diff options
| author | Tristan Zur <tzur@web.web.ccwn.org> | 2014-03-27 22:27:47 +0100 |
|---|---|---|
| committer | Tristan Zur <tzur@web.web.ccwn.org> | 2014-03-27 22:27:47 +0100 |
| commit | b62676ca5d3d6f6ba3f019ea3f99722e165a98d8 (patch) | |
| tree | 86722cb80f07d4569f90088eeaea2fc2f6e2ef94 /hugo/js | |
Diffstat (limited to 'hugo/js')
203 files changed, 78882 insertions, 0 deletions
diff --git a/hugo/js/OpenStreetMap.js b/hugo/js/OpenStreetMap.js new file mode 100644 index 0000000..8a7f016 --- /dev/null +++ b/hugo/js/OpenStreetMap.js @@ -0,0 +1,126 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Namespace: Util.OSM + */ +OpenLayers.Util.OSM = {}; + +/** + * Constant: MISSING_TILE_URL + * {String} URL of image to display for missing tiles + */ +OpenLayers.Util.OSM.MISSING_TILE_URL = "http://www.openstreetmap.org/openlayers/img/404.png"; + +/** + * Property: originalOnImageLoadError + * {Function} Original onImageLoadError function. + */ +OpenLayers.Util.OSM.originalOnImageLoadError = OpenLayers.Util.onImageLoadError; + +/** + * Function: onImageLoadError + */ +OpenLayers.Util.onImageLoadError = function() { + if (this.src.match(/^http:\/\/[abc]\.[a-z]+\.openstreetmap\.org\//)) { + this.src = OpenLayers.Util.OSM.MISSING_TILE_URL; + } else if (this.src.match(/^http:\/\/[def]\.tah\.openstreetmap\.org\//)) { + // do nothing - this layer is transparent + } else { + OpenLayers.Util.OSM.originalOnImageLoadError; + } +}; + +/** + * Class: OpenLayers.Layer.OSM.Mapnik + * + * Inherits from: + * - <OpenLayers.Layer.OSM> + */ +OpenLayers.Layer.OSM.Mapnik = OpenLayers.Class(OpenLayers.Layer.OSM, { + /** + * Constructor: OpenLayers.Layer.OSM.Mapnik + * + * Parameters: + * name - {String} + * options - {Object} Hashtable of extra options to tag onto the layer + */ + initialize: function(name, options) { + var url = [ + "http://a.tile.openstreetmap.org/${z}/${x}/${y}.png", + "http://b.tile.openstreetmap.org/${z}/${x}/${y}.png", + "http://c.tile.openstreetmap.org/${z}/${x}/${y}.png" + ]; + options = OpenLayers.Util.extend({ + numZoomLevels: 19, + buffer: 0, + transitionEffect: "resize" + }, options); + var newArguments = [name, url, options]; + OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments); + }, + + CLASS_NAME: "OpenLayers.Layer.OSM.Mapnik" +}); + +/** + * Class: OpenLayers.Layer.OSM.Osmarender + * + * Inherits from: + * - <OpenLayers.Layer.OSM> + */ +OpenLayers.Layer.OSM.Osmarender = OpenLayers.Class(OpenLayers.Layer.OSM, { + /** + * Constructor: OpenLayers.Layer.OSM.Osmarender + * + * Parameters: + * name - {String} + * options - {Object} Hashtable of extra options to tag onto the layer + */ + initialize: function(name, options) { + var url = [ + "http://a.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png", + "http://b.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png", + "http://c.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png" + ]; + options = OpenLayers.Util.extend({ + numZoomLevels: 18, + buffer: 0, + transitionEffect: "resize" + }, options); + var newArguments = [name, url, options]; + OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments); + }, + + CLASS_NAME: "OpenLayers.Layer.OSM.Osmarender" +}); + +/** + * Class: OpenLayers.Layer.OSM.CycleMap + * + * Inherits from: + * - <OpenLayers.Layer.OSM> + */ +OpenLayers.Layer.OSM.CycleMap = OpenLayers.Class(OpenLayers.Layer.OSM, { + /** + * Constructor: OpenLayers.Layer.OSM.CycleMap + * + * Parameters: + * name - {String} + * options - {Object} Hashtable of extra options to tag onto the layer + */ + initialize: function(name, options) { + var url = [ + "http://a.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png", + "http://b.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png", + "http://c.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png" + ]; + options = OpenLayers.Util.extend({ + numZoomLevels: 19, + buffer: 0, + transitionEffect: "resize" + }, options); + var newArguments = [name, url, options]; + OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments); + }, + + CLASS_NAME: "OpenLayers.Layer.OSM.CycleMap" +}); diff --git a/hugo/js/ajax.js b/hugo/js/ajax.js new file mode 100644 index 0000000..9186b8e --- /dev/null +++ b/hugo/js/ajax.js @@ -0,0 +1,811 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * This object handles ajax requests for pages. It also + * handles the reloading of the main menu and scripts. + */ +var AJAX = { + /** + * @var bool active Whether we are busy + */ + active: false, + /** + * @var object source The object whose event initialized the request + */ + source: null, + /** + * @var function Callback to execute after a successful request + * Used by PMA_commonFunctions from common.js + */ + _callback: function () {}, + /** + * @var bool _debug Makes noise in your Firebug console + */ + _debug: false, + /** + * @var object $msgbox A reference to a jQuery object that links to a message + * box that is generated by PMA_ajaxShowMessage() + */ + $msgbox: null, + /** + * Given the filename of a script, returns a hash to be + * used to refer to all the events registered for the file + * + * @param string key The filename for which to get the event name + * + * @return int + */ + hash: function (key){ + /* http://burtleburtle.net/bob/hash/doobs.html#one */ + key += ""; + var len = key.length, hash=0, i=0; + for (; i<len; ++i) { + hash += key.charCodeAt(i); + hash += (hash << 10); + hash ^= (hash >> 6); + } + hash += (hash << 3); + hash ^= (hash >> 11); + hash += (hash << 15); + return Math.abs(hash); + }, + /** + * Registers an onload event for a file + * + * @param string file The filename for which to register the event + * @param function func The function to execute when the page is ready + * + * @return self For chaining + */ + registerOnload: function (file, func) { + var eventName = 'onload_' + AJAX.hash(file); + $(document).bind(eventName, func); + this._debug && console.log( + // no need to translate + "Registered event " + eventName + " for file " + file + ); + return this; + }, + /** + * Registers a teardown event for a file. This is useful to execute functions + * that unbind events for page elements that are about to be removed. + * + * @param string file The filename for which to register the event + * @param function func The function to execute when + * the page is about to be torn down + * + * @return self For chaining + */ + registerTeardown: function (file, func) { + var eventName = 'teardown_' + AJAX.hash(file); + $(document).bind(eventName, func); + this._debug && console.log( + // no need to translate + "Registered event " + eventName + " for file " + file + ); + return this; + }, + /** + * Called when a page has finished loading, once for every + * file that registered to the onload event of that file. + * + * @param string file The filename for which to fire the event + * + * @return void + */ + fireOnload: function (file) { + var eventName = 'onload_' + AJAX.hash(file); + $(document).trigger(eventName); + this._debug && console.log( + // no need to translate + "Fired event " + eventName + " for file " + file + ); + }, + /** + * Called just before a page is torn down, once for every + * file that registered to the teardown event of that file. + * + * @param string file The filename for which to fire the event + * + * @return void + */ + fireTeardown: function (file) { + var eventName = 'teardown_' + AJAX.hash(file); + $(document).triggerHandler(eventName); + this._debug && console.log( + // no need to translate + "Fired event " + eventName + " for file " + file + ); + }, + /** + * Event handler for clicks on links and form submissions + * + * @param object e Event data + * + * @return void + */ + requestHandler: function (event) { + // In some cases we don't want to handle the request here and either + // leave the browser deal with it natively (e.g: file download) + // or leave an existing ajax event handler present elsewhere deal with it + var href = $(this).attr('href'); + if (event.shiftKey || event.ctrlKey) { + return true; + } else if ($(this).attr('target')) { + return true; + } else if ($(this).hasClass('ajax') || $(this).hasClass('disableAjax')) { + return true; + } else if (href && href.match(/^#/)) { + return true; + } else if (href && href.match(/^mailto/)) { + return true; + } else if ($(this).hasClass('ui-datepicker-next') || + $(this).hasClass('ui-datepicker-prev') + ) { + return true; + } + + if (typeof event != 'undefined') { + event.preventDefault(); + event.stopImmediatePropagation(); + } + if (AJAX.active == true) { + // Silently bail out, there is already a request in progress. + // TODO: save a reference to the request and cancel the old request + // when the user requests something else. Something like this is + // already implemented in the PMA_fastFilter object in navigation.js + return false; + } + + AJAX.source = $(this); + + $('html, body').animate({scrollTop: 0}, 'fast'); + + var isLink = !! href || false; + var url = isLink ? href : $(this).attr('action'); + var params = 'ajax_request=true&ajax_page_request=true'; + if (! isLink) { + params += '&' + $(this).serialize(); + } + // Add a list of menu hashes that we have in the cache to the request + params += AJAX.cache.menus.getRequestParam(); + + AJAX._debug && console.log("Loading: " + url); // no need to translate + + if (isLink) { + AJAX.active = true; + AJAX.$msgbox = PMA_ajaxShowMessage(); + $.get(url, params, AJAX.responseHandler); + } else { + /** + * Manually fire the onsubmit event for the form, if any. + * The event was saved in the jQuery data object by an onload + * handler defined below. Workaround for bug #3583316 + */ + var onsubmit = $(this).data('onsubmit'); + // Submit the request if there is no onsubmit handler + // or if it returns a value that evaluates to true + if (typeof onsubmit !== 'function' || onsubmit.apply(this, [event])) { + AJAX.active = true; + AJAX.$msgbox = PMA_ajaxShowMessage(); + $.post(url, params, AJAX.responseHandler); + } + } + }, + /** + * Called after the request that was initiated by this.requestHandler() + * has completed successfully or with a caught error. For completely + * failed requests or requests with uncaught errors, see the .ajaxError + * handler at the bottom of this file. + * + * To refer to self use 'AJAX', instead of 'this' as this function + * is called in the jQuery context. + * + * @param object e Event data + * + * @return void + */ + responseHandler: function (data) { + if (data.success) { + $table_clone = false; + PMA_ajaxRemoveMessage(AJAX.$msgbox); + + if (data._redirect) { + PMA_ajaxShowMessage(data._redirect, false); + AJAX.active = false; + return; + } + + AJAX.scriptHandler.reset(function () { + if (data._reloadNavigation) { + PMA_reloadNavigation(); + } + if (data._reloadQuerywindow) { + var params = data._reloadQuerywindow; + PMA_querywindow.reload( + params.db, + params.table, + params.sql_query + ); + } + if (data._focusQuerywindow) { + PMA_querywindow.focus( + data._focusQuerywindow + ); + } + if (data._title) { + $('title').replaceWith(data._title); + } + if (data._menu) { + AJAX.cache.menus.replace(data._menu); + AJAX.cache.menus.add(data._menuHash, data._menu); + } else if (data._menuHash) { + AJAX.cache.menus.replace(AJAX.cache.menus.get(data._menuHash)); + } + + // Remove all containers that may have + // been added outside of #page_content + $('body').children() + .not('#pma_navigation') + .not('#floating_menubar') + .not('#goto_pagetop') + .not('#page_content') + .not('#selflink') + .not('#session_debug') + .remove(); + // Replace #page_content with new content + if (data.message && data.message.length > 0) { + $('#page_content').replaceWith( + "<div id='page_content'>" + data.message + "</div>" + ); + } + + if (data._selflink) { + $('#selflink > a').attr('href', data._selflink); + } + if (data._scripts) { + AJAX.scriptHandler.load(data._scripts); + } + if (data._selflink && data._scripts && data._menuHash && data._params) { + AJAX.cache.add( + data._selflink, + data._scripts, + data._menuHash, + data._params, + AJAX.source.attr('rel') + ); + } + if (data._params) { + PMA_commonParams.setAll(data._params); + } + if (data._displayMessage) { + $('#page_content').prepend(data._displayMessage); + } + + $('#pma_errors').remove(); + if (data._errors) { + $('<div/>', {id:'pma_errors'}) + .insertAfter('#selflink') + .append(data._errors); + } + + if (typeof AJAX._callback === 'function') { + AJAX._callback.call(); + } + AJAX._callback = function () {}; + }); + } else { + PMA_ajaxShowMessage(data.error, false); + AJAX.active = false; + } + }, + /** + * This object is in charge of downloading scripts, + * keeping track of what's downloaded and firing + * the onload event for them when the page is ready. + */ + scriptHandler: { + /** + * @var array _scripts The list of files already downloaded + */ + _scripts: [], + /** + * @var array _scriptsToBeLoaded The list of files that + * need to be downloaded + */ + _scriptsToBeLoaded: [], + /** + * @var array _scriptsToBeFired The list of files for which + * to fire the onload event + */ + _scriptsToBeFired: [], + /** + * Records that a file has been downloaded + * + * @param string file The filename + * @param string fire Whether this file will be registering + * onload/teardown events + * + * @return self For chaining + */ + add: function (file, fire) { + this._scripts.push(file); + if (fire) { + // Record whether to fire any events for the file + // This is necessary to correctly tear down the initial page + this._scriptsToBeFired.push(file); + } + return this; + }, + /** + * Download a list of js files in one request + * + * @param array files An array of filenames and flags + * + * @return void + */ + load: function (files) { + var self = this; + self._scriptsToBeLoaded = []; + self._scriptsToBeFired = []; + for (var i in files) { + self._scriptsToBeLoaded.push(files[i].name); + if (files[i].fire) { + self._scriptsToBeFired.push(files[i].name); + } + } + // Generate a request string + var request = []; + var needRequest = false; + for (var index in self._scriptsToBeLoaded) { + var script = self._scriptsToBeLoaded[index]; + // Only for scripts that we don't already have + if ($.inArray(script, self._scripts) == -1) { + needRequest = true; + this.add(script); + request.push("scripts[]=" + script); + } + } + // Download the composite js file, if necessary + if (needRequest) { + $.ajax({ + url: "js/get_scripts.js.php?" + request.join("&"), + cache: true, + success: function () { + self.done(); + }, + dataType: "script" + }); + } else { + self.done(); + } + }, + /** + * Called whenever all files are loaded + * + * @return void + */ + done: function () { + for (var i in this._scriptsToBeFired) { + AJAX.fireOnload(this._scriptsToBeFired[i]); + } + AJAX.active = false; + }, + /** + * Fires all the teardown event handlers for the current page + * and rebinds all forms and links to the request handler + * + * @param function callback The callback to call after resetting + * + * @return void + */ + reset: function (callback) { + for (var i in this._scriptsToBeFired) { + AJAX.fireTeardown(this._scriptsToBeFired[i]); + } + this._scriptsToBeFired = []; + /** + * Re-attach a generic event handler to clicks + * on pages and submissions of forms + */ + $('a').die('click').live('click', AJAX.requestHandler); + $('form').die('submit').live('submit', AJAX.requestHandler); + AJAX.cache.update(); + callback(); + } + } +}; + +/** + * Here we register a function that will remove the onsubmit event from all + * forms that will be handled by the generic page loader. We then save this + * event handler in the "jQuery data", so that we can fire it up later in + * AJAX.requestHandler(). + * + * See bug #3583316 + */ +AJAX.registerOnload('functions.js', function () { + // Registering the onload event for functions.js + // ensures that it will be fired for all pages + $('form').not('.ajax').not('.disableAjax').each(function () { + if ($(this).attr('onsubmit')) { + $(this).data('onsubmit', this.onsubmit).attr('onsubmit', ''); + } + }); +}); + +/** + * An implementation of a client-side page cache. + * This object also uses the cache to provide a simple microhistory, + * that is the ability to use the back and forward buttons in the browser + */ +AJAX.cache = { + /** + * @var int The maximum number of pages to keep in the cache + */ + MAX: 6, + /** + * @var object A hash used to prime the cache with data about the initially + * loaded page. This is set in the footer, and then loaded + * by a double-queued event further down this file. + */ + primer: {}, + /** + * @var array Stores the content of the cached pages + */ + pages: [], + /** + * @var int The index of the currently loaded page + * This is used to know at which point in the history we are + */ + current: 0, + /** + * Saves a new page in the cache + * + * @param string hash The hash part of the url that is being loaded + * @param array scripts A list of scripts that is requured for the page + * @param string menu A hash that links to a menu stored + * in a dedicated menu cache + * @param array params A list of parameters used by PMA_commonParams() + * @param string rel A relationship to the current page: + * 'samepage': Forces the response to be treated as + * the same page as the current one + * 'newpage': Forces the response to be treated as + * a new page + * undefined: Default behaviour, 'samepage' if the + * selflinks of the two pages are the same. + * 'newpage' otherwise + * + * @return void + */ + add: function (hash, scripts, menu, params, rel) { + if (this.pages.length > AJAX.cache.MAX) { + // Trim the cache, to the maximum number of allowed entries + // This way we will have a cached menu for every page + for (var i=0; i<this.pages.length-this.MAX; i++) { + delete this.pages[i]; + } + } + while (this.current < this.pages.length) { + // trim the cache if we went back in the history + // and are now going forward again + this.pages.pop(); + } + if (rel === 'newpage' || + ( + typeof rel === 'undefined' && ( + typeof this.pages[this.current - 1] === 'undefined' + || + this.pages[this.current - 1].hash !== hash + ) + ) + ) { + this.pages.push({ + hash: hash, + content: $('#page_content').html(), + scripts: scripts, + selflink: $('#selflink').html(), + menu: menu, + params: params + }); + AJAX.setUrlHash(this.current, hash); + this.current++; + } + }, + /** + * Restores a page from the cache. This is called when the hash + * part of the url changes and it's structure appears to be valid + * + * @param string index Which page from the history to load + * + * @return void + */ + navigate: function (index) { + if (typeof this.pages[index] === 'undefined') { + PMA_ajaxShowMessage( + '<div class="error">' + PMA_messages['strInvalidPage'] + '</div>', + false + ); + } else { + AJAX.active = true; + var record = this.pages[index]; + AJAX.scriptHandler.reset(function () { + $('#page_content').html(record.content); + $('#selflink').html(record.selflink); + AJAX.cache.menus.replace(AJAX.cache.menus.get(record.menu)); + PMA_commonParams.setAll(record.params); + AJAX.scriptHandler.load(record.scripts); + AJAX.cache.current = ++index; + }); + } + }, + /** + * Resaves the content of the current page in the cache. + * Necessary in order not to show the user some outdated version of the page + * + * @return void + */ + update: function () { + var page = this.pages[this.current - 1]; + if (page) { + page.content = $('#page_content').html(); + } + }, + /** + * @var object Dedicated menu cache + */ + menus: { + /** + * Returns the number of items in an associative array + * + * @return int + */ + size: function(obj) { + var size = 0, key; + for (key in obj) { + if (obj.hasOwnProperty(key)) { + size++; + } + } + return size; + }, + /** + * @var hash Stores the content of the cached menus + */ + data: {}, + /** + * Saves a new menu in the cache + * + * @param string hash The hash (trimmed md5) of the menu to be saved + * @param string content The HTML code of the menu to be saved + * + * @return void + */ + add: function (hash, content) { + if (this.size(this.data) > AJAX.cache.MAX) { + // when the cache grows, we remove the oldest entry + var oldest, key, init = 0; + for (var i in this.data) { + if (this.data[i]) { + if (! init || this.data[i].timestamp.getTime() < oldest.getTime()) { + oldest = this.data[i].timestamp; + key = i; + init = 1; + } + } + } + delete this.data[key]; + } + this.data[hash] = { + content: content, + timestamp: new Date() + }; + }, + /** + * Retrieves a menu given its hash + * + * @param string hash The hash of the menu to be retrieved + * + * @return string + */ + get: function (hash) { + if (this.data[hash]) { + return this.data[hash].content; + } else { + // This should never happen as long as the number of stored menus + // is larger or equal to the number of pages in the page cache + return ''; + } + }, + /** + * Prepares part of the parameter string used during page requests, + * this is necessary to tell the server which menus we have in the cache + * + * @return string + */ + getRequestParam: function () { + var param = ''; + var menuHashes = []; + for (var i in this.data) { + menuHashes.push(i); + } + var menuHashesParam = menuHashes.join('-'); + if (menuHashesParam) { + param = '&menuHashes=' + menuHashesParam; + } + return param; + }, + /** + * Replaces the menu with new content + * + * @return void + */ + replace: function (content) { + $('#floating_menubar').html(content) + // Remove duplicate wrapper + // TODO: don't send it in the response + .children().first().remove(); + $('#topmenu').menuResizer(PMA_mainMenuResizerCallback); + } + } +}; + +/** + * URL hash management module. + * Allows direct bookmarking and microhistory. + */ +AJAX.setUrlHash = (function (jQuery, window) { + "use strict"; + /** + * Indictaes whether we have already completed + * the initialisation of the hash + * + * @access private + */ + var ready = false; + /** + * Stores a hash that needed to be set when we were not ready + * + * @access private + */ + var savedHash = ""; + /** + * Flag to indicate if the change of hash was triggered + * by a user pressing the back/forward button or if + * the change was triggered internally + * + * @access private + */ + var userChange = true; + + // Fix favicon disappearing in Firefox when setting location.hash + function resetFavicon() { + if (jQuery.browser.mozilla) { + // Move the link tags for the favicon to the bottom + // of the head element to force a reload of the favicon + $('head > link[href=favicon\\.ico]').appendTo('head'); + } + } + + /** + * Sets the hash part of the URL + * + * @access public + */ + function setUrlHash(index, hash) { + /* + * Known problem: + * Setting hash leads to reload in webkit: + * http://www.quirksmode.org/bugreports/archives/2005/05/Safari_13_visual_anomaly_with_windowlocationhref.html + * + * so we expect that users are not running an ancient Safari version + */ + + userChange = false; + if (ready) { + window.location.hash = "PMAURL-" + index + ":" + hash; + resetFavicon(); + } else { + savedHash = "PMAURL-" + index + ":" + hash; + } + } + /** + * Start initialisation + */ + if (window.location.hash.substring(0, 8) == '#PMAURL-') { + // We have a valid hash, let's redirect the user + // to the page that it's pointing to + window.location = window.location.hash.substring( + window.location.hash.indexOf(':') + 1 + ); + } else { + // We don't have a valid hash, so we'll set it up + // when the page finishes loading + jQuery(function(){ + /* Check if we should set URL */ + if (savedHash != "") { + window.location.hash = savedHash; + savedHash = ""; + resetFavicon(); + } + // Indicate that we're done initialising + ready = true; + }); + } + /** + * Register an event handler for when the url hash changes + */ + jQuery(function(){ + jQuery(window).hashchange(function () { + if (userChange === false) { + // Ignore internally triggered hash changes + userChange = true; + } else if (/^#PMAURL-\d+:/.test(window.location.hash)) { + // Change page if the hash changed was triggered by a user action + var index = window.location.hash.substring( + 8, window.location.hash.indexOf(':') + ); + AJAX.cache.navigate(index); + } + }); + }); + /** + * Publicly exposes a reference to the otherwise private setUrlHash function + */ + return setUrlHash; +})(jQuery, window); + +/** + * Page load event handler + */ +$(function () { + // Add the menu from the initial page into the cache + // The cache primer is set by the footer class + if (AJAX.cache.primer.url) { + AJAX.cache.menus.add( + AJAX.cache.primer.menuHash, + $('<div></div>') + .append('<div></div>') + .append($('#serverinfo').clone()) + .append($('#topmenucontainer').clone()) + .html() + ); + } + $(function () { + // Queue up this event twice to make sure that we get a copy + // of the page after all other onload events have been fired + if (AJAX.cache.primer.url) { + AJAX.cache.add( + AJAX.cache.primer.url, + AJAX.cache.primer.scripts, + AJAX.cache.primer.menuHash + ); + } + }); +}); + +/** + * Attach a generic event handler to clicks + * on pages and submissions of forms + */ +$('a').live('click', AJAX.requestHandler); +$('form').live('submit', AJAX.requestHandler); + +/** + * Gracefully handle fatal server errors + * (e.g: 500 - Internal server error) + */ +$(document).ajaxError(function(event, request, settings){ + if (request.status !== 0) { // Don't handle aborted requests + var errorCode = $.sprintf(PMA_messages['strErrorCode'], request.status); + var errorText = $.sprintf(PMA_messages['strErrorText'], request.statusText); + PMA_ajaxShowMessage( + '<div class="error">' + + PMA_messages['strErrorProcessingRequest'] + + '<div>' + errorCode + '</div>' + + '<div>' + errorText + '</div>' + + '</div>', + false + ); + AJAX.active = false; + } +}); diff --git a/hugo/js/canvg/MIT-LICENSE.txt b/hugo/js/canvg/MIT-LICENSE.txt new file mode 100644 index 0000000..40f19bd --- /dev/null +++ b/hugo/js/canvg/MIT-LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (c) 2010-2011 Gabe Lerner (gabelerner@gmail.com) - http://code.google.com/p/canvg/ + + Permission is hereby granted, free of charge, to any person + obtaining a copy of this software and associated documentation + files (the "Software"), to deal in the Software without + restriction, including without limitation the rights to use, + copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following + conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file diff --git a/hugo/js/canvg/canvg.js b/hugo/js/canvg/canvg.js new file mode 100644 index 0000000..dbc5a9d --- /dev/null +++ b/hugo/js/canvg/canvg.js @@ -0,0 +1,2509 @@ +/* + * canvg.js - Javascript SVG parser and renderer on Canvas + * MIT Licensed + * Gabe Lerner (gabelerner@gmail.com) + * http://code.google.com/p/canvg/ + * + * Requires: rgbcolor.js - http://www.phpied.com/rgb-color-parser-in-javascript/ + */ +if(!window.console) { + window.console = {}; + window.console.log = function(str) {}; + window.console.dir = function(str) {}; +} + +// <3 IE +if(!Array.indexOf){ + Array.prototype.indexOf = function(obj){ + for(var i=0; i<this.length; i++){ + if(this[i]==obj){ + return i; + } + } + return -1; + } +} + +(function(){ + // canvg(target, s) + // empty parameters: replace all 'svg' elements on page with 'canvas' elements + // target: canvas element or the id of a canvas element + // s: svg string or url to svg file + // opts: optional hash of options + // ignoreMouse: true => ignore mouse events + // ignoreAnimation: true => ignore animations + // ignoreDimensions: true => does not try to resize canvas + // ignoreClear: true => does not clear canvas + // offsetX: int => draws at a x offset + // offsetY: int => draws at a y offset + // scaleWidth: int => scales horizontally to width + // scaleHeight: int => scales vertically to height + // renderCallback: function => will call the function after the first render is completed + // forceRedraw: function => will call the function on every frame, if it returns true, will redraw + this.canvg = function (target, s, opts) { + // no parameters + if (target == null && s == null && opts == null) { + var svgTags = document.getElementsByTagName('svg'); + for (var i=0; i<svgTags.length; i++) { + var svgTag = svgTags[i]; + var c = document.createElement('canvas'); + c.width = svgTag.clientWidth; + c.height = svgTag.clientHeight; + svgTag.parentNode.insertBefore(c, svgTag); + svgTag.parentNode.removeChild(svgTag); + var div = document.createElement('div'); + div.appendChild(svgTag); + canvg(c, div.innerHTML); + } + return; + } + + if (typeof target == 'string') { + target = document.getElementById(target); + } + + // reuse class per canvas + var svg; + if (target.svg == null) { + svg = build(); + target.svg = svg; + } + else { + svg = target.svg; + svg.stop(); + } + svg.opts = opts; + + var ctx = target.getContext('2d'); + if (s.substr(0,1) == '<') { + // load from xml string + svg.loadXml(ctx, s); + } + else { + // load from url + svg.load(ctx, s); + } + } + + function build() { + var svg = { }; + + svg.FRAMERATE = 30; + + // globals + svg.init = function(ctx) { + svg.Definitions = {}; + svg.Styles = {}; + svg.Animations = []; + svg.Images = []; + svg.ctx = ctx; + svg.ViewPort = new (function () { + this.viewPorts = []; + this.SetCurrent = function(width, height) { this.viewPorts.push({ width: width, height: height }); } + this.RemoveCurrent = function() { this.viewPorts.pop(); } + this.Current = function() { return this.viewPorts[this.viewPorts.length - 1]; } + this.width = function() { return this.Current().width; } + this.height = function() { return this.Current().height; } + this.ComputeSize = function(d) { + if (d != null && typeof(d) == 'number') return d; + if (d == 'x') return this.width(); + if (d == 'y') return this.height(); + return Math.sqrt(Math.pow(this.width(), 2) + Math.pow(this.height(), 2)) / Math.sqrt(2); + } + }); + } + svg.init(); + + // images loaded + svg.ImagesLoaded = function() { + for (var i=0; i<svg.Images.length; i++) { + if (!svg.Images[i].loaded) return false; + } + return true; + } + + // trim + svg.trim = function(s) { return s.replace(/^\s+|\s+$/g, ''); } + + // compress spaces + svg.compressSpaces = function(s) { return s.replace(/[\s\r\t\n]+/gm,' '); } + + // ajax + svg.ajax = function(url) { + var AJAX; + if(window.XMLHttpRequest){AJAX=new XMLHttpRequest();} + else{AJAX=new ActiveXObject('Microsoft.XMLHTTP');} + if(AJAX){ + AJAX.open('GET',url,false); + AJAX.send(null); + return AJAX.responseText; + } + return null; + } + + // parse xml + svg.parseXml = function(xml) { + if (window.DOMParser) + { + var parser = new DOMParser(); + return parser.parseFromString(xml, 'text/xml'); + } + else + { + xml = xml.replace(/<!DOCTYPE svg[^>]*>/, ''); + var xmlDoc = new ActiveXObject('Microsoft.XMLDOM'); + xmlDoc.async = 'false'; + xmlDoc.loadXML(xml); + return xmlDoc; + } + } + + svg.Property = function(name, value) { + this.name = name; + this.value = value; + + this.hasValue = function() { + return (this.value != null && this.value != ''); + } + + // return the numerical value of the property + this.numValue = function() { + if (!this.hasValue()) return 0; + + var n = parseFloat(this.value); + if ((this.value + '').match(/%$/)) { + n = n / 100.0; + } + return n; + } + + this.valueOrDefault = function(def) { + if (this.hasValue()) return this.value; + return def; + } + + this.numValueOrDefault = function(def) { + if (this.hasValue()) return this.numValue(); + return def; + } + + /* EXTENSIONS */ + var that = this; + + // color extensions + this.Color = { + // augment the current color value with the opacity + addOpacity: function(opacity) { + var newValue = that.value; + if (opacity != null && opacity != '') { + var color = new RGBColor(that.value); + if (color.ok) { + newValue = 'rgba(' + color.r + ', ' + color.g + ', ' + color.b + ', ' + opacity + ')'; + } + } + return new svg.Property(that.name, newValue); + } + } + + // definition extensions + this.Definition = { + // get the definition from the definitions table + getDefinition: function() { + var name = that.value.replace(/^(url\()?#([^\)]+)\)?$/, '$2'); + return svg.Definitions[name]; + }, + + isUrl: function() { + return that.value.indexOf('url(') == 0 + }, + + getFillStyle: function(e) { + var def = this.getDefinition(); + + // gradient + if (def != null && def.createGradient) { + return def.createGradient(svg.ctx, e); + } + + // pattern + if (def != null && def.createPattern) { + return def.createPattern(svg.ctx, e); + } + + return null; + } + } + + // length extensions + this.Length = { + DPI: function(viewPort) { + return 96.0; // TODO: compute? + }, + + EM: function(viewPort) { + var em = 12; + + var fontSize = new svg.Property('fontSize', svg.Font.Parse(svg.ctx.font).fontSize); + if (fontSize.hasValue()) em = fontSize.Length.toPixels(viewPort); + + return em; + }, + + // get the length as pixels + toPixels: function(viewPort) { + if (!that.hasValue()) return 0; + var s = that.value+''; + if (s.match(/em$/)) return that.numValue() * this.EM(viewPort); + if (s.match(/ex$/)) return that.numValue() * this.EM(viewPort) / 2.0; + if (s.match(/px$/)) return that.numValue(); + if (s.match(/pt$/)) return that.numValue() * 1.25; + if (s.match(/pc$/)) return that.numValue() * 15; + if (s.match(/cm$/)) return that.numValue() * this.DPI(viewPort) / 2.54; + if (s.match(/mm$/)) return that.numValue() * this.DPI(viewPort) / 25.4; + if (s.match(/in$/)) return that.numValue() * this.DPI(viewPort); + if (s.match(/%$/)) return that.numValue() * svg.ViewPort.ComputeSize(viewPort); + return that.numValue(); + } + } + + // time extensions + this.Time = { + // get the time as milliseconds + toMilliseconds: function() { + if (!that.hasValue()) return 0; + var s = that.value+''; + if (s.match(/s$/)) return that.numValue() * 1000; + if (s.match(/ms$/)) return that.numValue(); + return that.numValue(); + } + } + + // angle extensions + this.Angle = { + // get the angle as radians + toRadians: function() { + if (!that.hasValue()) return 0; + var s = that.value+''; + if (s.match(/deg$/)) return that.numValue() * (Math.PI / 180.0); + if (s.match(/grad$/)) return that.numValue() * (Math.PI / 200.0); + if (s.match(/rad$/)) return that.numValue(); + return that.numValue() * (Math.PI / 180.0); + } + } + } + + // fonts + svg.Font = new (function() { + this.Styles = ['normal','italic','oblique','inherit']; + this.Variants = ['normal','small-caps','inherit']; + this.Weights = ['normal','bold','bolder','lighter','100','200','300','400','500','600','700','800','900','inherit']; + + this.CreateFont = function(fontStyle, fontVariant, fontWeight, fontSize, fontFamily, inherit) { + var f = inherit != null ? this.Parse(inherit) : this.CreateFont('', '', '', '', '', svg.ctx.font); + return { + fontFamily: fontFamily || f.fontFamily, + fontSize: fontSize || f.fontSize, + fontStyle: fontStyle || f.fontStyle, + fontWeight: fontWeight || f.fontWeight, + fontVariant: fontVariant || f.fontVariant, + toString: function () { return [this.fontStyle, this.fontVariant, this.fontWeight, this.fontSize, this.fontFamily].join(' ') } + } + } + + var that = this; + this.Parse = function(s) { + var f = {}; + var d = svg.trim(svg.compressSpaces(s || '')).split(' '); + var set = { fontSize: false, fontStyle: false, fontWeight: false, fontVariant: false } + var ff = ''; + for (var i=0; i<d.length; i++) { + if (!set.fontStyle && that.Styles.indexOf(d[i]) != -1) { if (d[i] != 'inherit') f.fontStyle = d[i]; set.fontStyle = true; } + else if (!set.fontVariant && that.Variants.indexOf(d[i]) != -1) { if (d[i] != 'inherit') f.fontVariant = d[i]; set.fontStyle = set.fontVariant = true; } + else if (!set.fontWeight && that.Weights.indexOf(d[i]) != -1) { if (d[i] != 'inherit') f.fontWeight = d[i]; set.fontStyle = set.fontVariant = set.fontWeight = true; } + else if (!set.fontSize) { if (d[i] != 'inherit') f.fontSize = d[i].split('/')[0]; set.fontStyle = set.fontVariant = set.fontWeight = set.fontSize = true; } + else { if (d[i] != 'inherit') ff += d[i]; } + } if (ff != '') f.fontFamily = ff; + return f; + } + }); + + // points and paths + svg.ToNumberArray = function(s) { + var a = svg.trim(svg.compressSpaces((s || '').replace(/,/g, ' '))).split(' '); + for (var i=0; i<a.length; i++) { + a[i] = parseFloat(a[i]); + } + return a; + } + svg.Point = function(x, y) { + this.x = x; + this.y = y; + + this.angleTo = function(p) { + return Math.atan2(p.y - this.y, p.x - this.x); + } + + this.applyTransform = function(v) { + var xp = this.x * v[0] + this.y * v[2] + v[4]; + var yp = this.x * v[1] + this.y * v[3] + v[5]; + this.x = xp; + this.y = yp; + } + } + svg.CreatePoint = function(s) { + var a = svg.ToNumberArray(s); + return new svg.Point(a[0], a[1]); + } + svg.CreatePath = function(s) { + var a = svg.ToNumberArray(s); + var path = []; + for (var i=0; i<a.length; i+=2) { + path.push(new svg.Point(a[i], a[i+1])); + } + return path; + } + + // bounding box + svg.BoundingBox = function(x1, y1, x2, y2) { // pass in initial points if you want + this.x1 = Number.NaN; + this.y1 = Number.NaN; + this.x2 = Number.NaN; + this.y2 = Number.NaN; + + this.x = function() { return this.x1; } + this.y = function() { return this.y1; } + this.width = function() { return this.x2 - this.x1; } + this.height = function() { return this.y2 - this.y1; } + + this.addPoint = function(x, y) { + if (x != null) { + if (isNaN(this.x1) || isNaN(this.x2)) { + this.x1 = x; + this.x2 = x; + } + if (x < this.x1) this.x1 = x; + if (x > this.x2) this.x2 = x; + } + + if (y != null) { + if (isNaN(this.y1) || isNaN(this.y2)) { + this.y1 = y; + this.y2 = y; + } + if (y < this.y1) this.y1 = y; + if (y > this.y2) this.y2 = y; + } + } + this.addX = function(x) { this.addPoint(x, null); } + this.addY = function(y) { this.addPoint(null, y); } + + this.addBoundingBox = function(bb) { + this.addPoint(bb.x1, bb.y1); + this.addPoint(bb.x2, bb.y2); + } + + this.addQuadraticCurve = function(p0x, p0y, p1x, p1y, p2x, p2y) { + var cp1x = p0x + 2/3 * (p1x - p0x); // CP1 = QP0 + 2/3 *(QP1-QP0) + var cp1y = p0y + 2/3 * (p1y - p0y); // CP1 = QP0 + 2/3 *(QP1-QP0) + var cp2x = cp1x + 1/3 * (p2x - p0x); // CP2 = CP1 + 1/3 *(QP2-QP0) + var cp2y = cp1y + 1/3 * (p2y - p0y); // CP2 = CP1 + 1/3 *(QP2-QP0) + this.addBezierCurve(p0x, p0y, cp1x, cp2x, cp1y, cp2y, p2x, p2y); + } + + this.addBezierCurve = function(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y) { + // from http://blog.hackers-cafe.net/2009/06/how-to-calculate-bezier-curves-bounding.html + var p0 = [p0x, p0y], p1 = [p1x, p1y], p2 = [p2x, p2y], p3 = [p3x, p3y]; + this.addPoint(p0[0], p0[1]); + this.addPoint(p3[0], p3[1]); + + for (i=0; i<=1; i++) { + var f = function(t) { + return Math.pow(1-t, 3) * p0[i] + + 3 * Math.pow(1-t, 2) * t * p1[i] + + 3 * (1-t) * Math.pow(t, 2) * p2[i] + + Math.pow(t, 3) * p3[i]; + } + + var b = 6 * p0[i] - 12 * p1[i] + 6 * p2[i]; + var a = -3 * p0[i] + 9 * p1[i] - 9 * p2[i] + 3 * p3[i]; + var c = 3 * p1[i] - 3 * p0[i]; + + if (a == 0) { + if (b == 0) continue; + var t = -c / b; + if (0 < t && t < 1) { + if (i == 0) this.addX(f(t)); + if (i == 1) this.addY(f(t)); + } + continue; + } + + var b2ac = Math.pow(b, 2) - 4 * c * a; + if (b2ac < 0) continue; + var t1 = (-b + Math.sqrt(b2ac)) / (2 * a); + if (0 < t1 && t1 < 1) { + if (i == 0) this.addX(f(t1)); + if (i == 1) this.addY(f(t1)); + } + var t2 = (-b - Math.sqrt(b2ac)) / (2 * a); + if (0 < t2 && t2 < 1) { + if (i == 0) this.addX(f(t2)); + if (i == 1) this.addY(f(t2)); + } + } + } + + this.isPointInBox = function(x, y) { + return (this.x1 <= x && x <= this.x2 && this.y1 <= y && y <= this.y2); + } + + this.addPoint(x1, y1); + this.addPoint(x2, y2); + } + + // transforms + svg.Transform = function(v) { + var that = this; + this.Type = {} + + // translate + this.Type.translate = function(s) { + this.p = svg.CreatePoint(s); + this.apply = function(ctx) { + ctx.translate(this.p.x || 0.0, this.p.y || 0.0); + } + this.applyToPoint = function(p) { + p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]); + } + } + + // rotate + this.Type.rotate = function(s) { + var a = svg.ToNumberArray(s); + this.angle = new svg.Property('angle', a[0]); + this.cx = a[1] || 0; + this.cy = a[2] || 0; + this.apply = function(ctx) { + ctx.translate(this.cx, this.cy); + ctx.rotate(this.angle.Angle.toRadians()); + ctx.translate(-this.cx, -this.cy); + } + this.applyToPoint = function(p) { + var a = this.angle.Angle.toRadians(); + p.applyTransform([1, 0, 0, 1, this.p.x || 0.0, this.p.y || 0.0]); + p.applyTransform([Math.cos(a), Math.sin(a), -Math.sin(a), Math.cos(a), 0, 0]); + p.applyTransform([1, 0, 0, 1, -this.p.x || 0.0, -this.p.y || 0.0]); + } + } + + this.Type.scale = function(s) { + this.p = svg.CreatePoint(s); + this.apply = function(ctx) { + ctx.scale(this.p.x || 1.0, this.p.y || this.p.x || 1.0); + } + this.applyToPoint = function(p) { + p.applyTransform([this.p.x || 0.0, 0, 0, this.p.y || 0.0, 0, 0]); + } + } + + this.Type.matrix = function(s) { + this.m = svg.ToNumberArray(s); + this.apply = function(ctx) { + ctx.transform(this.m[0], this.m[1], this.m[2], this.m[3], this.m[4], this.m[5]); + } + this.applyToPoint = function(p) { + p.applyTransform(this.m); + } + } + + this.Type.SkewBase = function(s) { + this.base = that.Type.matrix; + this.base(s); + this.angle = new svg.Property('angle', s); + } + this.Type.SkewBase.prototype = new this.Type.matrix; + + this.Type.skewX = function(s) { + this.base = that.Type.SkewBase; + this.base(s); + this.m = [1, 0, Math.tan(this.angle.Angle.toRadians()), 1, 0, 0]; + } + this.Type.skewX.prototype = new this.Type.SkewBase; + + this.Type.skewY = function(s) { + this.base = that.Type.SkewBase; + this.base(s); + this.m = [1, Math.tan(this.angle.Angle.toRadians()), 0, 1, 0, 0]; + } + this.Type.skewY.prototype = new this.Type.SkewBase; + + this.transforms = []; + + this.apply = function(ctx) { + for (var i=0; i<this.transforms.length; i++) { + this.transforms[i].apply(ctx); + } + } + + this.applyToPoint = function(p) { + for (var i=0; i<this.transforms.length; i++) { + this.transforms[i].applyToPoint(p); + } + } + + var data = v.split(/\s(?=[a-z])/); + for (var i=0; i<data.length; i++) { + var type = data[i].split('(')[0]; + var s = data[i].split('(')[1].replace(')',''); + var transform = new this.Type[type](s); + this.transforms.push(transform); + } + } + + // aspect ratio + svg.AspectRatio = function(ctx, aspectRatio, width, desiredWidth, height, desiredHeight, minX, minY, refX, refY) { + // aspect ratio - http://www.w3.org/TR/SVG/coords.html#PreserveAspectRatioAttribute + aspectRatio = svg.compressSpaces(aspectRatio); + aspectRatio = aspectRatio.replace(/^defer\s/,''); // ignore defer + var align = aspectRatio.split(' ')[0] || 'xMidYMid'; + var meetOrSlice = aspectRatio.split(' ')[1] || 'meet'; + + // calculate scale + var scaleX = width / desiredWidth; + var scaleY = height / desiredHeight; + var scaleMin = Math.min(scaleX, scaleY); + var scaleMax = Math.max(scaleX, scaleY); + if (meetOrSlice == 'meet') { desiredWidth *= scaleMin; desiredHeight *= scaleMin; } + if (meetOrSlice == 'slice') { desiredWidth *= scaleMax; desiredHeight *= scaleMax; } + + refX = new svg.Property('refX', refX); + refY = new svg.Property('refY', refY); + if (refX.hasValue() && refY.hasValue()) { + ctx.translate(-scaleMin * refX.Length.toPixels('x'), -scaleMin * refY.Length.toPixels('y')); + } + else { + // align + if (align.match(/^xMid/) && ((meetOrSlice == 'meet' && scaleMin == scaleY) || (meetOrSlice == 'slice' && scaleMax == scaleY))) ctx.translate(width / 2.0 - desiredWidth / 2.0, 0); + if (align.match(/YMid$/) && ((meetOrSlice == 'meet' && scaleMin == scaleX) || (meetOrSlice == 'slice' && scaleMax == scaleX))) ctx.translate(0, height / 2.0 - desiredHeight / 2.0); + if (align.match(/^xMax/) && ((meetOrSlice == 'meet' && scaleMin == scaleY) || (meetOrSlice == 'slice' && scaleMax == scaleY))) ctx.translate(width - desiredWidth, 0); + if (align.match(/YMax$/) && ((meetOrSlice == 'meet' && scaleMin == scaleX) || (meetOrSlice == 'slice' && scaleMax == scaleX))) ctx.translate(0, height - desiredHeight); + } + + // scale + if (align == 'none') ctx.scale(scaleX, scaleY); + else if (meetOrSlice == 'meet') ctx.scale(scaleMin, scaleMin); + else if (meetOrSlice == 'slice') ctx.scale(scaleMax, scaleMax); + + // translate + ctx.translate(minX == null ? 0 : -minX, minY == null ? 0 : -minY); + } + + // elements + svg.Element = {} + + svg.Element.ElementBase = function(node) { + this.attributes = {}; + this.styles = {}; + this.children = []; + + // get or create attribute + this.attribute = function(name, createIfNotExists) { + var a = this.attributes[name]; + if (a != null) return a; + + a = new svg.Property(name, ''); + if (createIfNotExists == true) this.attributes[name] = a; + return a; + } + + // get or create style + this.style = function(name, createIfNotExists) { + var s = this.styles[name]; + if (s != null) return s; + + var a = this.attribute(name); + if (a != null && a.hasValue()) { + return a; + } + + s = new svg.Property(name, ''); + if (createIfNotExists == true) this.styles[name] = s; + return s; + } + + // base render + this.render = function(ctx) { + // don't render display=none + if (this.attribute('display').value == 'none') return; + + ctx.save(); + this.setContext(ctx); + this.renderChildren(ctx); + this.clearContext(ctx); + ctx.restore(); + } + + // base set context + this.setContext = function(ctx) { + // OVERRIDE ME! + } + + // base clear context + this.clearContext = function(ctx) { + // OVERRIDE ME! + } + + // base render children + this.renderChildren = function(ctx) { + for (var i=0; i<this.children.length; i++) { + this.children[i].render(ctx); + } + } + + this.addChild = function(childNode, create) { + var child = childNode; + if (create) child = svg.CreateElement(childNode); + child.parent = this; + this.children.push(child); + } + + if (node != null && node.nodeType == 1) { //ELEMENT_NODE + // add children + for (var i=0; i<node.childNodes.length; i++) { + var childNode = node.childNodes[i]; + if (childNode.nodeType == 1) this.addChild(childNode, true); //ELEMENT_NODE + } + + // add attributes + for (var i=0; i<node.attributes.length; i++) { + var attribute = node.attributes[i]; + this.attributes[attribute.nodeName] = new svg.Property(attribute.nodeName, attribute.nodeValue); + } + + // add tag styles + var styles = svg.Styles[this.type]; + if (styles != null) { + for (var name in styles) { + this.styles[name] = styles[name]; + } + } + + // add class styles + if (this.attribute('class').hasValue()) { + var classes = svg.compressSpaces(this.attribute('class').value).split(' '); + for (var j=0; j<classes.length; j++) { + styles = svg.Styles['.'+classes[j]]; + if (styles != null) { + for (var name in styles) { + this.styles[name] = styles[name]; + } + } + } + } + + // add inline styles + if (this.attribute('style').hasValue()) { + var styles = this.attribute('style').value.split(';'); + for (var i=0; i<styles.length; i++) { + if (svg.trim(styles[i]) != '') { + var style = styles[i].split(':'); + var name = svg.trim(style[0]); + var value = svg.trim(style[1]); + this.styles[name] = new svg.Property(name, value); + } + } + } + + // add id + if (this.attribute('id').hasValue()) { + if (svg.Definitions[this.attribute('id').value] == null) { + svg.Definitions[this.attribute('id').value] = this; + } + } + } + } + + svg.Element.RenderedElementBase = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.setContext = function(ctx) { + // fill + if (this.style('fill').Definition.isUrl()) { + var fs = this.style('fill').Definition.getFillStyle(this); + if (fs != null) ctx.fillStyle = fs; + } + else if (this.style('fill').hasValue()) { + var fillStyle = this.style('fill'); + if (this.style('fill-opacity').hasValue()) fillStyle = fillStyle.Color.addOpacity(this.style('fill-opacity').value); + ctx.fillStyle = (fillStyle.value == 'none' ? 'rgba(0,0,0,0)' : fillStyle.value); + } + + // stroke + if (this.style('stroke').Definition.isUrl()) { + var fs = this.style('stroke').Definition.getFillStyle(this); + if (fs != null) ctx.strokeStyle = fs; + } + else if (this.style('stroke').hasValue()) { + var strokeStyle = this.style('stroke'); + if (this.style('stroke-opacity').hasValue()) strokeStyle = strokeStyle.Color.addOpacity(this.style('stroke-opacity').value); + ctx.strokeStyle = (strokeStyle.value == 'none' ? 'rgba(0,0,0,0)' : strokeStyle.value); + } + if (this.style('stroke-width').hasValue()) ctx.lineWidth = this.style('stroke-width').Length.toPixels(); + if (this.style('stroke-linecap').hasValue()) ctx.lineCap = this.style('stroke-linecap').value; + if (this.style('stroke-linejoin').hasValue()) ctx.lineJoin = this.style('stroke-linejoin').value; + if (this.style('stroke-miterlimit').hasValue()) ctx.miterLimit = this.style('stroke-miterlimit').value; + + // font + if (typeof(ctx.font) != 'undefined') { + ctx.font = svg.Font.CreateFont( + this.style('font-style').value, + this.style('font-variant').value, + this.style('font-weight').value, + this.style('font-size').hasValue() ? this.style('font-size').Length.toPixels() + 'px' : '', + this.style('font-family').value).toString(); + } + + // transform + if (this.attribute('transform').hasValue()) { + var transform = new svg.Transform(this.attribute('transform').value); + transform.apply(ctx); + } + + // clip + if (this.attribute('clip-path').hasValue()) { + var clip = this.attribute('clip-path').Definition.getDefinition(); + if (clip != null) clip.apply(ctx); + } + + // opacity + if (this.style('opacity').hasValue()) { + ctx.globalAlpha = this.style('opacity').numValue(); + } + } + } + svg.Element.RenderedElementBase.prototype = new svg.Element.ElementBase; + + svg.Element.PathElementBase = function(node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + + this.path = function(ctx) { + if (ctx != null) ctx.beginPath(); + return new svg.BoundingBox(); + } + + this.renderChildren = function(ctx) { + this.path(ctx); + svg.Mouse.checkPath(this, ctx); + if (ctx.fillStyle != '') ctx.fill(); + if (ctx.strokeStyle != '') ctx.stroke(); + + var markers = this.getMarkers(); + if (markers != null) { + if (this.attribute('marker-start').Definition.isUrl()) { + var marker = this.attribute('marker-start').Definition.getDefinition(); + marker.render(ctx, markers[0][0], markers[0][1]); + } + if (this.attribute('marker-mid').Definition.isUrl()) { + var marker = this.attribute('marker-mid').Definition.getDefinition(); + for (var i=1;i<markers.length-1;i++) { + marker.render(ctx, markers[i][0], markers[i][1]); + } + } + if (this.attribute('marker-end').Definition.isUrl()) { + var marker = this.attribute('marker-end').Definition.getDefinition(); + marker.render(ctx, markers[markers.length-1][0], markers[markers.length-1][1]); + } + } + } + + this.getBoundingBox = function() { + return this.path(); + } + + this.getMarkers = function() { + return null; + } + } + svg.Element.PathElementBase.prototype = new svg.Element.RenderedElementBase; + + // svg element + svg.Element.svg = function(node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + + this.baseClearContext = this.clearContext; + this.clearContext = function(ctx) { + this.baseClearContext(ctx); + svg.ViewPort.RemoveCurrent(); + } + + this.baseSetContext = this.setContext; + this.setContext = function(ctx) { + // initial values + ctx.strokeStyle = 'rgba(0,0,0,0)'; + ctx.lineCap = 'butt'; + ctx.lineJoin = 'miter'; + ctx.miterLimit = 4; + + this.baseSetContext(ctx); + + // create new view port + if (this.attribute('x').hasValue() && this.attribute('y').hasValue()) { + ctx.translate(this.attribute('x').Length.toPixels('x'), this.attribute('y').Length.toPixels('y')); + } + + var width = svg.ViewPort.width(); + var height = svg.ViewPort.height(); + if (this.attribute('width').hasValue() && this.attribute('height').hasValue()) { + width = this.attribute('width').Length.toPixels('x'); + height = this.attribute('height').Length.toPixels('y'); + + var x = 0; + var y = 0; + if (this.attribute('refX').hasValue() && this.attribute('refY').hasValue()) { + x = -this.attribute('refX').Length.toPixels('x'); + y = -this.attribute('refY').Length.toPixels('y'); + } + + ctx.beginPath(); + ctx.moveTo(x, y); + ctx.lineTo(width, y); + ctx.lineTo(width, height); + ctx.lineTo(x, height); + ctx.closePath(); + ctx.clip(); + } + svg.ViewPort.SetCurrent(width, height); + + // viewbox + if (this.attribute('viewBox').hasValue()) { + var viewBox = svg.ToNumberArray(this.attribute('viewBox').value); + var minX = viewBox[0]; + var minY = viewBox[1]; + width = viewBox[2]; + height = viewBox[3]; + + svg.AspectRatio(ctx, + this.attribute('preserveAspectRatio').value, + svg.ViewPort.width(), + width, + svg.ViewPort.height(), + height, + minX, + minY, + this.attribute('refX').value, + this.attribute('refY').value); + + svg.ViewPort.RemoveCurrent(); + svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]); + } + } + } + svg.Element.svg.prototype = new svg.Element.RenderedElementBase; + + // rect element + svg.Element.rect = function(node) { + this.base = svg.Element.PathElementBase; + this.base(node); + + this.path = function(ctx) { + var x = this.attribute('x').Length.toPixels('x'); + var y = this.attribute('y').Length.toPixels('y'); + var width = this.attribute('width').Length.toPixels('x'); + var height = this.attribute('height').Length.toPixels('y'); + var rx = this.attribute('rx').Length.toPixels('x'); + var ry = this.attribute('ry').Length.toPixels('y'); + if (this.attribute('rx').hasValue() && !this.attribute('ry').hasValue()) ry = rx; + if (this.attribute('ry').hasValue() && !this.attribute('rx').hasValue()) rx = ry; + + if (ctx != null) { + ctx.beginPath(); + ctx.moveTo(x + rx, y); + ctx.lineTo(x + width - rx, y); + ctx.quadraticCurveTo(x + width, y, x + width, y + ry) + ctx.lineTo(x + width, y + height - ry); + ctx.quadraticCurveTo(x + width, y + height, x + width - rx, y + height) + ctx.lineTo(x + rx, y + height); + ctx.quadraticCurveTo(x, y + height, x, y + height - ry) + ctx.lineTo(x, y + ry); + ctx.quadraticCurveTo(x, y, x + rx, y) + ctx.closePath(); + } + + return new svg.BoundingBox(x, y, x + width, y + height); + } + } + svg.Element.rect.prototype = new svg.Element.PathElementBase; + + // circle element + svg.Element.circle = function(node) { + this.base = svg.Element.PathElementBase; + this.base(node); + + this.path = function(ctx) { + var cx = this.attribute('cx').Length.toPixels('x'); + var cy = this.attribute('cy').Length.toPixels('y'); + var r = this.attribute('r').Length.toPixels(); + + if (ctx != null) { + ctx.beginPath(); + ctx.arc(cx, cy, r, 0, Math.PI * 2, true); + ctx.closePath(); + } + + return new svg.BoundingBox(cx - r, cy - r, cx + r, cy + r); + } + } + svg.Element.circle.prototype = new svg.Element.PathElementBase; + + // ellipse element + svg.Element.ellipse = function(node) { + this.base = svg.Element.PathElementBase; + this.base(node); + + this.path = function(ctx) { + var KAPPA = 4 * ((Math.sqrt(2) - 1) / 3); + var rx = this.attribute('rx').Length.toPixels('x'); + var ry = this.attribute('ry').Length.toPixels('y'); + var cx = this.attribute('cx').Length.toPixels('x'); + var cy = this.attribute('cy').Length.toPixels('y'); + + if (ctx != null) { + ctx.beginPath(); + ctx.moveTo(cx, cy - ry); + ctx.bezierCurveTo(cx + (KAPPA * rx), cy - ry, cx + rx, cy - (KAPPA * ry), cx + rx, cy); + ctx.bezierCurveTo(cx + rx, cy + (KAPPA * ry), cx + (KAPPA * rx), cy + ry, cx, cy + ry); + ctx.bezierCurveTo(cx - (KAPPA * rx), cy + ry, cx - rx, cy + (KAPPA * ry), cx - rx, cy); + ctx.bezierCurveTo(cx - rx, cy - (KAPPA * ry), cx - (KAPPA * rx), cy - ry, cx, cy - ry); + ctx.closePath(); + } + + return new svg.BoundingBox(cx - rx, cy - ry, cx + rx, cy + ry); + } + } + svg.Element.ellipse.prototype = new svg.Element.PathElementBase; + + // line element + svg.Element.line = function(node) { + this.base = svg.Element.PathElementBase; + this.base(node); + + this.getPoints = function() { + return [ + new svg.Point(this.attribute('x1').Length.toPixels('x'), this.attribute('y1').Length.toPixels('y')), + new svg.Point(this.attribute('x2').Length.toPixels('x'), this.attribute('y2').Length.toPixels('y'))]; + } + + this.path = function(ctx) { + var points = this.getPoints(); + + if (ctx != null) { + ctx.beginPath(); + ctx.moveTo(points[0].x, points[0].y); + ctx.lineTo(points[1].x, points[1].y); + } + + return new svg.BoundingBox(points[0].x, points[0].y, points[1].x, points[1].y); + } + + this.getMarkers = function() { + var points = this.getPoints(); + var a = points[0].angleTo(points[1]); + return [[points[0], a], [points[1], a]]; + } + } + svg.Element.line.prototype = new svg.Element.PathElementBase; + + // polyline element + svg.Element.polyline = function(node) { + this.base = svg.Element.PathElementBase; + this.base(node); + + this.points = svg.CreatePath(this.attribute('points').value); + this.path = function(ctx) { + var bb = new svg.BoundingBox(this.points[0].x, this.points[0].y); + if (ctx != null) { + ctx.beginPath(); + ctx.moveTo(this.points[0].x, this.points[0].y); + } + for (var i=1; i<this.points.length; i++) { + bb.addPoint(this.points[i].x, this.points[i].y); + if (ctx != null) ctx.lineTo(this.points[i].x, this.points[i].y); + } + return bb; + } + + this.getMarkers = function() { + var markers = []; + for (var i=0; i<this.points.length - 1; i++) { + markers.push([this.points[i], this.points[i].angleTo(this.points[i+1])]); + } + markers.push([this.points[this.points.length-1], markers[markers.length-1][1]]); + return markers; + } + } + svg.Element.polyline.prototype = new svg.Element.PathElementBase; + + // polygon element + svg.Element.polygon = function(node) { + this.base = svg.Element.polyline; + this.base(node); + + this.basePath = this.path; + this.path = function(ctx) { + var bb = this.basePath(ctx); + if (ctx != null) { + ctx.lineTo(this.points[0].x, this.points[0].y); + ctx.closePath(); + } + return bb; + } + } + svg.Element.polygon.prototype = new svg.Element.polyline; + + // path element + svg.Element.path = function(node) { + this.base = svg.Element.PathElementBase; + this.base(node); + + var d = this.attribute('d').value; + // TODO: floating points, convert to real lexer based on http://www.w3.org/TR/SVG11/paths.html#PathDataBNF + d = d.replace(/,/gm,' '); // get rid of all commas + d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm,'$1 $2'); // separate commands from commands + d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([MmZzLlHhVvCcSsQqTtAa])/gm,'$1 $2'); // separate commands from commands + d = d.replace(/([MmZzLlHhVvCcSsQqTtAa])([^\s])/gm,'$1 $2'); // separate commands from points + d = d.replace(/([^\s])([MmZzLlHhVvCcSsQqTtAa])/gm,'$1 $2'); // separate commands from points + d = d.replace(/([0-9])([+\-])/gm,'$1 $2'); // separate digits when no comma + d = d.replace(/(\.[0-9]*)(\.)/gm,'$1 $2'); // separate digits when no comma + d = d.replace(/([Aa](\s+[0-9]+){3})\s+([01])\s*([01])/gm,'$1 $3 $4 '); // shorthand elliptical arc path syntax + d = svg.compressSpaces(d); // compress multiple spaces + d = svg.trim(d); + this.PathParser = new (function(d) { + this.tokens = d.split(' '); + + this.reset = function() { + this.i = -1; + this.command = ''; + this.previousCommand = ''; + this.start = new svg.Point(0, 0); + this.control = new svg.Point(0, 0); + this.current = new svg.Point(0, 0); + this.points = []; + this.angles = []; + } + + this.isEnd = function() { + return this.i >= this.tokens.length - 1; + } + + this.isCommandOrEnd = function() { + if (this.isEnd()) return true; + return this.tokens[this.i + 1].match(/[A-Za-z]/) != null; + } + + this.isRelativeCommand = function() { + return this.command == this.command.toLowerCase(); + } + + this.getToken = function() { + this.i = this.i + 1; + return this.tokens[this.i]; + } + + this.getScalar = function() { + return parseFloat(this.getToken()); + } + + this.nextCommand = function() { + this.previousCommand = this.command; + this.command = this.getToken(); + } + + this.getPoint = function() { + var p = new svg.Point(this.getScalar(), this.getScalar()); + return this.makeAbsolute(p); + } + + this.getAsControlPoint = function() { + var p = this.getPoint(); + this.control = p; + return p; + } + + this.getAsCurrentPoint = function() { + var p = this.getPoint(); + this.current = p; + return p; + } + + this.getReflectedControlPoint = function() { + if (this.previousCommand.toLowerCase() != 'c' && this.previousCommand.toLowerCase() != 's') { + return this.current; + } + + // reflect point + var p = new svg.Point(2 * this.current.x - this.control.x, 2 * this.current.y - this.control.y); + return p; + } + + this.makeAbsolute = function(p) { + if (this.isRelativeCommand()) { + p.x = this.current.x + p.x; + p.y = this.current.y + p.y; + } + return p; + } + + this.addMarker = function(p, from) { + this.addMarkerAngle(p, from == null ? null : from.angleTo(p)); + } + + this.addMarkerAngle = function(p, a) { + this.points.push(p); + this.angles.push(a); + } + + this.getMarkerPoints = function() { return this.points; } + this.getMarkerAngles = function() { + for (var i=0; i<this.angles.length; i++) { + if (this.angles[i] == null) { + for (var j=i+1; j<this.angles.length; j++) { + if (this.angles[j] != null) { + this.angles[i] = this.angles[j]; + break; + } + } + } + } + return this.angles; + } + })(d); + + this.path = function(ctx) { + var pp = this.PathParser; + pp.reset(); + + var bb = new svg.BoundingBox(); + + if(this.attribute('visibility').value=='hidden') return; + + if (ctx != null) ctx.beginPath(); + while (!pp.isEnd()) { + pp.nextCommand(); + switch (pp.command.toUpperCase()) { + case 'M': + var p = pp.getAsCurrentPoint(); + pp.addMarker(p); + bb.addPoint(p.x, p.y); + if (ctx != null) ctx.moveTo(p.x, p.y); + pp.start = pp.current; + while (!pp.isCommandOrEnd()) { + var p = pp.getAsCurrentPoint(); + pp.addMarker(p); + bb.addPoint(p.x, p.y); + if (ctx != null) ctx.lineTo(p.x, p.y); + } + break; + case 'L': + while (!pp.isCommandOrEnd()) { + var c = pp.current; + var p = pp.getAsCurrentPoint(); + pp.addMarker(p, c); + bb.addPoint(p.x, p.y); + if (ctx != null) ctx.lineTo(p.x, p.y); + } + break; + case 'H': + while (!pp.isCommandOrEnd()) { + var newP = new svg.Point((pp.isRelativeCommand() ? pp.current.x : 0) + pp.getScalar(), pp.current.y); + pp.addMarker(newP, pp.current); + pp.current = newP; + bb.addPoint(pp.current.x, pp.current.y); + if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y); + } + break; + case 'V': + while (!pp.isCommandOrEnd()) { + var newP = new svg.Point(pp.current.x, (pp.isRelativeCommand() ? pp.current.y : 0) + pp.getScalar()); + pp.addMarker(newP, pp.current); + pp.current = newP; + bb.addPoint(pp.current.x, pp.current.y); + if (ctx != null) ctx.lineTo(pp.current.x, pp.current.y); + } + break; + case 'C': + while (!pp.isCommandOrEnd()) { + var curr = pp.current; + var p1 = pp.getPoint(); + var cntrl = pp.getAsControlPoint(); + var cp = pp.getAsCurrentPoint(); + pp.addMarker(cp, cntrl); + bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y); + if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y); + } + break; + case 'S': + while (!pp.isCommandOrEnd()) { + var curr = pp.current; + var p1 = pp.getReflectedControlPoint(); + var cntrl = pp.getAsControlPoint(); + var cp = pp.getAsCurrentPoint(); + pp.addMarker(cp, cntrl); + bb.addBezierCurve(curr.x, curr.y, p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y); + if (ctx != null) ctx.bezierCurveTo(p1.x, p1.y, cntrl.x, cntrl.y, cp.x, cp.y); + } + break; + case 'Q': + while (!pp.isCommandOrEnd()) { + var curr = pp.current; + var cntrl = pp.getAsControlPoint(); + var cp = pp.getAsCurrentPoint(); + pp.addMarker(cp, cntrl); + bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y); + if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y); + } + break; + case 'T': + while (!pp.isCommandOrEnd()) { + var curr = pp.current; + var cntrl = pp.getReflectedControlPoint(); + pp.control = cntrl; + var cp = pp.getAsCurrentPoint(); + pp.addMarker(cp, cntrl); + bb.addQuadraticCurve(curr.x, curr.y, cntrl.x, cntrl.y, cp.x, cp.y); + if (ctx != null) ctx.quadraticCurveTo(cntrl.x, cntrl.y, cp.x, cp.y); + } + break; + case 'A': + while (!pp.isCommandOrEnd()) { + var curr = pp.current; + var rx = pp.getScalar(); + var ry = pp.getScalar(); + var xAxisRotation = pp.getScalar() * (Math.PI / 180.0); + var largeArcFlag = pp.getScalar(); + var sweepFlag = pp.getScalar(); + var cp = pp.getAsCurrentPoint(); + + // Conversion from endpoint to center parameterization + // http://www.w3.org/TR/SVG11/implnote.html#ArcImplementationNotes + // x1', y1' + var currp = new svg.Point( + Math.cos(xAxisRotation) * (curr.x - cp.x) / 2.0 + Math.sin(xAxisRotation) * (curr.y - cp.y) / 2.0, + -Math.sin(xAxisRotation) * (curr.x - cp.x) / 2.0 + Math.cos(xAxisRotation) * (curr.y - cp.y) / 2.0 + ); + // adjust radii + var l = Math.pow(currp.x,2)/Math.pow(rx,2)+Math.pow(currp.y,2)/Math.pow(ry,2); + if (l > 1) { + rx *= Math.sqrt(l); + ry *= Math.sqrt(l); + } + // cx', cy' + var s = (largeArcFlag == sweepFlag ? -1 : 1) * Math.sqrt( + ((Math.pow(rx,2)*Math.pow(ry,2))-(Math.pow(rx,2)*Math.pow(currp.y,2))-(Math.pow(ry,2)*Math.pow(currp.x,2))) / + (Math.pow(rx,2)*Math.pow(currp.y,2)+Math.pow(ry,2)*Math.pow(currp.x,2)) + ); + if (isNaN(s)) s = 0; + var cpp = new svg.Point(s * rx * currp.y / ry, s * -ry * currp.x / rx); + // cx, cy + var centp = new svg.Point( + (curr.x + cp.x) / 2.0 + Math.cos(xAxisRotation) * cpp.x - Math.sin(xAxisRotation) * cpp.y, + (curr.y + cp.y) / 2.0 + Math.sin(xAxisRotation) * cpp.x + Math.cos(xAxisRotation) * cpp.y + ); + // vector magnitude + var m = function(v) { return Math.sqrt(Math.pow(v[0],2) + Math.pow(v[1],2)); } + // ratio between two vectors + var r = function(u, v) { return (u[0]*v[0]+u[1]*v[1]) / (m(u)*m(v)) } + // angle between two vectors + var a = function(u, v) { return (u[0]*v[1] < u[1]*v[0] ? -1 : 1) * Math.acos(r(u,v)); } + // initial angle + var a1 = a([1,0], [(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry]); + // angle delta + var u = [(currp.x-cpp.x)/rx,(currp.y-cpp.y)/ry]; + var v = [(-currp.x-cpp.x)/rx,(-currp.y-cpp.y)/ry]; + var ad = a(u, v); + if (r(u,v) <= -1) ad = Math.PI; + if (r(u,v) >= 1) ad = 0; + + if (sweepFlag == 0 && ad > 0) ad = ad - 2 * Math.PI; + if (sweepFlag == 1 && ad < 0) ad = ad + 2 * Math.PI; + + // for markers + var halfWay = new svg.Point( + centp.x - rx * Math.cos((a1 + ad) / 2), + centp.y - ry * Math.sin((a1 + ad) / 2) + ); + pp.addMarkerAngle(halfWay, (a1 + ad) / 2 + (sweepFlag == 0 ? 1 : -1) * Math.PI / 2); + pp.addMarkerAngle(cp, ad + (sweepFlag == 0 ? 1 : -1) * Math.PI / 2); + + bb.addPoint(cp.x, cp.y); // TODO: this is too naive, make it better + if (ctx != null) { + var r = rx > ry ? rx : ry; + var sx = rx > ry ? 1 : rx / ry; + var sy = rx > ry ? ry / rx : 1; + + ctx.translate(centp.x, centp.y); + ctx.rotate(xAxisRotation); + ctx.scale(sx, sy); + ctx.arc(0, 0, r, a1, a1 + ad, 1 - sweepFlag); + ctx.scale(1/sx, 1/sy); + ctx.rotate(-xAxisRotation); + ctx.translate(-centp.x, -centp.y); + } + } + break; + case 'Z': + if (ctx != null) ctx.closePath(); + pp.current = pp.start; + } + } + + return bb; + } + + this.getMarkers = function() { + var points = this.PathParser.getMarkerPoints(); + var angles = this.PathParser.getMarkerAngles(); + + var markers = []; + for (var i=0; i<points.length; i++) { + markers.push([points[i], angles[i]]); + } + return markers; + } + } + svg.Element.path.prototype = new svg.Element.PathElementBase; + + // pattern element + svg.Element.pattern = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.createPattern = function(ctx, element) { + // render me using a temporary svg element + var tempSvg = new svg.Element.svg(); + tempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value); + tempSvg.attributes['x'] = new svg.Property('x', this.attribute('x').value); + tempSvg.attributes['y'] = new svg.Property('y', this.attribute('y').value); + tempSvg.attributes['width'] = new svg.Property('width', this.attribute('width').value); + tempSvg.attributes['height'] = new svg.Property('height', this.attribute('height').value); + tempSvg.children = this.children; + + var c = document.createElement('canvas'); + c.width = this.attribute('width').Length.toPixels(); + c.height = this.attribute('height').Length.toPixels(); + tempSvg.render(c.getContext('2d')); + return ctx.createPattern(c, 'repeat'); + } + } + svg.Element.pattern.prototype = new svg.Element.ElementBase; + + // marker element + svg.Element.marker = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.baseRender = this.render; + this.render = function(ctx, point, angle) { + ctx.translate(point.x, point.y); + if (this.attribute('orient').valueOrDefault('auto') == 'auto') ctx.rotate(angle); + if (this.attribute('markerUnits').valueOrDefault('strokeWidth') == 'strokeWidth') ctx.scale(ctx.lineWidth, ctx.lineWidth); + ctx.save(); + + // render me using a temporary svg element + var tempSvg = new svg.Element.svg(); + tempSvg.attributes['viewBox'] = new svg.Property('viewBox', this.attribute('viewBox').value); + tempSvg.attributes['refX'] = new svg.Property('refX', this.attribute('refX').value); + tempSvg.attributes['refY'] = new svg.Property('refY', this.attribute('refY').value); + tempSvg.attributes['width'] = new svg.Property('width', this.attribute('markerWidth').value); + tempSvg.attributes['height'] = new svg.Property('height', this.attribute('markerHeight').value); + tempSvg.attributes['fill'] = new svg.Property('fill', this.attribute('fill').valueOrDefault('black')); + tempSvg.attributes['stroke'] = new svg.Property('stroke', this.attribute('stroke').valueOrDefault('none')); + tempSvg.children = this.children; + tempSvg.render(ctx); + + ctx.restore(); + if (this.attribute('markerUnits').valueOrDefault('strokeWidth') == 'strokeWidth') ctx.scale(1/ctx.lineWidth, 1/ctx.lineWidth); + if (this.attribute('orient').valueOrDefault('auto') == 'auto') ctx.rotate(-angle); + ctx.translate(-point.x, -point.y); + } + } + svg.Element.marker.prototype = new svg.Element.ElementBase; + + // definitions element + svg.Element.defs = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.render = function(ctx) { + // NOOP + } + } + svg.Element.defs.prototype = new svg.Element.ElementBase; + + // base for gradients + svg.Element.GradientBase = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.gradientUnits = this.attribute('gradientUnits').valueOrDefault('objectBoundingBox'); + + this.stops = []; + for (var i=0; i<this.children.length; i++) { + var child = this.children[i]; + this.stops.push(child); + } + + this.getGradient = function() { + // OVERRIDE ME! + } + + this.createGradient = function(ctx, element) { + var stopsContainer = this; + if (this.attribute('xlink:href').hasValue()) { + stopsContainer = this.attribute('xlink:href').Definition.getDefinition(); + } + + var g = this.getGradient(ctx, element); + for (var i=0; i<stopsContainer.stops.length; i++) { + g.addColorStop(stopsContainer.stops[i].offset, stopsContainer.stops[i].color); + } + return g; + } + } + svg.Element.GradientBase.prototype = new svg.Element.ElementBase; + + // linear gradient element + svg.Element.linearGradient = function(node) { + this.base = svg.Element.GradientBase; + this.base(node); + + this.getGradient = function(ctx, element) { + var bb = element.getBoundingBox(); + + var x1 = (this.gradientUnits == 'objectBoundingBox' + ? bb.x() + bb.width() * this.attribute('x1').numValue() + : this.attribute('x1').Length.toPixels('x')); + var y1 = (this.gradientUnits == 'objectBoundingBox' + ? bb.y() + bb.height() * this.attribute('y1').numValue() + : this.attribute('y1').Length.toPixels('y')); + var x2 = (this.gradientUnits == 'objectBoundingBox' + ? bb.x() + bb.width() * this.attribute('x2').numValue() + : this.attribute('x2').Length.toPixels('x')); + var y2 = (this.gradientUnits == 'objectBoundingBox' + ? bb.y() + bb.height() * this.attribute('y2').numValue() + : this.attribute('y2').Length.toPixels('y')); + + var p1 = new svg.Point(x1, y1); + var p2 = new svg.Point(x2, y2); + if (this.attribute('gradientTransform').hasValue()) { + var transform = new svg.Transform(this.attribute('gradientTransform').value); + transform.applyToPoint(p1); + transform.applyToPoint(p2); + } + + return ctx.createLinearGradient(p1.x, p1.y, p2.x, p2.y); + } + } + svg.Element.linearGradient.prototype = new svg.Element.GradientBase; + + // radial gradient element + svg.Element.radialGradient = function(node) { + this.base = svg.Element.GradientBase; + this.base(node); + + this.getGradient = function(ctx, element) { + var bb = element.getBoundingBox(); + + var cx = (this.gradientUnits == 'objectBoundingBox' + ? bb.x() + bb.width() * this.attribute('cx').numValue() + : this.attribute('cx').Length.toPixels('x')); + var cy = (this.gradientUnits == 'objectBoundingBox' + ? bb.y() + bb.height() * this.attribute('cy').numValue() + : this.attribute('cy').Length.toPixels('y')); + + var fx = cx; + var fy = cy; + if (this.attribute('fx').hasValue()) { + fx = (this.gradientUnits == 'objectBoundingBox' + ? bb.x() + bb.width() * this.attribute('fx').numValue() + : this.attribute('fx').Length.toPixels('x')); + } + if (this.attribute('fy').hasValue()) { + fy = (this.gradientUnits == 'objectBoundingBox' + ? bb.y() + bb.height() * this.attribute('fy').numValue() + : this.attribute('fy').Length.toPixels('y')); + } + + var r = (this.gradientUnits == 'objectBoundingBox' + ? (bb.width() + bb.height()) / 2.0 * this.attribute('r').numValue() + : this.attribute('r').Length.toPixels()); + + var c = new svg.Point(cx, cy); + var f = new svg.Point(fx, fy); + if (this.attribute('gradientTransform').hasValue()) { + var transform = new svg.Transform(this.attribute('gradientTransform').value); + transform.applyToPoint(c); + transform.applyToPoint(f); + + for (var i=0; i<transform.transforms.length; i++) { + // average the scaling part of the transform, apply to radius + var scale1 = transform.transforms[i].m[0]; + var scale2 = transform.transforms[i].m[3]; + r = r * ((scale1 + scale2) / 2.0); + } + } + + return ctx.createRadialGradient(f.x, f.y, 0, c.x, c.y, r); + } + } + svg.Element.radialGradient.prototype = new svg.Element.GradientBase; + + // gradient stop element + svg.Element.stop = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.offset = this.attribute('offset').numValue(); + + var stopColor = this.style('stop-color'); + if (this.style('stop-opacity').hasValue()) stopColor = stopColor.Color.addOpacity(this.style('stop-opacity').value); + this.color = stopColor.value; + } + svg.Element.stop.prototype = new svg.Element.ElementBase; + + // animation base element + svg.Element.AnimateBase = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + + svg.Animations.push(this); + + this.duration = 0.0; + this.begin = this.attribute('begin').Time.toMilliseconds(); + this.maxDuration = this.begin + this.attribute('dur').Time.toMilliseconds(); + + this.getProperty = function() { + var attributeType = this.attribute('attributeType').value; + var attributeName = this.attribute('attributeName').value; + + if (attributeType == 'CSS') { + return this.parent.style(attributeName, true); + } + return this.parent.attribute(attributeName, true); + }; + + this.initialValue = null; + this.removed = false; + + this.calcValue = function() { + // OVERRIDE ME! + return ''; + } + + this.update = function(delta) { + // set initial value + if (this.initialValue == null) { + this.initialValue = this.getProperty().value; + } + + // if we're past the end time + if (this.duration > this.maxDuration) { + // loop for indefinitely repeating animations + if (this.attribute('repeatCount').value == 'indefinite') { + this.duration = 0.0 + } + else if (this.attribute('fill').valueOrDefault('remove') == 'remove' && !this.removed) { + this.removed = true; + this.getProperty().value = this.initialValue; + return true; + } + else { + return false; // no updates made + } + } + this.duration = this.duration + delta; + + // if we're past the begin time + var updated = false; + if (this.begin < this.duration) { + var newValue = this.calcValue(); // tween + + if (this.attribute('type').hasValue()) { + // for transform, etc. + var type = this.attribute('type').value; + newValue = type + '(' + newValue + ')'; + } + + this.getProperty().value = newValue; + updated = true; + } + + return updated; + } + + // fraction of duration we've covered + this.progress = function() { + return ((this.duration - this.begin) / (this.maxDuration - this.begin)); + } + } + svg.Element.AnimateBase.prototype = new svg.Element.ElementBase; + + // animate element + svg.Element.animate = function(node) { + this.base = svg.Element.AnimateBase; + this.base(node); + + this.calcValue = function() { + var from = this.attribute('from').numValue(); + var to = this.attribute('to').numValue(); + + // tween value linearly + return from + (to - from) * this.progress(); + }; + } + svg.Element.animate.prototype = new svg.Element.AnimateBase; + + // animate color element + svg.Element.animateColor = function(node) { + this.base = svg.Element.AnimateBase; + this.base(node); + + this.calcValue = function() { + var from = new RGBColor(this.attribute('from').value); + var to = new RGBColor(this.attribute('to').value); + + if (from.ok && to.ok) { + // tween color linearly + var r = from.r + (to.r - from.r) * this.progress(); + var g = from.g + (to.g - from.g) * this.progress(); + var b = from.b + (to.b - from.b) * this.progress(); + return 'rgb('+parseInt(r,10)+','+parseInt(g,10)+','+parseInt(b,10)+')'; + } + return this.attribute('from').value; + }; + } + svg.Element.animateColor.prototype = new svg.Element.AnimateBase; + + // animate transform element + svg.Element.animateTransform = function(node) { + this.base = svg.Element.animate; + this.base(node); + } + svg.Element.animateTransform.prototype = new svg.Element.animate; + + // text element + svg.Element.text = function(node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + + if (node != null) { + // add children + this.children = []; + for (var i=0; i<node.childNodes.length; i++) { + var childNode = node.childNodes[i]; + if (childNode.nodeType == 1) { // capture tspan and tref nodes + this.addChild(childNode, true); + } + else if (childNode.nodeType == 3) { // capture text + this.addChild(new svg.Element.tspan(childNode), false); + } + } + } + + this.baseSetContext = this.setContext; + this.setContext = function(ctx) { + this.baseSetContext(ctx); + if (this.attribute('text-anchor').hasValue()) { + var textAnchor = this.attribute('text-anchor').value; + ctx.textAlign = textAnchor == 'middle' ? 'center' : textAnchor; + } + if (this.attribute('alignment-baseline').hasValue()) ctx.textBaseline = this.attribute('alignment-baseline').value; + } + + this.renderChildren = function(ctx) { + if(this.attribute('visibility').value=='hidden') return; + + var x = this.attribute('x').Length.toPixels('x'); + var y = this.attribute('y').Length.toPixels('y'); + + for (var i=0; i<this.children.length; i++) { + var child = this.children[i]; + + if (child.attribute('x').hasValue()) { + child.x = child.attribute('x').Length.toPixels('x'); + } + else { + if (child.attribute('dx').hasValue()) x += child.attribute('dx').Length.toPixels('x'); + child.x = x; + x += child.measureText(ctx); + } + + if (child.attribute('y').hasValue()) { + child.y = child.attribute('y').Length.toPixels('y'); + } + else { + if (child.attribute('dy').hasValue()) y += child.attribute('dy').Length.toPixels('y'); + child.y = y; + } + + child.render(ctx); + } + } + } + svg.Element.text.prototype = new svg.Element.RenderedElementBase; + + // text base + svg.Element.TextElementBase = function(node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + + this.renderChildren = function(ctx) { + ctx.fillText(svg.compressSpaces(this.getText()), this.x, this.y); + } + + this.getText = function() { + // OVERRIDE ME + } + + this.measureText = function(ctx) { + var textToMeasure = svg.compressSpaces(this.getText()); + if (!ctx.measureText) return textToMeasure.length * 10; + return ctx.measureText(textToMeasure).width; + } + } + svg.Element.TextElementBase.prototype = new svg.Element.RenderedElementBase; + + // tspan + svg.Element.tspan = function(node) { + this.base = svg.Element.TextElementBase; + this.base(node); + + // TEXT ELEMENT + this.text = node.nodeType == 3 ? node.nodeValue : node.childNodes[0].nodeValue; + this.getText = function() { + return this.text; + } + } + svg.Element.tspan.prototype = new svg.Element.TextElementBase; + + // tref + svg.Element.tref = function(node) { + this.base = svg.Element.TextElementBase; + this.base(node); + + this.getText = function() { + var element = this.attribute('xlink:href').Definition.getDefinition(); + if (element != null) return element.children[0].getText(); + } + } + svg.Element.tref.prototype = new svg.Element.TextElementBase; + + // a element + svg.Element.a = function(node) { + this.base = svg.Element.TextElementBase; + this.base(node); + + this.hasText = true; + for (var i=0; i<node.childNodes.length; i++) { + if (node.childNodes[i].nodeType != 3) this.hasText = false; + } + + // this might contain text + this.text = this.hasText ? node.childNodes[0].nodeValue : ''; + this.getText = function() { + return this.text; + } + + this.baseRenderChildren = this.renderChildren; + this.renderChildren = function(ctx) { + if (this.hasText) { + // render as text element + this.baseRenderChildren(ctx); + var fontSize = new svg.Property('fontSize', svg.Font.Parse(svg.ctx.font).fontSize); + svg.Mouse.checkBoundingBox(this, new svg.BoundingBox(this.x, this.y - fontSize.Length.toPixels('y'), this.x + this.measureText(ctx), this.y)); + } + else { + // render as temporary group + var g = new svg.Element.g(); + g.children = this.children; + g.parent = this; + g.render(ctx); + } + } + + this.onclick = function() { + window.open(this.attribute('xlink:href').value); + } + + this.onmousemove = function() { + svg.ctx.canvas.style.cursor = 'pointer'; + } + } + svg.Element.a.prototype = new svg.Element.TextElementBase; + + // image element + svg.Element.image = function(node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + + svg.Images.push(this); + this.img = document.createElement('img'); + this.loaded = false; + var that = this; + this.img.onload = function() { that.loaded = true; } + this.img.src = this.attribute('xlink:href').value; + + this.renderChildren = function(ctx) { + var x = this.attribute('x').Length.toPixels('x'); + var y = this.attribute('y').Length.toPixels('y'); + + var width = this.attribute('width').Length.toPixels('x'); + var height = this.attribute('height').Length.toPixels('y'); + if (width == 0 || height == 0) return; + + ctx.save(); + ctx.translate(x, y); + svg.AspectRatio(ctx, + this.attribute('preserveAspectRatio').value, + width, + this.img.width, + height, + this.img.height, + 0, + 0); + ctx.drawImage(this.img, 0, 0); + ctx.restore(); + } + } + svg.Element.image.prototype = new svg.Element.RenderedElementBase; + + // group element + svg.Element.g = function(node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + + this.getBoundingBox = function() { + var bb = new svg.BoundingBox(); + for (var i=0; i<this.children.length; i++) { + bb.addBoundingBox(this.children[i].getBoundingBox()); + } + return bb; + }; + } + svg.Element.g.prototype = new svg.Element.RenderedElementBase; + + // symbol element + svg.Element.symbol = function(node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + + this.baseSetContext = this.setContext; + this.setContext = function(ctx) { + this.baseSetContext(ctx); + + // viewbox + if (this.attribute('viewBox').hasValue()) { + var viewBox = svg.ToNumberArray(this.attribute('viewBox').value); + var minX = viewBox[0]; + var minY = viewBox[1]; + width = viewBox[2]; + height = viewBox[3]; + + svg.AspectRatio(ctx, + this.attribute('preserveAspectRatio').value, + this.attribute('width').Length.toPixels('x'), + width, + this.attribute('height').Length.toPixels('y'), + height, + minX, + minY); + + svg.ViewPort.SetCurrent(viewBox[2], viewBox[3]); + } + } + } + svg.Element.symbol.prototype = new svg.Element.RenderedElementBase; + + // style element + svg.Element.style = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + + var css = node.childNodes[0].nodeValue; + css = css.replace(/(\/\*([^*]|[\r\n]|(\*+([^*\/]|[\r\n])))*\*+\/)|(\/\/.*)/gm, ''); // remove comments + css = svg.compressSpaces(css); // replace whitespace + var cssDefs = css.split('}'); + for (var i=0; i<cssDefs.length; i++) { + if (svg.trim(cssDefs[i]) != '') { + var cssDef = cssDefs[i].split('{'); + var cssClasses = cssDef[0].split(','); + var cssProps = cssDef[1].split(';'); + for (var j=0; j<cssClasses.length; j++) { + var cssClass = svg.trim(cssClasses[j]); + if (cssClass != '') { + var props = {}; + for (var k=0; k<cssProps.length; k++) { + var prop = cssProps[k].split(':'); + var name = prop[0]; + var value = prop[1]; + if (name != null && value != null) { + props[svg.trim(prop[0])] = new svg.Property(svg.trim(prop[0]), svg.trim(prop[1])); + } + } + svg.Styles[cssClass] = props; + } + } + } + } + } + svg.Element.style.prototype = new svg.Element.ElementBase; + + // use element + svg.Element.use = function(node) { + this.base = svg.Element.RenderedElementBase; + this.base(node); + + this.baseSetContext = this.setContext; + this.setContext = function(ctx) { + this.baseSetContext(ctx); + if (this.attribute('x').hasValue()) ctx.translate(this.attribute('x').Length.toPixels('x'), 0); + if (this.attribute('y').hasValue()) ctx.translate(0, this.attribute('y').Length.toPixels('y')); + } + + this.getDefinition = function() { + var element = this.attribute('xlink:href').Definition.getDefinition(); + if (this.attribute('width').hasValue()) element.attribute('width', true).value = this.attribute('width').value; + if (this.attribute('height').hasValue()) element.attribute('height', true).value = this.attribute('height').value; + return element; + } + + this.path = function(ctx) { + var element = this.getDefinition(); + if (element != null) element.path(ctx); + } + + this.renderChildren = function(ctx) { + var element = this.getDefinition(); + if (element != null) element.render(ctx); + } + } + svg.Element.use.prototype = new svg.Element.RenderedElementBase; + + // clip element + svg.Element.clipPath = function(node) { + this.base = svg.Element.ElementBase; + this.base(node); + + this.apply = function(ctx) { + for (var i=0; i<this.children.length; i++) { + if (this.children[i].path) { + this.children[i].path(ctx); + ctx.clip(); + } + } + } + } + svg.Element.clipPath.prototype = new svg.Element.ElementBase; + + // title element, do nothing + svg.Element.title = function(node) { + } + svg.Element.title.prototype = new svg.Element.ElementBase; + + // desc element, do nothing + svg.Element.desc = function(node) { + } + svg.Element.desc.prototype = new svg.Element.ElementBase; + + svg.Element.MISSING = function(node) { + console.log('ERROR: Element \'' + node.nodeName + '\' not yet implemented.'); + } + svg.Element.MISSING.prototype = new svg.Element.ElementBase; + + // element factory + svg.CreateElement = function(node) { + var className = node.nodeName.replace(/^[^:]+:/,''); + var e = null; + if (typeof(svg.Element[className]) != 'undefined') { + e = new svg.Element[className](node); + } + else { + e = new svg.Element.MISSING(node); + } + + e.type = node.nodeName; + return e; + } + + // load from url + svg.load = function(ctx, url) { + svg.loadXml(ctx, svg.ajax(url)); + } + + // load from xml + svg.loadXml = function(ctx, xml) { + svg.init(ctx); + + var mapXY = function(p) { + var e = ctx.canvas; + while (e) { + p.x -= e.offsetLeft; + p.y -= e.offsetTop; + e = e.offsetParent; + } + if (window.scrollX) p.x += window.scrollX; + if (window.scrollY) p.y += window.scrollY; + return p; + } + + // bind mouse + if (svg.opts == null || svg.opts['ignoreMouse'] != true) { + ctx.canvas.onclick = function(e) { + var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY)); + svg.Mouse.onclick(p.x, p.y); + }; + ctx.canvas.onmousemove = function(e) { + var p = mapXY(new svg.Point(e != null ? e.clientX : event.clientX, e != null ? e.clientY : event.clientY)); + svg.Mouse.onmousemove(p.x, p.y); + }; + } + + var dom = svg.parseXml(xml); + var e = svg.CreateElement(dom.documentElement); + + // render loop + var isFirstRender = true; + var draw = function() { + if (svg.opts == null || svg.opts['ignoreDimensions'] != true) { + // set canvas size + if (e.style('width').hasValue()) { + ctx.canvas.width = e.style('width').Length.toPixels(ctx.canvas.parentNode.clientWidth); + } + if (e.style('height').hasValue()) { + ctx.canvas.height = e.style('height').Length.toPixels(ctx.canvas.parentNode.clientHeight); + } + } + svg.ViewPort.SetCurrent(ctx.canvas.clientWidth, ctx.canvas.clientHeight); + + if (svg.opts != null && svg.opts['offsetX'] != null) e.attribute('x', true).value = svg.opts['offsetX']; + if (svg.opts != null && svg.opts['offsetY'] != null) e.attribute('y', true).value = svg.opts['offsetY']; + if (svg.opts != null && svg.opts['scaleWidth'] != null && svg.opts['scaleHeight'] != null) { + e.attribute('width', true).value = svg.opts['scaleWidth']; + e.attribute('height', true).value = svg.opts['scaleHeight']; + e.attribute('viewBox', true).value = '0 0 ' + ctx.canvas.clientWidth + ' ' + ctx.canvas.clientHeight; + e.attribute('preserveAspectRatio', true).value = 'none'; + } + + // clear and render + if (svg.opts == null || svg.opts['ignoreClear'] != true) { + ctx.clearRect(0, 0, ctx.canvas.clientWidth, ctx.canvas.clientHeight); + } + e.render(ctx); + if (isFirstRender) { + isFirstRender = false; + if (svg.opts != null && typeof(svg.opts['renderCallback']) == 'function') svg.opts['renderCallback'](); + } + } + + var waitingForImages = true; + if (svg.ImagesLoaded()) { + waitingForImages = false; + draw(); + } + svg.intervalID = setInterval(function() { + var needUpdate = false; + + if (waitingForImages && svg.ImagesLoaded()) { + waitingForImages = false; + needUpdate = true; + } + + // need update from mouse events? + if (svg.opts == null || svg.opts['ignoreMouse'] != true) { + needUpdate = needUpdate | svg.Mouse.hasEvents(); + } + + // need update from animations? + if (svg.opts == null || svg.opts['ignoreAnimation'] != true) { + for (var i=0; i<svg.Animations.length; i++) { + needUpdate = needUpdate | svg.Animations[i].update(1000 / svg.FRAMERATE); + } + } + + // need update from redraw? + if (svg.opts != null && typeof(svg.opts['forceRedraw']) == 'function') { + if (svg.opts['forceRedraw']() == true) needUpdate = true; + } + + // render if needed + if (needUpdate) { + draw(); + svg.Mouse.runEvents(); // run and clear our events + } + }, 1000 / svg.FRAMERATE); + } + + svg.stop = function() { + if (svg.intervalID) { + clearInterval(svg.intervalID); + } + } + + svg.Mouse = new (function() { + this.events = []; + this.hasEvents = function() { return this.events.length != 0; } + + this.onclick = function(x, y) { + this.events.push({ type: 'onclick', x: x, y: y, + run: function(e) { if (e.onclick) e.onclick(); } + }); + } + + this.onmousemove = function(x, y) { + this.events.push({ type: 'onmousemove', x: x, y: y, + run: function(e) { if (e.onmousemove) e.onmousemove(); } + }); + } + + this.eventElements = []; + + this.checkPath = function(element, ctx) { + for (var i=0; i<this.events.length; i++) { + var e = this.events[i]; + if (ctx.isPointInPath && ctx.isPointInPath(e.x, e.y)) this.eventElements[i] = element; + } + } + + this.checkBoundingBox = function(element, bb) { + for (var i=0; i<this.events.length; i++) { + var e = this.events[i]; + if (bb.isPointInBox(e.x, e.y)) this.eventElements[i] = element; + } + } + + this.runEvents = function() { + svg.ctx.canvas.style.cursor = ''; + + for (var i=0; i<this.events.length; i++) { + var e = this.events[i]; + var element = this.eventElements[i]; + while (element) { + e.run(element); + element = element.parent; + } + } + + // done running, clear + this.events = []; + this.eventElements = []; + } + }); + + return svg; + } +})(); + +if (CanvasRenderingContext2D) { + CanvasRenderingContext2D.prototype.drawSvg = function(s, dx, dy, dw, dh) { + canvg(this.canvas, s, { + ignoreMouse: true, + ignoreAnimation: true, + ignoreDimensions: true, + ignoreClear: true, + offsetX: dx, + offsetY: dy, + scaleWidth: dw, + scaleHeight: dh + }); + } +} + +/** + * A class to parse color values + * @author Stoyan Stefanov <sstoo@gmail.com> + * @link http://www.phpied.com/rgb-color-parser-in-javascript/ + * @license Use it if you like it + */ +function RGBColor(color_string) +{ + this.ok = false; + + // strip any leading # + if (color_string.charAt(0) == '#') { // remove # if any + color_string = color_string.substr(1,6); + } + + color_string = color_string.replace(/ /g,''); + color_string = color_string.toLowerCase(); + + // before getting into regexps, try simple matches + // and overwrite the input + var simple_colors = { + aliceblue: 'f0f8ff', + antiquewhite: 'faebd7', + aqua: '00ffff', + aquamarine: '7fffd4', + azure: 'f0ffff', + beige: 'f5f5dc', + bisque: 'ffe4c4', + black: '000000', + blanchedalmond: 'ffebcd', + blue: '0000ff', + blueviolet: '8a2be2', + brown: 'a52a2a', + burlywood: 'deb887', + cadetblue: '5f9ea0', + chartreuse: '7fff00', + chocolate: 'd2691e', + coral: 'ff7f50', + cornflowerblue: '6495ed', + cornsilk: 'fff8dc', + crimson: 'dc143c', + cyan: '00ffff', + darkblue: '00008b', + darkcyan: '008b8b', + darkgoldenrod: 'b8860b', + darkgray: 'a9a9a9', + darkgreen: '006400', + darkkhaki: 'bdb76b', + darkmagenta: '8b008b', + darkolivegreen: '556b2f', + darkorange: 'ff8c00', + darkorchid: '9932cc', + darkred: '8b0000', + darksalmon: 'e9967a', + darkseagreen: '8fbc8f', + darkslateblue: '483d8b', + darkslategray: '2f4f4f', + darkturquoise: '00ced1', + darkviolet: '9400d3', + deeppink: 'ff1493', + deepskyblue: '00bfff', + dimgray: '696969', + dodgerblue: '1e90ff', + feldspar: 'd19275', + firebrick: 'b22222', + floralwhite: 'fffaf0', + forestgreen: '228b22', + fuchsia: 'ff00ff', + gainsboro: 'dcdcdc', + ghostwhite: 'f8f8ff', + gold: 'ffd700', + goldenrod: 'daa520', + gray: '808080', + green: '008000', + greenyellow: 'adff2f', + honeydew: 'f0fff0', + hotpink: 'ff69b4', + indianred : 'cd5c5c', + indigo : '4b0082', + ivory: 'fffff0', + khaki: 'f0e68c', + lavender: 'e6e6fa', + lavenderblush: 'fff0f5', + lawngreen: '7cfc00', + lemonchiffon: 'fffacd', + lightblue: 'add8e6', + lightcoral: 'f08080', + lightcyan: 'e0ffff', + lightgoldenrodyellow: 'fafad2', + lightgrey: 'd3d3d3', + lightgreen: '90ee90', + lightpink: 'ffb6c1', + lightsalmon: 'ffa07a', + lightseagreen: '20b2aa', + lightskyblue: '87cefa', + lightslateblue: '8470ff', + lightslategray: '778899', + lightsteelblue: 'b0c4de', + lightyellow: 'ffffe0', + lime: '00ff00', + limegreen: '32cd32', + linen: 'faf0e6', + magenta: 'ff00ff', + maroon: '800000', + mediumaquamarine: '66cdaa', + mediumblue: '0000cd', + mediumorchid: 'ba55d3', + mediumpurple: '9370d8', + mediumseagreen: '3cb371', + mediumslateblue: '7b68ee', + mediumspringgreen: '00fa9a', + mediumturquoise: '48d1cc', + mediumvioletred: 'c71585', + midnightblue: '191970', + mintcream: 'f5fffa', + mistyrose: 'ffe4e1', + moccasin: 'ffe4b5', + navajowhite: 'ffdead', + navy: '000080', + oldlace: 'fdf5e6', + olive: '808000', + olivedrab: '6b8e23', + orange: 'ffa500', + orangered: 'ff4500', + orchid: 'da70d6', + palegoldenrod: 'eee8aa', + palegreen: '98fb98', + paleturquoise: 'afeeee', + palevioletred: 'd87093', + papayawhip: 'ffefd5', + peachpuff: 'ffdab9', + peru: 'cd853f', + pink: 'ffc0cb', + plum: 'dda0dd', + powderblue: 'b0e0e6', + purple: '800080', + red: 'ff0000', + rosybrown: 'bc8f8f', + royalblue: '4169e1', + saddlebrown: '8b4513', + salmon: 'fa8072', + sandybrown: 'f4a460', + seagreen: '2e8b57', + seashell: 'fff5ee', + sienna: 'a0522d', + silver: 'c0c0c0', + skyblue: '87ceeb', + slateblue: '6a5acd', + slategray: '708090', + snow: 'fffafa', + springgreen: '00ff7f', + steelblue: '4682b4', + tan: 'd2b48c', + teal: '008080', + thistle: 'd8bfd8', + tomato: 'ff6347', + turquoise: '40e0d0', + violet: 'ee82ee', + violetred: 'd02090', + wheat: 'f5deb3', + white: 'ffffff', + whitesmoke: 'f5f5f5', + yellow: 'ffff00', + yellowgreen: '9acd32' + }; + for (var key in simple_colors) { + if (color_string == key) { + color_string = simple_colors[key]; + } + } + // emd of simple type-in colors + + // array of color definition objects + var color_defs = [ + { + re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/, + example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'], + process: function (bits){ + return [ + parseInt(bits[1]), + parseInt(bits[2]), + parseInt(bits[3]) + ]; + } + }, + { + re: /^(\w{2})(\w{2})(\w{2})$/, + example: ['#00ff00', '336699'], + process: function (bits){ + return [ + parseInt(bits[1], 16), + parseInt(bits[2], 16), + parseInt(bits[3], 16) + ]; + } + }, + { + re: /^(\w{1})(\w{1})(\w{1})$/, + example: ['#fb0', 'f0f'], + process: function (bits){ + return [ + parseInt(bits[1] + bits[1], 16), + parseInt(bits[2] + bits[2], 16), + parseInt(bits[3] + bits[3], 16) + ]; + } + } + ]; + + // search through the definitions to find a match + for (var i = 0; i < color_defs.length; i++) { + var re = color_defs[i].re; + var processor = color_defs[i].process; + var bits = re.exec(color_string); + if (bits) { + channels = processor(bits); + this.r = channels[0]; + this.g = channels[1]; + this.b = channels[2]; + this.ok = true; + } + + } + + // validate/cleanup values + this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r); + this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g); + this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b); + + // some getters + this.toRGB = function () { + return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')'; + } + this.toHex = function () { + var r = this.r.toString(16); + var g = this.g.toString(16); + var b = this.b.toString(16); + if (r.length == 1) r = '0' + r; + if (g.length == 1) g = '0' + g; + if (b.length == 1) b = '0' + b; + return '#' + r + g + b; + } + + // help + this.getHelpXML = function () { + + var examples = new Array(); + // add regexps + for (var i = 0; i < color_defs.length; i++) { + var example = color_defs[i].example; + for (var j = 0; j < example.length; j++) { + examples[examples.length] = example[j]; + } + } + // add type-in colors + for (var sc in simple_colors) { + examples[examples.length] = sc; + } + + var xml = document.createElement('ul'); + xml.setAttribute('id', 'rgbcolor-examples'); + for (var i = 0; i < examples.length; i++) { + try { + var list_item = document.createElement('li'); + var list_color = new RGBColor(examples[i]); + var example_div = document.createElement('div'); + example_div.style.cssText = + 'margin: 3px; ' + + 'border: 1px solid black; ' + + 'background:' + list_color.toHex() + '; ' + + 'color:' + list_color.toHex() + ; + example_div.appendChild(document.createTextNode('test')); + var list_item_value = document.createTextNode( + ' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex() + ); + list_item.appendChild(example_div); + list_item.appendChild(list_item_value); + xml.appendChild(list_item); + + } catch(e){} + } + return xml; + + } + +}
\ No newline at end of file diff --git a/hugo/js/canvg/flashcanvas.js b/hugo/js/canvg/flashcanvas.js new file mode 100644 index 0000000..6ecaa94 --- /dev/null +++ b/hugo/js/canvg/flashcanvas.js @@ -0,0 +1,1093 @@ +/* + * FlashCanvas + * + * Copyright (c) 2009 Tim Cameron Ryan + * Copyright (c) 2009-2011 FlashCanvas Project + * Released under the MIT/X License + */ + +// Reference: +// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-element.html +// http://dev.w3.org/html5/spec/the-canvas-element.html + +// If the browser is IE and does not support HTML5 Canvas +if (window["ActiveXObject"] && !window["CanvasRenderingContext2D"]) { + +(function(window, document, undefined) { + +/* + * Constant + */ + +var NULL = null; +var CANVAS = "canvas"; +var CANVAS_RENDERING_CONTEXT_2D = "CanvasRenderingContext2D"; +var CANVAS_GRADIENT = "CanvasGradient"; +var CANVAS_PATTERN = "CanvasPattern"; +var FLASH_CANVAS = "FlashCanvas"; +var G_VML_CANVAS_MANAGER = "G_vmlCanvasManager"; +var OBJECT_ID_PREFIX = "external"; +var ON_FOCUS = "onfocus"; +var ON_PROPERTY_CHANGE = "onpropertychange"; +var ON_READY_STATE_CHANGE = "onreadystatechange"; +var ON_UNLOAD = "onunload"; + +var config = window[FLASH_CANVAS + "Options"] || {}; +var BASE_URL = config["swfPath"] || getScriptUrl().replace(/[^\/]+$/, ""); +var SWF_URL = BASE_URL + "flashcanvas.swf"; + +// DOMException code +var INDEX_SIZE_ERR = 1; +var NOT_SUPPORTED_ERR = 9; +var INVALID_STATE_ERR = 11; +var SYNTAX_ERR = 12; +var TYPE_MISMATCH_ERR = 17; +var SECURITY_ERR = 18; + +/** + * @constructor + */ +function Lookup(array) { + for (var i = 0, n = array.length; i < n; i++) + this[array[i]] = i; +} + +var properties = new Lookup([ + // Canvas element + "toDataURL", + + // CanvasRenderingContext2D + "save", + "restore", + "scale", + "rotate", + "translate", + "transform", + "setTransform", + "globalAlpha", + "globalCompositeOperation", + "strokeStyle", + "fillStyle", + "createLinearGradient", + "createRadialGradient", + "createPattern", + "lineWidth", + "lineCap", + "lineJoin", + "miterLimit", + "shadowOffsetX", + "shadowOffsetY", + "shadowBlur", + "shadowColor", + "clearRect", + "fillRect", + "strokeRect", + "beginPath", + "closePath", + "moveTo", + "lineTo", + "quadraticCurveTo", + "bezierCurveTo", + "arcTo", + "rect", + "arc", + "fill", + "stroke", + "clip", + "isPointInPath", +// "drawFocusRing", + "font", + "textAlign", + "textBaseline", + "fillText", + "strokeText", + "measureText", + "drawImage", + "createImageData", + "getImageData", + "putImageData", + + // CanvasGradient + "addColorStop", + + // Internal use + "direction", + "resize" +]); + +// Whether swf is ready for use +var isReady = {}; + +// Monitor the number of loading files +var lock = {}; + +// Canvas elements +var canvases = {}; + +// SPAN element embedded in the canvas +var spans = {}; + +/** + * 2D context + * @constructor + */ +var CanvasRenderingContext2D = function(canvas, swf) { + // back-reference to the canvas + this.canvas = canvas; + + // back-reference to the swf + this._swf = swf; + + // unique ID of canvas + this._canvasId = swf.id.slice(8); + + // initialize drawing states + this._initialize(); + + // Count CanvasGradient and CanvasPattern objects + this._gradientPatternId = 0; + + // Directionality of the canvas element + this._direction = ""; + + // frame update interval + var self = this; + setInterval(function() { + if (lock[self._canvasId] === 0) { + self._executeCommand(); + } + }, 30); +}; + +CanvasRenderingContext2D.prototype = { + /* + * state + */ + + save: function() { + // write all properties + this._setCompositing(); + this._setShadows(); + this._setStrokeStyle(); + this._setFillStyle(); + this._setLineStyles(); + this._setFontStyles(); + + // push state + this._stateStack.push([ + this._globalAlpha, + this._globalCompositeOperation, + this._strokeStyle, + this._fillStyle, + this._lineWidth, + this._lineCap, + this._lineJoin, + this._miterLimit, + this._shadowOffsetX, + this._shadowOffsetY, + this._shadowBlur, + this._shadowColor, + this._font, + this._textAlign, + this._textBaseline + ]); + + this._queue.push(properties.save); + }, + + restore: function() { + // pop state + var stateStack = this._stateStack; + if (stateStack.length) { + var state = stateStack.pop(); + this.globalAlpha = state[0]; + this.globalCompositeOperation = state[1]; + this.strokeStyle = state[2]; + this.fillStyle = state[3]; + this.lineWidth = state[4]; + this.lineCap = state[5]; + this.lineJoin = state[6]; + this.miterLimit = state[7]; + this.shadowOffsetX = state[8]; + this.shadowOffsetY = state[9]; + this.shadowBlur = state[10]; + this.shadowColor = state[11]; + this.font = state[12]; + this.textAlign = state[13]; + this.textBaseline = state[14]; + } + + this._queue.push(properties.restore); + }, + + /* + * transformations + */ + + scale: function(x, y) { + this._queue.push(properties.scale, x, y); + }, + + rotate: function(angle) { + this._queue.push(properties.rotate, angle); + }, + + translate: function(x, y) { + this._queue.push(properties.translate, x, y); + }, + + transform: function(m11, m12, m21, m22, dx, dy) { + this._queue.push(properties.transform, m11, m12, m21, m22, dx, dy); + }, + + setTransform: function(m11, m12, m21, m22, dx, dy) { + this._queue.push(properties.setTransform, m11, m12, m21, m22, dx, dy); + }, + + /* + * compositing + */ + + _setCompositing: function() { + var queue = this._queue; + if (this._globalAlpha !== this.globalAlpha) { + this._globalAlpha = this.globalAlpha; + queue.push(properties.globalAlpha, this._globalAlpha); + } + if (this._globalCompositeOperation !== this.globalCompositeOperation) { + this._globalCompositeOperation = this.globalCompositeOperation; + queue.push(properties.globalCompositeOperation, this._globalCompositeOperation); + } + }, + + /* + * colors and styles + */ + + _setStrokeStyle: function() { + if (this._strokeStyle !== this.strokeStyle) { + var style = this._strokeStyle = this.strokeStyle; + this._queue.push(properties.strokeStyle, (typeof style === "object") ? style.id : style); + } + }, + + _setFillStyle: function() { + if (this._fillStyle !== this.fillStyle) { + var style = this._fillStyle = this.fillStyle; + this._queue.push(properties.fillStyle, (typeof style === "object") ? style.id : style); + } + }, + + createLinearGradient: function(x0, y0, x1, y1) { + // If any of the arguments are not finite numbers, throws a + // NOT_SUPPORTED_ERR exception. + if (!(isFinite(x0) && isFinite(y0) && isFinite(x1) && isFinite(y1))) { + throwException(NOT_SUPPORTED_ERR); + } + + this._queue.push(properties.createLinearGradient, x0, y0, x1, y1); + return new CanvasGradient(this); + }, + + createRadialGradient: function(x0, y0, r0, x1, y1, r1) { + // If any of the arguments are not finite numbers, throws a + // NOT_SUPPORTED_ERR exception. + if (!(isFinite(x0) && isFinite(y0) && isFinite(r0) && + isFinite(x1) && isFinite(y1) && isFinite(r1))) { + throwException(NOT_SUPPORTED_ERR); + } + + // If either of the radii are negative, throws an INDEX_SIZE_ERR + // exception. + if (r0 < 0 || r1 < 0) { + throwException(INDEX_SIZE_ERR); + } + + this._queue.push(properties.createRadialGradient, x0, y0, r0, x1, y1, r1); + return new CanvasGradient(this); + }, + + createPattern: function(image, repetition) { + // If the image is null, the implementation must raise a + // TYPE_MISMATCH_ERR exception. + if (!image) { + throwException(TYPE_MISMATCH_ERR); + } + + var tagName = image.tagName, src; + var canvasId = this._canvasId; + + // If the first argument isn't an img, canvas, or video element, + // throws a TYPE_MISMATCH_ERR exception. + if (tagName) { + tagName = tagName.toLowerCase(); + if (tagName === "img") { + src = image.getAttribute("src", 2); + } else if (tagName === CANVAS || tagName === "video") { + // For now, only HTMLImageElement is supported. + return; + } else { + throwException(TYPE_MISMATCH_ERR); + } + } + + // Additionally, we accept any object that has a src property. + // This is useful when you'd like to specify a long data URI. + else if (image.src) { + src = image.src; + } else { + throwException(TYPE_MISMATCH_ERR); + } + + // If the second argument isn't one of the allowed values, throws a + // SYNTAX_ERR exception. + if (!(repetition === "repeat" || repetition === "no-repeat" || + repetition === "repeat-x" || repetition === "repeat-y" || + repetition === "" || repetition === NULL)) { + throwException(SYNTAX_ERR); + } + + // Special characters in the filename need escaping. + this._queue.push(properties.createPattern, encodeXML(src), repetition); + + if (isReady[canvasId]) { + this._executeCommand(); + ++lock[canvasId]; + } + + return new CanvasPattern(this); + }, + + /* + * line caps/joins + */ + + _setLineStyles: function() { + var queue = this._queue; + if (this._lineWidth !== this.lineWidth) { + this._lineWidth = this.lineWidth; + queue.push(properties.lineWidth, this._lineWidth); + } + if (this._lineCap !== this.lineCap) { + this._lineCap = this.lineCap; + queue.push(properties.lineCap, this._lineCap); + } + if (this._lineJoin !== this.lineJoin) { + this._lineJoin = this.lineJoin; + queue.push(properties.lineJoin, this._lineJoin); + } + if (this._miterLimit !== this.miterLimit) { + this._miterLimit = this.miterLimit; + queue.push(properties.miterLimit, this._miterLimit); + } + }, + + /* + * shadows + */ + + _setShadows: function() { + var queue = this._queue; + if (this._shadowOffsetX !== this.shadowOffsetX) { + this._shadowOffsetX = this.shadowOffsetX; + queue.push(properties.shadowOffsetX, this._shadowOffsetX); + } + if (this._shadowOffsetY !== this.shadowOffsetY) { + this._shadowOffsetY = this.shadowOffsetY; + queue.push(properties.shadowOffsetY, this._shadowOffsetY); + } + if (this._shadowBlur !== this.shadowBlur) { + this._shadowBlur = this.shadowBlur; + queue.push(properties.shadowBlur, this._shadowBlur); + } + if (this._shadowColor !== this.shadowColor) { + this._shadowColor = this.shadowColor; + queue.push(properties.shadowColor, this._shadowColor); + } + }, + + /* + * rects + */ + + clearRect: function(x, y, w, h) { + this._queue.push(properties.clearRect, x, y, w, h); + }, + + fillRect: function(x, y, w, h) { + this._setCompositing(); + this._setShadows(); + this._setFillStyle(); + this._queue.push(properties.fillRect, x, y, w, h); + }, + + strokeRect: function(x, y, w, h) { + this._setCompositing(); + this._setShadows(); + this._setStrokeStyle(); + this._setLineStyles(); + this._queue.push(properties.strokeRect, x, y, w, h); + }, + + /* + * path API + */ + + beginPath: function() { + this._queue.push(properties.beginPath); + }, + + closePath: function() { + this._queue.push(properties.closePath); + }, + + moveTo: function(x, y) { + this._queue.push(properties.moveTo, x, y); + }, + + lineTo: function(x, y) { + this._queue.push(properties.lineTo, x, y); + }, + + quadraticCurveTo: function(cpx, cpy, x, y) { + this._queue.push(properties.quadraticCurveTo, cpx, cpy, x, y); + }, + + bezierCurveTo: function(cp1x, cp1y, cp2x, cp2y, x, y) { + this._queue.push(properties.bezierCurveTo, cp1x, cp1y, cp2x, cp2y, x, y); + }, + + arcTo: function(x1, y1, x2, y2, radius) { + // Throws an INDEX_SIZE_ERR exception if the given radius is negative. + if (radius < 0 && isFinite(radius)) { + throwException(INDEX_SIZE_ERR); + } + + this._queue.push(properties.arcTo, x1, y1, x2, y2, radius); + }, + + rect: function(x, y, w, h) { + this._queue.push(properties.rect, x, y, w, h); + }, + + arc: function(x, y, radius, startAngle, endAngle, anticlockwise) { + // Throws an INDEX_SIZE_ERR exception if the given radius is negative. + if (radius < 0 && isFinite(radius)) { + throwException(INDEX_SIZE_ERR); + } + + this._queue.push(properties.arc, x, y, radius, startAngle, endAngle, anticlockwise ? 1 : 0); + }, + + fill: function() { + this._setCompositing(); + this._setShadows(); + this._setFillStyle(); + this._queue.push(properties.fill); + }, + + stroke: function() { + this._setCompositing(); + this._setShadows(); + this._setStrokeStyle(); + this._setLineStyles(); + this._queue.push(properties.stroke); + }, + + clip: function() { + this._queue.push(properties.clip); + }, + + isPointInPath: function(x, y) { + // TODO: Implement + }, + + /* + * text + */ + + _setFontStyles: function() { + var queue = this._queue; + if (this._font !== this.font) { + try { + var span = spans[this._canvasId]; + span.style.font = this._font = this.font; + + var style = span.currentStyle; + var fontSize = span.offsetHeight; + var font = [style.fontStyle, style.fontWeight, fontSize, style.fontFamily].join(" "); + queue.push(properties.font, font); + } catch(e) { + // If this.font cannot be parsed as a CSS font value, then it + // must be ignored. + } + } + if (this._textAlign !== this.textAlign) { + this._textAlign = this.textAlign; + queue.push(properties.textAlign, this._textAlign); + } + if (this._textBaseline !== this.textBaseline) { + this._textBaseline = this.textBaseline; + queue.push(properties.textBaseline, this._textBaseline); + } + if (this._direction !== this.canvas.currentStyle.direction) { + this._direction = this.canvas.currentStyle.direction; + queue.push(properties.direction, this._direction); + } + }, + + fillText: function(text, x, y, maxWidth) { + this._setCompositing(); + this._setFillStyle(); + this._setShadows(); + this._setFontStyles(); + this._queue.push(properties.fillText, encodeXML(text), x, y, + maxWidth === undefined ? Infinity : maxWidth); + }, + + strokeText: function(text, x, y, maxWidth) { + this._setCompositing(); + this._setStrokeStyle(); + this._setShadows(); + this._setFontStyles(); + this._queue.push(properties.strokeText, encodeXML(text), x, y, + maxWidth === undefined ? Infinity : maxWidth); + }, + + measureText: function(text) { + var span = spans[this._canvasId]; + try { + span.style.font = this.font; + } catch(e) { + // If this.font cannot be parsed as a CSS font value, then it must + // be ignored. + } + + // Replace space characters with tab characters because innerText + // removes trailing white spaces. + span.innerText = text.replace(/[ \n\f\r]/g, "\t"); + + return new TextMetrics(span.offsetWidth); + }, + + /* + * drawing images + */ + + drawImage: function(image, x1, y1, w1, h1, x2, y2, w2, h2) { + // If the image is null, the implementation must raise a + // TYPE_MISMATCH_ERR exception. + if (!image) { + throwException(TYPE_MISMATCH_ERR); + } + + var tagName = image.tagName, src, argc = arguments.length; + var canvasId = this._canvasId; + + // If the first argument isn't an img, canvas, or video element, + // throws a TYPE_MISMATCH_ERR exception. + if (tagName) { + tagName = tagName.toLowerCase(); + if (tagName === "img") { + src = image.getAttribute("src", 2); + } else if (tagName === CANVAS || tagName === "video") { + // For now, only HTMLImageElement is supported. + return; + } else { + throwException(TYPE_MISMATCH_ERR); + } + } + + // Additionally, we accept any object that has a src property. + // This is useful when you'd like to specify a long data URI. + else if (image.src) { + src = image.src; + } else { + throwException(TYPE_MISMATCH_ERR); + } + + this._setCompositing(); + this._setShadows(); + + // Special characters in the filename need escaping. + src = encodeXML(src); + + if (argc === 3) { + this._queue.push(properties.drawImage, argc, src, x1, y1); + } else if (argc === 5) { + this._queue.push(properties.drawImage, argc, src, x1, y1, w1, h1); + } else if (argc === 9) { + // If one of the sw or sh arguments is zero, the implementation + // must raise an INDEX_SIZE_ERR exception. + if (w1 === 0 || h1 === 0) { + throwException(INDEX_SIZE_ERR); + } + + this._queue.push(properties.drawImage, argc, src, x1, y1, w1, h1, x2, y2, w2, h2); + } else { + return; + } + + if (isReady[canvasId]) { + this._executeCommand(); + ++lock[canvasId]; + } + }, + + /* + * pixel manipulation + */ + + // ImageData createImageData(in float sw, in float sh); + // ImageData createImageData(in ImageData imagedata); + createImageData: function() { + // TODO: Implement + }, + + // ImageData getImageData(in float sx, in float sy, in float sw, in float sh); + getImageData: function(sx, sy, sw, sh) { + // TODO: Implement + }, + + // void putImageData(in ImageData imagedata, in float dx, in float dy, [Optional] in float dirtyX, in float dirtyY, in float dirtyWidth, in float dirtyHeight); + putImageData: function(imagedata, dx, dy, dirtyX, dirtyY, dirtyWidth, dirtyHeight) { + // TODO: Implement + }, + + /* + * private methods + */ + + _initialize: function() { + // compositing + this.globalAlpha = this._globalAlpha = 1.0; + this.globalCompositeOperation = this._globalCompositeOperation = "source-over"; + + // colors and styles + this.strokeStyle = this._strokeStyle = "#000000"; + this.fillStyle = this._fillStyle = "#000000"; + + // line caps/joins + this.lineWidth = this._lineWidth = 1.0; + this.lineCap = this._lineCap = "butt"; + this.lineJoin = this._lineJoin = "miter"; + this.miterLimit = this._miterLimit = 10.0; + + // shadows + this.shadowOffsetX = this._shadowOffsetX = 0; + this.shadowOffsetY = this._shadowOffsetY = 0; + this.shadowBlur = this._shadowBlur = 0; + this.shadowColor = this._shadowColor = "rgba(0, 0, 0, 0.0)"; + + // text + this.font = this._font = "10px sans-serif"; + this.textAlign = this._textAlign = "start"; + this.textBaseline = this._textBaseline = "alphabetic"; + + // command queue + this._queue = []; + + // stack of drawing states + this._stateStack = []; + }, + + _flush: function() { + var queue = this._queue; + this._queue = []; + return queue; + }, + + _executeCommand: function() { + // execute commands + var commands = this._flush(); + if (commands.length > 0) { + return eval(this._swf.CallFunction( + '<invoke name="executeCommand" returntype="javascript"><arguments><string>' + + commands.join("�") + "</string></arguments></invoke>" + )); + } + }, + + _resize: function(width, height) { + // Flush commands in the queue + this._executeCommand(); + + // Clear back to the initial state + this._initialize(); + + // Adjust the size of Flash to that of the canvas + if (width > 0) { + this._swf.width = width; + } + if (height > 0) { + this._swf.height = height; + } + + // Execute a resize command at the start of the next frame + this._queue.push(properties.resize, width, height); + } +}; + +/** + * CanvasGradient stub + * @constructor + */ +var CanvasGradient = function(ctx) { + this._ctx = ctx; + this.id = ctx._gradientPatternId++; +}; + +CanvasGradient.prototype = { + addColorStop: function(offset, color) { + // Throws an INDEX_SIZE_ERR exception if the offset is out of range. + if (isNaN(offset) || offset < 0 || offset > 1) { + throwException(INDEX_SIZE_ERR); + } + + this._ctx._queue.push(properties.addColorStop, this.id, offset, color); + } +}; + +/** + * CanvasPattern stub + * @constructor + */ +var CanvasPattern = function(ctx) { + this.id = ctx._gradientPatternId++; +}; + +/** + * TextMetrics stub + * @constructor + */ +var TextMetrics = function(width) { + this.width = width; +}; + +/** + * DOMException + * @constructor + */ +var DOMException = function(code) { + this.code = code; + this.message = DOMExceptionNames[code]; +}; + +DOMException.prototype = new Error; + +var DOMExceptionNames = { + 1: "INDEX_SIZE_ERR", + 9: "NOT_SUPPORTED_ERR", + 11: "INVALID_STATE_ERR", + 12: "SYNTAX_ERR", + 17: "TYPE_MISMATCH_ERR", + 18: "SECURITY_ERR" +}; + +/* + * Event handlers + */ + +function onReadyStateChange() { + if (document.readyState === "complete") { + document.detachEvent(ON_READY_STATE_CHANGE, onReadyStateChange); + + var canvases = document.getElementsByTagName(CANVAS); + for (var i = 0, n = canvases.length; i < n; ++i) { + FlashCanvas.initElement(canvases[i]); + } + } +} + +function onFocus() { + // forward the event to the parent + var swf = event.srcElement, canvas = swf.parentNode; + swf.blur(); + canvas.focus(); +} + +function onPropertyChange() { + var prop = event.propertyName; + if (prop === "width" || prop === "height") { + var canvas = event.srcElement; + var value = canvas[prop]; + var number = parseInt(value, 10); + + if (isNaN(number) || number < 0) { + number = (prop === "width") ? 300 : 150; + } + + if (value === number) { + canvas.style[prop] = number + "px"; + canvas.getContext("2d")._resize(canvas.width, canvas.height); + } else { + canvas[prop] = number; + } + } +} + +function onUnload() { + window.detachEvent(ON_UNLOAD, onUnload); + + for (var canvasId in canvases) { + var canvas = canvases[canvasId], swf = canvas.firstChild, prop; + + // clean up the references of swf.executeCommand and swf.resize + for (prop in swf) { + if (typeof swf[prop] === "function") { + swf[prop] = NULL; + } + } + + // clean up the references of canvas.getContext and canvas.toDataURL + for (prop in canvas) { + if (typeof canvas[prop] === "function") { + canvas[prop] = NULL; + } + } + + // remove event listeners + swf.detachEvent(ON_FOCUS, onFocus); + canvas.detachEvent(ON_PROPERTY_CHANGE, onPropertyChange); + } + + // delete exported symbols + window[CANVAS_RENDERING_CONTEXT_2D] = NULL; + window[CANVAS_GRADIENT] = NULL; + window[CANVAS_PATTERN] = NULL; + window[FLASH_CANVAS] = NULL; + window[G_VML_CANVAS_MANAGER] = NULL; +} + +/* + * FlashCanvas API + */ + +var FlashCanvas = { + initElement: function(canvas) { + // Check whether the initialization is required or not. + if (canvas.getContext) { + return canvas; + } + + // initialize lock + var canvasId = getUniqueId(); + var objectId = OBJECT_ID_PREFIX + canvasId; + isReady[canvasId] = false; + lock[canvasId] = 1; + + // Set the width and height attributes. + setCanvasSize(canvas); + + // embed swf and SPAN element + canvas.innerHTML = + '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"' + + ' codebase="' + location.protocol + '//fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0"' + + ' width="100%" height="100%" id="' + objectId + '">' + + '<param name="allowScriptAccess" value="always">' + + '<param name="flashvars" value="id=' + objectId + '">' + + '<param name="wmode" value="transparent">' + + '</object>' + + '<span style="margin:0;padding:0;border:0;display:inline-block;position:static;height:1em;overflow:visible;white-space:nowrap">' + + '</span>'; + + canvases[canvasId] = canvas; + var swf = canvas.firstChild; + spans[canvasId] = canvas.lastChild; + + // Check whether the canvas element is in the DOM tree + var documentContains = document.body.contains; + if (documentContains(canvas)) { + // Load swf file immediately + swf["movie"] = SWF_URL; + } else { + // Wait until the element is added to the DOM tree + var intervalId = setInterval(function() { + if (documentContains(canvas)) { + clearInterval(intervalId); + swf["movie"] = SWF_URL; + } + }, 0); + } + + // If the browser is IE6 or in quirks mode + if (document.compatMode === "BackCompat" || !window.XMLHttpRequest) { + spans[canvasId].style.overflow = "hidden"; + } + + // initialize context + var ctx = new CanvasRenderingContext2D(canvas, swf); + + // canvas API + canvas.getContext = function(contextId) { + return contextId === "2d" ? ctx : NULL; + }; + + canvas.toDataURL = function(type, quality) { + if (("" + type).replace(/[A-Z]+/g, toLowerCase) === "image/jpeg") { + ctx._queue.push(properties.toDataURL, type, + typeof quality === "number" ? quality : ""); + } else { + ctx._queue.push(properties.toDataURL, type); + } + return ctx._executeCommand(); + }; + + // add event listener + swf.attachEvent(ON_FOCUS, onFocus); + + return canvas; + }, + + saveImage: function(canvas) { + var swf = canvas.firstChild; + swf.saveImage(); + }, + + setOptions: function(options) { + // TODO: Implement + }, + + trigger: function(canvasId, type) { + var canvas = canvases[canvasId]; + canvas.fireEvent("on" + type); + }, + + unlock: function(canvasId, ready) { + if (lock[canvasId]) { + --lock[canvasId]; + } + if (ready) { + var canvas = canvases[canvasId]; + var swf = canvas.firstChild; + var width; + var height; + + // Set the width and height attributes of the canvas element. + setCanvasSize(canvas); + width = canvas.width; + height = canvas.height; + + canvas.style.width = width + "px"; + canvas.style.height = height + "px"; + + // Adjust the size of Flash to that of the canvas + if (width > 0) { + swf.width = width; + } + if (height > 0) { + swf.height = height; + } + swf.resize(width, height); + + // Add event listener + canvas.attachEvent(ON_PROPERTY_CHANGE, onPropertyChange); + + // ExternalInterface is now ready for use + isReady[canvasId] = true; + } + } +}; + +/* + * Utility methods + */ + +// Get the absolute URL of flashcanvas.js +function getScriptUrl() { + var scripts = document.getElementsByTagName("script"); + var script = scripts[scripts.length - 1]; + + // @see http://msdn.microsoft.com/en-us/library/ms536429(VS.85).aspx + if (document.documentMode >= 8) { + return script.src; + } else { + return script.getAttribute("src", 4); + } +} + +// Get a unique ID composed of alphanumeric characters. +function getUniqueId() { + return Math.random().toString(36).slice(2) || "0"; +} + +// Escape characters not permitted in XML. +function encodeXML(str) { + return ("" + str).replace(/&/g, "&").replace(/</g, "<"); +} + +function toLowerCase(str) { + return str.toLowerCase(); +} + +function throwException(code) { + throw new DOMException(code); +} + +// The width and height attributes of a canvas element must have values that +// are valid non-negative integers. +function setCanvasSize(canvas) { + var width = parseInt(canvas.width, 10); + var height = parseInt(canvas.height, 10); + + if (isNaN(width) || width < 0) { + width = 300; + } + if (isNaN(height) || height < 0) { + height = 150; + } + + canvas.width = width; + canvas.height = height; +} + +/* + * initialization + */ + +// IE HTML5 shiv +document.createElement(CANVAS); + +// setup default CSS +document.createStyleSheet().cssText = + CANVAS + "{display:inline-block;overflow:hidden;width:300px;height:150px}"; + +// initialize canvas elements +if (document.readyState === "complete") { + onReadyStateChange(); +} else { + document.attachEvent(ON_READY_STATE_CHANGE, onReadyStateChange); +} + +// prevent IE6 memory leaks +window.attachEvent(ON_UNLOAD, onUnload); + +// preload SWF file if it's in the same domain +if (SWF_URL.indexOf(location.protocol + "//" + location.host + "/") === 0) { + var req = new ActiveXObject("Microsoft.XMLHTTP"); + req.open("GET", SWF_URL, false); + req.send(NULL); +} + +/* + * public API + */ + +window[CANVAS_RENDERING_CONTEXT_2D] = CanvasRenderingContext2D; +window[CANVAS_GRADIENT] = CanvasGradient; +window[CANVAS_PATTERN] = CanvasPattern; +window[FLASH_CANVAS] = FlashCanvas; + +// ExplorerCanvas-compatible APIs for convenience +window[G_VML_CANVAS_MANAGER] = { + init: function(){}, + init_: function(){}, + initElement: FlashCanvas.initElement +}; + +// Prevent Closure Compiler from removing the function. +keep = CanvasRenderingContext2D.measureText; + +})(window, document); + +} diff --git a/hugo/js/canvg/flashcanvas.swf b/hugo/js/canvg/flashcanvas.swf Binary files differnew file mode 100644 index 0000000..66ff213 --- /dev/null +++ b/hugo/js/canvg/flashcanvas.swf diff --git a/hugo/js/chart.js b/hugo/js/chart.js new file mode 100644 index 0000000..6cc7970 --- /dev/null +++ b/hugo/js/chart.js @@ -0,0 +1,541 @@ +/** + * Chart type enumerations + */ +var ChartType = { + LINE : 'line', + SPLINE : 'spline', + AREA : 'area', + BAR : 'bar', + COLUMN : 'column', + PIE : 'pie', + TIMELINE: 'timeline' +}; + +/** + * Abstract chart factory which defines the contract for chart factories + */ +var ChartFactory = function() { +}; +ChartFactory.prototype = { + createChart : function(type, options) { + throw new Error("createChart must be implemented by a subclass"); + } +}; + +/** + * Abstract chart which defines the contract for charts + * + * @param elementId + * id of the div element the chart is drawn in + */ +var Chart = function(elementId) { + this.elementId = elementId; +}; +Chart.prototype = { + draw : function(data, options) { + throw new Error("draw must be implemented by a subclass"); + }, + redraw : function(options) { + throw new Error("redraw must be implemented by a subclass"); + }, + destroy : function() { + throw new Error("destroy must be implemented by a subclass"); + } +}; + +/** + * Abstract representation of charts that operates on DataTable where,<br /> + * <ul> + * <li>First column provides index to the data.</li> + * <li>Each subsequent columns are of type + * <code>ColumnType.NUMBER<code> and represents a data series.</li> + * </ul> + * Line chart, area chart, bar chart, column chart are typical examples. + * + * @param elementId + * id of the div element the chart is drawn in + */ +var BaseChart = function(elementId) { + Chart.call(this, elementId); +}; +BaseChart.prototype = new Chart(); +BaseChart.prototype.constructor = BaseChart; +BaseChart.prototype.validateColumns = function(dataTable) { + var columns = dataTable.getColumns(); + if (columns.length < 2) { + throw new Error("Minimum of two columns are required for this chart"); + } + for ( var i = 1; i < columns.length; i++) { + if (columns[i].type != ColumnType.NUMBER) { + throw new Error("Column " + (i + 1) + " should be of type 'Number'"); + } + } + return true; +}; + +/** + * Abstract pie chart + * + * @param elementId + * id of the div element the chart is drawn in + */ +var PieChart = function(elementId) { + BaseChart.call(this, elementId); +}; +PieChart.prototype = new BaseChart(); +PieChart.prototype.constructor = PieChart; +PieChart.prototype.validateColumns = function(dataTable) { + var columns = dataTable.getColumns(); + if (columns.length > 2) { + throw new Error("Pie charts can draw only one series"); + } + return BaseChart.prototype.validateColumns.call(this, dataTable); +}; + +/** + * Abstract timeline chart + * + * @param elementId + * id of the div element the chart is drawn in + */ +var TimelineChart = function(elementId) { + BaseChart.call(this, elementId); +}; +TimelineChart.prototype = new BaseChart(); +TimelineChart.prototype.constructor = TimelineChart; +TimelineChart.prototype.validateColumns = function(dataTable) { + var result = BaseChart.prototype.validateColumns.call(this, dataTable); + if (result) { + var columns = dataTable.getColumns(); + if (columns[0].type != ColumnType.DATE) { + throw new Error("First column of timeline chart need to be a date column"); + } + } + return result; +}; + +/** + * The data table contains column information and data for the chart. + */ +var DataTable = function() { + var columns = []; + var data; + + this.addColumn = function(type, name) { + columns.push({ + 'type' : type, + 'name' : name + }); + }; + + this.getColumns = function() { + return columns; + }; + + this.setData = function(rows) { + data = rows; + fillMissingValues(); + }; + + this.getData = function() { + return data; + }; + + var fillMissingValues = function() { + if (columns.length == 0) { + throw new Error("Set columns first"); + } + var row, column; + for ( var i = 0; i < data.length; i++) { + row = data[i]; + if (row.length > columns.length) { + row.splice(columns.length - 1, row.length - columns.length); + } else if (row.length < columns.length) { + for ( var j = row.length; j < columns.length; j++) { + row.push(null); + } + } + } + }; +}; + +/** + * Column type enumeration + */ +var ColumnType = { + STRING : 'string', + NUMBER : 'number', + BOOLEAN : 'boolean', + DATE : 'date' +}; + +/******************************************************************************* + * JQPlot specifc code + ******************************************************************************/ + +/** + * Chart factory that returns JQPlotCharts + */ +var JQPlotChartFactory = function() { +}; +JQPlotChartFactory.prototype = new ChartFactory(); +JQPlotChartFactory.prototype.createChart = function(type, elementId) { + var chart; + switch (type) { + case ChartType.LINE: + chart = new JQPlotLineChart(elementId); + break; + case ChartType.SPLINE: + chart = new JQPlotSplineChart(elementId); + break; + case ChartType.TIMELINE: + chart = new JQPlotTimelineChart(elementId); + break; + case ChartType.AREA: + chart = new JQPlotAreaChart(elementId); + break; + case ChartType.BAR: + chart = new JQPlotBarChart(elementId); + break; + case ChartType.COLUMN: + chart = new JQPlotColumnChart(elementId); + break; + case ChartType.PIE: + chart = new JQPlotPieChart(elementId); + break; + } + + return chart; +}; + +/** + * Abstract JQplot chart + * + * @param elementId + * id of the div element the chart is drawn in + */ +var JQPlotChart = function(elementId) { + Chart.call(this, elementId); + this.plot; + this.validator; +}; +JQPlotChart.prototype = new Chart(); +JQPlotChart.prototype.constructor = JQPlotChart; +JQPlotChart.prototype.draw = function(data, options) { + if (this.validator.validateColumns(data)) { + this.plot = $.jqplot(this.elementId, this.prepareData(data), this + .populateOptions(data, options)); + } +}; +JQPlotChart.prototype.destroy = function() { + if (this.plot != null) { + this.plot.destroy(); + } +}; +JQPlotChart.prototype.redraw = function(options) { + if (this.plot != null) { + this.plot.replot(options); + } +}; +JQPlotChart.prototype.populateOptions = function(dataTable, options) { + throw new Error("populateOptions must be implemented by a subclass"); +}; +JQPlotChart.prototype.prepareData = function(dataTable) { + throw new Error("prepareData must be implemented by a subclass"); +}; + +/** + * JQPlot line chart + * + * @param elementId + * id of the div element the chart is drawn in + */ +var JQPlotLineChart = function(elementId) { + JQPlotChart.call(this, elementId); + this.validator = BaseChart.prototype; +}; +JQPlotLineChart.prototype = new JQPlotChart(); +JQPlotLineChart.prototype.constructor = JQPlotLineChart; + +JQPlotLineChart.prototype.populateOptions = function(dataTable, options) { + var columns = dataTable.getColumns(); + var optional = { + axes : { + xaxis : { + label : columns[0].name, + renderer : $.jqplot.CategoryAxisRenderer, + ticks : [] + }, + yaxis : { + label : (columns.length == 2 ? columns[1].name : 'Values'), + labelRenderer : $.jqplot.CanvasAxisLabelRenderer + } + }, + series : [] + }; + $.extend(true, optional, options); + + if (optional.series.length == 0) { + for ( var i = 1; i < columns.length; i++) { + optional.series.push({ + label : columns[i].name.toString() + }); + } + } + if (optional.axes.xaxis.ticks.length == 0) { + var data = dataTable.getData(); + for ( var i = 0; i < data.length; i++) { + optional.axes.xaxis.ticks.push(data[i][0].toString()); + } + } + return optional; +}; + +JQPlotLineChart.prototype.prepareData = function(dataTable) { + var data = dataTable.getData(), row; + var retData = [], retRow; + for ( var i = 0; i < data.length; i++) { + row = data[i]; + for ( var j = 1; j < row.length; j++) { + retRow = retData[j - 1]; + if (retRow == null) { + retRow = []; + retData[j - 1] = retRow; + } + retRow.push(row[j]); + } + } + return retData; +}; + +/** + * JQPlot spline chart + * + * @param elementId + * id of the div element the chart is drawn in + */ +var JQPlotSplineChart = function(elementId) { + JQPlotLineChart.call(this, elementId); +}; +JQPlotSplineChart.prototype = new JQPlotLineChart(); +JQPlotSplineChart.prototype.constructor = JQPlotSplineChart; + +JQPlotSplineChart.prototype.populateOptions = function(dataTable, options) { + var optional = {}; + var opt = JQPlotLineChart.prototype.populateOptions.call(this, dataTable, + options); + var compulsory = { + seriesDefaults : { + rendererOptions : { + smooth : true + } + } + }; + $.extend(true, optional, opt, compulsory); + return optional; +}; + +/** + * JQPlot timeline chart + * + * @param elementId + * id of the div element the chart is drawn in + */ +var JQPlotTimelineChart = function(elementId) { + JQPlotLineChart.call(this, elementId); + this.validator = TimelineChart.prototype; +}; +JQPlotTimelineChart.prototype = new JQPlotLineChart(); +JQPlotTimelineChart.prototype.constructor = JQPlotAreaChart; + +JQPlotTimelineChart.prototype.populateOptions = function(dataTable, options) { + var optional = { + axes : { + xaxis : { + tickOptions : { + formatString:'%b %#d, %y' + } + } + } + }; + var opt = JQPlotLineChart.prototype.populateOptions.call(this, dataTable, options); + var compulsory = { + axes : { + xaxis : { + renderer : $.jqplot.DateAxisRenderer + } + } + }; + $.extend(true, optional, opt, compulsory); + return optional; +}; + +JQPlotTimelineChart.prototype.prepareData = function(dataTable) { + var data = dataTable.getData(), row, d; + var retData = [], retRow; + for ( var i = 0; i < data.length; i++) { + row = data[i]; + d = row[0]; + for ( var j = 1; j < row.length; j++) { + retRow = retData[j - 1]; + if (retRow == null) { + retRow = []; + retData[j - 1] = retRow; + } + if (d != null) { + retRow.push([d.getTime(), row[j]]); + } + } + } + return retData; +}; + +/** + * JQPlot area chart + * + * @param elementId + * id of the div element the chart is drawn in + */ +var JQPlotAreaChart = function(elementId) { + JQPlotLineChart.call(this, elementId); +}; +JQPlotAreaChart.prototype = new JQPlotLineChart(); +JQPlotAreaChart.prototype.constructor = JQPlotAreaChart; + +JQPlotAreaChart.prototype.populateOptions = function(dataTable, options) { + var optional = { + seriesDefaults : { + fillToZero : true + } + }; + var opt = JQPlotLineChart.prototype.populateOptions.call(this, dataTable, + options); + var compulsory = { + seriesDefaults : { + fill : true + } + }; + $.extend(true, optional, opt, compulsory); + return optional; +}; + +/** + * JQPlot column chart + * + * @param elementId + * id of the div element the chart is drawn in + */ +var JQPlotColumnChart = function(elementId) { + JQPlotLineChart.call(this, elementId); +}; +JQPlotColumnChart.prototype = new JQPlotLineChart(); +JQPlotColumnChart.prototype.constructor = JQPlotColumnChart; + +JQPlotColumnChart.prototype.populateOptions = function(dataTable, options) { + var optional = { + seriesDefaults : { + fillToZero : true + } + }; + var opt = JQPlotLineChart.prototype.populateOptions.call(this, dataTable, + options); + var compulsory = { + seriesDefaults : { + renderer : $.jqplot.BarRenderer + } + }; + $.extend(true, optional, opt, compulsory); + return optional; +}; + +/** + * JQPlot bar chart + * + * @param elementId + * id of the div element the chart is drawn in + */ +var JQPlotBarChart = function(elementId) { + JQPlotLineChart.call(this, elementId); +}; +JQPlotBarChart.prototype = new JQPlotLineChart(); +JQPlotBarChart.prototype.constructor = JQPlotBarChart; + +JQPlotBarChart.prototype.populateOptions = function(dataTable, options) { + var columns = dataTable.getColumns(); + var optional = { + axes : { + yaxis : { + label : columns[0].name, + labelRenderer : $.jqplot.CanvasAxisLabelRenderer, + renderer : $.jqplot.CategoryAxisRenderer, + ticks : [] + }, + xaxis : { + label : (columns.length == 2 ? columns[1].name : 'Values'), + labelRenderer : $.jqplot.CanvasAxisLabelRenderer + } + }, + series : [], + seriesDefaults : { + fillToZero : true + } + }; + var compulsory = { + seriesDefaults : { + renderer : $.jqplot.BarRenderer, + rendererOptions : { + barDirection : 'horizontal' + } + } + }; + $.extend(true, optional, options, compulsory); + + if (optional.axes.yaxis.ticks.length == 0) { + var data = dataTable.getData(); + for ( var i = 0; i < data.length; i++) { + optional.axes.yaxis.ticks.push(data[i][0].toString()); + } + } + if (optional.series.length == 0) { + for ( var i = 1; i < columns.length; i++) { + optional.series.push({ + label : columns[i].name.toString() + }); + } + } + return optional; +}; + +/** + * JQPlot pie chart + * + * @param elementId + * id of the div element the chart is drawn in + */ +var JQPlotPieChart = function(elementId) { + JQPlotChart.call(this, elementId); + this.validator = PieChart.prototype; +}; +JQPlotPieChart.prototype = new JQPlotChart(); +JQPlotPieChart.prototype.constructor = JQPlotPieChart; + +JQPlotPieChart.prototype.populateOptions = function(dataTable, options) { + var optional = {}; + var compulsory = { + seriesDefaults : { + renderer : $.jqplot.PieRenderer + } + }; + $.extend(true, optional, options, compulsory); + return optional; +}; + +JQPlotPieChart.prototype.prepareData = function(dataTable) { + var data = dataTable.getData(), row; + var retData = []; + for ( var i = 0; i < data.length; i++) { + row = data[i]; + retData.push([ row[0], row[1] ]); + } + return [ retData ]; +}; diff --git a/hugo/js/codemirror/LICENSE b/hugo/js/codemirror/LICENSE new file mode 100644 index 0000000..3f7c0bb --- /dev/null +++ b/hugo/js/codemirror/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2011 by Marijn Haverbeke <marijnh@gmail.com> + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/hugo/js/codemirror/lib/codemirror.js b/hugo/js/codemirror/lib/codemirror.js new file mode 100644 index 0000000..15788ff --- /dev/null +++ b/hugo/js/codemirror/lib/codemirror.js @@ -0,0 +1,3192 @@ +// CodeMirror version 2.38 +// +// All functions that need access to the editor's state live inside +// the CodeMirror function. Below that, at the bottom of the file, +// some utilities are defined. + +// CodeMirror is the only global var we claim +window.CodeMirror = (function() { + "use strict"; + // This is the function that produces an editor instance. Its + // closure is used to store the editor state. + function CodeMirror(place, givenOptions) { + // Determine effective options based on given values and defaults. + var options = {}, defaults = CodeMirror.defaults; + for (var opt in defaults) + if (defaults.hasOwnProperty(opt)) + options[opt] = (givenOptions && givenOptions.hasOwnProperty(opt) ? givenOptions : defaults)[opt]; + + var input = elt("textarea", null, null, "position: absolute; padding: 0; width: 1px; height: 1em"); + input.setAttribute("wrap", "off"); input.setAttribute("autocorrect", "off"); input.setAttribute("autocapitalize", "off"); + // Wraps and hides input textarea + var inputDiv = elt("div", [input], null, "overflow: hidden; position: relative; width: 3px; height: 0px;"); + // The empty scrollbar content, used solely for managing the scrollbar thumb. + var scrollbarInner = elt("div", null, "CodeMirror-scrollbar-inner"); + // The vertical scrollbar. Horizontal scrolling is handled by the scroller itself. + var scrollbar = elt("div", [scrollbarInner], "CodeMirror-scrollbar"); + // DIVs containing the selection and the actual code + var lineDiv = elt("div"), selectionDiv = elt("div", null, null, "position: relative; z-index: -1"); + // Blinky cursor, and element used to ensure cursor fits at the end of a line + var cursor = elt("pre", "\u00a0", "CodeMirror-cursor"), widthForcer = elt("pre", "\u00a0", "CodeMirror-cursor", "visibility: hidden"); + // Used to measure text size + var measure = elt("div", null, null, "position: absolute; width: 100%; height: 0px; overflow: hidden; visibility: hidden;"); + var lineSpace = elt("div", [measure, cursor, widthForcer, selectionDiv, lineDiv], null, "position: relative; z-index: 0"); + var gutterText = elt("div", null, "CodeMirror-gutter-text"), gutter = elt("div", [gutterText], "CodeMirror-gutter"); + // Moved around its parent to cover visible view + var mover = elt("div", [gutter, elt("div", [lineSpace], "CodeMirror-lines")], null, "position: relative"); + // Set to the height of the text, causes scrolling + var sizer = elt("div", [mover], null, "position: relative"); + // Provides scrolling + var scroller = elt("div", [sizer], "CodeMirror-scroll"); + scroller.setAttribute("tabIndex", "-1"); + // The element in which the editor lives. + var wrapper = elt("div", [inputDiv, scrollbar, scroller], "CodeMirror" + (options.lineWrapping ? " CodeMirror-wrap" : "")); + if (place.appendChild) place.appendChild(wrapper); else place(wrapper); + + themeChanged(); keyMapChanged(); + // Needed to hide big blue blinking cursor on Mobile Safari + if (ios) input.style.width = "0px"; + if (!webkit) scroller.draggable = true; + lineSpace.style.outline = "none"; + if (options.tabindex != null) input.tabIndex = options.tabindex; + if (options.autofocus) focusInput(); + if (!options.gutter && !options.lineNumbers) gutter.style.display = "none"; + // Needed to handle Tab key in KHTML + if (khtml) inputDiv.style.height = "1px", inputDiv.style.position = "absolute"; + + // Check for OS X >= 10.7. This has transparent scrollbars, so the + // overlaying of one scrollbar with another won't work. This is a + // temporary hack to simply turn off the overlay scrollbar. See + // issue #727. + if (mac_geLion) { scrollbar.style.zIndex = -2; scrollbar.style.visibility = "hidden"; } + // Need to set a minimum width to see the scrollbar on IE7 (but must not set it on IE8). + else if (ie_lt8) scrollbar.style.minWidth = "18px"; + + // Delayed object wrap timeouts, making sure only one is active. blinker holds an interval. + var poll = new Delayed(), highlight = new Delayed(), blinker; + + // mode holds a mode API object. doc is the tree of Line objects, + // frontier is the point up to which the content has been parsed, + // and history the undo history (instance of History constructor). + var mode, doc = new BranchChunk([new LeafChunk([new Line("")])]), frontier = 0, focused; + loadMode(); + // The selection. These are always maintained to point at valid + // positions. Inverted is used to remember that the user is + // selecting bottom-to-top. + var sel = {from: {line: 0, ch: 0}, to: {line: 0, ch: 0}, inverted: false}; + // Selection-related flags. shiftSelecting obviously tracks + // whether the user is holding shift. + var shiftSelecting, lastClick, lastDoubleClick, lastScrollTop = 0, draggingText, + overwrite = false, suppressEdits = false, pasteIncoming = false; + // Variables used by startOperation/endOperation to track what + // happened during the operation. + var updateInput, userSelChange, changes, textChanged, selectionChanged, + gutterDirty, callbacks; + // Current visible range (may be bigger than the view window). + var displayOffset = 0, showingFrom = 0, showingTo = 0, lastSizeC = 0; + // bracketHighlighted is used to remember that a bracket has been + // marked. + var bracketHighlighted; + // Tracks the maximum line length so that the horizontal scrollbar + // can be kept static when scrolling. + var maxLine = getLine(0), updateMaxLine = false, maxLineChanged = true; + var pollingFast = false; // Ensures slowPoll doesn't cancel fastPoll + var goalColumn = null; + + // Initialize the content. + operation(function(){setValue(options.value || ""); updateInput = false;})(); + var history = new History(); + + // Register our event handlers. + connect(scroller, "mousedown", operation(onMouseDown)); + connect(scroller, "dblclick", operation(onDoubleClick)); + connect(lineSpace, "selectstart", e_preventDefault); + // Gecko browsers fire contextmenu *after* opening the menu, at + // which point we can't mess with it anymore. Context menu is + // handled in onMouseDown for Gecko. + if (!gecko) connect(scroller, "contextmenu", onContextMenu); + connect(scroller, "scroll", onScrollMain); + connect(scrollbar, "scroll", onScrollBar); + connect(scrollbar, "mousedown", function() {if (focused) setTimeout(focusInput, 0);}); + var resizeHandler = connect(window, "resize", function() { + if (wrapper.parentNode) updateDisplay(true); + else resizeHandler(); + }, true); + connect(input, "keyup", operation(onKeyUp)); + connect(input, "input", fastPoll); + connect(input, "keydown", operation(onKeyDown)); + connect(input, "keypress", operation(onKeyPress)); + connect(input, "focus", onFocus); + connect(input, "blur", onBlur); + + function drag_(e) { + if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return; + e_stop(e); + } + if (options.dragDrop) { + connect(scroller, "dragstart", onDragStart); + connect(scroller, "dragenter", drag_); + connect(scroller, "dragover", drag_); + connect(scroller, "drop", operation(onDrop)); + } + connect(scroller, "paste", function(){focusInput(); fastPoll();}); + connect(input, "paste", function(){pasteIncoming = true; fastPoll();}); + connect(input, "cut", operation(function(){ + if (!options.readOnly) replaceSelection(""); + })); + + // Needed to handle Tab key in KHTML + if (khtml) connect(sizer, "mouseup", function() { + if (document.activeElement == input) input.blur(); + focusInput(); + }); + + // IE throws unspecified error in certain cases, when + // trying to access activeElement before onload + var hasFocus; try { hasFocus = (document.activeElement == input); } catch(e) { } + if (hasFocus || options.autofocus) setTimeout(onFocus, 20); + else onBlur(); + + function isLine(l) {return l >= 0 && l < doc.size;} + // The instance object that we'll return. Mostly calls out to + // local functions in the CodeMirror function. Some do some extra + // range checking and/or clipping. operation is used to wrap the + // call so that changes it makes are tracked, and the display is + // updated afterwards. + var instance = wrapper.CodeMirror = { + getValue: getValue, + setValue: operation(setValue), + getSelection: getSelection, + replaceSelection: operation(replaceSelection), + focus: function(){window.focus(); focusInput(); onFocus(); fastPoll();}, + setOption: function(option, value) { + var oldVal = options[option]; + options[option] = value; + if (option == "mode" || option == "indentUnit") loadMode(); + else if (option == "readOnly" && value == "nocursor") {onBlur(); input.blur();} + else if (option == "readOnly" && !value) {resetInput(true);} + else if (option == "theme") themeChanged(); + else if (option == "lineWrapping" && oldVal != value) operation(wrappingChanged)(); + else if (option == "tabSize") updateDisplay(true); + else if (option == "keyMap") keyMapChanged(); + else if (option == "tabindex") input.tabIndex = value; + else if (option == "showCursorWhenSelecting") updateSelection(); + if (option == "lineNumbers" || option == "gutter" || option == "firstLineNumber" || + option == "theme" || option == "lineNumberFormatter") { + gutterChanged(); + updateDisplay(true); + } + }, + getOption: function(option) {return options[option];}, + getMode: function() {return mode;}, + undo: operation(undo), + redo: operation(redo), + indentLine: operation(function(n, dir) { + if (typeof dir != "string") { + if (dir == null) dir = options.smartIndent ? "smart" : "prev"; + else dir = dir ? "add" : "subtract"; + } + if (isLine(n)) indentLine(n, dir); + }), + indentSelection: operation(indentSelected), + historySize: function() {return {undo: history.done.length, redo: history.undone.length};}, + clearHistory: function() {history = new History();}, + setHistory: function(histData) { + history = new History(); + history.done = histData.done; + history.undone = histData.undone; + }, + getHistory: function() { + function cp(arr) { + for (var i = 0, nw = [], nwelt; i < arr.length; ++i) { + nw.push(nwelt = []); + for (var j = 0, elt = arr[i]; j < elt.length; ++j) { + var old = [], cur = elt[j]; + nwelt.push({start: cur.start, added: cur.added, old: old}); + for (var k = 0; k < cur.old.length; ++k) old.push(hlText(cur.old[k])); + } + } + return nw; + } + return {done: cp(history.done), undone: cp(history.undone)}; + }, + matchBrackets: operation(function(){matchBrackets(true);}), + getTokenAt: operation(function(pos) { + pos = clipPos(pos); + return getLine(pos.line).getTokenAt(mode, getStateBefore(pos.line), options.tabSize, pos.ch); + }), + getStateAfter: function(line) { + line = clipLine(line == null ? doc.size - 1: line); + return getStateBefore(line + 1); + }, + cursorCoords: function(start, mode) { + if (start == null) start = sel.inverted; + return this.charCoords(start ? sel.from : sel.to, mode); + }, + charCoords: function(pos, mode) { + pos = clipPos(pos); + if (mode == "local") return localCoords(pos, false); + if (mode == "div") return localCoords(pos, true); + return pageCoords(pos); + }, + coordsChar: function(coords) { + var off = eltOffset(lineSpace); + return coordsChar(coords.x - off.left, coords.y - off.top); + }, + defaultTextHeight: function() { return textHeight(); }, + markText: operation(markText), + setBookmark: setBookmark, + findMarksAt: findMarksAt, + setMarker: operation(addGutterMarker), + clearMarker: operation(removeGutterMarker), + setLineClass: operation(setLineClass), + hideLine: operation(function(h) {return setLineHidden(h, true);}), + showLine: operation(function(h) {return setLineHidden(h, false);}), + onDeleteLine: function(line, f) { + if (typeof line == "number") { + if (!isLine(line)) return null; + line = getLine(line); + } + (line.handlers || (line.handlers = [])).push(f); + return line; + }, + lineInfo: lineInfo, + getViewport: function() { return {from: showingFrom, to: showingTo};}, + addWidget: function(pos, node, scroll, vert, horiz) { + pos = localCoords(clipPos(pos)); + var top = pos.yBot, left = pos.x; + node.style.position = "absolute"; + sizer.appendChild(node); + if (vert == "over") top = pos.y; + else if (vert == "near") { + var vspace = Math.max(scroller.offsetHeight, doc.height * textHeight()), + hspace = Math.max(sizer.clientWidth, lineSpace.clientWidth) - paddingLeft(); + if (pos.yBot + node.offsetHeight > vspace && pos.y > node.offsetHeight) + top = pos.y - node.offsetHeight; + if (left + node.offsetWidth > hspace) + left = hspace - node.offsetWidth; + } + node.style.top = (top + paddingTop()) + "px"; + node.style.left = node.style.right = ""; + if (horiz == "right") { + left = sizer.clientWidth - node.offsetWidth; + node.style.right = "0px"; + } else { + if (horiz == "left") left = 0; + else if (horiz == "middle") left = (sizer.clientWidth - node.offsetWidth) / 2; + node.style.left = (left + paddingLeft()) + "px"; + } + if (scroll) + scrollIntoView(left, top, left + node.offsetWidth, top + node.offsetHeight); + }, + + lineCount: function() {return doc.size;}, + clipPos: clipPos, + getCursor: function(start) { + if (start == null || start == "head") start = sel.inverted; + if (start == "anchor") start = !sel.inverted; + if (start == "end") start = false; + return copyPos(start ? sel.from : sel.to); + }, + somethingSelected: function() {return !posEq(sel.from, sel.to);}, + setCursor: operation(function(line, ch, user) { + if (ch == null && typeof line.line == "number") setCursor(line.line, line.ch, user); + else setCursor(line, ch, user); + }), + setSelection: operation(function(from, to, user) { + (user ? setSelectionUser : setSelection)(clipPos(from), clipPos(to || from)); + }), + getLine: function(line) {if (isLine(line)) return getLine(line).text;}, + getLineHandle: function(line) {if (isLine(line)) return getLine(line);}, + setLine: operation(function(line, text) { + if (isLine(line)) replaceRange(text, {line: line, ch: 0}, {line: line, ch: getLine(line).text.length}); + }), + removeLine: operation(function(line) { + if (isLine(line)) replaceRange("", {line: line, ch: 0}, clipPos({line: line+1, ch: 0})); + }), + replaceRange: operation(replaceRange), + getRange: function(from, to, lineSep) {return getRange(clipPos(from), clipPos(to), lineSep);}, + + triggerOnKeyDown: operation(onKeyDown), + execCommand: function(cmd) {return commands[cmd](instance);}, + // Stuff used by commands, probably not much use to outside code. + moveH: operation(moveH), + deleteH: operation(deleteH), + moveV: operation(moveV), + toggleOverwrite: function() { + if(overwrite){ + overwrite = false; + cursor.className = cursor.className.replace(" CodeMirror-overwrite", ""); + } else { + overwrite = true; + cursor.className += " CodeMirror-overwrite"; + } + }, + + posFromIndex: function(off) { + var lineNo = 0, ch; + doc.iter(0, doc.size, function(line) { + var sz = line.text.length + 1; + if (sz > off) { ch = off; return true; } + off -= sz; + ++lineNo; + }); + return clipPos({line: lineNo, ch: ch}); + }, + indexFromPos: function (coords) { + if (coords.line < 0 || coords.ch < 0) return 0; + var index = coords.ch; + doc.iter(0, coords.line, function (line) { + index += line.text.length + 1; + }); + return index; + }, + scrollTo: function(x, y) { + if (x != null) scroller.scrollLeft = x; + if (y != null) scrollbar.scrollTop = scroller.scrollTop = y; + updateDisplay([]); + }, + getScrollInfo: function() { + return {x: scroller.scrollLeft, y: scrollbar.scrollTop, + height: scrollbar.scrollHeight, width: scroller.scrollWidth}; + }, + scrollIntoView: function(pos) { + var coords = localCoords(pos ? clipPos(pos) : sel.inverted ? sel.from : sel.to); + scrollIntoView(coords.x, coords.y, coords.x, coords.yBot); + }, + + setSize: function(width, height) { + function interpret(val) { + val = String(val); + return /^\d+$/.test(val) ? val + "px" : val; + } + if (width != null) wrapper.style.width = interpret(width); + if (height != null) scroller.style.height = interpret(height); + instance.refresh(); + }, + + operation: function(f){return operation(f)();}, + compoundChange: function(f){return compoundChange(f);}, + refresh: function(){ + updateDisplay(true, null, lastScrollTop); + if (scrollbar.scrollHeight > lastScrollTop) + scrollbar.scrollTop = lastScrollTop; + }, + getInputField: function(){return input;}, + getWrapperElement: function(){return wrapper;}, + getScrollerElement: function(){return scroller;}, + getGutterElement: function(){return gutter;} + }; + + function getLine(n) { return getLineAt(doc, n); } + function updateLineHeight(line, height) { + gutterDirty = true; + var diff = height - line.height; + for (var n = line; n; n = n.parent) n.height += diff; + } + + function lineContent(line, wrapAt) { + if (!line.styles) + line.highlight(mode, line.stateAfter = getStateBefore(lineNo(line)), options.tabSize); + return line.getContent(options.tabSize, wrapAt, options.lineWrapping); + } + + function setValue(code) { + var top = {line: 0, ch: 0}; + updateLines(top, {line: doc.size - 1, ch: getLine(doc.size-1).text.length}, + splitLines(code), top, top); + updateInput = true; + } + function getValue(lineSep) { + var text = []; + doc.iter(0, doc.size, function(line) { text.push(line.text); }); + return text.join(lineSep || "\n"); + } + + function onScrollBar(e) { + if (Math.abs(scrollbar.scrollTop - lastScrollTop) > 1) { + lastScrollTop = scroller.scrollTop = scrollbar.scrollTop; + updateDisplay([]); + } + } + + function onScrollMain(e) { + if (options.fixedGutter && gutter.style.left != scroller.scrollLeft + "px") + gutter.style.left = scroller.scrollLeft + "px"; + if (Math.abs(scroller.scrollTop - lastScrollTop) > 1) { + lastScrollTop = scroller.scrollTop; + if (scrollbar.scrollTop != lastScrollTop) + scrollbar.scrollTop = lastScrollTop; + updateDisplay([]); + } + if (options.onScroll) options.onScroll(instance); + } + + function onMouseDown(e) { + setShift(e_prop(e, "shiftKey")); + // Check whether this is a click in a widget + for (var n = e_target(e); n != wrapper; n = n.parentNode) + if (n.parentNode == sizer && n != mover) return; + + // See if this is a click in the gutter + for (var n = e_target(e); n != wrapper; n = n.parentNode) + if (n.parentNode == gutterText) { + if (options.onGutterClick) + options.onGutterClick(instance, indexOf(gutterText.childNodes, n) + showingFrom, e); + return e_preventDefault(e); + } + + var start = posFromMouse(e); + + switch (e_button(e)) { + case 3: + if (gecko) onContextMenu(e); + return; + case 2: + if (start) setCursor(start.line, start.ch, true); + setTimeout(focusInput, 20); + e_preventDefault(e); + return; + } + // For button 1, if it was clicked inside the editor + // (posFromMouse returning non-null), we have to adjust the + // selection. + if (!start) {if (e_target(e) == scroller) e_preventDefault(e); return;} + + if (!focused) onFocus(); + + var now = +new Date, type = "single"; + if (lastDoubleClick && lastDoubleClick.time > now - 400 && posEq(lastDoubleClick.pos, start)) { + type = "triple"; + e_preventDefault(e); + setTimeout(focusInput, 20); + selectLine(start.line); + } else if (lastClick && lastClick.time > now - 400 && posEq(lastClick.pos, start)) { + type = "double"; + lastDoubleClick = {time: now, pos: start}; + e_preventDefault(e); + var word = findWordAt(start); + setSelectionUser(word.from, word.to); + } else { lastClick = {time: now, pos: start}; } + + function dragEnd(e2) { + if (webkit) scroller.draggable = false; + draggingText = false; + up(); drop(); + if (Math.abs(e.clientX - e2.clientX) + Math.abs(e.clientY - e2.clientY) < 10) { + e_preventDefault(e2); + setCursor(start.line, start.ch, true); + focusInput(); + } + } + var last = start, going; + if (options.dragDrop && dragAndDrop && !options.readOnly && !posEq(sel.from, sel.to) && + !posLess(start, sel.from) && !posLess(sel.to, start) && type == "single") { + // Let the drag handler handle this. + if (webkit) scroller.draggable = true; + var up = connect(document, "mouseup", operation(dragEnd), true); + var drop = connect(scroller, "drop", operation(dragEnd), true); + draggingText = true; + // IE's approach to draggable + if (scroller.dragDrop) scroller.dragDrop(); + return; + } + e_preventDefault(e); + if (type == "single") setCursor(start.line, start.ch, true); + + var startstart = sel.from, startend = sel.to; + + function doSelect(cur) { + if (type == "single") { + setSelectionUser(clipPos(start), cur); + return; + } + startstart = clipPos(startstart); + startend = clipPos(startend); + if (type == "double") { + var word = findWordAt(cur); + if (posLess(cur, startstart)) setSelectionUser(word.from, startend); + else setSelectionUser(startstart, word.to); + } else if (type == "triple") { + if (posLess(cur, startstart)) setSelectionUser(startend, clipPos({line: cur.line, ch: 0})); + else setSelectionUser(startstart, clipPos({line: cur.line + 1, ch: 0})); + } + } + + function extend(e) { + var cur = posFromMouse(e, true); + if (cur && !posEq(cur, last)) { + if (!focused) onFocus(); + last = cur; + doSelect(cur); + updateInput = false; + var visible = visibleLines(); + if (cur.line >= visible.to || cur.line < visible.from) + going = setTimeout(operation(function(){extend(e);}), 150); + } + } + + function done(e) { + clearTimeout(going); + var cur = posFromMouse(e); + if (cur) doSelect(cur); + e_preventDefault(e); + focusInput(); + updateInput = true; + move(); up(); + } + var move = connect(document, "mousemove", operation(function(e) { + clearTimeout(going); + e_preventDefault(e); + if (!ie && !e_button(e)) done(e); + else extend(e); + }), true); + var up = connect(document, "mouseup", operation(done), true); + } + function onDoubleClick(e) { + for (var n = e_target(e); n != wrapper; n = n.parentNode) + if (n.parentNode == gutterText) return e_preventDefault(e); + e_preventDefault(e); + } + function onDrop(e) { + if (options.onDragEvent && options.onDragEvent(instance, addStop(e))) return; + e_preventDefault(e); + var pos = posFromMouse(e, true), files = e.dataTransfer.files; + if (!pos || options.readOnly) return; + if (files && files.length && window.FileReader && window.File) { + var n = files.length, text = Array(n), read = 0; + var loadFile = function(file, i) { + var reader = new FileReader; + reader.onload = function() { + text[i] = reader.result; + if (++read == n) { + pos = clipPos(pos); + operation(function() { + var end = replaceRange(text.join(""), pos, pos); + setSelectionUser(pos, end); + })(); + } + }; + reader.readAsText(file); + }; + for (var i = 0; i < n; ++i) loadFile(files[i], i); + } else { + // Don't do a replace if the drop happened inside of the selected text. + if (draggingText && !(posLess(pos, sel.from) || posLess(sel.to, pos))) return; + try { + var text = e.dataTransfer.getData("Text"); + if (text) { + compoundChange(function() { + var curFrom = sel.from, curTo = sel.to; + setSelectionUser(pos, pos); + if (draggingText) replaceRange("", curFrom, curTo); + replaceSelection(text); + focusInput(); + }); + } + } + catch(e){} + } + } + function onDragStart(e) { + var txt = getSelection(); + e.dataTransfer.setData("Text", txt); + + // Use dummy image instead of default browsers image. + if (e.dataTransfer.setDragImage) + e.dataTransfer.setDragImage(elt('img'), 0, 0); + } + + function doHandleBinding(bound, dropShift) { + if (typeof bound == "string") { + bound = commands[bound]; + if (!bound) return false; + } + var prevShift = shiftSelecting; + try { + if (options.readOnly) suppressEdits = true; + if (dropShift) shiftSelecting = null; + bound(instance); + } catch(e) { + if (e != Pass) throw e; + return false; + } finally { + shiftSelecting = prevShift; + suppressEdits = false; + } + return true; + } + var maybeTransition; + function handleKeyBinding(e) { + // Handle auto keymap transitions + var startMap = getKeyMap(options.keyMap), next = startMap.auto; + clearTimeout(maybeTransition); + if (next && !isModifierKey(e)) maybeTransition = setTimeout(function() { + if (getKeyMap(options.keyMap) == startMap) { + options.keyMap = (next.call ? next.call(null, instance) : next); + } + }, 50); + + var name = keyNames[e_prop(e, "keyCode")], handled = false; + if (name == null || e.altGraphKey) return false; + if (e_prop(e, "altKey")) name = "Alt-" + name; + if (e_prop(e, flipCtrlCmd ? "metaKey" : "ctrlKey")) name = "Ctrl-" + name; + if (e_prop(e, flipCtrlCmd ? "ctrlKey" : "metaKey")) name = "Cmd-" + name; + + var stopped = false; + function stop() { stopped = true; } + + if (e_prop(e, "shiftKey")) { + handled = lookupKey("Shift-" + name, options.extraKeys, options.keyMap, + function(b) {return doHandleBinding(b, true);}, stop) + || lookupKey(name, options.extraKeys, options.keyMap, function(b) { + if (typeof b == "string" && /^go[A-Z]/.test(b)) return doHandleBinding(b); + }, stop); + } else { + handled = lookupKey(name, options.extraKeys, options.keyMap, doHandleBinding, stop); + } + if (stopped) handled = false; + if (handled) { + e_preventDefault(e); + restartBlink(); + if (ie_lt9) { e.oldKeyCode = e.keyCode; e.keyCode = 0; } + } + return handled; + } + function handleCharBinding(e, ch) { + var handled = lookupKey("'" + ch + "'", options.extraKeys, + options.keyMap, function(b) { return doHandleBinding(b, true); }); + if (handled) { + e_preventDefault(e); + restartBlink(); + } + return handled; + } + + var lastStoppedKey = null; + function onKeyDown(e) { + if (!focused) onFocus(); + if (ie && e.keyCode == 27) { e.returnValue = false; } + if (pollingFast) { if (readInput()) pollingFast = false; } + if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return; + var code = e_prop(e, "keyCode"); + // IE does strange things with escape. + setShift(code == 16 || e_prop(e, "shiftKey")); + // First give onKeyEvent option a chance to handle this. + var handled = handleKeyBinding(e); + if (opera) { + lastStoppedKey = handled ? code : null; + // Opera has no cut event... we try to at least catch the key combo + if (!handled && code == 88 && e_prop(e, mac ? "metaKey" : "ctrlKey")) + replaceSelection(""); + } + } + function onKeyPress(e) { + if (pollingFast) readInput(); + if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return; + var keyCode = e_prop(e, "keyCode"), charCode = e_prop(e, "charCode"); + if (opera && keyCode == lastStoppedKey) {lastStoppedKey = null; e_preventDefault(e); return;} + if (((opera && (!e.which || e.which < 10)) || khtml) && handleKeyBinding(e)) return; + var ch = String.fromCharCode(charCode == null ? keyCode : charCode); + if (options.electricChars && mode.electricChars && options.smartIndent && !options.readOnly) { + if (mode.electricChars.indexOf(ch) > -1) + setTimeout(operation(function() {indentLine(sel.to.line, "smart");}), 75); + } + if (handleCharBinding(e, ch)) return; + fastPoll(); + } + function onKeyUp(e) { + if (options.onKeyEvent && options.onKeyEvent(instance, addStop(e))) return; + if (e_prop(e, "keyCode") == 16) shiftSelecting = null; + } + + function onFocus() { + if (options.readOnly == "nocursor") return; + if (!focused) { + if (options.onFocus) options.onFocus(instance); + focused = true; + if (scroller.className.search(/\bCodeMirror-focused\b/) == -1) + scroller.className += " CodeMirror-focused"; + } + slowPoll(); + restartBlink(); + } + function onBlur() { + if (focused) { + if (options.onBlur) options.onBlur(instance); + focused = false; + if (bracketHighlighted) + operation(function(){ + if (bracketHighlighted) { bracketHighlighted(); bracketHighlighted = null; } + })(); + scroller.className = scroller.className.replace(" CodeMirror-focused", ""); + } + clearInterval(blinker); + setTimeout(function() {if (!focused) shiftSelecting = null;}, 150); + } + + // Replace the range from from to to by the strings in newText. + // Afterwards, set the selection to selFrom, selTo. + function updateLines(from, to, newText, selFrom, selTo) { + if (suppressEdits) return; + var old = []; + doc.iter(from.line, to.line + 1, function(line) { + old.push(newHL(line.text, line.markedSpans)); + }); + if (history) { + history.addChange(from.line, newText.length, old); + while (history.done.length > options.undoDepth) history.done.shift(); + } + var lines = updateMarkedSpans(hlSpans(old[0]), hlSpans(lst(old)), from.ch, to.ch, newText); + updateLinesNoUndo(from, to, lines, selFrom, selTo); + } + function unredoHelper(from, to) { + if (!from.length) return; + var set = from.pop(), out = []; + for (var i = set.length - 1; i >= 0; i -= 1) { + var change = set[i]; + var replaced = [], end = change.start + change.added; + doc.iter(change.start, end, function(line) { replaced.push(newHL(line.text, line.markedSpans)); }); + out.push({start: change.start, added: change.old.length, old: replaced}); + var pos = {line: change.start + change.old.length - 1, + ch: editEnd(hlText(lst(replaced)), hlText(lst(change.old)))}; + updateLinesNoUndo({line: change.start, ch: 0}, {line: end - 1, ch: getLine(end-1).text.length}, + change.old, pos, pos); + } + updateInput = true; + to.push(out); + } + function undo() {unredoHelper(history.done, history.undone);} + function redo() {unredoHelper(history.undone, history.done);} + + function updateLinesNoUndo(from, to, lines, selFrom, selTo) { + if (suppressEdits) return; + var recomputeMaxLength = false, maxLineLength = maxLine.text.length; + if (!options.lineWrapping) + doc.iter(from.line, to.line + 1, function(line) { + if (!line.hidden && line.text.length == maxLineLength) {recomputeMaxLength = true; return true;} + }); + if (from.line != to.line || lines.length > 1) gutterDirty = true; + + var nlines = to.line - from.line, firstLine = getLine(from.line), lastLine = getLine(to.line); + var lastHL = lst(lines); + + // First adjust the line structure + if (from.ch == 0 && to.ch == 0 && hlText(lastHL) == "") { + // This is a whole-line replace. Treated specially to make + // sure line objects move the way they are supposed to. + var added = [], prevLine = null; + for (var i = 0, e = lines.length - 1; i < e; ++i) + added.push(new Line(hlText(lines[i]), hlSpans(lines[i]))); + lastLine.update(lastLine.text, hlSpans(lastHL)); + if (nlines) doc.remove(from.line, nlines, callbacks); + if (added.length) doc.insert(from.line, added); + } else if (firstLine == lastLine) { + if (lines.length == 1) { + firstLine.update(firstLine.text.slice(0, from.ch) + hlText(lines[0]) + firstLine.text.slice(to.ch), hlSpans(lines[0])); + } else { + for (var added = [], i = 1, e = lines.length - 1; i < e; ++i) + added.push(new Line(hlText(lines[i]), hlSpans(lines[i]))); + added.push(new Line(hlText(lastHL) + firstLine.text.slice(to.ch), hlSpans(lastHL))); + firstLine.update(firstLine.text.slice(0, from.ch) + hlText(lines[0]), hlSpans(lines[0])); + doc.insert(from.line + 1, added); + } + } else if (lines.length == 1) { + firstLine.update(firstLine.text.slice(0, from.ch) + hlText(lines[0]) + lastLine.text.slice(to.ch), hlSpans(lines[0])); + doc.remove(from.line + 1, nlines, callbacks); + } else { + var added = []; + firstLine.update(firstLine.text.slice(0, from.ch) + hlText(lines[0]), hlSpans(lines[0])); + lastLine.update(hlText(lastHL) + lastLine.text.slice(to.ch), hlSpans(lastHL)); + for (var i = 1, e = lines.length - 1; i < e; ++i) + added.push(new Line(hlText(lines[i]), hlSpans(lines[i]))); + if (nlines > 1) doc.remove(from.line + 1, nlines - 1, callbacks); + doc.insert(from.line + 1, added); + } + if (options.lineWrapping) { + var perLine = Math.max(5, scroller.clientWidth / charWidth() - 3); + doc.iter(from.line, from.line + lines.length, function(line) { + if (line.hidden) return; + var guess = Math.ceil(line.text.length / perLine) || 1; + if (guess != line.height) updateLineHeight(line, guess); + }); + } else { + doc.iter(from.line, from.line + lines.length, function(line) { + var l = line.text; + if (!line.hidden && l.length > maxLineLength) { + maxLine = line; maxLineLength = l.length; maxLineChanged = true; + recomputeMaxLength = false; + } + }); + if (recomputeMaxLength) updateMaxLine = true; + } + + // Adjust frontier, schedule worker + frontier = Math.min(frontier, from.line); + startWorker(400); + + var lendiff = lines.length - nlines - 1; + // Remember that these lines changed, for updating the display + changes.push({from: from.line, to: to.line + 1, diff: lendiff}); + if (options.onChange) { + // Normalize lines to contain only strings, since that's what + // the change event handler expects + for (var i = 0; i < lines.length; ++i) + if (typeof lines[i] != "string") lines[i] = lines[i].text; + var changeObj = {from: from, to: to, text: lines}; + if (textChanged) { + for (var cur = textChanged; cur.next; cur = cur.next) {} + cur.next = changeObj; + } else textChanged = changeObj; + } + + // Update the selection + function updateLine(n) {return n <= Math.min(to.line, to.line + lendiff) ? n : n + lendiff;} + setSelection(clipPos(selFrom), clipPos(selTo), + updateLine(sel.from.line), updateLine(sel.to.line)); + } + + function needsScrollbar() { + var realHeight = doc.height * textHeight() + 2 * paddingTop(); + return realHeight * .99 > scroller.offsetHeight ? realHeight : false; + } + + function updateVerticalScroll(scrollTop) { + var scrollHeight = needsScrollbar(); + scrollbar.style.display = scrollHeight ? "block" : "none"; + if (scrollHeight) { + scrollbarInner.style.height = sizer.style.minHeight = scrollHeight + "px"; + scrollbar.style.height = scroller.clientHeight + "px"; + if (scrollTop != null) { + scrollbar.scrollTop = scroller.scrollTop = scrollTop; + // 'Nudge' the scrollbar to work around a Webkit bug where, + // in some situations, we'd end up with a scrollbar that + // reported its scrollTop (and looked) as expected, but + // *behaved* as if it was still in a previous state (i.e. + // couldn't scroll up, even though it appeared to be at the + // bottom). + if (webkit) setTimeout(function() { + if (scrollbar.scrollTop != scrollTop) return; + scrollbar.scrollTop = scrollTop + (scrollTop ? -1 : 1); + scrollbar.scrollTop = scrollTop; + }, 0); + } + } else { + sizer.style.minHeight = ""; + } + // Position the mover div to align with the current virtual scroll position + mover.style.top = displayOffset * textHeight() + "px"; + } + + function computeMaxLength() { + maxLine = getLine(0); maxLineChanged = true; + var maxLineLength = maxLine.text.length; + doc.iter(1, doc.size, function(line) { + var l = line.text; + if (!line.hidden && l.length > maxLineLength) { + maxLineLength = l.length; maxLine = line; + } + }); + updateMaxLine = false; + } + + function replaceRange(code, from, to) { + from = clipPos(from); + if (!to) to = from; else to = clipPos(to); + code = splitLines(code); + function adjustPos(pos) { + if (posLess(pos, from)) return pos; + if (!posLess(to, pos)) return end; + var line = pos.line + code.length - (to.line - from.line) - 1; + var ch = pos.ch; + if (pos.line == to.line) + ch += lst(code).length - (to.ch - (to.line == from.line ? from.ch : 0)); + return {line: line, ch: ch}; + } + var end; + replaceRange1(code, from, to, function(end1) { + end = end1; + return {from: adjustPos(sel.from), to: adjustPos(sel.to)}; + }); + return end; + } + function replaceSelection(code, collapse) { + replaceRange1(splitLines(code), sel.from, sel.to, function(end) { + if (collapse == "end") return {from: end, to: end}; + else if (collapse == "start") return {from: sel.from, to: sel.from}; + else return {from: sel.from, to: end}; + }); + } + function replaceRange1(code, from, to, computeSel) { + var endch = code.length == 1 ? code[0].length + from.ch : lst(code).length; + var newSel = computeSel({line: from.line + code.length - 1, ch: endch}); + updateLines(from, to, code, newSel.from, newSel.to); + } + + function getRange(from, to, lineSep) { + var l1 = from.line, l2 = to.line; + if (l1 == l2) return getLine(l1).text.slice(from.ch, to.ch); + var code = [getLine(l1).text.slice(from.ch)]; + doc.iter(l1 + 1, l2, function(line) { code.push(line.text); }); + code.push(getLine(l2).text.slice(0, to.ch)); + return code.join(lineSep || "\n"); + } + function getSelection(lineSep) { + return getRange(sel.from, sel.to, lineSep); + } + + function slowPoll() { + if (pollingFast) return; + poll.set(options.pollInterval, function() { + readInput(); + if (focused) slowPoll(); + }); + } + function fastPoll() { + var missed = false; + pollingFast = true; + function p() { + var changed = readInput(); + if (!changed && !missed) {missed = true; poll.set(60, p);} + else {pollingFast = false; slowPoll();} + } + poll.set(20, p); + } + + // Previnput is a hack to work with IME. If we reset the textarea + // on every change, that breaks IME. So we look for changes + // compared to the previous content instead. (Modern browsers have + // events that indicate IME taking place, but these are not widely + // supported or compatible enough yet to rely on.) + var prevInput = ""; + function readInput() { + if (!focused || hasSelection(input) || options.readOnly) return false; + var text = input.value; + if (text == prevInput) return false; + if (!nestedOperation) startOperation(); + shiftSelecting = null; + var same = 0, l = Math.min(prevInput.length, text.length); + while (same < l && prevInput[same] == text[same]) ++same; + if (same < prevInput.length) + sel.from = {line: sel.from.line, ch: sel.from.ch - (prevInput.length - same)}; + else if (overwrite && posEq(sel.from, sel.to) && !pasteIncoming) + sel.to = {line: sel.to.line, ch: Math.min(getLine(sel.to.line).text.length, sel.to.ch + (text.length - same))}; + replaceSelection(text.slice(same), "end"); + if (text.length > 1000) { input.value = prevInput = ""; } + else prevInput = text; + if (!nestedOperation) endOperation(); + pasteIncoming = false; + return true; + } + function resetInput(user) { + if (!posEq(sel.from, sel.to)) { + prevInput = ""; + input.value = getSelection(); + if (focused) selectInput(input); + } else if (user) prevInput = input.value = ""; + } + + function focusInput() { + if (options.readOnly != "nocursor" && (ie_lt9 || document.activeElement != input)) + input.focus(); + } + + function scrollCursorIntoView() { + var coords = calculateCursorCoords(); + scrollIntoView(coords.x, coords.y, coords.x, coords.yBot); + if (!focused) return; + var box = sizer.getBoundingClientRect(), doScroll = null; + if (coords.y + box.top < 0) doScroll = true; + else if (coords.y + box.top + textHeight() > (window.innerHeight || document.documentElement.clientHeight)) doScroll = false; + if (doScroll != null) { + var hidden = cursor.style.display == "none"; + if (hidden) { + cursor.style.display = ""; + cursor.style.left = coords.x + "px"; + cursor.style.top = (coords.y - displayOffset) + "px"; + } + cursor.scrollIntoView(doScroll); + if (hidden) cursor.style.display = "none"; + } + } + function calculateCursorCoords() { + var cursor = localCoords(sel.inverted ? sel.from : sel.to); + var x = options.lineWrapping ? Math.min(cursor.x, lineSpace.offsetWidth) : cursor.x; + return {x: x, y: cursor.y, yBot: cursor.yBot}; + } + function scrollIntoView(x1, y1, x2, y2) { + var scrollPos = calculateScrollPos(x1, y1, x2, y2); + if (scrollPos.scrollLeft != null) {scroller.scrollLeft = scrollPos.scrollLeft;} + if (scrollPos.scrollTop != null) {scrollbar.scrollTop = scroller.scrollTop = scrollPos.scrollTop;} + } + function calculateScrollPos(x1, y1, x2, y2) { + var pl = paddingLeft(), pt = paddingTop(); + y1 += pt; y2 += pt; x1 += pl; x2 += pl; + var screen = scroller.clientHeight, screentop = scrollbar.scrollTop, result = {}; + var docBottom = needsScrollbar() || Infinity; + var atTop = y1 < pt + 10, atBottom = y2 + pt > docBottom - 10; + if (y1 < screentop) result.scrollTop = atTop ? 0 : Math.max(0, y1); + else if (y2 > screentop + screen) result.scrollTop = (atBottom ? docBottom : y2) - screen; + + var screenw = scroller.clientWidth, screenleft = scroller.scrollLeft; + var gutterw = options.fixedGutter ? gutter.clientWidth : 0; + var atLeft = x1 < gutterw + pl + 10; + if (x1 < screenleft + gutterw || atLeft) { + if (atLeft) x1 = 0; + result.scrollLeft = Math.max(0, x1 - 10 - gutterw); + } else if (x2 > screenw + screenleft - 3) { + result.scrollLeft = x2 + 10 - screenw; + } + return result; + } + + function visibleLines(scrollTop) { + var lh = textHeight(), top = (scrollTop != null ? scrollTop : scrollbar.scrollTop) - paddingTop(); + var fromHeight = Math.max(0, Math.floor(top / lh)); + var toHeight = Math.ceil((top + scroller.clientHeight) / lh); + return {from: lineAtHeight(doc, fromHeight), + to: lineAtHeight(doc, toHeight)}; + } + // Uses a set of changes plus the current scroll position to + // determine which DOM updates have to be made, and makes the + // updates. + function updateDisplay(changes, suppressCallback, scrollTop) { + if (!scroller.clientWidth) { + showingFrom = showingTo = displayOffset = 0; + return; + } + // Compute the new visible window + // If scrollTop is specified, use that to determine which lines + // to render instead of the current scrollbar position. + var visible = visibleLines(scrollTop); + // Bail out if the visible area is already rendered and nothing changed. + if (changes !== true && changes.length == 0 && visible.from > showingFrom && visible.to < showingTo) { + updateVerticalScroll(scrollTop); + return; + } + var from = Math.max(visible.from - 100, 0), to = Math.min(doc.size, visible.to + 100); + if (showingFrom < from && from - showingFrom < 20) from = showingFrom; + if (showingTo > to && showingTo - to < 20) to = Math.min(doc.size, showingTo); + + // Create a range of theoretically intact lines, and punch holes + // in that using the change info. + var intact = changes === true ? [] : + computeIntact([{from: showingFrom, to: showingTo, domStart: 0}], changes); + // Clip off the parts that won't be visible + var intactLines = 0; + for (var i = 0; i < intact.length; ++i) { + var range = intact[i]; + if (range.from < from) {range.domStart += (from - range.from); range.from = from;} + if (range.to > to) range.to = to; + if (range.from >= range.to) intact.splice(i--, 1); + else intactLines += range.to - range.from; + } + if (intactLines == to - from && from == showingFrom && to == showingTo) { + updateVerticalScroll(scrollTop); + return; + } + intact.sort(function(a, b) {return a.domStart - b.domStart;}); + + var th = textHeight(), gutterDisplay = gutter.style.display; + lineDiv.style.display = "none"; + patchDisplay(from, to, intact); + lineDiv.style.display = gutter.style.display = ""; + + var different = from != showingFrom || to != showingTo || lastSizeC != scroller.clientHeight + th; + // This is just a bogus formula that detects when the editor is + // resized or the font size changes. + if (different) lastSizeC = scroller.clientHeight + th; + if (from != showingFrom || to != showingTo && options.onViewportChange) + setTimeout(function(){ + if (options.onViewportChange) options.onViewportChange(instance, from, to); + }); + showingFrom = from; showingTo = to; + displayOffset = heightAtLine(doc, from); + startWorker(100); + + // Since this is all rather error prone, it is honoured with the + // only assertion in the whole file. + if (lineDiv.childNodes.length != showingTo - showingFrom) + throw new Error("BAD PATCH! " + JSON.stringify(intact) + " size=" + (showingTo - showingFrom) + + " nodes=" + lineDiv.childNodes.length); + + function checkHeights() { + var curNode = lineDiv.firstChild, heightChanged = false; + doc.iter(showingFrom, showingTo, function(line) { + // Work around bizarro IE7 bug where, sometimes, our curNode + // is magically replaced with a new node in the DOM, leaving + // us with a reference to an orphan (nextSibling-less) node. + if (!curNode) return; + if (!line.hidden) { + var height = Math.round(curNode.offsetHeight / th) || 1; + if (line.height != height) { + updateLineHeight(line, height); + gutterDirty = heightChanged = true; + } + } + curNode = curNode.nextSibling; + }); + return heightChanged; + } + + if (options.lineWrapping) checkHeights(); + + gutter.style.display = gutterDisplay; + if (different || gutterDirty) { + // If the gutter grew in size, re-check heights. If those changed, re-draw gutter. + updateGutter() && options.lineWrapping && checkHeights() && updateGutter(); + } + updateVerticalScroll(scrollTop); + updateSelection(); + if (!suppressCallback && options.onUpdate) options.onUpdate(instance); + return true; + } + + function computeIntact(intact, changes) { + for (var i = 0, l = changes.length || 0; i < l; ++i) { + var change = changes[i], intact2 = [], diff = change.diff || 0; + for (var j = 0, l2 = intact.length; j < l2; ++j) { + var range = intact[j]; + if (change.to <= range.from && change.diff) + intact2.push({from: range.from + diff, to: range.to + diff, + domStart: range.domStart}); + else if (change.to <= range.from || change.from >= range.to) + intact2.push(range); + else { + if (change.from > range.from) + intact2.push({from: range.from, to: change.from, domStart: range.domStart}); + if (change.to < range.to) + intact2.push({from: change.to + diff, to: range.to + diff, + domStart: range.domStart + (change.to - range.from)}); + } + } + intact = intact2; + } + return intact; + } + + function patchDisplay(from, to, intact) { + function killNode(node) { + var tmp = node.nextSibling; + node.parentNode.removeChild(node); + return tmp; + } + // The first pass removes the DOM nodes that aren't intact. + if (!intact.length) removeChildren(lineDiv); + else { + var domPos = 0, curNode = lineDiv.firstChild, n; + for (var i = 0; i < intact.length; ++i) { + var cur = intact[i]; + while (cur.domStart > domPos) {curNode = killNode(curNode); domPos++;} + for (var j = 0, e = cur.to - cur.from; j < e; ++j) {curNode = curNode.nextSibling; domPos++;} + } + while (curNode) curNode = killNode(curNode); + } + // This pass fills in the lines that actually changed. + var nextIntact = intact.shift(), curNode = lineDiv.firstChild, j = from; + doc.iter(from, to, function(line) { + if (nextIntact && nextIntact.to == j) nextIntact = intact.shift(); + if (!nextIntact || nextIntact.from > j) { + if (line.hidden) var lineElement = elt("pre"); + else { + var lineElement = lineContent(line); + if (line.className) lineElement.className = line.className; + // Kludge to make sure the styled element lies behind the selection (by z-index) + if (line.bgClassName) { + var pre = elt("pre", "\u00a0", line.bgClassName, "position: absolute; left: 0; right: 0; top: 0; bottom: 0; z-index: -2"); + lineElement = elt("div", [pre, lineElement], null, "position: relative"); + } + } + lineDiv.insertBefore(lineElement, curNode); + } else { + curNode = curNode.nextSibling; + } + ++j; + }); + } + + function updateGutter() { + if (!options.gutter && !options.lineNumbers) return; + var hText = mover.offsetHeight, hEditor = scroller.clientHeight; + gutter.style.height = (hText - hEditor < 2 ? hEditor : hText) + "px"; + var fragment = document.createDocumentFragment(), i = showingFrom, normalNode; + doc.iter(showingFrom, Math.max(showingTo, showingFrom + 1), function(line) { + if (line.hidden) { + fragment.appendChild(elt("pre")); + } else { + var marker = line.gutterMarker; + var text = options.lineNumbers ? options.lineNumberFormatter(i + options.firstLineNumber) : null; + if (marker && marker.text) + text = marker.text.replace("%N%", text != null ? text : ""); + else if (text == null) + text = "\u00a0"; + var markerElement = fragment.appendChild(elt("pre", null, marker && marker.style)); + markerElement.innerHTML = text; + for (var j = 1; j < line.height; ++j) { + markerElement.appendChild(elt("br")); + markerElement.appendChild(document.createTextNode("\u00a0")); + } + if (!marker) normalNode = i; + } + ++i; + }); + gutter.style.display = "none"; + removeChildrenAndAdd(gutterText, fragment); + // Make sure scrolling doesn't cause number gutter size to pop + if (normalNode != null && options.lineNumbers) { + var node = gutterText.childNodes[normalNode - showingFrom]; + var minwidth = String(doc.size).length, val = eltText(node.firstChild), pad = ""; + while (val.length + pad.length < minwidth) pad += "\u00a0"; + if (pad) node.insertBefore(document.createTextNode(pad), node.firstChild); + } + gutter.style.display = ""; + var resized = Math.abs((parseInt(lineSpace.style.marginLeft) || 0) - gutter.offsetWidth) > 2; + lineSpace.style.marginLeft = gutter.offsetWidth + "px"; + gutterDirty = false; + return resized; + } + function updateSelection() { + var collapsed = posEq(sel.from, sel.to); + var fromPos = localCoords(sel.from, true); + var toPos = collapsed ? fromPos : localCoords(sel.to, true); + var headPos = sel.inverted ? fromPos : toPos, th = textHeight(); + var wrapOff = eltOffset(wrapper), lineOff = eltOffset(lineDiv); + inputDiv.style.top = Math.max(0, Math.min(scroller.offsetHeight, headPos.y + lineOff.top - wrapOff.top)) + "px"; + inputDiv.style.left = Math.max(0, Math.min(scroller.offsetWidth, headPos.x + lineOff.left - wrapOff.left)) + "px"; + if (collapsed || options.showCursorWhenSelecting) { + cursor.style.top = headPos.y + "px"; + cursor.style.left = (options.lineWrapping ? Math.min(headPos.x, lineSpace.offsetWidth) : headPos.x) + "px"; + cursor.style.display = ""; + } else { + cursor.style.display = "none"; + } + if (!collapsed) { + var sameLine = fromPos.y == toPos.y, fragment = document.createDocumentFragment(); + var clientWidth = lineSpace.clientWidth || lineSpace.offsetWidth; + var clientHeight = lineSpace.clientHeight || lineSpace.offsetHeight; + var add = function(left, top, right, height) { + var rstyle = quirksMode ? "width: " + (!right ? clientWidth : clientWidth - right - left) + "px" + : "right: " + (right - 1) + "px"; + fragment.appendChild(elt("div", null, "CodeMirror-selected", "position: absolute; left: " + left + + "px; top: " + top + "px; " + rstyle + "; height: " + height + "px")); + }; + if (sel.from.ch && fromPos.y >= 0) { + var right = sameLine ? clientWidth - toPos.x : 0; + add(fromPos.x, fromPos.y, right, th); + } + var middleStart = Math.max(0, fromPos.y + (sel.from.ch ? th : 0)); + var middleHeight = Math.min(toPos.y, clientHeight) - middleStart; + if (middleHeight > 0.2 * th) + add(0, middleStart, 0, middleHeight); + if ((!sameLine || !sel.from.ch) && toPos.y < clientHeight - .5 * th) + add(0, toPos.y, clientWidth - toPos.x, th); + removeChildrenAndAdd(selectionDiv, fragment); + selectionDiv.style.display = ""; + } else { + selectionDiv.style.display = "none"; + } + } + + function setShift(val) { + if (val) shiftSelecting = shiftSelecting || (sel.inverted ? sel.to : sel.from); + else shiftSelecting = null; + } + function setSelectionUser(from, to) { + var sh = shiftSelecting && clipPos(shiftSelecting); + if (sh) { + if (posLess(sh, from)) from = sh; + else if (posLess(to, sh)) to = sh; + } + setSelection(from, to); + userSelChange = true; + } + // Update the selection. Last two args are only used by + // updateLines, since they have to be expressed in the line + // numbers before the update. + function setSelection(from, to, oldFrom, oldTo) { + goalColumn = null; + if (oldFrom == null) {oldFrom = sel.from.line; oldTo = sel.to.line;} + if (posEq(sel.from, from) && posEq(sel.to, to)) return; + if (posLess(to, from)) {var tmp = to; to = from; from = tmp;} + + // Skip over hidden lines. + if (from.line != oldFrom) { + var from1 = skipHidden(from, oldFrom, sel.from.ch); + // If there is no non-hidden line left, force visibility on current line + if (!from1) setLineHidden(from.line, false); + else from = from1; + } + if (to.line != oldTo) to = skipHidden(to, oldTo, sel.to.ch); + + if (posEq(from, to)) sel.inverted = false; + else if (posEq(from, sel.to)) sel.inverted = false; + else if (posEq(to, sel.from)) sel.inverted = true; + + if (options.autoClearEmptyLines && posEq(sel.from, sel.to)) { + var head = sel.inverted ? from : to; + if (head.line != sel.from.line && sel.from.line < doc.size) { + var oldLine = getLine(sel.from.line); + if (/^\s+$/.test(oldLine.text)) + setTimeout(operation(function() { + if (oldLine.parent && /^\s+$/.test(oldLine.text)) { + var no = lineNo(oldLine); + replaceRange("", {line: no, ch: 0}, {line: no, ch: oldLine.text.length}); + } + }, 10)); + } + } + + sel.from = from; sel.to = to; + selectionChanged = true; + } + function skipHidden(pos, oldLine, oldCh) { + function getNonHidden(dir) { + var lNo = pos.line + dir, end = dir == 1 ? doc.size : -1; + while (lNo != end) { + var line = getLine(lNo); + if (!line.hidden) { + var ch = pos.ch; + if (toEnd || ch > oldCh || ch > line.text.length) ch = line.text.length; + return {line: lNo, ch: ch}; + } + lNo += dir; + } + } + var line = getLine(pos.line); + var toEnd = pos.ch == line.text.length && pos.ch != oldCh; + if (!line.hidden) return pos; + if (pos.line >= oldLine) return getNonHidden(1) || getNonHidden(-1); + else return getNonHidden(-1) || getNonHidden(1); + } + function setCursor(line, ch, user) { + var pos = clipPos({line: line, ch: ch || 0}); + (user ? setSelectionUser : setSelection)(pos, pos); + } + + function clipLine(n) {return Math.max(0, Math.min(n, doc.size-1));} + function clipPos(pos) { + if (pos.line < 0) return {line: 0, ch: 0}; + if (pos.line >= doc.size) return {line: doc.size-1, ch: getLine(doc.size-1).text.length}; + var ch = pos.ch, linelen = getLine(pos.line).text.length; + if (ch == null || ch > linelen) return {line: pos.line, ch: linelen}; + else if (ch < 0) return {line: pos.line, ch: 0}; + else return pos; + } + + function findPosH(dir, unit) { + var end = sel.inverted ? sel.from : sel.to, line = end.line, ch = end.ch; + var lineObj = getLine(line); + function findNextLine() { + for (var l = line + dir, e = dir < 0 ? -1 : doc.size; l != e; l += dir) { + var lo = getLine(l); + if (!lo.hidden) { line = l; lineObj = lo; return true; } + } + } + function moveOnce(boundToLine) { + if (ch == (dir < 0 ? 0 : lineObj.text.length)) { + if (!boundToLine && findNextLine()) ch = dir < 0 ? lineObj.text.length : 0; + else return false; + } else ch += dir; + return true; + } + if (unit == "char") moveOnce(); + else if (unit == "column") moveOnce(true); + else if (unit == "word") { + var sawWord = false; + for (;;) { + if (dir < 0) if (!moveOnce()) break; + if (isWordChar(lineObj.text.charAt(ch))) sawWord = true; + else if (sawWord) {if (dir < 0) {dir = 1; moveOnce();} break;} + if (dir > 0) if (!moveOnce()) break; + } + } + return {line: line, ch: ch}; + } + function moveH(dir, unit) { + var pos = dir < 0 ? sel.from : sel.to; + if (shiftSelecting || posEq(sel.from, sel.to)) pos = findPosH(dir, unit); + setCursor(pos.line, pos.ch, true); + } + function deleteH(dir, unit) { + if (!posEq(sel.from, sel.to)) replaceRange("", sel.from, sel.to); + else if (dir < 0) replaceRange("", findPosH(dir, unit), sel.to); + else replaceRange("", sel.from, findPosH(dir, unit)); + userSelChange = true; + } + function moveV(dir, unit) { + var dist = 0, pos = localCoords(sel.inverted ? sel.from : sel.to, true); + if (goalColumn != null) pos.x = goalColumn; + if (unit == "page") { + var screen = Math.min(scroller.clientHeight, window.innerHeight || document.documentElement.clientHeight); + var target = coordsChar(pos.x, pos.y + screen * dir); + } else if (unit == "line") { + var th = textHeight(); + var target = coordsChar(pos.x, pos.y + .5 * th + dir * th); + } + if (unit == "page") scrollbar.scrollTop += localCoords(target, true).y - pos.y; + setCursor(target.line, target.ch, true); + goalColumn = pos.x; + } + + function findWordAt(pos) { + var line = getLine(pos.line).text; + var start = pos.ch, end = pos.ch; + if (line) { + if (pos.after === false || end == line.length) --start; else ++end; + var startChar = line.charAt(start); + var check = isWordChar(startChar) ? isWordChar : + /\s/.test(startChar) ? function(ch) {return /\s/.test(ch);} : + function(ch) {return !/\s/.test(ch) && isWordChar(ch);}; + while (start > 0 && check(line.charAt(start - 1))) --start; + while (end < line.length && check(line.charAt(end))) ++end; + } + return {from: {line: pos.line, ch: start}, to: {line: pos.line, ch: end}}; + } + function selectLine(line) { + setSelectionUser({line: line, ch: 0}, clipPos({line: line + 1, ch: 0})); + } + function indentSelected(mode) { + if (posEq(sel.from, sel.to)) return indentLine(sel.from.line, mode); + var e = sel.to.line - (sel.to.ch ? 0 : 1); + for (var i = sel.from.line; i <= e; ++i) indentLine(i, mode); + } + + function indentLine(n, how) { + if (!how) how = "add"; + if (how == "smart") { + if (!mode.indent) how = "prev"; + else var state = getStateBefore(n); + } + + var line = getLine(n), curSpace = line.indentation(options.tabSize), + curSpaceString = line.text.match(/^\s*/)[0], indentation; + if (how == "smart") { + indentation = mode.indent(state, line.text.slice(curSpaceString.length), line.text); + if (indentation == Pass) how = "prev"; + } + if (how == "prev") { + if (n) indentation = getLine(n-1).indentation(options.tabSize); + else indentation = 0; + } + else if (how == "add") indentation = curSpace + options.indentUnit; + else if (how == "subtract") indentation = curSpace - options.indentUnit; + indentation = Math.max(0, indentation); + var diff = indentation - curSpace; + + var indentString = "", pos = 0; + if (options.indentWithTabs) + for (var i = Math.floor(indentation / options.tabSize); i; --i) {pos += options.tabSize; indentString += "\t";} + if (pos < indentation) indentString += spaceStr(indentation - pos); + + if (indentString != curSpaceString) + replaceRange(indentString, {line: n, ch: 0}, {line: n, ch: curSpaceString.length}); + line.stateAfter = null; + } + + function loadMode() { + mode = CodeMirror.getMode(options, options.mode); + doc.iter(0, doc.size, function(line) { line.stateAfter = null; }); + frontier = 0; + startWorker(100); + } + function gutterChanged() { + var visible = options.gutter || options.lineNumbers; + gutter.style.display = visible ? "" : "none"; + if (visible) gutterDirty = true; + else lineDiv.parentNode.style.marginLeft = 0; + } + function wrappingChanged(from, to) { + if (options.lineWrapping) { + wrapper.className += " CodeMirror-wrap"; + var perLine = scroller.clientWidth / charWidth() - 3; + doc.iter(0, doc.size, function(line) { + if (line.hidden) return; + var guess = Math.ceil(line.text.length / perLine) || 1; + if (guess != 1) updateLineHeight(line, guess); + }); + lineSpace.style.minWidth = widthForcer.style.left = ""; + } else { + wrapper.className = wrapper.className.replace(" CodeMirror-wrap", ""); + computeMaxLength(); + doc.iter(0, doc.size, function(line) { + if (line.height != 1 && !line.hidden) updateLineHeight(line, 1); + }); + } + changes.push({from: 0, to: doc.size}); + } + function themeChanged() { + scroller.className = scroller.className.replace(/\s*cm-s-\S+/g, "") + + options.theme.replace(/(^|\s)\s*/g, " cm-s-"); + } + function keyMapChanged() { + var style = keyMap[options.keyMap].style; + wrapper.className = wrapper.className.replace(/\s*cm-keymap-\S+/g, "") + + (style ? " cm-keymap-" + style : ""); + } + + function TextMarker(type, style) { this.lines = []; this.type = type; if (style) this.style = style; } + TextMarker.prototype.clear = operation(function() { + var min, max; + for (var i = 0; i < this.lines.length; ++i) { + var line = this.lines[i]; + var span = getMarkedSpanFor(line.markedSpans, this); + if (span.from != null) min = lineNo(line); + if (span.to != null) max = lineNo(line); + line.markedSpans = removeMarkedSpan(line.markedSpans, span); + } + if (min != null) changes.push({from: min, to: max + 1}); + this.lines.length = 0; + this.explicitlyCleared = true; + }); + TextMarker.prototype.find = function() { + var from, to; + for (var i = 0; i < this.lines.length; ++i) { + var line = this.lines[i]; + var span = getMarkedSpanFor(line.markedSpans, this); + if (span.from != null || span.to != null) { + var found = lineNo(line); + if (span.from != null) from = {line: found, ch: span.from}; + if (span.to != null) to = {line: found, ch: span.to}; + } + } + if (this.type == "bookmark") return from; + return from && {from: from, to: to}; + }; + + function markText(from, to, className, options) { + from = clipPos(from); to = clipPos(to); + var marker = new TextMarker("range", className); + if (options) for (var opt in options) if (options.hasOwnProperty(opt)) + marker[opt] = options[opt]; + var curLine = from.line; + doc.iter(curLine, to.line + 1, function(line) { + var span = {from: curLine == from.line ? from.ch : null, + to: curLine == to.line ? to.ch : null, + marker: marker}; + line.markedSpans = (line.markedSpans || []).concat([span]); + marker.lines.push(line); + ++curLine; + }); + changes.push({from: from.line, to: to.line + 1}); + return marker; + } + + function setBookmark(pos) { + pos = clipPos(pos); + var marker = new TextMarker("bookmark"), line = getLine(pos.line); + history.addChange(pos.line, 1, [newHL(line.text, line.markedSpans)], true); + var span = {from: pos.ch, to: pos.ch, marker: marker}; + line.markedSpans = (line.markedSpans || []).concat([span]); + marker.lines.push(line); + return marker; + } + + function findMarksAt(pos) { + pos = clipPos(pos); + var markers = [], spans = getLine(pos.line).markedSpans; + if (spans) for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if ((span.from == null || span.from <= pos.ch) && + (span.to == null || span.to >= pos.ch)) + markers.push(span.marker); + } + return markers; + } + + function addGutterMarker(line, text, className) { + if (typeof line == "number") line = getLine(clipLine(line)); + line.gutterMarker = {text: text, style: className}; + gutterDirty = true; + return line; + } + function removeGutterMarker(line) { + if (typeof line == "number") line = getLine(clipLine(line)); + line.gutterMarker = null; + gutterDirty = true; + } + + function changeLine(handle, op) { + var no = handle, line = handle; + if (typeof handle == "number") line = getLine(clipLine(handle)); + else no = lineNo(handle); + if (no == null) return null; + if (op(line, no)) changes.push({from: no, to: no + 1}); + else return null; + return line; + } + function setLineClass(handle, className, bgClassName) { + return changeLine(handle, function(line) { + if (line.className != className || line.bgClassName != bgClassName) { + line.className = className; + line.bgClassName = bgClassName; + return true; + } + }); + } + function setLineHidden(handle, hidden) { + return changeLine(handle, function(line, no) { + if (line.hidden != hidden) { + line.hidden = hidden; + if (!options.lineWrapping) { + if (hidden && line.text.length == maxLine.text.length) { + updateMaxLine = true; + } else if (!hidden && line.text.length > maxLine.text.length) { + maxLine = line; updateMaxLine = false; + } + } + updateLineHeight(line, hidden ? 0 : 1); + var fline = sel.from.line, tline = sel.to.line; + if (hidden && (fline == no || tline == no)) { + var from = fline == no ? skipHidden({line: fline, ch: 0}, fline, 0) : sel.from; + var to = tline == no ? skipHidden({line: tline, ch: 0}, tline, 0) : sel.to; + // Can't hide the last visible line, we'd have no place to put the cursor + if (!to) return; + setSelection(from, to); + } + return (gutterDirty = true); + } + }); + } + + function lineInfo(line) { + if (typeof line == "number") { + if (!isLine(line)) return null; + var n = line; + line = getLine(line); + if (!line) return null; + } else { + var n = lineNo(line); + if (n == null) return null; + } + var marker = line.gutterMarker; + return {line: n, handle: line, text: line.text, markerText: marker && marker.text, + markerClass: marker && marker.style, lineClass: line.className, bgClass: line.bgClassName}; + } + + function measureLine(line, ch) { + if (ch == 0) return {top: 0, left: 0}; + var pre = lineContent(line, ch); + removeChildrenAndAdd(measure, pre); + var anchor = pre.anchor; + var top = anchor.offsetTop, left = anchor.offsetLeft; + // Older IEs report zero offsets for spans directly after a wrap + if (ie && top == 0 && left == 0) { + var backup = elt("span", "x"); + anchor.parentNode.insertBefore(backup, anchor.nextSibling); + top = backup.offsetTop; + } + return {top: top, left: left}; + } + function localCoords(pos, inLineWrap) { + var x, lh = textHeight(), y = lh * (heightAtLine(doc, pos.line) - (inLineWrap ? displayOffset : 0)); + if (pos.ch == 0) x = 0; + else { + var sp = measureLine(getLine(pos.line), pos.ch); + x = sp.left; + if (options.lineWrapping) y += Math.max(0, sp.top); + } + return {x: x, y: y, yBot: y + lh}; + } + // Coords must be lineSpace-local + function coordsChar(x, y) { + var th = textHeight(), cw = charWidth(), heightPos = displayOffset + Math.floor(y / th); + if (heightPos < 0) return {line: 0, ch: 0}; + var lineNo = lineAtHeight(doc, heightPos); + if (lineNo >= doc.size) return {line: doc.size - 1, ch: getLine(doc.size - 1).text.length}; + var lineObj = getLine(lineNo), text = lineObj.text; + var tw = options.lineWrapping, innerOff = tw ? heightPos - heightAtLine(doc, lineNo) : 0; + if (x <= 0 && innerOff == 0) return {line: lineNo, ch: 0}; + var wrongLine = false; + function getX(len) { + var sp = measureLine(lineObj, len); + if (tw) { + var off = Math.round(sp.top / th); + wrongLine = off != innerOff; + return Math.max(0, sp.left + (off - innerOff) * scroller.clientWidth); + } + return sp.left; + } + var from = 0, fromX = 0, to = text.length, toX; + // Guess a suitable upper bound for our search. + var estimated = Math.min(to, Math.ceil((x + innerOff * scroller.clientWidth * .9) / cw)); + for (;;) { + var estX = getX(estimated); + if (estX <= x && estimated < to) estimated = Math.min(to, Math.ceil(estimated * 1.2)); + else {toX = estX; to = estimated; break;} + } + if (x > toX) return {line: lineNo, ch: to}; + // Try to guess a suitable lower bound as well. + estimated = Math.floor(to * 0.8); estX = getX(estimated); + if (estX < x) {from = estimated; fromX = estX;} + // Do a binary search between these bounds. + for (;;) { + if (to - from <= 1) { + var after = x - fromX < toX - x; + return {line: lineNo, ch: after ? from : to, after: after}; + } + var middle = Math.ceil((from + to) / 2), middleX = getX(middle); + if (middleX > x) {to = middle; toX = middleX; if (wrongLine) toX += 1000; } + else {from = middle; fromX = middleX;} + } + } + function pageCoords(pos) { + var local = localCoords(pos, true), off = eltOffset(lineSpace); + return {x: off.left + local.x, y: off.top + local.y, yBot: off.top + local.yBot}; + } + + var cachedHeight, cachedHeightFor, measurePre; + function textHeight() { + if (measurePre == null) { + measurePre = elt("pre"); + for (var i = 0; i < 49; ++i) { + measurePre.appendChild(document.createTextNode("x")); + measurePre.appendChild(elt("br")); + } + measurePre.appendChild(document.createTextNode("x")); + } + var offsetHeight = lineDiv.clientHeight; + if (offsetHeight == cachedHeightFor) return cachedHeight; + cachedHeightFor = offsetHeight; + removeChildrenAndAdd(measure, measurePre.cloneNode(true)); + cachedHeight = measure.firstChild.offsetHeight / 50 || 1; + removeChildren(measure); + return cachedHeight; + } + var cachedWidth, cachedWidthFor = 0; + function charWidth() { + if (scroller.clientWidth == cachedWidthFor) return cachedWidth; + cachedWidthFor = scroller.clientWidth; + var anchor = elt("span", "x"); + var pre = elt("pre", [anchor]); + removeChildrenAndAdd(measure, pre); + return (cachedWidth = anchor.offsetWidth || 10); + } + function paddingTop() {return lineSpace.offsetTop;} + function paddingLeft() {return lineSpace.offsetLeft;} + + function posFromMouse(e, liberal) { + var offW = eltOffset(scroller, true), x, y; + // Fails unpredictably on IE[67] when mouse is dragged around quickly. + try { x = e.clientX; y = e.clientY; } catch (e) { return null; } + // This is a mess of a heuristic to try and determine whether a + // scroll-bar was clicked or not, and to return null if one was + // (and !liberal). + if (!liberal && (x - offW.left > scroller.clientWidth || y - offW.top > scroller.clientHeight)) + return null; + var offL = eltOffset(lineSpace, true); + return coordsChar(x - offL.left, y - offL.top); + } + var detectingSelectAll; + function onContextMenu(e) { + var pos = posFromMouse(e), scrollPos = scrollbar.scrollTop; + if (!pos || opera) return; // Opera is difficult. + if (posEq(sel.from, sel.to) || posLess(pos, sel.from) || !posLess(pos, sel.to)) + operation(setCursor)(pos.line, pos.ch); + + var oldCSS = input.style.cssText; + inputDiv.style.position = "absolute"; + input.style.cssText = "position: fixed; width: 30px; height: 30px; top: " + (e.clientY - 5) + + "px; left: " + (e.clientX - 5) + "px; z-index: 1000; background: white; " + + "border-width: 0; outline: none; overflow: hidden; opacity: .05; filter: alpha(opacity=5);"; + focusInput(); + resetInput(true); + // Adds "Select all" to context menu in FF + if (posEq(sel.from, sel.to)) input.value = prevInput = " "; + + function rehide() { + inputDiv.style.position = "relative"; + input.style.cssText = oldCSS; + if (ie_lt9) scrollbar.scrollTop = scrollPos; + slowPoll(); + + // Try to detect the user choosing select-all + if (input.selectionStart != null) { + clearTimeout(detectingSelectAll); + var extval = input.value = " " + (posEq(sel.from, sel.to) ? "" : input.value), i = 0; + prevInput = " "; + input.selectionStart = 1; input.selectionEnd = extval.length; + detectingSelectAll = setTimeout(function poll(){ + if (prevInput == " " && input.selectionStart == 0) + operation(commands.selectAll)(instance); + else if (i++ < 10) detectingSelectAll = setTimeout(poll, 500); + else resetInput(); + }, 200); + } + } + + if (gecko) { + e_stop(e); + var mouseup = connect(window, "mouseup", function() { + mouseup(); + setTimeout(rehide, 20); + }, true); + } else { + setTimeout(rehide, 50); + } + } + + // Cursor-blinking + function restartBlink() { + clearInterval(blinker); + var on = true; + cursor.style.visibility = ""; + blinker = setInterval(function() { + cursor.style.visibility = (on = !on) ? "" : "hidden"; + }, options.cursorBlinkRate); + } + + var matching = {"(": ")>", ")": "(<", "[": "]>", "]": "[<", "{": "}>", "}": "{<"}; + function matchBrackets(autoclear) { + var head = sel.inverted ? sel.from : sel.to, line = getLine(head.line), pos = head.ch - 1; + var match = (pos >= 0 && matching[line.text.charAt(pos)]) || matching[line.text.charAt(++pos)]; + if (!match) return; + var ch = match.charAt(0), forward = match.charAt(1) == ">", d = forward ? 1 : -1, st = line.styles; + for (var off = pos + 1, i = 0, e = st.length; i < e; i+=2) + if ((off -= st[i].length) <= 0) {var style = st[i+1]; break;} + + var stack = [line.text.charAt(pos)], re = /[(){}[\]]/; + function scan(line, from, to) { + if (!line.text) return; + var st = line.styles, pos = forward ? 0 : line.text.length - 1, cur; + for (var i = forward ? 0 : st.length - 2, e = forward ? st.length : -2; i != e; i += 2*d) { + var text = st[i]; + if (st[i+1] != style) {pos += d * text.length; continue;} + for (var j = forward ? 0 : text.length - 1, te = forward ? text.length : -1; j != te; j += d, pos+=d) { + if (pos >= from && pos < to && re.test(cur = text.charAt(j))) { + var match = matching[cur]; + if (match.charAt(1) == ">" == forward) stack.push(cur); + else if (stack.pop() != match.charAt(0)) return {pos: pos, match: false}; + else if (!stack.length) return {pos: pos, match: true}; + } + } + } + } + for (var i = head.line, e = forward ? Math.min(i + 100, doc.size) : Math.max(-1, i - 100); i != e; i+=d) { + var line = getLine(i), first = i == head.line; + var found = scan(line, first && forward ? pos + 1 : 0, first && !forward ? pos : line.text.length); + if (found) break; + } + if (!found) found = {pos: null, match: false}; + var style = found.match ? "CodeMirror-matchingbracket" : "CodeMirror-nonmatchingbracket"; + var one = markText({line: head.line, ch: pos}, {line: head.line, ch: pos+1}, style), + two = found.pos != null && markText({line: i, ch: found.pos}, {line: i, ch: found.pos + 1}, style); + var clear = operation(function(){one.clear(); two && two.clear();}); + if (autoclear) setTimeout(clear, 800); + else bracketHighlighted = clear; + } + + // Finds the line to start with when starting a parse. Tries to + // find a line with a stateAfter, so that it can start with a + // valid state. If that fails, it returns the line with the + // smallest indentation, which tends to need the least context to + // parse correctly. + function findStartLine(n) { + var minindent, minline; + for (var search = n, lim = n - 40; search > lim; --search) { + if (search == 0) return 0; + var line = getLine(search-1); + if (line.stateAfter) return search; + var indented = line.indentation(options.tabSize); + if (minline == null || minindent > indented) { + minline = search - 1; + minindent = indented; + } + } + return minline; + } + function getStateBefore(n) { + var pos = findStartLine(n), state = pos && getLine(pos-1).stateAfter; + if (!state) state = startState(mode); + else state = copyState(mode, state); + doc.iter(pos, n, function(line) { + line.process(mode, state, options.tabSize); + line.stateAfter = (pos == n - 1 || pos % 5 == 0) ? copyState(mode, state) : null; + }); + return state; + } + function highlightWorker() { + if (frontier >= showingTo) return; + var end = +new Date + options.workTime, state = copyState(mode, getStateBefore(frontier)); + var startFrontier = frontier; + doc.iter(frontier, showingTo, function(line) { + if (frontier >= showingFrom) { // Visible + line.highlight(mode, state, options.tabSize); + line.stateAfter = copyState(mode, state); + } else { + line.process(mode, state, options.tabSize); + line.stateAfter = frontier % 5 == 0 ? copyState(mode, state) : null; + } + ++frontier; + if (+new Date > end) { + startWorker(options.workDelay); + return true; + } + }); + if (showingTo > startFrontier && frontier >= showingFrom) + operation(function() {changes.push({from: startFrontier, to: frontier});})(); + } + function startWorker(time) { + if (frontier < showingTo) + highlight.set(time, highlightWorker); + } + + // Operations are used to wrap changes in such a way that each + // change won't have to update the cursor and display (which would + // be awkward, slow, and error-prone), but instead updates are + // batched and then all combined and executed at once. + function startOperation() { + updateInput = userSelChange = textChanged = null; + changes = []; selectionChanged = false; callbacks = []; + } + function endOperation() { + if (updateMaxLine) computeMaxLength(); + if (maxLineChanged && !options.lineWrapping) { + var cursorWidth = widthForcer.offsetWidth, left = measureLine(maxLine, maxLine.text.length).left; + if (!ie_lt8) { + widthForcer.style.left = left + "px"; + lineSpace.style.minWidth = (left + cursorWidth) + "px"; + } + maxLineChanged = false; + } + var newScrollPos, updated; + if (selectionChanged) { + var coords = calculateCursorCoords(); + newScrollPos = calculateScrollPos(coords.x, coords.y, coords.x, coords.yBot); + } + if (changes.length || newScrollPos && newScrollPos.scrollTop != null) + updated = updateDisplay(changes, true, newScrollPos && newScrollPos.scrollTop); + if (!updated) { + if (selectionChanged) updateSelection(); + if (gutterDirty) updateGutter(); + } + if (newScrollPos) scrollCursorIntoView(); + if (selectionChanged) restartBlink(); + + if (focused && (updateInput === true || (updateInput !== false && selectionChanged))) + resetInput(userSelChange); + + if (selectionChanged && options.matchBrackets) + setTimeout(operation(function() { + if (bracketHighlighted) {bracketHighlighted(); bracketHighlighted = null;} + if (posEq(sel.from, sel.to)) matchBrackets(false); + }), 20); + var sc = selectionChanged, cbs = callbacks; // these can be reset by callbacks + if (textChanged && options.onChange && instance) + options.onChange(instance, textChanged); + if (sc && options.onCursorActivity) + options.onCursorActivity(instance); + for (var i = 0; i < cbs.length; ++i) cbs[i](instance); + if (updated && options.onUpdate) options.onUpdate(instance); + } + var nestedOperation = 0; + function operation(f) { + return function() { + if (!nestedOperation++) startOperation(); + try {var result = f.apply(this, arguments);} + finally {if (!--nestedOperation) endOperation();} + return result; + }; + } + + function compoundChange(f) { + history.startCompound(); + try { return f(); } finally { history.endCompound(); } + } + + for (var ext in extensions) + if (extensions.propertyIsEnumerable(ext) && + !instance.propertyIsEnumerable(ext)) + instance[ext] = extensions[ext]; + for (var i = 0; i < initHooks.length; ++i) initHooks[i](instance); + return instance; + } // (end of function CodeMirror) + + // The default configuration options. + CodeMirror.defaults = { + value: "", + mode: null, + theme: "default", + indentUnit: 2, + indentWithTabs: false, + smartIndent: true, + tabSize: 4, + keyMap: "default", + extraKeys: null, + electricChars: true, + autoClearEmptyLines: false, + onKeyEvent: null, + onDragEvent: null, + lineWrapping: false, + lineNumbers: false, + gutter: false, + fixedGutter: false, + firstLineNumber: 1, + showCursorWhenSelecting: false, + readOnly: false, + dragDrop: true, + onChange: null, + onCursorActivity: null, + onViewportChange: null, + onGutterClick: null, + onUpdate: null, + onFocus: null, onBlur: null, onScroll: null, + matchBrackets: false, + cursorBlinkRate: 530, + workTime: 100, + workDelay: 200, + pollInterval: 100, + undoDepth: 40, + tabindex: null, + autofocus: null, + lineNumberFormatter: function(integer) { return integer; } + }; + + var ios = /AppleWebKit/.test(navigator.userAgent) && /Mobile\/\w+/.test(navigator.userAgent); + var mac = ios || /Mac/.test(navigator.platform); + var win = /Win/.test(navigator.platform); + + // Known modes, by name and by MIME + var modes = CodeMirror.modes = {}, mimeModes = CodeMirror.mimeModes = {}; + CodeMirror.defineMode = function(name, mode) { + if (!CodeMirror.defaults.mode && name != "null") CodeMirror.defaults.mode = name; + if (arguments.length > 2) { + mode.dependencies = []; + for (var i = 2; i < arguments.length; ++i) mode.dependencies.push(arguments[i]); + } + modes[name] = mode; + }; + CodeMirror.defineMIME = function(mime, spec) { + mimeModes[mime] = spec; + }; + CodeMirror.resolveMode = function(spec) { + if (typeof spec == "string" && mimeModes.hasOwnProperty(spec)) + spec = mimeModes[spec]; + else if (typeof spec == "string" && /^[\w\-]+\/[\w\-]+\+xml$/.test(spec)) + return CodeMirror.resolveMode("application/xml"); + if (typeof spec == "string") return {name: spec}; + else return spec || {name: "null"}; + }; + CodeMirror.getMode = function(options, spec) { + var spec = CodeMirror.resolveMode(spec); + var mfactory = modes[spec.name]; + if (!mfactory) return CodeMirror.getMode(options, "text/plain"); + var modeObj = mfactory(options, spec); + if (modeExtensions.hasOwnProperty(spec.name)) { + var exts = modeExtensions[spec.name]; + for (var prop in exts) { + if (!exts.hasOwnProperty(prop)) continue; + if (modeObj.hasOwnProperty(prop)) modeObj["_" + prop] = modeObj[prop]; + modeObj[prop] = exts[prop]; + } + } + modeObj.name = spec.name; + return modeObj; + }; + CodeMirror.listModes = function() { + var list = []; + for (var m in modes) + if (modes.propertyIsEnumerable(m)) list.push(m); + return list; + }; + CodeMirror.listMIMEs = function() { + var list = []; + for (var m in mimeModes) + if (mimeModes.propertyIsEnumerable(m)) list.push({mime: m, mode: mimeModes[m]}); + return list; + }; + + var extensions = CodeMirror.extensions = {}; + CodeMirror.defineExtension = function(name, func) { + extensions[name] = func; + }; + + var initHooks = []; + CodeMirror.defineInitHook = function(f) {initHooks.push(f);}; + + var modeExtensions = CodeMirror.modeExtensions = {}; + CodeMirror.extendMode = function(mode, properties) { + var exts = modeExtensions.hasOwnProperty(mode) ? modeExtensions[mode] : (modeExtensions[mode] = {}); + for (var prop in properties) if (properties.hasOwnProperty(prop)) + exts[prop] = properties[prop]; + }; + + var commands = CodeMirror.commands = { + selectAll: function(cm) {cm.setSelection({line: 0, ch: 0}, {line: cm.lineCount() - 1});}, + killLine: function(cm) { + var from = cm.getCursor(true), to = cm.getCursor(false), sel = !posEq(from, to); + if (!sel && cm.getLine(from.line).length == from.ch) cm.replaceRange("", from, {line: from.line + 1, ch: 0}); + else cm.replaceRange("", from, sel ? to : {line: from.line}); + }, + deleteLine: function(cm) {var l = cm.getCursor().line; cm.replaceRange("", {line: l, ch: 0}, {line: l});}, + undo: function(cm) {cm.undo();}, + redo: function(cm) {cm.redo();}, + goDocStart: function(cm) {cm.setCursor(0, 0, true);}, + goDocEnd: function(cm) {cm.setSelection({line: cm.lineCount() - 1}, null, true);}, + goLineStart: function(cm) {cm.setCursor(cm.getCursor().line, 0, true);}, + goLineStartSmart: function(cm) { + var cur = cm.getCursor(); + var text = cm.getLine(cur.line), firstNonWS = Math.max(0, text.search(/\S/)); + cm.setCursor(cur.line, cur.ch <= firstNonWS && cur.ch ? 0 : firstNonWS, true); + }, + goLineEnd: function(cm) {cm.setSelection({line: cm.getCursor().line}, null, true);}, + goLineUp: function(cm) {cm.moveV(-1, "line");}, + goLineDown: function(cm) {cm.moveV(1, "line");}, + goPageUp: function(cm) {cm.moveV(-1, "page");}, + goPageDown: function(cm) {cm.moveV(1, "page");}, + goCharLeft: function(cm) {cm.moveH(-1, "char");}, + goCharRight: function(cm) {cm.moveH(1, "char");}, + goColumnLeft: function(cm) {cm.moveH(-1, "column");}, + goColumnRight: function(cm) {cm.moveH(1, "column");}, + goWordLeft: function(cm) {cm.moveH(-1, "word");}, + goWordRight: function(cm) {cm.moveH(1, "word");}, + delCharLeft: function(cm) {cm.deleteH(-1, "char");}, + delCharRight: function(cm) {cm.deleteH(1, "char");}, + delWordLeft: function(cm) {cm.deleteH(-1, "word");}, + delWordRight: function(cm) {cm.deleteH(1, "word");}, + indentAuto: function(cm) {cm.indentSelection("smart");}, + indentMore: function(cm) {cm.indentSelection("add");}, + indentLess: function(cm) {cm.indentSelection("subtract");}, + insertTab: function(cm) {cm.replaceSelection("\t", "end");}, + defaultTab: function(cm) { + if (cm.somethingSelected()) cm.indentSelection("add"); + else cm.replaceSelection("\t", "end"); + }, + transposeChars: function(cm) { + var cur = cm.getCursor(), line = cm.getLine(cur.line); + if (cur.ch > 0 && cur.ch < line.length - 1) + cm.replaceRange(line.charAt(cur.ch) + line.charAt(cur.ch - 1), + {line: cur.line, ch: cur.ch - 1}, {line: cur.line, ch: cur.ch + 1}); + }, + newlineAndIndent: function(cm) { + cm.replaceSelection("\n", "end"); + cm.indentLine(cm.getCursor().line); + }, + toggleOverwrite: function(cm) {cm.toggleOverwrite();} + }; + + var keyMap = CodeMirror.keyMap = {}; + keyMap.basic = { + "Left": "goCharLeft", "Right": "goCharRight", "Up": "goLineUp", "Down": "goLineDown", + "End": "goLineEnd", "Home": "goLineStartSmart", "PageUp": "goPageUp", "PageDown": "goPageDown", + "Delete": "delCharRight", "Backspace": "delCharLeft", "Tab": "defaultTab", "Shift-Tab": "indentAuto", + "Enter": "newlineAndIndent", "Insert": "toggleOverwrite" + }; + // Note that the save and find-related commands aren't defined by + // default. Unknown commands are simply ignored. + keyMap.pcDefault = { + "Ctrl-A": "selectAll", "Ctrl-D": "deleteLine", "Ctrl-Z": "undo", "Shift-Ctrl-Z": "redo", "Ctrl-Y": "redo", + "Ctrl-Home": "goDocStart", "Alt-Up": "goDocStart", "Ctrl-End": "goDocEnd", "Ctrl-Down": "goDocEnd", + "Ctrl-Left": "goWordLeft", "Ctrl-Right": "goWordRight", "Alt-Left": "goLineStart", "Alt-Right": "goLineEnd", + "Ctrl-Backspace": "delWordLeft", "Ctrl-Delete": "delWordRight", "Ctrl-S": "save", "Ctrl-F": "find", + "Ctrl-G": "findNext", "Shift-Ctrl-G": "findPrev", "Shift-Ctrl-F": "replace", "Shift-Ctrl-R": "replaceAll", + "Ctrl-[": "indentLess", "Ctrl-]": "indentMore", + fallthrough: "basic" + }; + keyMap.macDefault = { + "Cmd-A": "selectAll", "Cmd-D": "deleteLine", "Cmd-Z": "undo", "Shift-Cmd-Z": "redo", "Cmd-Y": "redo", + "Cmd-Up": "goDocStart", "Cmd-End": "goDocEnd", "Cmd-Down": "goDocEnd", "Alt-Left": "goWordLeft", + "Alt-Right": "goWordRight", "Cmd-Left": "goLineStart", "Cmd-Right": "goLineEnd", "Alt-Backspace": "delWordLeft", + "Ctrl-Alt-Backspace": "delWordRight", "Alt-Delete": "delWordRight", "Cmd-S": "save", "Cmd-F": "find", + "Cmd-G": "findNext", "Shift-Cmd-G": "findPrev", "Cmd-Alt-F": "replace", "Shift-Cmd-Alt-F": "replaceAll", + "Cmd-[": "indentLess", "Cmd-]": "indentMore", + fallthrough: ["basic", "emacsy"] + }; + keyMap["default"] = mac ? keyMap.macDefault : keyMap.pcDefault; + keyMap.emacsy = { + "Ctrl-F": "goCharRight", "Ctrl-B": "goCharLeft", "Ctrl-P": "goLineUp", "Ctrl-N": "goLineDown", + "Alt-F": "goWordRight", "Alt-B": "goWordLeft", "Ctrl-A": "goLineStart", "Ctrl-E": "goLineEnd", + "Ctrl-V": "goPageDown", "Shift-Ctrl-V": "goPageUp", "Ctrl-D": "delCharRight", "Ctrl-H": "delCharLeft", + "Alt-D": "delWordRight", "Alt-Backspace": "delWordLeft", "Ctrl-K": "killLine", "Ctrl-T": "transposeChars" + }; + + function getKeyMap(val) { + if (typeof val == "string") return keyMap[val]; + else return val; + } + function lookupKey(name, extraMap, map, handle, stop) { + function lookup(map) { + map = getKeyMap(map); + var found = map[name]; + if (found === false) { + if (stop) stop(); + return true; + } + if (found != null && handle(found)) return true; + if (map.nofallthrough) { + if (stop) stop(); + return true; + } + var fallthrough = map.fallthrough; + if (fallthrough == null) return false; + if (Object.prototype.toString.call(fallthrough) != "[object Array]") + return lookup(fallthrough); + for (var i = 0, e = fallthrough.length; i < e; ++i) { + if (lookup(fallthrough[i])) return true; + } + return false; + } + if (extraMap && lookup(extraMap)) return true; + return lookup(map); + } + function isModifierKey(event) { + var name = keyNames[e_prop(event, "keyCode")]; + return name == "Ctrl" || name == "Alt" || name == "Shift" || name == "Mod"; + } + CodeMirror.isModifierKey = isModifierKey; + + CodeMirror.fromTextArea = function(textarea, options) { + if (!options) options = {}; + options.value = textarea.value; + if (!options.tabindex && textarea.tabindex) + options.tabindex = textarea.tabindex; + // Set autofocus to true if this textarea is focused, or if it has + // autofocus and no other element is focused. + if (options.autofocus == null) { + var hasFocus = document.body; + // doc.activeElement occasionally throws on IE + try { hasFocus = document.activeElement; } catch(e) {} + options.autofocus = hasFocus == textarea || + textarea.getAttribute("autofocus") != null && hasFocus == document.body; + } + + function save() {textarea.value = instance.getValue();} + if (textarea.form) { + // Deplorable hack to make the submit method do the right thing. + var rmSubmit = connect(textarea.form, "submit", save, true); + var form = textarea.form, realSubmit = form.submit; + textarea.form.submit = function wrappedSubmit() { + save(); + form.submit = realSubmit; + form.submit(); + form.submit = wrappedSubmit; + }; + } + + textarea.style.display = "none"; + var instance = CodeMirror(function(node) { + textarea.parentNode.insertBefore(node, textarea.nextSibling); + }, options); + instance.save = save; + instance.getTextArea = function() { return textarea; }; + instance.toTextArea = function() { + save(); + textarea.parentNode.removeChild(instance.getWrapperElement()); + textarea.style.display = ""; + if (textarea.form) { + rmSubmit(); + if (typeof textarea.form.submit == "function") + textarea.form.submit = realSubmit; + } + }; + return instance; + }; + + var gecko = /gecko\/\d/i.test(navigator.userAgent); + var ie = /MSIE \d/.test(navigator.userAgent); + var ie_lt8 = /MSIE [1-7]\b/.test(navigator.userAgent); + var ie_lt9 = /MSIE [1-8]\b/.test(navigator.userAgent); + var quirksMode = ie && document.documentMode == 5; + var webkit = /WebKit\//.test(navigator.userAgent); + var qtwebkit = webkit && /Qt\/\d+\.\d+/.test(navigator.userAgent); + var chrome = /Chrome\//.test(navigator.userAgent); + var opera = /Opera\//.test(navigator.userAgent); + var safari = /Apple Computer/.test(navigator.vendor); + var khtml = /KHTML\//.test(navigator.userAgent); + var mac_geLion = /Mac OS X 10\D([7-9]|\d\d)\D/.test(navigator.userAgent); + + var opera_version = opera && navigator.userAgent.match(/Version\/(\d*\.\d*)/); + if (opera_version) opera_version = Number(opera_version[1]); + // Some browsers use the wrong event properties to signal cmd/ctrl on OS X + var flipCtrlCmd = mac && (qtwebkit || opera && (opera_version == null || opera_version < 12.11)); + + // Utility functions for working with state. Exported because modes + // sometimes need to do this. + function copyState(mode, state) { + if (state === true) return state; + if (mode.copyState) return mode.copyState(state); + var nstate = {}; + for (var n in state) { + var val = state[n]; + if (val instanceof Array) val = val.concat([]); + nstate[n] = val; + } + return nstate; + } + CodeMirror.copyState = copyState; + function startState(mode, a1, a2) { + return mode.startState ? mode.startState(a1, a2) : true; + } + CodeMirror.startState = startState; + CodeMirror.innerMode = function(mode, state) { + while (mode.innerMode) { + var info = mode.innerMode(state); + state = info.state; + mode = info.mode; + } + return info || {mode: mode, state: state}; + }; + + // The character stream used by a mode's parser. + function StringStream(string, tabSize) { + this.pos = this.start = 0; + this.string = string; + this.tabSize = tabSize || 8; + } + StringStream.prototype = { + eol: function() {return this.pos >= this.string.length;}, + sol: function() {return this.pos == 0;}, + peek: function() {return this.string.charAt(this.pos) || undefined;}, + next: function() { + if (this.pos < this.string.length) + return this.string.charAt(this.pos++); + }, + eat: function(match) { + var ch = this.string.charAt(this.pos); + if (typeof match == "string") var ok = ch == match; + else var ok = ch && (match.test ? match.test(ch) : match(ch)); + if (ok) {++this.pos; return ch;} + }, + eatWhile: function(match) { + var start = this.pos; + while (this.eat(match)){} + return this.pos > start; + }, + eatSpace: function() { + var start = this.pos; + while (/[\s\u00a0]/.test(this.string.charAt(this.pos))) ++this.pos; + return this.pos > start; + }, + skipToEnd: function() {this.pos = this.string.length;}, + skipTo: function(ch) { + var found = this.string.indexOf(ch, this.pos); + if (found > -1) {this.pos = found; return true;} + }, + backUp: function(n) {this.pos -= n;}, + column: function() {return countColumn(this.string, this.start, this.tabSize);}, + indentation: function() {return countColumn(this.string, null, this.tabSize);}, + match: function(pattern, consume, caseInsensitive) { + if (typeof pattern == "string") { + var cased = function(str) {return caseInsensitive ? str.toLowerCase() : str;}; + if (cased(this.string).indexOf(cased(pattern), this.pos) == this.pos) { + if (consume !== false) this.pos += pattern.length; + return true; + } + } else { + var match = this.string.slice(this.pos).match(pattern); + if (match && match.index > 0) return null; + if (match && consume !== false) this.pos += match[0].length; + return match; + } + }, + current: function(){return this.string.slice(this.start, this.pos);} + }; + CodeMirror.StringStream = StringStream; + + function MarkedSpan(from, to, marker) { + this.from = from; this.to = to; this.marker = marker; + } + + function getMarkedSpanFor(spans, marker) { + if (spans) for (var i = 0; i < spans.length; ++i) { + var span = spans[i]; + if (span.marker == marker) return span; + } + } + + function removeMarkedSpan(spans, span) { + var r; + for (var i = 0; i < spans.length; ++i) + if (spans[i] != span) (r || (r = [])).push(spans[i]); + return r; + } + + function markedSpansBefore(old, startCh, endCh) { + if (old) for (var i = 0, nw; i < old.length; ++i) { + var span = old[i], marker = span.marker; + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= startCh : span.from < startCh); + if (startsBefore || marker.type == "bookmark" && span.from == startCh && span.from != endCh) { + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= startCh : span.to > startCh); + (nw || (nw = [])).push({from: span.from, + to: endsAfter ? null : span.to, + marker: marker}); + } + } + return nw; + } + + function markedSpansAfter(old, endCh) { + if (old) for (var i = 0, nw; i < old.length; ++i) { + var span = old[i], marker = span.marker; + var endsAfter = span.to == null || (marker.inclusiveRight ? span.to >= endCh : span.to > endCh); + if (endsAfter || marker.type == "bookmark" && span.from == endCh) { + var startsBefore = span.from == null || (marker.inclusiveLeft ? span.from <= endCh : span.from < endCh); + (nw || (nw = [])).push({from: startsBefore ? null : span.from - endCh, + to: span.to == null ? null : span.to - endCh, + marker: marker}); + } + } + return nw; + } + + function updateMarkedSpans(oldFirst, oldLast, startCh, endCh, newText) { + if (!oldFirst && !oldLast) return newText; + // Get the spans that 'stick out' on both sides + var first = markedSpansBefore(oldFirst, startCh); + var last = markedSpansAfter(oldLast, endCh); + + // Next, merge those two ends + var sameLine = newText.length == 1, offset = lst(newText).length + (sameLine ? startCh : 0); + if (first) { + // Fix up .to properties of first + for (var i = 0; i < first.length; ++i) { + var span = first[i]; + if (span.to == null) { + var found = getMarkedSpanFor(last, span.marker); + if (!found) span.to = startCh; + else if (sameLine) span.to = found.to == null ? null : found.to + offset; + } + } + } + if (last) { + // Fix up .from in last (or move them into first in case of sameLine) + for (var i = 0; i < last.length; ++i) { + var span = last[i]; + if (span.to != null) span.to += offset; + if (span.from == null) { + var found = getMarkedSpanFor(first, span.marker); + if (!found) { + span.from = offset; + if (sameLine) (first || (first = [])).push(span); + } + } else { + span.from += offset; + if (sameLine) (first || (first = [])).push(span); + } + } + } + + var newMarkers = [newHL(newText[0], first)]; + if (!sameLine) { + // Fill gap with whole-line-spans + var gap = newText.length - 2, gapMarkers; + if (gap > 0 && first) + for (var i = 0; i < first.length; ++i) + if (first[i].to == null) + (gapMarkers || (gapMarkers = [])).push({from: null, to: null, marker: first[i].marker}); + for (var i = 0; i < gap; ++i) + newMarkers.push(newHL(newText[i+1], gapMarkers)); + newMarkers.push(newHL(lst(newText), last)); + } + return newMarkers; + } + + // hl stands for history-line, a data structure that can be either a + // string (line without markers) or a {text, markedSpans} object. + function hlText(val) { return typeof val == "string" ? val : val.text; } + function hlSpans(val) { + if (typeof val == "string") return null; + var spans = val.markedSpans, out = null; + for (var i = 0; i < spans.length; ++i) { + if (spans[i].marker.explicitlyCleared) { if (!out) out = spans.slice(0, i); } + else if (out) out.push(spans[i]); + } + return !out ? spans : out.length ? out : null; + } + function newHL(text, spans) { return spans ? {text: text, markedSpans: spans} : text; } + + function detachMarkedSpans(line) { + var spans = line.markedSpans; + if (!spans) return; + for (var i = 0; i < spans.length; ++i) { + var lines = spans[i].marker.lines; + var ix = indexOf(lines, line); + lines.splice(ix, 1); + } + line.markedSpans = null; + } + + function attachMarkedSpans(line, spans) { + if (!spans) return; + for (var i = 0; i < spans.length; ++i) + var marker = spans[i].marker.lines.push(line); + line.markedSpans = spans; + } + + // When measuring the position of the end of a line, different + // browsers require different approaches. If an empty span is added, + // many browsers report bogus offsets. Of those, some (Webkit, + // recent IE) will accept a space without moving the whole span to + // the next line when wrapping it, others work with a zero-width + // space. + var eolSpanContent = " "; + if (gecko || (ie && !ie_lt8)) eolSpanContent = "\u200b"; + else if (opera) eolSpanContent = ""; + + // Line objects. These hold state related to a line, including + // highlighting info (the styles array). + function Line(text, markedSpans) { + this.text = text; + this.height = 1; + attachMarkedSpans(this, markedSpans); + } + Line.prototype = { + update: function(text, markedSpans) { + this.text = text; + this.stateAfter = this.styles = null; + detachMarkedSpans(this); + attachMarkedSpans(this, markedSpans); + }, + // Run the given mode's parser over a line, update the styles + // array, which contains alternating fragments of text and CSS + // classes. + highlight: function(mode, state, tabSize) { + var stream = new StringStream(this.text, tabSize), st = this.styles || (this.styles = []); + var pos = st.length = 0; + if (this.text == "" && mode.blankLine) mode.blankLine(state); + while (!stream.eol()) { + var style = mode.token(stream, state), substr = stream.current(); + stream.start = stream.pos; + if (pos && st[pos-1] == style) { + st[pos-2] += substr; + } else if (substr) { + st[pos++] = substr; st[pos++] = style; + } + // Give up when line is ridiculously long + if (stream.pos > 5000) { + st[pos++] = this.text.slice(stream.pos); st[pos++] = null; + break; + } + } + }, + process: function(mode, state, tabSize) { + var stream = new StringStream(this.text, tabSize); + if (this.text == "" && mode.blankLine) mode.blankLine(state); + while (!stream.eol() && stream.pos <= 5000) { + mode.token(stream, state); + stream.start = stream.pos; + } + }, + // Fetch the parser token for a given character. Useful for hacks + // that want to inspect the mode state (say, for completion). + getTokenAt: function(mode, state, tabSize, ch) { + var txt = this.text, stream = new StringStream(txt, tabSize); + while (stream.pos < ch && !stream.eol()) { + stream.start = stream.pos; + var style = mode.token(stream, state); + } + return {start: stream.start, + end: stream.pos, + string: stream.current(), + className: style || null, + state: state}; + }, + indentation: function(tabSize) {return countColumn(this.text, null, tabSize);}, + // Produces an HTML fragment for the line, taking selection, + // marking, and highlighting into account. + getContent: function(tabSize, wrapAt, compensateForWrapping) { + var first = true, col = 0, specials = /[\t\u0000-\u0019\u200b\u2028\u2029\uFEFF]/g; + var pre = elt("pre"); + function span_(html, text, style) { + if (!text) return; + // Work around a bug where, in some compat modes, IE ignores leading spaces + if (first && ie && text.charAt(0) == " ") text = "\u00a0" + text.slice(1); + first = false; + if (!specials.test(text)) { + col += text.length; + var content = document.createTextNode(text); + } else { + var content = document.createDocumentFragment(), pos = 0; + while (true) { + specials.lastIndex = pos; + var m = specials.exec(text); + var skipped = m ? m.index - pos : text.length - pos; + if (skipped) { + content.appendChild(document.createTextNode(text.slice(pos, pos + skipped))); + col += skipped; + } + if (!m) break; + pos += skipped + 1; + if (m[0] == "\t") { + var tabWidth = tabSize - col % tabSize; + content.appendChild(elt("span", spaceStr(tabWidth), "cm-tab")); + col += tabWidth; + } else { + var token = elt("span", "\u2022", "cm-invalidchar"); + token.title = "\\u" + m[0].charCodeAt(0).toString(16); + content.appendChild(token); + col += 1; + } + } + } + if (style) html.appendChild(elt("span", [content], style)); + else html.appendChild(content); + } + var span = span_; + if (wrapAt != null) { + var outPos = 0, anchor = pre.anchor = elt("span"); + span = function(html, text, style) { + var l = text.length; + if (wrapAt >= outPos && wrapAt < outPos + l) { + var cut = wrapAt - outPos; + if (cut) { + span_(html, text.slice(0, cut), style); + // See comment at the definition of spanAffectsWrapping + if (compensateForWrapping) { + var view = text.slice(cut - 1, cut + 1); + if (spanAffectsWrapping.test(view)) html.appendChild(elt("wbr")); + else if (!ie_lt8 && /\w\w/.test(view)) html.appendChild(document.createTextNode("\u200d")); + } + } + html.appendChild(anchor); + span_(anchor, opera ? text.slice(cut, cut + 1) : text.slice(cut), style); + if (opera) span_(html, text.slice(cut + 1), style); + wrapAt--; + outPos += l; + } else { + outPos += l; + span_(html, text, style); + if (outPos == wrapAt && outPos == len) { + setTextContent(anchor, eolSpanContent); + html.appendChild(anchor); + } + // Stop outputting HTML when gone sufficiently far beyond measure + else if (outPos > wrapAt + 10 && /\s/.test(text)) span = function(){}; + } + }; + } + + var st = this.styles, allText = this.text, marked = this.markedSpans; + var len = allText.length; + function styleToClass(style) { + if (!style) return null; + return "cm-" + style.replace(/ +/g, " cm-"); + } + if (!allText && wrapAt == null) { + span(pre, " "); + } else if (!marked || !marked.length) { + for (var i = 0, ch = 0; ch < len; i+=2) { + var str = st[i], style = st[i+1], l = str.length; + if (ch + l > len) str = str.slice(0, len - ch); + ch += l; + span(pre, str, styleToClass(style)); + } + } else { + marked.sort(function(a, b) { return a.from - b.from; }); + var pos = 0, i = 0, text = "", style, sg = 0; + var nextChange = marked[0].from || 0, marks = [], markpos = 0; + var advanceMarks = function() { + var m; + while (markpos < marked.length && + ((m = marked[markpos]).from == pos || m.from == null)) { + if (m.marker.type == "range") marks.push(m); + ++markpos; + } + nextChange = markpos < marked.length ? marked[markpos].from : Infinity; + for (var i = 0; i < marks.length; ++i) { + var to = marks[i].to; + if (to == null) to = Infinity; + if (to == pos) marks.splice(i--, 1); + else nextChange = Math.min(to, nextChange); + } + }; + var m = 0; + while (pos < len) { + if (nextChange == pos) advanceMarks(); + var upto = Math.min(len, nextChange); + while (true) { + if (text) { + var end = pos + text.length; + var appliedStyle = style; + for (var j = 0; j < marks.length; ++j) { + var mark = marks[j]; + appliedStyle = (appliedStyle ? appliedStyle + " " : "") + mark.marker.style; + if (mark.marker.endStyle && mark.to === Math.min(end, upto)) appliedStyle += " " + mark.marker.endStyle; + if (mark.marker.startStyle && mark.from === pos) appliedStyle += " " + mark.marker.startStyle; + } + span(pre, end > upto ? text.slice(0, upto - pos) : text, appliedStyle); + if (end >= upto) {text = text.slice(upto - pos); pos = upto; break;} + pos = end; + } + text = st[i++]; style = styleToClass(st[i++]); + } + } + } + return pre; + }, + cleanUp: function() { + this.parent = null; + detachMarkedSpans(this); + } + }; + + // Data structure that holds the sequence of lines. + function LeafChunk(lines) { + this.lines = lines; + this.parent = null; + for (var i = 0, e = lines.length, height = 0; i < e; ++i) { + lines[i].parent = this; + height += lines[i].height; + } + this.height = height; + } + LeafChunk.prototype = { + chunkSize: function() { return this.lines.length; }, + remove: function(at, n, callbacks) { + for (var i = at, e = at + n; i < e; ++i) { + var line = this.lines[i]; + this.height -= line.height; + line.cleanUp(); + if (line.handlers) + for (var j = 0; j < line.handlers.length; ++j) callbacks.push(line.handlers[j]); + } + this.lines.splice(at, n); + }, + collapse: function(lines) { + lines.splice.apply(lines, [lines.length, 0].concat(this.lines)); + }, + insertHeight: function(at, lines, height) { + this.height += height; + this.lines = this.lines.slice(0, at).concat(lines).concat(this.lines.slice(at)); + for (var i = 0, e = lines.length; i < e; ++i) lines[i].parent = this; + }, + iterN: function(at, n, op) { + for (var e = at + n; at < e; ++at) + if (op(this.lines[at])) return true; + } + }; + function BranchChunk(children) { + this.children = children; + var size = 0, height = 0; + for (var i = 0, e = children.length; i < e; ++i) { + var ch = children[i]; + size += ch.chunkSize(); height += ch.height; + ch.parent = this; + } + this.size = size; + this.height = height; + this.parent = null; + } + BranchChunk.prototype = { + chunkSize: function() { return this.size; }, + remove: function(at, n, callbacks) { + this.size -= n; + for (var i = 0; i < this.children.length; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at < sz) { + var rm = Math.min(n, sz - at), oldHeight = child.height; + child.remove(at, rm, callbacks); + this.height -= oldHeight - child.height; + if (sz == rm) { this.children.splice(i--, 1); child.parent = null; } + if ((n -= rm) == 0) break; + at = 0; + } else at -= sz; + } + if (this.size - n < 25) { + var lines = []; + this.collapse(lines); + this.children = [new LeafChunk(lines)]; + this.children[0].parent = this; + } + }, + collapse: function(lines) { + for (var i = 0, e = this.children.length; i < e; ++i) this.children[i].collapse(lines); + }, + insert: function(at, lines) { + var height = 0; + for (var i = 0, e = lines.length; i < e; ++i) height += lines[i].height; + this.insertHeight(at, lines, height); + }, + insertHeight: function(at, lines, height) { + this.size += lines.length; + this.height += height; + for (var i = 0, e = this.children.length; i < e; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at <= sz) { + child.insertHeight(at, lines, height); + if (child.lines && child.lines.length > 50) { + while (child.lines.length > 50) { + var spilled = child.lines.splice(child.lines.length - 25, 25); + var newleaf = new LeafChunk(spilled); + child.height -= newleaf.height; + this.children.splice(i + 1, 0, newleaf); + newleaf.parent = this; + } + this.maybeSpill(); + } + break; + } + at -= sz; + } + }, + maybeSpill: function() { + if (this.children.length <= 10) return; + var me = this; + do { + var spilled = me.children.splice(me.children.length - 5, 5); + var sibling = new BranchChunk(spilled); + if (!me.parent) { // Become the parent node + var copy = new BranchChunk(me.children); + copy.parent = me; + me.children = [copy, sibling]; + me = copy; + } else { + me.size -= sibling.size; + me.height -= sibling.height; + var myIndex = indexOf(me.parent.children, me); + me.parent.children.splice(myIndex + 1, 0, sibling); + } + sibling.parent = me.parent; + } while (me.children.length > 10); + me.parent.maybeSpill(); + }, + iter: function(from, to, op) { this.iterN(from, to - from, op); }, + iterN: function(at, n, op) { + for (var i = 0, e = this.children.length; i < e; ++i) { + var child = this.children[i], sz = child.chunkSize(); + if (at < sz) { + var used = Math.min(n, sz - at); + if (child.iterN(at, used, op)) return true; + if ((n -= used) == 0) break; + at = 0; + } else at -= sz; + } + } + }; + + function getLineAt(chunk, n) { + while (!chunk.lines) { + for (var i = 0;; ++i) { + var child = chunk.children[i], sz = child.chunkSize(); + if (n < sz) { chunk = child; break; } + n -= sz; + } + } + return chunk.lines[n]; + } + function lineNo(line) { + if (line.parent == null) return null; + var cur = line.parent, no = indexOf(cur.lines, line); + for (var chunk = cur.parent; chunk; cur = chunk, chunk = chunk.parent) { + for (var i = 0; ; ++i) { + if (chunk.children[i] == cur) break; + no += chunk.children[i].chunkSize(); + } + } + return no; + } + function lineAtHeight(chunk, h) { + var n = 0; + outer: do { + for (var i = 0, e = chunk.children.length; i < e; ++i) { + var child = chunk.children[i], ch = child.height; + if (h < ch) { chunk = child; continue outer; } + h -= ch; + n += child.chunkSize(); + } + return n; + } while (!chunk.lines); + for (var i = 0, e = chunk.lines.length; i < e; ++i) { + var line = chunk.lines[i], lh = line.height; + if (h < lh) break; + h -= lh; + } + return n + i; + } + function heightAtLine(chunk, n) { + var h = 0; + outer: do { + for (var i = 0, e = chunk.children.length; i < e; ++i) { + var child = chunk.children[i], sz = child.chunkSize(); + if (n < sz) { chunk = child; continue outer; } + n -= sz; + h += child.height; + } + return h; + } while (!chunk.lines); + for (var i = 0; i < n; ++i) h += chunk.lines[i].height; + return h; + } + + // The history object 'chunks' changes that are made close together + // and at almost the same time into bigger undoable units. + function History() { + this.time = 0; + this.done = []; this.undone = []; + this.compound = 0; + this.closed = false; + } + History.prototype = { + addChange: function(start, added, old) { + this.undone.length = 0; + var time = +new Date, cur = lst(this.done), last = cur && lst(cur); + var dtime = time - this.time; + + if (cur && !this.closed && this.compound) { + cur.push({start: start, added: added, old: old}); + } else if (dtime > 400 || !last || this.closed || + last.start > start + old.length || last.start + last.added < start) { + this.done.push([{start: start, added: added, old: old}]); + this.closed = false; + } else { + var startBefore = Math.max(0, last.start - start), + endAfter = Math.max(0, (start + old.length) - (last.start + last.added)); + for (var i = startBefore; i > 0; --i) last.old.unshift(old[i - 1]); + for (var i = endAfter; i > 0; --i) last.old.push(old[old.length - i]); + if (startBefore) last.start = start; + last.added += added - (old.length - startBefore - endAfter); + } + this.time = time; + }, + startCompound: function() { + if (!this.compound++) this.closed = true; + }, + endCompound: function() { + if (!--this.compound) this.closed = true; + } + }; + + function stopMethod() {e_stop(this);} + // Ensure an event has a stop method. + function addStop(event) { + if (!event.stop) event.stop = stopMethod; + return event; + } + + function e_preventDefault(e) { + if (e.preventDefault) e.preventDefault(); + else e.returnValue = false; + } + function e_stopPropagation(e) { + if (e.stopPropagation) e.stopPropagation(); + else e.cancelBubble = true; + } + function e_stop(e) {e_preventDefault(e); e_stopPropagation(e);} + CodeMirror.e_stop = e_stop; + CodeMirror.e_preventDefault = e_preventDefault; + CodeMirror.e_stopPropagation = e_stopPropagation; + + function e_target(e) {return e.target || e.srcElement;} + function e_button(e) { + var b = e.which; + if (b == null) { + if (e.button & 1) b = 1; + else if (e.button & 2) b = 3; + else if (e.button & 4) b = 2; + } + if (mac && e.ctrlKey && b == 1) b = 3; + return b; + } + + // Allow 3rd-party code to override event properties by adding an override + // object to an event object. + function e_prop(e, prop) { + var overridden = e.override && e.override.hasOwnProperty(prop); + return overridden ? e.override[prop] : e[prop]; + } + + // Event handler registration. If disconnect is true, it'll return a + // function that unregisters the handler. + function connect(node, type, handler, disconnect) { + if (typeof node.addEventListener == "function") { + node.addEventListener(type, handler, false); + if (disconnect) return function() {node.removeEventListener(type, handler, false);}; + } else { + var wrapHandler = function(event) {handler(event || window.event);}; + node.attachEvent("on" + type, wrapHandler); + if (disconnect) return function() {node.detachEvent("on" + type, wrapHandler);}; + } + } + CodeMirror.connect = connect; + + function Delayed() {this.id = null;} + Delayed.prototype = {set: function(ms, f) {clearTimeout(this.id); this.id = setTimeout(f, ms);}}; + + var Pass = CodeMirror.Pass = {toString: function(){return "CodeMirror.Pass";}}; + + // Detect drag-and-drop + var dragAndDrop = function() { + // There is *some* kind of drag-and-drop support in IE6-8, but I + // couldn't get it to work yet. + if (ie_lt9) return false; + var div = elt('div'); + return "draggable" in div || "dragDrop" in div; + }(); + + // Feature-detect whether newlines in textareas are converted to \r\n + var lineSep = function () { + var te = elt("textarea"); + te.value = "foo\nbar"; + if (te.value.indexOf("\r") > -1) return "\r\n"; + return "\n"; + }(); + + // For a reason I have yet to figure out, some browsers disallow + // word wrapping between certain characters *only* if a new inline + // element is started between them. This makes it hard to reliably + // measure the position of things, since that requires inserting an + // extra span. This terribly fragile set of regexps matches the + // character combinations that suffer from this phenomenon on the + // various browsers. + var spanAffectsWrapping = /^$/; // Won't match any two-character string + if (gecko) spanAffectsWrapping = /$'/; + else if (safari) spanAffectsWrapping = /\-[^ \-?]|\?[^ !'\"\),.\-\/:;\?\]\}]/; + else if (chrome) spanAffectsWrapping = /\-[^ \-\.?]|\?[^ \-\.?\]\}:;!'\"\),\/]|[\.!\"#&%\)*+,:;=>\]|\}~][\(\{\[<]|\$'/; + + // Counts the column offset in a string, taking tabs into account. + // Used mostly to find indentation. + function countColumn(string, end, tabSize) { + if (end == null) { + end = string.search(/[^\s\u00a0]/); + if (end == -1) end = string.length; + } + for (var i = 0, n = 0; i < end; ++i) { + if (string.charAt(i) == "\t") n += tabSize - (n % tabSize); + else ++n; + } + return n; + } + + function eltOffset(node, screen) { + // Take the parts of bounding client rect that we are interested in so we are able to edit if need be, + // since the returned value cannot be changed externally (they are kept in sync as the element moves within the page) + try { var box = node.getBoundingClientRect(); box = { top: box.top, left: box.left }; } + catch(e) { box = {top: 0, left: 0}; } + if (!screen) { + // Get the toplevel scroll, working around browser differences. + if (window.pageYOffset == null) { + var t = document.documentElement || document.body.parentNode; + if (t.scrollTop == null) t = document.body; + box.top += t.scrollTop; box.left += t.scrollLeft; + } else { + box.top += window.pageYOffset; box.left += window.pageXOffset; + } + } + return box; + } + + function eltText(node) { + return node.textContent || node.innerText || node.nodeValue || ""; + } + + var spaceStrs = [""]; + function spaceStr(n) { + while (spaceStrs.length <= n) + spaceStrs.push(lst(spaceStrs) + " "); + return spaceStrs[n]; + } + + function lst(arr) { return arr[arr.length-1]; } + + function selectInput(node) { + if (ios) { // Mobile Safari apparently has a bug where select() is broken. + node.selectionStart = 0; + node.selectionEnd = node.value.length; + } else node.select(); + } + + // Operations on {line, ch} objects. + function posEq(a, b) {return a.line == b.line && a.ch == b.ch;} + function posLess(a, b) {return a.line < b.line || (a.line == b.line && a.ch < b.ch);} + function copyPos(x) {return {line: x.line, ch: x.ch};} + + function elt(tag, content, className, style) { + var e = document.createElement(tag); + if (className) e.className = className; + if (style) e.style.cssText = style; + if (typeof content == "string") setTextContent(e, content); + else if (content) for (var i = 0; i < content.length; ++i) e.appendChild(content[i]); + return e; + } + function removeChildren(e) { + e.innerHTML = ""; + return e; + } + function removeChildrenAndAdd(parent, e) { + removeChildren(parent).appendChild(e); + } + function setTextContent(e, str) { + if (ie_lt9) { + e.innerHTML = ""; + e.appendChild(document.createTextNode(str)); + } else e.textContent = str; + } + + // Used to position the cursor after an undo/redo by finding the + // last edited character. + function editEnd(from, to) { + if (!to) return 0; + if (!from) return to.length; + for (var i = from.length, j = to.length; i >= 0 && j >= 0; --i, --j) + if (from.charAt(i) != to.charAt(j)) break; + return j + 1; + } + + function indexOf(collection, elt) { + if (collection.indexOf) return collection.indexOf(elt); + for (var i = 0, e = collection.length; i < e; ++i) + if (collection[i] == elt) return i; + return -1; + } + var nonASCIISingleCaseWordChar = /[\u3040-\u309f\u30a0-\u30ff\u3400-\u4db5\u4e00-\u9fcc]/; + function isWordChar(ch) { + return /\w/.test(ch) || ch > "\x80" && + (ch.toUpperCase() != ch.toLowerCase() || nonASCIISingleCaseWordChar.test(ch)); + } + + // See if "".split is the broken IE version, if so, provide an + // alternative way to split lines. + var splitLines = "\n\nb".split(/\n/).length != 3 ? function(string) { + var pos = 0, result = [], l = string.length; + while (pos <= l) { + var nl = string.indexOf("\n", pos); + if (nl == -1) nl = string.length; + var line = string.slice(pos, string.charAt(nl - 1) == "\r" ? nl - 1 : nl); + var rt = line.indexOf("\r"); + if (rt != -1) { + result.push(line.slice(0, rt)); + pos += rt + 1; + } else { + result.push(line); + pos = nl + 1; + } + } + return result; + } : function(string){return string.split(/\r\n?|\n/);}; + CodeMirror.splitLines = splitLines; + + var hasSelection = window.getSelection ? function(te) { + try { return te.selectionStart != te.selectionEnd; } + catch(e) { return false; } + } : function(te) { + try {var range = te.ownerDocument.selection.createRange();} + catch(e) {} + if (!range || range.parentElement() != te) return false; + return range.compareEndPoints("StartToEnd", range) != 0; + }; + + CodeMirror.defineMode("null", function() { + return {token: function(stream) {stream.skipToEnd();}}; + }); + CodeMirror.defineMIME("text/plain", "null"); + + var keyNames = {3: "Enter", 8: "Backspace", 9: "Tab", 13: "Enter", 16: "Shift", 17: "Ctrl", 18: "Alt", + 19: "Pause", 20: "CapsLock", 27: "Esc", 32: "Space", 33: "PageUp", 34: "PageDown", 35: "End", + 36: "Home", 37: "Left", 38: "Up", 39: "Right", 40: "Down", 44: "PrintScrn", 45: "Insert", + 46: "Delete", 59: ";", 91: "Mod", 92: "Mod", 93: "Mod", 109: "-", 107: "=", 127: "Delete", + 186: ";", 187: "=", 188: ",", 189: "-", 190: ".", 191: "/", 192: "`", 219: "[", 220: "\\", + 221: "]", 222: "'", 63276: "PageUp", 63277: "PageDown", 63275: "End", 63273: "Home", + 63234: "Left", 63232: "Up", 63235: "Right", 63233: "Down", 63302: "Insert", 63272: "Delete"}; + CodeMirror.keyNames = keyNames; + (function() { + // Number keys + for (var i = 0; i < 10; i++) keyNames[i + 48] = String(i); + // Alphabetic keys + for (var i = 65; i <= 90; i++) keyNames[i] = String.fromCharCode(i); + // Function keys + for (var i = 1; i <= 12; i++) keyNames[i + 111] = keyNames[i + 63235] = "F" + i; + })(); + + CodeMirror.version = "2.38"; + + return CodeMirror; +})(); diff --git a/hugo/js/codemirror/mode/mysql/mysql.js b/hugo/js/codemirror/mode/mysql/mysql.js new file mode 100644 index 0000000..0224919 --- /dev/null +++ b/hugo/js/codemirror/mode/mysql/mysql.js @@ -0,0 +1,203 @@ +/* + * MySQL Mode for CodeMirror 2 by MySQL-Tools + * @author James Thorne (partydroid) + * @link http://github.com/partydroid/MySQL-Tools + * @link http://mysqltools.org + * @version 02/Jan/2012 +*/ +CodeMirror.defineMode("mysql", function(config) { + var indentUnit = config.indentUnit; + var curPunc; + + function wordRegexp(words) { + return new RegExp("^(?:" + words.join("|") + ")$", "i"); + } + var ops = wordRegexp(["str", "lang", "langmatches", "datatype", "bound", "sameterm", "isiri", "isuri", + "isblank", "isliteral", "union", "a"]); + var keywords = wordRegexp([ + ('ACCESSIBLE'),('ALTER'),('AS'),('BEFORE'),('BINARY'),('BY'),('CASE'),('CHARACTER'),('COLUMN'),('CONTINUE'),('CROSS'),('CURRENT_TIMESTAMP'),('DATABASE'),('DAY_MICROSECOND'),('DEC'),('DEFAULT'), + ('DESC'),('DISTINCT'),('DOUBLE'),('EACH'),('ENCLOSED'),('EXIT'),('FETCH'),('FLOAT8'),('FOREIGN'),('GRANT'),('HIGH_PRIORITY'),('HOUR_SECOND'),('IN'),('INNER'),('INSERT'),('INT2'),('INT8'), + ('INTO'),('JOIN'),('KILL'),('LEFT'),('LINEAR'),('LOCALTIME'),('LONG'),('LOOP'),('MATCH'),('MEDIUMTEXT'),('MINUTE_SECOND'),('NATURAL'),('NULL'),('OPTIMIZE'),('OR'),('OUTER'),('PRIMARY'), + ('RANGE'),('READ_WRITE'),('REGEXP'),('REPEAT'),('RESTRICT'),('RIGHT'),('SCHEMAS'),('SENSITIVE'),('SHOW'),('SPECIFIC'),('SQLSTATE'),('SQL_CALC_FOUND_ROWS'),('STARTING'),('TERMINATED'), + ('TINYINT'),('TRAILING'),('UNDO'),('UNLOCK'),('USAGE'),('UTC_DATE'),('VALUES'),('VARCHARACTER'),('WHERE'),('WRITE'),('ZEROFILL'),('ALL'),('AND'),('ASENSITIVE'),('BIGINT'),('BOTH'),('CASCADE'), + ('CHAR'),('COLLATE'),('CONSTRAINT'),('CREATE'),('CURRENT_TIME'),('CURSOR'),('DAY_HOUR'),('DAY_SECOND'),('DECLARE'),('DELETE'),('DETERMINISTIC'),('DIV'),('DUAL'),('ELSEIF'),('EXISTS'),('FALSE'), + ('FLOAT4'),('FORCE'),('FULLTEXT'),('HAVING'),('HOUR_MINUTE'),('IGNORE'),('INFILE'),('INSENSITIVE'),('INT1'),('INT4'),('INTERVAL'),('ITERATE'),('KEYS'),('LEAVE'),('LIMIT'),('LOAD'),('LOCK'), + ('LONGTEXT'),('MASTER_SSL_VERIFY_SERVER_CERT'),('MEDIUMINT'),('MINUTE_MICROSECOND'),('MODIFIES'),('NO_WRITE_TO_BINLOG'),('ON'),('OPTIONALLY'),('OUT'),('PRECISION'),('PURGE'),('READS'), + ('REFERENCES'),('RENAME'),('REQUIRE'),('REVOKE'),('SCHEMA'),('SELECT'),('SET'),('SPATIAL'),('SQLEXCEPTION'),('SQL_BIG_RESULT'),('SSL'),('TABLE'),('TINYBLOB'),('TO'),('TRUE'),('UNIQUE'), + ('UPDATE'),('USING'),('UTC_TIMESTAMP'),('VARCHAR'),('WHEN'),('WITH'),('YEAR_MONTH'),('ADD'),('ANALYZE'),('ASC'),('BETWEEN'),('BLOB'),('CALL'),('CHANGE'),('CHECK'),('CONDITION'),('CONVERT'), + ('CURRENT_DATE'),('CURRENT_USER'),('DATABASES'),('DAY_MINUTE'),('DECIMAL'),('DELAYED'),('DESCRIBE'),('DISTINCTROW'),('DROP'),('ELSE'),('ESCAPED'),('EXPLAIN'),('FLOAT'),('FOR'),('FROM'), + ('GROUP'),('HOUR_MICROSECOND'),('IF'),('INDEX'),('INOUT'),('INT'),('INT3'),('INTEGER'),('IS'),('KEY'),('LEADING'),('LIKE'),('LINES'),('LOCALTIMESTAMP'),('LONGBLOB'),('LOW_PRIORITY'), + ('MEDIUMBLOB'),('MIDDLEINT'),('MOD'),('NOT'),('NUMERIC'),('OPTION'),('ORDER'),('OUTFILE'),('PROCEDURE'),('READ'),('REAL'),('RELEASE'),('REPLACE'),('RETURN'),('RLIKE'),('SECOND_MICROSECOND'), + ('SEPARATOR'),('SMALLINT'),('SQL'),('SQLWARNING'),('SQL_SMALL_RESULT'),('STRAIGHT_JOIN'),('THEN'),('TINYTEXT'),('TRIGGER'),('UNION'),('UNSIGNED'),('USE'),('UTC_TIME'),('VARBINARY'),('VARYING'), + ('WHILE'),('XOR'),('FULL'),('COLUMNS'),('MIN'),('MAX'),('STDEV'),('COUNT') + ]); + var operatorChars = /[*+\-<>=&|]/; + + function tokenBase(stream, state) { + var ch = stream.next(); + curPunc = null; + if (ch == "$" || ch == "?") { + stream.match(/^[\w\d]*/); + return "variable-2"; + } + else if (ch == "<" && !stream.match(/^[\s\u00a0=]/, false)) { + stream.match(/^[^\s\u00a0>]*>?/); + return "atom"; + } + else if (ch == "\"" || ch == "'") { + state.tokenize = tokenLiteral(ch); + return state.tokenize(stream, state); + } + else if (ch == "`") { + state.tokenize = tokenOpLiteral(ch); + return state.tokenize(stream, state); + } + else if (/[{}\(\),\.;\[\]]/.test(ch)) { + curPunc = ch; + return null; + } + else if (ch == "-" && stream.eat("-")) { + stream.skipToEnd(); + return "comment"; + } + else if (ch == "/" && stream.eat("*")) { + state.tokenize = tokenComment; + return state.tokenize(stream, state); + } + else if (operatorChars.test(ch)) { + stream.eatWhile(operatorChars); + return null; + } + else if (ch == ":") { + stream.eatWhile(/[\w\d\._\-]/); + return "atom"; + } + else { + stream.eatWhile(/[_\w\d]/); + if (stream.eat(":")) { + stream.eatWhile(/[\w\d_\-]/); + return "atom"; + } + var word = stream.current(), type; + if (ops.test(word)) + return null; + else if (keywords.test(word)) + return "keyword"; + else + return "variable"; + } + } + + function tokenLiteral(quote) { + return function(stream, state) { + var escaped = false, ch; + while ((ch = stream.next()) != null) { + if (ch == quote && !escaped) { + state.tokenize = tokenBase; + break; + } + escaped = !escaped && ch == "\\"; + } + return "string"; + }; + } + + function tokenOpLiteral(quote) { + return function(stream, state) { + var escaped = false, ch; + while ((ch = stream.next()) != null) { + if (ch == quote && !escaped) { + state.tokenize = tokenBase; + break; + } + escaped = !escaped && ch == "\\"; + } + return "variable-2"; + }; + } + + function tokenComment(stream, state) { + for (;;) { + if (stream.skipTo("*")) { + stream.next(); + if (stream.eat("/")) { + state.tokenize = tokenBase; + break; + } + } else { + stream.skipToEnd(); + break; + } + } + return "comment"; + } + + + function pushContext(state, type, col) { + state.context = {prev: state.context, indent: state.indent, col: col, type: type}; + } + function popContext(state) { + state.indent = state.context.indent; + state.context = state.context.prev; + } + + return { + startState: function(base) { + return {tokenize: tokenBase, + context: null, + indent: 0, + col: 0}; + }, + + token: function(stream, state) { + if (stream.sol()) { + if (state.context && state.context.align == null) state.context.align = false; + state.indent = stream.indentation(); + } + if (stream.eatSpace()) return null; + var style = state.tokenize(stream, state); + + if (style != "comment" && state.context && state.context.align == null && state.context.type != "pattern") { + state.context.align = true; + } + + if (curPunc == "(") pushContext(state, ")", stream.column()); + else if (curPunc == "[") pushContext(state, "]", stream.column()); + else if (curPunc == "{") pushContext(state, "}", stream.column()); + else if (/[\]\}\)]/.test(curPunc)) { + while (state.context && state.context.type == "pattern") popContext(state); + if (state.context && curPunc == state.context.type) popContext(state); + } + else if (curPunc == "." && state.context && state.context.type == "pattern") popContext(state); + else if (/atom|string|variable/.test(style) && state.context) { + if (/[\}\]]/.test(state.context.type)) + pushContext(state, "pattern", stream.column()); + else if (state.context.type == "pattern" && !state.context.align) { + state.context.align = true; + state.context.col = stream.column(); + } + } + + return style; + }, + + indent: function(state, textAfter) { + var firstChar = textAfter && textAfter.charAt(0); + var context = state.context; + if (/[\]\}]/.test(firstChar)) + while (context && context.type == "pattern") context = context.prev; + + var closing = context && firstChar == context.type; + if (!context) + return 0; + else if (context.type == "pattern") + return context.col; + else if (context.align) + return context.col + (closing ? 0 : 1); + else + return context.indent + (closing ? 0 : indentUnit); + } + }; +}); + +CodeMirror.defineMIME("text/x-mysql", "mysql"); diff --git a/hugo/js/common.js b/hugo/js/common.js new file mode 100644 index 0000000..02dd342 --- /dev/null +++ b/hugo/js/common.js @@ -0,0 +1,296 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Functionality for communicating with the querywindow + */ +$(function () { + /** + * Event handler for click on the open query window link + * in the top menu of the navigation panel + */ + $('#pma_open_querywindow').click(function (event) { + event.preventDefault(); + PMA_querywindow.focus(); + }); +}); + +/** + * Holds common parameters such as server, db, table, etc + * + * The content for this is normally loaded from Header.class.php or + * Response.class.php and executed by ajax.js + */ +var PMA_commonParams = (function () { + /** + * @var hash params An associative array of key value pairs + * @access private + */ + var params = {}; + // The returned object is the public part of the module + return { + /** + * Saves all the key value pair that + * are provided in the input array + * + * @param hash obj The input array + * + * @return void + */ + setAll: function (obj) { + var reload = false; + var updateNavigation = false; + for (var i in obj) { + if (params[i] !== undefined && params[i] !== obj[i]) { + reload = true; + } + if (i == 'db' || i == 'table') { + updateNavigation = true; + } + params[i] = obj[i]; + } + if (updateNavigation) { + PMA_showCurrentNavigation(); + } + if (reload) { + PMA_querywindow.refresh(); + } + }, + /** + * Retrieves a value given its key + * Returns empty string for undefined values + * + * @param string name The key + * + * @return string + */ + get: function (name) { + return params[name] || ''; + }, + /** + * Saves a single key value pair + * + * @param string name The key + * @param string value The value + * + * @return self For chainability + */ + set: function (name, value) { + if (params[name] !== undefined && params[name] !== value) { + PMA_querywindow.refresh(); + } + params[name] = value; + if (name == 'db' || name == 'table') { + PMA_showCurrentNavigation(); + } + return this; + }, + /** + * Returns the url query string using the saved parameters + * + * @return string + */ + getUrlQuery: function () { + return $.sprintf( + '?%s&server=%s&db=%s&table=%s', + this.get('common_query'), + encodeURIComponent(this.get('server')), + encodeURIComponent(this.get('db')), + encodeURIComponent(this.get('table')) + ); + } + }; +})(); + +/** + * Holds common parameters such as server, db, table, etc + * + * The content for this is normally loaded from Header.class.php or + * Response.class.php and executed by ajax.js + */ +var PMA_commonActions = { + /** + * Saves the database name when it's changed + * and reloads the query window, if necessary + * + * @param string new_db The name of the new database + * + * @return void + */ + setDb: function (new_db) { + if (new_db != PMA_commonParams.get('db')) { + PMA_commonParams.setAll({'db': new_db, 'table': ''}); + } + }, + /** + * Opens a database in the main part of the page + * + * @param string new_db The name of the new database + * + * @return void + */ + openDb: function (new_db) { + PMA_commonParams + .set('db', new_db) + .set('table', ''); + PMA_querywindow.refresh(); + this.refreshMain( + PMA_commonParams.get('opendb_url') + ); + }, + /** + * Refreshes the main frame + * + * @param mixed url Undefined to refresh to the same page + * String to go to a different page, e.g: 'index.php' + * + * @return void + */ + refreshMain: function (url, callback) { + if (! url) { + url = $('#selflink a').attr('href'); + url = url.substring(0, url.indexOf('?')); + } + url += PMA_commonParams.getUrlQuery(); + $('<a />', {href: url}) + .appendTo('body') + .click() + .remove(); + AJAX._callback = callback; + } +}; + +/** + * Common functions used for communicating with the querywindow + */ +var PMA_querywindow = (function ($, window) { + /** + * @var Object querywindow Reference to the window + * object of the querywindow + * @access private + */ + var querywindow = {}; + /** + * @var string queryToLoad Stores the SQL query that is to be displayed + * in the querywindow when it is ready + * @access private + */ + var queryToLoad = ''; + // The returned object is the public part of the module + return { + /** + * Opens the query window + * + * @param mixed url Undefined to open the default page + * String to go to a different + * + * @return void + */ + open: function (url, sql_query) { + if (! url) { + url = 'querywindow.php' + PMA_commonParams.getUrlQuery(); + } + if (sql_query) { + url += '&sql_query=' + encodeURIComponent(sql_query); + } + + if (! querywindow.closed && querywindow.location) { + var href = querywindow.location.href; + if (href != url + && href != PMA_commonParams.get('pma_absolute_uri') + url + ) { + if (PMA_commonParams.get('safari_browser')) { + querywindow.location.href = targeturl; + } else { + querywindow.location.replace(targeturl); + } + querywindow.focus(); + } + } else { + querywindow = window.open( + url + '&init=1', + '', + 'toolbar=0,location=0,directories=0,status=1,' + + 'menubar=0,scrollbars=yes,resizable=yes,' + + 'width=' + PMA_commonParams.get('querywindow_width') + ',' + + 'height=' + PMA_commonParams.get('querywindow_height') + ); + } + if (! querywindow.opener) { + querywindow.opener = window.window; + } + if (window.focus) { + querywindow.focus(); + } + }, + /** + * Opens, if necessary, focuses the query window + * and displays an SQL query. + * + * @param string sql_query The SQL query to display in + * the query window + * + * @return void + */ + focus: function (sql_query) { + if (! querywindow || querywindow.closed || ! querywindow.location) { + // we need first to open the window and cannot pass the query with it + // as we dont know if the query exceeds max url length + queryToLoad = sql_query; + this.open(false, sql_query); + } else { + //var querywindow = querywindow; + var hiddenqueryform = querywindow + .document + .getElementById('hiddenqueryform'); + if (hiddenqueryform.querydisplay_tab != 'sql' ) { + hiddenqueryform.querydisplay_tab.value = "sql"; + hiddenqueryform.sql_query.value = sql_query; + $(hiddenqueryform).addClass('disableAjax'); + hiddenqueryform.submit(); + querywindow.focus(); + } else { + querywindow.focus(); + } + } + }, + /** + * Refreshes the query window given a url + * + * @param string url Where to go to + * + * @return void + */ + refresh: function (url) { + if (! querywindow.closed && querywindow.location) { + var $form = $(querywindow.document).find('#sqlqueryform'); + if ($form.find('#checkbox_lock:checked').length == 0) { + PMA_querywindow.open(url); + } + } + }, + /** + * Reloads the query window given the details + * of a db, a table and an sql_query + * + * @param string db The name of the database + * @param string table The name of the table + * @param string sql_query The SQL query to be displayed + * + * @return void + */ + reload: function (db, table, sql_query) { + if (! querywindow.closed && querywindow.location) { + var $form = $(querywindow.document).find('#sqlqueryform'); + if ($form.find('#checkbox_lock:checked').length == 0) { + var $hiddenform = $(querywindow.document) + .find('#hiddenqueryform'); + $hiddenform.find('input[name=db]').val(db); + $hiddenform.find('input[name=table]').val(table); + if (sql_query) { + $hiddenform.find('input[name=sql_query]').val(sql_query); + } + $hiddenform.addClass('disableAjax').submit(); + } + } + } + }; +})(jQuery, window); diff --git a/hugo/js/config.js b/hugo/js/config.js new file mode 100644 index 0000000..fdd0fc4 --- /dev/null +++ b/hugo/js/config.js @@ -0,0 +1,776 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Functions used in configuration forms and on user preferences pages + */ + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('config.js', function() { + $('input[id], select[id], textarea[id]').unbind('change').unbind('keyup'); + $('input[type=button][name=submit_reset]').unbind('click'); + $('div.tabs_contents').undelegate(); + $('#import_local_storage, #export_local_storage').unbind('click'); + $('form.prefs-form').unbind('change').unbind('submit'); + $('div.click-hide-message').die('click'); + $('#prefs_autoload').find('a').unbind('click'); +}); + +AJAX.registerOnload('config.js', function() { + $('#topmenu2').find('li.active a').attr('rel', 'samepage'); + $('#topmenu2').find('li:not(.active) a').attr('rel', 'newpage'); +}); + +// default values for fields +var defaultValues = {}; + +/** + * Returns field type + * + * @param {Element} field + */ +function getFieldType(field) +{ + field = $(field); + var tagName = field.prop('tagName'); + if (tagName == 'INPUT') { + return field.attr('type'); + } else if (tagName == 'SELECT') { + return 'select'; + } else if (tagName == 'TEXTAREA') { + return 'text'; + } + return ''; +} + +/** + * Sets field value + * + * value must be of type: + * o undefined (omitted) - restore default value (form default, not PMA default) + * o String - if field_type is 'text' + * o boolean - if field_type is 'checkbox' + * o Array of values - if field_type is 'select' + * + * @param {Element} field + * @param {String} field_type see {@link #getFieldType} + * @param {String|Boolean} [value] + */ +function setFieldValue(field, field_type, value) +{ + field = $(field); + switch (field_type) { + case 'text': + //TODO: replace to .val() + field.attr('value', (value != undefined ? value : field.attr('defaultValue'))); + break; + case 'checkbox': + //TODO: replace to .prop() + field.attr('checked', (value != undefined ? value : field.attr('defaultChecked'))); + break; + case 'select': + var options = field.prop('options'); + var i, imax = options.length; + if (value == undefined) { + for (i = 0; i < imax; i++) { + options[i].selected = options[i].defaultSelected; + } + } else { + for (i = 0; i < imax; i++) { + options[i].selected = (value.indexOf(options[i].value) != -1); + } + } + break; + } + markField(field); +} + +/** + * Gets field value + * + * Will return one of: + * o String - if type is 'text' + * o boolean - if type is 'checkbox' + * o Array of values - if type is 'select' + * + * @param {Element} field + * @param {String} field_type returned by {@link #getFieldType} + * @type Boolean|String|String[] + */ +function getFieldValue(field, field_type) +{ + field = $(field); + switch (field_type) { + case 'text': + return field.prop('value'); + case 'checkbox': + return field.prop('checked'); + case 'select': + var options = field.prop('options'); + var i, imax = options.length, items = []; + for (i = 0; i < imax; i++) { + if (options[i].selected) { + items.push(options[i].value); + } + } + return items; + } + return null; +} + +/** + * Returns values for all fields in fieldsets + */ +function getAllValues() +{ + var elements = $('fieldset input, fieldset select, fieldset textarea'); + var values = {}; + var type, value; + for (var i = 0; i < elements.length; i++) { + type = getFieldType(elements[i]); + value = getFieldValue(elements[i], type); + if (typeof value != 'undefined') { + // we only have single selects, fatten array + if (type == 'select') { + value = value[0]; + } + values[elements[i].name] = value; + } + } + return values; +} + +/** + * Checks whether field has its default value + * + * @param {Element} field + * @param {String} type + * @return boolean + */ +function checkFieldDefault(field, type) +{ + field = $(field); + var field_id = field.attr('id'); + if (typeof defaultValues[field_id] == 'undefined') { + return true; + } + var isDefault = true; + var currentValue = getFieldValue(field, type); + if (type != 'select') { + isDefault = currentValue == defaultValues[field_id]; + } else { + // compare arrays, will work for our representation of select values + if (currentValue.length != defaultValues[field_id].length) { + isDefault = false; + } + else { + for (var i = 0; i < currentValue.length; i++) { + if (currentValue[i] != defaultValues[field_id][i]) { + isDefault = false; + break; + } + } + } + } + return isDefault; +} + +/** + * Returns element's id prefix + * @param {Element} element + */ +function getIdPrefix(element) +{ + return $(element).attr('id').replace(/[^-]+$/, ''); +} + +// ------------------------------------------------------------------ +// Form validation and field operations +// + +// form validator assignments +var validate = {}; + +// form validator list +var validators = { + // regexp: numeric value + _regexp_numeric: /^[0-9]+$/, + // regexp: extract parts from PCRE expression + _regexp_pcre_extract: /(.)(.*)\1(.*)?/, + /** + * Validates positive number + * + * @param {boolean} isKeyUp + */ + validate_positive_number: function (isKeyUp) { + if (isKeyUp && this.value == '') { + return true; + } + var result = this.value != '0' && validators._regexp_numeric.test(this.value); + return result ? true : PMA_messages['error_nan_p']; + }, + /** + * Validates non-negative number + * + * @param {boolean} isKeyUp + */ + validate_non_negative_number: function (isKeyUp) { + if (isKeyUp && this.value == '') { + return true; + } + var result = validators._regexp_numeric.test(this.value); + return result ? true : PMA_messages['error_nan_nneg']; + }, + /** + * Validates port number + * + * @param {boolean} isKeyUp + */ + validate_port_number: function(isKeyUp) { + if (this.value == '') { + return true; + } + var result = validators._regexp_numeric.test(this.value) && this.value != '0'; + return result && this.value <= 65535 ? true : PMA_messages['error_incorrect_port']; + }, + /** + * Validates value according to given regular expression + * + * @param {boolean} isKeyUp + * @param {string} regexp + */ + validate_by_regex: function(isKeyUp, regexp) { + if (isKeyUp && this.value == '') { + return true; + } + // convert PCRE regexp + var parts = regexp.match(validators._regexp_pcre_extract); + var valid = this.value.match(new RegExp(parts[2], parts[3])) != null; + return valid ? true : PMA_messages['error_invalid_value']; + }, + /** + * Validates upper bound for numeric inputs + * + * @param {boolean} isKeyUp + * @param {int} max_value + */ + validate_upper_bound: function(isKeyUp, max_value) { + var val = parseInt(this.value); + if (isNaN(val)) { + return true; + } + return val <= max_value ? true : $.sprintf(PMA_messages['error_value_lte'], max_value); + }, + // field validators + _field: { + }, + // fieldset validators + _fieldset: { + } +}; + +/** + * Registers validator for given field + * + * @param {String} id field id + * @param {String} type validator (key in validators object) + * @param {boolean} onKeyUp whether fire on key up + * @param {Array} params validation function parameters + */ +function validateField(id, type, onKeyUp, params) +{ + if (typeof validators[type] == 'undefined') { + return; + } + if (typeof validate[id] == 'undefined') { + validate[id] = []; + } + validate[id].push([type, params, onKeyUp]); +} + +/** + * Returns valdiation functions associated with form field + * + * @param {String} field_id form field id + * @param {boolean} onKeyUpOnly see validateField + * @type Array + * @return array of [function, paramseters to be passed to function] + */ +function getFieldValidators(field_id, onKeyUpOnly) +{ + // look for field bound validator + var name = field_id.match(/[^-]+$/)[0]; + if (typeof validators._field[name] != 'undefined') { + return [[validators._field[name], null]]; + } + + // look for registered validators + var functions = []; + if (typeof validate[field_id] != 'undefined') { + // validate[field_id]: array of [type, params, onKeyUp] + for (var i = 0, imax = validate[field_id].length; i < imax; i++) { + if (onKeyUpOnly && !validate[field_id][i][2]) { + continue; + } + functions.push([validators[validate[field_id][i][0]], validate[field_id][i][1]]); + } + } + + return functions; +} + +/** + * Displays errors for given form fields + * + * WARNING: created DOM elements must be identical with the ones made by + * display_input() in FormDisplay.tpl.php! + * + * @param {Object} error_list list of errors in the form {field id: error array} + */ +function displayErrors(error_list) +{ + for (var field_id in error_list) { + var errors = error_list[field_id]; + var field = $('#'+field_id); + var isFieldset = field.attr('tagName') == 'FIELDSET'; + var errorCnt = isFieldset + ? field.find('dl.errors') + : field.siblings('.inline_errors'); + + // remove empty errors (used to clear error list) + errors = $.grep(errors, function(item) { + return item != ''; + }); + + // CSS error class + if (!isFieldset) { + // checkboxes uses parent <span> for marking + var fieldMarker = (field.attr('type') == 'checkbox') ? field.parent() : field; + fieldMarker[errors.length ? 'addClass' : 'removeClass']('field-error'); + } + + if (errors.length) { + // if error container doesn't exist, create it + if (errorCnt.length == 0) { + if (isFieldset) { + errorCnt = $('<dl class="errors" />'); + field.find('table').before(errorCnt); + } else { + errorCnt = $('<dl class="inline_errors" />'); + field.closest('td').append(errorCnt); + } + } + + var html = ''; + for (var i = 0, imax = errors.length; i < imax; i++) { + html += '<dd>' + errors[i] + '</dd>'; + } + errorCnt.html(html); + } else if (errorCnt !== null) { + // remove useless error container + errorCnt.remove(); + } + } +} + +/** + * Validates fieldset and puts errors in 'errors' object + * + * @param {Element} fieldset + * @param {boolean} isKeyUp + * @param {Object} errors + */ +function validate_fieldset(fieldset, isKeyUp, errors) +{ + fieldset = $(fieldset); + if (fieldset.length && typeof validators._fieldset[fieldset.attr('id')] != 'undefined') { + var fieldset_errors = validators._fieldset[fieldset.attr('id')].apply(fieldset[0], [isKeyUp]); + for (var field_id in fieldset_errors) { + if (typeof errors[field_id] == 'undefined') { + errors[field_id] = []; + } + if (typeof fieldset_errors[field_id] == 'string') { + fieldset_errors[field_id] = [fieldset_errors[field_id]]; + } + $.merge(errors[field_id], fieldset_errors[field_id]); + } + } +} + +/** + * Validates form field and puts errors in 'errors' object + * + * @param {Element} field + * @param {boolean} isKeyUp + * @param {Object} errors + */ +function validate_field(field, isKeyUp, errors) +{ + field = $(field); + var field_id = field.attr('id'); + errors[field_id] = []; + var functions = getFieldValidators(field_id, isKeyUp); + for (var i = 0; i < functions.length; i++) { + var args = functions[i][1] != null + ? functions[i][1].slice(0) + : []; + args.unshift(isKeyUp); + var result = functions[i][0].apply(field[0], args); + if (result !== true) { + if (typeof result == 'string') { + result = [result]; + } + $.merge(errors[field_id], result); + } + } +} + +/** + * Validates form field and parent fieldset + * + * @param {Element} field + * @param {boolean} isKeyUp + */ +function validate_field_and_fieldset(field, isKeyUp) +{ + field = $(field); + var errors = {}; + validate_field(field, isKeyUp, errors); + validate_fieldset(field.closest('fieldset'), isKeyUp, errors); + displayErrors(errors); +} + +/** + * Marks field depending on its value (system default or custom) + * + * @param {Element} field + */ +function markField(field) +{ + field = $(field); + var type = getFieldType(field); + var isDefault = checkFieldDefault(field, type); + + // checkboxes uses parent <span> for marking + var fieldMarker = (type == 'checkbox') ? field.parent() : field; + setRestoreDefaultBtn(field, !isDefault); + fieldMarker[isDefault ? 'removeClass' : 'addClass']('custom'); +} + +/** + * Enables or disables the "restore default value" button + * + * @param {Element} field + * @param {boolean} display + */ +function setRestoreDefaultBtn(field, display) +{ + var el = $(field).closest('td').find('.restore-default img'); + el[display ? 'show' : 'hide'](); +} + +AJAX.registerOnload('config.js', function() { + // register validators and mark custom values + var elements = $('input[id], select[id], textarea[id]'); + $('input[id], select[id], textarea[id]').each(function(){ + markField(this); + var el = $(this); + el.bind('change', function() { + validate_field_and_fieldset(this, false); + markField(this); + }); + var tagName = el.attr('tagName'); + // text fields can be validated after each change + if (tagName == 'INPUT' && el.attr('type') == 'text') { + el.keyup(function() { + validate_field_and_fieldset(el, true); + markField(el); + }); + } + // disable textarea spellcheck + if (tagName == 'TEXTAREA') { + el.attr('spellcheck', false); + } + }); + + // check whether we've refreshed a page and browser remembered modified + // form values + var check_page_refresh = $('#check_page_refresh'); + if (check_page_refresh.length == 0 || check_page_refresh.val() == '1') { + // run all field validators + var errors = {}; + for (var i = 0; i < elements.length; i++) { + validate_field(elements[i], false, errors); + } + // run all fieldset validators + $('fieldset').each(function(){ + validate_fieldset(this, false, errors); + }); + + displayErrors(errors); + } else if (check_page_refresh) { + check_page_refresh.val('1'); + } +}); + +// +// END: Form validation and field operations +// ------------------------------------------------------------------ + +// ------------------------------------------------------------------ +// Tabbed forms +// + +/** + * Sets active tab + * + * @param {String} tab_id + */ +function setTab(tab_id) +{ + $('ul.tabs li').removeClass('active').find('a[href=#' + tab_id + ']').parent().addClass('active'); + $('div.tabs_contents fieldset').hide().filter('#' + tab_id).show(); + location.hash = 'tab_' + tab_id; + $('form.config-form input[name=tab_hash]').val(location.hash); +} + +AJAX.registerOnload('config.js', function() { + var tabs = $('ul.tabs'); + if (!tabs.length) { + return; + } + // add tabs events and activate one tab (the first one or indicated by location hash) + tabs.find('a') + .click(function(e) { + e.preventDefault(); + setTab($(this).attr('href').substr(1)); + }) + .filter(':first') + .parent() + .addClass('active'); + $('div.tabs_contents fieldset').hide().filter(':first').show(); + + // tab links handling, check each 200ms + // (works with history in FF, further browser support here would be an overkill) + var prev_hash; + var tab_check_fnc = function() { + if (location.hash != prev_hash) { + prev_hash = location.hash; + if (location.hash.match(/^#tab_.+/) && $('#' + location.hash.substr(5)).length) { + setTab(location.hash.substr(5)); + } + } + }; + tab_check_fnc(); + setInterval(tab_check_fnc, 200); +}); + +// +// END: Tabbed forms +// ------------------------------------------------------------------ + +// ------------------------------------------------------------------ +// Form reset buttons +// + +AJAX.registerOnload('config.js', function() { + $('input[type=button][name=submit_reset]').click(function() { + var fields = $(this).closest('fieldset').find('input, select, textarea'); + for (var i = 0, imax = fields.length; i < imax; i++) { + setFieldValue(fields[i], getFieldType(fields[i])); + } + }); +}); + +// +// END: Form reset buttons +// ------------------------------------------------------------------ + +// ------------------------------------------------------------------ +// "Restore default" and "set value" buttons +// + +/** + * Restores field's default value + * + * @param {String} field_id + */ +function restoreField(field_id) +{ + var field = $('#'+field_id); + if (field.length == 0 || defaultValues[field_id] == undefined) { + return; + } + setFieldValue(field, getFieldType(field), defaultValues[field_id]); +} + +AJAX.registerOnload('config.js', function() { + $('div.tabs_contents') + .delegate('.restore-default, .set-value', 'mouseenter', function(){$(this).css('opacity', 1)}) + .delegate('.restore-default, .set-value', 'mouseleave', function(){$(this).css('opacity', 0.25)}) + .delegate('.restore-default, .set-value', 'click', function(e) { + e.preventDefault(); + var href = $(this).attr('href'); + var field_sel; + if ($(this).hasClass('restore-default')) { + field_sel = href; + restoreField(field_sel.substr(1)); + } else { + field_sel = href.match(/^[^=]+/)[0]; + var value = href.match(/=(.+)$/)[1]; + setFieldValue($(field_sel), 'text', value); + } + $(field_sel).trigger('change'); + }) + .find('.restore-default, .set-value') + // inline-block for IE so opacity inheritance works + .css({display: 'inline-block', opacity: 0.25}); +}); + +// +// END: "Restore default" and "set value" buttons +// ------------------------------------------------------------------ + +// ------------------------------------------------------------------ +// User preferences import/export +// + +AJAX.registerOnload('config.js', function() { + offerPrefsAutoimport(); + var radios = $('#import_local_storage, #export_local_storage'); + if (!radios.length) { + return; + } + + // enable JavaScript dependent fields + radios + .prop('disabled', false) + .add('#export_text_file, #import_text_file') + .click(function(){ + var enable_id = $(this).attr('id'); + var disable_id = enable_id.match(/local_storage$/) + ? enable_id.replace(/local_storage$/, 'text_file') + : enable_id.replace(/text_file$/, 'local_storage'); + $('#opts_'+disable_id).addClass('disabled').find('input').prop('disabled', true); + $('#opts_'+enable_id).removeClass('disabled').find('input').prop('disabled', false); + }); + + // detect localStorage state + var ls_supported = window.localStorage || false; + var ls_exists = ls_supported ? (window.localStorage['config'] || false) : false; + $('div.localStorage-'+(ls_supported ? 'un' : '')+'supported').hide(); + $('div.localStorage-'+(ls_exists ? 'empty' : 'exists')).hide(); + if (ls_exists) { + updatePrefsDate(); + } + $('form.prefs-form').change(function(){ + var form = $(this); + var disabled = false; + if (!ls_supported) { + disabled = form.find('input[type=radio][value$=local_storage]').prop('checked'); + } else if (!ls_exists && form.attr('name') == 'prefs_import' + && $('#import_local_storage')[0].checked) { + disabled = true; + } + form.find('input[type=submit]').prop('disabled', disabled); + }).submit(function(e) { + var form = $(this); + if (form.attr('name') == 'prefs_export' && $('#export_local_storage')[0].checked) { + e.preventDefault(); + // use AJAX to read JSON settings and save them + savePrefsToLocalStorage(form); + } else if (form.attr('name') == 'prefs_import' && $('#import_local_storage')[0].checked) { + // set 'json' input and submit form + form.find('input[name=json]').val(window.localStorage['config']); + } + }); + + $('div.click-hide-message').live('click', function(){ + $(this) + .hide() + .parent('.group') + .css('height', '') + .next('form') + .show(); + }); +}); + +/** + * Saves user preferences to localStorage + * + * @param {Element} form + */ +function savePrefsToLocalStorage(form) +{ + form = $(form); + var submit = form.find('input[type=submit]'); + submit.prop('disabled', true); + $.ajax({ + url: 'prefs_manage.php', + cache: false, + type: 'POST', + data: { + ajax_request: true, + token: form.find('input[name=token]').val(), + submit_get_json: true + }, + success: function(response) { + window.localStorage['config'] = response.prefs; + window.localStorage['config_mtime'] = response.mtime; + window.localStorage['config_mtime_local'] = (new Date()).toUTCString(); + updatePrefsDate(); + $('div.localStorage-empty').hide(); + $('div.localStorage-exists').show(); + var group = form.parent('.group'); + group.css('height', group.height() + 'px'); + form.hide('fast'); + form.prev('.click-hide-message').show('fast'); + }, + complete: function() { + submit.prop('disabled', false); + } + }); +} + +/** + * Updates preferences timestamp in Import form + */ +function updatePrefsDate() +{ + var d = new Date(window.localStorage['config_mtime_local']); + var msg = PMA_messages.strSavedOn.replace( + '@DATE@', + PMA_formatDateTime(d) + ); + $('#opts_import_local_storage div.localStorage-exists').html(msg); +} + +/** + * Prepares message which informs that localStorage preferences are available and can be imported + */ +function offerPrefsAutoimport() +{ + var has_config = (window.localStorage || false) && (window.localStorage['config'] || false); + var cnt = $('#prefs_autoload'); + if (!cnt.length || !has_config) { + return; + } + cnt.find('a').click(function(e) { + e.preventDefault(); + var a = $(this); + if (a.attr('href') == '#no') { + cnt.remove(); + $.post('index.php', { + token: cnt.find('input[name=token]').val(), + prefs_autoload: 'hide'}); + return; + } + cnt.find('input[name=json]').val(window.localStorage['config']); + cnt.find('form').submit(); + }); + cnt.show(); +} + +// +// END: User preferences import/export +// ------------------------------------------------------------------ diff --git a/hugo/js/cross_framing_protection.js b/hugo/js/cross_framing_protection.js new file mode 100644 index 0000000..1e1caf0 --- /dev/null +++ b/hugo/js/cross_framing_protection.js @@ -0,0 +1,9 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Conditionally included if framing is not allowed + */ +if(self == top) { + document.documentElement.style.display = 'block' ; +} else { + top.location = self.location ; +} diff --git a/hugo/js/db_operations.js b/hugo/js/db_operations.js new file mode 100644 index 0000000..848f984 --- /dev/null +++ b/hugo/js/db_operations.js @@ -0,0 +1,114 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * @fileoverview function used in server privilege pages + * @name Database Operations + * + * @requires jQuery + * @requires jQueryUI + * @requires js/functions.js + * + */ + +/** + * Ajax event handlers here for db_operations.php + * + * Actions Ajaxified here: + * Rename Database + * Copy Database + * Change charset + */ + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('db_operations.js', function() { + $("#rename_db_form.ajax").die('submit'); + $("#copy_db_form.ajax").die('submit'); + $("#change_db_charset_form.ajax").die('submit'); +}); + +AJAX.registerOnload('db_operations.js', function() { + + /** + * Ajax event handlers for 'Rename Database' + */ + $("#rename_db_form.ajax").live('submit', function(event) { + event.preventDefault(); + + var $form = $(this); + + var question = escapeHtml('CREATE DATABASE ' + $('#new_db_name').val() + ' / DROP DATABASE ' + PMA_commonParams.get('db')); + + PMA_prepareForAjaxRequest($form); + + $form.PMA_confirm(question, $form.attr('action'), function(url) { + PMA_ajaxShowMessage(PMA_messages['strRenamingDatabases'], false); + $.get(url, $("#rename_db_form").serialize() + '&is_js_confirmed=1', function(data) { + if (data.success == true) { + PMA_ajaxShowMessage(data.message); + PMA_commonParams.set('db', data.newname); + + PMA_reloadNavigation(function() { + $('#pma_navigation_tree') + .find("a:not('.expander')") + .each(function(index) { + var $thisAnchor = $(this); + if ($thisAnchor.text() == data.newname) { + // simulate a click on the new db name + // in navigation + $thisAnchor.trigger('click'); + } + }); + }); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.get() + }) + }); // end Rename Database + + /** + * Ajax Event Handler for 'Copy Database' + */ + $("#copy_db_form.ajax").live('submit', function(event) { + event.preventDefault(); + PMA_ajaxShowMessage(PMA_messages['strCopyingDatabase'], false); + var $form = $(this); + PMA_prepareForAjaxRequest($form); + $.get($form.attr('action'), $form.serialize(), function(data) { + // use messages that stay on screen + $('div.success, div.error').fadeOut(); + if (data.success == true) { + PMA_commonParams.set('db', data.newname); + if ( $("#checkbox_switch").is(":checked")) { + PMA_commonParams.set('db', data.newname); + PMA_commonActions.refreshMain(false, function () { + PMA_ajaxShowMessage(data.message); + }); + } else { + PMA_ajaxShowMessage(data.message); + } + PMA_reloadNavigation(); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.get + }); // end copy database + + /** + * Ajax Event handler for 'Change Charset' of the database + */ + $("#change_db_charset_form.ajax").live('submit', function(event) { + event.preventDefault(); + var $form = $(this); + PMA_prepareForAjaxRequest($form); + PMA_ajaxShowMessage(PMA_messages['strChangingCharset']); + $.get($form.attr('action'), $form.serialize() + "&submitcollation=1", function(data) { + if (data.success == true) { + PMA_ajaxShowMessage(data.message); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.get() + }); // end change charset +}); diff --git a/hugo/js/db_search.js b/hugo/js/db_search.js new file mode 100644 index 0000000..495abad --- /dev/null +++ b/hugo/js/db_search.js @@ -0,0 +1,228 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * JavaScript functions used on Database Search page + * + * @requires jQuery + * @requires js/functions.js + * + * @package PhpMyAdmin + */ + +/** + * AJAX script for the Database Search page. + * + * Actions ajaxified here: + * Retrieve result of SQL query + */ + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('db_search.js', function() { + $('#buttonGo').unbind('click'); + $('#togglesearchresultlink').unbind('click'); + $("#togglequerybox").unbind('click'); + $('#togglesearchformlink').unbind('click'); + $("#db_search_form.ajax").die('submit'); +}); + +/** + * Loads the database search results + * + * @param result_path Url of the page to load + * @param table_name Name of table to browse + * + * @return nothing + */ +function loadResult(result_path, table_name, link) +{ + $(function() { + /** Hides the results shown by the delete criteria */ + var $msg = PMA_ajaxShowMessage(PMA_messages['strBrowsing'], false); + $('#sqlqueryform').hide(); + $('#togglequerybox').hide(); + /** Load the browse results to the page */ + $("#table-info").show(); + $('#table-link').attr({"href" : 'sql.php?'+link }).text(table_name); + var url = result_path + " #sqlqueryresults"; + $('#browse-results').load(url, null, function() { + $('html, body') + .animate({ + scrollTop: $("#browse-results").offset().top + }, 1000); + PMA_ajaxRemoveMessage($msg); + PMA_makegrid($('#table_results')[0], true, true, true, true); + }).show(); + }); +} + +/** + * Delete the selected search results + * + * @param result_path Url of the page to load + * @param msg Text for the confirmation dialog + * + * @return nothing + */ +function deleteResult(result_path, msg) +{ + $(function() { + /** Hides the results shown by the browse criteria */ + $("#table-info").hide(); + $('#browse-results').hide(); + $('#sqlqueryform').hide(); + $('#togglequerybox').hide(); + /** Conformation message for deletion */ + if (confirm(msg)) { + var $msg = PMA_ajaxShowMessage(PMA_messages['strDeleting'], false); + /** Load the deleted option to the page*/ + $('#sqlqueryform').html(''); + var url = result_path + " #result_query, #sqlqueryform"; + $('#browse-results').load(url, function () { + /** Refresh the search results after the deletion */ + document.getElementById('buttonGo').click(); + $('#togglequerybox').html(PMA_messages['strHideQueryBox']); + /** Show the results of the deletion option */ + $('#browse-results').show(); + $('#sqlqueryform').show(); + $('#togglequerybox').show(); + $('html, body') + .animate({ + scrollTop: $("#browse-results").offset().top + }, 1000); + PMA_ajaxRemoveMessage($msg); + }); + } + }); +} + +AJAX.registerOnload('db_search.js', function() { + /** Hide the table link in the initial search result */ + var icon = PMA_getImage('s_tbl.png', '', {'id': 'table-image'}).toString(); + $("#table-info").prepend(icon).hide(); + + /** Hide the browse and deleted results in the new search criteria */ + $('#buttonGo').click(function(){ + $("#table-info").hide(); + $('#browse-results').hide(); + $('#sqlqueryform').hide(); + $('#togglequerybox').hide(); + }); + /** + * Prepare a div containing a link for toggle the search results + */ + $('<div id="togglesearchresultsdiv"><a id="togglesearchresultlink"></a></div>') + .insertAfter('#searchresults') + /** don't show it until we have results on-screen */ + .hide(); + + $('<br class="clearfloat" />').insertAfter("#togglesearchresultsdiv").show(); + /** + * Changing the displayed text according to + * the hide/show criteria in search result forms + */ + $('#togglesearchresultlink') + .html(PMA_messages['strHideSearchResults']) + .bind('click', function() { + var $link = $(this); + $('#searchresults').slideToggle(); + if ($link.text() == PMA_messages['strHideSearchResults']) { + $link.text(PMA_messages['strShowSearchResults']); + } else { + $link.text(PMA_messages['strHideSearchResults']); + } + /** avoid default click action */ + return false; + }); + + /** + * Prepare a div containing a link for toggle the search form, + * otherwise it's incorrectly displayed after a couple of clicks + */ + $('<div id="togglesearchformdiv"><a id="togglesearchformlink"></a></div>') + .insertAfter('#db_search_form') + .hide(); // don't show it until we have results on-screen + + /** + * Changing the displayed text according to + * the hide/show criteria in search form + */ + $("#togglequerybox") + .hide() + .bind('click', function() { + var $link = $(this); + $('#sqlqueryform').slideToggle("medium"); + if ($link.text() == PMA_messages['strHideQueryBox']) { + $link.text(PMA_messages['strShowQueryBox']); + } else { + $link.text(PMA_messages['strHideQueryBox']); + } + /** avoid default click action */ + return false; + }); + + /** don't show it until we have results on-screen */ + + /** + * Changing the displayed text according to + * the hide/show criteria in search criteria form + */ + $('#togglesearchformlink') + .html(PMA_messages['strShowSearchCriteria']) + .bind('click', function() { + var $link = $(this); + $('#db_search_form').slideToggle(); + if ($link.text() == PMA_messages['strHideSearchCriteria']) { + $link.text(PMA_messages['strShowSearchCriteria']); + } else { + $link.text(PMA_messages['strHideSearchCriteria']); + } + /** avoid default click action */ + return false; + }); + /** + * Ajax Event handler for retrieving the result of an SQL Query + */ + $("#db_search_form.ajax").live('submit', function(event) { + event.preventDefault(); + + var $msgbox = PMA_ajaxShowMessage(PMA_messages['strSearching'], false); + // jQuery object to reuse + var $form = $(this); + + PMA_prepareForAjaxRequest($form); + + var url = $form.serialize() + "&submit_search=" + $("#buttonGo").val(); + $.post($form.attr('action'), url, function(data) { + if (data.success == true) { + // found results + $("#searchresults").html(data.message); + + $('#togglesearchresultlink') + // always start with the Show message + .text(PMA_messages['strHideSearchResults']); + $('#togglesearchresultsdiv') + // now it's time to show the div containing the link + .show(); + $('#searchresults').show(); + + + $('#db_search_form') + // workaround for Chrome problem (bug #3168569) + .slideToggle() + .hide(); + $('#togglesearchformlink') + // always start with the Show message + .text(PMA_messages['strShowSearchCriteria']); + $('#togglesearchformdiv') + // now it's time to show the div containing the link + .show(); + } else { + // error message (zero rows) + $("#sqlqueryresults").html(data.error); + } + + PMA_ajaxRemoveMessage($msgbox); + }) + }) +}); // end $() diff --git a/hugo/js/db_structure.js b/hugo/js/db_structure.js new file mode 100644 index 0000000..5081d02 --- /dev/null +++ b/hugo/js/db_structure.js @@ -0,0 +1,386 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * @fileoverview functions used on the database structure page + * @name Database Structure + * + * @requires jQuery + * @requires jQueryUI + * @required js/functions.js + */ + +/** + * AJAX scripts for db_structure.php + * + * Actions ajaxified here: + * Drop Database + * Truncate Table + * Drop Table + * + */ + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('db_structure.js', function() { + $("span.fkc_switch").unbind('click'); + $('#fkc_checkbox').unbind('change'); + $("a.truncate_table_anchor.ajax").die('click'); + $("a.drop_table_anchor.ajax").die('click'); + $('a.drop_tracking_anchor.ajax').die('click'); + $('#real_end_input').die('click'); +}); + +/** + * Adjust number of rows and total size in the summary + * when truncating, creating, dropping or inserting into a table + */ +function PMA_adjustTotals() { + var byteUnits = new Array( + PMA_messages['strB'], + PMA_messages['strKiB'], + PMA_messages['strMiB'], + PMA_messages['strGiB'], + PMA_messages['strTiB'], + PMA_messages['strPiB'], + PMA_messages['strEiB'] + ); + /** + * @var $allTr jQuery object that references all the rows in the list of tables + */ + var $allTr = $("#tablesForm table.data tbody:first tr"); + // New summary values for the table + var tableSum = $allTr.size(); + var rowsSum = 0; + var sizeSum = 0; + var overheadSum = 0; + var rowSumApproximated = false; + + $allTr.each(function () { + var $this = $(this); + // Get the number of rows for this SQL table + var strRows = $this.find('.tbl_rows').text(); + // If the value is approximated + if (strRows.indexOf('~') == 0) { + rowSumApproximated = true; + // The approximated value contains a preceding ~ and a following 2 (Eg 100 --> ~1002) + strRows = strRows.substring(1, strRows.length - 1); + } + strRows = strRows.replace(/[,.]/g , ''); + var intRow = parseInt(strRows, 10); + if (! isNaN(intRow)) { + rowsSum += intRow; + } + // Extract the size and overhead + var valSize = 0; + var valOverhead = 0; + var strSize = $.trim($this.find('.tbl_size span:not(.unit)').text()); + var strSizeUnit = $.trim($this.find('.tbl_size span.unit').text()); + var strOverhead = $.trim($this.find('.tbl_overhead span:not(.unit)').text()); + var strOverheadUnit = $.trim($this.find('.tbl_overhead span.unit').text()); + // Given a value and a unit, such as 100 and KiB, for the table size + // and overhead calculate their numeric values in bytes, such as 102400 + for (var i = 0; i < byteUnits.length; i++) { + if (strSizeUnit == byteUnits[i]) { + var tmpVal = parseFloat(strSize); + valSize = tmpVal * Math.pow(1024, i); + break; + } + } + for (var i = 0; i < byteUnits.length; i++) { + if (strOverheadUnit == byteUnits[i]) { + var tmpVal = parseFloat(strOverhead); + valOverhead = tmpVal * Math.pow(1024, i); + break; + } + } + sizeSum += valSize; + overheadSum += valOverhead; + }); + // Add some commas for readablility: + // 1000000 becomes 1,000,000 + var strRowSum = rowsSum + ""; + var regex = /(\d+)(\d{3})/; + while (regex.test(strRowSum)) { + strRowSum = strRowSum.replace(regex, '$1' + ',' + '$2'); + } + // If approximated total value add ~ in front + if (rowSumApproximated) { + strRowSum = "~" + strRowSum; + } + // Calculate the magnitude for the size and overhead values + var size_magnitude = 0, overhead_magnitude = 0; + while (sizeSum >= 1024) { + sizeSum /= 1024; + size_magnitude++; + } + while (overheadSum >= 1024) { + overheadSum /= 1024; + overhead_magnitude++; + } + + sizeSum = Math.round(sizeSum * 10) / 10; + overheadSum = Math.round(overheadSum * 10) / 10; + + // Update summary with new data + var $summary = $("#tbl_summary_row"); + $summary.find('.tbl_num').text($.sprintf(PMA_messages['strTables'], tableSum)); + $summary.find('.tbl_rows').text(strRowSum); + $summary.find('.tbl_size').text(sizeSum + " " + byteUnits[size_magnitude]); + $summary.find('.tbl_overhead').text(overheadSum + " " + byteUnits[overhead_magnitude]); +} + +AJAX.registerOnload('db_structure.js', function() { + /** + * Handler for the print view multisubmit. + * All other multi submits can be handled via ajax, but this one needs + * special treatment as the results need to open in another browser window + */ + $('#tablesForm').submit(function (event) { + var $form = $(this); + if ($form.find('select[name=submit_mult]').val() === 'print') { + event.preventDefault(); + event.stopPropagation(); + $('form#clone').remove(); + var $clone = $form + .clone() + .hide() + .appendTo('body'); + $clone + .find('select[name=submit_mult]') + .val('print'); + $clone + .attr('target', 'printview') + .attr('id', 'clone') + .submit(); + } + }); + + /** + * Event handler for 'Foreign Key Checks' disabling option + * in the drop table confirmation form + */ + $("span.fkc_switch").click(function(event){ + if ($("#fkc_checkbox").prop('checked')) { + $("#fkc_checkbox").prop('checked', false); + $("#fkc_status").html(PMA_messages['strForeignKeyCheckDisabled']); + return; + } + $("#fkc_checkbox").prop('checked', true); + $("#fkc_status").html(PMA_messages['strForeignKeyCheckEnabled']); + }); + + $('#fkc_checkbox').change(function () { + if ($(this).prop("checked")) { + $("#fkc_status").html(PMA_messages['strForeignKeyCheckEnabled']); + return; + } + $("#fkc_status").html(PMA_messages['strForeignKeyCheckDisabled']); + }); // End of event handler for 'Foreign Key Check' + + /** + * Ajax Event handler for 'Truncate Table' + */ + $("a.truncate_table_anchor.ajax").live('click', function(event) { + event.preventDefault(); + + /** + * @var $this_anchor Object referring to the anchor clicked + */ + var $this_anchor = $(this); + + //extract current table name and build the question string + /** + * @var curr_table_name String containing the name of the table to be truncated + */ + var curr_table_name = $this_anchor.parents('tr').children('th').children('a').text(); + /** + * @var question String containing the question to be asked for confirmation + */ + var question = + PMA_messages.strTruncateTableStrongWarning + ' ' + + $.sprintf(PMA_messages.strDoYouReally, 'TRUNCATE ' + escapeHtml(curr_table_name)); + + $this_anchor.PMA_confirm(question, $this_anchor.attr('href'), function(url) { + + PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); + + $.get(url, {'is_js_confirmed' : 1, 'ajax_request' : true}, function(data) { + if (data.success == true) { + PMA_ajaxShowMessage(data.message); + // Adjust table statistics + var $tr = $this_anchor.closest('tr'); + $tr.find('.tbl_rows').text('0'); + $tr.find('.tbl_size, .tbl_overhead').text('-'); + //Fetch inner span of this anchor + //and replace the icon with its disabled version + var span = $this_anchor.html().replace(/b_empty/, 'bd_empty'); + //To disable further attempts to truncate the table, + //replace the a element with its inner span (modified) + $this_anchor + .replaceWith(span) + .removeClass('truncate_table_anchor'); + PMA_adjustTotals(); + } else { + PMA_ajaxShowMessage(PMA_messages['strErrorProcessingRequest'] + " : " + data.error, false); + } + }); // end $.get() + }); //end $.PMA_confirm() + }); //end of Truncate Table Ajax action + + /** + * Ajax Event handler for 'Drop Table' or 'Drop View' + */ + $("a.drop_table_anchor.ajax").live('click', function(event) { + event.preventDefault(); + + var $this_anchor = $(this); + + //extract current table name and build the question string + /** + * @var $curr_row Object containing reference to the current row + */ + var $curr_row = $this_anchor.parents('tr'); + /** + * @var curr_table_name String containing the name of the table to be truncated + */ + var curr_table_name = $curr_row.children('th').children('a').text(); + /** + * @var is_view Boolean telling if we have a view + */ + var is_view = $curr_row.hasClass('is_view') || $this_anchor.hasClass('view'); + /** + * @var question String containing the question to be asked for confirmation + */ + var question; + if (! is_view) { + question = + PMA_messages.strDropTableStrongWarning + ' ' + + $.sprintf(PMA_messages.strDoYouReally, 'DROP TABLE ' + escapeHtml(curr_table_name)); + } else { + question = + $.sprintf(PMA_messages.strDoYouReally, 'DROP VIEW ' + escapeHtml(curr_table_name)); + } + + $this_anchor.PMA_confirm(question, $this_anchor.attr('href'), function(url) { + + var $msg = PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); + + $.get(url, {'is_js_confirmed' : 1, 'ajax_request' : true}, function(data) { + if (data.success == true) { + PMA_ajaxShowMessage(data.message); + toggleRowColors($curr_row.next()); + $curr_row.hide("medium").remove(); + PMA_adjustTotals(); + PMA_reloadNavigation(); + PMA_ajaxRemoveMessage($msg); + } else { + PMA_ajaxShowMessage(PMA_messages['strErrorProcessingRequest'] + " : " + data.error, false); + } + }); // end $.get() + }); // end $.PMA_confirm() + }); //end of Drop Table Ajax action + + /** + * Ajax Event handler for 'Drop tracking' + */ + $('a.drop_tracking_anchor.ajax').live('click', function(event) { + event.preventDefault(); + + var $anchor = $(this); + + /** + * @var curr_tracking_row Object containing reference to the current tracked table's row + */ + var $curr_tracking_row = $anchor.parents('tr'); + /** + * @var question String containing the question to be asked for confirmation + */ + var question = PMA_messages['strDeleteTrackingData']; + + $anchor.PMA_confirm(question, $anchor.attr('href'), function(url) { + + PMA_ajaxShowMessage(PMA_messages['strDeletingTrackingData']); + + $.get(url, {'is_js_confirmed': 1, 'ajax_request': true}, function(data) { + if (data.success == true) { + var $tracked_table = $curr_tracking_row.parents('table'); + var table_name = $curr_tracking_row.find('td:nth-child(2)').text(); + + // Check how many rows will be left after we remove + if ($tracked_table.find('tbody tr').length === 1) { + // We are removing the only row it has + $('#tracked_tables').hide("slow").remove(); + } else { + // There are more rows left after the deletion + toggleRowColors($curr_tracking_row.next()); + $curr_tracking_row.hide("slow", function() { + $(this).remove(); + }); + } + + // Make the removed table visible in the list of 'Untracked tables'. + var $untracked_table = $('table#noversions'); + + // This won't work if no untracked tables are there. + if ($untracked_table.length > 0) { + var $rows = $untracked_table.find('tbody tr'); + + $rows.each(function(index) { + var $row = $(this); + var tmp_tbl_name = $row.find('td:first-child').text(); + var is_last_iteration = (index == ($rows.length - 1)); + + if (tmp_tbl_name > table_name || is_last_iteration) { + var $cloned = $row.clone(); + + // Change the table name of the cloned row. + $cloned.find('td:first-child').text(table_name); + + // Change the link of the cloned row. + var new_url = $cloned + .find('td:nth-child(2) a') + .attr('href') + .replace('table=' + tmp_tbl_name, 'table=' + encodeURIComponent(table_name)); + $cloned.find('td:nth-child(2) a').attr('href', new_url); + + // Insert the cloned row in an appropriate location. + if (tmp_tbl_name > table_name) { + $cloned.insertBefore($row); + toggleRowColors($row); + return false; + } else { + $cloned.insertAfter($row); + toggleRowColors($cloned); + } + } + }); + } + + PMA_ajaxShowMessage(data.message); + } else { + PMA_ajaxShowMessage(PMA_messages['strErrorProcessingRequest'] + " : " + data.error, false); + } + }); // end $.get() + }); // end $.PMA_confirm() + }); //end Drop Tracking + + //Calculate Real End for InnoDB + /** + * Ajax Event handler for calculatig the real end for a InnoDB table + * + */ + $('#real_end_input').live('click', function(event) { + event.preventDefault(); + + /** + * @var question String containing the question to be asked for confirmation + */ + var question = PMA_messages['strOperationTakesLongTime']; + + $(this).PMA_confirm(question, '', function() { + return true; + }); + return false; + }); //end Calculate Real End for InnoDB + +}); // end $() diff --git a/hugo/js/export.js b/hugo/js/export.js new file mode 100644 index 0000000..979b847 --- /dev/null +++ b/hugo/js/export.js @@ -0,0 +1,257 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Functions used in the export tab + * + */ + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('export.js', function() { + $("#plugins").unbind('change'); + $("input[type='radio'][name='sql_structure_or_data']").unbind('change'); + $("input[type='radio'][name='latex_structure_or_data']").unbind('change'); + $("input[type='radio'][name='odt_structure_or_data']").unbind('change'); + $("input[type='radio'][name='texytext_structure_or_data']").unbind('change'); + $("input[type='radio'][name='htmlword_structure_or_data']").unbind('change'); + $("input[type='radio'][name='sql_structure_or_data']").unbind('change'); + $("input[type='radio'][name='output_format']").unbind('change'); + $("#checkbox_sql_include_comments").unbind('change'); + $("#plugins").unbind('change'); + $("input[type='radio'][name='quick_or_custom']").unbind('change'); + $("input[type='radio'][name='allrows']").unbind('change'); +}); + +AJAX.registerOnload('export.js', function () { + /** + * Toggles the hiding and showing of each plugin's options + * according to the currently selected plugin from the dropdown list + */ + $("#plugins").change(function() { + $("#format_specific_opts div.format_specific_options").hide(); + var selected_plugin_name = $("#plugins option:selected").val(); + $("#" + selected_plugin_name + "_options").show(); + }); + + /** + * Toggles the enabling and disabling of the SQL plugin's comment options that apply only when exporting structure + */ + $("input[type='radio'][name='sql_structure_or_data']").change(function() { + var comments_are_present = $("#checkbox_sql_include_comments").prop("checked"); + var show = $("input[type='radio'][name='sql_structure_or_data']:checked").val(); + if (show == 'data') { + // disable the SQL comment options + if (comments_are_present) { + $("#checkbox_sql_dates").prop('disabled', true).parent().fadeTo('fast', 0.4); + } + $("#checkbox_sql_relation").prop('disabled', true).parent().fadeTo('fast', 0.4); + $("#checkbox_sql_mime").prop('disabled', true).parent().fadeTo('fast', 0.4); + } else { + // enable the SQL comment options + if (comments_are_present) { + $("#checkbox_sql_dates").removeProp('disabled').parent().fadeTo('fast', 1); + } + $("#checkbox_sql_relation").removeProp('disabled').parent().fadeTo('fast', 1); + $("#checkbox_sql_mime").removeProp('disabled').parent().fadeTo('fast', 1); + } + }); +}); + + +/** + * Toggles the hiding and showing of plugin structure-specific and data-specific + * options + */ +function toggle_structure_data_opts(pluginName) +{ + var radioFormName = pluginName + "_structure_or_data"; + var dataDiv = "#" + pluginName + "_data"; + var structureDiv = "#" + pluginName + "_structure"; + var show = $("input[type='radio'][name='" + radioFormName + "']:checked").val(); + if (show == 'data') { + $(dataDiv).slideDown('slow'); + $(structureDiv).slideUp('slow'); + } else { + $(structureDiv).slideDown('slow'); + if (show == 'structure') { + $(dataDiv).slideUp('slow'); + } else { + $(dataDiv).slideDown('slow'); + } + } +} + +AJAX.registerOnload('export.js', function () { + $("input[type='radio'][name='latex_structure_or_data']").change(function() { + toggle_structure_data_opts("latex"); + }); + $("input[type='radio'][name='odt_structure_or_data']").change(function() { + toggle_structure_data_opts("odt"); + }); + $("input[type='radio'][name='texytext_structure_or_data']").change(function() { + toggle_structure_data_opts("texytext"); + }); + $("input[type='radio'][name='htmlword_structure_or_data']").change(function() { + toggle_structure_data_opts("htmlword"); + }); + $("input[type='radio'][name='sql_structure_or_data']").change(function() { + toggle_structure_data_opts("sql"); + }); +}); + +/** + * Toggles the disabling of the "save to file" options + */ +function toggle_save_to_file() +{ + if (!$("#radio_dump_asfile").prop("checked")) { + $("#ul_save_asfile > li").fadeTo('fast', 0.4); + $("#ul_save_asfile > li > input").prop('disabled', true); + $("#ul_save_asfile > li> select").prop('disabled', true); + } else { + $("#ul_save_asfile > li").fadeTo('fast', 1); + $("#ul_save_asfile > li > input").removeProp('disabled'); + $("#ul_save_asfile > li> select").removeProp('disabled'); + } +} + +AJAX.registerOnload('export.js', function () { + toggle_save_to_file(); + $("input[type='radio'][name='output_format']").change(toggle_save_to_file); +}); + +/** + * For SQL plugin, toggles the disabling of the "display comments" options + */ +function toggle_sql_include_comments() +{ + $("#checkbox_sql_include_comments").change(function() { + if (!$("#checkbox_sql_include_comments").prop("checked")) { + $("#ul_include_comments > li").fadeTo('fast', 0.4); + $("#ul_include_comments > li > input").prop('disabled', true); + } else { + // If structure is not being exported, the comment options for structure should not be enabled + if ($("#radio_sql_structure_or_data_data").prop("checked")) { + $("#text_sql_header_comment").removeProp('disabled').parent("li").fadeTo('fast', 1); + } else { + $("#ul_include_comments > li").fadeTo('fast', 1); + $("#ul_include_comments > li > input").removeProp('disabled'); + } + } + }); +} + +AJAX.registerOnload('export.js', function () { + /** + * For SQL plugin, if "CREATE TABLE options" is checked/unchecked, check/uncheck each of its sub-options + */ + var $create = $("#checkbox_sql_create_table_statements"); + var $create_options = $("#ul_create_table_statements input"); + $create.change(function() { + $create_options.prop('checked', $(this).prop("checked")); + }); + $create_options.change(function() { + if ($create_options.is(":checked")) { + $create.prop('checked', true); + } + }); + + /** + * Disables the view output as text option if the output must be saved as a file + */ + $("#plugins").change(function() { + var active_plugin = $("#plugins option:selected").val(); + var force_file = $("#force_file_" + active_plugin).val(); + if (force_file == "true") { + $("#radio_view_as_text").prop('disabled', true).parent().fadeTo('fast', 0.4); + } else { + $("#radio_view_as_text").removeProp('disabled').parent().fadeTo('fast', 1); + } + }); +}); + +/** + * Toggles display of options when quick and custom export are selected + */ +function toggle_quick_or_custom() +{ + if ($("#radio_custom_export").prop("checked")) { + $("#databases_and_tables").show(); + $("#rows").show(); + $("#output").show(); + $("#format_specific_opts").show(); + $("#output_quick_export").hide(); + var selected_plugin_name = $("#plugins option:selected").val(); + $("#" + selected_plugin_name + "_options").show(); + } else { + $("#databases_and_tables").hide(); + $("#rows").hide(); + $("#output").hide(); + $("#format_specific_opts").hide(); + $("#output_quick_export").show(); + } +} + +AJAX.registerOnload('export.js', function () { + $("input[type='radio'][name='quick_or_custom']").change(toggle_quick_or_custom); + + /** + * Sets up the interface for Javascript-enabled browsers since the default is for + * Javascript-disabled browsers + * TODO: drop non-JS behaviour + */ + if ($("input[type='hidden'][name='export_method']").val() != "custom-no-form") { + $("#quick_or_custom").show(); + } + $("#scroll_to_options_msg").hide(); + $("#format_specific_opts div.format_specific_options") + .hide() + .css({ + "border": 0, + "margin": 0, + "padding": 0 + }) + .find("h3") + .remove(); + toggle_quick_or_custom(); + toggle_structure_data_opts($("select#plugins").val()); + toggle_sql_include_comments(); + + /** + * Initially disables the "Dump some row(s)" sub-options + */ + disable_dump_some_rows_sub_options(); + + /** + * Disables the "Dump some row(s)" sub-options when it is not selected + */ + $("input[type='radio'][name='allrows']").change(function() { + if ($("input[type='radio'][name='allrows']").prop("checked")) { + enable_dump_some_rows_sub_options(); + } else { + disable_dump_some_rows_sub_options(); + } + }); +}); + +/** + * Disables the "Dump some row(s)" sub-options + */ +function disable_dump_some_rows_sub_options() +{ + $("label[for='limit_to']").fadeTo('fast', 0.4); + $("label[for='limit_from']").fadeTo('fast', 0.4); + $("input[type='text'][name='limit_to']").prop('disabled', 'disabled'); + $("input[type='text'][name='limit_from']").prop('disabled', 'disabled'); +} + +/** + * Enables the "Dump some row(s)" sub-options + */ +function enable_dump_some_rows_sub_options() +{ + $("label[for='limit_to']").fadeTo('fast', 1); + $("label[for='limit_from']").fadeTo('fast', 1); + $("input[type='text'][name='limit_to']").prop('disabled', ''); + $("input[type='text'][name='limit_from']").prop('disabled', ''); +} diff --git a/hugo/js/functions.js b/hugo/js/functions.js new file mode 100644 index 0000000..731c137 --- /dev/null +++ b/hugo/js/functions.js @@ -0,0 +1,3865 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * general function, usually for data manipulation pages + * + */ + +/** + * @var $table_clone reference to the action links on the tbl_structure page + */ +var $table_clone = false; + +/** + * @var sql_box_locked lock for the sqlbox textarea in the querybox/querywindow + */ +var sql_box_locked = false; + +/** + * @var array holds elements which content should only selected once + */ +var only_once_elements = []; + +/** + * @var int ajax_message_count Number of AJAX messages shown since page load + */ +var ajax_message_count = 0; + +/** + * @var codemirror_editor object containing CodeMirror editor of the query editor in SQL tab + */ +var codemirror_editor = false; + +/** + * @var codemirror_editor object containing CodeMirror editor of the inline query editor + */ +var codemirror_inline_editor = false; + +/** + * @var chart_activeTimeouts object active timeouts that refresh the charts. When disabling a realtime chart, this can be used to stop the continuous ajax requests + */ +var chart_activeTimeouts = {}; + +/** + * Make sure that ajax requests will not be cached + * by appending a random variable to their parameters + */ +$.ajaxPrefilter(function (options, originalOptions, jqXHR) { + var nocache = new Date().getTime() + "" + Math.floor(Math.random() * 1000000); + if (typeof options.data == "string") { + options.data += "&_nocache=" + nocache; + } else if (typeof options.data == "object") { + options.data = $.extend(originalOptions.data, {'_nocache':nocache}); + } +}); + +/** + * Add a hidden field to the form to indicate that this will be an + * Ajax request (only if this hidden field does not exist) + * + * @param object the form + */ +function PMA_prepareForAjaxRequest($form) +{ + if (! $form.find('input:hidden').is('#ajax_request_hidden')) { + $form.append('<input type="hidden" id="ajax_request_hidden" name="ajax_request" value="true" />'); + } +} + +/** + * Generate a new password and copy it to the password input areas + * + * @param object the form that holds the password fields + * + * @return boolean always true + */ +function suggestPassword(passwd_form) +{ + // restrict the password to just letters and numbers to avoid problems: + // "editors and viewers regard the password as multiple words and + // things like double click no longer work" + var pwchars = "abcdefhjmnpqrstuvwxyz23456789ABCDEFGHJKLMNPQRSTUVWYXZ"; + var passwordlength = 16; // do we want that to be dynamic? no, keep it simple :) + var passwd = passwd_form.generated_pw; + passwd.value = ''; + + for (var i = 0; i < passwordlength; i++ ) { + passwd.value += pwchars.charAt( Math.floor( Math.random() * pwchars.length ) ); + } + passwd_form.text_pma_pw.value = passwd.value; + passwd_form.text_pma_pw2.value = passwd.value; + return true; +} + +/** + * Version string to integer conversion. + */ +function parseVersionString (str) +{ + if (typeof(str) != 'string') { return false; } + var add = 0; + // Parse possible alpha/beta/rc/ + var state = str.split('-'); + if (state.length >= 2) { + if (state[1].substr(0, 2) == 'rc') { + add = - 20 - parseInt(state[1].substr(2)); + } else if (state[1].substr(0, 4) == 'beta') { + add = - 40 - parseInt(state[1].substr(4)); + } else if (state[1].substr(0, 5) == 'alpha') { + add = - 60 - parseInt(state[1].substr(5)); + } else if (state[1].substr(0, 3) == 'dev') { + /* We don't handle dev, it's git snapshot */ + add = 0; + } + } + // Parse version + var x = str.split('.'); + // Use 0 for non existing parts + var maj = parseInt(x[0]) || 0; + var min = parseInt(x[1]) || 0; + var pat = parseInt(x[2]) || 0; + var hotfix = parseInt(x[3]) || 0; + return maj * 100000000 + min * 1000000 + pat * 10000 + hotfix * 100 + add; +} + +/** + * Indicates current available version on main page. + */ +function PMA_current_version(data) +{ + if (data && data.version && data.date) { + var current = parseVersionString(pmaversion); + var latest = parseVersionString(data['version']); + var version_information_message = PMA_messages['strLatestAvailable'] + ' ' + escapeHtml(data['version']); + if (latest > current) { + var message = $.sprintf( + PMA_messages['strNewerVersion'], + escapeHtml(data['version']), + escapeHtml(data['date']) + ); + if (Math.floor(latest / 10000) === Math.floor(current / 10000)) { + /* Security update */ + var klass = 'error'; + } else { + var klass = 'notice'; + } + $('#maincontainer').after('<div class="' + klass + '">' + message + '</div>'); + } + if (latest === current) { + version_information_message = ' (' + PMA_messages['strUpToDate'] + ')'; + } + $('#li_pma_version').append(version_information_message); + } +} + +/** + * Loads Git revision data from ajax for index.php + */ +function PMA_display_git_revision() +{ + $('#is_git_revision').remove(); + $.get( + "index.php", + { + "server": PMA_commonParams.get('server'), + "token": PMA_commonParams.get('token'), + "git_revision": true, + "ajax_request": true + }, + function (data) { + if (data.success == true) { + $(data.message).insertAfter('#li_pma_version'); + } + } + ); +} + +/** + * for libraries/display_change_password.lib.php + * libraries/user_password.php + * + */ + +function displayPasswordGenerateButton() +{ + $('#tr_element_before_generate_password').parent().append('<tr class="vmiddle"><td>' + PMA_messages['strGeneratePassword'] + '</td><td><input type="button" class="button" id="button_generate_password" value="' + PMA_messages['strGenerate'] + '" onclick="suggestPassword(this.form)" /><input type="text" name="generated_pw" id="generated_pw" /></td></tr>'); + $('#div_element_before_generate_password').parent().append('<div class="item"><label for="button_generate_password">' + PMA_messages['strGeneratePassword'] + ':</label><span class="options"><input type="button" class="button" id="button_generate_password" value="' + PMA_messages['strGenerate'] + '" onclick="suggestPassword(this.form)" /></span><input type="text" name="generated_pw" id="generated_pw" /></div>'); +} + +/* + * Adds a date/time picker to an element + * + * @param object $this_element a jQuery object pointing to the element + */ +function PMA_addDatepicker($this_element, options) +{ + var showTimeOption = false; + if ($this_element.is('.datetimefield')) { + showTimeOption = true; + } + + var defaultOptions = { + showOn: 'button', + buttonImage: themeCalendarImage, // defined in js/messages.php + buttonImageOnly: true, + stepMinutes: 1, + stepHours: 1, + showSecond: true, + showTimepicker: showTimeOption, + showButtonPanel: false, + dateFormat: 'yy-mm-dd', // yy means year with four digits + timeFormat: 'HH:mm:ss', + altFieldTimeOnly: false, + showAnim: '', + beforeShow: function(input, inst) { + // Remember that we came from the datepicker; this is used + // in tbl_change.js by verificationsAfterFieldChange() + $this_element.data('comes_from', 'datepicker'); + + // Fix wrong timepicker z-index, doesn't work without timeout + setTimeout(function() { + $('#ui-timepicker-div').css('z-index',$('#ui-datepicker-div').css('z-index')); + }, 0); + }, + onClose: function(dateText, dp_inst) { + // The value is no more from the date picker + $this_element.data('comes_from', ''); + } + }; + if ( showTimeOption || (typeof(options) != 'undefined' && options.showTimepicker) ) { + $this_element.datetimepicker($.extend(defaultOptions, options)); + } else { + $this_element.datepicker($.extend(defaultOptions, options)); + } +} + +/** + * selects the content of a given object, f.e. a textarea + * + * @param object element element of which the content will be selected + * @param var lock variable which holds the lock for this element + * or true, if no lock exists + * @param boolean only_once if true this is only done once + * f.e. only on first focus + */ +function selectContent( element, lock, only_once ) +{ + if ( only_once && only_once_elements[element.name] ) { + return; + } + + only_once_elements[element.name] = true; + + if ( lock ) { + return; + } + + element.select(); +} + +/** + * Displays a confirmation box before submitting a "DROP/DELETE/ALTER" query. + * This function is called while clicking links + * + * @param object the link + * @param object the sql query to submit + * + * @return boolean whether to run the query or not + */ +function confirmLink(theLink, theSqlQuery) +{ + // Confirmation is not required in the configuration file + // or browser is Opera (crappy js implementation) + if (PMA_messages['strDoYouReally'] == '' || typeof(window.opera) != 'undefined') { + return true; + } + + var is_confirmed = confirm($.sprintf(PMA_messages['strDoYouReally'], theSqlQuery)); + if (is_confirmed) { + if ( $(theLink).hasClass('formLinkSubmit') ) { + var name = 'is_js_confirmed'; + if ($(theLink).attr('href').indexOf('usesubform') != -1) { + name = 'subform[' + $(theLink).attr('href').substr('#').match(/usesubform\[(\d+)\]/i)[1] + '][is_js_confirmed]'; + } + + $(theLink).parents('form').append('<input type="hidden" name="' + name + '" value="1" />'); + } else if ( typeof(theLink.href) != 'undefined' ) { + theLink.href += '&is_js_confirmed=1'; + } else if ( typeof(theLink.form) != 'undefined' ) { + theLink.form.action += '?is_js_confirmed=1'; + } + } + + return is_confirmed; +} // end of the 'confirmLink()' function + +/** + * Displays an error message if a "DROP DATABASE" statement is submitted + * while it isn't allowed, else confirms a "DROP/DELETE/ALTER" query before + * sumitting it if required. + * This function is called by the 'checkSqlQuery()' js function. + * + * @param object the form + * @param object the sql query textarea + * + * @return boolean whether to run the query or not + * + * @see checkSqlQuery() + */ +function confirmQuery(theForm1, sqlQuery1) +{ + // Confirmation is not required in the configuration file + if (PMA_messages['strDoYouReally'] == '') { + return true; + } + + // "DROP DATABASE" statement isn't allowed + if (PMA_messages['strNoDropDatabases'] != '') { + var drop_re = new RegExp('(^|;)\\s*DROP\\s+(IF EXISTS\\s+)?DATABASE\\s', 'i'); + if (drop_re.test(sqlQuery1.value)) { + alert(PMA_messages['strNoDropDatabases']); + theForm1.reset(); + sqlQuery1.focus(); + return false; + } // end if + } // end if + + // Confirms a "DROP/DELETE/ALTER/TRUNCATE" statement + // + // TODO: find a way (if possible) to use the parser-analyser + // for this kind of verification + // For now, I just added a ^ to check for the statement at + // beginning of expression + + var do_confirm_re_0 = new RegExp('^\\s*DROP\\s+(IF EXISTS\\s+)?(TABLE|DATABASE|PROCEDURE)\\s', 'i'); + var do_confirm_re_1 = new RegExp('^\\s*ALTER\\s+TABLE\\s+((`[^`]+`)|([A-Za-z0-9_$]+))\\s+DROP\\s', 'i'); + var do_confirm_re_2 = new RegExp('^\\s*DELETE\\s+FROM\\s', 'i'); + var do_confirm_re_3 = new RegExp('^\\s*TRUNCATE\\s', 'i'); + + if (do_confirm_re_0.test(sqlQuery1.value) + || do_confirm_re_1.test(sqlQuery1.value) + || do_confirm_re_2.test(sqlQuery1.value) + || do_confirm_re_3.test(sqlQuery1.value)) { + var message = (sqlQuery1.value.length > 100) + ? sqlQuery1.value.substr(0, 100) + '\n ...' + : sqlQuery1.value; + var is_confirmed = confirm($.sprintf(PMA_messages['strDoYouReally'], message)); + // statement is confirmed -> update the + // "is_js_confirmed" form field so the confirm test won't be + // run on the server side and allows to submit the form + if (is_confirmed) { + theForm1.elements['is_js_confirmed'].value = 1; + return true; + } + // statement is rejected -> do not submit the form + else { + window.focus(); + sqlQuery1.focus(); + return false; + } // end if (handle confirm box result) + } // end if (display confirm box) + + return true; +} // end of the 'confirmQuery()' function + +/** + * Displays an error message if the user submitted the sql query form with no + * sql query, else checks for "DROP/DELETE/ALTER" statements + * + * @param object the form + * + * @return boolean always false + * + * @see confirmQuery() + */ +function checkSqlQuery(theForm) +{ + + // First check if codemirror is active. + if (codemirror_editor) { + theForm.elements['sql_query'].value = codemirror_editor.getValue(); + } + + var sqlQuery = theForm.elements['sql_query']; + + var isEmpty = 1; + + var space_re = new RegExp('\\s+'); + if (typeof(theForm.elements['sql_file']) != 'undefined' && + theForm.elements['sql_file'].value.replace(space_re, '') != '') { + return true; + } + if (typeof(theForm.elements['sql_localfile']) != 'undefined' && + theForm.elements['sql_localfile'].value.replace(space_re, '') != '') { + return true; + } + if (isEmpty && typeof(theForm.elements['id_bookmark']) != 'undefined' && + (theForm.elements['id_bookmark'].value != null || theForm.elements['id_bookmark'].value != '') && + theForm.elements['id_bookmark'].selectedIndex != 0 + ) { + return true; + } + // Checks for "DROP/DELETE/ALTER" statements + if (sqlQuery.value.replace(space_re, '') != '') { + if (confirmQuery(theForm, sqlQuery)) { + return true; + } else { + return false; + } + } + theForm.reset(); + isEmpty = 1; + + if (isEmpty) { + sqlQuery.select(); + alert(PMA_messages['strFormEmpty']); + sqlQuery.focus(); + return false; + } + + return true; +} // end of the 'checkSqlQuery()' function + +/** + * Check if a form's element is empty. + * An element containing only spaces is also considered empty + * + * @param object the form + * @param string the name of the form field to put the focus on + * + * @return boolean whether the form field is empty or not + */ +function emptyCheckTheField(theForm, theFieldName) +{ + var theField = theForm.elements[theFieldName]; + var space_re = new RegExp('\\s+'); + return (theField.value.replace(space_re, '') == '') ? 1 : 0; +} // end of the 'emptyCheckTheField()' function + + +/** + * Check whether a form field is empty or not + * + * @param object the form + * @param string the name of the form field to put the focus on + * + * @return boolean whether the form field is empty or not + */ +function emptyFormElements(theForm, theFieldName) +{ + var theField = theForm.elements[theFieldName]; + var isEmpty = emptyCheckTheField(theForm, theFieldName); + + + return isEmpty; +} // end of the 'emptyFormElements()' function + + +/** + * Ensures a value submitted in a form is numeric and is in a range + * + * @param object the form + * @param string the name of the form field to check + * @param integer the minimum authorized value + * @param integer the maximum authorized value + * + * @return boolean whether a valid number has been submitted or not + */ +function checkFormElementInRange(theForm, theFieldName, message, min, max) +{ + var theField = theForm.elements[theFieldName]; + var val = parseInt(theField.value); + + if (typeof(min) == 'undefined') { + min = 0; + } + if (typeof(max) == 'undefined') { + max = Number.MAX_VALUE; + } + + // It's not a number + if (isNaN(val)) { + theField.select(); + alert(PMA_messages['strNotNumber']); + theField.focus(); + return false; + } + // It's a number but it is not between min and max + else if (val < min || val > max) { + theField.select(); + alert($.sprintf(message, val)); + theField.focus(); + return false; + } + // It's a valid number + else { + theField.value = val; + } + return true; + +} // end of the 'checkFormElementInRange()' function + + +function checkTableEditForm(theForm, fieldsCnt) +{ + // TODO: avoid sending a message if user just wants to add a line + // on the form but has not completed at least one field name + + var atLeastOneField = 0; + var i, elm, elm2, elm3, val, id; + + for (i=0; i<fieldsCnt; i++) + { + id = "#field_" + i + "_2"; + elm = $(id); + val = elm.val(); + if (val == 'VARCHAR' || val == 'CHAR' || val == 'BIT' || val == 'VARBINARY' || val == 'BINARY') { + elm2 = $("#field_" + i + "_3"); + val = parseInt(elm2.val()); + elm3 = $("#field_" + i + "_1"); + if (isNaN(val) && elm3.val() != "") { + elm2.select(); + alert(PMA_messages['strNotNumber']); + elm2.focus(); + return false; + } + } + + if (atLeastOneField == 0) { + id = "field_" + i + "_1"; + if (!emptyCheckTheField(theForm, id)) { + atLeastOneField = 1; + } + } + } + if (atLeastOneField == 0) { + var theField = theForm.elements["field_0_1"]; + alert(PMA_messages['strFormEmpty']); + theField.focus(); + return false; + } + + // at least this section is under jQuery + if ($("input.textfield[name='table']").val() == "") { + alert(PMA_messages['strFormEmpty']); + $("input.textfield[name='table']").focus(); + return false; + } + + + return true; +} // enf of the 'checkTableEditForm()' function + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('functions.js', function() { + $('input:checkbox.checkall').die('click'); +}); +AJAX.registerOnload('functions.js', function() { + /** + * Row marking in horizontal mode (use "live" so that it works also for + * next pages reached via AJAX); a tr may have the class noclick to remove + * this behavior. + */ + + $('input:checkbox.checkall').live('click', function(e) { + var $tr = $(this).closest('tr'); + + // make the table unselectable (to prevent default highlighting when shift+click) + //$tr.parents('table').noSelect(); + + if (!e.shiftKey || last_clicked_row == -1) { + // usual click + + // XXX: FF fires two click events for <label> (label and checkbox), so we need to handle this differently + var $checkbox = $tr.find(':checkbox'); + if ($checkbox.length) { + // checkbox in a row, add or remove class depending on checkbox state + var checked = $checkbox.prop('checked'); + if (!$(e.target).is(':checkbox, label')) { + checked = !checked; + $checkbox.prop('checked', checked).trigger('change'); + } + if (checked) { + $tr.addClass('marked'); + } else { + $tr.removeClass('marked'); + } + last_click_checked = checked; + } else { + // normal data table, just toggle class + $tr.toggleClass('marked'); + last_click_checked = false; + } + + // remember the last clicked row + last_clicked_row = last_click_checked ? $('tr.odd:not(.noclick), tr.even:not(.noclick)').index($tr) : -1; + last_shift_clicked_row = -1; + } else { + // handle the shift click + PMA_clearSelection(); + var start, end; + + // clear last shift click result + if (last_shift_clicked_row >= 0) { + if (last_shift_clicked_row >= last_clicked_row) { + start = last_clicked_row; + end = last_shift_clicked_row; + } else { + start = last_shift_clicked_row; + end = last_clicked_row; + } + $tr.parent().find('tr.odd:not(.noclick), tr.even:not(.noclick)') + .slice(start, end + 1) + .removeClass('marked') + .find(':checkbox') + .prop('checked', false) + .trigger('change'); + } + + // handle new shift click + var curr_row = $('tr.odd:not(.noclick), tr.even:not(.noclick)').index($tr); + if (curr_row >= last_clicked_row) { + start = last_clicked_row; + end = curr_row; + } else { + start = curr_row; + end = last_clicked_row; + } + $tr.parent().find('tr.odd:not(.noclick), tr.even:not(.noclick)') + .slice(start, end + 1) + .addClass('marked') + .find(':checkbox') + .prop('checked', true) + .trigger('change'); + + // remember the last shift clicked row + last_shift_clicked_row = curr_row; + } + }); + + addDateTimePicker(); + + /** + * Add attribute to text boxes for iOS devices (based on bugID: 3508912) + */ + if (navigator.userAgent.match(/(iphone|ipod|ipad)/i)) { + $('input[type=text]').attr('autocapitalize','off').attr('autocorrect','off'); + } +}); + +/** + * True if last click is to check a row. + */ +var last_click_checked = false; + +/** + * Zero-based index of last clicked row. + * Used to handle the shift + click event in the code above. + */ +var last_clicked_row = -1; + +/** + * Zero-based index of last shift clicked row. + */ +var last_shift_clicked_row = -1; + +/** + * Row highlighting in horizontal mode (use "live" + * so that it works also for pages reached via AJAX) + */ +/*AJAX.registerOnload('functions.js', function() { + $('tr.odd, tr.even').live('hover',function(event) { + var $tr = $(this); + $tr.toggleClass('hover',event.type=='mouseover'); + $tr.children().toggleClass('hover',event.type=='mouseover'); + }); +})*/ + +/** + * This array is used to remember mark status of rows in browse mode + */ +var marked_row = []; + +/** + * marks all rows and selects its first checkbox inside the given element + * the given element is usaly a table or a div containing the table or tables + * + * @param container DOM element + */ +function markAllRows(container_id) +{ + + $("#" + container_id).find("input:checkbox:enabled").prop('checked', true) + .trigger("change") + .parents("tr").addClass("marked"); + return true; +} + +/** + * marks all rows and selects its first checkbox inside the given element + * the given element is usaly a table or a div containing the table or tables + * + * @param container DOM element + */ +function unMarkAllRows(container_id) +{ + + $("#" + container_id).find("input:checkbox:enabled").prop('checked', false) + .trigger("change") + .parents("tr").removeClass("marked"); + return true; +} + +/** + * Checks/unchecks all checkbox in given conainer (f.e. a form, fieldset or div) + * + * @param string container_id the container id + * @param boolean state new value for checkbox (true or false) + * @return boolean always true + */ +function setCheckboxes(container_id, state) +{ + + $("#" + container_id).find("input:checkbox").prop('checked', state); + return true; +} // end of the 'setCheckboxes()' function + +/** + * Checks/unchecks all options of a <select> element + * + * @param string the form name + * @param string the element name + * @param boolean whether to check or to uncheck options + * + * @return boolean always true + */ +function setSelectOptions(the_form, the_select, do_check) +{ + $("form[name='"+ the_form +"'] select[name='"+the_select+"']").find("option").prop('selected', do_check); + return true; +} // end of the 'setSelectOptions()' function + +/** + * Sets current value for query box. + */ +function setQuery(query) +{ + if (codemirror_editor) { + codemirror_editor.setValue(query); + codemirror_editor.focus(); + } else { + document.sqlform.sql_query.value = query; + document.sqlform.sql_query.focus(); + } +} + + +/** + * Create quick sql statements. + * + */ +function insertQuery(queryType) +{ + if (queryType == "clear") { + setQuery(''); + return; + } + + var query = ""; + var myListBox = document.sqlform.dummy; + var table = document.sqlform.table.value; + + if (myListBox.options.length > 0) { + sql_box_locked = true; + var chaineAj = ""; + var valDis = ""; + var editDis = ""; + var NbSelect = 0; + for (var i=0; i < myListBox.options.length; i++) { + NbSelect++; + if (NbSelect > 1) { + chaineAj += ", "; + valDis += ","; + editDis += ","; + } + chaineAj += myListBox.options[i].value; + valDis += "[value-" + NbSelect + "]"; + editDis += myListBox.options[i].value + "=[value-" + NbSelect + "]"; + } + if (queryType == "selectall") { + query = "SELECT * FROM `" + table + "` WHERE 1"; + } else if (queryType == "select") { + query = "SELECT " + chaineAj + " FROM `" + table + "` WHERE 1"; + } else if (queryType == "insert") { + query = "INSERT INTO `" + table + "`(" + chaineAj + ") VALUES (" + valDis + ")"; + } else if (queryType == "update") { + query = "UPDATE `" + table + "` SET " + editDis + " WHERE 1"; + } else if (queryType == "delete") { + query = "DELETE FROM `" + table + "` WHERE 1"; + } + setQuery(query); + sql_box_locked = false; + } +} + + +/** + * Inserts multiple fields. + * + */ +function insertValueQuery() +{ + var myQuery = document.sqlform.sql_query; + var myListBox = document.sqlform.dummy; + + if (myListBox.options.length > 0) { + sql_box_locked = true; + var chaineAj = ""; + var NbSelect = 0; + for (var i=0; i<myListBox.options.length; i++) { + if (myListBox.options[i].selected) { + NbSelect++; + if (NbSelect > 1) { + chaineAj += ", "; + } + chaineAj += myListBox.options[i].value; + } + } + + /* CodeMirror support */ + if (codemirror_editor) { + codemirror_editor.replaceSelection(chaineAj); + //IE support + } else if (document.selection) { + myQuery.focus(); + var sel = document.selection.createRange(); + sel.text = chaineAj; + document.sqlform.insert.focus(); + } + //MOZILLA/NETSCAPE support + else if (document.sqlform.sql_query.selectionStart || document.sqlform.sql_query.selectionStart == "0") { + var startPos = document.sqlform.sql_query.selectionStart; + var endPos = document.sqlform.sql_query.selectionEnd; + var chaineSql = document.sqlform.sql_query.value; + + myQuery.value = chaineSql.substring(0, startPos) + chaineAj + chaineSql.substring(endPos, chaineSql.length); + } else { + myQuery.value += chaineAj; + } + sql_box_locked = false; + } +} + +/** + * Add a date/time picker to each element that needs it + * (only when jquery-ui-timepicker-addon.js is loaded) + */ +function addDateTimePicker() { + if ($.timepicker != undefined) { + $('input.datefield, input.datetimefield').each(function() { + PMA_addDatepicker($(this)); + }); + } +} + +/** + * Refresh/resize the WYSIWYG scratchboard + */ +function refreshLayout() +{ + var $elm = $('#pdflayout'); + var orientation = $('#orientation_opt').val(); + if ($('#paper_opt').length==1) { + var paper = $('#paper_opt').val(); + }else{ + var paper = 'A4'; + } + if (orientation == 'P') { + var posa = 'x'; + var posb = 'y'; + } else { + var posa = 'y'; + var posb = 'x'; + } + $elm.css('width', pdfPaperSize(paper, posa) + 'px'); + $elm.css('height', pdfPaperSize(paper, posb) + 'px'); +} + +/** + * Initializes positions of elements. + */ +function TableDragInit() { + $('.pdflayout_table').each(function () { + var $this = $(this); + var number = $this.data('number'); + var x = $('#c_table_' + number + '_x').val(); + var y = $('#c_table_' + number + '_y').val(); + $this.css('left', x + 'px'); + $this.css('top', y + 'px'); + /* Make elements draggable */ + $this.draggable({ + containment: "parent", + drag: function (evt, ui) { + var number = $this.data('number'); + $('#c_table_' + number + '_x').val(parseInt(ui.position.left)); + $('#c_table_' + number + '_y').val(parseInt(ui.position.top)); + } + }); + }); +} + +/** + * Resets drag and drop positions. + */ +function resetDrag() { + $('.pdflayout_table').each(function () { + var $this = $(this); + var x = $this.data('x'); + var y = $this.data('y'); + $this.css('left', x + 'px'); + $this.css('top', y + 'px'); + }); +} + +/** + * User schema handlers. + */ +$(function () { + /* Move in scratchboard on manual change */ + $('.position-change').live('change', function () { + var $this = $(this); + var $elm = $('#table_' + $this.data('number')); + $elm.css($this.data('axis'), $this.val() + 'px'); + }); + /* Refresh on paper size/orientation change */ + $('.paper-change').live('change', function () { + var $elm = $('#pdflayout'); + if ($elm.css('visibility') == 'visible') { + refreshLayout(); + TableDragInit(); + } + }); + /* Show/hide the WYSIWYG scratchboard */ + $('#toggle-dragdrop').live('click', function () { + var $elm = $('#pdflayout'); + if ($elm.css('visibility') == 'hidden') { + refreshLayout(); + TableDragInit(); + $elm.css('visibility', 'visible'); + $elm.css('display', 'block'); + $('#showwysiwyg').val('1'); + } else { + $elm.css('visibility', 'hidden'); + $elm.css('display', 'none'); + $('#showwysiwyg').val('0'); + } + }); + /* Reset scratchboard */ + $('#reset-dragdrop').live('click', function () { + resetDrag(); + }); +}); + +/** + * Returns paper sizes for a given format + */ +function pdfPaperSize(format, axis) +{ + switch (format.toUpperCase()) { + case '4A0': + if (axis == 'x') { + return 4767.87; + } else { + return 6740.79; + } + break; + case '2A0': + if (axis == 'x') { + return 3370.39; + } else { + return 4767.87; + } + break; + case 'A0': + if (axis == 'x') { + return 2383.94; + } else { + return 3370.39; + } + break; + case 'A1': + if (axis == 'x') { + return 1683.78; + } else { + return 2383.94; + } + break; + case 'A2': + if (axis == 'x') { + return 1190.55; + } else { + return 1683.78; + } + break; + case 'A3': + if (axis == 'x') { + return 841.89; + } else { + return 1190.55; + } + break; + case 'A4': + if (axis == 'x') { + return 595.28; + } else { + return 841.89; + } + break; + case 'A5': + if (axis == 'x') { + return 419.53; + } else { + return 595.28; + } + break; + case 'A6': + if (axis == 'x') { + return 297.64; + } else { + return 419.53; + } + break; + case 'A7': + if (axis == 'x') { + return 209.76; + } else { + return 297.64; + } + break; + case 'A8': + if (axis == 'x') { + return 147.40; + } else { + return 209.76; + } + break; + case 'A9': + if (axis == 'x') { + return 104.88; + } else { + return 147.40; + } + break; + case 'A10': + if (axis == 'x') { + return 73.70; + } else { + return 104.88; + } + break; + case 'B0': + if (axis == 'x') { + return 2834.65; + } else { + return 4008.19; + } + break; + case 'B1': + if (axis == 'x') { + return 2004.09; + } else { + return 2834.65; + } + break; + case 'B2': + if (axis == 'x') { + return 1417.32; + } else { + return 2004.09; + } + break; + case 'B3': + if (axis == 'x') { + return 1000.63; + } else { + return 1417.32; + } + break; + case 'B4': + if (axis == 'x') { + return 708.66; + } else { + return 1000.63; + } + break; + case 'B5': + if (axis == 'x') { + return 498.90; + } else { + return 708.66; + } + break; + case 'B6': + if (axis == 'x') { + return 354.33; + } else { + return 498.90; + } + break; + case 'B7': + if (axis == 'x') { + return 249.45; + } else { + return 354.33; + } + break; + case 'B8': + if (axis == 'x') { + return 175.75; + } else { + return 249.45; + } + break; + case 'B9': + if (axis == 'x') { + return 124.72; + } else { + return 175.75; + } + break; + case 'B10': + if (axis == 'x') { + return 87.87; + } else { + return 124.72; + } + break; + case 'C0': + if (axis == 'x') { + return 2599.37; + } else { + return 3676.54; + } + break; + case 'C1': + if (axis == 'x') { + return 1836.85; + } else { + return 2599.37; + } + break; + case 'C2': + if (axis == 'x') { + return 1298.27; + } else { + return 1836.85; + } + break; + case 'C3': + if (axis == 'x') { + return 918.43; + } else { + return 1298.27; + } + break; + case 'C4': + if (axis == 'x') { + return 649.13; + } else { + return 918.43; + } + break; + case 'C5': + if (axis == 'x') { + return 459.21; + } else { + return 649.13; + } + break; + case 'C6': + if (axis == 'x') { + return 323.15; + } else { + return 459.21; + } + break; + case 'C7': + if (axis == 'x') { + return 229.61; + } else { + return 323.15; + } + break; + case 'C8': + if (axis == 'x') { + return 161.57; + } else { + return 229.61; + } + break; + case 'C9': + if (axis == 'x') { + return 113.39; + } else { + return 161.57; + } + break; + case 'C10': + if (axis == 'x') { + return 79.37; + } else { + return 113.39; + } + break; + case 'RA0': + if (axis == 'x') { + return 2437.80; + } else { + return 3458.27; + } + break; + case 'RA1': + if (axis == 'x') { + return 1729.13; + } else { + return 2437.80; + } + break; + case 'RA2': + if (axis == 'x') { + return 1218.90; + } else { + return 1729.13; + } + break; + case 'RA3': + if (axis == 'x') { + return 864.57; + } else { + return 1218.90; + } + break; + case 'RA4': + if (axis == 'x') { + return 609.45; + } else { + return 864.57; + } + break; + case 'SRA0': + if (axis == 'x') { + return 2551.18; + } else { + return 3628.35; + } + break; + case 'SRA1': + if (axis == 'x') { + return 1814.17; + } else { + return 2551.18; + } + break; + case 'SRA2': + if (axis == 'x') { + return 1275.59; + } else { + return 1814.17; + } + break; + case 'SRA3': + if (axis == 'x') { + return 907.09; + } else { + return 1275.59; + } + break; + case 'SRA4': + if (axis == 'x') { + return 637.80; + } else { + return 907.09; + } + break; + case 'LETTER': + if (axis == 'x') { + return 612.00; + } else { + return 792.00; + } + break; + case 'LEGAL': + if (axis == 'x') { + return 612.00; + } else { + return 1008.00; + } + break; + case 'EXECUTIVE': + if (axis == 'x') { + return 521.86; + } else { + return 756.00; + } + break; + case 'FOLIO': + if (axis == 'x') { + return 612.00; + } else { + return 936.00; + } + break; + } // end switch + + return 0; +} + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('functions.js', function() { + $("a.inline_edit_sql").die('click'); + $("input#sql_query_edit_save").die('click'); + $("input#sql_query_edit_discard").die('click'); + $('input.sqlbutton').unbind('click'); + $("#export_type").unbind('change'); + $('#sqlquery').unbind('keydown'); + $('#sql_query_edit').unbind('keydown'); + + if (codemirror_inline_editor) { + // Copy the sql query to the text area to preserve it. + $('#sql_query_edit').text(codemirror_inline_editor.getValue()); + $(codemirror_inline_editor.getWrapperElement()).unbind('keydown'); + codemirror_inline_editor.toTextArea(); + codemirror_inline_editor = false; + } + if (codemirror_editor) { + $(codemirror_editor.getWrapperElement()).unbind('keydown'); + } +}); + +/** + * Jquery Coding for inline editing SQL_QUERY + */ +AJAX.registerOnload('functions.js', function() { + // If we are coming back to the page by clicking forward button + // of the browser, bind the code mirror to inline query editor. + bindCodeMirrorToInlineEditor(); + $("a.inline_edit_sql").live('click', function() { + if ($('#sql_query_edit').length) { + // An inline query editor is already open, + // we don't want another copy of it + return false; + } + + var $form = $(this).prev('form'); + var sql_query = $form.find("input[name='sql_query']").val(); + var $inner_sql = $(this).parent().prev().find('.inner_sql'); + var old_text = $inner_sql.html(); + + var new_content = "<textarea name=\"sql_query_edit\" id=\"sql_query_edit\">" + sql_query + "</textarea>\n"; + new_content += "<input type=\"submit\" id=\"sql_query_edit_save\" class=\"button btnSave\" value=\"" + PMA_messages['strGo'] + "\"/>\n"; + new_content += "<input type=\"button\" id=\"sql_query_edit_discard\" class=\"button btnDiscard\" value=\"" + PMA_messages['strCancel'] + "\"/>\n"; + var $editor_area = $('div#inline_editor'); + if ($editor_area.length == 0) { + $editor_area = $('<div id="inline_editor_outer"></div>'); + $editor_area.insertBefore($inner_sql); + } + $editor_area.html(new_content); + $inner_sql.hide(); + + bindCodeMirrorToInlineEditor(); + return false; + }); + + $("input#sql_query_edit_save").live('click', function() { + if (codemirror_inline_editor) { + var sql_query = codemirror_inline_editor.getValue(); + } else { + var sql_query = $(this).prev().val(); + } + + var $form = $("a.inline_edit_sql").prev('form'); + var $fake_form = $('<form>', {action: 'import.php', method: 'post'}) + .append($form.find("input[name=server], input[name=db], input[name=table], input[name=token]").clone()) + .append($('<input/>', {type: 'hidden', name: 'show_query', value: 1})) + .append($('<input/>', {type: 'hidden', name: 'sql_query', value: sql_query})); + $fake_form.appendTo($('body')).submit(); + }); + + $("input#sql_query_edit_discard").live('click', function() { + $('div#inline_editor_outer') + .empty() + .siblings('.inner_sql').show(); + }); + + $('input.sqlbutton').click(function(evt) { + insertQuery(evt.target.id); + return false; + }); + + $("#export_type").change(function() { + if ($("#export_type").val()=='svg') { + $("#show_grid_opt").prop("disabled",true); + $("#orientation_opt").prop("disabled",true); + $("#with_doc").prop("disabled",true); + $("#show_table_dim_opt").removeProp("disabled"); + $("#all_tables_same_width").removeProp("disabled"); + $("#paper_opt").removeProp("disabled"); + $("#show_color_opt").removeProp("disabled"); + //$(this).css("background-color","yellow"); + } else if ($("#export_type").val()=='dia') { + $("#show_grid_opt").prop("disabled",true); + $("#with_doc").prop("disabled",true); + $("#show_table_dim_opt").prop("disabled",true); + $("#all_tables_same_width").prop("disabled",true); + $("#paper_opt").removeProp("disabled"); + $("#show_color_opt").removeProp("disabled"); + $("#orientation_opt").removeProp("disabled"); + } else if ($("#export_type").val()=='eps') { + $("#show_grid_opt").prop("disabled",true); + $("#orientation_opt").removeProp("disabled"); + $("#with_doc").prop("disabled",true); + $("#show_table_dim_opt").prop("disabled",true); + $("#all_tables_same_width").prop("disabled",true); + $("#paper_opt").prop("disabled",true); + $("#show_color_opt").prop("disabled",true); + } else if ($("#export_type").val()=='pdf') { + $("#show_grid_opt").removeProp("disabled"); + $("#orientation_opt").removeProp("disabled"); + $("#with_doc").removeProp("disabled"); + $("#show_table_dim_opt").removeProp("disabled"); + $("#all_tables_same_width").removeProp("disabled"); + $("#paper_opt").removeProp("disabled"); + $("#show_color_opt").removeProp("disabled"); + } else { + // nothing + } + }); + + if ($('#input_username')) { + if ($('#input_username').val() == '') { + $('#input_username').focus(); + } else { + $('#input_password').focus(); + } + } +}); + +/** + * Binds the CodeMirror to the text area used to inline edit a query. + */ +function bindCodeMirrorToInlineEditor() { + var $inline_editor = $('#sql_query_edit'); + if ($inline_editor.length > 0) { + if (typeof CodeMirror !== 'undefined') { + var height = $('#sql_query_edit').css('height'); + codemirror_inline_editor = CodeMirror.fromTextArea($inline_editor[0], { + lineNumbers: true, + matchBrackets: true, + indentUnit: 4, + mode: "text/x-mysql", + lineWrapping: true + }); + codemirror_inline_editor.getScrollerElement().style.height = height; + codemirror_inline_editor.refresh(); + codemirror_inline_editor.focus(); + $(codemirror_inline_editor.getWrapperElement()).bind( + 'keydown', + catchKeypressesFromSqlTextboxes + ); + } else { + $inline_editor.focus().bind( + 'keydown', + catchKeypressesFromSqlTextboxes + ); + } + } +} + +function catchKeypressesFromSqlTextboxes(event) { + // ctrl-enter is 10 in chrome and ie, but 13 in ff + if (event.ctrlKey && (event.keyCode == 13 || event.keyCode == 10)) { + if ($('#sql_query_edit').length > 0) { + $("#sql_query_edit_save").trigger('click'); + } else if ($('#sqlquery').length > 0) { + $("#button_submit_query").trigger('click'); + } + } +} + +/** + * Show a message on the top of the page for an Ajax request + * + * Sample usage: + * + * 1) var $msg = PMA_ajaxShowMessage(); + * This will show a message that reads "Loading...". Such a message will not + * disappear automatically and cannot be dismissed by the user. To remove this + * message either the PMA_ajaxRemoveMessage($msg) function must be called or + * another message must be show with PMA_ajaxShowMessage() function. + * + * 2) var $msg = PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); + * This is a special case. The behaviour is same as above, + * just with a different message + * + * 3) var $msg = PMA_ajaxShowMessage('The operation was successful'); + * This will show a message that will disappear automatically and it can also + * be dismissed by the user. + * + * 4) var $msg = PMA_ajaxShowMessage('Some error', false); + * This will show a message that will not disappear automatically, but it + * can be dismissed by the user after he has finished reading it. + * + * @param string message string containing the message to be shown. + * optional, defaults to 'Loading...' + * @param mixed timeout number of milliseconds for the message to be visible + * optional, defaults to 5000. If set to 'false', the + * notification will never disappear + * @return jQuery object jQuery Element that holds the message div + * this object can be passed to PMA_ajaxRemoveMessage() + * to remove the notification + */ +function PMA_ajaxShowMessage(message, timeout) +{ + /** + * @var self_closing Whether the notification will automatically disappear + */ + var self_closing = true; + /** + * @var dismissable Whether the user will be able to remove + * the notification by clicking on it + */ + var dismissable = true; + // Handle the case when a empty data.message is passed. + // We don't want the empty message + if (message == '') { + return true; + } else if (! message) { + // If the message is undefined, show the default + message = PMA_messages['strLoading']; + dismissable = false; + self_closing = false; + } else if (message == PMA_messages['strProcessingRequest']) { + // This is another case where the message should not disappear + dismissable = false; + self_closing = false; + } + // Figure out whether (or after how long) to remove the notification + if (timeout == undefined) { + timeout = 5000; + } else if (timeout === false) { + self_closing = false; + } + // Create a parent element for the AJAX messages, if necessary + if ($('#loading_parent').length == 0) { + $('<div id="loading_parent"></div>') + .prependTo("body"); + } + // Update message count to create distinct message elements every time + ajax_message_count++; + // Remove all old messages, if any + $("span.ajax_notification[id^=ajax_message_num]").remove(); + /** + * @var $retval a jQuery object containing the reference + * to the created AJAX message + */ + var $retval = $( + '<span class="ajax_notification" id="ajax_message_num_' + + ajax_message_count + + '"></span>' + ) + .hide() + .appendTo("#loading_parent") + .html(message) + .show(); + // If the notification is self-closing we should create a callback to remove it + if (self_closing) { + $retval + .delay(timeout) + .fadeOut('medium', function() { + if ($(this).is('.dismissable')) { + $(this).tooltip('destroy'); + } + // Remove the notification + $(this).remove(); + }); + } + // If the notification is dismissable we need to add the relevant class to it + // and add a tooltip so that the users know that it can be removed + if (dismissable) { + $retval.addClass('dismissable').css('cursor', 'pointer'); + /** + * Add a tooltip to the notification to let the user know that (s)he + * can dismiss the ajax notification by clicking on it. + */ + PMA_tooltip( + $retval, + 'span', + PMA_messages['strDismiss'] + ); + } + + return $retval; +} + +/** + * Removes the message shown for an Ajax operation when it's completed + * + * @param jQuery object jQuery Element that holds the notification + * + * @return nothing + */ +function PMA_ajaxRemoveMessage($this_msgbox) +{ + if ($this_msgbox != undefined && $this_msgbox instanceof jQuery) { + $this_msgbox + .stop(true, true) + .fadeOut('medium'); + if ($this_msgbox.is('.dismissable')) { + if ($.isFunction($this_msgbox.tooltip)) { + $this_msgbox.tooltip('destroy'); + } + } else { + $this_msgbox.remove(); + } + } +} + +// This event only need to be fired once after the initial page load +$(function() { + /** + * Allows the user to dismiss a notification + * created with PMA_ajaxShowMessage() + */ + $('span.ajax_notification.dismissable').live('click', function () { + PMA_ajaxRemoveMessage($(this)); + }); + /** + * The below two functions hide the "Dismiss notification" tooltip when a user + * is hovering a link or button that is inside an ajax message + */ + $('span.ajax_notification a, span.ajax_notification button, span.ajax_notification input') + .live('mouseover', function () { + $(this).parents('span.ajax_notification').tooltip('disable'); + }) + .live('mouseout', function () { + $(this).parents('span.ajax_notification').tooltip('enable'); + }); +}); + +/** + * Hides/shows the "Open in ENUM/SET editor" message, depending on the data type of the column currently selected + */ +function PMA_showNoticeForEnum(selectElement) +{ + var enum_notice_id = selectElement.attr("id").split("_")[1]; + enum_notice_id += "_" + (parseInt(selectElement.attr("id").split("_")[2]) + 1); + var selectedType = selectElement.val(); + if (selectedType == "ENUM" || selectedType == "SET") { + $("p#enum_notice_" + enum_notice_id).show(); + } else { + $("p#enum_notice_" + enum_notice_id).hide(); + } +} + +/* + * Creates a Profiling Chart with jqplot. Used in sql.js + * and in server_status_monitor.js + */ +function PMA_createProfilingChartJqplot(target, data) +{ + return $.jqplot(target, [data], + { + seriesDefaults: { + renderer: $.jqplot.PieRenderer, + rendererOptions: { + showDataLabels: true + } + }, + legend: { + show: true, + location: 'e' + }, + // from http://tango.freedesktop.org/Tango_Icon_Theme_Guidelines#Color_Palette + seriesColors: [ + '#fce94f', + '#fcaf3e', + '#e9b96e', + '#8ae234', + '#729fcf', + '#ad7fa8', + '#ef2929', + '#eeeeec', + '#888a85', + '#c4a000', + '#ce5c00', + '#8f5902', + '#4e9a06', + '#204a87', + '#5c3566', + '#a40000', + '#babdb6', + '#2e3436' + ] + } + ); +} + +/** + * Formats a profiling duration nicely (in us and ms time). Used in server_status.js + * + * @param integer Number to be formatted, should be in the range of microsecond to second + * @param integer Accuracy, how many numbers right to the comma should be + * @return string The formatted number + */ +function PMA_prettyProfilingNum(num, acc) +{ + if (!acc) { + acc = 2; + } + acc = Math.pow(10, acc); + if (num * 1000 < 0.1) { + num = Math.round(acc * (num * 1000 * 1000)) / acc + 'µ'; + } else if (num < 0.1) { + num = Math.round(acc * (num * 1000)) / acc + 'm'; + } else { + num = Math.round(acc * num) / acc; + } + + return num + 's'; +} + + +/** + * Formats a SQL Query nicely with newlines and indentation. Depends on Codemirror and MySQL Mode! + * + * @param string Query to be formatted + * @return string The formatted query + */ +function PMA_SQLPrettyPrint(string) +{ + if (typeof CodeMirror == 'undefined') { + return string; + } + + var mode = CodeMirror.getMode({},"text/x-mysql"); + var stream = new CodeMirror.StringStream(string); + var state = mode.startState(); + var token, tokens = []; + var output = ''; + var tabs = function(cnt) { + var ret = ''; + for (var i=0; i<4*cnt; i++) { + ret += " "; + } + return ret; + }; + + // "root-level" statements + var statements = { + 'select': ['select', 'from','on','where','having','limit','order by','group by'], + 'update': ['update', 'set','where'], + 'insert into': ['insert into', 'values'] + }; + // don't put spaces before these tokens + var spaceExceptionsBefore = { ';':true, ',': true, '.': true, '(': true }; + // don't put spaces after these tokens + var spaceExceptionsAfter = { '.': true }; + + // Populate tokens array + var str=''; + while (! stream.eol()) { + stream.start = stream.pos; + token = mode.token(stream, state); + if (token != null) { + tokens.push([token, stream.current().toLowerCase()]); + } + } + + var currentStatement = tokens[0][1]; + + if (! statements[currentStatement]) { + return string; + } + // Holds all currently opened code blocks (statement, function or generic) + var blockStack = []; + // Holds the type of block from last iteration (the current is in blockStack[0]) + var previousBlock; + // If a new code block is found, newBlock contains its type for one iteration and vice versa for endBlock + var newBlock, endBlock; + // How much to indent in the current line + var indentLevel = 0; + // Holds the "root-level" statements + var statementPart, lastStatementPart = statements[currentStatement][0]; + + blockStack.unshift('statement'); + + // Iterate through every token and format accordingly + for (var i = 0; i < tokens.length; i++) { + previousBlock = blockStack[0]; + + // New block => push to stack + if (tokens[i][1] == '(') { + if (i < tokens.length - 1 && tokens[i+1][0] == 'statement-verb') { + blockStack.unshift(newBlock = 'statement'); + } else if (i > 0 && tokens[i-1][0] == 'builtin') { + blockStack.unshift(newBlock = 'function'); + } else { + blockStack.unshift(newBlock = 'generic'); + } + } else { + newBlock = null; + } + + // Block end => pop from stack + if (tokens[i][1] == ')') { + endBlock = blockStack[0]; + blockStack.shift(); + } else { + endBlock = null; + } + + // A subquery is starting + if (i > 0 && newBlock == 'statement') { + indentLevel++; + output += "\n" + tabs(indentLevel) + tokens[i][1] + ' ' + tokens[i+1][1].toUpperCase() + "\n" + tabs(indentLevel + 1); + currentStatement = tokens[i+1][1]; + i++; + continue; + } + + // A subquery is ending + if (endBlock == 'statement' && indentLevel > 0) { + output += "\n" + tabs(indentLevel); + indentLevel--; + } + + // One less indentation for statement parts (from, where, order by, etc.) and a newline + statementPart = statements[currentStatement].indexOf(tokens[i][1]); + if (statementPart != -1) { + if (i > 0) { + output += "\n"; + } + output += tabs(indentLevel) + tokens[i][1].toUpperCase(); + output += "\n" + tabs(indentLevel + 1); + lastStatementPart = tokens[i][1]; + } + // Normal indentatin and spaces for everything else + else { + if (! spaceExceptionsBefore[tokens[i][1]] + && ! (i > 0 && spaceExceptionsAfter[tokens[i-1][1]]) + && output.charAt(output.length -1) != ' ' ) { + output += " "; + } + if (tokens[i][0] == 'keyword') { + output += tokens[i][1].toUpperCase(); + } else { + output += tokens[i][1]; + } + } + + // split columns in select and 'update set' clauses, but only inside statements blocks + if (( lastStatementPart == 'select' || lastStatementPart == 'where' || lastStatementPart == 'set') + && tokens[i][1]==',' && blockStack[0] == 'statement') { + + output += "\n" + tabs(indentLevel + 1); + } + + // split conditions in where clauses, but only inside statements blocks + if (lastStatementPart == 'where' + && (tokens[i][1]=='and' || tokens[i][1]=='or' || tokens[i][1]=='xor')) { + + if (blockStack[0] == 'statement') { + output += "\n" + tabs(indentLevel + 1); + } + // Todo: Also split and or blocks in newlines & identation++ + //if (blockStack[0] == 'generic') + // output += ... + } + } + return output; +} + +/** + * jQuery function that uses jQueryUI's dialogs to confirm with user. Does not + * return a jQuery object yet and hence cannot be chained + * + * @param string question + * @param string url URL to be passed to the callbackFn to make + * an Ajax call to + * @param function callbackFn callback to execute after user clicks on OK + */ + +jQuery.fn.PMA_confirm = function(question, url, callbackFn) { + var confirmState = PMA_commonParams.get('confirm'); + // when the Confirm directive is set to false in config.inc.php + // and not changed in user prefs, confirmState is "" + // when it's unticked in user prefs, confirmState is 1 + if (confirmState === "" || confirmState === "1") { + // user does not want to confirm + if ($.isFunction(callbackFn)) { + callbackFn.call(this, url); + return true; + } + } + if (PMA_messages['strDoYouReally'] == '') { + return true; + } + + /** + * @var button_options Object that stores the options passed to jQueryUI + * dialog + */ + var button_options = {}; + button_options[PMA_messages['strOK']] = function() { + $(this).dialog("close"); + + if ($.isFunction(callbackFn)) { + callbackFn.call(this, url); + } + }; + button_options[PMA_messages['strCancel']] = function() { + $(this).dialog("close"); + }; + + $('<div/>', {'id':'confirm_dialog'}) + .prepend(question) + .dialog({ + buttons: button_options, + close: function () { + $(this).remove(); + }, + modal: true + }); +}; + +/** + * jQuery function to sort a table's body after a new row has been appended to it. + * Also fixes the even/odd classes of the table rows at the end. + * + * @param string text_selector string to select the sortKey's text + * + * @return jQuery Object for chaining purposes + */ +jQuery.fn.PMA_sort_table = function(text_selector) { + return this.each(function() { + + /** + * @var table_body Object referring to the table's <tbody> element + */ + var table_body = $(this); + /** + * @var rows Object referring to the collection of rows in {@link table_body} + */ + var rows = $(this).find('tr').get(); + + //get the text of the field that we will sort by + $.each(rows, function(index, row) { + row.sortKey = $.trim($(row).find(text_selector).text().toLowerCase()); + }); + + //get the sorted order + rows.sort(function(a, b) { + if (a.sortKey < b.sortKey) { + return -1; + } + if (a.sortKey > b.sortKey) { + return 1; + } + return 0; + }); + + //pull out each row from the table and then append it according to it's order + $.each(rows, function(index, row) { + $(table_body).append(row); + row.sortKey = null; + }); + + //Re-check the classes of each row + $(this).find('tr:odd') + .removeClass('even').addClass('odd') + .end() + .find('tr:even') + .removeClass('odd').addClass('even'); + }); +}; + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('functions.js', function() { + $("#create_table_form_minimal.ajax").die('submit'); + $("form.create_table_form.ajax").die('submit'); + $("form.create_table_form.ajax input[name=submit_num_fields]").die('click'); + $("form.create_table_form.ajax input").die('keyup'); +}); + +/** + * jQuery coding for 'Create Table'. Used on db_operations.php, + * db_structure.php and db_tracking.php (i.e., wherever + * libraries/display_create_table.lib.php is used) + * + * Attach Ajax Event handlers for Create Table + */ +AJAX.registerOnload('functions.js', function() { + /** + * Attach event handler for submission of create table form (save) + */ + $("form.create_table_form.ajax").live('submit', function(event) { + event.preventDefault(); + + /** + * @var the_form object referring to the create table form + */ + var $form = $(this); + + /* + * First validate the form; if there is a problem, avoid submitting it + * + * checkTableEditForm() needs a pure element and not a jQuery object, + * this is why we pass $form[0] as a parameter (the jQuery object + * is actually an array of DOM elements) + */ + + if (checkTableEditForm($form[0], $form.find('input[name=orig_num_fields]').val())) { + PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); + PMA_prepareForAjaxRequest($form); + //User wants to submit the form + $.post($form.attr('action'), $form.serialize() + "&do_save_data=1", function(data) { + if (data.success == true) { + $('#properties_message') + .removeClass('error') + .html(''); + PMA_ajaxShowMessage(data.message); + // Only if the create table dialog (distinct panel) exists + if ($("#create_table_dialog").length > 0) { + $("#create_table_dialog").dialog("close").remove(); + } + $('#tableslistcontainer').before(data.formatted_sql); + + /** + * @var tables_table Object referring to the <tbody> element that holds the list of tables + */ + var tables_table = $("#tablesForm").find("tbody").not("#tbl_summary_row"); + // this is the first table created in this db + if (tables_table.length == 0) { + PMA_commonActions.refreshMain( + PMA_commonParams.get('opendb_url') + ); + } else { + /** + * @var curr_last_row Object referring to the last <tr> element in {@link tables_table} + */ + var curr_last_row = $(tables_table).find('tr:last'); + /** + * @var curr_last_row_index_string String containing the index of {@link curr_last_row} + */ + var curr_last_row_index_string = $(curr_last_row).find('input:checkbox').attr('id').match(/\d+/)[0]; + /** + * @var curr_last_row_index Index of {@link curr_last_row} + */ + var curr_last_row_index = parseFloat(curr_last_row_index_string); + /** + * @var new_last_row_index Index of the new row to be appended to {@link tables_table} + */ + var new_last_row_index = curr_last_row_index + 1; + /** + * @var new_last_row_id String containing the id of the row to be appended to {@link tables_table} + */ + var new_last_row_id = 'checkbox_tbl_' + new_last_row_index; + + data.new_table_string = data.new_table_string.replace(/checkbox_tbl_/, new_last_row_id); + //append to table + $(data.new_table_string) + .appendTo(tables_table); + + //Sort the table + $(tables_table).PMA_sort_table('th'); + + // Adjust summary row + PMA_adjustTotals(); + } + + //Refresh navigation as a new table has been added + PMA_reloadNavigation(); + } else { + PMA_ajaxShowMessage( + '<div class="error">' + data.error + '</div>', + false + ); + } + }); // end $.post() + } // end if (checkTableEditForm() ) + }); // end create table form (save) + + /** + * Attach event handler for create table form (add fields) + */ + $("form.create_table_form.ajax input[name=submit_num_fields]").live('click', function(event) { + event.preventDefault(); + /** + * @var the_form object referring to the create table form + */ + var $form = $(this).closest('form'); + + var $msgbox = PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); + PMA_prepareForAjaxRequest($form); + + //User wants to add more fields to the table + $.post($form.attr('action'), $form.serialize() + "&submit_num_fields=1", function(data) { + if (data.success) { + $("#page_content").html(data.message); + PMA_verifyColumnsProperties(); + PMA_ajaxRemoveMessage($msgbox); + } else { + PMA_ajaxShowMessage(data.error); + } + }); //end $.post() + }); // end create table form (add fields) + + $("form.create_table_form.ajax input").live('keydown', function (event) { + if (event.keyCode == 13) { + event.preventDefault(); + event.stopImmediatePropagation(); + $(this) + .closest('form') + .append('<input type="hidden" name="do_save_data" value="1" />') + .submit(); + } + }); +}); + + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('functions.js', function() { + $("#copyTable.ajax").die('submit'); + $("#moveTableForm").die('submit'); + $("#tableOptionsForm").die('submit'); + $("#tbl_maintenance li a.maintain_action.ajax").die('click'); +}); +/** + * jQuery coding for 'Table operations'. Used on tbl_operations.php + * Attach Ajax Event handlers for Table operations + */ +AJAX.registerOnload('functions.js', function() { + /** + *Ajax action for submitting the "Copy table" + **/ + $("#copyTable.ajax").live('submit', function(event) { + event.preventDefault(); + var $form = $(this); + PMA_prepareForAjaxRequest($form); + $.post($form.attr('action'), $form.serialize()+"&submit_copy=Go", function(data) { + if (data.success == true) { + if ($form.find("input[name='switch_to_new']").prop('checked')) { + PMA_commonParams.set( + 'db', + data.db + ); + PMA_commonParams.set( + 'table', + $form.find("input[name='new_name']").val() + ); + PMA_commonActions.refreshMain(false, function () { + PMA_ajaxShowMessage(data.message); + }); + } else { + PMA_ajaxShowMessage(data.message); + } + // Refresh navigation when the table is copied + PMA_reloadNavigation(); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.post() + });//end of copyTable ajax submit + + /** + *Ajax action for submitting the "Move table" + */ + $("#moveTableForm").live('submit', function(event) { + event.preventDefault(); + var $form = $(this); + var db = $form.find('select[name=target_db]').val(); + var tbl = $form.find('input[name=new_name]').val(); + PMA_prepareForAjaxRequest($form); + $.post($form.attr('action'), $form.serialize()+"&submit_move=1", function(data) { + if (data.success == true) { + PMA_commonParams.set('db', db); + PMA_commonParams.set('table', tbl); + PMA_commonActions.refreshMain(false, function () { + PMA_ajaxShowMessage(data.message); + }); + // Refresh navigation when the table is copied + PMA_reloadNavigation(); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.post() + }); + + /** + * Ajax action for submitting the "Table options" + */ + $("#tableOptionsForm").live('submit', function(event) { + event.preventDefault(); + event.stopPropagation(); + var $form = $(this); + var $tblNameField = $form.find('input[name=new_name]'); + if ($tblNameField.val() !== $tblNameField[0].defaultValue) { + // reload page and navigation if the table has been renamed + PMA_prepareForAjaxRequest($form); + var tbl = $tblNameField.val(); + $.post($form.attr('action'), $form.serialize(), function(data) { + if (data.success == true) { + PMA_commonParams.set('table', tbl); + PMA_commonActions.refreshMain(false, function() { + $('#page_content').html(data.message); + }); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.post() + } else { + $form.removeClass('ajax').submit().addClass('ajax'); + } + }); + + /** + *Ajax events for actions in the "Table maintenance" + **/ + $("#tbl_maintenance li a.maintain_action.ajax").live('click', function(event) { + event.preventDefault(); + if ($("#sqlqueryresults").length != 0) { + $("#sqlqueryresults").remove(); + } + if ($("#result_query").length != 0) { + $("#result_query").remove(); + } + //variables which stores the common attributes + $.post($(this).attr('href'), { ajax_request: 1 }, function(data) { + function scrollToTop() { + $('html, body').animate({ scrollTop: 0 }); + } + if (data.success == true && data.sql_query != undefined) { + PMA_ajaxShowMessage(data.message); + $("<div id='sqlqueryresults' class='ajax'></div>").prependTo("#page_content"); + $("#sqlqueryresults").html(data.sql_query); + scrollToTop(); + } else if (data.success == true) { + var $temp_div = $("<div id='temp_div'></div>"); + $temp_div.html(data.message); + var $success = $temp_div.find("#result_query .success"); + PMA_ajaxShowMessage($success); + $("<div id='sqlqueryresults' class='ajax'></div>").prependTo("#page_content"); + $("#sqlqueryresults").html(data.message); + PMA_init_slider(); + $("#sqlqueryresults").children("fieldset,br").remove(); + scrollToTop(); + } else { + var $temp_div = $("<div id='temp_div'></div>"); + $temp_div.html(data.error); + var $error = $temp_div.find("code").addClass("error"); + PMA_ajaxShowMessage($error, false); + } + }); // end $.post() + });//end of table maintanance ajax click +}); //end $(document).ready for 'Table operations' + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('functions.js', function() { + $("#drop_db_anchor.ajax").die('click'); +}); +/** + * Attach Ajax event handlers for Drop Database. Moved here from db_structure.js + * as it was also required on db_create.php + */ +AJAX.registerOnload('functions.js', function() { + $("#drop_db_anchor.ajax").live('click', function(event) { + event.preventDefault(); + /** + * @var question String containing the question to be asked for confirmation + */ + var question = PMA_messages.strDropDatabaseStrongWarning + ' '; + question += $.sprintf( + PMA_messages.strDoYouReally, + 'DROP DATABASE ' + escapeHtml(PMA_commonParams.get('db')) + ); + $(this).PMA_confirm(question, $(this).attr('href'), function(url) { + PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); + $.get(url, {'is_js_confirmed': '1', 'ajax_request': true}, function(data) { + if (data.success) { + //Database deleted successfully, refresh both the frames + PMA_reloadNavigation(); + PMA_commonParams.set('db', ''); + PMA_commonActions.refreshMain( + 'server_databases.php', + function () { + PMA_ajaxShowMessage(data.message); + } + ); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); + }); + }); +}); // end of $() for Drop Database + +/** + * Validates the password field in a form + * + * @see PMA_messages['strPasswordEmpty'] + * @see PMA_messages['strPasswordNotSame'] + * @param object $the_form The form to be validated + * @return bool + */ +function PMA_checkPassword($the_form) +{ + // Did the user select 'no password'? + if ($the_form.find('#nopass_1').is(':checked')) { + return true; + } else { + var $pred = $the_form.find('#select_pred_password'); + if ($pred.length && ($pred.val() == 'none' || $pred.val() == 'keep')) { + return true; + } + } + + var $password = $the_form.find('input[name=pma_pw]'); + var $password_repeat = $the_form.find('input[name=pma_pw2]'); + var alert_msg = false; + + if ($password.val() == '') { + alert_msg = PMA_messages['strPasswordEmpty']; + } else if ($password.val() != $password_repeat.val()) { + alert_msg = PMA_messages['strPasswordNotSame']; + } + + if (alert_msg) { + alert(alert_msg); + $password.val(''); + $password_repeat.val(''); + $password.focus(); + return false; + } + return true; +} + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('functions.js', function() { + $('#change_password_anchor.ajax').die('click'); +}); +/** + * Attach Ajax event handlers for 'Change Password' on index.php + */ +AJAX.registerOnload('functions.js', function() { + + /** + * Attach Ajax event handler on the change password anchor + */ + $('#change_password_anchor.ajax').live('click', function(event) { + event.preventDefault(); + + var $msgbox = PMA_ajaxShowMessage(); + + /** + * @var button_options Object containing options to be passed to jQueryUI's dialog + */ + var button_options = {}; + button_options[PMA_messages['strGo']] = function() { + + event.preventDefault(); + + /** + * @var $the_form Object referring to the change password form + */ + var $the_form = $("#change_password_form"); + + if (! PMA_checkPassword($the_form)) { + return false; + } + + /** + * @var this_value String containing the value of the submit button. + * Need to append this for the change password form on Server Privileges + * page to work + */ + var this_value = $(this).val(); + + var $msgbox = PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); + $the_form.append('<input type="hidden" name="ajax_request" value="true" />'); + + $.post($the_form.attr('action'), $the_form.serialize() + '&change_pw='+ this_value, function(data) { + if (data.success == true) { + $("#page_content").prepend(data.message); + $("#change_password_dialog").hide().remove(); + $("#edit_user_dialog").dialog("close").remove(); + PMA_ajaxRemoveMessage($msgbox); + } + else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.post() + }; + + button_options[PMA_messages['strCancel']] = function() { + $(this).dialog('close'); + }; + $.get($(this).attr('href'), {'ajax_request': true}, function(data) { + if (data.success) { + $('<div id="change_password_dialog"></div>') + .dialog({ + title: PMA_messages['strChangePassword'], + width: 600, + close: function(ev, ui) { + $(this).remove(); + }, + buttons : button_options, + modal: true + }) + .append(data.message); + // for this dialog, we remove the fieldset wrapping due to double headings + $("fieldset#fieldset_change_password") + .find("legend").remove().end() + .find("table.noclick").unwrap().addClass("some-margin") + .find("input#text_pma_pw").focus(); + displayPasswordGenerateButton(); + $('#fieldset_change_password_footer').hide(); + PMA_ajaxRemoveMessage($msgbox); + $('#change_password_form').bind('submit', function (e) { + e.preventDefault(); + $(this) + .closest('.ui-dialog') + .find('.ui-dialog-buttonpane .ui-button') + .first() + .click(); + }); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.get() + }); // end handler for change password anchor +}); // end $() for Change Password + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('functions.js', function() { + $("select.column_type").die('change'); + $("select.default_type").die('change'); + $('input.allow_null').die('change'); +}); +/** + * Toggle the hiding/showing of the "Open in ENUM/SET editor" message when + * the page loads and when the selected data type changes + */ +AJAX.registerOnload('functions.js', function() { + // is called here for normal page loads and also when opening + // the Create table dialog + PMA_verifyColumnsProperties(); + // + // needs live() to work also in the Create Table dialog + $("select.column_type").live('change', function() { + PMA_showNoticeForEnum($(this)); + }); + $("select.default_type").live('change', function() { + PMA_hideShowDefaultValue($(this)); + }); + $('input.allow_null').live('change', function() { + PMA_validateDefaultValue($(this)); + }); +}); + +function PMA_verifyColumnsProperties() +{ + $("select.column_type").each(function() { + PMA_showNoticeForEnum($(this)); + }); + $("select.default_type").each(function() { + PMA_hideShowDefaultValue($(this)); + }); +} + +/** + * Hides/shows the default value input field, depending on the default type + * Ticks the NULL checkbox if NULL is chosen as default value. + */ +function PMA_hideShowDefaultValue($default_type) +{ + if ($default_type.val() == 'USER_DEFINED') { + $default_type.siblings('.default_value').show().focus(); + } else { + $default_type.siblings('.default_value').hide(); + if ($default_type.val() == 'NULL') { + var $null_checkbox = $default_type.closest('tr').find('.allow_null'); + $null_checkbox.prop('checked', true); + } + } +} + +/** + * If the column does not allow NULL values, makes sure that default is not NULL + */ +function PMA_validateDefaultValue($null_checkbox) +{ + if (! $null_checkbox.prop('checked')) { + var $default = $null_checkbox.closest('tr').find('.default_type'); + if ($default.val() == 'NULL') { + $default.val('NONE'); + } + } +} + + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('functions.js', function() { + $("a.open_enum_editor").die('click'); + $("input.add_value").die('click'); + $("#enum_editor td.drop").die('click'); +}); +/** + * @var $enum_editor_dialog An object that points to the jQuery + * dialog of the ENUM/SET editor + */ +var $enum_editor_dialog = null; +/** + * Opens the ENUM/SET editor and controls its functions + */ +AJAX.registerOnload('functions.js', function() { + $("a.open_enum_editor").live('click', function() { + // Get the name of the column that is being edited + var colname = $(this).closest('tr').find('input:first').val(); + // And use it to make up a title for the page + if (colname.length < 1) { + var title = PMA_messages['enum_newColumnVals']; + } else { + var title = PMA_messages['enum_columnVals'].replace( + /%s/, + '"' + decodeURIComponent(colname) + '"' + ); + } + // Get the values as a string + var inputstring = $(this) + .closest('td') + .find("input") + .val(); + // Escape html entities + inputstring = $('<div/>') + .text(inputstring) + .html(); + // Parse the values, escaping quotes and + // slashes on the fly, into an array + var values = []; + var in_string = false; + var curr, next, buffer = ''; + for (var i=0; i<inputstring.length; i++) { + curr = inputstring.charAt(i); + next = i == inputstring.length ? '' : inputstring.charAt(i+1); + if (! in_string && curr == "'") { + in_string = true; + } else if (in_string && curr == "\\" && next == "\\") { + buffer += "\"; + i++; + } else if (in_string && next == "'" && (curr == "'" || curr == "\\")) { + buffer += "'"; + i++; + } else if (in_string && curr == "'") { + in_string = false; + values.push(buffer); + buffer = ''; + } else if (in_string) { + buffer += curr; + } + } + if (buffer.length > 0) { + // The leftovers in the buffer are the last value (if any) + values.push(buffer); + } + var fields = ''; + // If there are no values, maybe the user is about to make a + // new list so we add a few for him/her to get started with. + if (values.length == 0) { + values.push('','','',''); + } + // Add the parsed values to the editor + var drop_icon = PMA_getImage('b_drop.png'); + for (var i=0; i<values.length; i++) { + fields += "<tr><td>" + + "<input type='text' value='" + values[i] + "'/>" + + "</td><td class='drop'>" + + drop_icon + + "</td></tr>"; + } + /** + * @var dialog HTML code for the ENUM/SET dialog + */ + var dialog = "<div id='enum_editor'>" + + "<fieldset>" + + "<legend>" + title + "</legend>" + + "<p>" + PMA_getImage('s_notice.png') + + PMA_messages['enum_hint'] + "</p>" + + "<table class='values'>" + fields + "</table>" + + "</fieldset><fieldset class='tblFooters'>" + + "<table class='add'><tr><td>" + + "<div class='slider'></div>" + + "</td><td>" + + "<form><div><input type='submit' class='add_value' value='" + + $.sprintf(PMA_messages['enum_addValue'], 1) + + "'/></div></form>" + + "</td></tr></table>" + + "<input type='hidden' value='" // So we know which column's data is being edited + + $(this).closest('td').find("input").attr("id") + + "' />" + + "</fieldset>" + + "</div>"; + /** + * @var Defines functions to be called when the buttons in + * the buttonOptions jQuery dialog bar are pressed + */ + var buttonOptions = {}; + buttonOptions[PMA_messages['strGo']] = function () { + // When the submit button is clicked, + // put the data back into the original form + var value_array = []; + $(this).find(".values input").each(function(index, elm) { + var val = elm.value.replace(/\\/g, '\\\\').replace(/'/g, "''"); + value_array.push("'" + val + "'"); + }); + // get the Length/Values text field where this value belongs + var values_id = $(this).find("input[type='hidden']").val(); + $("input#" + values_id).val(value_array.join(",")); + $(this).dialog("close"); + }; + buttonOptions[PMA_messages['strClose']] = function () { + $(this).dialog("close"); + }; + // Show the dialog + var width = parseInt( + (parseInt($('html').css('font-size'), 10)/13)*340, + 10 + ); + if (! width) { + width = 340; + } + $enum_editor_dialog = $(dialog).dialog({ + minWidth: width, + modal: true, + title: PMA_messages['enum_editor'], + buttons: buttonOptions, + open: function() { + // Focus the "Go" button after opening the dialog + $(this).closest('.ui-dialog').find('.ui-dialog-buttonpane button:first').focus(); + }, + close: function() { + $(this).remove(); + } + }); + // slider for choosing how many fields to add + $enum_editor_dialog.find(".slider").slider({ + animate: true, + range: "min", + value: 1, + min: 1, + max: 9, + slide: function( event, ui ) { + $(this).closest('table').find('input[type=submit]').val( + $.sprintf(PMA_messages['enum_addValue'], ui.value) + ); + } + }); + // Focus the slider, otherwise it looks nearly transparent + $('a.ui-slider-handle').addClass('ui-state-focus'); + return false; + }); + + // When "add a new value" is clicked, append an empty text field + $("input.add_value").live('click', function(e) { + e.preventDefault(); + var num_new_rows = $enum_editor_dialog.find("div.slider").slider('value'); + while (num_new_rows--) { + $enum_editor_dialog.find('.values') + .append( + "<tr style='display: none;'><td>" + + "<input type='text' />" + + "</td><td class='drop'>" + + PMA_getImage('b_drop.png') + + "</td></tr>" + ) + .find('tr:last') + .show('fast'); + } + }); + + // Removes the specified row from the enum editor + $("#enum_editor td.drop").live('click', function() { + $(this).closest('tr').hide('fast', function () { + $(this).remove(); + }); + }); +}); + +/** + * Ensures indexes names are valid according to their type and, for a primary + * key, lock index name to 'PRIMARY' + * @param string form_id Variable which parses the form name as + * the input + * @return boolean false if there is no index form, true else + */ +function checkIndexName(form_id) +{ + if ($("#"+form_id).length == 0) { + return false; + } + + // Gets the elements pointers + var $the_idx_name = $("#input_index_name"); + var $the_idx_type = $("#select_index_type"); + + // Index is a primary key + if ($the_idx_type.find("option:selected").val() == 'PRIMARY') { + $the_idx_name.val('PRIMARY'); + $the_idx_name.prop("disabled", true); + } + + // Other cases + else { + if ($the_idx_name.val() == 'PRIMARY') { + $the_idx_name.val(""); + } + $the_idx_name.prop("disabled", false); + } + + return true; +} // end of the 'checkIndexName()' function + +AJAX.registerTeardown('functions.js', function() { + $('#index_frm input[type=submit]').die('click'); +}); +AJAX.registerOnload('functions.js', function() { + /** + * Handler for adding more columns to an index in the editor + */ + $('#index_frm input[type=submit]').live('click', function(event) { + event.preventDefault(); + var rows_to_add = $(this) + .closest('fieldset') + .find('.slider') + .slider('value'); + while (rows_to_add--) { + var $newrow = $('#index_columns') + .find('tbody > tr:first') + .clone() + .appendTo( + $('#index_columns').find('tbody') + ); + $newrow.find(':input').each(function() { + $(this).val(''); + }); + // focus index size input on column picked + $newrow.find('select').change(function() { + if ($(this).find("option:selected").val() == '') { + return true; + } + $(this).closest("tr").find("input").focus(); + }); + } + }); +}); + +function indexEditorDialog(url, title, callback_success, callback_failure) +{ + /*Remove the hidden dialogs if there are*/ + if ($('#edit_index_dialog').length != 0) { + $('#edit_index_dialog').remove(); + } + var $div = $('<div id="edit_index_dialog"></div>'); + + /** + * @var button_options Object that stores the options + * passed to jQueryUI dialog + */ + var button_options = {}; + button_options[PMA_messages['strGo']] = function() { + /** + * @var the_form object referring to the export form + */ + var $form = $("#index_frm"); + PMA_prepareForAjaxRequest($form); + //User wants to submit the form + $.post($form.attr('action'), $form.serialize()+"&do_save_data=1", function(data) { + if ($("#sqlqueryresults").length != 0) { + $("#sqlqueryresults").remove(); + } + if (data.success == true) { + PMA_ajaxShowMessage(data.message); + if ($('#result_query').length) { + $('#result_query').remove(); + } + if (data.sql_query) { + $('<div id="result_query"></div>') + .html(data.sql_query) + .prependTo('#page_content'); + } + $("#result_query .notice").remove(); + $("#result_query").prepend(data.message); + /*Reload the field form*/ + $("#table_index").remove(); + var $temp_div = $("<div id='temp_div'><div>").append(data.index_table); + $temp_div.find("#table_index").insertAfter("#index_header"); + if ($("#edit_index_dialog").length > 0) { + $("#edit_index_dialog").dialog("close"); + } + $('div.no_indexes_defined').hide(); + if (callback_success) { + callback_success(); + } + PMA_reloadNavigation(); + } else { + var $temp_div = $("<div id='temp_div'><div>").append(data.error); + if ($temp_div.find(".error code").length != 0) { + var $error = $temp_div.find(".error code").addClass("error"); + } else { + var $error = $temp_div; + } + if (callback_failure) { + callback_failure(); + } + PMA_ajaxShowMessage($error, false); + } + }); // end $.post() + }; + button_options[PMA_messages['strCancel']] = function() { + $(this).dialog('close'); + }; + var $msgbox = PMA_ajaxShowMessage(); + $.get("tbl_indexes.php", url, function(data) { + if (data.success == false) { + //in the case of an error, show the error message returned. + PMA_ajaxShowMessage(data.error, false); + } else { + PMA_ajaxRemoveMessage($msgbox); + // Show dialog if the request was successful + $div + .append(data.message) + .dialog({ + title: title, + width: 450, + open: PMA_verifyColumnsProperties, + modal: true, + buttons: button_options, + close: function () { + $(this).remove(); + } + }); + checkIndexType(); + checkIndexName("index_frm"); + PMA_showHints($div); + // Add a slider for selecting how many columns to add to the index + $div.find('.slider').slider({ + animate: true, + value: 1, + min: 1, + max: 16, + slide: function( event, ui ) { + $(this).closest('fieldset').find('input[type=submit]').val( + $.sprintf(PMA_messages['strAddToIndex'], ui.value) + ); + } + }); + // focus index size input on column picked + $div.find('table#index_columns select').change(function() { + if ($(this).find("option:selected").val() == '') { + return true; + } + $(this).closest("tr").find("input").focus(); + }); + // Focus the slider, otherwise it looks nearly transparent + $('a.ui-slider-handle').addClass('ui-state-focus'); + // set focus on index name input, if empty + var input = $div.find('input#input_index_name'); + input.val() || input.focus(); + } + }); // end $.get() +} + +/** + * Function to display tooltips that were + * generated on the PHP side by PMA_Util::showHint() + * + * @param object $div a div jquery object which specifies the + * domain for searching for tooltips. If we + * omit this parameter the function searches + * in the whole body + **/ +function PMA_showHints($div) +{ + if ($div == undefined || ! $div instanceof jQuery || $div.length == 0) { + $div = $("body"); + } + $div.find('.pma_hint').each(function () { + PMA_tooltip( + $(this).children('img'), + 'img', + $(this).children('span').html() + ); + }); +} + +AJAX.registerOnload('functions.js', function() { + PMA_showHints(); +}); + +function PMA_mainMenuResizerCallback() { + // 5 px margin for jumping menu in Chrome + return $(document.body).width() - 5; +} +// This must be fired only once after the inital page load +$(function() { + // Initialise the menu resize plugin + $('#topmenu').menuResizer(PMA_mainMenuResizerCallback); + // register resize event + $(window).resize(function (){ + $('#topmenu').menuResizer('resize'); + }); +}); + +/** + * Get the row number from the classlist (for example, row_1) + */ +function PMA_getRowNumber(classlist) +{ + return parseInt(classlist.split(/\s+row_/)[1]); +} + +/** + * Changes status of slider + */ +function PMA_set_status_label($element) +{ + var text = $element.css('display') == 'none' + ? '+ ' + : '- '; + $element.closest('.slide-wrapper').prev().find('span').text(text); +} + +/** + * var toggleButton This is a function that creates a toggle + * sliding button given a jQuery reference + * to the correct DOM element + */ +var toggleButton = function ($obj) { + // In rtl mode the toggle switch is flipped horizontally + // so we need to take that into account + if ($('span.text_direction', $obj).text() == 'ltr') { + var right = 'right'; + } else { + var right = 'left'; + } + /** + * var h Height of the button, used to scale the + * background image and position the layers + */ + var h = $obj.height(); + $('img', $obj).height(h); + $('table', $obj).css('bottom', h-1); + /** + * var on Width of the "ON" part of the toggle switch + * var off Width of the "OFF" part of the toggle switch + */ + var on = $('td.toggleOn', $obj).width(); + var off = $('td.toggleOff', $obj).width(); + // Make the "ON" and "OFF" parts of the switch the same size + // + 2 pixels to avoid overflowed + $('td.toggleOn > div', $obj).width(Math.max(on, off) + 2); + $('td.toggleOff > div', $obj).width(Math.max(on, off) + 2); + /** + * var w Width of the central part of the switch + */ + var w = parseInt(($('img', $obj).height() / 16) * 22, 10); + // Resize the central part of the switch on the top + // layer to match the background + $('table td:nth-child(2) > div', $obj).width(w); + /** + * var imgw Width of the background image + * var tblw Width of the foreground layer + * var offset By how many pixels to move the background + * image, so that it matches the top layer + */ + var imgw = $('img', $obj).width(); + var tblw = $('table', $obj).width(); + var offset = parseInt(((imgw - tblw) / 2), 10); + // Move the background to match the layout of the top layer + $obj.find('img').css(right, offset); + /** + * var offw Outer width of the "ON" part of the toggle switch + * var btnw Outer width of the central part of the switch + */ + var offw = $('td.toggleOff', $obj).outerWidth(); + var btnw = $('table td:nth-child(2)', $obj).outerWidth(); + // Resize the main div so that exactly one side of + // the switch plus the central part fit into it. + $obj.width(offw + btnw + 2); + /** + * var move How many pixels to move the + * switch by when toggling + */ + var move = $('td.toggleOff', $obj).outerWidth(); + // If the switch is initialized to the + // OFF state we need to move it now. + if ($('div.container', $obj).hasClass('off')) { + if (right == 'right') { + $('div.container', $obj).animate({'left': '-=' + move + 'px'}, 0); + } else { + $('div.container', $obj).animate({'left': '+=' + move + 'px'}, 0); + } + } + // Attach an 'onclick' event to the switch + $('div.container', $obj).click(function () { + if ($(this).hasClass('isActive')) { + return false; + } else { + $(this).addClass('isActive'); + } + var $msg = PMA_ajaxShowMessage(); + var $container = $(this); + var callback = $('span.callback', this).text(); + // Perform the actual toggle + if ($(this).hasClass('on')) { + if (right == 'right') { + var operator = '-='; + } else { + var operator = '+='; + } + var url = $(this).find('td.toggleOff > span').text(); + var removeClass = 'on'; + var addClass = 'off'; + } else { + if (right == 'right') { + var operator = '+='; + } else { + var operator = '-='; + } + var url = $(this).find('td.toggleOn > span').text(); + var removeClass = 'off'; + var addClass = 'on'; + } + $.post(url, {'ajax_request': true}, function(data) { + if (data.success == true) { + PMA_ajaxRemoveMessage($msg); + $container + .removeClass(removeClass) + .addClass(addClass) + .animate({'left': operator + move + 'px'}, function () { + $container.removeClass('isActive'); + }); + eval(callback); + } else { + PMA_ajaxShowMessage(data.error, false); + $container.removeClass('isActive'); + } + }); + }); +}; + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('functions.js', function() { + $('div.container').unbind('click'); +}); +/** + * Initialise all toggle buttons + */ +AJAX.registerOnload('functions.js', function () { + $('div.toggleAjax').each(function () { + var $button = $(this).show(); + $button.find('img').each(function() { + if (this.complete) { + toggleButton($button); + } else { + $(this).load(function () { + toggleButton($button); + }); + } + }); + }); +}); + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('functions.js', function() { + $('.vpointer').die('hover'); + $('.vmarker').die('click'); + $('#pageselector').die('change'); + $('a.formLinkSubmit').die('click'); + $('#update_recent_tables').unbind('ready'); +}); +/** + * Vertical pointer + */ +AJAX.registerOnload('functions.js', function() { + $('.vpointer').live('hover', + //handlerInOut + function(e) { + var $this_td = $(this); + var row_num = PMA_getRowNumber($this_td.attr('class')); + // for all td of the same vertical row, toggle hover + $('.vpointer').filter('.row_' + row_num).toggleClass('hover'); + } + ); + + + /** + * Vertical marker + */ + $('.vmarker').live('click', function(e) { + // do not trigger when clicked on anchor + if ($(e.target).is('a, img, a *')) { + return; + } + + var $this_td = $(this); + var row_num = PMA_getRowNumber($this_td.attr('class')); + + // XXX: FF fires two click events for <label> (label and checkbox), so we need to handle this differently + var $checkbox = $('.vmarker').filter('.row_' + row_num + ':first').find(':checkbox'); + if ($checkbox.length) { + // checkbox in a row, add or remove class depending on checkbox state + var checked = $checkbox.prop('checked'); + if (!$(e.target).is(':checkbox, label')) { + checked = !checked; + $checkbox.prop('checked', checked); + } + // for all td of the same vertical row, toggle the marked class + if (checked) { + $('.vmarker').filter('.row_' + row_num).addClass('marked'); + } else { + $('.vmarker').filter('.row_' + row_num).removeClass('marked'); + } + } else { + // normaln data table, just toggle class + $('.vmarker').filter('.row_' + row_num).toggleClass('marked'); + } + }); + + /** + * Autosubmit page selector + */ + $('select.pageselector').live('change', function(event) { + event.stopPropagation(); + // Check where to load the new content + if ($(this).closest("#pma_navigation").length == 0) { + // For the main page we don't need to do anything, + $(this).closest("form").submit(); + } else { + // but for the navigation we need to manually replace the content + PMA_navigationTreePagination($(this)); + } + }); + + /** + * Load version information asynchronously. + */ + if ($('li.jsversioncheck').length > 0) { + $.getJSON('version_check.php', {}, PMA_current_version); + } + + if ($('#is_git_revision').length > 0) { + setTimeout(PMA_display_git_revision, 10); + } + + /** + * Slider effect. + */ + PMA_init_slider(); + + /** + * Enables the text generated by PMA_Util::linkOrButton() to be clickable + */ + $('a.formLinkSubmit').live('click', function(e) { + + if ($(this).attr('href').indexOf('=') != -1) { + var data = $(this).attr('href').substr($(this).attr('href').indexOf('#')+1).split('=', 2); + $(this).parents('form').append('<input type="hidden" name="' + data[0] + '" value="' + data[1] + '"/>'); + } + $(this).parents('form').submit(); + return false; + }); + + if ($('#update_recent_tables').length) { + $.get( + $('#update_recent_tables').attr('href'), + function (data) { + if (data.success == true) { + $('#recentTable').html(data.options); + } + } + ); + } + +}); // end of $() + + +/** + * Initializes slider effect. + */ +function PMA_init_slider() +{ + $('div.pma_auto_slider').each(function() { + var $this = $(this); + if ($this.data('slider_init_done')) { + return; + } + var $wrapper = $('<div>', {'class': 'slide-wrapper'}); + $wrapper.toggle($this.is(':visible')); + $('<a>', {href: '#'+this.id, "class":'ajax'}) + .text(this.title) + .prepend($('<span>')) + .insertBefore($this) + .click(function() { + var $wrapper = $this.closest('.slide-wrapper'); + var visible = $this.is(':visible'); + if (!visible) { + $wrapper.show(); + } + $this[visible ? 'hide' : 'show']('blind', function() { + $wrapper.toggle(!visible); + PMA_set_status_label($this); + }); + return false; + }); + $this.wrap($wrapper); + PMA_set_status_label($this); + $this.data('slider_init_done', 1); + }); +} + +/** + * Initializes slider effect. + */ +AJAX.registerOnload('functions.js', function() { + PMA_init_slider(); +}); + +/** + * Restores sliders to the state they were in before initialisation. + */ +AJAX.registerTeardown('functions.js', function() { + $('div.pma_auto_slider').each(function() { + var $this = $(this); + $this.removeData(); + $this.parent().replaceWith($this); + $this.parent().children('a').remove(); + }); +}); + +/** + * Creates a message inside an object with a sliding effect + * + * @param msg A string containing the text to display + * @param $obj a jQuery object containing the reference + * to the element where to put the message + * This is optional, if no element is + * provided, one will be created below the + * navigation links at the top of the page + * + * @return bool True on success, false on failure + */ +function PMA_slidingMessage(msg, $obj) +{ + if (msg == undefined || msg.length == 0) { + // Don't show an empty message + return false; + } + if ($obj == undefined || ! $obj instanceof jQuery || $obj.length == 0) { + // If the second argument was not supplied, + // we might have to create a new DOM node. + if ($('#PMA_slidingMessage').length == 0) { + $('#page_content').prepend( + '<span id="PMA_slidingMessage" ' + + 'style="display: inline-block;"></span>' + ); + } + $obj = $('#PMA_slidingMessage'); + } + if ($obj.has('div').length > 0) { + // If there already is a message inside the + // target object, we must get rid of it + $obj + .find('div') + .first() + .fadeOut(function () { + $obj + .children() + .remove(); + $obj + .append('<div style="display: none;">' + msg + '</div>') + .animate({ + height: $obj.find('div').first().height() + }) + .find('div') + .first() + .fadeIn(); + }); + } else { + // Object does not already have a message + // inside it, so we simply slide it down + var h = $obj + .width('100%') + .html('<div style="display: none;">' + msg + '</div>') + .find('div') + .first() + .height(); + $obj + .find('div') + .first() + .css('height', 0) + .show() + .animate({ + height: h + }, function() { + // Set the height of the parent + // to the height of the child + $obj + .height( + $obj + .find('div') + .first() + .height() + ); + }); + } + return true; +} // end PMA_slidingMessage() + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('functions.js', function() { + $("#drop_tbl_anchor.ajax").die('click'); + $("#truncate_tbl_anchor.ajax").die('click'); +}); +/** + * Attach Ajax event handlers for Drop Table. + */ +AJAX.registerOnload('functions.js', function() { + $("#drop_tbl_anchor.ajax").live('click', function(event) { + event.preventDefault(); + /** + * @var question String containing the question to be asked for confirmation + */ + var question = PMA_messages.strDropTableStrongWarning + ' '; + question += $.sprintf( + PMA_messages.strDoYouReally, + 'DROP TABLE ' + PMA_commonParams.get('table') + ); + + $(this).PMA_confirm(question, $(this).attr('href'), function(url) { + + var $msgbox = PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); + $.get(url, {'is_js_confirmed': '1', 'ajax_request': true}, function(data) { + if (data.success == true) { + PMA_ajaxRemoveMessage($msgbox); + // Table deleted successfully, refresh both the frames + PMA_reloadNavigation(); + PMA_commonParams.set('table', ''); + PMA_commonActions.refreshMain( + PMA_commonParams.get('opendb_url'), + function () { + PMA_ajaxShowMessage(data.message); + } + ); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.get() + }); // end $.PMA_confirm() + }); //end of Drop Table Ajax action + + $("#truncate_tbl_anchor.ajax").live('click', function(event) { + event.preventDefault(); + /** + * @var question String containing the question to be asked for confirmation + */ + var question = PMA_messages.strTruncateTableStrongWarning + ' '; + question += $.sprintf( + PMA_messages.strDoYouReally, + 'TRUNCATE ' + PMA_commonParams.get('table') + ); + $(this).PMA_confirm(question, $(this).attr('href'), function(url) { + PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); + $.get(url, {'is_js_confirmed': '1', 'ajax_request': true}, function(data) { + if ($("#sqlqueryresults").length != 0) { + $("#sqlqueryresults").remove(); + } + if ($("#result_query").length != 0) { + $("#result_query").remove(); + } + if (data.success == true) { + PMA_ajaxShowMessage(data.message); + $("<div id='sqlqueryresults'></div>").prependTo("#page_content"); + $("#sqlqueryresults").html(data.sql_query); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.get() + }); // end $.PMA_confirm() + }); //end of Truncate Table Ajax action +}); // end of $() for Truncate Table + +/** + * Attach CodeMirror2 editor to SQL edit area. + */ +AJAX.registerOnload('functions.js', function() { + var $elm = $('#sqlquery'); + if ($elm.length > 0) { + if (typeof CodeMirror != 'undefined') { + // for codemirror + codemirror_editor = CodeMirror.fromTextArea($elm[0], { + lineNumbers: true, + matchBrackets: true, + indentUnit: 4, + mode: "text/x-mysql", + lineWrapping: true + }); + codemirror_editor.focus(); + $(codemirror_editor.getWrapperElement()).bind( + 'keydown', + catchKeypressesFromSqlTextboxes + ); + } else { + // without codemirror + $elm.focus().bind('keydown', catchKeypressesFromSqlTextboxes); + } + } +}); +AJAX.registerTeardown('functions.js', function() { + if (codemirror_editor) { + $('#sqlquery').text(codemirror_editor.getValue()); + codemirror_editor.toTextArea(); + codemirror_editor = false; + } +}); + +/** + * jQuery plugin to cancel selection in HTML code. + */ +(function ($) { + $.fn.noSelect = function (p) { //no select plugin by Paulo P.Marinas + var prevent = (p == null) ? true : p; + if (prevent) { + return this.each(function () { + if ($.browser.msie || $.browser.safari) { + $(this).bind('selectstart', function () { + return false; + }); + } else if ($.browser.mozilla) { + $(this).css('MozUserSelect', 'none'); + $('body').trigger('focus'); + } else if ($.browser.opera) { + $(this).bind('mousedown', function () { + return false; + }); + } else { + $(this).attr('unselectable', 'on'); + } + }); + } else { + return this.each(function () { + if ($.browser.msie || $.browser.safari) { + $(this).unbind('selectstart'); + } else if ($.browser.mozilla) { + $(this).css('MozUserSelect', 'inherit'); + } else if ($.browser.opera) { + $(this).unbind('mousedown'); + } else { + $(this).removeAttr('unselectable'); + } + }); + } + }; //end noSelect +})(jQuery); + +/** + * jQuery plugin to correctly filter input fields by value, needed + * because some nasty values may break selector syntax + */ +(function ($) { + $.fn.filterByValue = function (value) { + return this.filter(function () { + return $(this).val() === value; + }); + }; +})(jQuery); + +/** + * Create a jQuery UI tooltip + * + * @param $elements jQuery object representing the elements + * @param item the item + * (see http://api.jqueryui.com/tooltip/#option-items) + * @param myContent content of the tooltip + * @param additionalOptions to override the default options + * + */ +function PMA_tooltip($elements, item, myContent, additionalOptions) +{ + if ($('#no_hint').length > 0) { + return; + } + + var defaultOptions = { + content: myContent, + items: item, + tooltipClass: "tooltip", + track: true, + show: false, + hide: false + }; + + $elements.tooltip($.extend(true, defaultOptions, additionalOptions)); +} + +/** + * Return value of a cell in a table. + */ +function PMA_getCellValue(td) { + var $td = $(td); + if ($td.is('.null')) { + return ''; + } else if (! $td.is('.to_be_saved') && $td.data('original_data')) { + return $td.data('original_data'); + } else { + return $td.text(); + } +} + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('functions.js', function() { + $('a.themeselect').die('click'); + $('.autosubmit').die('change'); + $('a.take_theme').unbind('click'); +}); + +AJAX.registerOnload('functions.js', function() { + /** + * Theme selector. + */ + $('a.themeselect').live('click', function(e) { + window.open( + e.target, + 'themes', + 'left=10,top=20,width=510,height=350,scrollbars=yes,status=yes,resizable=yes' + ); + return false; + }); + + /** + * Automatic form submission on change. + */ + $('.autosubmit').live('change', function(e) { + $(this).closest('form').submit(); + }); + + /** + * Theme changer. + */ + $('a.take_theme').click(function(e) { + var what = this.name; + if (window.opener && window.opener.document.forms['setTheme'].elements['set_theme']) { + window.opener.document.forms['setTheme'].elements['set_theme'].value = what; + window.opener.document.forms['setTheme'].submit(); + window.close(); + return false; + } + return true; + }); +}); + +/** + * Clear text selection + */ +function PMA_clearSelection() { + if (document.selection && document.selection.empty) { + document.selection.empty(); + } else if (window.getSelection) { + var sel = window.getSelection(); + if (sel.empty) { + sel.empty(); + } + if (sel.removeAllRanges) { + sel.removeAllRanges(); + } + } +} + +/** + * HTML escaping + */ +function escapeHtml(unsafe) { + return unsafe + .replace(/&/g, "&") + .replace(/</g, "<") + .replace(/>/g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); +} + +/** + * Print button + */ +function printPage() +{ + // Do print the page + if (typeof(window.print) != 'undefined') { + window.print(); + } +} + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('functions.js', function() { + $('input#print').unbind('click'); + $('span a.create_view.ajax').die('click'); + $('#createViewDialog').find('input, select').die('keydown'); +}); + +AJAX.registerOnload('functions.js', function() { + $('input#print').click(printPage); + /** + * Ajaxification for the "Create View" action + */ + $('span a.create_view.ajax').live('click', function (e) { + e.preventDefault(); + PMA_createViewDialog($(this)); + }); + /** + * Attach Ajax event handlers for input fields in the editor + * and used to submit the Ajax request when the ENTER key is pressed. + */ + $('#createViewDialog').find('input, select').live('keydown', function (e) { + if (e.which === 13) { // 13 is the ENTER key + e.preventDefault(); + $(this).closest('.ui-dialog').find('.ui-button:first').click(); + } + }); // end $.live() +}); + +function PMA_createViewDialog($this) +{ + var $msg = PMA_ajaxShowMessage(); + var syntaxHighlighter = null; + $.get($this.attr('href') + '&ajax_request=1', function (data) { + if (data.success == true) { + PMA_ajaxRemoveMessage($msg); + var buttonOptions = {}; + buttonOptions[PMA_messages['strGo']] = function () { + if (typeof CodeMirror !== 'undefined') { + syntaxHighlighter.save(); + } + $msg = PMA_ajaxShowMessage(); + $.get('view_create.php', $('#createViewDialog').find('form').serialize(), function (data) { + PMA_ajaxRemoveMessage($msg); + if (data.success === true) { + $('#createViewDialog').dialog("close"); + $('#result_query').html(data.message); + PMA_reloadNavigation(); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); + }; + buttonOptions[PMA_messages['strClose']] = function () { + $(this).dialog("close"); + }; + var $dialog = $('<div/>').attr('id', 'createViewDialog').append(data.message).dialog({ + width: 500, + minWidth: 300, + maxWidth: 620, + modal: true, + buttons: buttonOptions, + title: $('legend', $(data.message)).html(), + close: function () { + $(this).remove(); + } + }); + $dialog.find('legend').remove(); + // Attach syntax highlited editor + if (typeof CodeMirror !== 'undefined') { + var $elm = $dialog.find('textarea'); + var opts = {lineNumbers: true, matchBrackets: true, indentUnit: 4, mode: "text/x-mysql"}; + syntaxHighlighter = CodeMirror.fromTextArea($elm[0], opts); + } + $('input:visible[type=text]', $dialog).first().focus(); + } else { + PMA_ajaxShowMessage(data.error); + } + }); +} + +/** + * Makes the breadcrumbs and the menu bar float at the top of the viewport + */ +$(function () { + if ($("#floating_menubar").length && $('#PMA_disable_floating_menubar').length == 0) { + var left = $('html').attr('dir') == 'ltr' ? 'left' : 'right'; + $("#floating_menubar") + .css('margin-' + left, $('#pma_navigation').width() + $('#pma_navigation_resizer').width()) + .css(left, 0) + .css({ + 'position': 'fixed', + 'top': 0, + 'width': '100%', + 'z-index': 500 + }) + .append($('#serverinfo')) + .append($('#topmenucontainer')); + // Allow the DOM to render, then adjust the padding on the body + setTimeout(function () { + $('body').css( + 'padding-top', + $('#floating_menubar').outerHeight(true) + ); + $('#topmenu').menuResizer('resize'); + }, 4); + } +}); + +/** + * Scrolls the page to the top if clicking the serverinfo bar + */ +$(function () { + $(document).delegate("#serverinfo, #goto_pagetop", "click", function (event) { + event.preventDefault(); + $('html, body').animate({scrollTop: 0}, 'fast'); + }); +}); + +/** + * Watches checkboxes in a form to set the checkall box accordingly + */ +var checkboxes_sel = "input.checkall:checkbox:enabled"; +$(checkboxes_sel).live("change", function () { + var $form = $(this.form); + // total number of checkboxes in current form + var total_boxes = $form.find(checkboxes_sel).length; + // number of checkboxes checked in current form + var checked_boxes = $form.find(checkboxes_sel + ":checked").length; + var $checkall = $form.find("input#checkall"); + if (total_boxes == checked_boxes) { + $checkall.prop({checked: true, indeterminate: false}); + } + else if (checked_boxes > 0) { + $checkall.prop({checked: true, indeterminate: true}); + } + else { + $checkall.prop({checked: false, indeterminate: false}); + } +}); +$("input#checkall").live("change", function() { + var is_checked = $(this).is(":checked"); + $(this.form).find(checkboxes_sel).prop("checked", is_checked) + .parents("tr").toggleClass("marked", is_checked); +}); + +/** + * Toggles row colors of a set of 'tr' elements starting from a given element + * + * @param $start Starting element + */ +function toggleRowColors($start) +{ + for (var $curr_row = $start; $curr_row.length > 0; $curr_row = $curr_row.next()) { + if ($curr_row.hasClass('odd')) { + $curr_row.removeClass('odd').addClass('even'); + } else if ($curr_row.hasClass('even')) { + $curr_row.removeClass('even').addClass('odd'); + } + } +} + +/** + * Formats a byte number to human-readable form + * + * @param bytes the bytes to format + * @param optional subdecimals the number of digits after the point + * @param optional pointchar the char to use as decimal point + */ +function formatBytes(bytes, subdecimals, pointchar) { + if (!subdecimals) { + var subdecimals = 0; + } + if (!pointchar) { + var pointchar = '.'; + } + var units = ['B', 'KiB', 'MiB', 'GiB']; + for (var i = 0; bytes > 1024 && i < units.length; i++) { + bytes /= 1024; + } + var factor = Math.pow(10, subdecimals); + bytes = Math.round(bytes * factor) / factor; + bytes = bytes.toString().split('.').join(pointchar); + return bytes + ' ' + units[i]; +} + +AJAX.registerOnload('functions.js', function () { + /** + * Opens pma more themes link in themes browser, in new window instead of popup + * This way, we don't break HTML validity + */ + $("a._blank").prop("target", "_blank"); + /** + * Reveal the login form to users with JS enabled + * and focus the appropriate input field + */ + var $loginform = $('#loginform'); + if ($loginform.length) { + $loginform.find('.js-show').show(); + if ($('#input_username').val()) { + $('#input_password').focus(); + } else { + $('#input_username').focus(); + } + } +}); + +/** + * When user gets an ajax session expiry message, we show a login link + */ +$('a.login-link').live('click', function(e) { + e.preventDefault(); + window.location.reload(true); +}); + +/** + * Formats timestamp for display + */ +function PMA_formatDateTime(date, seconds) { + var result = $.datepicker.formatDate('yy-mm-dd', date); + var timefmt = 'HH:mm'; + if (seconds) { + timefmt = 'HH:mm:ss'; + } + return result + ' ' + $.datepicker.formatTime( + timefmt, { + hour: date.getHours(), + minute: date.getMinutes(), + second: date.getSeconds() + } + ); +} diff --git a/hugo/js/get_image.js.php b/hugo/js/get_image.js.php new file mode 100644 index 0000000..0861fa3 --- /dev/null +++ b/hugo/js/get_image.js.php @@ -0,0 +1,138 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Provides the functionality for retreiving images + * which may be actual images or an icon from a sprite + * + * @package PhpMyAdmin + */ +chdir('..'); + +// Send correct type: +header('Content-Type: text/javascript; charset=UTF-8'); +header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 3600) . ' GMT'); + +// Avoid loading the full common.inc.php because this would add many +// non-js-compatible stuff like DOCTYPE +define('PMA_MINIMUM_COMMON', true); +require_once './libraries/common.inc.php'; + +// Get the data for the sprites, if it's available +if (is_readable($_SESSION['PMA_Theme']->getPath() . '/sprites.lib.php')) { + include $_SESSION['PMA_Theme']->getPath() . '/sprites.lib.php'; +} +$sprites = array(); +if (function_exists('PMA_sprites')) { + $sprites = PMA_sprites(); +} +// We only need the keys from the array of sprites data, +// since they contain the (partial) class names +$keys = array(); +foreach ($sprites as $key => $value) { + $keys[] = "'$key'"; +} + +?> +/** + * Returns an HTML IMG tag for a particular image from a theme, + * which may be an actual file or an icon from a sprite + * + * @param string image The name of the file to get + * @param string alternate Used to set 'alt' and 'title' attributes of the image + * @param object attributes An associative array of other attributes + * + * @return Object The requested image, this object has two methods: + * .toString() - Returns the IMG tag for the requested image + * .attr(name) - Returns a particular attribute of the IMG + * tag given it's name + * .attr(name, value) - Sets a particular attribute of the IMG + * tag to the given value + * And one property: + * .isSprite - Whether the image is a sprite or not + */ +function PMA_getImage(image, alternate, attributes) { + var in_array = function (needle, haystack) { + for (var i in haystack) { + if (haystack[i] == needle) { + return true; + } + } + return false; + }; + var sprites = [ + <?php echo implode($keys, ",\n ") . "\n"; ?> + ]; + // custom image object, it will eventually be returned by this functions + var retval = { + data: { + // this is private + alt: '', + title: '', + src: (typeof PMA_TEST_THEME == 'undefined' ? '' : '../') + + 'themes/dot.gif' + }, + isSprite: true, + attr: function (name, value) { + if (value == undefined) { + if (this.data[name] == undefined) { + return ''; + } else { + return this.data[name]; + } + } else { + this.data[name] = value; + } + }, + toString: function () { + var retval = '<' + 'img'; + for (var i in this.data) { + retval += ' ' + i + '="' + this.data[i] + '"'; + } + retval += ' /' + '>'; + return retval; + } + }; + // initialise missing parameters + if (attributes == undefined) { + attributes = {}; + } + if (alternate == undefined) { + alternate = ''; + } + // set alt + if (attributes.alt != undefined) { + retval.attr('alt', attributes.alt); + } else { + retval.attr('alt', alternate); + } + // set title + if (attributes.title != undefined) { + retval.attr('title', attributes.title); + } else { + retval.attr('title', alternate); + } + // set src + var klass = image.replace('.gif', '').replace('.png', ''); + if (in_array(klass, sprites)) { + // it's an icon from a sprite + retval.attr('class', 'icon ic_' + klass); + } else { + // it's an image file + retval.isSprite = false; + retval.attr('src', "<?php echo $_SESSION['PMA_Theme']->getImgPath(); ?>" + image); + } + // set all other attrubutes + for (var i in attributes) { + if (i == 'src') { + // do not allow to override the 'src' attribute + continue; + } else if (i == 'class') { + retval.attr(i, retval.attr('class') + ' ' + attributes[i]); + } else { + retval.attr(i, attributes[i]); + } + } + + return retval; +} +//
\ No newline at end of file diff --git a/hugo/js/get_scripts.js.php b/hugo/js/get_scripts.js.php new file mode 100644 index 0000000..564fda7 --- /dev/null +++ b/hugo/js/get_scripts.js.php @@ -0,0 +1,38 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Concatenates reveral js files to reduce the number of + * http requests sent to the server + * + * @package PhpMyAdmin + */ +chdir('..'); + +// Send correct type +header('Content-Type: text/javascript; charset=UTF-8'); +// Enable browser cache for 1 hour +header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 3600) . ' GMT'); + +if (! empty($_GET['scripts']) && is_array($_GET['scripts'])) { + foreach ($_GET['scripts'] as $script) { + // Sanitise filename + $script_name = 'js'; + $path = explode("/", $script); + foreach ($path as $index => $filename) { + if (! preg_match("@^\.+$@", $filename) + && preg_match("@^[\w\.-]+$@", $filename) + ) { + // Disallow "." and ".." alone + // Allow alphanumeric, "." and "-" chars only + $script_name .= DIRECTORY_SEPARATOR . $filename; + } + } + // Output file contents + if (preg_match("@\.js$@", $script_name) && is_readable($script_name)) { + readfile($script_name); + echo ";\n\n"; + } + } +} + +?> diff --git a/hugo/js/gis_data_editor.js b/hugo/js/gis_data_editor.js new file mode 100644 index 0000000..d24bfb9 --- /dev/null +++ b/hugo/js/gis_data_editor.js @@ -0,0 +1,387 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * @fileoverview functions used in GIS data editor + * + * @requires jQuery + * + */ + +var gisEditorLoaded = false; + +/** + * Closes the GIS data editor and perform necessary clean up work. + */ +function closeGISEditor(){ + $("#popup_background").fadeOut("fast"); + $("#gis_editor").fadeOut("fast", function () { + $(this).empty(); + }); +} + +/** + * Prepares the HTML recieved via AJAX. + */ +function prepareJSVersion() { + // Change the text on the submit button + $("#gis_editor input[name='gis_data[save]']") + .val(PMA_messages['strCopy']) + .insertAfter($('#gis_data_textarea')) + .before('<br/><br/>'); + + // Add close and cancel links + $('#gis_data_editor').prepend('<a class="close_gis_editor" href="#">' + PMA_messages['strClose'] + '</a>'); + $('<a class="cancel_gis_editor" href="#"> ' + PMA_messages['strCancel'] + '</a>') + .insertAfter($("input[name='gis_data[save]']")); + + // Remove the unnecessary text + $('div#gis_data_output p').remove(); + + // Remove 'add' buttons and add links + $('#gis_editor input.add').each(function(e) { + var $button = $(this); + $button.addClass('addJs').removeClass('add'); + var classes = $button.attr('class'); + $button.replaceWith( + '<a class="' + classes + '" name="' + $button.attr('name') + + '" href="#">+ ' + $button.val() + '</a>' + ); + }); +} + +/** + * Returns the HTML for a data point. + * + * @param pointNumber point number + * @param prefix prefix of the name + * @returns the HTML for a data point + */ +function addDataPoint(pointNumber, prefix) { + return '<br/>' + $.sprintf(PMA_messages['strPointN'], (pointNumber + 1)) + ': ' + + '<label for="x">' + PMA_messages['strX'] + '</label>' + + '<input type="text" name="' + prefix + '[' + pointNumber + '][x]" value=""/>' + + '<label for="y">' + PMA_messages['strY'] + '</label>' + + '<input type="text" name="' + prefix + '[' + pointNumber + '][y]" value=""/>'; +} + +/** + * Initialize the visualization in the GIS data editor. + */ +function initGISEditorVisualization() { + // Loads either SVG or OSM visualization based on the choice + selectVisualization(); + // Adds necessary styles to the div that coontains the openStreetMap + styleOSM(); + // Loads the SVG element and make a reference to it + loadSVG(); + // Adds controllers for zooming and panning + addZoomPanControllers(); + zoomAndPan(); +} + +/** + * Loads JavaScript files and the GIS editor. + * + * @param value current value of the geometry field + * @param field field name + * @param type geometry type + * @param input_name name of the input field + * @param token token + */ +function loadJSAndGISEditor(value, field, type, input_name, token) { + var head = document.getElementsByTagName('head')[0]; + var script; + + // Loads a set of small JS file needed for the GIS editor + var smallScripts = [ 'js/jquery/jquery.svg.js', + 'js/jquery/jquery.mousewheel.js', + 'js/jquery/jquery.event.drag-2.2.js', + 'js/tbl_gis_visualization.js' ]; + + for (var i = 0; i < smallScripts.length; i++) { + script = document.createElement('script'); + script.type = 'text/javascript'; + script.src = smallScripts[i]; + head.appendChild(script); + } + + // OpenLayers.js is BIG and takes time. So asynchronous loading would not work. + // Load the JS and do a callback to load the content for the GIS Editor. + script = document.createElement('script'); + script.type = 'text/javascript'; + + script.onreadystatechange = function() { + if (this.readyState == 'complete') { + loadGISEditor(value, field, type, input_name, token); + } + }; + script.onload = function() { + loadGISEditor(value, field, type, input_name, token); + }; + + script.src = 'js/openlayers/OpenLayers.js'; + head.appendChild(script); + + gisEditorLoaded = true; +} + +/** + * Loads the GIS editor via AJAX + * + * @param value current value of the geometry field + * @param field field name + * @param type geometry type + * @param input_name name of the input field + * @param token token + */ +function loadGISEditor(value, field, type, input_name, token) { + + var $gis_editor = $("#gis_editor"); + $.post('gis_data_editor.php', { + 'field' : field, + 'value' : value, + 'type' : type, + 'input_name' : input_name, + 'get_gis_editor' : true, + 'token' : token, + 'ajax_request': true + }, function(data) { + if (data.success == true) { + $gis_editor.html(data.gis_editor); + initGISEditorVisualization(); + prepareJSVersion(); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }, 'json'); +} + +/** + * Opens up the dialog for the GIS data editor. + */ +function openGISEditor() { + + // Center the popup + var windowWidth = document.documentElement.clientWidth; + var windowHeight = document.documentElement.clientHeight; + var popupWidth = windowWidth * 0.9; + var popupHeight = windowHeight * 0.9; + var popupOffsetTop = windowHeight / 2 - popupHeight / 2; + var popupOffsetLeft = windowWidth / 2 - popupWidth / 2; + + var $gis_editor = $("#gis_editor"); + var $backgrouond = $("#popup_background"); + + $gis_editor.css({"top": popupOffsetTop, "left": popupOffsetLeft, "width": popupWidth, "height": popupHeight}); + $backgrouond.css({"opacity":"0.7"}); + + $gis_editor.append('<div id="gis_data_editor"><img class="ajaxIcon" id="loadingMonitorIcon" src="' + + pmaThemeImage + 'ajax_clock_small.gif" alt=""/></div>' + ); + + // Make it appear + $backgrouond.fadeIn("fast"); + $gis_editor.fadeIn("fast"); +} + +/** + * Prepare and insert the GIS data in Well Known Text format + * to the input field. + */ +function insertDataAndClose() { + var $form = $('form#gis_data_editor_form'); + var input_name = $form.find("input[name='input_name']").val(); + + $.post('gis_data_editor.php', $form.serialize() + "&generate=true&ajax_request=true", function(data) { + if (data.success == true) { + $("input[name='" + input_name + "']").val(data.result); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }, 'json'); + closeGISEditor(); +} + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('gis_data_editor.js', function() { + $("#gis_editor input[name='gis_data[save]']").die('click'); + $('#gis_editor').die('submit'); + $('#gis_editor').find("input[type='text']").die('change'); + $("#gis_editor select.gis_type").die('change'); + $('#gis_editor a.close_gis_editor, #gis_editor a.cancel_gis_editor').die('click'); + $('#gis_editor a.addJs.addPoint').die('click'); + $('#gis_editor a.addLine.addJs').die('click'); + $('#gis_editor a.addJs.addPolygon').die('click'); + $('#gis_editor a.addJs.addGeom').die('click'); +}); + +AJAX.registerOnload('gis_data_editor.js', function() { + + // Remove the class that is added due to the URL being too long. + $('span.open_gis_editor a').removeClass('formLinkSubmit'); + + /** + * Prepares and insert the GIS data to the input field on clicking 'copy'. + */ + $("#gis_editor input[name='gis_data[save]']").live('click', function(event) { + event.preventDefault(); + insertDataAndClose(); + }); + + /** + * Prepares and insert the GIS data to the input field on pressing 'enter'. + */ + $('#gis_editor').live('submit', function(event) { + event.preventDefault(); + insertDataAndClose(); + }); + + /** + * Trigger asynchronous calls on data change and update the output. + */ + $('#gis_editor').find("input[type='text']").live('change', function() { + var $form = $('form#gis_data_editor_form'); + $.post('gis_data_editor.php', $form.serialize() + "&generate=true&ajax_request=true", function(data) { + if (data.success == true) { + $('#gis_data_textarea').val(data.result); + $('#placeholder').empty().removeClass('hasSVG').html(data.visualization); + $('#openlayersmap').empty(); + eval(data.openLayers); + initGISEditorVisualization(); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }, 'json'); + }); + + /** + * Update the form on change of the GIS type. + */ + $("#gis_editor select.gis_type").live('change', function(event) { + var $gis_editor = $("#gis_editor"); + var $form = $('form#gis_data_editor_form'); + + $.post('gis_data_editor.php', $form.serialize() + "&get_gis_editor=true&ajax_request=true", function(data) { + if (data.success == true) { + $gis_editor.html(data.gis_editor); + initGISEditorVisualization(); + prepareJSVersion(); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }, 'json'); + }); + + /** + * Handles closing of the GIS data editor. + */ + $('#gis_editor a.close_gis_editor, #gis_editor a.cancel_gis_editor').live('click', function() { + closeGISEditor(); + }); + + /** + * Handles adding data points + */ + $('#gis_editor a.addJs.addPoint').live('click', function() { + var $a = $(this); + var name = $a.attr('name'); + // Eg. name = gis_data[0][MULTIPOINT][add_point] => prefix = gis_data[0][MULTIPOINT] + var prefix = name.substr(0, name.length - 11); + // Find the number of points + var $noOfPointsInput = $("input[name='" + prefix + "[no_of_points]" + "']"); + var noOfPoints = parseInt($noOfPointsInput.val()); + // Add the new data point + var html = addDataPoint(noOfPoints, prefix); + $a.before(html); + $noOfPointsInput.val(noOfPoints + 1); + }); + + /** + * Handles adding linestrings and inner rings + */ + $('#gis_editor a.addLine.addJs').live('click', function() { + var $a = $(this); + var name = $a.attr('name'); + + // Eg. name = gis_data[0][MULTILINESTRING][add_line] => prefix = gis_data[0][MULTILINESTRING] + var prefix = name.substr(0, name.length - 10); + var type = prefix.slice(prefix.lastIndexOf('[') + 1, prefix.lastIndexOf(']')); + + // Find the number of lines + var $noOfLinesInput = $("input[name='" + prefix + "[no_of_lines]" + "']"); + var noOfLines = parseInt($noOfLinesInput.val()); + + // Add the new linesting of inner ring based on the type + var html = '<br/>'; + if (type == 'MULTILINESTRING') { + html += PMA_messages['strLineString'] + ' ' + (noOfLines + 1) + ':'; + var noOfPoints = 2; + } else { + html += PMA_messages['strInnerRing'] + ' ' + noOfLines + ':'; + var noOfPoints = 4; + } + html += '<input type="hidden" name="' + prefix + '[' + noOfLines + '][no_of_points]" value="' + noOfPoints + '"/>'; + for (var i = 0; i < noOfPoints; i++) { + html += addDataPoint(i, (prefix + '[' + noOfLines + ']')); + } + html += '<a class="addPoint addJs" name="' + prefix + '[' + noOfLines + '][add_point]" href="#">+ ' + + PMA_messages['strAddPoint'] + '</a><br/>'; + + $a.before(html); + $noOfLinesInput.val(noOfLines + 1); + }); + + /** + * Handles adding polygons + */ + $('#gis_editor a.addJs.addPolygon').live('click', function() { + var $a = $(this); + var name = $a.attr('name'); + // Eg. name = gis_data[0][MULTIPOLYGON][add_polygon] => prefix = gis_data[0][MULTIPOLYGON] + var prefix = name.substr(0, name.length - 13); + // Find the number of polygons + var $noOfPolygonsInput = $("input[name='" + prefix + "[no_of_polygons]" + "']"); + var noOfPolygons = parseInt($noOfPolygonsInput.val()); + + // Add the new polygon + var html = PMA_messages['strPolygon'] + ' ' + (noOfPolygons + 1) + ':<br/>'; + html += '<input type="hidden" name="' + prefix + '[' + noOfPolygons + '][no_of_lines]" value="1"/>' + + '<br/>' + PMA_messages['strOuterRing'] + ':' + + '<input type="hidden" name="' + prefix + '[' + noOfPolygons + '][0][no_of_points]" value="4"/>'; + for (var i = 0; i < 4; i++) { + html += addDataPoint(i, (prefix + '[' + noOfPolygons + '][0]')); + } + html += '<a class="addPoint addJs" name="' + prefix + '[' + noOfPolygons + '][0][add_point]" href="#">+ ' + + PMA_messages['strAddPoint'] + '</a><br/>' + + '<a class="addLine addJs" name="' + prefix + '[' + noOfPolygons + '][add_line]" href="#">+ ' + + PMA_messages['strAddInnerRing'] + '</a><br/><br/>'; + + $a.before(html); + $noOfPolygonsInput.val(noOfPolygons + 1); + }); + + /** + * Handles adding geoms + */ + $('#gis_editor a.addJs.addGeom').live('click', function() { + var $a = $(this); + var prefix = 'gis_data[GEOMETRYCOLLECTION]'; + // Find the number of geoms + var $noOfGeomsInput = $("input[name='" + prefix + "[geom_count]" + "']"); + var noOfGeoms = parseInt($noOfGeomsInput.val()); + + var html1 = PMA_messages['strGeometry'] + ' ' + (noOfGeoms + 1) + ':<br/>'; + var $geomType = $("select[name='gis_data[" + (noOfGeoms - 1) + "][gis_type]']").clone(); + $geomType.attr('name', 'gis_data[' + noOfGeoms + '][gis_type]').val('POINT'); + var html2 = '<br/>' + PMA_messages['strPoint'] + ' :' + + '<label for="x"> ' + PMA_messages['strX'] + ' </label>' + + '<input type="text" name="gis_data[' + noOfGeoms + '][POINT][x]" value=""/>' + + '<label for="y"> ' + PMA_messages['strY'] + ' </label>' + + '<input type="text" name="gis_data[' + noOfGeoms + '][POINT][y]" value=""/>' + + '<br/><br/>'; + + $a.before(html1); $geomType.insertBefore($a); $a.before(html2); + $noOfGeomsInput.val(noOfGeoms + 1); + }); +}); diff --git a/hugo/js/import.js b/hugo/js/import.js new file mode 100644 index 0000000..4dfda5a --- /dev/null +++ b/hugo/js/import.js @@ -0,0 +1,102 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Functions used in the import tab + * + */ + + +/** + * Toggles the hiding and showing of each plugin's options + * according to the currently selected plugin from the dropdown list + */ +function changePluginOpts() +{ + $("#format_specific_opts div.format_specific_options").each(function() { + $(this).hide(); + }); + var selected_plugin_name = $("#plugins option:selected").val(); + $("#" + selected_plugin_name + "_options").fadeIn('slow'); + if (selected_plugin_name == "csv") { + $("#import_notification").text(PMA_messages['strImportCSV']); + } else { + $("#import_notification").text(""); + } +} + +/** + * Toggles the hiding and showing of each plugin's options and sets the selected value + * in the plugin dropdown list according to the format of the selected file + */ +function matchFile(fname) +{ + var fname_array = fname.toLowerCase().split("."); + var len = fname_array.length; + if (len != 0) { + var extension = fname_array[len - 1]; + if (extension == "gz" || extension == "bz2" || extension == "zip") { + len--; + } + // Only toggle if the format of the file can be imported + if ($("select[name='format'] option").filterByValue(fname_array[len - 1]).length == 1) { + $("select[name='format'] option").filterByValue(fname_array[len - 1]).prop('selected', true); + changePluginOpts(); + } + } +} + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('import.js', function() { + $("#plugins").unbind('change'); + $("#input_import_file").unbind('change'); + $("#select_local_import_file").unbind('change'); + $("#input_import_file").unbind('change').unbind('focus'); + $("#select_local_import_file").unbind('focus'); +}); + +AJAX.registerOnload('import.js', function() { + // Initially display the options for the selected plugin + changePluginOpts(); + + // Whenever the selected plugin changes, change the options displayed + $("#plugins").change(function() { + changePluginOpts(); + }); + + $("#input_import_file").change(function() { + matchFile($(this).val()); + }); + + $("#select_local_import_file").change(function() { + matchFile($(this).val()); + }); + + /* + * When the "Browse the server" form is clicked or the "Select from the web server upload directory" + * form is clicked, the radio button beside it becomes selected and the other form becomes disabled. + */ + $("#input_import_file").bind("focus change", function() { + $("#radio_import_file").prop('checked', true); + $("#radio_local_import_file").prop('checked', false); + }); + $("#select_local_import_file").focus(function() { + $("#radio_local_import_file").prop('checked', true); + $("#radio_import_file").prop('checked', false); + }); + + /** + * Set up the interface for Javascript-enabled browsers since the default is for + * Javascript-disabled browsers + */ + $("#scroll_to_options_msg").hide(); + $("#format_specific_opts div.format_specific_options") + .css({ + "border": 0, + "margin": 0, + "padding": 0 + }) + .find("h3") + .remove(); + //$("form[name=import] *").unwrap(); +}); diff --git a/hugo/js/indexes.js b/hugo/js/indexes.js new file mode 100644 index 0000000..de94076 --- /dev/null +++ b/hugo/js/indexes.js @@ -0,0 +1,207 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * @fileoverview function used for index manipulation pages + * @name Table Structure + * + * @requires jQuery + * @requires jQueryUI + * @required js/functions.js + */ + +/** + * Hides/shows the inputs and submits appropriately depending + * on whether the index type chosen is 'SPATIAL' or not. + */ +function checkIndexType() +{ + /** + * @var Object Dropdown to select the index type. + */ + $select_index_type = $('#select_index_type'); + /** + * @var Object Table header for the size column. + */ + $size_header = $('#index_columns thead tr th:nth-child(2)'); + /** + * @var Object Inputs to specify the columns for the index. + */ + $column_inputs = $('select[name="index[columns][names][]"]'); + /** + * @var Object Inputs to specify sizes for columns of the index. + */ + $size_inputs = $('input[name="index[columns][sub_parts][]"]'); + /** + * @var Object Footer containg the controllers to add more columns + */ + $add_more = $('#index_frm .tblFooters'); + + if ($select_index_type.val() == 'SPATIAL') { + // Disable and hide the size column + $size_header.hide(); + $size_inputs.each(function(){ + $(this) + .prop('disabled', true) + .parent('td').hide(); + }); + + // Disable and hide the columns of the index other than the first one + var initial = true; + $column_inputs.each(function() { + $column_input = $(this); + if (! initial) { + $column_input + .prop('disabled', true) + .parent('td').hide(); + } else { + initial = false; + } + }); + + // Hide controllers to add more columns + $add_more.hide(); + } else { + // Enable and show the size column + $size_header.show(); + $size_inputs.each(function() { + $(this) + .prop('disabled', false) + .parent('td').show(); + }); + + // Enable and show the columns of the index + $column_inputs.each(function() { + $(this) + .prop('disabled', false) + .parent('td').show(); + }); + + // Show controllers to add more columns + $add_more.show(); + } +} + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('indexes.js', function() { + $('#select_index_type').die('change'); + $('a.drop_primary_key_index_anchor.ajax').die('click'); + $("#table_index tbody tr td.edit_index.ajax, #indexes .add_index.ajax").die('click'); + $('#index_frm input[type=submit]').die('click'); +}); + +/** + * @description <p>Ajax scripts for table index page</p> + * + * Actions ajaxified here: + * <ul> + * <li>Showing/hiding inputs depending on the index type chosen</li> + * <li>create/edit/drop indexes</li> + * </ul> + */ +AJAX.registerOnload('indexes.js', function() { + checkIndexType(); + checkIndexName("index_frm"); + $('#select_index_type').live('change', function(event){ + event.preventDefault(); + checkIndexType(); + checkIndexName("index_frm"); + }); + + /** + * Ajax Event handler for 'Drop Index' + */ + $('a.drop_primary_key_index_anchor.ajax').live('click', function(event) { + event.preventDefault(); + var $anchor = $(this); + /** + * @var $curr_row Object containing reference to the current field's row + */ + var $curr_row = $anchor.parents('tr'); + /** @var Number of columns in the key */ + var rows = $anchor.parents('td').attr('rowspan') || 1; + /** @var Rows that should be hidden */ + var $rows_to_hide = $curr_row; + for (var i = 1, $last_row = $curr_row.next(); i < rows; i++, $last_row = $last_row.next()) { + $rows_to_hide = $rows_to_hide.add($last_row); + } + + var question = escapeHtml( + $curr_row.children('td') + .children('.drop_primary_key_index_msg') + .val() + ); + + $anchor.PMA_confirm(question, $anchor.attr('href'), function(url) { + var $msg = PMA_ajaxShowMessage(PMA_messages['strDroppingPrimaryKeyIndex'], false); + $.get(url, {'is_js_confirmed': 1, 'ajax_request': true}, function(data) { + if (data.success == true) { + PMA_ajaxRemoveMessage($msg); + var $table_ref = $rows_to_hide.closest('table'); + if ($rows_to_hide.length == $table_ref.find('tbody > tr').length) { + // We are about to remove all rows from the table + $table_ref.hide('medium', function() { + $('div.no_indexes_defined').show('medium'); + $rows_to_hide.remove(); + }); + $table_ref.siblings('div.notice').hide('medium'); + } else { + // We are removing some of the rows only + toggleRowColors($rows_to_hide.last().next()); + $rows_to_hide.hide("medium", function () { + $(this).remove(); + }); + } + if ($('#result_query').length) { + $('#result_query').remove(); + } + if (data.sql_query) { + $('<div id="result_query"></div>') + .html(data.sql_query) + .prependTo('#page_content'); + } + PMA_commonActions.refreshMain(false, function() { + $("a.ajax[href^=#indexes]").click(); + }); + PMA_reloadNavigation(); + } else { + PMA_ajaxShowMessage(PMA_messages['strErrorProcessingRequest'] + " : " + data.error, false); + } + }); // end $.get() + }); // end $.PMA_confirm() + }); //end Drop Primary Key/Index + + /** + *Ajax event handler for index edit + **/ + $("#table_index tbody tr td.edit_index.ajax, #indexes .add_index.ajax").live('click', function(event) { + event.preventDefault(); + if ($(this).find("a").length == 0) { + // Add index + var valid = checkFormElementInRange( + $(this).closest('form')[0], + 'added_fields', + 'Column count has to be larger than zero.' + ); + if (! valid) { + return; + } + var url = $(this).closest('form').serialize(); + var title = PMA_messages['strAddIndex']; + } else { + // Edit index + var url = $(this).find("a").attr("href"); + if (url.substring(0, 16) == "tbl_indexes.php?") { + url = url.substring(16, url.length); + } + var title = PMA_messages['strEditIndex']; + } + url += "&ajax_request=true"; + indexEditorDialog(url, title, function() { + // refresh the page using ajax + PMA_commonActions.refreshMain(false, function() { + $("a.ajax[href^=#indexes]").click(); + }); + }); + }); +}); diff --git a/hugo/js/jqplot/excanvas.js b/hugo/js/jqplot/excanvas.js new file mode 100644 index 0000000..4ca9653 --- /dev/null +++ b/hugo/js/jqplot/excanvas.js @@ -0,0 +1,1438 @@ +// Memory Leaks patch from http://explorercanvas.googlecode.com/svn/trunk/ +// svn : r73 +// ------------------------------------------------------------------ +// Copyright 2006 Google Inc. +// +// 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. + + +// Known Issues: +// +// * Patterns only support repeat. +// * Radial gradient are not implemented. The VML version of these look very +// different from the canvas one. +// * Clipping paths are not implemented. +// * Coordsize. The width and height attribute have higher priority than the +// width and height style values which isn't correct. +// * Painting mode isn't implemented. +// * Canvas width/height should is using content-box by default. IE in +// Quirks mode will draw the canvas using border-box. Either change your +// doctype to HTML5 +// (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype) +// or use Box Sizing Behavior from WebFX +// (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html) +// * Non uniform scaling does not correctly scale strokes. +// * Optimize. There is always room for speed improvements. + +// Only add this code if we do not already have a canvas implementation +if (!document.createElement('canvas').getContext) { + +(function() { + + // alias some functions to make (compiled) code shorter + var m = Math; + var mr = m.round; + var ms = m.sin; + var mc = m.cos; + var abs = m.abs; + var sqrt = m.sqrt; + + // this is used for sub pixel precision + var Z = 10; + var Z2 = Z / 2; + + var IE_VERSION = +navigator.userAgent.match(/MSIE ([\d.]+)?/)[1]; + + /** + * This funtion is assigned to the <canvas> elements as element.getContext(). + * @this {HTMLElement} + * @return {CanvasRenderingContext2D_} + */ + function getContext() { + return this.context_ || + (this.context_ = new CanvasRenderingContext2D_(this)); + } + + var slice = Array.prototype.slice; + + /** + * Binds a function to an object. The returned function will always use the + * passed in {@code obj} as {@code this}. + * + * Example: + * + * g = bind(f, obj, a, b) + * g(c, d) // will do f.call(obj, a, b, c, d) + * + * @param {Function} f The function to bind the object to + * @param {Object} obj The object that should act as this when the function + * is called + * @param {*} var_args Rest arguments that will be used as the initial + * arguments when the function is called + * @return {Function} A new function that has bound this + */ + function bind(f, obj, var_args) { + var a = slice.call(arguments, 2); + return function() { + return f.apply(obj, a.concat(slice.call(arguments))); + }; + } + + function encodeHtmlAttribute(s) { + return String(s).replace(/&/g, '&').replace(/"/g, '"'); + } + + function addNamespace(doc, prefix, urn) { + if (!doc.namespaces[prefix]) { + doc.namespaces.add(prefix, urn, '#default#VML'); + } + } + + function addNamespacesAndStylesheet(doc) { + addNamespace(doc, 'g_vml_', 'urn:schemas-microsoft-com:vml'); + addNamespace(doc, 'g_o_', 'urn:schemas-microsoft-com:office:office'); + + // Setup default CSS. Only add one style sheet per document + if (!doc.styleSheets['ex_canvas_']) { + var ss = doc.createStyleSheet(); + ss.owningElement.id = 'ex_canvas_'; + ss.cssText = 'canvas{display:inline-block;overflow:hidden;' + + // default size is 300x150 in Gecko and Opera + 'text-align:left;width:300px;height:150px}'; + } + } + + // Add namespaces and stylesheet at startup. + addNamespacesAndStylesheet(document); + + var G_vmlCanvasManager_ = { + init: function(opt_doc) { + var doc = opt_doc || document; + // Create a dummy element so that IE will allow canvas elements to be + // recognized. + doc.createElement('canvas'); + doc.attachEvent('onreadystatechange', bind(this.init_, this, doc)); + }, + + init_: function(doc) { + // find all canvas elements + var els = doc.getElementsByTagName('canvas'); + for (var i = 0; i < els.length; i++) { + this.initElement(els[i]); + } + }, + + /** + * Public initializes a canvas element so that it can be used as canvas + * element from now on. This is called automatically before the page is + * loaded but if you are creating elements using createElement you need to + * make sure this is called on the element. + * @param {HTMLElement} el The canvas element to initialize. + * @return {HTMLElement} the element that was created. + */ + initElement: function(el) { + if (!el.getContext) { + el.getContext = getContext; + + // Add namespaces and stylesheet to document of the element. + addNamespacesAndStylesheet(el.ownerDocument); + + // Remove fallback content. There is no way to hide text nodes so we + // just remove all childNodes. We could hide all elements and remove + // text nodes but who really cares about the fallback content. + el.innerHTML = ''; + + // do not use inline function because that will leak memory + el.attachEvent('onpropertychange', onPropertyChange); + el.attachEvent('onresize', onResize); + + var attrs = el.attributes; + if (attrs.width && attrs.width.specified) { + // TODO: use runtimeStyle and coordsize + // el.getContext().setWidth_(attrs.width.nodeValue); + el.style.width = attrs.width.nodeValue + 'px'; + } else { + el.width = el.clientWidth; + } + if (attrs.height && attrs.height.specified) { + // TODO: use runtimeStyle and coordsize + // el.getContext().setHeight_(attrs.height.nodeValue); + el.style.height = attrs.height.nodeValue + 'px'; + } else { + el.height = el.clientHeight; + } + //el.getContext().setCoordsize_() + } + return el; + }, + + // Memory Leaks patch : see http://code.google.com/p/explorercanvas/issues/detail?id=82 + uninitElement: function(el){ + if (el.getContext) { + var ctx = el.getContext(); + delete ctx.element_; + delete ctx.canvas; + el.innerHTML = ""; + //el.outerHTML = ""; + el.context_ = null; + el.getContext = null; + el.detachEvent("onpropertychange", onPropertyChange); + el.detachEvent("onresize", onResize); + } + } + }; + + function onPropertyChange(e) { + var el = e.srcElement; + + switch (e.propertyName) { + case 'width': + el.getContext().clearRect(); + el.style.width = el.attributes.width.nodeValue + 'px'; + // In IE8 this does not trigger onresize. + el.firstChild.style.width = el.clientWidth + 'px'; + break; + case 'height': + el.getContext().clearRect(); + el.style.height = el.attributes.height.nodeValue + 'px'; + el.firstChild.style.height = el.clientHeight + 'px'; + break; + } + } + + function onResize(e) { + var el = e.srcElement; + if (el.firstChild) { + el.firstChild.style.width = el.clientWidth + 'px'; + el.firstChild.style.height = el.clientHeight + 'px'; + } + } + + G_vmlCanvasManager_.init(); + + // precompute "00" to "FF" + var decToHex = []; + for (var i = 0; i < 16; i++) { + for (var j = 0; j < 16; j++) { + decToHex[i * 16 + j] = i.toString(16) + j.toString(16); + } + } + + function createMatrixIdentity() { + return [ + [1, 0, 0], + [0, 1, 0], + [0, 0, 1] + ]; + } + + function matrixMultiply(m1, m2) { + var result = createMatrixIdentity(); + + for (var x = 0; x < 3; x++) { + for (var y = 0; y < 3; y++) { + var sum = 0; + + for (var z = 0; z < 3; z++) { + sum += m1[x][z] * m2[z][y]; + } + + result[x][y] = sum; + } + } + return result; + } + + function copyState(o1, o2) { + o2.fillStyle = o1.fillStyle; + o2.lineCap = o1.lineCap; + o2.lineJoin = o1.lineJoin; + o2.lineWidth = o1.lineWidth; + o2.miterLimit = o1.miterLimit; + o2.shadowBlur = o1.shadowBlur; + o2.shadowColor = o1.shadowColor; + o2.shadowOffsetX = o1.shadowOffsetX; + o2.shadowOffsetY = o1.shadowOffsetY; + o2.strokeStyle = o1.strokeStyle; + o2.globalAlpha = o1.globalAlpha; + o2.font = o1.font; + o2.textAlign = o1.textAlign; + o2.textBaseline = o1.textBaseline; + o2.arcScaleX_ = o1.arcScaleX_; + o2.arcScaleY_ = o1.arcScaleY_; + o2.lineScale_ = o1.lineScale_; + } + + var colorData = { + aliceblue: '#F0F8FF', + antiquewhite: '#FAEBD7', + aquamarine: '#7FFFD4', + azure: '#F0FFFF', + beige: '#F5F5DC', + bisque: '#FFE4C4', + black: '#000000', + blanchedalmond: '#FFEBCD', + blueviolet: '#8A2BE2', + brown: '#A52A2A', + burlywood: '#DEB887', + cadetblue: '#5F9EA0', + chartreuse: '#7FFF00', + chocolate: '#D2691E', + coral: '#FF7F50', + cornflowerblue: '#6495ED', + cornsilk: '#FFF8DC', + crimson: '#DC143C', + cyan: '#00FFFF', + darkblue: '#00008B', + darkcyan: '#008B8B', + darkgoldenrod: '#B8860B', + darkgray: '#A9A9A9', + darkgreen: '#006400', + darkgrey: '#A9A9A9', + darkkhaki: '#BDB76B', + darkmagenta: '#8B008B', + darkolivegreen: '#556B2F', + darkorange: '#FF8C00', + darkorchid: '#9932CC', + darkred: '#8B0000', + darksalmon: '#E9967A', + darkseagreen: '#8FBC8F', + darkslateblue: '#483D8B', + darkslategray: '#2F4F4F', + darkslategrey: '#2F4F4F', + darkturquoise: '#00CED1', + darkviolet: '#9400D3', + deeppink: '#FF1493', + deepskyblue: '#00BFFF', + dimgray: '#696969', + dimgrey: '#696969', + dodgerblue: '#1E90FF', + firebrick: '#B22222', + floralwhite: '#FFFAF0', + forestgreen: '#228B22', + gainsboro: '#DCDCDC', + ghostwhite: '#F8F8FF', + gold: '#FFD700', + goldenrod: '#DAA520', + grey: '#808080', + greenyellow: '#ADFF2F', + honeydew: '#F0FFF0', + hotpink: '#FF69B4', + indianred: '#CD5C5C', + indigo: '#4B0082', + ivory: '#FFFFF0', + khaki: '#F0E68C', + lavender: '#E6E6FA', + lavenderblush: '#FFF0F5', + lawngreen: '#7CFC00', + lemonchiffon: '#FFFACD', + lightblue: '#ADD8E6', + lightcoral: '#F08080', + lightcyan: '#E0FFFF', + lightgoldenrodyellow: '#FAFAD2', + lightgreen: '#90EE90', + lightgrey: '#D3D3D3', + lightpink: '#FFB6C1', + lightsalmon: '#FFA07A', + lightseagreen: '#20B2AA', + lightskyblue: '#87CEFA', + lightslategray: '#778899', + lightslategrey: '#778899', + lightsteelblue: '#B0C4DE', + lightyellow: '#FFFFE0', + limegreen: '#32CD32', + linen: '#FAF0E6', + magenta: '#FF00FF', + mediumaquamarine: '#66CDAA', + mediumblue: '#0000CD', + mediumorchid: '#BA55D3', + mediumpurple: '#9370DB', + mediumseagreen: '#3CB371', + mediumslateblue: '#7B68EE', + mediumspringgreen: '#00FA9A', + mediumturquoise: '#48D1CC', + mediumvioletred: '#C71585', + midnightblue: '#191970', + mintcream: '#F5FFFA', + mistyrose: '#FFE4E1', + moccasin: '#FFE4B5', + navajowhite: '#FFDEAD', + oldlace: '#FDF5E6', + olivedrab: '#6B8E23', + orange: '#FFA500', + orangered: '#FF4500', + orchid: '#DA70D6', + palegoldenrod: '#EEE8AA', + palegreen: '#98FB98', + paleturquoise: '#AFEEEE', + palevioletred: '#DB7093', + papayawhip: '#FFEFD5', + peachpuff: '#FFDAB9', + peru: '#CD853F', + pink: '#FFC0CB', + plum: '#DDA0DD', + powderblue: '#B0E0E6', + rosybrown: '#BC8F8F', + royalblue: '#4169E1', + saddlebrown: '#8B4513', + salmon: '#FA8072', + sandybrown: '#F4A460', + seagreen: '#2E8B57', + seashell: '#FFF5EE', + sienna: '#A0522D', + skyblue: '#87CEEB', + slateblue: '#6A5ACD', + slategray: '#708090', + slategrey: '#708090', + snow: '#FFFAFA', + springgreen: '#00FF7F', + steelblue: '#4682B4', + tan: '#D2B48C', + thistle: '#D8BFD8', + tomato: '#FF6347', + turquoise: '#40E0D0', + violet: '#EE82EE', + wheat: '#F5DEB3', + whitesmoke: '#F5F5F5', + yellowgreen: '#9ACD32' + }; + + + function getRgbHslContent(styleString) { + var start = styleString.indexOf('(', 3); + var end = styleString.indexOf(')', start + 1); + var parts = styleString.substring(start + 1, end).split(','); + // add alpha if needed + if (parts.length != 4 || styleString.charAt(3) != 'a') { + parts[3] = 1; + } + return parts; + } + + function percent(s) { + return parseFloat(s) / 100; + } + + function clamp(v, min, max) { + return Math.min(max, Math.max(min, v)); + } + + function hslToRgb(parts){ + var r, g, b, h, s, l; + h = parseFloat(parts[0]) / 360 % 360; + if (h < 0) + h++; + s = clamp(percent(parts[1]), 0, 1); + l = clamp(percent(parts[2]), 0, 1); + if (s == 0) { + r = g = b = l; // achromatic + } else { + var q = l < 0.5 ? l * (1 + s) : l + s - l * s; + var p = 2 * l - q; + r = hueToRgb(p, q, h + 1 / 3); + g = hueToRgb(p, q, h); + b = hueToRgb(p, q, h - 1 / 3); + } + + return '#' + decToHex[Math.floor(r * 255)] + + decToHex[Math.floor(g * 255)] + + decToHex[Math.floor(b * 255)]; + } + + function hueToRgb(m1, m2, h) { + if (h < 0) + h++; + if (h > 1) + h--; + + if (6 * h < 1) + return m1 + (m2 - m1) * 6 * h; + else if (2 * h < 1) + return m2; + else if (3 * h < 2) + return m1 + (m2 - m1) * (2 / 3 - h) * 6; + else + return m1; + } + + var processStyleCache = {}; + + function processStyle(styleString) { + if (styleString in processStyleCache) { + return processStyleCache[styleString]; + } + + var str, alpha = 1; + + styleString = String(styleString); + if (styleString.charAt(0) == '#') { + str = styleString; + } else if (/^rgb/.test(styleString)) { + var parts = getRgbHslContent(styleString); + var str = '#', n; + for (var i = 0; i < 3; i++) { + if (parts[i].indexOf('%') != -1) { + n = Math.floor(percent(parts[i]) * 255); + } else { + n = +parts[i]; + } + str += decToHex[clamp(n, 0, 255)]; + } + alpha = +parts[3]; + } else if (/^hsl/.test(styleString)) { + var parts = getRgbHslContent(styleString); + str = hslToRgb(parts); + alpha = parts[3]; + } else { + str = colorData[styleString] || styleString; + } + return processStyleCache[styleString] = {color: str, alpha: alpha}; + } + + var DEFAULT_STYLE = { + style: 'normal', + variant: 'normal', + weight: 'normal', + size: 10, + family: 'sans-serif' + }; + + // Internal text style cache + var fontStyleCache = {}; + + function processFontStyle(styleString) { + if (fontStyleCache[styleString]) { + return fontStyleCache[styleString]; + } + + var el = document.createElement('div'); + var style = el.style; + try { + style.font = styleString; + } catch (ex) { + // Ignore failures to set to invalid font. + } + + return fontStyleCache[styleString] = { + style: style.fontStyle || DEFAULT_STYLE.style, + variant: style.fontVariant || DEFAULT_STYLE.variant, + weight: style.fontWeight || DEFAULT_STYLE.weight, + size: style.fontSize || DEFAULT_STYLE.size, + family: style.fontFamily || DEFAULT_STYLE.family + }; + } + + function getComputedStyle(style, element) { + var computedStyle = {}; + + for (var p in style) { + computedStyle[p] = style[p]; + } + + // Compute the size + var canvasFontSize = parseFloat(element.currentStyle.fontSize), + fontSize = parseFloat(style.size); + + if (typeof style.size == 'number') { + computedStyle.size = style.size; + } else if (style.size.indexOf('px') != -1) { + computedStyle.size = fontSize; + } else if (style.size.indexOf('em') != -1) { + computedStyle.size = canvasFontSize * fontSize; + } else if(style.size.indexOf('%') != -1) { + computedStyle.size = (canvasFontSize / 100) * fontSize; + } else if (style.size.indexOf('pt') != -1) { + computedStyle.size = fontSize / .75; + } else { + computedStyle.size = canvasFontSize; + } + + // Different scaling between normal text and VML text. This was found using + // trial and error to get the same size as non VML text. + computedStyle.size *= 0.981; + + // Fix for VML handling of bare font family names. Add a '' around font family names. + computedStyle.family = "'" + computedStyle.family.replace(/(\'|\")/g,'').replace(/\s*,\s*/g, "', '") + "'"; + + return computedStyle; + } + + function buildStyle(style) { + return style.style + ' ' + style.variant + ' ' + style.weight + ' ' + + style.size + 'px ' + style.family; + } + + var lineCapMap = { + 'butt': 'flat', + 'round': 'round' + }; + + function processLineCap(lineCap) { + return lineCapMap[lineCap] || 'square'; + } + + /** + * This class implements CanvasRenderingContext2D interface as described by + * the WHATWG. + * @param {HTMLElement} canvasElement The element that the 2D context should + * be associated with + */ + function CanvasRenderingContext2D_(canvasElement) { + this.m_ = createMatrixIdentity(); + + this.mStack_ = []; + this.aStack_ = []; + this.currentPath_ = []; + + // Canvas context properties + this.strokeStyle = '#000'; + this.fillStyle = '#000'; + + this.lineWidth = 1; + this.lineJoin = 'miter'; + this.lineCap = 'butt'; + this.miterLimit = Z * 1; + this.globalAlpha = 1; + this.font = '10px sans-serif'; + this.textAlign = 'left'; + this.textBaseline = 'alphabetic'; + this.canvas = canvasElement; + + var cssText = 'width:' + canvasElement.clientWidth + 'px;height:' + + canvasElement.clientHeight + 'px;overflow:hidden;position:absolute'; + var el = canvasElement.ownerDocument.createElement('div'); + el.style.cssText = cssText; + canvasElement.appendChild(el); + + var overlayEl = el.cloneNode(false); + // Use a non transparent background. + overlayEl.style.backgroundColor = 'red'; + overlayEl.style.filter = 'alpha(opacity=0)'; + canvasElement.appendChild(overlayEl); + + this.element_ = el; + this.arcScaleX_ = 1; + this.arcScaleY_ = 1; + this.lineScale_ = 1; + } + + var contextPrototype = CanvasRenderingContext2D_.prototype; + contextPrototype.clearRect = function() { + if (this.textMeasureEl_) { + this.textMeasureEl_.removeNode(true); + this.textMeasureEl_ = null; + } + this.element_.innerHTML = ''; + }; + + contextPrototype.beginPath = function() { + // TODO: Branch current matrix so that save/restore has no effect + // as per safari docs. + this.currentPath_ = []; + }; + + contextPrototype.moveTo = function(aX, aY) { + var p = getCoords(this, aX, aY); + this.currentPath_.push({type: 'moveTo', x: p.x, y: p.y}); + this.currentX_ = p.x; + this.currentY_ = p.y; + }; + + contextPrototype.lineTo = function(aX, aY) { + var p = getCoords(this, aX, aY); + this.currentPath_.push({type: 'lineTo', x: p.x, y: p.y}); + + this.currentX_ = p.x; + this.currentY_ = p.y; + }; + + contextPrototype.bezierCurveTo = function(aCP1x, aCP1y, + aCP2x, aCP2y, + aX, aY) { + var p = getCoords(this, aX, aY); + var cp1 = getCoords(this, aCP1x, aCP1y); + var cp2 = getCoords(this, aCP2x, aCP2y); + bezierCurveTo(this, cp1, cp2, p); + }; + + // Helper function that takes the already fixed cordinates. + function bezierCurveTo(self, cp1, cp2, p) { + self.currentPath_.push({ + type: 'bezierCurveTo', + cp1x: cp1.x, + cp1y: cp1.y, + cp2x: cp2.x, + cp2y: cp2.y, + x: p.x, + y: p.y + }); + self.currentX_ = p.x; + self.currentY_ = p.y; + } + + contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) { + // the following is lifted almost directly from + // http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes + + var cp = getCoords(this, aCPx, aCPy); + var p = getCoords(this, aX, aY); + + var cp1 = { + x: this.currentX_ + 2.0 / 3.0 * (cp.x - this.currentX_), + y: this.currentY_ + 2.0 / 3.0 * (cp.y - this.currentY_) + }; + var cp2 = { + x: cp1.x + (p.x - this.currentX_) / 3.0, + y: cp1.y + (p.y - this.currentY_) / 3.0 + }; + + bezierCurveTo(this, cp1, cp2, p); + }; + + contextPrototype.arc = function(aX, aY, aRadius, + aStartAngle, aEndAngle, aClockwise) { + aRadius *= Z; + var arcType = aClockwise ? 'at' : 'wa'; + + var xStart = aX + mc(aStartAngle) * aRadius - Z2; + var yStart = aY + ms(aStartAngle) * aRadius - Z2; + + var xEnd = aX + mc(aEndAngle) * aRadius - Z2; + var yEnd = aY + ms(aEndAngle) * aRadius - Z2; + + // IE won't render arches drawn counter clockwise if xStart == xEnd. + if (xStart == xEnd && !aClockwise) { + xStart += 0.125; // Offset xStart by 1/80 of a pixel. Use something + // that can be represented in binary + } + + var p = getCoords(this, aX, aY); + var pStart = getCoords(this, xStart, yStart); + var pEnd = getCoords(this, xEnd, yEnd); + + this.currentPath_.push({type: arcType, + x: p.x, + y: p.y, + radius: aRadius, + xStart: pStart.x, + yStart: pStart.y, + xEnd: pEnd.x, + yEnd: pEnd.y}); + + }; + + contextPrototype.rect = function(aX, aY, aWidth, aHeight) { + this.moveTo(aX, aY); + this.lineTo(aX + aWidth, aY); + this.lineTo(aX + aWidth, aY + aHeight); + this.lineTo(aX, aY + aHeight); + this.closePath(); + }; + + contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) { + var oldPath = this.currentPath_; + this.beginPath(); + + this.moveTo(aX, aY); + this.lineTo(aX + aWidth, aY); + this.lineTo(aX + aWidth, aY + aHeight); + this.lineTo(aX, aY + aHeight); + this.closePath(); + this.stroke(); + + this.currentPath_ = oldPath; + }; + + contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) { + var oldPath = this.currentPath_; + this.beginPath(); + + this.moveTo(aX, aY); + this.lineTo(aX + aWidth, aY); + this.lineTo(aX + aWidth, aY + aHeight); + this.lineTo(aX, aY + aHeight); + this.closePath(); + this.fill(); + + this.currentPath_ = oldPath; + }; + + contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) { + var gradient = new CanvasGradient_('gradient'); + gradient.x0_ = aX0; + gradient.y0_ = aY0; + gradient.x1_ = aX1; + gradient.y1_ = aY1; + return gradient; + }; + + contextPrototype.createRadialGradient = function(aX0, aY0, aR0, + aX1, aY1, aR1) { + var gradient = new CanvasGradient_('gradientradial'); + gradient.x0_ = aX0; + gradient.y0_ = aY0; + gradient.r0_ = aR0; + gradient.x1_ = aX1; + gradient.y1_ = aY1; + gradient.r1_ = aR1; + return gradient; + }; + + contextPrototype.drawImage = function(image, var_args) { + var dx, dy, dw, dh, sx, sy, sw, sh; + + // to find the original width we overide the width and height + var oldRuntimeWidth = image.runtimeStyle.width; + var oldRuntimeHeight = image.runtimeStyle.height; + image.runtimeStyle.width = 'auto'; + image.runtimeStyle.height = 'auto'; + + // get the original size + var w = image.width; + var h = image.height; + + // and remove overides + image.runtimeStyle.width = oldRuntimeWidth; + image.runtimeStyle.height = oldRuntimeHeight; + + if (arguments.length == 3) { + dx = arguments[1]; + dy = arguments[2]; + sx = sy = 0; + sw = dw = w; + sh = dh = h; + } else if (arguments.length == 5) { + dx = arguments[1]; + dy = arguments[2]; + dw = arguments[3]; + dh = arguments[4]; + sx = sy = 0; + sw = w; + sh = h; + } else if (arguments.length == 9) { + sx = arguments[1]; + sy = arguments[2]; + sw = arguments[3]; + sh = arguments[4]; + dx = arguments[5]; + dy = arguments[6]; + dw = arguments[7]; + dh = arguments[8]; + } else { + throw Error('Invalid number of arguments'); + } + + var d = getCoords(this, dx, dy); + + var w2 = sw / 2; + var h2 = sh / 2; + + var vmlStr = []; + + var W = 10; + var H = 10; + + // For some reason that I've now forgotten, using divs didn't work + vmlStr.push(' <g_vml_:group', + ' coordsize="', Z * W, ',', Z * H, '"', + ' coordorigin="0,0"' , + ' style="width:', W, 'px;height:', H, 'px;position:absolute;'); + + // If filters are necessary (rotation exists), create them + // filters are bog-slow, so only create them if abbsolutely necessary + // The following check doesn't account for skews (which don't exist + // in the canvas spec (yet) anyway. + + if (this.m_[0][0] != 1 || this.m_[0][1] || + this.m_[1][1] != 1 || this.m_[1][0]) { + var filter = []; + + // Note the 12/21 reversal + filter.push('M11=', this.m_[0][0], ',', + 'M12=', this.m_[1][0], ',', + 'M21=', this.m_[0][1], ',', + 'M22=', this.m_[1][1], ',', + 'Dx=', mr(d.x / Z), ',', + 'Dy=', mr(d.y / Z), ''); + + // Bounding box calculation (need to minimize displayed area so that + // filters don't waste time on unused pixels. + var max = d; + var c2 = getCoords(this, dx + dw, dy); + var c3 = getCoords(this, dx, dy + dh); + var c4 = getCoords(this, dx + dw, dy + dh); + + max.x = m.max(max.x, c2.x, c3.x, c4.x); + max.y = m.max(max.y, c2.y, c3.y, c4.y); + + vmlStr.push('padding:0 ', mr(max.x / Z), 'px ', mr(max.y / Z), + 'px 0;filter:progid:DXImageTransform.Microsoft.Matrix(', + filter.join(''), ", sizingmethod='clip');"); + + } else { + vmlStr.push('top:', mr(d.y / Z), 'px;left:', mr(d.x / Z), 'px;'); + } + + vmlStr.push(' ">' , + '<g_vml_:image src="', image.src, '"', + ' style="width:', Z * dw, 'px;', + ' height:', Z * dh, 'px"', + ' cropleft="', sx / w, '"', + ' croptop="', sy / h, '"', + ' cropright="', (w - sx - sw) / w, '"', + ' cropbottom="', (h - sy - sh) / h, '"', + ' />', + '</g_vml_:group>'); + + this.element_.insertAdjacentHTML('BeforeEnd', vmlStr.join('')); + }; + + contextPrototype.stroke = function(aFill) { + var lineStr = []; + var lineOpen = false; + + var W = 10; + var H = 10; + + lineStr.push('<g_vml_:shape', + ' filled="', !!aFill, '"', + ' style="position:absolute;width:', W, 'px;height:', H, 'px;"', + ' coordorigin="0,0"', + ' coordsize="', Z * W, ',', Z * H, '"', + ' stroked="', !aFill, '"', + ' path="'); + + var newSeq = false; + var min = {x: null, y: null}; + var max = {x: null, y: null}; + + for (var i = 0; i < this.currentPath_.length; i++) { + var p = this.currentPath_[i]; + var c; + + switch (p.type) { + case 'moveTo': + c = p; + lineStr.push(' m ', mr(p.x), ',', mr(p.y)); + break; + case 'lineTo': + lineStr.push(' l ', mr(p.x), ',', mr(p.y)); + break; + case 'close': + lineStr.push(' x '); + p = null; + break; + case 'bezierCurveTo': + lineStr.push(' c ', + mr(p.cp1x), ',', mr(p.cp1y), ',', + mr(p.cp2x), ',', mr(p.cp2y), ',', + mr(p.x), ',', mr(p.y)); + break; + case 'at': + case 'wa': + lineStr.push(' ', p.type, ' ', + mr(p.x - this.arcScaleX_ * p.radius), ',', + mr(p.y - this.arcScaleY_ * p.radius), ' ', + mr(p.x + this.arcScaleX_ * p.radius), ',', + mr(p.y + this.arcScaleY_ * p.radius), ' ', + mr(p.xStart), ',', mr(p.yStart), ' ', + mr(p.xEnd), ',', mr(p.yEnd)); + break; + } + + + // TODO: Following is broken for curves due to + // move to proper paths. + + // Figure out dimensions so we can do gradient fills + // properly + if (p) { + if (min.x == null || p.x < min.x) { + min.x = p.x; + } + if (max.x == null || p.x > max.x) { + max.x = p.x; + } + if (min.y == null || p.y < min.y) { + min.y = p.y; + } + if (max.y == null || p.y > max.y) { + max.y = p.y; + } + } + } + lineStr.push(' ">'); + + if (!aFill) { + appendStroke(this, lineStr); + } else { + appendFill(this, lineStr, min, max); + } + + lineStr.push('</g_vml_:shape>'); + + this.element_.insertAdjacentHTML('beforeEnd', lineStr.join('')); + }; + + function appendStroke(ctx, lineStr) { + var a = processStyle(ctx.strokeStyle); + var color = a.color; + var opacity = a.alpha * ctx.globalAlpha; + var lineWidth = ctx.lineScale_ * ctx.lineWidth; + + // VML cannot correctly render a line if the width is less than 1px. + // In that case, we dilute the color to make the line look thinner. + if (lineWidth < 1) { + opacity *= lineWidth; + } + + lineStr.push( + '<g_vml_:stroke', + ' opacity="', opacity, '"', + ' joinstyle="', ctx.lineJoin, '"', + ' miterlimit="', ctx.miterLimit, '"', + ' endcap="', processLineCap(ctx.lineCap), '"', + ' weight="', lineWidth, 'px"', + ' color="', color, '" />' + ); + } + + function appendFill(ctx, lineStr, min, max) { + var fillStyle = ctx.fillStyle; + var arcScaleX = ctx.arcScaleX_; + var arcScaleY = ctx.arcScaleY_; + var width = max.x - min.x; + var height = max.y - min.y; + if (fillStyle instanceof CanvasGradient_) { + // TODO: Gradients transformed with the transformation matrix. + var angle = 0; + var focus = {x: 0, y: 0}; + + // additional offset + var shift = 0; + // scale factor for offset + var expansion = 1; + + if (fillStyle.type_ == 'gradient') { + var x0 = fillStyle.x0_ / arcScaleX; + var y0 = fillStyle.y0_ / arcScaleY; + var x1 = fillStyle.x1_ / arcScaleX; + var y1 = fillStyle.y1_ / arcScaleY; + var p0 = getCoords(ctx, x0, y0); + var p1 = getCoords(ctx, x1, y1); + var dx = p1.x - p0.x; + var dy = p1.y - p0.y; + angle = Math.atan2(dx, dy) * 180 / Math.PI; + + // The angle should be a non-negative number. + if (angle < 0) { + angle += 360; + } + + // Very small angles produce an unexpected result because they are + // converted to a scientific notation string. + if (angle < 1e-6) { + angle = 0; + } + } else { + var p0 = getCoords(ctx, fillStyle.x0_, fillStyle.y0_); + focus = { + x: (p0.x - min.x) / width, + y: (p0.y - min.y) / height + }; + + width /= arcScaleX * Z; + height /= arcScaleY * Z; + var dimension = m.max(width, height); + shift = 2 * fillStyle.r0_ / dimension; + expansion = 2 * fillStyle.r1_ / dimension - shift; + } + + // We need to sort the color stops in ascending order by offset, + // otherwise IE won't interpret it correctly. + var stops = fillStyle.colors_; + stops.sort(function(cs1, cs2) { + return cs1.offset - cs2.offset; + }); + + var length = stops.length; + var color1 = stops[0].color; + var color2 = stops[length - 1].color; + var opacity1 = stops[0].alpha * ctx.globalAlpha; + var opacity2 = stops[length - 1].alpha * ctx.globalAlpha; + + var colors = []; + for (var i = 0; i < length; i++) { + var stop = stops[i]; + colors.push(stop.offset * expansion + shift + ' ' + stop.color); + } + + // When colors attribute is used, the meanings of opacity and o:opacity2 + // are reversed. + lineStr.push('<g_vml_:fill type="', fillStyle.type_, '"', + ' method="none" focus="100%"', + ' color="', color1, '"', + ' color2="', color2, '"', + ' colors="', colors.join(','), '"', + ' opacity="', opacity2, '"', + ' g_o_:opacity2="', opacity1, '"', + ' angle="', angle, '"', + ' focusposition="', focus.x, ',', focus.y, '" />'); + } else if (fillStyle instanceof CanvasPattern_) { + if (width && height) { + var deltaLeft = -min.x; + var deltaTop = -min.y; + lineStr.push('<g_vml_:fill', + ' position="', + deltaLeft / width * arcScaleX * arcScaleX, ',', + deltaTop / height * arcScaleY * arcScaleY, '"', + ' type="tile"', + // TODO: Figure out the correct size to fit the scale. + //' size="', w, 'px ', h, 'px"', + ' src="', fillStyle.src_, '" />'); + } + } else { + var a = processStyle(ctx.fillStyle); + var color = a.color; + var opacity = a.alpha * ctx.globalAlpha; + lineStr.push('<g_vml_:fill color="', color, '" opacity="', opacity, + '" />'); + } + } + + contextPrototype.fill = function() { + this.stroke(true); + }; + + contextPrototype.closePath = function() { + this.currentPath_.push({type: 'close'}); + }; + + function getCoords(ctx, aX, aY) { + var m = ctx.m_; + return { + x: Z * (aX * m[0][0] + aY * m[1][0] + m[2][0]) - Z2, + y: Z * (aX * m[0][1] + aY * m[1][1] + m[2][1]) - Z2 + }; + }; + + contextPrototype.save = function() { + var o = {}; + copyState(this, o); + this.aStack_.push(o); + this.mStack_.push(this.m_); + this.m_ = matrixMultiply(createMatrixIdentity(), this.m_); + }; + + contextPrototype.restore = function() { + if (this.aStack_.length) { + copyState(this.aStack_.pop(), this); + this.m_ = this.mStack_.pop(); + } + }; + + function matrixIsFinite(m) { + return isFinite(m[0][0]) && isFinite(m[0][1]) && + isFinite(m[1][0]) && isFinite(m[1][1]) && + isFinite(m[2][0]) && isFinite(m[2][1]); + } + + function setM(ctx, m, updateLineScale) { + if (!matrixIsFinite(m)) { + return; + } + ctx.m_ = m; + + if (updateLineScale) { + // Get the line scale. + // Determinant of this.m_ means how much the area is enlarged by the + // transformation. So its square root can be used as a scale factor + // for width. + var det = m[0][0] * m[1][1] - m[0][1] * m[1][0]; + ctx.lineScale_ = sqrt(abs(det)); + } + } + + contextPrototype.translate = function(aX, aY) { + var m1 = [ + [1, 0, 0], + [0, 1, 0], + [aX, aY, 1] + ]; + + setM(this, matrixMultiply(m1, this.m_), false); + }; + + contextPrototype.rotate = function(aRot) { + var c = mc(aRot); + var s = ms(aRot); + + var m1 = [ + [c, s, 0], + [-s, c, 0], + [0, 0, 1] + ]; + + setM(this, matrixMultiply(m1, this.m_), false); + }; + + contextPrototype.scale = function(aX, aY) { + this.arcScaleX_ *= aX; + this.arcScaleY_ *= aY; + var m1 = [ + [aX, 0, 0], + [0, aY, 0], + [0, 0, 1] + ]; + + setM(this, matrixMultiply(m1, this.m_), true); + }; + + contextPrototype.transform = function(m11, m12, m21, m22, dx, dy) { + var m1 = [ + [m11, m12, 0], + [m21, m22, 0], + [dx, dy, 1] + ]; + + setM(this, matrixMultiply(m1, this.m_), true); + }; + + contextPrototype.setTransform = function(m11, m12, m21, m22, dx, dy) { + var m = [ + [m11, m12, 0], + [m21, m22, 0], + [dx, dy, 1] + ]; + + setM(this, m, true); + }; + + /** + * The text drawing function. + * The maxWidth argument isn't taken in account, since no browser supports + * it yet. + */ + contextPrototype.drawText_ = function(text, x, y, maxWidth, stroke) { + var m = this.m_, + delta = 1000, + left = 0, + right = delta, + offset = {x: 0, y: 0}, + lineStr = []; + + var fontStyle = getComputedStyle(processFontStyle(this.font), this.element_); + + var fontStyleString = buildStyle(fontStyle); + + var elementStyle = this.element_.currentStyle; + var textAlign = this.textAlign.toLowerCase(); + switch (textAlign) { + case 'left': + case 'center': + case 'right': + break; + case 'end': + textAlign = elementStyle.direction == 'ltr' ? 'right' : 'left'; + break; + case 'start': + textAlign = elementStyle.direction == 'rtl' ? 'right' : 'left'; + break; + default: + textAlign = 'left'; + } + + // 1.75 is an arbitrary number, as there is no info about the text baseline + switch (this.textBaseline) { + case 'hanging': + case 'top': + offset.y = fontStyle.size / 1.75; + break; + case 'middle': + break; + default: + case null: + case 'alphabetic': + case 'ideographic': + case 'bottom': + offset.y = -fontStyle.size / 2.25; + break; + } + + switch(textAlign) { + case 'right': + left = delta; + right = 0.05; + break; + case 'center': + left = right = delta / 2; + break; + } + + var d = getCoords(this, x + offset.x, y + offset.y); + + lineStr.push('<g_vml_:line from="', -left ,' 0" to="', right ,' 0.05" ', + ' coordsize="100 100" coordorigin="0 0"', + ' filled="', !stroke, '" stroked="', !!stroke, + '" style="position:absolute;width:1px;height:1px;">'); + + if (stroke) { + appendStroke(this, lineStr); + } else { + // TODO: Fix the min and max params. + appendFill(this, lineStr, {x: -left, y: 0}, + {x: right, y: fontStyle.size}); + } + + var skewM = m[0][0].toFixed(3) + ',' + m[1][0].toFixed(3) + ',' + + m[0][1].toFixed(3) + ',' + m[1][1].toFixed(3) + ',0,0'; + + var skewOffset = mr(d.x / Z + 1 - m[0][0]) + ',' + mr(d.y / Z - 2 * m[1][0]); + + + lineStr.push('<g_vml_:skew on="t" matrix="', skewM ,'" ', + ' offset="', skewOffset, '" origin="', left ,' 0" />', + '<g_vml_:path textpathok="true" />', + '<g_vml_:textpath on="true" string="', + encodeHtmlAttribute(text), + '" style="v-text-align:', textAlign, + ';font:', encodeHtmlAttribute(fontStyleString), + '" /></g_vml_:line>'); + + this.element_.insertAdjacentHTML('beforeEnd', lineStr.join('')); + }; + + contextPrototype.fillText = function(text, x, y, maxWidth) { + this.drawText_(text, x, y, maxWidth, false); + }; + + contextPrototype.strokeText = function(text, x, y, maxWidth) { + this.drawText_(text, x, y, maxWidth, true); + }; + + contextPrototype.measureText = function(text) { + if (!this.textMeasureEl_) { + var s = '<span style="position:absolute;' + + 'top:-20000px;left:0;padding:0;margin:0;border:none;' + + 'white-space:pre;"></span>'; + this.element_.insertAdjacentHTML('beforeEnd', s); + this.textMeasureEl_ = this.element_.lastChild; + } + var doc = this.element_.ownerDocument; + this.textMeasureEl_.innerHTML = ''; + this.textMeasureEl_.style.font = this.font; + // Don't use innerHTML or innerText because they allow markup/whitespace. + this.textMeasureEl_.appendChild(doc.createTextNode(text)); + return {width: this.textMeasureEl_.offsetWidth}; + }; + + /******** STUBS ********/ + contextPrototype.clip = function() { + // TODO: Implement + }; + + contextPrototype.arcTo = function() { + // TODO: Implement + }; + + contextPrototype.createPattern = function(image, repetition) { + return new CanvasPattern_(image, repetition); + }; + + // Gradient / Pattern Stubs + function CanvasGradient_(aType) { + this.type_ = aType; + this.x0_ = 0; + this.y0_ = 0; + this.r0_ = 0; + this.x1_ = 0; + this.y1_ = 0; + this.r1_ = 0; + this.colors_ = []; + } + + CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) { + aColor = processStyle(aColor); + this.colors_.push({offset: aOffset, + color: aColor.color, + alpha: aColor.alpha}); + }; + + function CanvasPattern_(image, repetition) { + assertImageIsValid(image); + switch (repetition) { + case 'repeat': + case null: + case '': + this.repetition_ = 'repeat'; + break; + case 'repeat-x': + case 'repeat-y': + case 'no-repeat': + this.repetition_ = repetition; + break; + default: + throwException('SYNTAX_ERR'); + } + + this.src_ = image.src; + this.width_ = image.width; + this.height_ = image.height; + } + + function throwException(s) { + throw new DOMException_(s); + } + + function assertImageIsValid(img) { + if (!img || img.nodeType != 1 || img.tagName != 'IMG') { + throwException('TYPE_MISMATCH_ERR'); + } + if (img.readyState != 'complete') { + throwException('INVALID_STATE_ERR'); + } + } + + function DOMException_(s) { + this.code = this[s]; + this.message = s +': DOM Exception ' + this.code; + } + var p = DOMException_.prototype = new Error; + p.INDEX_SIZE_ERR = 1; + p.DOMSTRING_SIZE_ERR = 2; + p.HIERARCHY_REQUEST_ERR = 3; + p.WRONG_DOCUMENT_ERR = 4; + p.INVALID_CHARACTER_ERR = 5; + p.NO_DATA_ALLOWED_ERR = 6; + p.NO_MODIFICATION_ALLOWED_ERR = 7; + p.NOT_FOUND_ERR = 8; + p.NOT_SUPPORTED_ERR = 9; + p.INUSE_ATTRIBUTE_ERR = 10; + p.INVALID_STATE_ERR = 11; + p.SYNTAX_ERR = 12; + p.INVALID_MODIFICATION_ERR = 13; + p.NAMESPACE_ERR = 14; + p.INVALID_ACCESS_ERR = 15; + p.VALIDATION_ERR = 16; + p.TYPE_MISMATCH_ERR = 17; + + // set up externs + G_vmlCanvasManager = G_vmlCanvasManager_; + CanvasRenderingContext2D = CanvasRenderingContext2D_; + CanvasGradient = CanvasGradient_; + CanvasPattern = CanvasPattern_; + DOMException = DOMException_; + G_vmlCanvasManager._version = 888; +})(); + +} // if diff --git a/hugo/js/jqplot/jquery.jqplot.js b/hugo/js/jqplot/jquery.jqplot.js new file mode 100644 index 0000000..cded47a --- /dev/null +++ b/hugo/js/jqplot/jquery.jqplot.js @@ -0,0 +1,11381 @@ +/** + * Title: jqPlot Charts + * + * Pure JavaScript plotting plugin for jQuery. + * + * About: Version + * + * version: 1.0.4 + * revision: 1121 + * + * About: Copyright & License + * + * Copyright (c) 2009-2012 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT and GPL version 2.0 licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * See <GPL Version 2> and <MIT License> contained within this distribution for further information. + * + * The author would appreciate an email letting him know of any substantial + * use of jqPlot. You can reach the author at: chris at jqplot dot com + * or see http://www.jqplot.com/info.php. This is, of course, not required. + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php. + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + * + * About: Introduction + * + * jqPlot requires jQuery (1.4+ required for certain features). jQuery 1.4.2 is included in the distribution. + * To use jqPlot include jQuery, the jqPlot jQuery plugin, the jqPlot css file and optionally + * the excanvas script for IE support in your web page: + * + * > <!--[if lt IE 9]><script language="javascript" type="text/javascript" src="excanvas.js"></script><![endif]--> + * > <script language="javascript" type="text/javascript" src="jquery-1.4.4.min.js"></script> + * > <script language="javascript" type="text/javascript" src="jquery.jqplot.min.js"></script> + * > <link rel="stylesheet" type="text/css" href="jquery.jqplot.css" /> + * + * jqPlot can be customized by overriding the defaults of any of the objects which make + * up the plot. The general usage of jqplot is: + * + * > chart = $.jqplot('targetElemId', [dataArray,...], {optionsObject}); + * + * The options available to jqplot are detailed in <jqPlot Options> in the jqPlotOptions.txt file. + * + * An actual call to $.jqplot() may look like the + * examples below: + * + * > chart = $.jqplot('chartdiv', [[[1, 2],[3,5.12],[5,13.1],[7,33.6],[9,85.9],[11,219.9]]]); + * + * or + * + * > dataArray = [34,12,43,55,77]; + * > chart = $.jqplot('targetElemId', [dataArray, ...], {title:'My Plot', axes:{yaxis:{min:20, max:100}}}); + * + * For more inforrmation, see <jqPlot Usage>. + * + * About: Usage + * + * See <jqPlot Usage> + * + * About: Available Options + * + * See <jqPlot Options> for a list of options available thorugh the options object (not complete yet!) + * + * About: Options Usage + * + * See <Options Tutorial> + * + * About: Changes + * + * See <Change Log> + * + */ + +(function($) { + // make sure undefined is undefined + var undefined; + + $.fn.emptyForce = function() { + for ( var i = 0, elem; (elem = $(this)[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + $.cleanData( elem.getElementsByTagName("*") ); + } + + // Remove any remaining nodes + if ($.jqplot.use_excanvas) { + elem.outerHTML = ""; + } + else { + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + } + + elem = null; + } + + return $(this); + }; + + $.fn.removeChildForce = function(parent) { + while ( parent.firstChild ) { + this.removeChildForce( parent.firstChild ); + parent.removeChild( parent.firstChild ); + } + }; + + $.fn.jqplot = function() { + var datas = []; + var options = []; + // see how many data arrays we have + for (var i=0, l=arguments.length; i<l; i++) { + if ($.isArray(arguments[i])) { + datas.push(arguments[i]); + } + else if ($.isPlainObject(arguments[i])) { + options.push(arguments[i]); + } + } + + return this.each(function(index) { + var tid, + plot, + $this = $(this), + dl = datas.length, + ol = options.length, + data, + opts; + + if (index < dl) { + data = datas[index]; + } + else { + data = dl ? datas[dl-1] : null; + } + + if (index < ol) { + opts = options[index]; + } + else { + opts = ol ? options[ol-1] : null; + } + + // does el have an id? + // if not assign it one. + tid = $this.attr('id'); + if (tid === undefined) { + tid = 'jqplot_target_' + $.jqplot.targetCounter++; + $this.attr('id', tid); + } + + plot = $.jqplot(tid, data, opts); + + $this.data('jqplot', plot); + }); + }; + + + /** + * Namespace: $.jqplot + * jQuery function called by the user to create a plot. + * + * Parameters: + * target - ID of target element to render the plot into. + * data - an array of data series. + * options - user defined options object. See the individual classes for available options. + * + * Properties: + * config - object to hold configuration information for jqPlot plot object. + * + * attributes: + * enablePlugins - False to disable plugins by default. Plugins must then be explicitly + * enabled in the individual plot options. Default: false. + * This property sets the "show" property of certain plugins to true or false. + * Only plugins that can be immediately active upon loading are affected. This includes + * non-renderer plugins like cursor, dragable, highlighter, and trendline. + * defaultHeight - Default height for plots where no css height specification exists. This + * is a jqplot wide default. + * defaultWidth - Default height for plots where no css height specification exists. This + * is a jqplot wide default. + */ + + $.jqplot = function(target, data, options) { + var _data = null, _options = null; + + if (arguments.length === 3) { + _data = data; + _options = options; + } + + else if (arguments.length === 2) { + if ($.isArray(data)) { + _data = data; + } + + else if ($.isPlainObject(data)) { + _options = data; + } + } + + if (_data === null && _options !== null && _options.data) { + _data = _options.data; + } + + var plot = new jqPlot(); + // remove any error class that may be stuck on target. + $('#'+target).removeClass('jqplot-error'); + + if ($.jqplot.config.catchErrors) { + try { + plot.init(target, _data, _options); + plot.draw(); + plot.themeEngine.init.call(plot); + return plot; + } + catch(e) { + var msg = $.jqplot.config.errorMessage || e.message; + $('#'+target).append('<div class="jqplot-error-message">'+msg+'</div>'); + $('#'+target).addClass('jqplot-error'); + document.getElementById(target).style.background = $.jqplot.config.errorBackground; + document.getElementById(target).style.border = $.jqplot.config.errorBorder; + document.getElementById(target).style.fontFamily = $.jqplot.config.errorFontFamily; + document.getElementById(target).style.fontSize = $.jqplot.config.errorFontSize; + document.getElementById(target).style.fontStyle = $.jqplot.config.errorFontStyle; + document.getElementById(target).style.fontWeight = $.jqplot.config.errorFontWeight; + } + } + else { + plot.init(target, _data, _options); + plot.draw(); + plot.themeEngine.init.call(plot); + return plot; + } + }; + + $.jqplot.version = "1.0.4"; + $.jqplot.revision = "1121"; + + $.jqplot.targetCounter = 1; + + // canvas manager to reuse canvases on the plot. + // Should help solve problem of canvases not being freed and + // problem of waiting forever for firefox to decide to free memory. + $.jqplot.CanvasManager = function() { + // canvases are managed globally so that they can be reused + // across plots after they have been freed + if (typeof $.jqplot.CanvasManager.canvases == 'undefined') { + $.jqplot.CanvasManager.canvases = []; + $.jqplot.CanvasManager.free = []; + } + + var myCanvases = []; + + this.getCanvas = function() { + var canvas; + var makeNew = true; + + if (!$.jqplot.use_excanvas) { + for (var i = 0, l = $.jqplot.CanvasManager.canvases.length; i < l; i++) { + if ($.jqplot.CanvasManager.free[i] === true) { + makeNew = false; + canvas = $.jqplot.CanvasManager.canvases[i]; + // $(canvas).removeClass('jqplot-canvasManager-free').addClass('jqplot-canvasManager-inuse'); + $.jqplot.CanvasManager.free[i] = false; + myCanvases.push(i); + break; + } + } + } + + if (makeNew) { + canvas = document.createElement('canvas'); + myCanvases.push($.jqplot.CanvasManager.canvases.length); + $.jqplot.CanvasManager.canvases.push(canvas); + $.jqplot.CanvasManager.free.push(false); + } + + return canvas; + }; + + // this method has to be used after settings the dimesions + // on the element returned by getCanvas() + this.initCanvas = function(canvas) { + if ($.jqplot.use_excanvas) { + return window.G_vmlCanvasManager.initElement(canvas); + } + return canvas; + }; + + this.freeAllCanvases = function() { + for (var i = 0, l=myCanvases.length; i < l; i++) { + this.freeCanvas(myCanvases[i]); + } + myCanvases = []; + }; + + this.freeCanvas = function(idx) { + if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) { + // excanvas can't be reused, but properly unset + window.G_vmlCanvasManager.uninitElement($.jqplot.CanvasManager.canvases[idx]); + $.jqplot.CanvasManager.canvases[idx] = null; + } + else { + var canvas = $.jqplot.CanvasManager.canvases[idx]; + canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height); + $(canvas).unbind().removeAttr('class').removeAttr('style'); + // Style attributes seemed to be still hanging around. wierd. Some ticks + // still retained a left: 0px attribute after reusing a canvas. + $(canvas).css({left: '', top: '', position: ''}); + // setting size to 0 may save memory of unused canvases? + canvas.width = 0; + canvas.height = 0; + $.jqplot.CanvasManager.free[idx] = true; + } + }; + + }; + + + // Convienence function that won't hang IE or FF without FireBug. + $.jqplot.log = function() { + if (window.console) { + window.console.log.apply(window.console, arguments); + } + }; + + $.jqplot.config = { + addDomReference: false, + enablePlugins:false, + defaultHeight:300, + defaultWidth:400, + UTCAdjust:false, + timezoneOffset: new Date(new Date().getTimezoneOffset() * 60000), + errorMessage: '', + errorBackground: '', + errorBorder: '', + errorFontFamily: '', + errorFontSize: '', + errorFontStyle: '', + errorFontWeight: '', + catchErrors: false, + defaultTickFormatString: "%.1f", + defaultColors: [ "#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"], + defaultNegativeColors: [ "#498991", "#C08840", "#9F9274", "#546D61", "#646C4A", "#6F6621", "#6E3F5F", "#4F64B0", "#A89050", "#C45923", "#187399", "#945381", "#959E5C", "#C7AF7B", "#478396", "#907294"], + dashLength: 4, + gapLength: 4, + dotGapLength: 2.5, + srcLocation: 'jqplot/src/', + pluginLocation: 'jqplot/src/plugins/' + }; + + + $.jqplot.arrayMax = function( array ){ + return Math.max.apply( Math, array ); + }; + + $.jqplot.arrayMin = function( array ){ + return Math.min.apply( Math, array ); + }; + + $.jqplot.enablePlugins = $.jqplot.config.enablePlugins; + + // canvas related tests taken from modernizer: + // Copyright (c) 2009 - 2010 Faruk Ates. + // http://www.modernizr.com + + $.jqplot.support_canvas = function() { + if (typeof $.jqplot.support_canvas.result == 'undefined') { + $.jqplot.support_canvas.result = !!document.createElement('canvas').getContext; + } + return $.jqplot.support_canvas.result; + }; + + $.jqplot.support_canvas_text = function() { + if (typeof $.jqplot.support_canvas_text.result == 'undefined') { + if (window.G_vmlCanvasManager !== undefined && window.G_vmlCanvasManager._version > 887) { + $.jqplot.support_canvas_text.result = true; + } + else { + $.jqplot.support_canvas_text.result = !!(document.createElement('canvas').getContext && typeof document.createElement('canvas').getContext('2d').fillText == 'function'); + } + + } + return $.jqplot.support_canvas_text.result; + }; + + $.jqplot.use_excanvas = ($.browser.msie && !$.jqplot.support_canvas()) ? true : false; + + /** + * + * Hooks: jqPlot Pugin Hooks + * + * $.jqplot.preInitHooks - called before initialization. + * $.jqplot.postInitHooks - called after initialization. + * $.jqplot.preParseOptionsHooks - called before user options are parsed. + * $.jqplot.postParseOptionsHooks - called after user options are parsed. + * $.jqplot.preDrawHooks - called before plot draw. + * $.jqplot.postDrawHooks - called after plot draw. + * $.jqplot.preDrawSeriesHooks - called before each series is drawn. + * $.jqplot.postDrawSeriesHooks - called after each series is drawn. + * $.jqplot.preDrawLegendHooks - called before the legend is drawn. + * $.jqplot.addLegendRowHooks - called at the end of legend draw, so plugins + * can add rows to the legend table. + * $.jqplot.preSeriesInitHooks - called before series is initialized. + * $.jqplot.postSeriesInitHooks - called after series is initialized. + * $.jqplot.preParseSeriesOptionsHooks - called before series related options + * are parsed. + * $.jqplot.postParseSeriesOptionsHooks - called after series related options + * are parsed. + * $.jqplot.eventListenerHooks - called at the end of plot drawing, binds + * listeners to the event canvas which lays on top of the grid area. + * $.jqplot.preDrawSeriesShadowHooks - called before series shadows are drawn. + * $.jqplot.postDrawSeriesShadowHooks - called after series shadows are drawn. + * + */ + + $.jqplot.preInitHooks = []; + $.jqplot.postInitHooks = []; + $.jqplot.preParseOptionsHooks = []; + $.jqplot.postParseOptionsHooks = []; + $.jqplot.preDrawHooks = []; + $.jqplot.postDrawHooks = []; + $.jqplot.preDrawSeriesHooks = []; + $.jqplot.postDrawSeriesHooks = []; + $.jqplot.preDrawLegendHooks = []; + $.jqplot.addLegendRowHooks = []; + $.jqplot.preSeriesInitHooks = []; + $.jqplot.postSeriesInitHooks = []; + $.jqplot.preParseSeriesOptionsHooks = []; + $.jqplot.postParseSeriesOptionsHooks = []; + $.jqplot.eventListenerHooks = []; + $.jqplot.preDrawSeriesShadowHooks = []; + $.jqplot.postDrawSeriesShadowHooks = []; + + // A superclass holding some common properties and methods. + $.jqplot.ElemContainer = function() { + this._elem; + this._plotWidth; + this._plotHeight; + this._plotDimensions = {height:null, width:null}; + }; + + $.jqplot.ElemContainer.prototype.createElement = function(el, offsets, clss, cssopts, attrib) { + this._offsets = offsets; + var klass = clss || 'jqplot'; + var elem = document.createElement(el); + this._elem = $(elem); + this._elem.addClass(klass); + this._elem.css(cssopts); + this._elem.attr(attrib); + // avoid memory leak; + elem = null; + return this._elem; + }; + + $.jqplot.ElemContainer.prototype.getWidth = function() { + if (this._elem) { + return this._elem.outerWidth(true); + } + else { + return null; + } + }; + + $.jqplot.ElemContainer.prototype.getHeight = function() { + if (this._elem) { + return this._elem.outerHeight(true); + } + else { + return null; + } + }; + + $.jqplot.ElemContainer.prototype.getPosition = function() { + if (this._elem) { + return this._elem.position(); + } + else { + return {top:null, left:null, bottom:null, right:null}; + } + }; + + $.jqplot.ElemContainer.prototype.getTop = function() { + return this.getPosition().top; + }; + + $.jqplot.ElemContainer.prototype.getLeft = function() { + return this.getPosition().left; + }; + + $.jqplot.ElemContainer.prototype.getBottom = function() { + return this._elem.css('bottom'); + }; + + $.jqplot.ElemContainer.prototype.getRight = function() { + return this._elem.css('right'); + }; + + + /** + * Class: Axis + * An individual axis object. Cannot be instantiated directly, but created + * by the Plot oject. Axis properties can be set or overriden by the + * options passed in from the user. + * + */ + function Axis(name) { + $.jqplot.ElemContainer.call(this); + // Group: Properties + // + // Axes options are specified within an axes object at the top level of the + // plot options like so: + // > { + // > axes: { + // > xaxis: {min: 5}, + // > yaxis: {min: 2, max: 8, numberTicks:4}, + // > x2axis: {pad: 1.5}, + // > y2axis: {ticks:[22, 44, 66, 88]} + // > } + // > } + // There are 2 x axes, 'xaxis' and 'x2axis', and + // 9 yaxes, 'yaxis', 'y2axis'. 'y3axis', ... Any or all of which may be specified. + this.name = name; + this._series = []; + // prop: show + // Wether to display the axis on the graph. + this.show = false; + // prop: tickRenderer + // A class of a rendering engine for creating the ticks labels displayed on the plot, + // See <$.jqplot.AxisTickRenderer>. + this.tickRenderer = $.jqplot.AxisTickRenderer; + // prop: tickOptions + // Options that will be passed to the tickRenderer, see <$.jqplot.AxisTickRenderer> options. + this.tickOptions = {}; + // prop: labelRenderer + // A class of a rendering engine for creating an axis label. + this.labelRenderer = $.jqplot.AxisLabelRenderer; + // prop: labelOptions + // Options passed to the label renderer. + this.labelOptions = {}; + // prop: label + // Label for the axis + this.label = null; + // prop: showLabel + // true to show the axis label. + this.showLabel = true; + // prop: min + // minimum value of the axis (in data units, not pixels). + this.min = null; + // prop: max + // maximum value of the axis (in data units, not pixels). + this.max = null; + // prop: autoscale + // DEPRECATED + // the default scaling algorithm produces superior results. + this.autoscale = false; + // prop: pad + // Padding to extend the range above and below the data bounds. + // The data range is multiplied by this factor to determine minimum and maximum axis bounds. + // A value of 0 will be interpreted to mean no padding, and pad will be set to 1.0. + this.pad = 1.2; + // prop: padMax + // Padding to extend the range above data bounds. + // The top of the data range is multiplied by this factor to determine maximum axis bounds. + // A value of 0 will be interpreted to mean no padding, and padMax will be set to 1.0. + this.padMax = null; + // prop: padMin + // Padding to extend the range below data bounds. + // The bottom of the data range is multiplied by this factor to determine minimum axis bounds. + // A value of 0 will be interpreted to mean no padding, and padMin will be set to 1.0. + this.padMin = null; + // prop: ticks + // 1D [val, val, ...] or 2D [[val, label], [val, label], ...] array of ticks for the axis. + // If no label is specified, the value is formatted into an appropriate label. + this.ticks = []; + // prop: numberTicks + // Desired number of ticks. Default is to compute automatically. + this.numberTicks; + // prop: tickInterval + // number of units between ticks. Mutually exclusive with numberTicks. + this.tickInterval; + // prop: renderer + // A class of a rendering engine that handles tick generation, + // scaling input data to pixel grid units and drawing the axis element. + this.renderer = $.jqplot.LinearAxisRenderer; + // prop: rendererOptions + // renderer specific options. See <$.jqplot.LinearAxisRenderer> for options. + this.rendererOptions = {}; + // prop: showTicks + // Wether to show the ticks (both marks and labels) or not. + // Will not override showMark and showLabel options if specified on the ticks themselves. + this.showTicks = true; + // prop: showTickMarks + // Wether to show the tick marks (line crossing grid) or not. + // Overridden by showTicks and showMark option of tick itself. + this.showTickMarks = true; + // prop: showMinorTicks + // Wether or not to show minor ticks. This is renderer dependent. + this.showMinorTicks = true; + // prop: drawMajorGridlines + // True to draw gridlines for major axis ticks. + this.drawMajorGridlines = true; + // prop: drawMinorGridlines + // True to draw gridlines for minor ticks. + this.drawMinorGridlines = false; + // prop: drawMajorTickMarks + // True to draw tick marks for major axis ticks. + this.drawMajorTickMarks = true; + // prop: drawMinorTickMarks + // True to draw tick marks for minor ticks. This is renderer dependent. + this.drawMinorTickMarks = true; + // prop: useSeriesColor + // Use the color of the first series associated with this axis for the + // tick marks and line bordering this axis. + this.useSeriesColor = false; + // prop: borderWidth + // width of line stroked at the border of the axis. Defaults + // to the width of the grid boarder. + this.borderWidth = null; + // prop: borderColor + // color of the border adjacent to the axis. Defaults to grid border color. + this.borderColor = null; + // prop: scaleToHiddenSeries + // True to include hidden series when computing axes bounds and scaling. + this.scaleToHiddenSeries = false; + // minimum and maximum values on the axis. + this._dataBounds = {min:null, max:null}; + // statistics (min, max, mean) as well as actual data intervals for each series attached to axis. + // holds collection of {intervals:[], min:, max:, mean: } objects for each series on axis. + this._intervalStats = []; + // pixel position from the top left of the min value and max value on the axis. + this._offsets = {min:null, max:null}; + this._ticks=[]; + this._label = null; + // prop: syncTicks + // true to try and synchronize tick spacing across multiple axes so that ticks and + // grid lines line up. This has an impact on autoscaling algorithm, however. + // In general, autoscaling an individual axis will work better if it does not + // have to sync ticks. + this.syncTicks = null; + // prop: tickSpacing + // Approximate pixel spacing between ticks on graph. Used during autoscaling. + // This number will be an upper bound, actual spacing will be less. + this.tickSpacing = 75; + // Properties to hold the original values for min, max, ticks, tickInterval and numberTicks + // so they can be restored if altered by plugins. + this._min = null; + this._max = null; + this._tickInterval = null; + this._numberTicks = null; + this.__ticks = null; + // hold original user options. + this._options = {}; + } + + Axis.prototype = new $.jqplot.ElemContainer(); + Axis.prototype.constructor = Axis; + + Axis.prototype.init = function() { + if ($.isFunction(this.renderer)) { + this.renderer = new this.renderer(); + } + // set the axis name + this.tickOptions.axis = this.name; + // if showMark or showLabel tick options not specified, use value of axis option. + // showTicks overrides showTickMarks. + if (this.tickOptions.showMark == null) { + this.tickOptions.showMark = this.showTicks; + } + if (this.tickOptions.showMark == null) { + this.tickOptions.showMark = this.showTickMarks; + } + if (this.tickOptions.showLabel == null) { + this.tickOptions.showLabel = this.showTicks; + } + + if (this.label == null || this.label == '') { + this.showLabel = false; + } + else { + this.labelOptions.label = this.label; + } + if (this.showLabel == false) { + this.labelOptions.show = false; + } + // set the default padMax, padMin if not specified + // special check, if no padding desired, padding + // should be set to 1.0 + if (this.pad == 0) { + this.pad = 1.0; + } + if (this.padMax == 0) { + this.padMax = 1.0; + } + if (this.padMin == 0) { + this.padMin = 1.0; + } + if (this.padMax == null) { + this.padMax = (this.pad-1)/2 + 1; + } + if (this.padMin == null) { + this.padMin = (this.pad-1)/2 + 1; + } + // now that padMin and padMax are correctly set, reset pad in case user has supplied + // padMin and/or padMax + this.pad = this.padMax + this.padMin - 1; + if (this.min != null || this.max != null) { + this.autoscale = false; + } + // if not set, sync ticks for y axes but not x by default. + if (this.syncTicks == null && this.name.indexOf('y') > -1) { + this.syncTicks = true; + } + else if (this.syncTicks == null){ + this.syncTicks = false; + } + this.renderer.init.call(this, this.rendererOptions); + + }; + + Axis.prototype.draw = function(ctx, plot) { + // Memory Leaks patch + if (this.__ticks) { + this.__ticks = null; + } + + return this.renderer.draw.call(this, ctx, plot); + + }; + + Axis.prototype.set = function() { + this.renderer.set.call(this); + }; + + Axis.prototype.pack = function(pos, offsets) { + if (this.show) { + this.renderer.pack.call(this, pos, offsets); + } + // these properties should all be available now. + if (this._min == null) { + this._min = this.min; + this._max = this.max; + this._tickInterval = this.tickInterval; + this._numberTicks = this.numberTicks; + this.__ticks = this._ticks; + } + }; + + // reset the axis back to original values if it has been scaled, zoomed, etc. + Axis.prototype.reset = function() { + this.renderer.reset.call(this); + }; + + Axis.prototype.resetScale = function(opts) { + $.extend(true, this, {min: null, max: null, numberTicks: null, tickInterval: null, _ticks: [], ticks: []}, opts); + this.resetDataBounds(); + }; + + Axis.prototype.resetDataBounds = function() { + // Go through all the series attached to this axis and find + // the min/max bounds for this axis. + var db = this._dataBounds; + db.min = null; + db.max = null; + var l, s, d; + // check for when to force min 0 on bar series plots. + var doforce = (this.show) ? true : false; + for (var i=0; i<this._series.length; i++) { + s = this._series[i]; + if (s.show || this.scaleToHiddenSeries) { + d = s._plotData; + if (s._type === 'line' && s.renderer.bands.show && this.name.charAt(0) !== 'x') { + d = [[0, s.renderer.bands._min], [1, s.renderer.bands._max]]; + } + + var minyidx = 1, maxyidx = 1; + + if (s._type != null && s._type == 'ohlc') { + minyidx = 3; + maxyidx = 2; + } + + for (var j=0, l=d.length; j<l; j++) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + if ((d[j][0] != null && d[j][0] < db.min) || db.min == null) { + db.min = d[j][0]; + } + if ((d[j][0] != null && d[j][0] > db.max) || db.max == null) { + db.max = d[j][0]; + } + } + else { + if ((d[j][minyidx] != null && d[j][minyidx] < db.min) || db.min == null) { + db.min = d[j][minyidx]; + } + if ((d[j][maxyidx] != null && d[j][maxyidx] > db.max) || db.max == null) { + db.max = d[j][maxyidx]; + } + } + } + + // Hack to not pad out bottom of bar plots unless user has specified a padding. + // every series will have a chance to set doforce to false. once it is set to + // false, it cannot be reset to true. + // If any series attached to axis is not a bar, wont force 0. + if (doforce && s.renderer.constructor !== $.jqplot.BarRenderer) { + doforce = false; + } + + else if (doforce && this._options.hasOwnProperty('forceTickAt0') && this._options.forceTickAt0 == false) { + doforce = false; + } + + else if (doforce && s.renderer.constructor === $.jqplot.BarRenderer) { + if (s.barDirection == 'vertical' && this.name != 'xaxis' && this.name != 'x2axis') { + if (this._options.pad != null || this._options.padMin != null) { + doforce = false; + } + } + + else if (s.barDirection == 'horizontal' && (this.name == 'xaxis' || this.name == 'x2axis')) { + if (this._options.pad != null || this._options.padMin != null) { + doforce = false; + } + } + + } + } + } + + if (doforce && this.renderer.constructor === $.jqplot.LinearAxisRenderer && db.min >= 0) { + this.padMin = 1.0; + this.forceTickAt0 = true; + } + }; + + /** + * Class: Legend + * Legend object. Cannot be instantiated directly, but created + * by the Plot oject. Legend properties can be set or overriden by the + * options passed in from the user. + */ + function Legend(options) { + $.jqplot.ElemContainer.call(this); + // Group: Properties + + // prop: show + // Wether to display the legend on the graph. + this.show = false; + // prop: location + // Placement of the legend. one of the compass directions: nw, n, ne, e, se, s, sw, w + this.location = 'ne'; + // prop: labels + // Array of labels to use. By default the renderer will look for labels on the series. + // Labels specified in this array will override labels specified on the series. + this.labels = []; + // prop: showLabels + // true to show the label text on the legend. + this.showLabels = true; + // prop: showSwatch + // true to show the color swatches on the legend. + this.showSwatches = true; + // prop: placement + // "insideGrid" places legend inside the grid area of the plot. + // "outsideGrid" places the legend outside the grid but inside the plot container, + // shrinking the grid to accomodate the legend. + // "inside" synonym for "insideGrid", + // "outside" places the legend ouside the grid area, but does not shrink the grid which + // can cause the legend to overflow the plot container. + this.placement = "insideGrid"; + // prop: xoffset + // DEPRECATED. Set the margins on the legend using the marginTop, marginLeft, etc. + // properties or via CSS margin styling of the .jqplot-table-legend class. + this.xoffset = 0; + // prop: yoffset + // DEPRECATED. Set the margins on the legend using the marginTop, marginLeft, etc. + // properties or via CSS margin styling of the .jqplot-table-legend class. + this.yoffset = 0; + // prop: border + // css spec for the border around the legend box. + this.border; + // prop: background + // css spec for the background of the legend box. + this.background; + // prop: textColor + // css color spec for the legend text. + this.textColor; + // prop: fontFamily + // css font-family spec for the legend text. + this.fontFamily; + // prop: fontSize + // css font-size spec for the legend text. + this.fontSize ; + // prop: rowSpacing + // css padding-top spec for the rows in the legend. + this.rowSpacing = '0.5em'; + // renderer + // A class that will create a DOM object for the legend, + // see <$.jqplot.TableLegendRenderer>. + this.renderer = $.jqplot.TableLegendRenderer; + // prop: rendererOptions + // renderer specific options passed to the renderer. + this.rendererOptions = {}; + // prop: predraw + // Wether to draw the legend before the series or not. + // Used with series specific legend renderers for pie, donut, mekko charts, etc. + this.preDraw = false; + // prop: marginTop + // CSS margin for the legend DOM element. This will set an element + // CSS style for the margin which will override any style sheet setting. + // The default will be taken from the stylesheet. + this.marginTop = null; + // prop: marginRight + // CSS margin for the legend DOM element. This will set an element + // CSS style for the margin which will override any style sheet setting. + // The default will be taken from the stylesheet. + this.marginRight = null; + // prop: marginBottom + // CSS margin for the legend DOM element. This will set an element + // CSS style for the margin which will override any style sheet setting. + // The default will be taken from the stylesheet. + this.marginBottom = null; + // prop: marginLeft + // CSS margin for the legend DOM element. This will set an element + // CSS style for the margin which will override any style sheet setting. + // The default will be taken from the stylesheet. + this.marginLeft = null; + // prop: escapeHtml + // True to escape special characters with their html entity equivalents + // in legend text. "<" becomes < and so on, so html tags are not rendered. + this.escapeHtml = false; + this._series = []; + + $.extend(true, this, options); + } + + Legend.prototype = new $.jqplot.ElemContainer(); + Legend.prototype.constructor = Legend; + + Legend.prototype.setOptions = function(options) { + $.extend(true, this, options); + + // Try to emulate deprecated behaviour + // if user has specified xoffset or yoffset, copy these to + // the margin properties. + + if (this.placement == 'inside') { + this.placement = 'insideGrid'; + } + + if (this.xoffset >0) { + if (this.placement == 'insideGrid') { + switch (this.location) { + case 'nw': + case 'w': + case 'sw': + if (this.marginLeft == null) { + this.marginLeft = this.xoffset + 'px'; + } + this.marginRight = '0px'; + break; + case 'ne': + case 'e': + case 'se': + default: + if (this.marginRight == null) { + this.marginRight = this.xoffset + 'px'; + } + this.marginLeft = '0px'; + break; + } + } + else if (this.placement == 'outside') { + switch (this.location) { + case 'nw': + case 'w': + case 'sw': + if (this.marginRight == null) { + this.marginRight = this.xoffset + 'px'; + } + this.marginLeft = '0px'; + break; + case 'ne': + case 'e': + case 'se': + default: + if (this.marginLeft == null) { + this.marginLeft = this.xoffset + 'px'; + } + this.marginRight = '0px'; + break; + } + } + this.xoffset = 0; + } + + if (this.yoffset >0) { + if (this.placement == 'outside') { + switch (this.location) { + case 'sw': + case 's': + case 'se': + if (this.marginTop == null) { + this.marginTop = this.yoffset + 'px'; + } + this.marginBottom = '0px'; + break; + case 'ne': + case 'n': + case 'nw': + default: + if (this.marginBottom == null) { + this.marginBottom = this.yoffset + 'px'; + } + this.marginTop = '0px'; + break; + } + } + else if (this.placement == 'insideGrid') { + switch (this.location) { + case 'sw': + case 's': + case 'se': + if (this.marginBottom == null) { + this.marginBottom = this.yoffset + 'px'; + } + this.marginTop = '0px'; + break; + case 'ne': + case 'n': + case 'nw': + default: + if (this.marginTop == null) { + this.marginTop = this.yoffset + 'px'; + } + this.marginBottom = '0px'; + break; + } + } + this.yoffset = 0; + } + + // TO-DO: + // Handle case where offsets are < 0. + // + }; + + Legend.prototype.init = function() { + if ($.isFunction(this.renderer)) { + this.renderer = new this.renderer(); + } + this.renderer.init.call(this, this.rendererOptions); + }; + + Legend.prototype.draw = function(offsets, plot) { + for (var i=0; i<$.jqplot.preDrawLegendHooks.length; i++){ + $.jqplot.preDrawLegendHooks[i].call(this, offsets); + } + return this.renderer.draw.call(this, offsets, plot); + }; + + Legend.prototype.pack = function(offsets) { + this.renderer.pack.call(this, offsets); + }; + + /** + * Class: Title + * Plot Title object. Cannot be instantiated directly, but created + * by the Plot oject. Title properties can be set or overriden by the + * options passed in from the user. + * + * Parameters: + * text - text of the title. + */ + function Title(text) { + $.jqplot.ElemContainer.call(this); + // Group: Properties + + // prop: text + // text of the title; + this.text = text; + // prop: show + // wether or not to show the title + this.show = true; + // prop: fontFamily + // css font-family spec for the text. + this.fontFamily; + // prop: fontSize + // css font-size spec for the text. + this.fontSize ; + // prop: textAlign + // css text-align spec for the text. + this.textAlign; + // prop: textColor + // css color spec for the text. + this.textColor; + // prop: renderer + // A class for creating a DOM element for the title, + // see <$.jqplot.DivTitleRenderer>. + this.renderer = $.jqplot.DivTitleRenderer; + // prop: rendererOptions + // renderer specific options passed to the renderer. + this.rendererOptions = {}; + // prop: escapeHtml + // True to escape special characters with their html entity equivalents + // in title text. "<" becomes < and so on, so html tags are not rendered. + this.escapeHtml = false; + } + + Title.prototype = new $.jqplot.ElemContainer(); + Title.prototype.constructor = Title; + + Title.prototype.init = function() { + if ($.isFunction(this.renderer)) { + this.renderer = new this.renderer(); + } + this.renderer.init.call(this, this.rendererOptions); + }; + + Title.prototype.draw = function(width) { + return this.renderer.draw.call(this, width); + }; + + Title.prototype.pack = function() { + this.renderer.pack.call(this); + }; + + + /** + * Class: Series + * An individual data series object. Cannot be instantiated directly, but created + * by the Plot oject. Series properties can be set or overriden by the + * options passed in from the user. + */ + function Series(options) { + options = options || {}; + $.jqplot.ElemContainer.call(this); + // Group: Properties + // Properties will be assigned from a series array at the top level of the + // options. If you had two series and wanted to change the color and line + // width of the first and set the second to use the secondary y axis with + // no shadow and supply custom labels for each: + // > { + // > series:[ + // > {color: '#ff4466', lineWidth: 5, label:'good line'}, + // > {yaxis: 'y2axis', shadow: false, label:'bad line'} + // > ] + // > } + + // prop: show + // wether or not to draw the series. + this.show = true; + // prop: xaxis + // which x axis to use with this series, either 'xaxis' or 'x2axis'. + this.xaxis = 'xaxis'; + this._xaxis; + // prop: yaxis + // which y axis to use with this series, either 'yaxis' or 'y2axis'. + this.yaxis = 'yaxis'; + this._yaxis; + this.gridBorderWidth = 2.0; + // prop: renderer + // A class of a renderer which will draw the series, + // see <$.jqplot.LineRenderer>. + this.renderer = $.jqplot.LineRenderer; + // prop: rendererOptions + // Options to pass on to the renderer. + this.rendererOptions = {}; + this.data = []; + this.gridData = []; + // prop: label + // Line label to use in the legend. + this.label = ''; + // prop: showLabel + // true to show label for this series in the legend. + this.showLabel = true; + // prop: color + // css color spec for the series + this.color; + // prop: negativeColor + // css color spec used for filled (area) plots that are filled to zero and + // the "useNegativeColors" option is true. + this.negativeColor; + // prop: lineWidth + // width of the line in pixels. May have different meanings depending on renderer. + this.lineWidth = 2.5; + // prop: lineJoin + // Canvas lineJoin style between segments of series. + this.lineJoin = 'round'; + // prop: lineCap + // Canvas lineCap style at ends of line. + this.lineCap = 'round'; + // prop: linePattern + // line pattern 'dashed', 'dotted', 'solid', some combination + // of '-' and '.' characters such as '.-.' or a numerical array like + // [draw, skip, draw, skip, ...] such as [1, 10] to draw a dotted line, + // [1, 10, 20, 10] to draw a dot-dash line, and so on. + this.linePattern = 'solid'; + this.shadow = true; + // prop: shadowAngle + // Shadow angle in degrees + this.shadowAngle = 45; + // prop: shadowOffset + // Shadow offset from line in pixels + this.shadowOffset = 1.25; + // prop: shadowDepth + // Number of times shadow is stroked, each stroke offset shadowOffset from the last. + this.shadowDepth = 3; + // prop: shadowAlpha + // Alpha channel transparency of shadow. 0 = transparent. + this.shadowAlpha = '0.1'; + // prop: breakOnNull + // Wether line segments should be be broken at null value. + // False will join point on either side of line. + this.breakOnNull = false; + // prop: markerRenderer + // A class of a renderer which will draw marker (e.g. circle, square, ...) at the data points, + // see <$.jqplot.MarkerRenderer>. + this.markerRenderer = $.jqplot.MarkerRenderer; + // prop: markerOptions + // renderer specific options to pass to the markerRenderer, + // see <$.jqplot.MarkerRenderer>. + this.markerOptions = {}; + // prop: showLine + // wether to actually draw the line or not. Series will still be renderered, even if no line is drawn. + this.showLine = true; + // prop: showMarker + // wether or not to show the markers at the data points. + this.showMarker = true; + // prop: index + // 0 based index of this series in the plot series array. + this.index; + // prop: fill + // true or false, wether to fill under lines or in bars. + // May not be implemented in all renderers. + this.fill = false; + // prop: fillColor + // CSS color spec to use for fill under line. Defaults to line color. + this.fillColor; + // prop: fillAlpha + // Alpha transparency to apply to the fill under the line. + // Use this to adjust alpha separate from fill color. + this.fillAlpha; + // prop: fillAndStroke + // If true will stroke the line (with color this.color) as well as fill under it. + // Applies only when fill is true. + this.fillAndStroke = false; + // prop: disableStack + // true to not stack this series with other series in the plot. + // To render properly, non-stacked series must come after any stacked series + // in the plot's data series array. So, the plot's data series array would look like: + // > [stackedSeries1, stackedSeries2, ..., nonStackedSeries1, nonStackedSeries2, ...] + // disableStack will put a gap in the stacking order of series, and subsequent + // stacked series will not fill down through the non-stacked series and will + // most likely not stack properly on top of the non-stacked series. + this.disableStack = false; + // _stack is set by the Plot if the plot is a stacked chart. + // will stack lines or bars on top of one another to build a "mountain" style chart. + // May not be implemented in all renderers. + this._stack = false; + // prop: neighborThreshold + // how close or far (in pixels) the cursor must be from a point marker to detect the point. + this.neighborThreshold = 4; + // prop: fillToZero + // true will force bar and filled series to fill toward zero on the fill Axis. + this.fillToZero = false; + // prop: fillToValue + // fill a filled series to this value on the fill axis. + // Works in conjunction with fillToZero, so that must be true. + this.fillToValue = 0; + // prop: fillAxis + // Either 'x' or 'y'. Which axis to fill the line toward if fillToZero is true. + // 'y' means fill up/down to 0 on the y axis for this series. + this.fillAxis = 'y'; + // prop: useNegativeColors + // true to color negative values differently in filled and bar charts. + this.useNegativeColors = true; + this._stackData = []; + // _plotData accounts for stacking. If plots not stacked, _plotData and data are same. If + // stacked, _plotData is accumulation of stacking data. + this._plotData = []; + // _plotValues hold the individual x and y values that will be plotted for this series. + this._plotValues = {x:[], y:[]}; + // statistics about the intervals between data points. Used for auto scaling. + this._intervals = {x:{}, y:{}}; + // data from the previous series, for stacked charts. + this._prevPlotData = []; + this._prevGridData = []; + this._stackAxis = 'y'; + this._primaryAxis = '_xaxis'; + // give each series a canvas to draw on. This should allow for redrawing speedups. + this.canvas = new $.jqplot.GenericCanvas(); + this.shadowCanvas = new $.jqplot.GenericCanvas(); + this.plugins = {}; + // sum of y values in this series. + this._sumy = 0; + this._sumx = 0; + this._type = ''; + } + + Series.prototype = new $.jqplot.ElemContainer(); + Series.prototype.constructor = Series; + + Series.prototype.init = function(index, gridbw, plot) { + // weed out any null values in the data. + this.index = index; + this.gridBorderWidth = gridbw; + var d = this.data; + var temp = [], i, l; + for (i=0, l=d.length; i<l; i++) { + if (! this.breakOnNull) { + if (d[i] == null || d[i][0] == null || d[i][1] == null) { + continue; + } + else { + temp.push(d[i]); + } + } + else { + // TODO: figure out what to do with null values + // probably involve keeping nulls in data array + // and then updating renderers to break line + // when it hits null value. + // For now, just keep value. + temp.push(d[i]); + } + } + this.data = temp; + + // parse the renderer options and apply default colors if not provided + // Set color even if not shown, so series don't change colors when other + // series on plot shown/hidden. + if (!this.color) { + this.color = plot.colorGenerator.get(this.index); + } + if (!this.negativeColor) { + this.negativeColor = plot.negativeColorGenerator.get(this.index); + } + + + if (!this.fillColor) { + this.fillColor = this.color; + } + if (this.fillAlpha) { + var comp = $.jqplot.normalize2rgb(this.fillColor); + var comp = $.jqplot.getColorComponents(comp); + this.fillColor = 'rgba('+comp[0]+','+comp[1]+','+comp[2]+','+this.fillAlpha+')'; + } + if ($.isFunction(this.renderer)) { + this.renderer = new this.renderer(); + } + this.renderer.init.call(this, this.rendererOptions, plot); + this.markerRenderer = new this.markerRenderer(); + if (!this.markerOptions.color) { + this.markerOptions.color = this.color; + } + if (this.markerOptions.show == null) { + this.markerOptions.show = this.showMarker; + } + this.showMarker = this.markerOptions.show; + // the markerRenderer is called within it's own scaope, don't want to overwrite series options!! + this.markerRenderer.init(this.markerOptions); + }; + + // data - optional data point array to draw using this series renderer + // gridData - optional grid data point array to draw using this series renderer + // stackData - array of cumulative data for stacked plots. + Series.prototype.draw = function(sctx, opts, plot) { + var options = (opts == undefined) ? {} : opts; + sctx = (sctx == undefined) ? this.canvas._ctx : sctx; + + var j, data, gridData; + + // hooks get called even if series not shown + // we don't clear canvas here, it would wipe out all other series as well. + for (j=0; j<$.jqplot.preDrawSeriesHooks.length; j++) { + $.jqplot.preDrawSeriesHooks[j].call(this, sctx, options); + } + if (this.show) { + this.renderer.setGridData.call(this, plot); + if (!options.preventJqPlotSeriesDrawTrigger) { + $(sctx.canvas).trigger('jqplotSeriesDraw', [this.data, this.gridData]); + } + data = []; + if (options.data) { + data = options.data; + } + else if (!this._stack) { + data = this.data; + } + else { + data = this._plotData; + } + gridData = options.gridData || this.renderer.makeGridData.call(this, data, plot); + + if (this._type === 'line' && this.renderer.smooth && this.renderer._smoothedData.length) { + gridData = this.renderer._smoothedData; + } + + this.renderer.draw.call(this, sctx, gridData, options, plot); + } + + for (j=0; j<$.jqplot.postDrawSeriesHooks.length; j++) { + $.jqplot.postDrawSeriesHooks[j].call(this, sctx, options, plot); + } + + sctx = opts = plot = j = data = gridData = null; + }; + + Series.prototype.drawShadow = function(sctx, opts, plot) { + var options = (opts == undefined) ? {} : opts; + sctx = (sctx == undefined) ? this.shadowCanvas._ctx : sctx; + + var j, data, gridData; + + // hooks get called even if series not shown + // we don't clear canvas here, it would wipe out all other series as well. + for (j=0; j<$.jqplot.preDrawSeriesShadowHooks.length; j++) { + $.jqplot.preDrawSeriesShadowHooks[j].call(this, sctx, options); + } + if (this.shadow) { + this.renderer.setGridData.call(this, plot); + + data = []; + if (options.data) { + data = options.data; + } + else if (!this._stack) { + data = this.data; + } + else { + data = this._plotData; + } + gridData = options.gridData || this.renderer.makeGridData.call(this, data, plot); + + this.renderer.drawShadow.call(this, sctx, gridData, options, plot); + } + + for (j=0; j<$.jqplot.postDrawSeriesShadowHooks.length; j++) { + $.jqplot.postDrawSeriesShadowHooks[j].call(this, sctx, options); + } + + sctx = opts = plot = j = data = gridData = null; + + }; + + // toggles series display on plot, e.g. show/hide series + Series.prototype.toggleDisplay = function(ev, callback) { + var s, speed; + if (ev.data.series) { + s = ev.data.series; + } + else { + s = this; + } + + if (ev.data.speed) { + speed = ev.data.speed; + } + if (speed) { + // this can be tricky because series may not have a canvas element if replotting. + if (s.canvas._elem.is(':hidden') || !s.show) { + s.show = true; + + s.canvas._elem.removeClass('jqplot-series-hidden'); + if (s.shadowCanvas._elem) { + s.shadowCanvas._elem.fadeIn(speed); + } + s.canvas._elem.fadeIn(speed, callback); + s.canvas._elem.nextAll('.jqplot-point-label.jqplot-series-'+s.index).fadeIn(speed); + } + else { + s.show = false; + + s.canvas._elem.addClass('jqplot-series-hidden'); + if (s.shadowCanvas._elem) { + s.shadowCanvas._elem.fadeOut(speed); + } + s.canvas._elem.fadeOut(speed, callback); + s.canvas._elem.nextAll('.jqplot-point-label.jqplot-series-'+s.index).fadeOut(speed); + } + } + else { + // this can be tricky because series may not have a canvas element if replotting. + if (s.canvas._elem.is(':hidden') || !s.show) { + s.show = true; + + s.canvas._elem.removeClass('jqplot-series-hidden'); + if (s.shadowCanvas._elem) { + s.shadowCanvas._elem.show(); + } + s.canvas._elem.show(0, callback); + s.canvas._elem.nextAll('.jqplot-point-label.jqplot-series-'+s.index).show(); + } + else { + s.show = false; + + s.canvas._elem.addClass('jqplot-series-hidden'); + if (s.shadowCanvas._elem) { + s.shadowCanvas._elem.hide(); + } + s.canvas._elem.hide(0, callback); + s.canvas._elem.nextAll('.jqplot-point-label.jqplot-series-'+s.index).hide(); + } + } + }; + + + + /** + * Class: Grid + * + * Object representing the grid on which the plot is drawn. The grid in this + * context is the area bounded by the axes, the area which will contain the series. + * Note, the series are drawn on their own canvas. + * The Grid object cannot be instantiated directly, but is created by the Plot oject. + * Grid properties can be set or overriden by the options passed in from the user. + */ + function Grid() { + $.jqplot.ElemContainer.call(this); + // Group: Properties + + // prop: drawGridlines + // wether to draw the gridlines on the plot. + this.drawGridlines = true; + // prop: gridLineColor + // color of the grid lines. + this.gridLineColor = '#cccccc'; + // prop: gridLineWidth + // width of the grid lines. + this.gridLineWidth = 1.0; + // prop: background + // css spec for the background color. + this.background = '#fffdf6'; + // prop: borderColor + // css spec for the color of the grid border. + this.borderColor = '#999999'; + // prop: borderWidth + // width of the border in pixels. + this.borderWidth = 2.0; + // prop: drawBorder + // True to draw border around grid. + this.drawBorder = true; + // prop: shadow + // wether to show a shadow behind the grid. + this.shadow = true; + // prop: shadowAngle + // shadow angle in degrees + this.shadowAngle = 45; + // prop: shadowOffset + // Offset of each shadow stroke from the border in pixels + this.shadowOffset = 1.5; + // prop: shadowWidth + // width of the stoke for the shadow + this.shadowWidth = 3; + // prop: shadowDepth + // Number of times shadow is stroked, each stroke offset shadowOffset from the last. + this.shadowDepth = 3; + // prop: shadowColor + // an optional css color spec for the shadow in 'rgba(n, n, n, n)' form + this.shadowColor = null; + // prop: shadowAlpha + // Alpha channel transparency of shadow. 0 = transparent. + this.shadowAlpha = '0.07'; + this._left; + this._top; + this._right; + this._bottom; + this._width; + this._height; + this._axes = []; + // prop: renderer + // Instance of a renderer which will actually render the grid, + // see <$.jqplot.CanvasGridRenderer>. + this.renderer = $.jqplot.CanvasGridRenderer; + // prop: rendererOptions + // Options to pass on to the renderer, + // see <$.jqplot.CanvasGridRenderer>. + this.rendererOptions = {}; + this._offsets = {top:null, bottom:null, left:null, right:null}; + } + + Grid.prototype = new $.jqplot.ElemContainer(); + Grid.prototype.constructor = Grid; + + Grid.prototype.init = function() { + if ($.isFunction(this.renderer)) { + this.renderer = new this.renderer(); + } + this.renderer.init.call(this, this.rendererOptions); + }; + + Grid.prototype.createElement = function(offsets,plot) { + this._offsets = offsets; + return this.renderer.createElement.call(this, plot); + }; + + Grid.prototype.draw = function() { + this.renderer.draw.call(this); + }; + + $.jqplot.GenericCanvas = function() { + $.jqplot.ElemContainer.call(this); + this._ctx; + }; + + $.jqplot.GenericCanvas.prototype = new $.jqplot.ElemContainer(); + $.jqplot.GenericCanvas.prototype.constructor = $.jqplot.GenericCanvas; + + $.jqplot.GenericCanvas.prototype.createElement = function(offsets, clss, plotDimensions, plot) { + this._offsets = offsets; + var klass = 'jqplot'; + if (clss != undefined) { + klass = clss; + } + var elem; + + elem = plot.canvasManager.getCanvas(); + + // if new plotDimensions supplied, use them. + if (plotDimensions != null) { + this._plotDimensions = plotDimensions; + } + + elem.width = this._plotDimensions.width - this._offsets.left - this._offsets.right; + elem.height = this._plotDimensions.height - this._offsets.top - this._offsets.bottom; + this._elem = $(elem); + this._elem.css({ position: 'absolute', left: this._offsets.left, top: this._offsets.top }); + + this._elem.addClass(klass); + + elem = plot.canvasManager.initCanvas(elem); + + elem = null; + return this._elem; + }; + + $.jqplot.GenericCanvas.prototype.setContext = function() { + this._ctx = this._elem.get(0).getContext("2d"); + return this._ctx; + }; + + // Memory Leaks patch + $.jqplot.GenericCanvas.prototype.resetCanvas = function() { + if (this._elem) { + if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) { + window.G_vmlCanvasManager.uninitElement(this._elem.get(0)); + } + + //this._elem.remove(); + this._elem.emptyForce(); + } + + this._ctx = null; + }; + + $.jqplot.HooksManager = function () { + this.hooks =[]; + this.args = []; + }; + + $.jqplot.HooksManager.prototype.addOnce = function(fn, args) { + args = args || []; + var havehook = false; + for (var i=0, l=this.hooks.length; i<l; i++) { + if (this.hooks[i] == fn) { + havehook = true; + } + } + if (!havehook) { + this.hooks.push(fn); + this.args.push(args); + } + }; + + $.jqplot.HooksManager.prototype.add = function(fn, args) { + args = args || []; + this.hooks.push(fn); + this.args.push(args); + }; + + $.jqplot.EventListenerManager = function () { + this.hooks =[]; + }; + + $.jqplot.EventListenerManager.prototype.addOnce = function(ev, fn) { + var havehook = false, h, i; + for (var i=0, l=this.hooks.length; i<l; i++) { + h = this.hooks[i]; + if (h[0] == ev && h[1] == fn) { + havehook = true; + } + } + if (!havehook) { + this.hooks.push([ev, fn]); + } + }; + + $.jqplot.EventListenerManager.prototype.add = function(ev, fn) { + this.hooks.push([ev, fn]); + }; + + + var _axisNames = ['yMidAxis', 'xaxis', 'yaxis', 'x2axis', 'y2axis', 'y3axis', 'y4axis', 'y5axis', 'y6axis', 'y7axis', 'y8axis', 'y9axis']; + + /** + * Class: jqPlot + * Plot object returned by call to $.jqplot. Handles parsing user options, + * creating sub objects (Axes, legend, title, series) and rendering the plot. + */ + function jqPlot() { + // Group: Properties + // These properties are specified at the top of the options object + // like so: + // > { + // > axesDefaults:{min:0}, + // > series:[{color:'#6633dd'}], + // > title: 'A Plot' + // > } + // + + // prop: animate + // True to animate the series on initial plot draw (renderer dependent). + // Actual animation functionality must be supported in the renderer. + this.animate = false; + // prop: animateReplot + // True to animate series after a call to the replot() method. + // Use with caution! Replots can happen very frequently under + // certain circumstances (e.g. resizing, dragging points) and + // animation in these situations can cause problems. + this.animateReplot = false; + // prop: axes + // up to 4 axes are supported, each with it's own options, + // See <Axis> for axis specific options. + this.axes = {xaxis: new Axis('xaxis'), yaxis: new Axis('yaxis'), x2axis: new Axis('x2axis'), y2axis: new Axis('y2axis'), y3axis: new Axis('y3axis'), y4axis: new Axis('y4axis'), y5axis: new Axis('y5axis'), y6axis: new Axis('y6axis'), y7axis: new Axis('y7axis'), y8axis: new Axis('y8axis'), y9axis: new Axis('y9axis'), yMidAxis: new Axis('yMidAxis')}; + this.baseCanvas = new $.jqplot.GenericCanvas(); + // true to intercept right click events and fire a 'jqplotRightClick' event. + // this will also block the context menu. + this.captureRightClick = false; + // prop: data + // user's data. Data should *NOT* be specified in the options object, + // but be passed in as the second argument to the $.jqplot() function. + // The data property is described here soley for reference. + // The data should be in the form of an array of 2D or 1D arrays like + // > [ [[x1, y1], [x2, y2],...], [y1, y2, ...] ]. + this.data = []; + // prop: dataRenderer + // A callable which can be used to preprocess data passed into the plot. + // Will be called with 2 arguments, the plot data and a reference to the plot. + this.dataRenderer; + // prop: dataRendererOptions + // Options that will be passed to the dataRenderer. + // Can be of any type. + this.dataRendererOptions; + this.defaults = { + // prop: axesDefaults + // default options that will be applied to all axes. + // see <Axis> for axes options. + axesDefaults: {}, + axes: {xaxis:{}, yaxis:{}, x2axis:{}, y2axis:{}, y3axis:{}, y4axis:{}, y5axis:{}, y6axis:{}, y7axis:{}, y8axis:{}, y9axis:{}, yMidAxis:{}}, + // prop: seriesDefaults + // default options that will be applied to all series. + // see <Series> for series options. + seriesDefaults: {}, + series:[] + }; + // prop: defaultAxisStart + // 1-D data series are internally converted into 2-D [x,y] data point arrays + // by jqPlot. This is the default starting value for the missing x or y value. + // The added data will be a monotonically increasing series (e.g. [1, 2, 3, ...]) + // starting at this value. + this.defaultAxisStart = 1; + // this.doCustomEventBinding = true; + // prop: drawIfHidden + // True to execute the draw method even if the plot target is hidden. + // Generally, this should be false. Most plot elements will not be sized/ + // positioned correclty if renderered into a hidden container. To render into + // a hidden container, call the replot method when the container is shown. + this.drawIfHidden = false; + this.eventCanvas = new $.jqplot.GenericCanvas(); + // prop: fillBetween + // Fill between 2 line series in a plot. + // Options object: + // { + // series1: first index (0 based) of series in fill + // series2: second index (0 based) of series in fill + // color: color of fill [default fillColor of series1] + // baseSeries: fill will be drawn below this series (0 based index) + // fill: false to turn off fill [default true]. + // } + this.fillBetween = { + series1: null, + series2: null, + color: null, + baseSeries: 0, + fill: true + }; + // prop; fontFamily + // css spec for the font-family attribute. Default for the entire plot. + this.fontFamily; + // prop: fontSize + // css spec for the font-size attribute. Default for the entire plot. + this.fontSize; + // prop: grid + // See <Grid> for grid specific options. + this.grid = new Grid(); + // prop: legend + // see <$.jqplot.TableLegendRenderer> + this.legend = new Legend(); + // prop: noDataIndicator + // Options to set up a mock plot with a data loading indicator if no data is specified. + this.negativeSeriesColors = $.jqplot.config.defaultNegativeColors; + this.noDataIndicator = { + show: false, + indicator: 'Loading Data...', + axes: { + xaxis: { + min: 0, + max: 10, + tickInterval: 2, + show: true + }, + yaxis: { + min: 0, + max: 12, + tickInterval: 3, + show: true + } + } + }; + // container to hold all of the merged options. Convienence for plugins. + this.options = {}; + this.previousSeriesStack = []; + // Namespece to hold plugins. Generally non-renderer plugins add themselves to here. + this.plugins = {}; + // prop: series + // Array of series object options. + // see <Series> for series specific options. + this.series = []; + // array of series indicies. Keep track of order + // which series canvases are displayed, lowest + // to highest, back to front. + this.seriesStack = []; + // prop: seriesColors + // Ann array of CSS color specifications that will be applied, in order, + // to the series in the plot. Colors will wrap around so, if their + // are more series than colors, colors will be reused starting at the + // beginning. For pie charts, this specifies the colors of the slices. + this.seriesColors = $.jqplot.config.defaultColors; + // prop: sortData + // false to not sort the data passed in by the user. + // Many bar, stakced and other graphs as well as many plugins depend on + // having sorted data. + this.sortData = true; + // prop: stackSeries + // true or false, creates a stack or "mountain" plot. + // Not all series renderers may implement this option. + this.stackSeries = false; + // a shortcut for axis syncTicks options. Not implemented yet. + this.syncXTicks = true; + // a shortcut for axis syncTicks options. Not implemented yet. + this.syncYTicks = true; + // the jquery object for the dom target. + this.target = null; + // The id of the dom element to render the plot into + this.targetId = null; + // prop textColor + // css spec for the css color attribute. Default for the entire plot. + this.textColor; + // prop: title + // Title object. See <Title> for specific options. As a shortcut, you + // can specify the title option as just a string like: title: 'My Plot' + // and this will create a new title object with the specified text. + this.title = new Title(); + // Count how many times the draw method has been called while the plot is visible. + // Mostly used to test if plot has never been dran (=0), has been successfully drawn + // into a visible container once (=1) or draw more than once into a visible container. + // Can use this in tests to see if plot has been visibly drawn at least one time. + // After plot has been visibly drawn once, it generally doesn't need redrawn if its + // container is hidden and shown. + this._drawCount = 0; + // sum of y values for all series in plot. + // used in mekko chart. + this._sumy = 0; + this._sumx = 0; + // array to hold the cumulative stacked series data. + // used to ajust the individual series data, which won't have access to other + // series data. + this._stackData = []; + // array that holds the data to be plotted. This will be the series data + // merged with the the appropriate data from _stackData according to the stackAxis. + this._plotData = []; + this._width = null; + this._height = null; + this._plotDimensions = {height:null, width:null}; + this._gridPadding = {top:null, right:null, bottom:null, left:null}; + this._defaultGridPadding = {top:10, right:10, bottom:23, left:10}; + + this._addDomReference = $.jqplot.config.addDomReference; + + this.preInitHooks = new $.jqplot.HooksManager(); + this.postInitHooks = new $.jqplot.HooksManager(); + this.preParseOptionsHooks = new $.jqplot.HooksManager(); + this.postParseOptionsHooks = new $.jqplot.HooksManager(); + this.preDrawHooks = new $.jqplot.HooksManager(); + this.postDrawHooks = new $.jqplot.HooksManager(); + this.preDrawSeriesHooks = new $.jqplot.HooksManager(); + this.postDrawSeriesHooks = new $.jqplot.HooksManager(); + this.preDrawLegendHooks = new $.jqplot.HooksManager(); + this.addLegendRowHooks = new $.jqplot.HooksManager(); + this.preSeriesInitHooks = new $.jqplot.HooksManager(); + this.postSeriesInitHooks = new $.jqplot.HooksManager(); + this.preParseSeriesOptionsHooks = new $.jqplot.HooksManager(); + this.postParseSeriesOptionsHooks = new $.jqplot.HooksManager(); + this.eventListenerHooks = new $.jqplot.EventListenerManager(); + this.preDrawSeriesShadowHooks = new $.jqplot.HooksManager(); + this.postDrawSeriesShadowHooks = new $.jqplot.HooksManager(); + + this.colorGenerator = new $.jqplot.ColorGenerator(); + this.negativeColorGenerator = new $.jqplot.ColorGenerator(); + + this.canvasManager = new $.jqplot.CanvasManager(); + + this.themeEngine = new $.jqplot.ThemeEngine(); + + var seriesColorsIndex = 0; + + // Group: methods + // + // method: init + // sets the plot target, checks data and applies user + // options to plot. + this.init = function(target, data, options) { + options = options || {}; + for (var i=0; i<$.jqplot.preInitHooks.length; i++) { + $.jqplot.preInitHooks[i].call(this, target, data, options); + } + + for (var i=0; i<this.preInitHooks.hooks.length; i++) { + this.preInitHooks.hooks[i].call(this, target, data, options); + } + + this.targetId = '#'+target; + this.target = $('#'+target); + + ////// + // Add a reference to plot + ////// + if (this._addDomReference) { + this.target.data('jqplot', this); + } + // remove any error class that may be stuck on target. + this.target.removeClass('jqplot-error'); + if (!this.target.get(0)) { + throw "No plot target specified"; + } + + // make sure the target is positioned by some means and set css + if (this.target.css('position') == 'static') { + this.target.css('position', 'relative'); + } + if (!this.target.hasClass('jqplot-target')) { + this.target.addClass('jqplot-target'); + } + + // if no height or width specified, use a default. + if (!this.target.height()) { + var h; + if (options && options.height) { + h = parseInt(options.height, 10); + } + else if (this.target.attr('data-height')) { + h = parseInt(this.target.attr('data-height'), 10); + } + else { + h = parseInt($.jqplot.config.defaultHeight, 10); + } + this._height = h; + this.target.css('height', h+'px'); + } + else { + this._height = h = this.target.height(); + } + if (!this.target.width()) { + var w; + if (options && options.width) { + w = parseInt(options.width, 10); + } + else if (this.target.attr('data-width')) { + w = parseInt(this.target.attr('data-width'), 10); + } + else { + w = parseInt($.jqplot.config.defaultWidth, 10); + } + this._width = w; + this.target.css('width', w+'px'); + } + else { + this._width = w = this.target.width(); + } + + for (var i=0, l=_axisNames.length; i<l; i++) { + this.axes[_axisNames[i]] = new Axis(_axisNames[i]); + } + + this._plotDimensions.height = this._height; + this._plotDimensions.width = this._width; + this.grid._plotDimensions = this._plotDimensions; + this.title._plotDimensions = this._plotDimensions; + this.baseCanvas._plotDimensions = this._plotDimensions; + this.eventCanvas._plotDimensions = this._plotDimensions; + this.legend._plotDimensions = this._plotDimensions; + if (this._height <=0 || this._width <=0 || !this._height || !this._width) { + throw "Canvas dimension not set"; + } + + if (options.dataRenderer && $.isFunction(options.dataRenderer)) { + if (options.dataRendererOptions) { + this.dataRendererOptions = options.dataRendererOptions; + } + this.dataRenderer = options.dataRenderer; + data = this.dataRenderer(data, this, this.dataRendererOptions); + } + + if (options.noDataIndicator && $.isPlainObject(options.noDataIndicator)) { + $.extend(true, this.noDataIndicator, options.noDataIndicator); + } + + if (data == null || $.isArray(data) == false || data.length == 0 || $.isArray(data[0]) == false || data[0].length == 0) { + + if (this.noDataIndicator.show == false) { + throw "No Data"; + } + + else { + // have to be descructive here in order for plot to not try and render series. + // This means that $.jqplot() will have to be called again when there is data. + //delete options.series; + + for (var ax in this.noDataIndicator.axes) { + for (var prop in this.noDataIndicator.axes[ax]) { + this.axes[ax][prop] = this.noDataIndicator.axes[ax][prop]; + } + } + + this.postDrawHooks.add(function() { + var eh = this.eventCanvas.getHeight(); + var ew = this.eventCanvas.getWidth(); + var temp = $('<div class="jqplot-noData-container" style="position:absolute;"></div>'); + this.target.append(temp); + temp.height(eh); + temp.width(ew); + temp.css('top', this.eventCanvas._offsets.top); + temp.css('left', this.eventCanvas._offsets.left); + + var temp2 = $('<div class="jqplot-noData-contents" style="text-align:center; position:relative; margin-left:auto; margin-right:auto;"></div>'); + temp.append(temp2); + temp2.html(this.noDataIndicator.indicator); + var th = temp2.height(); + var tw = temp2.width(); + temp2.height(th); + temp2.width(tw); + temp2.css('top', (eh - th)/2 + 'px'); + }); + + } + } + + // make a copy of the data + this.data = $.extend(true, [], data); + + this.parseOptions(options); + + if (this.textColor) { + this.target.css('color', this.textColor); + } + if (this.fontFamily) { + this.target.css('font-family', this.fontFamily); + } + if (this.fontSize) { + this.target.css('font-size', this.fontSize); + } + + this.title.init(); + this.legend.init(); + this._sumy = 0; + this._sumx = 0; + this.computePlotData(); + for (var i=0; i<this.series.length; i++) { + // set default stacking order for series canvases + this.seriesStack.push(i); + this.previousSeriesStack.push(i); + this.series[i].shadowCanvas._plotDimensions = this._plotDimensions; + this.series[i].canvas._plotDimensions = this._plotDimensions; + for (var j=0; j<$.jqplot.preSeriesInitHooks.length; j++) { + $.jqplot.preSeriesInitHooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this); + } + for (var j=0; j<this.preSeriesInitHooks.hooks.length; j++) { + this.preSeriesInitHooks.hooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this); + } + // this.populatePlotData(this.series[i], i); + this.series[i]._plotDimensions = this._plotDimensions; + this.series[i].init(i, this.grid.borderWidth, this); + for (var j=0; j<$.jqplot.postSeriesInitHooks.length; j++) { + $.jqplot.postSeriesInitHooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this); + } + for (var j=0; j<this.postSeriesInitHooks.hooks.length; j++) { + this.postSeriesInitHooks.hooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this); + } + this._sumy += this.series[i]._sumy; + this._sumx += this.series[i]._sumx; + } + + var name, + axis; + for (var i=0, l=_axisNames.length; i<l; i++) { + name = _axisNames[i]; + axis = this.axes[name]; + axis._plotDimensions = this._plotDimensions; + axis.init(); + if (this.axes[name].borderColor == null) { + if (name.charAt(0) !== 'x' && axis.useSeriesColor === true && axis.show) { + axis.borderColor = axis._series[0].color; + } + else { + axis.borderColor = this.grid.borderColor; + } + } + } + + if (this.sortData) { + sortData(this.series); + } + this.grid.init(); + this.grid._axes = this.axes; + + this.legend._series = this.series; + + for (var i=0; i<$.jqplot.postInitHooks.length; i++) { + $.jqplot.postInitHooks[i].call(this, target, this.data, options); + } + + for (var i=0; i<this.postInitHooks.hooks.length; i++) { + this.postInitHooks.hooks[i].call(this, target, this.data, options); + } + }; + + // method: resetAxesScale + // Reset the specified axes min, max, numberTicks and tickInterval properties to null + // or reset these properties on all axes if no list of axes is provided. + // + // Parameters: + // axes - Boolean to reset or not reset all axes or an array or object of axis names to reset. + this.resetAxesScale = function(axes, options) { + var opts = options || {}; + var ax = axes || this.axes; + if (ax === true) { + ax = this.axes; + } + if ($.isArray(ax)) { + for (var i = 0; i < ax.length; i++) { + this.axes[ax[i]].resetScale(opts[ax[i]]); + } + } + else if (typeof(ax) === 'object') { + for (var name in ax) { + this.axes[name].resetScale(opts[name]); + } + } + }; + // method: reInitialize + // reinitialize plot for replotting. + // not called directly. + this.reInitialize = function (data, opts) { + // Plot should be visible and have a height and width. + // If plot doesn't have height and width for some + // reason, set it by other means. Plot must not have + // a display:none attribute, however. + + var options = $.extend(true, {}, this.options, opts); + + var target = this.targetId.substr(1); + var tdata = (data == null) ? this.data : data; + + for (var i=0; i<$.jqplot.preInitHooks.length; i++) { + $.jqplot.preInitHooks[i].call(this, target, tdata, options); + } + + for (var i=0; i<this.preInitHooks.hooks.length; i++) { + this.preInitHooks.hooks[i].call(this, target, tdata, options); + } + + this._height = this.target.height(); + this._width = this.target.width(); + + if (this._height <=0 || this._width <=0 || !this._height || !this._width) { + throw "Target dimension not set"; + } + + this._plotDimensions.height = this._height; + this._plotDimensions.width = this._width; + this.grid._plotDimensions = this._plotDimensions; + this.title._plotDimensions = this._plotDimensions; + this.baseCanvas._plotDimensions = this._plotDimensions; + this.eventCanvas._plotDimensions = this._plotDimensions; + this.legend._plotDimensions = this._plotDimensions; + + var name, + t, + j, + axis; + + for (var i=0, l=_axisNames.length; i<l; i++) { + name = _axisNames[i]; + axis = this.axes[name]; + + // Memory Leaks patch : clear ticks elements + t = axis._ticks; + for (var j = 0, tlen = t.length; j < tlen; j++) { + var el = t[j]._elem; + if (el) { + // if canvas renderer + if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) { + window.G_vmlCanvasManager.uninitElement(el.get(0)); + } + el.emptyForce(); + el = null; + t._elem = null; + } + } + t = null; + + delete axis.ticks; + delete axis._ticks; + this.axes[name] = new Axis(name); + this.axes[name]._plotWidth = this._width; + this.axes[name]._plotHeight = this._height; + } + + if (data) { + if (options.dataRenderer && $.isFunction(options.dataRenderer)) { + if (options.dataRendererOptions) { + this.dataRendererOptions = options.dataRendererOptions; + } + this.dataRenderer = options.dataRenderer; + data = this.dataRenderer(data, this, this.dataRendererOptions); + } + + // make a copy of the data + this.data = $.extend(true, [], data); + } + + if (opts) { + this.parseOptions(options); + } + + this.title._plotWidth = this._width; + + if (this.textColor) { + this.target.css('color', this.textColor); + } + if (this.fontFamily) { + this.target.css('font-family', this.fontFamily); + } + if (this.fontSize) { + this.target.css('font-size', this.fontSize); + } + + this.title.init(); + this.legend.init(); + this._sumy = 0; + this._sumx = 0; + + this.seriesStack = []; + this.previousSeriesStack = []; + + this.computePlotData(); + for (var i=0, l=this.series.length; i<l; i++) { + // set default stacking order for series canvases + this.seriesStack.push(i); + this.previousSeriesStack.push(i); + this.series[i].shadowCanvas._plotDimensions = this._plotDimensions; + this.series[i].canvas._plotDimensions = this._plotDimensions; + for (var j=0; j<$.jqplot.preSeriesInitHooks.length; j++) { + $.jqplot.preSeriesInitHooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this); + } + for (var j=0; j<this.preSeriesInitHooks.hooks.length; j++) { + this.preSeriesInitHooks.hooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this); + } + // this.populatePlotData(this.series[i], i); + this.series[i]._plotDimensions = this._plotDimensions; + this.series[i].init(i, this.grid.borderWidth, this); + for (var j=0; j<$.jqplot.postSeriesInitHooks.length; j++) { + $.jqplot.postSeriesInitHooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this); + } + for (var j=0; j<this.postSeriesInitHooks.hooks.length; j++) { + this.postSeriesInitHooks.hooks[j].call(this.series[i], target, this.data, this.options.seriesDefaults, this.options.series[i], this); + } + this._sumy += this.series[i]._sumy; + this._sumx += this.series[i]._sumx; + } + + for (var i=0, l=_axisNames.length; i<l; i++) { + name = _axisNames[i]; + axis = this.axes[name]; + + axis._plotDimensions = this._plotDimensions; + axis.init(); + if (axis.borderColor == null) { + if (name.charAt(0) !== 'x' && axis.useSeriesColor === true && axis.show) { + axis.borderColor = axis._series[0].color; + } + else { + axis.borderColor = this.grid.borderColor; + } + } + } + + if (this.sortData) { + sortData(this.series); + } + this.grid.init(); + this.grid._axes = this.axes; + + this.legend._series = this.series; + + for (var i=0, l=$.jqplot.postInitHooks.length; i<l; i++) { + $.jqplot.postInitHooks[i].call(this, target, this.data, options); + } + + for (var i=0, l=this.postInitHooks.hooks.length; i<l; i++) { + this.postInitHooks.hooks[i].call(this, target, this.data, options); + } + }; + + + + // method: quickInit + // + // Quick reinitialization plot for replotting. + // Does not parse options ore recreate axes and series. + // not called directly. + this.quickInit = function () { + // Plot should be visible and have a height and width. + // If plot doesn't have height and width for some + // reason, set it by other means. Plot must not have + // a display:none attribute, however. + + this._height = this.target.height(); + this._width = this.target.width(); + + if (this._height <=0 || this._width <=0 || !this._height || !this._width) { + throw "Target dimension not set"; + } + + this._plotDimensions.height = this._height; + this._plotDimensions.width = this._width; + this.grid._plotDimensions = this._plotDimensions; + this.title._plotDimensions = this._plotDimensions; + this.baseCanvas._plotDimensions = this._plotDimensions; + this.eventCanvas._plotDimensions = this._plotDimensions; + this.legend._plotDimensions = this._plotDimensions; + + for (var n in this.axes) { + this.axes[n]._plotWidth = this._width; + this.axes[n]._plotHeight = this._height; + } + + this.title._plotWidth = this._width; + + if (this.textColor) { + this.target.css('color', this.textColor); + } + if (this.fontFamily) { + this.target.css('font-family', this.fontFamily); + } + if (this.fontSize) { + this.target.css('font-size', this.fontSize); + } + + this._sumy = 0; + this._sumx = 0; + this.computePlotData(); + for (var i=0; i<this.series.length; i++) { + // this.populatePlotData(this.series[i], i); + if (this.series[i]._type === 'line' && this.series[i].renderer.bands.show) { + this.series[i].renderer.initBands.call(this.series[i], this.series[i].renderer.options, this); + } + this.series[i]._plotDimensions = this._plotDimensions; + this.series[i].canvas._plotDimensions = this._plotDimensions; + //this.series[i].init(i, this.grid.borderWidth); + this._sumy += this.series[i]._sumy; + this._sumx += this.series[i]._sumx; + } + + var name; + + for (var j=0; j<12; j++) { + name = _axisNames[j]; + // Memory Leaks patch : clear ticks elements + var t = this.axes[name]._ticks; + for (var i = 0; i < t.length; i++) { + var el = t[i]._elem; + if (el) { + // if canvas renderer + if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) { + window.G_vmlCanvasManager.uninitElement(el.get(0)); + } + el.emptyForce(); + el = null; + t._elem = null; + } + } + t = null; + + this.axes[name]._plotDimensions = this._plotDimensions; + this.axes[name]._ticks = []; + // this.axes[name].renderer.init.call(this.axes[name], {}); + } + + if (this.sortData) { + sortData(this.series); + } + + this.grid._axes = this.axes; + + this.legend._series = this.series; + }; + + // sort the series data in increasing order. + function sortData(series) { + var d, sd, pd, ppd, ret; + for (var i=0; i<series.length; i++) { + var check; + var bat = [series[i].data, series[i]._stackData, series[i]._plotData, series[i]._prevPlotData]; + for (var n=0; n<4; n++) { + check = true; + d = bat[n]; + if (series[i]._stackAxis == 'x') { + for (var j = 0; j < d.length; j++) { + if (typeof(d[j][1]) != "number") { + check = false; + break; + } + } + if (check) { + d.sort(function(a,b) { return a[1] - b[1]; }); + } + } + else { + for (var j = 0; j < d.length; j++) { + if (typeof(d[j][0]) != "number") { + check = false; + break; + } + } + if (check) { + d.sort(function(a,b) { return a[0] - b[0]; }); + } + } + } + + } + } + + this.computePlotData = function() { + this._plotData = []; + this._stackData = []; + var series, + index, + l; + + + for (index=0, l=this.series.length; index<l; index++) { + series = this.series[index]; + this._plotData.push([]); + this._stackData.push([]); + var cd = series.data; + this._plotData[index] = $.extend(true, [], cd); + this._stackData[index] = $.extend(true, [], cd); + series._plotData = this._plotData[index]; + series._stackData = this._stackData[index]; + var plotValues = {x:[], y:[]}; + + if (this.stackSeries && !series.disableStack) { + series._stack = true; + /////////////////////////// + // have to check for nulls + /////////////////////////// + var sidx = (series._stackAxis === 'x') ? 0 : 1; + + for (var k=0, cdl=cd.length; k<cdl; k++) { + var temp = cd[k][sidx]; + if (temp == null) { + temp = 0; + } + this._plotData[index][k][sidx] = temp; + this._stackData[index][k][sidx] = temp; + + if (index > 0) { + for (var j=index; j--;) { + var prevval = this._plotData[j][k][sidx]; + // only need to sum up the stack axis column of data + // and only sum if it is of same sign. + // if previous series isn't same sign, keep looking + // at earlier series untill we find one of same sign. + if (temp * prevval >= 0) { + this._plotData[index][k][sidx] += prevval; + this._stackData[index][k][sidx] += prevval; + break; + } + } + } + } + + } + else { + for (var i=0; i<series.data.length; i++) { + plotValues.x.push(series.data[i][0]); + plotValues.y.push(series.data[i][1]); + } + this._stackData.push(series.data); + this.series[index]._stackData = series.data; + this._plotData.push(series.data); + series._plotData = series.data; + series._plotValues = plotValues; + } + if (index>0) { + series._prevPlotData = this.series[index-1]._plotData; + } + series._sumy = 0; + series._sumx = 0; + for (i=series.data.length-1; i>-1; i--) { + series._sumy += series.data[i][1]; + series._sumx += series.data[i][0]; + } + } + + }; + + // populate the _stackData and _plotData arrays for the plot and the series. + this.populatePlotData = function(series, index) { + // if a stacked chart, compute the stacked data + this._plotData = []; + this._stackData = []; + series._stackData = []; + series._plotData = []; + var plotValues = {x:[], y:[]}; + if (this.stackSeries && !series.disableStack) { + series._stack = true; + var sidx = (series._stackAxis === 'x') ? 0 : 1; + // var idx = sidx ? 0 : 1; + // push the current data into stackData + //this._stackData.push(this.series[i].data); + var temp = $.extend(true, [], series.data); + // create the data that will be plotted for this series + var plotdata = $.extend(true, [], series.data); + var tempx, tempy, dval, stackval, comparator; + // for first series, nothing to add to stackData. + for (var j=0; j<index; j++) { + var cd = this.series[j].data; + for (var k=0; k<cd.length; k++) { + dval = cd[k]; + tempx = (dval[0] != null) ? dval[0] : 0; + tempy = (dval[1] != null) ? dval[1] : 0; + temp[k][0] += tempx; + temp[k][1] += tempy; + stackval = (sidx) ? tempy : tempx; + // only need to sum up the stack axis column of data + // and only sum if it is of same sign. + if (series.data[k][sidx] * stackval >= 0) { + plotdata[k][sidx] += stackval; + } + } + } + for (var i=0; i<plotdata.length; i++) { + plotValues.x.push(plotdata[i][0]); + plotValues.y.push(plotdata[i][1]); + } + this._plotData.push(plotdata); + this._stackData.push(temp); + series._stackData = temp; + series._plotData = plotdata; + series._plotValues = plotValues; + } + else { + for (var i=0; i<series.data.length; i++) { + plotValues.x.push(series.data[i][0]); + plotValues.y.push(series.data[i][1]); + } + this._stackData.push(series.data); + this.series[index]._stackData = series.data; + this._plotData.push(series.data); + series._plotData = series.data; + series._plotValues = plotValues; + } + if (index>0) { + series._prevPlotData = this.series[index-1]._plotData; + } + series._sumy = 0; + series._sumx = 0; + for (i=series.data.length-1; i>-1; i--) { + series._sumy += series.data[i][1]; + series._sumx += series.data[i][0]; + } + }; + + // function to safely return colors from the color array and wrap around at the end. + this.getNextSeriesColor = (function(t) { + var idx = 0; + var sc = t.seriesColors; + + return function () { + if (idx < sc.length) { + return sc[idx++]; + } + else { + idx = 0; + return sc[idx++]; + } + }; + })(this); + + this.parseOptions = function(options){ + for (var i=0; i<this.preParseOptionsHooks.hooks.length; i++) { + this.preParseOptionsHooks.hooks[i].call(this, options); + } + for (var i=0; i<$.jqplot.preParseOptionsHooks.length; i++) { + $.jqplot.preParseOptionsHooks[i].call(this, options); + } + this.options = $.extend(true, {}, this.defaults, options); + var opts = this.options; + this.animate = opts.animate; + this.animateReplot = opts.animateReplot; + this.stackSeries = opts.stackSeries; + if ($.isPlainObject(opts.fillBetween)) { + + var temp = ['series1', 'series2', 'color', 'baseSeries', 'fill'], + tempi; + + for (var i=0, l=temp.length; i<l; i++) { + tempi = temp[i]; + if (opts.fillBetween[tempi] != null) { + this.fillBetween[tempi] = opts.fillBetween[tempi]; + } + } + } + + if (opts.seriesColors) { + this.seriesColors = opts.seriesColors; + } + if (opts.negativeSeriesColors) { + this.negativeSeriesColors = opts.negativeSeriesColors; + } + if (opts.captureRightClick) { + this.captureRightClick = opts.captureRightClick; + } + this.defaultAxisStart = (options && options.defaultAxisStart != null) ? options.defaultAxisStart : this.defaultAxisStart; + this.colorGenerator.setColors(this.seriesColors); + this.negativeColorGenerator.setColors(this.negativeSeriesColors); + // var cg = new this.colorGenerator(this.seriesColors); + // var ncg = new this.colorGenerator(this.negativeSeriesColors); + // this._gridPadding = this.options.gridPadding; + $.extend(true, this._gridPadding, opts.gridPadding); + this.sortData = (opts.sortData != null) ? opts.sortData : this.sortData; + for (var i=0; i<12; i++) { + var n = _axisNames[i]; + var axis = this.axes[n]; + axis._options = $.extend(true, {}, opts.axesDefaults, opts.axes[n]); + $.extend(true, axis, opts.axesDefaults, opts.axes[n]); + axis._plotWidth = this._width; + axis._plotHeight = this._height; + } + // if (this.data.length == 0) { + // this.data = []; + // for (var i=0; i<this.options.series.length; i++) { + // this.data.push(this.options.series.data); + // } + // } + + var normalizeData = function(data, dir, start) { + // return data as an array of point arrays, + // in form [[x1,y1...], [x2,y2...], ...] + var temp = []; + var i, l; + dir = dir || 'vertical'; + if (!$.isArray(data[0])) { + // we have a series of scalars. One line with just y values. + // turn the scalar list of data into a data array of form: + // [[1, data[0]], [2, data[1]], ...] + for (i=0, l=data.length; i<l; i++) { + if (dir == 'vertical') { + temp.push([start + i, data[i]]); + } + else { + temp.push([data[i], start+i]); + } + } + } + else { + // we have a properly formatted data series, copy it. + $.extend(true, temp, data); + } + return temp; + }; + + var colorIndex = 0; + this.series = []; + for (var i=0; i<this.data.length; i++) { + var sopts = $.extend(true, {index: i}, {seriesColors:this.seriesColors, negativeSeriesColors:this.negativeSeriesColors}, this.options.seriesDefaults, this.options.series[i], {rendererOptions:{animation:{show: this.animate}}}); + // pass in options in case something needs set prior to initialization. + var temp = new Series(sopts); + for (var j=0; j<$.jqplot.preParseSeriesOptionsHooks.length; j++) { + $.jqplot.preParseSeriesOptionsHooks[j].call(temp, this.options.seriesDefaults, this.options.series[i]); + } + for (var j=0; j<this.preParseSeriesOptionsHooks.hooks.length; j++) { + this.preParseSeriesOptionsHooks.hooks[j].call(temp, this.options.seriesDefaults, this.options.series[i]); + } + // Now go back and apply the options to the series. Really should just do this during initializaiton, but don't want to + // mess up preParseSeriesOptionsHooks at this point. + $.extend(true, temp, sopts); + var dir = 'vertical'; + if (temp.renderer === $.jqplot.BarRenderer && temp.rendererOptions && temp.rendererOptions.barDirection == 'horizontal') { + dir = 'horizontal'; + temp._stackAxis = 'x'; + temp._primaryAxis = '_yaxis'; + } + temp.data = normalizeData(this.data[i], dir, this.defaultAxisStart); + switch (temp.xaxis) { + case 'xaxis': + temp._xaxis = this.axes.xaxis; + break; + case 'x2axis': + temp._xaxis = this.axes.x2axis; + break; + default: + break; + } + temp._yaxis = this.axes[temp.yaxis]; + temp._xaxis._series.push(temp); + temp._yaxis._series.push(temp); + if (temp.show) { + temp._xaxis.show = true; + temp._yaxis.show = true; + } + else { + if (temp._xaxis.scaleToHiddenSeries) { + temp._xaxis.show = true; + } + if (temp._yaxis.scaleToHiddenSeries) { + temp._yaxis.show = true; + } + } + + // // parse the renderer options and apply default colors if not provided + // if (!temp.color && temp.show != false) { + // temp.color = cg.next(); + // colorIndex = cg.getIndex() - 1;; + // } + // if (!temp.negativeColor && temp.show != false) { + // temp.negativeColor = ncg.get(colorIndex); + // ncg.setIndex(colorIndex); + // } + if (!temp.label) { + temp.label = 'Series '+ (i+1).toString(); + } + // temp.rendererOptions.show = temp.show; + // $.extend(true, temp.renderer, {color:this.seriesColors[i]}, this.rendererOptions); + this.series.push(temp); + for (var j=0; j<$.jqplot.postParseSeriesOptionsHooks.length; j++) { + $.jqplot.postParseSeriesOptionsHooks[j].call(this.series[i], this.options.seriesDefaults, this.options.series[i]); + } + for (var j=0; j<this.postParseSeriesOptionsHooks.hooks.length; j++) { + this.postParseSeriesOptionsHooks.hooks[j].call(this.series[i], this.options.seriesDefaults, this.options.series[i]); + } + } + + // copy the grid and title options into this object. + $.extend(true, this.grid, this.options.grid); + // if axis border properties aren't set, set default. + for (var i=0, l=_axisNames.length; i<l; i++) { + var n = _axisNames[i]; + var axis = this.axes[n]; + if (axis.borderWidth == null) { + axis.borderWidth =this.grid.borderWidth; + } + } + + if (typeof this.options.title == 'string') { + this.title.text = this.options.title; + } + else if (typeof this.options.title == 'object') { + $.extend(true, this.title, this.options.title); + } + this.title._plotWidth = this._width; + this.legend.setOptions(this.options.legend); + + for (var i=0; i<$.jqplot.postParseOptionsHooks.length; i++) { + $.jqplot.postParseOptionsHooks[i].call(this, options); + } + for (var i=0; i<this.postParseOptionsHooks.hooks.length; i++) { + this.postParseOptionsHooks.hooks[i].call(this, options); + } + }; + + // method: destroy + // Releases all resources occupied by the plot + this.destroy = function() { + this.canvasManager.freeAllCanvases(); + if (this.eventCanvas && this.eventCanvas._elem) { + this.eventCanvas._elem.unbind(); + } + // Couple of posts on Stack Overflow indicate that empty() doesn't + // always cear up the dom and release memory. Sometimes setting + // innerHTML property to null is needed. Particularly on IE, may + // have to directly set it to null, bypassing $. + this.target.empty(); + + this.target[0].innerHTML = ''; + }; + + // method: replot + // Does a reinitialization of the plot followed by + // a redraw. Method could be used to interactively + // change plot characteristics and then replot. + // + // Parameters: + // options - Options used for replotting. + // + // Properties: + // clear - false to not clear (empty) the plot container before replotting (default: true). + // resetAxes - true to reset all axes min, max, numberTicks and tickInterval setting so axes will rescale themselves. + // optionally pass in list of axes to reset (e.g. ['xaxis', 'y2axis']) (default: false). + this.replot = function(options) { + var opts = options || {}; + var data = opts.data || null; + var clear = (opts.clear === false) ? false : true; + var resetAxes = opts.resetAxes || false; + delete opts.data; + delete opts.clear; + delete opts.resetAxes; + + this.target.trigger('jqplotPreReplot'); + + if (clear) { + this.destroy(); + } + // if have data or other options, full reinit. + // otherwise, quickinit. + if (data || !$.isEmptyObject(opts)) { + this.reInitialize(data, opts); + } + else { + this.quickInit(); + } + + if (resetAxes) { + this.resetAxesScale(resetAxes, opts.axes); + } + this.draw(); + this.target.trigger('jqplotPostReplot'); + }; + + // method: redraw + // Empties the plot target div and redraws the plot. + // This enables plot data and properties to be changed + // and then to comletely clear the plot and redraw. + // redraw *will not* reinitialize any plot elements. + // That is, axes will not be autoscaled and defaults + // will not be reapplied to any plot elements. redraw + // is used primarily with zooming. + // + // Parameters: + // clear - false to not clear (empty) the plot container before redrawing (default: true). + this.redraw = function(clear) { + clear = (clear != null) ? clear : true; + this.target.trigger('jqplotPreRedraw'); + if (clear) { + this.canvasManager.freeAllCanvases(); + this.eventCanvas._elem.unbind(); + // Dont think I bind any events to the target, this shouldn't be necessary. + // It will remove user's events. + // this.target.unbind(); + this.target.empty(); + } + for (var ax in this.axes) { + this.axes[ax]._ticks = []; + } + this.computePlotData(); + // for (var i=0; i<this.series.length; i++) { + // this.populatePlotData(this.series[i], i); + // } + this._sumy = 0; + this._sumx = 0; + for (var i=0, tsl = this.series.length; i<tsl; i++) { + this._sumy += this.series[i]._sumy; + this._sumx += this.series[i]._sumx; + } + this.draw(); + this.target.trigger('jqplotPostRedraw'); + }; + + // method: draw + // Draws all elements of the plot into the container. + // Does not clear the container before drawing. + this.draw = function(){ + if (this.drawIfHidden || this.target.is(':visible')) { + this.target.trigger('jqplotPreDraw'); + var i, + j, + l, + tempseries; + for (i=0, l=$.jqplot.preDrawHooks.length; i<l; i++) { + $.jqplot.preDrawHooks[i].call(this); + } + for (i=0, l=this.preDrawHooks.length; i<l; i++) { + this.preDrawHooks.hooks[i].apply(this, this.preDrawSeriesHooks.args[i]); + } + // create an underlying canvas to be used for special features. + this.target.append(this.baseCanvas.createElement({left:0, right:0, top:0, bottom:0}, 'jqplot-base-canvas', null, this)); + this.baseCanvas.setContext(); + this.target.append(this.title.draw()); + this.title.pack({top:0, left:0}); + + // make room for the legend between the grid and the edge. + // pass a dummy offsets object and a reference to the plot. + var legendElem = this.legend.draw({}, this); + + var gridPadding = {top:0, left:0, bottom:0, right:0}; + + if (this.legend.placement == "outsideGrid") { + // temporarily append the legend to get dimensions + this.target.append(legendElem); + switch (this.legend.location) { + case 'n': + gridPadding.top += this.legend.getHeight(); + break; + case 's': + gridPadding.bottom += this.legend.getHeight(); + break; + case 'ne': + case 'e': + case 'se': + gridPadding.right += this.legend.getWidth(); + break; + case 'nw': + case 'w': + case 'sw': + gridPadding.left += this.legend.getWidth(); + break; + default: // same as 'ne' + gridPadding.right += this.legend.getWidth(); + break; + } + legendElem = legendElem.detach(); + } + + var ax = this.axes; + var name; + // draw the yMidAxis first, so xaxis of pyramid chart can adjust itself if needed. + for (i=0; i<12; i++) { + name = _axisNames[i]; + this.target.append(ax[name].draw(this.baseCanvas._ctx, this)); + ax[name].set(); + } + if (ax.yaxis.show) { + gridPadding.left += ax.yaxis.getWidth(); + } + var ra = ['y2axis', 'y3axis', 'y4axis', 'y5axis', 'y6axis', 'y7axis', 'y8axis', 'y9axis']; + var rapad = [0, 0, 0, 0, 0, 0, 0, 0]; + var gpr = 0; + var n; + for (n=0; n<8; n++) { + if (ax[ra[n]].show) { + gpr += ax[ra[n]].getWidth(); + rapad[n] = gpr; + } + } + gridPadding.right += gpr; + if (ax.x2axis.show) { + gridPadding.top += ax.x2axis.getHeight(); + } + if (this.title.show) { + gridPadding.top += this.title.getHeight(); + } + if (ax.xaxis.show) { + gridPadding.bottom += ax.xaxis.getHeight(); + } + + // end of gridPadding adjustments. + + // if user passed in gridDimensions option, check against calculated gridPadding + if (this.options.gridDimensions && $.isPlainObject(this.options.gridDimensions)) { + var gdw = parseInt(this.options.gridDimensions.width, 10) || 0; + var gdh = parseInt(this.options.gridDimensions.height, 10) || 0; + var widthAdj = (this._width - gridPadding.left - gridPadding.right - gdw)/2; + var heightAdj = (this._height - gridPadding.top - gridPadding.bottom - gdh)/2; + + if (heightAdj >= 0 && widthAdj >= 0) { + gridPadding.top += heightAdj; + gridPadding.bottom += heightAdj; + gridPadding.left += widthAdj; + gridPadding.right += widthAdj; + } + } + var arr = ['top', 'bottom', 'left', 'right']; + for (var n in arr) { + if (this._gridPadding[arr[n]] == null && gridPadding[arr[n]] > 0) { + this._gridPadding[arr[n]] = gridPadding[arr[n]]; + } + else if (this._gridPadding[arr[n]] == null) { + this._gridPadding[arr[n]] = this._defaultGridPadding[arr[n]]; + } + } + + var legendPadding = this._gridPadding; + + if (this.legend.placement === 'outsideGrid') { + legendPadding = {top:this.title.getHeight(), left: 0, right: 0, bottom: 0}; + if (this.legend.location === 's') { + legendPadding.left = this._gridPadding.left; + legendPadding.right = this._gridPadding.right; + } + } + + ax.xaxis.pack({position:'absolute', bottom:this._gridPadding.bottom - ax.xaxis.getHeight(), left:0, width:this._width}, {min:this._gridPadding.left, max:this._width - this._gridPadding.right}); + ax.yaxis.pack({position:'absolute', top:0, left:this._gridPadding.left - ax.yaxis.getWidth(), height:this._height}, {min:this._height - this._gridPadding.bottom, max: this._gridPadding.top}); + ax.x2axis.pack({position:'absolute', top:this._gridPadding.top - ax.x2axis.getHeight(), left:0, width:this._width}, {min:this._gridPadding.left, max:this._width - this._gridPadding.right}); + for (i=8; i>0; i--) { + ax[ra[i-1]].pack({position:'absolute', top:0, right:this._gridPadding.right - rapad[i-1]}, {min:this._height - this._gridPadding.bottom, max: this._gridPadding.top}); + } + var ltemp = (this._width - this._gridPadding.left - this._gridPadding.right)/2.0 + this._gridPadding.left - ax.yMidAxis.getWidth()/2.0; + ax.yMidAxis.pack({position:'absolute', top:0, left:ltemp, zIndex:9, textAlign: 'center'}, {min:this._height - this._gridPadding.bottom, max: this._gridPadding.top}); + + this.target.append(this.grid.createElement(this._gridPadding, this)); + this.grid.draw(); + + var series = this.series; + var seriesLength = series.length; + // put the shadow canvases behind the series canvases so shadows don't overlap on stacked bars. + for (i=0, l=seriesLength; i<l; i++) { + // draw series in order of stacking. This affects only + // order in which canvases are added to dom. + j = this.seriesStack[i]; + this.target.append(series[j].shadowCanvas.createElement(this._gridPadding, 'jqplot-series-shadowCanvas', null, this)); + series[j].shadowCanvas.setContext(); + series[j].shadowCanvas._elem.data('seriesIndex', j); + } + + for (i=0, l=seriesLength; i<l; i++) { + // draw series in order of stacking. This affects only + // order in which canvases are added to dom. + j = this.seriesStack[i]; + this.target.append(series[j].canvas.createElement(this._gridPadding, 'jqplot-series-canvas', null, this)); + series[j].canvas.setContext(); + series[j].canvas._elem.data('seriesIndex', j); + } + // Need to use filled canvas to capture events in IE. + // Also, canvas seems to block selection of other elements in document on FF. + this.target.append(this.eventCanvas.createElement(this._gridPadding, 'jqplot-event-canvas', null, this)); + this.eventCanvas.setContext(); + this.eventCanvas._ctx.fillStyle = 'rgba(0,0,0,0)'; + this.eventCanvas._ctx.fillRect(0,0,this.eventCanvas._ctx.canvas.width, this.eventCanvas._ctx.canvas.height); + + // bind custom event handlers to regular events. + this.bindCustomEvents(); + + // draw legend before series if the series needs to know the legend dimensions. + if (this.legend.preDraw) { + this.eventCanvas._elem.before(legendElem); + this.legend.pack(legendPadding); + if (this.legend._elem) { + this.drawSeries({legendInfo:{location:this.legend.location, placement:this.legend.placement, width:this.legend.getWidth(), height:this.legend.getHeight(), xoffset:this.legend.xoffset, yoffset:this.legend.yoffset}}); + } + else { + this.drawSeries(); + } + } + else { // draw series before legend + this.drawSeries(); + if (seriesLength) { + $(series[seriesLength-1].canvas._elem).after(legendElem); + } + this.legend.pack(legendPadding); + } + + // register event listeners on the overlay canvas + for (var i=0, l=$.jqplot.eventListenerHooks.length; i<l; i++) { + // in the handler, this will refer to the eventCanvas dom element. + // make sure there are references back into plot objects. + this.eventCanvas._elem.bind($.jqplot.eventListenerHooks[i][0], {plot:this}, $.jqplot.eventListenerHooks[i][1]); + } + + // register event listeners on the overlay canvas + for (var i=0, l=this.eventListenerHooks.hooks.length; i<l; i++) { + // in the handler, this will refer to the eventCanvas dom element. + // make sure there are references back into plot objects. + this.eventCanvas._elem.bind(this.eventListenerHooks.hooks[i][0], {plot:this}, this.eventListenerHooks.hooks[i][1]); + } + + var fb = this.fillBetween; + if (fb.fill && fb.series1 !== fb.series2 && fb.series1 < seriesLength && fb.series2 < seriesLength && series[fb.series1]._type === 'line' && series[fb.series2]._type === 'line') { + this.doFillBetweenLines(); + } + + for (var i=0, l=$.jqplot.postDrawHooks.length; i<l; i++) { + $.jqplot.postDrawHooks[i].call(this); + } + + for (var i=0, l=this.postDrawHooks.hooks.length; i<l; i++) { + this.postDrawHooks.hooks[i].apply(this, this.postDrawHooks.args[i]); + } + + if (this.target.is(':visible')) { + this._drawCount += 1; + } + + var temps, + tempr, + sel, + _els; + // ughh. ideally would hide all series then show them. + for (i=0, l=seriesLength; i<l; i++) { + temps = series[i]; + tempr = temps.renderer; + sel = '.jqplot-point-label.jqplot-series-'+i; + if (tempr.animation && tempr.animation._supported && tempr.animation.show && (this._drawCount < 2 || this.animateReplot)) { + _els = this.target.find(sel); + _els.stop(true, true).hide(); + temps.canvas._elem.stop(true, true).hide(); + temps.shadowCanvas._elem.stop(true, true).hide(); + temps.canvas._elem.jqplotEffect('blind', {mode: 'show', direction: tempr.animation.direction}, tempr.animation.speed); + temps.shadowCanvas._elem.jqplotEffect('blind', {mode: 'show', direction: tempr.animation.direction}, tempr.animation.speed); + _els.fadeIn(tempr.animation.speed*0.8); + } + } + _els = null; + + this.target.trigger('jqplotPostDraw', [this]); + } + }; + + jqPlot.prototype.doFillBetweenLines = function () { + var fb = this.fillBetween; + var sid1 = fb.series1; + var sid2 = fb.series2; + // first series should always be lowest index + var id1 = (sid1 < sid2) ? sid1 : sid2; + var id2 = (sid2 > sid1) ? sid2 : sid1; + + var series1 = this.series[id1]; + var series2 = this.series[id2]; + + if (series2.renderer.smooth) { + var tempgd = series2.renderer._smoothedData.slice(0).reverse(); + } + else { + var tempgd = series2.gridData.slice(0).reverse(); + } + + if (series1.renderer.smooth) { + var gd = series1.renderer._smoothedData.concat(tempgd); + } + else { + var gd = series1.gridData.concat(tempgd); + } + + var color = (fb.color !== null) ? fb.color : this.series[sid1].fillColor; + var baseSeries = (fb.baseSeries !== null) ? fb.baseSeries : id1; + + // now apply a fill to the shape on the lower series shadow canvas, + // so it is behind both series. + var sr = this.series[baseSeries].renderer.shapeRenderer; + var opts = {fillStyle: color, fill: true, closePath: true}; + sr.draw(series1.shadowCanvas._ctx, gd, opts); + }; + + this.bindCustomEvents = function() { + this.eventCanvas._elem.bind('click', {plot:this}, this.onClick); + this.eventCanvas._elem.bind('dblclick', {plot:this}, this.onDblClick); + this.eventCanvas._elem.bind('mousedown', {plot:this}, this.onMouseDown); + this.eventCanvas._elem.bind('mousemove', {plot:this}, this.onMouseMove); + this.eventCanvas._elem.bind('mouseenter', {plot:this}, this.onMouseEnter); + this.eventCanvas._elem.bind('mouseleave', {plot:this}, this.onMouseLeave); + if (this.captureRightClick) { + this.eventCanvas._elem.bind('mouseup', {plot:this}, this.onRightClick); + this.eventCanvas._elem.get(0).oncontextmenu = function() { + return false; + }; + } + else { + this.eventCanvas._elem.bind('mouseup', {plot:this}, this.onMouseUp); + } + }; + + function getEventPosition(ev) { + var plot = ev.data.plot; + var go = plot.eventCanvas._elem.offset(); + var gridPos = {x:ev.pageX - go.left, y:ev.pageY - go.top}; + var dataPos = {xaxis:null, yaxis:null, x2axis:null, y2axis:null, y3axis:null, y4axis:null, y5axis:null, y6axis:null, y7axis:null, y8axis:null, y9axis:null, yMidAxis:null}; + var an = ['xaxis', 'yaxis', 'x2axis', 'y2axis', 'y3axis', 'y4axis', 'y5axis', 'y6axis', 'y7axis', 'y8axis', 'y9axis', 'yMidAxis']; + var ax = plot.axes; + var n, axis; + for (n=11; n>0; n--) { + axis = an[n-1]; + if (ax[axis].show) { + dataPos[axis] = ax[axis].series_p2u(gridPos[axis.charAt(0)]); + } + } + + return {offsets:go, gridPos:gridPos, dataPos:dataPos}; + } + + + // function to check if event location is over a area area + function checkIntersection(gridpos, plot) { + var series = plot.series; + var i, j, k, s, r, x, y, theta, sm, sa, minang, maxang; + var d0, d, p, pp, points, bw, hp; + var threshold, t; + for (k=plot.seriesStack.length-1; k>=0; k--) { + i = plot.seriesStack[k]; + s = series[i]; + hp = s._highlightThreshold; + switch (s.renderer.constructor) { + case $.jqplot.BarRenderer: + x = gridpos.x; + y = gridpos.y; + for (j=0; j<s._barPoints.length; j++) { + points = s._barPoints[j]; + p = s.gridData[j]; + if (x>points[0][0] && x<points[2][0] && y>points[2][1] && y<points[0][1]) { + return {seriesIndex:s.index, pointIndex:j, gridData:p, data:s.data[j], points:s._barPoints[j]}; + } + } + break; + case $.jqplot.PyramidRenderer: + x = gridpos.x; + y = gridpos.y; + for (j=0; j<s._barPoints.length; j++) { + points = s._barPoints[j]; + p = s.gridData[j]; + if (x > points[0][0] + hp[0][0] && x < points[2][0] + hp[2][0] && y > points[2][1] && y < points[0][1]) { + return {seriesIndex:s.index, pointIndex:j, gridData:p, data:s.data[j], points:s._barPoints[j]}; + } + } + break; + + case $.jqplot.DonutRenderer: + sa = s.startAngle/180*Math.PI; + x = gridpos.x - s._center[0]; + y = gridpos.y - s._center[1]; + r = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); + if (x > 0 && -y >= 0) { + theta = 2*Math.PI - Math.atan(-y/x); + } + else if (x > 0 && -y < 0) { + theta = -Math.atan(-y/x); + } + else if (x < 0) { + theta = Math.PI - Math.atan(-y/x); + } + else if (x == 0 && -y > 0) { + theta = 3*Math.PI/2; + } + else if (x == 0 && -y < 0) { + theta = Math.PI/2; + } + else if (x == 0 && y == 0) { + theta = 0; + } + if (sa) { + theta -= sa; + if (theta < 0) { + theta += 2*Math.PI; + } + else if (theta > 2*Math.PI) { + theta -= 2*Math.PI; + } + } + + sm = s.sliceMargin/180*Math.PI; + if (r < s._radius && r > s._innerRadius) { + for (j=0; j<s.gridData.length; j++) { + minang = (j>0) ? s.gridData[j-1][1]+sm : sm; + maxang = s.gridData[j][1]; + if (theta > minang && theta < maxang) { + return {seriesIndex:s.index, pointIndex:j, gridData:s.gridData[j], data:s.data[j]}; + } + } + } + break; + + case $.jqplot.PieRenderer: + sa = s.startAngle/180*Math.PI; + x = gridpos.x - s._center[0]; + y = gridpos.y - s._center[1]; + r = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); + if (x > 0 && -y >= 0) { + theta = 2*Math.PI - Math.atan(-y/x); + } + else if (x > 0 && -y < 0) { + theta = -Math.atan(-y/x); + } + else if (x < 0) { + theta = Math.PI - Math.atan(-y/x); + } + else if (x == 0 && -y > 0) { + theta = 3*Math.PI/2; + } + else if (x == 0 && -y < 0) { + theta = Math.PI/2; + } + else if (x == 0 && y == 0) { + theta = 0; + } + if (sa) { + theta -= sa; + if (theta < 0) { + theta += 2*Math.PI; + } + else if (theta > 2*Math.PI) { + theta -= 2*Math.PI; + } + } + + sm = s.sliceMargin/180*Math.PI; + if (r < s._radius) { + for (j=0; j<s.gridData.length; j++) { + minang = (j>0) ? s.gridData[j-1][1]+sm : sm; + maxang = s.gridData[j][1]; + if (theta > minang && theta < maxang) { + return {seriesIndex:s.index, pointIndex:j, gridData:s.gridData[j], data:s.data[j]}; + } + } + } + break; + + case $.jqplot.BubbleRenderer: + x = gridpos.x; + y = gridpos.y; + var ret = null; + + if (s.show) { + for (var j=0; j<s.gridData.length; j++) { + p = s.gridData[j]; + d = Math.sqrt( (x-p[0]) * (x-p[0]) + (y-p[1]) * (y-p[1]) ); + if (d <= p[2] && (d <= d0 || d0 == null)) { + d0 = d; + ret = {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}; + } + } + if (ret != null) { + return ret; + } + } + break; + + case $.jqplot.FunnelRenderer: + x = gridpos.x; + y = gridpos.y; + var v = s._vertices, + vfirst = v[0], + vlast = v[v.length-1], + lex, + rex, + cv; + + // equations of right and left sides, returns x, y values given height of section (y value and 2 points) + + function findedge (l, p1 , p2) { + var m = (p1[1] - p2[1])/(p1[0] - p2[0]); + var b = p1[1] - m*p1[0]; + var y = l + p1[1]; + + return [(y - b)/m, y]; + } + + // check each section + lex = findedge(y, vfirst[0], vlast[3]); + rex = findedge(y, vfirst[1], vlast[2]); + for (j=0; j<v.length; j++) { + cv = v[j]; + if (y >= cv[0][1] && y <= cv[3][1] && x >= lex[0] && x <= rex[0]) { + return {seriesIndex:s.index, pointIndex:j, gridData:null, data:s.data[j]}; + } + } + break; + + case $.jqplot.LineRenderer: + x = gridpos.x; + y = gridpos.y; + r = s.renderer; + if (s.show) { + if ((s.fill || (s.renderer.bands.show && s.renderer.bands.fill)) && (!plot.plugins.highlighter || !plot.plugins.highlighter.show)) { + // first check if it is in bounding box + var inside = false; + if (x>s._boundingBox[0][0] && x<s._boundingBox[1][0] && y>s._boundingBox[1][1] && y<s._boundingBox[0][1]) { + // now check the crossing number + + var numPoints = s._areaPoints.length; + var ii; + var j = numPoints-1; + + for(var ii=0; ii < numPoints; ii++) { + var vertex1 = [s._areaPoints[ii][0], s._areaPoints[ii][1]]; + var vertex2 = [s._areaPoints[j][0], s._areaPoints[j][1]]; + + if (vertex1[1] < y && vertex2[1] >= y || vertex2[1] < y && vertex1[1] >= y) { + if (vertex1[0] + (y - vertex1[1]) / (vertex2[1] - vertex1[1]) * (vertex2[0] - vertex1[0]) < x) { + inside = !inside; + } + } + + j = ii; + } + } + if (inside) { + return {seriesIndex:i, pointIndex:null, gridData:s.gridData, data:s.data, points:s._areaPoints}; + } + break; + + } + + else { + t = s.markerRenderer.size/2+s.neighborThreshold; + threshold = (t > 0) ? t : 0; + for (var j=0; j<s.gridData.length; j++) { + p = s.gridData[j]; + // neighbor looks different to OHLC chart. + if (r.constructor == $.jqplot.OHLCRenderer) { + if (r.candleStick) { + var yp = s._yaxis.series_u2p; + if (x >= p[0]-r._bodyWidth/2 && x <= p[0]+r._bodyWidth/2 && y >= yp(s.data[j][2]) && y <= yp(s.data[j][3])) { + return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}; + } + } + // if an open hi low close chart + else if (!r.hlc){ + var yp = s._yaxis.series_u2p; + if (x >= p[0]-r._tickLength && x <= p[0]+r._tickLength && y >= yp(s.data[j][2]) && y <= yp(s.data[j][3])) { + return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}; + } + } + // a hi low close chart + else { + var yp = s._yaxis.series_u2p; + if (x >= p[0]-r._tickLength && x <= p[0]+r._tickLength && y >= yp(s.data[j][1]) && y <= yp(s.data[j][2])) { + return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}; + } + } + + } + else if (p[0] != null && p[1] != null){ + d = Math.sqrt( (x-p[0]) * (x-p[0]) + (y-p[1]) * (y-p[1]) ); + if (d <= threshold && (d <= d0 || d0 == null)) { + d0 = d; + return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}; + } + } + } + } + } + break; + + default: + x = gridpos.x; + y = gridpos.y; + r = s.renderer; + if (s.show) { + t = s.markerRenderer.size/2+s.neighborThreshold; + threshold = (t > 0) ? t : 0; + for (var j=0; j<s.gridData.length; j++) { + p = s.gridData[j]; + // neighbor looks different to OHLC chart. + if (r.constructor == $.jqplot.OHLCRenderer) { + if (r.candleStick) { + var yp = s._yaxis.series_u2p; + if (x >= p[0]-r._bodyWidth/2 && x <= p[0]+r._bodyWidth/2 && y >= yp(s.data[j][2]) && y <= yp(s.data[j][3])) { + return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}; + } + } + // if an open hi low close chart + else if (!r.hlc){ + var yp = s._yaxis.series_u2p; + if (x >= p[0]-r._tickLength && x <= p[0]+r._tickLength && y >= yp(s.data[j][2]) && y <= yp(s.data[j][3])) { + return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}; + } + } + // a hi low close chart + else { + var yp = s._yaxis.series_u2p; + if (x >= p[0]-r._tickLength && x <= p[0]+r._tickLength && y >= yp(s.data[j][1]) && y <= yp(s.data[j][2])) { + return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}; + } + } + + } + else { + d = Math.sqrt( (x-p[0]) * (x-p[0]) + (y-p[1]) * (y-p[1]) ); + if (d <= threshold && (d <= d0 || d0 == null)) { + d0 = d; + return {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}; + } + } + } + } + break; + } + } + + return null; + } + + + + this.onClick = function(ev) { + // Event passed in is normalized and will have data attribute. + // Event passed out is unnormalized. + var positions = getEventPosition(ev); + var p = ev.data.plot; + var neighbor = checkIntersection(positions.gridPos, p); + var evt = $.Event('jqplotClick'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + $(this).trigger(evt, [positions.gridPos, positions.dataPos, neighbor, p]); + }; + + this.onDblClick = function(ev) { + // Event passed in is normalized and will have data attribute. + // Event passed out is unnormalized. + var positions = getEventPosition(ev); + var p = ev.data.plot; + var neighbor = checkIntersection(positions.gridPos, p); + var evt = $.Event('jqplotDblClick'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + $(this).trigger(evt, [positions.gridPos, positions.dataPos, neighbor, p]); + }; + + this.onMouseDown = function(ev) { + var positions = getEventPosition(ev); + var p = ev.data.plot; + var neighbor = checkIntersection(positions.gridPos, p); + var evt = $.Event('jqplotMouseDown'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + $(this).trigger(evt, [positions.gridPos, positions.dataPos, neighbor, p]); + }; + + this.onMouseUp = function(ev) { + var positions = getEventPosition(ev); + var evt = $.Event('jqplotMouseUp'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + $(this).trigger(evt, [positions.gridPos, positions.dataPos, null, ev.data.plot]); + }; + + this.onRightClick = function(ev) { + var positions = getEventPosition(ev); + var p = ev.data.plot; + var neighbor = checkIntersection(positions.gridPos, p); + if (p.captureRightClick) { + if (ev.which == 3) { + var evt = $.Event('jqplotRightClick'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + $(this).trigger(evt, [positions.gridPos, positions.dataPos, neighbor, p]); + } + else { + var evt = $.Event('jqplotMouseUp'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + $(this).trigger(evt, [positions.gridPos, positions.dataPos, neighbor, p]); + } + } + }; + + this.onMouseMove = function(ev) { + var positions = getEventPosition(ev); + var p = ev.data.plot; + var neighbor = checkIntersection(positions.gridPos, p); + var evt = $.Event('jqplotMouseMove'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + $(this).trigger(evt, [positions.gridPos, positions.dataPos, neighbor, p]); + }; + + this.onMouseEnter = function(ev) { + var positions = getEventPosition(ev); + var p = ev.data.plot; + var evt = $.Event('jqplotMouseEnter'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + evt.relatedTarget = ev.relatedTarget; + $(this).trigger(evt, [positions.gridPos, positions.dataPos, null, p]); + }; + + this.onMouseLeave = function(ev) { + var positions = getEventPosition(ev); + var p = ev.data.plot; + var evt = $.Event('jqplotMouseLeave'); + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + evt.relatedTarget = ev.relatedTarget; + $(this).trigger(evt, [positions.gridPos, positions.dataPos, null, p]); + }; + + // method: drawSeries + // Redraws all or just one series on the plot. No axis scaling + // is performed and no other elements on the plot are redrawn. + // options is an options object to pass on to the series renderers. + // It can be an empty object {}. idx is the series index + // to redraw if only one series is to be redrawn. + this.drawSeries = function(options, idx){ + var i, series, ctx; + // if only one argument passed in and it is a number, use it ad idx. + idx = (typeof(options) === "number" && idx == null) ? options : idx; + options = (typeof(options) === "object") ? options : {}; + // draw specified series + if (idx != undefined) { + series = this.series[idx]; + ctx = series.shadowCanvas._ctx; + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + series.drawShadow(ctx, options, this); + ctx = series.canvas._ctx; + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + series.draw(ctx, options, this); + if (series.renderer.constructor == $.jqplot.BezierCurveRenderer) { + if (idx < this.series.length - 1) { + this.drawSeries(idx+1); + } + } + } + + else { + // if call series drawShadow method first, in case all series shadows + // should be drawn before any series. This will ensure, like for + // stacked bar plots, that shadows don't overlap series. + for (i=0; i<this.series.length; i++) { + // first clear the canvas + series = this.series[i]; + ctx = series.shadowCanvas._ctx; + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + series.drawShadow(ctx, options, this); + ctx = series.canvas._ctx; + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + series.draw(ctx, options, this); + } + } + options = idx = i = series = ctx = null; + }; + + // method: moveSeriesToFront + // This method requires jQuery 1.4+ + // Moves the specified series canvas in front of all other series canvases. + // This effectively "draws" the specified series on top of all other series, + // although it is performed through DOM manipulation, no redrawing is performed. + // + // Parameters: + // idx - 0 based index of the series to move. This will be the index of the series + // as it was first passed into the jqplot function. + this.moveSeriesToFront = function (idx) { + idx = parseInt(idx, 10); + var stackIndex = $.inArray(idx, this.seriesStack); + // if already in front, return + if (stackIndex == -1) { + return; + } + if (stackIndex == this.seriesStack.length -1) { + this.previousSeriesStack = this.seriesStack.slice(0); + return; + } + var opidx = this.seriesStack[this.seriesStack.length -1]; + var serelem = this.series[idx].canvas._elem.detach(); + var shadelem = this.series[idx].shadowCanvas._elem.detach(); + this.series[opidx].shadowCanvas._elem.after(shadelem); + this.series[opidx].canvas._elem.after(serelem); + this.previousSeriesStack = this.seriesStack.slice(0); + this.seriesStack.splice(stackIndex, 1); + this.seriesStack.push(idx); + }; + + // method: moveSeriesToBack + // This method requires jQuery 1.4+ + // Moves the specified series canvas behind all other series canvases. + // + // Parameters: + // idx - 0 based index of the series to move. This will be the index of the series + // as it was first passed into the jqplot function. + this.moveSeriesToBack = function (idx) { + idx = parseInt(idx, 10); + var stackIndex = $.inArray(idx, this.seriesStack); + // if already in back, return + if (stackIndex == 0 || stackIndex == -1) { + return; + } + var opidx = this.seriesStack[0]; + var serelem = this.series[idx].canvas._elem.detach(); + var shadelem = this.series[idx].shadowCanvas._elem.detach(); + this.series[opidx].shadowCanvas._elem.before(shadelem); + this.series[opidx].canvas._elem.before(serelem); + this.previousSeriesStack = this.seriesStack.slice(0); + this.seriesStack.splice(stackIndex, 1); + this.seriesStack.unshift(idx); + }; + + // method: restorePreviousSeriesOrder + // This method requires jQuery 1.4+ + // Restore the series canvas order to its previous state. + // Useful to put a series back where it belongs after moving + // it to the front. + this.restorePreviousSeriesOrder = function () { + var i, j, serelem, shadelem, temp, move, keep; + // if no change, return. + if (this.seriesStack == this.previousSeriesStack) { + return; + } + for (i=1; i<this.previousSeriesStack.length; i++) { + move = this.previousSeriesStack[i]; + keep = this.previousSeriesStack[i-1]; + serelem = this.series[move].canvas._elem.detach(); + shadelem = this.series[move].shadowCanvas._elem.detach(); + this.series[keep].shadowCanvas._elem.after(shadelem); + this.series[keep].canvas._elem.after(serelem); + } + temp = this.seriesStack.slice(0); + this.seriesStack = this.previousSeriesStack.slice(0); + this.previousSeriesStack = temp; + }; + + // method: restoreOriginalSeriesOrder + // This method requires jQuery 1.4+ + // Restore the series canvas order to its original order + // when the plot was created. + this.restoreOriginalSeriesOrder = function () { + var i, j, arr=[], serelem, shadelem; + for (i=0; i<this.series.length; i++) { + arr.push(i); + } + if (this.seriesStack == arr) { + return; + } + this.previousSeriesStack = this.seriesStack.slice(0); + this.seriesStack = arr; + for (i=1; i<this.seriesStack.length; i++) { + serelem = this.series[i].canvas._elem.detach(); + shadelem = this.series[i].shadowCanvas._elem.detach(); + this.series[i-1].shadowCanvas._elem.after(shadelem); + this.series[i-1].canvas._elem.after(serelem); + } + }; + + this.activateTheme = function (name) { + this.themeEngine.activate(this, name); + }; + } + + + // conpute a highlight color or array of highlight colors from given colors. + $.jqplot.computeHighlightColors = function(colors) { + var ret; + if ($.isArray(colors)) { + ret = []; + for (var i=0; i<colors.length; i++){ + var rgba = $.jqplot.getColorComponents(colors[i]); + var newrgb = [rgba[0], rgba[1], rgba[2]]; + var sum = newrgb[0] + newrgb[1] + newrgb[2]; + for (var j=0; j<3; j++) { + // when darkening, lowest color component can be is 60. + newrgb[j] = (sum > 660) ? newrgb[j] * 0.85 : 0.73 * newrgb[j] + 90; + newrgb[j] = parseInt(newrgb[j], 10); + (newrgb[j] > 255) ? 255 : newrgb[j]; + } + // newrgb[3] = (rgba[3] > 0.4) ? rgba[3] * 0.4 : rgba[3] * 1.5; + // newrgb[3] = (rgba[3] > 0.5) ? 0.8 * rgba[3] - .1 : rgba[3] + 0.2; + newrgb[3] = 0.3 + 0.35 * rgba[3]; + ret.push('rgba('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+','+newrgb[3]+')'); + } + } + else { + var rgba = $.jqplot.getColorComponents(colors); + var newrgb = [rgba[0], rgba[1], rgba[2]]; + var sum = newrgb[0] + newrgb[1] + newrgb[2]; + for (var j=0; j<3; j++) { + // when darkening, lowest color component can be is 60. + // newrgb[j] = (sum > 570) ? newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]); + // newrgb[j] = parseInt(newrgb[j], 10); + newrgb[j] = (sum > 660) ? newrgb[j] * 0.85 : 0.73 * newrgb[j] + 90; + newrgb[j] = parseInt(newrgb[j], 10); + (newrgb[j] > 255) ? 255 : newrgb[j]; + } + // newrgb[3] = (rgba[3] > 0.4) ? rgba[3] * 0.4 : rgba[3] * 1.5; + // newrgb[3] = (rgba[3] > 0.5) ? 0.8 * rgba[3] - .1 : rgba[3] + 0.2; + newrgb[3] = 0.3 + 0.35 * rgba[3]; + ret = 'rgba('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+','+newrgb[3]+')'; + } + return ret; + }; + + $.jqplot.ColorGenerator = function(colors) { + colors = colors || $.jqplot.config.defaultColors; + var idx = 0; + + this.next = function () { + if (idx < colors.length) { + return colors[idx++]; + } + else { + idx = 0; + return colors[idx++]; + } + }; + + this.previous = function () { + if (idx > 0) { + return colors[idx--]; + } + else { + idx = colors.length-1; + return colors[idx]; + } + }; + + // get a color by index without advancing pointer. + this.get = function(i) { + var idx = i - colors.length * Math.floor(i/colors.length); + return colors[idx]; + }; + + this.setColors = function(c) { + colors = c; + }; + + this.reset = function() { + idx = 0; + }; + + this.getIndex = function() { + return idx; + }; + + this.setIndex = function(index) { + idx = index; + }; + }; + + // convert a hex color string to rgb string. + // h - 3 or 6 character hex string, with or without leading # + // a - optional alpha + $.jqplot.hex2rgb = function(h, a) { + h = h.replace('#', ''); + if (h.length == 3) { + h = h.charAt(0)+h.charAt(0)+h.charAt(1)+h.charAt(1)+h.charAt(2)+h.charAt(2); + } + var rgb; + rgb = 'rgba('+parseInt(h.slice(0,2), 16)+', '+parseInt(h.slice(2,4), 16)+', '+parseInt(h.slice(4,6), 16); + if (a) { + rgb += ', '+a; + } + rgb += ')'; + return rgb; + }; + + // convert an rgb color spec to a hex spec. ignore any alpha specification. + $.jqplot.rgb2hex = function(s) { + var pat = /rgba?\( *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *(?:, *[0-9.]*)?\)/; + var m = s.match(pat); + var h = '#'; + for (var i=1; i<4; i++) { + var temp; + if (m[i].search(/%/) != -1) { + temp = parseInt(255*m[i]/100, 10).toString(16); + if (temp.length == 1) { + temp = '0'+temp; + } + } + else { + temp = parseInt(m[i], 10).toString(16); + if (temp.length == 1) { + temp = '0'+temp; + } + } + h += temp; + } + return h; + }; + + // given a css color spec, return an rgb css color spec + $.jqplot.normalize2rgb = function(s, a) { + if (s.search(/^ *rgba?\(/) != -1) { + return s; + } + else if (s.search(/^ *#?[0-9a-fA-F]?[0-9a-fA-F]/) != -1) { + return $.jqplot.hex2rgb(s, a); + } + else { + throw 'invalid color spec'; + } + }; + + // extract the r, g, b, a color components out of a css color spec. + $.jqplot.getColorComponents = function(s) { + // check to see if a color keyword. + s = $.jqplot.colorKeywordMap[s] || s; + var rgb = $.jqplot.normalize2rgb(s); + var pat = /rgba?\( *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *, *([0-9]{1,3}\.?[0-9]*%?) *,? *([0-9.]* *)?\)/; + var m = rgb.match(pat); + var ret = []; + for (var i=1; i<4; i++) { + if (m[i].search(/%/) != -1) { + ret[i-1] = parseInt(255*m[i]/100, 10); + } + else { + ret[i-1] = parseInt(m[i], 10); + } + } + ret[3] = parseFloat(m[4]) ? parseFloat(m[4]) : 1.0; + return ret; + }; + + $.jqplot.colorKeywordMap = { + aliceblue: 'rgb(240, 248, 255)', + antiquewhite: 'rgb(250, 235, 215)', + aqua: 'rgb( 0, 255, 255)', + aquamarine: 'rgb(127, 255, 212)', + azure: 'rgb(240, 255, 255)', + beige: 'rgb(245, 245, 220)', + bisque: 'rgb(255, 228, 196)', + black: 'rgb( 0, 0, 0)', + blanchedalmond: 'rgb(255, 235, 205)', + blue: 'rgb( 0, 0, 255)', + blueviolet: 'rgb(138, 43, 226)', + brown: 'rgb(165, 42, 42)', + burlywood: 'rgb(222, 184, 135)', + cadetblue: 'rgb( 95, 158, 160)', + chartreuse: 'rgb(127, 255, 0)', + chocolate: 'rgb(210, 105, 30)', + coral: 'rgb(255, 127, 80)', + cornflowerblue: 'rgb(100, 149, 237)', + cornsilk: 'rgb(255, 248, 220)', + crimson: 'rgb(220, 20, 60)', + cyan: 'rgb( 0, 255, 255)', + darkblue: 'rgb( 0, 0, 139)', + darkcyan: 'rgb( 0, 139, 139)', + darkgoldenrod: 'rgb(184, 134, 11)', + darkgray: 'rgb(169, 169, 169)', + darkgreen: 'rgb( 0, 100, 0)', + darkgrey: 'rgb(169, 169, 169)', + darkkhaki: 'rgb(189, 183, 107)', + darkmagenta: 'rgb(139, 0, 139)', + darkolivegreen: 'rgb( 85, 107, 47)', + darkorange: 'rgb(255, 140, 0)', + darkorchid: 'rgb(153, 50, 204)', + darkred: 'rgb(139, 0, 0)', + darksalmon: 'rgb(233, 150, 122)', + darkseagreen: 'rgb(143, 188, 143)', + darkslateblue: 'rgb( 72, 61, 139)', + darkslategray: 'rgb( 47, 79, 79)', + darkslategrey: 'rgb( 47, 79, 79)', + darkturquoise: 'rgb( 0, 206, 209)', + darkviolet: 'rgb(148, 0, 211)', + deeppink: 'rgb(255, 20, 147)', + deepskyblue: 'rgb( 0, 191, 255)', + dimgray: 'rgb(105, 105, 105)', + dimgrey: 'rgb(105, 105, 105)', + dodgerblue: 'rgb( 30, 144, 255)', + firebrick: 'rgb(178, 34, 34)', + floralwhite: 'rgb(255, 250, 240)', + forestgreen: 'rgb( 34, 139, 34)', + fuchsia: 'rgb(255, 0, 255)', + gainsboro: 'rgb(220, 220, 220)', + ghostwhite: 'rgb(248, 248, 255)', + gold: 'rgb(255, 215, 0)', + goldenrod: 'rgb(218, 165, 32)', + gray: 'rgb(128, 128, 128)', + grey: 'rgb(128, 128, 128)', + green: 'rgb( 0, 128, 0)', + greenyellow: 'rgb(173, 255, 47)', + honeydew: 'rgb(240, 255, 240)', + hotpink: 'rgb(255, 105, 180)', + indianred: 'rgb(205, 92, 92)', + indigo: 'rgb( 75, 0, 130)', + ivory: 'rgb(255, 255, 240)', + khaki: 'rgb(240, 230, 140)', + lavender: 'rgb(230, 230, 250)', + lavenderblush: 'rgb(255, 240, 245)', + lawngreen: 'rgb(124, 252, 0)', + lemonchiffon: 'rgb(255, 250, 205)', + lightblue: 'rgb(173, 216, 230)', + lightcoral: 'rgb(240, 128, 128)', + lightcyan: 'rgb(224, 255, 255)', + lightgoldenrodyellow: 'rgb(250, 250, 210)', + lightgray: 'rgb(211, 211, 211)', + lightgreen: 'rgb(144, 238, 144)', + lightgrey: 'rgb(211, 211, 211)', + lightpink: 'rgb(255, 182, 193)', + lightsalmon: 'rgb(255, 160, 122)', + lightseagreen: 'rgb( 32, 178, 170)', + lightskyblue: 'rgb(135, 206, 250)', + lightslategray: 'rgb(119, 136, 153)', + lightslategrey: 'rgb(119, 136, 153)', + lightsteelblue: 'rgb(176, 196, 222)', + lightyellow: 'rgb(255, 255, 224)', + lime: 'rgb( 0, 255, 0)', + limegreen: 'rgb( 50, 205, 50)', + linen: 'rgb(250, 240, 230)', + magenta: 'rgb(255, 0, 255)', + maroon: 'rgb(128, 0, 0)', + mediumaquamarine: 'rgb(102, 205, 170)', + mediumblue: 'rgb( 0, 0, 205)', + mediumorchid: 'rgb(186, 85, 211)', + mediumpurple: 'rgb(147, 112, 219)', + mediumseagreen: 'rgb( 60, 179, 113)', + mediumslateblue: 'rgb(123, 104, 238)', + mediumspringgreen: 'rgb( 0, 250, 154)', + mediumturquoise: 'rgb( 72, 209, 204)', + mediumvioletred: 'rgb(199, 21, 133)', + midnightblue: 'rgb( 25, 25, 112)', + mintcream: 'rgb(245, 255, 250)', + mistyrose: 'rgb(255, 228, 225)', + moccasin: 'rgb(255, 228, 181)', + navajowhite: 'rgb(255, 222, 173)', + navy: 'rgb( 0, 0, 128)', + oldlace: 'rgb(253, 245, 230)', + olive: 'rgb(128, 128, 0)', + olivedrab: 'rgb(107, 142, 35)', + orange: 'rgb(255, 165, 0)', + orangered: 'rgb(255, 69, 0)', + orchid: 'rgb(218, 112, 214)', + palegoldenrod: 'rgb(238, 232, 170)', + palegreen: 'rgb(152, 251, 152)', + paleturquoise: 'rgb(175, 238, 238)', + palevioletred: 'rgb(219, 112, 147)', + papayawhip: 'rgb(255, 239, 213)', + peachpuff: 'rgb(255, 218, 185)', + peru: 'rgb(205, 133, 63)', + pink: 'rgb(255, 192, 203)', + plum: 'rgb(221, 160, 221)', + powderblue: 'rgb(176, 224, 230)', + purple: 'rgb(128, 0, 128)', + red: 'rgb(255, 0, 0)', + rosybrown: 'rgb(188, 143, 143)', + royalblue: 'rgb( 65, 105, 225)', + saddlebrown: 'rgb(139, 69, 19)', + salmon: 'rgb(250, 128, 114)', + sandybrown: 'rgb(244, 164, 96)', + seagreen: 'rgb( 46, 139, 87)', + seashell: 'rgb(255, 245, 238)', + sienna: 'rgb(160, 82, 45)', + silver: 'rgb(192, 192, 192)', + skyblue: 'rgb(135, 206, 235)', + slateblue: 'rgb(106, 90, 205)', + slategray: 'rgb(112, 128, 144)', + slategrey: 'rgb(112, 128, 144)', + snow: 'rgb(255, 250, 250)', + springgreen: 'rgb( 0, 255, 127)', + steelblue: 'rgb( 70, 130, 180)', + tan: 'rgb(210, 180, 140)', + teal: 'rgb( 0, 128, 128)', + thistle: 'rgb(216, 191, 216)', + tomato: 'rgb(255, 99, 71)', + turquoise: 'rgb( 64, 224, 208)', + violet: 'rgb(238, 130, 238)', + wheat: 'rgb(245, 222, 179)', + white: 'rgb(255, 255, 255)', + whitesmoke: 'rgb(245, 245, 245)', + yellow: 'rgb(255, 255, 0)', + yellowgreen: 'rgb(154, 205, 50)' + }; + + + + // class: $.jqplot.AxisLabelRenderer + // Renderer to place labels on the axes. + $.jqplot.AxisLabelRenderer = function(options) { + // Group: Properties + $.jqplot.ElemContainer.call(this); + // name of the axis associated with this tick + this.axis; + // prop: show + // wether or not to show the tick (mark and label). + this.show = true; + // prop: label + // The text or html for the label. + this.label = ''; + this.fontFamily = null; + this.fontSize = null; + this.textColor = null; + this._elem; + // prop: escapeHTML + // true to escape HTML entities in the label. + this.escapeHTML = false; + + $.extend(true, this, options); + }; + + $.jqplot.AxisLabelRenderer.prototype = new $.jqplot.ElemContainer(); + $.jqplot.AxisLabelRenderer.prototype.constructor = $.jqplot.AxisLabelRenderer; + + $.jqplot.AxisLabelRenderer.prototype.init = function(options) { + $.extend(true, this, options); + }; + + $.jqplot.AxisLabelRenderer.prototype.draw = function(ctx, plot) { + // Memory Leaks patch + if (this._elem) { + this._elem.emptyForce(); + this._elem = null; + } + + this._elem = $('<div style="position:absolute;" class="jqplot-'+this.axis+'-label"></div>'); + + if (Number(this.label)) { + this._elem.css('white-space', 'nowrap'); + } + + if (!this.escapeHTML) { + this._elem.html(this.label); + } + else { + this._elem.text(this.label); + } + if (this.fontFamily) { + this._elem.css('font-family', this.fontFamily); + } + if (this.fontSize) { + this._elem.css('font-size', this.fontSize); + } + if (this.textColor) { + this._elem.css('color', this.textColor); + } + + return this._elem; + }; + + $.jqplot.AxisLabelRenderer.prototype.pack = function() { + }; + + // class: $.jqplot.AxisTickRenderer + // A "tick" object showing the value of a tick/gridline on the plot. + $.jqplot.AxisTickRenderer = function(options) { + // Group: Properties + $.jqplot.ElemContainer.call(this); + // prop: mark + // tick mark on the axis. One of 'inside', 'outside', 'cross', '' or null. + this.mark = 'outside'; + // name of the axis associated with this tick + this.axis; + // prop: showMark + // wether or not to show the mark on the axis. + this.showMark = true; + // prop: showGridline + // wether or not to draw the gridline on the grid at this tick. + this.showGridline = true; + // prop: isMinorTick + // if this is a minor tick. + this.isMinorTick = false; + // prop: size + // Length of the tick beyond the grid in pixels. + // DEPRECATED: This has been superceeded by markSize + this.size = 4; + // prop: markSize + // Length of the tick marks in pixels. For 'cross' style, length + // will be stoked above and below axis, so total length will be twice this. + this.markSize = 6; + // prop: show + // wether or not to show the tick (mark and label). + // Setting this to false requires more testing. It is recommended + // to set showLabel and showMark to false instead. + this.show = true; + // prop: showLabel + // wether or not to show the label. + this.showLabel = true; + this.label = null; + this.value = null; + this._styles = {}; + // prop: formatter + // A class of a formatter for the tick text. sprintf by default. + this.formatter = $.jqplot.DefaultTickFormatter; + // prop: prefix + // String to prepend to the tick label. + // Prefix is prepended to the formatted tick label. + this.prefix = ''; + // prop: suffix + // String to append to the tick label. + // Suffix is appended to the formatted tick label. + this.suffix = ''; + // prop: formatString + // string passed to the formatter. + this.formatString = ''; + // prop: fontFamily + // css spec for the font-family css attribute. + this.fontFamily; + // prop: fontSize + // css spec for the font-size css attribute. + this.fontSize; + // prop: textColor + // css spec for the color attribute. + this.textColor; + // prop: escapeHTML + // true to escape HTML entities in the label. + this.escapeHTML = false; + this._elem; + this._breakTick = false; + + $.extend(true, this, options); + }; + + $.jqplot.AxisTickRenderer.prototype.init = function(options) { + $.extend(true, this, options); + }; + + $.jqplot.AxisTickRenderer.prototype = new $.jqplot.ElemContainer(); + $.jqplot.AxisTickRenderer.prototype.constructor = $.jqplot.AxisTickRenderer; + + $.jqplot.AxisTickRenderer.prototype.setTick = function(value, axisName, isMinor) { + this.value = value; + this.axis = axisName; + if (isMinor) { + this.isMinorTick = true; + } + return this; + }; + + $.jqplot.AxisTickRenderer.prototype.draw = function() { + if (this.label === null) { + this.label = this.prefix + this.formatter(this.formatString, this.value) + this.suffix; + } + var style = {position: 'absolute'}; + if (Number(this.label)) { + style['whitSpace'] = 'nowrap'; + } + + // Memory Leaks patch + if (this._elem) { + this._elem.emptyForce(); + this._elem = null; + } + + this._elem = $(document.createElement('div')); + this._elem.addClass("jqplot-"+this.axis+"-tick"); + + if (!this.escapeHTML) { + this._elem.html(this.label); + } + else { + this._elem.text(this.label); + } + + this._elem.css(style); + + for (var s in this._styles) { + this._elem.css(s, this._styles[s]); + } + if (this.fontFamily) { + this._elem.css('font-family', this.fontFamily); + } + if (this.fontSize) { + this._elem.css('font-size', this.fontSize); + } + if (this.textColor) { + this._elem.css('color', this.textColor); + } + if (this._breakTick) { + this._elem.addClass('jqplot-breakTick'); + } + + return this._elem; + }; + + $.jqplot.DefaultTickFormatter = function (format, val) { + if (typeof val == 'number') { + if (!format) { + format = $.jqplot.config.defaultTickFormatString; + } + return $.jqplot.sprintf(format, val); + } + else { + return String(val); + } + }; + + $.jqplot.PercentTickFormatter = function (format, val) { + if (typeof val == 'number') { + val = 100 * val; + if (!format) { + format = $.jqplot.config.defaultTickFormatString; + } + return $.jqplot.sprintf(format, val); + } + else { + return String(val); + } + }; + + $.jqplot.AxisTickRenderer.prototype.pack = function() { + }; + + // Class: $.jqplot.CanvasGridRenderer + // The default jqPlot grid renderer, creating a grid on a canvas element. + // The renderer has no additional options beyond the <Grid> class. + $.jqplot.CanvasGridRenderer = function(){ + this.shadowRenderer = new $.jqplot.ShadowRenderer(); + }; + + // called with context of Grid object + $.jqplot.CanvasGridRenderer.prototype.init = function(options) { + this._ctx; + $.extend(true, this, options); + // set the shadow renderer options + var sopts = {lineJoin:'miter', lineCap:'round', fill:false, isarc:false, angle:this.shadowAngle, offset:this.shadowOffset, alpha:this.shadowAlpha, depth:this.shadowDepth, lineWidth:this.shadowWidth, closePath:false, strokeStyle:this.shadowColor}; + this.renderer.shadowRenderer.init(sopts); + }; + + // called with context of Grid. + $.jqplot.CanvasGridRenderer.prototype.createElement = function(plot) { + var elem; + // Memory Leaks patch + if (this._elem) { + if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) { + elem = this._elem.get(0); + window.G_vmlCanvasManager.uninitElement(elem); + elem = null; + } + + this._elem.emptyForce(); + this._elem = null; + } + + elem = plot.canvasManager.getCanvas(); + + var w = this._plotDimensions.width; + var h = this._plotDimensions.height; + elem.width = w; + elem.height = h; + this._elem = $(elem); + this._elem.addClass('jqplot-grid-canvas'); + this._elem.css({ position: 'absolute', left: 0, top: 0 }); + + elem = plot.canvasManager.initCanvas(elem); + + this._top = this._offsets.top; + this._bottom = h - this._offsets.bottom; + this._left = this._offsets.left; + this._right = w - this._offsets.right; + this._width = this._right - this._left; + this._height = this._bottom - this._top; + // avoid memory leak + elem = null; + return this._elem; + }; + + $.jqplot.CanvasGridRenderer.prototype.draw = function() { + this._ctx = this._elem.get(0).getContext("2d"); + var ctx = this._ctx; + var axes = this._axes; + // Add the grid onto the grid canvas. This is the bottom most layer. + ctx.save(); + ctx.clearRect(0, 0, this._plotDimensions.width, this._plotDimensions.height); + ctx.fillStyle = this.backgroundColor || this.background; + ctx.fillRect(this._left, this._top, this._width, this._height); + + ctx.save(); + ctx.lineJoin = 'miter'; + ctx.lineCap = 'butt'; + ctx.lineWidth = this.gridLineWidth; + ctx.strokeStyle = this.gridLineColor; + var b, e, s, m; + var ax = ['xaxis', 'yaxis', 'x2axis', 'y2axis']; + for (var i=4; i>0; i--) { + var name = ax[i-1]; + var axis = axes[name]; + var ticks = axis._ticks; + var numticks = ticks.length; + if (axis.show) { + if (axis.drawBaseline) { + var bopts = {}; + if (axis.baselineWidth !== null) { + bopts.lineWidth = axis.baselineWidth; + } + if (axis.baselineColor !== null) { + bopts.strokeStyle = axis.baselineColor; + } + switch (name) { + case 'xaxis': + drawLine (this._left, this._bottom, this._right, this._bottom, bopts); + break; + case 'yaxis': + drawLine (this._left, this._bottom, this._left, this._top, bopts); + break; + case 'x2axis': + drawLine (this._left, this._bottom, this._right, this._bottom, bopts); + break; + case 'y2axis': + drawLine (this._right, this._bottom, this._right, this._top, bopts); + break; + } + } + for (var j=numticks; j>0; j--) { + var t = ticks[j-1]; + if (t.show) { + var pos = Math.round(axis.u2p(t.value)) + 0.5; + switch (name) { + case 'xaxis': + // draw the grid line if we should + if (t.showGridline && this.drawGridlines && ((!t.isMinorTick && axis.drawMajorGridlines) || (t.isMinorTick && axis.drawMinorGridlines)) ) { + drawLine(pos, this._top, pos, this._bottom); + } + // draw the mark + if (t.showMark && t.mark && ((!t.isMinorTick && axis.drawMajorTickMarks) || (t.isMinorTick && axis.drawMinorTickMarks)) ) { + s = t.markSize; + m = t.mark; + var pos = Math.round(axis.u2p(t.value)) + 0.5; + switch (m) { + case 'outside': + b = this._bottom; + e = this._bottom+s; + break; + case 'inside': + b = this._bottom-s; + e = this._bottom; + break; + case 'cross': + b = this._bottom-s; + e = this._bottom+s; + break; + default: + b = this._bottom; + e = this._bottom+s; + break; + } + // draw the shadow + if (this.shadow) { + this.renderer.shadowRenderer.draw(ctx, [[pos,b],[pos,e]], {lineCap:'butt', lineWidth:this.gridLineWidth, offset:this.gridLineWidth*0.75, depth:2, fill:false, closePath:false}); + } + // draw the line + drawLine(pos, b, pos, e); + } + break; + case 'yaxis': + // draw the grid line + if (t.showGridline && this.drawGridlines && ((!t.isMinorTick && axis.drawMajorGridlines) || (t.isMinorTick && axis.drawMinorGridlines)) ) { + drawLine(this._right, pos, this._left, pos); + } + // draw the mark + if (t.showMark && t.mark && ((!t.isMinorTick && axis.drawMajorTickMarks) || (t.isMinorTick && axis.drawMinorTickMarks)) ) { + s = t.markSize; + m = t.mark; + var pos = Math.round(axis.u2p(t.value)) + 0.5; + switch (m) { + case 'outside': + b = this._left-s; + e = this._left; + break; + case 'inside': + b = this._left; + e = this._left+s; + break; + case 'cross': + b = this._left-s; + e = this._left+s; + break; + default: + b = this._left-s; + e = this._left; + break; + } + // draw the shadow + if (this.shadow) { + this.renderer.shadowRenderer.draw(ctx, [[b, pos], [e, pos]], {lineCap:'butt', lineWidth:this.gridLineWidth*1.5, offset:this.gridLineWidth*0.75, fill:false, closePath:false}); + } + drawLine(b, pos, e, pos, {strokeStyle:axis.borderColor}); + } + break; + case 'x2axis': + // draw the grid line + if (t.showGridline && this.drawGridlines && ((!t.isMinorTick && axis.drawMajorGridlines) || (t.isMinorTick && axis.drawMinorGridlines)) ) { + drawLine(pos, this._bottom, pos, this._top); + } + // draw the mark + if (t.showMark && t.mark && ((!t.isMinorTick && axis.drawMajorTickMarks) || (t.isMinorTick && axis.drawMinorTickMarks)) ) { + s = t.markSize; + m = t.mark; + var pos = Math.round(axis.u2p(t.value)) + 0.5; + switch (m) { + case 'outside': + b = this._top-s; + e = this._top; + break; + case 'inside': + b = this._top; + e = this._top+s; + break; + case 'cross': + b = this._top-s; + e = this._top+s; + break; + default: + b = this._top-s; + e = this._top; + break; + } + // draw the shadow + if (this.shadow) { + this.renderer.shadowRenderer.draw(ctx, [[pos,b],[pos,e]], {lineCap:'butt', lineWidth:this.gridLineWidth, offset:this.gridLineWidth*0.75, depth:2, fill:false, closePath:false}); + } + drawLine(pos, b, pos, e); + } + break; + case 'y2axis': + // draw the grid line + if (t.showGridline && this.drawGridlines && ((!t.isMinorTick && axis.drawMajorGridlines) || (t.isMinorTick && axis.drawMinorGridlines)) ) { + drawLine(this._left, pos, this._right, pos); + } + // draw the mark + if (t.showMark && t.mark && ((!t.isMinorTick && axis.drawMajorTickMarks) || (t.isMinorTick && axis.drawMinorTickMarks)) ) { + s = t.markSize; + m = t.mark; + var pos = Math.round(axis.u2p(t.value)) + 0.5; + switch (m) { + case 'outside': + b = this._right; + e = this._right+s; + break; + case 'inside': + b = this._right-s; + e = this._right; + break; + case 'cross': + b = this._right-s; + e = this._right+s; + break; + default: + b = this._right; + e = this._right+s; + break; + } + // draw the shadow + if (this.shadow) { + this.renderer.shadowRenderer.draw(ctx, [[b, pos], [e, pos]], {lineCap:'butt', lineWidth:this.gridLineWidth*1.5, offset:this.gridLineWidth*0.75, fill:false, closePath:false}); + } + drawLine(b, pos, e, pos, {strokeStyle:axis.borderColor}); + } + break; + default: + break; + } + } + } + t = null; + } + axis = null; + ticks = null; + } + // Now draw grid lines for additional y axes + ////// + // TO DO: handle yMidAxis + ////// + ax = ['y3axis', 'y4axis', 'y5axis', 'y6axis', 'y7axis', 'y8axis', 'y9axis', 'yMidAxis']; + for (var i=7; i>0; i--) { + var axis = axes[ax[i-1]]; + var ticks = axis._ticks; + if (axis.show) { + var tn = ticks[axis.numberTicks-1]; + var t0 = ticks[0]; + var left = axis.getLeft(); + var points = [[left, tn.getTop() + tn.getHeight()/2], [left, t0.getTop() + t0.getHeight()/2 + 1.0]]; + // draw the shadow + if (this.shadow) { + this.renderer.shadowRenderer.draw(ctx, points, {lineCap:'butt', fill:false, closePath:false}); + } + // draw the line + drawLine(points[0][0], points[0][1], points[1][0], points[1][1], {lineCap:'butt', strokeStyle:axis.borderColor, lineWidth:axis.borderWidth}); + // draw the tick marks + for (var j=ticks.length; j>0; j--) { + var t = ticks[j-1]; + s = t.markSize; + m = t.mark; + var pos = Math.round(axis.u2p(t.value)) + 0.5; + if (t.showMark && t.mark) { + switch (m) { + case 'outside': + b = left; + e = left+s; + break; + case 'inside': + b = left-s; + e = left; + break; + case 'cross': + b = left-s; + e = left+s; + break; + default: + b = left; + e = left+s; + break; + } + points = [[b,pos], [e,pos]]; + // draw the shadow + if (this.shadow) { + this.renderer.shadowRenderer.draw(ctx, points, {lineCap:'butt', lineWidth:this.gridLineWidth*1.5, offset:this.gridLineWidth*0.75, fill:false, closePath:false}); + } + // draw the line + drawLine(b, pos, e, pos, {strokeStyle:axis.borderColor}); + } + t = null; + } + t0 = null; + } + axis = null; + ticks = null; + } + + ctx.restore(); + + function drawLine(bx, by, ex, ey, opts) { + ctx.save(); + opts = opts || {}; + if (opts.lineWidth == null || opts.lineWidth != 0){ + $.extend(true, ctx, opts); + ctx.beginPath(); + ctx.moveTo(bx, by); + ctx.lineTo(ex, ey); + ctx.stroke(); + ctx.restore(); + } + } + + if (this.shadow) { + var points = [[this._left, this._bottom], [this._right, this._bottom], [this._right, this._top]]; + this.renderer.shadowRenderer.draw(ctx, points); + } + // Now draw border around grid. Use axis border definitions. start at + // upper left and go clockwise. + if (this.borderWidth != 0 && this.drawBorder) { + drawLine (this._left, this._top, this._right, this._top, {lineCap:'round', strokeStyle:axes.x2axis.borderColor, lineWidth:axes.x2axis.borderWidth}); + drawLine (this._right, this._top, this._right, this._bottom, {lineCap:'round', strokeStyle:axes.y2axis.borderColor, lineWidth:axes.y2axis.borderWidth}); + drawLine (this._right, this._bottom, this._left, this._bottom, {lineCap:'round', strokeStyle:axes.xaxis.borderColor, lineWidth:axes.xaxis.borderWidth}); + drawLine (this._left, this._bottom, this._left, this._top, {lineCap:'round', strokeStyle:axes.yaxis.borderColor, lineWidth:axes.yaxis.borderWidth}); + } + // ctx.lineWidth = this.borderWidth; + // ctx.strokeStyle = this.borderColor; + // ctx.strokeRect(this._left, this._top, this._width, this._height); + + ctx.restore(); + ctx = null; + axes = null; + }; + + // Class: $.jqplot.DivTitleRenderer + // The default title renderer for jqPlot. This class has no options beyond the <Title> class. + $.jqplot.DivTitleRenderer = function() { + }; + + $.jqplot.DivTitleRenderer.prototype.init = function(options) { + $.extend(true, this, options); + }; + + $.jqplot.DivTitleRenderer.prototype.draw = function() { + // Memory Leaks patch + if (this._elem) { + this._elem.emptyForce(); + this._elem = null; + } + + var r = this.renderer; + var elem = document.createElement('div'); + this._elem = $(elem); + this._elem.addClass('jqplot-title'); + + if (!this.text) { + this.show = false; + this._elem.height(0); + this._elem.width(0); + } + else if (this.text) { + var color; + if (this.color) { + color = this.color; + } + else if (this.textColor) { + color = this.textColor; + } + + // don't trust that a stylesheet is present, set the position. + var styles = {position:'absolute', top:'0px', left:'0px'}; + + if (this._plotWidth) { + styles['width'] = this._plotWidth+'px'; + } + if (this.fontSize) { + styles['fontSize'] = this.fontSize; + } + if (typeof this.textAlign === 'string') { + styles['textAlign'] = this.textAlign; + } + else { + styles['textAlign'] = 'center'; + } + if (color) { + styles['color'] = color; + } + if (this.paddingBottom) { + styles['paddingBottom'] = this.paddingBottom; + } + if (this.fontFamily) { + styles['fontFamily'] = this.fontFamily; + } + + this._elem.css(styles); + if (this.escapeHtml) { + this._elem.text(this.text); + } + else { + this._elem.html(this.text); + } + + + // styletext += (this._plotWidth) ? 'width:'+this._plotWidth+'px;' : ''; + // styletext += (this.fontSize) ? 'font-size:'+this.fontSize+';' : ''; + // styletext += (this.textAlign) ? 'text-align:'+this.textAlign+';' : 'text-align:center;'; + // styletext += (color) ? 'color:'+color+';' : ''; + // styletext += (this.paddingBottom) ? 'padding-bottom:'+this.paddingBottom+';' : ''; + // this._elem = $('<div class="jqplot-title" style="'+styletext+'">'+this.text+'</div>'); + // if (this.fontFamily) { + // this._elem.css('font-family', this.fontFamily); + // } + } + + elem = null; + + return this._elem; + }; + + $.jqplot.DivTitleRenderer.prototype.pack = function() { + // nothing to do here + }; + + + var dotlen = 0.1; + + $.jqplot.LinePattern = function (ctx, pattern) { + + var defaultLinePatterns = { + dotted: [ dotlen, $.jqplot.config.dotGapLength ], + dashed: [ $.jqplot.config.dashLength, $.jqplot.config.gapLength ], + solid: null + }; + + if (typeof pattern === 'string') { + if (pattern[0] === '.' || pattern[0] === '-') { + var s = pattern; + pattern = []; + for (var i=0, imax=s.length; i<imax; i++) { + if (s[i] === '.') { + pattern.push( dotlen ); + } + else if (s[i] === '-') { + pattern.push( $.jqplot.config.dashLength ); + } + else { + continue; + } + pattern.push( $.jqplot.config.gapLength ); + } + } + else { + pattern = defaultLinePatterns[pattern]; + } + } + + if (!(pattern && pattern.length)) { + return ctx; + } + + var patternIndex = 0; + var patternDistance = pattern[0]; + var px = 0; + var py = 0; + var pathx0 = 0; + var pathy0 = 0; + + var moveTo = function (x, y) { + ctx.moveTo( x, y ); + px = x; + py = y; + pathx0 = x; + pathy0 = y; + }; + + var lineTo = function (x, y) { + var scale = ctx.lineWidth; + var dx = x - px; + var dy = y - py; + var dist = Math.sqrt(dx*dx+dy*dy); + if ((dist > 0) && (scale > 0)) { + dx /= dist; + dy /= dist; + while (true) { + var dp = scale * patternDistance; + if (dp < dist) { + px += dp * dx; + py += dp * dy; + if ((patternIndex & 1) == 0) { + ctx.lineTo( px, py ); + } + else { + ctx.moveTo( px, py ); + } + dist -= dp; + patternIndex++; + if (patternIndex >= pattern.length) { + patternIndex = 0; + } + patternDistance = pattern[patternIndex]; + } + else { + px = x; + py = y; + if ((patternIndex & 1) == 0) { + ctx.lineTo( px, py ); + } + else { + ctx.moveTo( px, py ); + } + patternDistance -= dist / scale; + break; + } + } + } + }; + + var beginPath = function () { + ctx.beginPath(); + }; + + var closePath = function () { + lineTo( pathx0, pathy0 ); + }; + + return { + moveTo: moveTo, + lineTo: lineTo, + beginPath: beginPath, + closePath: closePath + }; + }; + + // Class: $.jqplot.LineRenderer + // The default line renderer for jqPlot, this class has no options beyond the <Series> class. + // Draws series as a line. + $.jqplot.LineRenderer = function(){ + this.shapeRenderer = new $.jqplot.ShapeRenderer(); + this.shadowRenderer = new $.jqplot.ShadowRenderer(); + }; + + // called with scope of series. + $.jqplot.LineRenderer.prototype.init = function(options, plot) { + // Group: Properties + // + options = options || {}; + this._type='line'; + this.renderer.animation = { + show: false, + direction: 'left', + speed: 2500, + _supported: true + }; + // prop: smooth + // True to draw a smoothed (interpolated) line through the data points + // with automatically computed number of smoothing points. + // Set to an integer number > 2 to specify number of smoothing points + // to use between each data point. + this.renderer.smooth = false; // true or a number > 2 for smoothing. + this.renderer.tension = null; // null to auto compute or a number typically > 6. Fewer points requires higher tension. + // prop: constrainSmoothing + // True to use a more accurate smoothing algorithm that will + // not overshoot any data points. False to allow overshoot but + // produce a smoother looking line. + this.renderer.constrainSmoothing = true; + // this is smoothed data in grid coordinates, like gridData + this.renderer._smoothedData = []; + // this is smoothed data in plot units (plot coordinates), like plotData. + this.renderer._smoothedPlotData = []; + this.renderer._hiBandGridData = []; + this.renderer._lowBandGridData = []; + this.renderer._hiBandSmoothedData = []; + this.renderer._lowBandSmoothedData = []; + + // prop: bandData + // Data used to draw error bands or confidence intervals above/below a line. + // + // bandData can be input in 3 forms. jqPlot will figure out which is the + // low band line and which is the high band line for all forms: + // + // A 2 dimensional array like [[yl1, yl2, ...], [yu1, yu2, ...]] where + // [yl1, yl2, ...] are y values of the lower line and + // [yu1, yu2, ...] are y values of the upper line. + // In this case there must be the same number of y data points as data points + // in the series and the bands will inherit the x values of the series. + // + // A 2 dimensional array like [[[xl1, yl1], [xl2, yl2], ...], [[xh1, yh1], [xh2, yh2], ...]] + // where [xl1, yl1] are x,y data points for the lower line and + // [xh1, yh1] are x,y data points for the high line. + // x values do not have to correspond to the x values of the series and can + // be of any arbitrary length. + // + // Can be of form [[yl1, yu1], [yl2, yu2], [yl3, yu3], ...] where + // there must be 3 or more arrays and there must be the same number of arrays + // as there are data points in the series. In this case, + // [yl1, yu1] specifies the lower and upper y values for the 1st + // data point and so on. The bands will inherit the x + // values from the series. + this.renderer.bandData = []; + + // Group: bands + // Banding around line, e.g error bands or confidence intervals. + this.renderer.bands = { + // prop: show + // true to show the bands. If bandData or interval is + // supplied, show will be set to true by default. + show: false, + hiData: [], + lowData: [], + // prop: color + // color of lines at top and bottom of bands [default: series color]. + color: this.color, + // prop: showLines + // True to show lines at top and bottom of bands [default: false]. + showLines: false, + // prop: fill + // True to fill area between bands [default: true]. + fill: true, + // prop: fillColor + // css color spec for filled area. [default: series color]. + fillColor: null, + _min: null, + _max: null, + // prop: interval + // User specified interval above and below line for bands [default: '3%'']. + // Can be a value like 3 or a string like '3%' + // or an upper/lower array like [1, -2] or ['2%', '-1.5%'] + interval: '3%' + }; + + + var lopts = {highlightMouseOver: options.highlightMouseOver, highlightMouseDown: options.highlightMouseDown, highlightColor: options.highlightColor}; + + delete (options.highlightMouseOver); + delete (options.highlightMouseDown); + delete (options.highlightColor); + + $.extend(true, this.renderer, options); + + this.renderer.options = options; + + // if we are given some band data, and bands aren't explicity set to false in options, turn them on. + if (this.renderer.bandData.length > 1 && (!options.bands || options.bands.show == null)) { + this.renderer.bands.show = true; + } + + // if we are given an interval, and bands aren't explicity set to false in options, turn them on. + else if (options.bands && options.bands.show == null && options.bands.interval != null) { + this.renderer.bands.show = true; + } + + // if plot is filled, turn off bands. + if (this.fill) { + this.renderer.bands.show = false; + } + + if (this.renderer.bands.show) { + this.renderer.initBands.call(this, this.renderer.options, plot); + } + + + // smoothing is not compatible with stacked lines, disable + if (this._stack) { + this.renderer.smooth = false; + } + + // set the shape renderer options + var opts = {lineJoin:this.lineJoin, lineCap:this.lineCap, fill:this.fill, isarc:false, strokeStyle:this.color, fillStyle:this.fillColor, lineWidth:this.lineWidth, linePattern:this.linePattern, closePath:this.fill}; + this.renderer.shapeRenderer.init(opts); + + var shadow_offset = options.shadowOffset; + // set the shadow renderer options + if (shadow_offset == null) { + // scale the shadowOffset to the width of the line. + if (this.lineWidth > 2.5) { + shadow_offset = 1.25 * (1 + (Math.atan((this.lineWidth/2.5))/0.785398163 - 1)*0.6); + // var shadow_offset = this.shadowOffset; + } + // for skinny lines, don't make such a big shadow. + else { + shadow_offset = 1.25 * Math.atan((this.lineWidth/2.5))/0.785398163; + } + } + + var sopts = {lineJoin:this.lineJoin, lineCap:this.lineCap, fill:this.fill, isarc:false, angle:this.shadowAngle, offset:shadow_offset, alpha:this.shadowAlpha, depth:this.shadowDepth, lineWidth:this.lineWidth, linePattern:this.linePattern, closePath:this.fill}; + this.renderer.shadowRenderer.init(sopts); + this._areaPoints = []; + this._boundingBox = [[],[]]; + + if (!this.isTrendline && this.fill || this.renderer.bands.show) { + // Group: Properties + // + // prop: highlightMouseOver + // True to highlight area on a filled plot when moused over. + // This must be false to enable highlightMouseDown to highlight when clicking on an area on a filled plot. + this.highlightMouseOver = true; + // prop: highlightMouseDown + // True to highlight when a mouse button is pressed over an area on a filled plot. + // This will be disabled if highlightMouseOver is true. + this.highlightMouseDown = false; + // prop: highlightColor + // color to use when highlighting an area on a filled plot. + this.highlightColor = null; + // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver + if (lopts.highlightMouseDown && lopts.highlightMouseOver == null) { + lopts.highlightMouseOver = false; + } + + $.extend(true, this, {highlightMouseOver: lopts.highlightMouseOver, highlightMouseDown: lopts.highlightMouseDown, highlightColor: lopts.highlightColor}); + + if (!this.highlightColor) { + var fc = (this.renderer.bands.show) ? this.renderer.bands.fillColor : this.fillColor; + this.highlightColor = $.jqplot.computeHighlightColors(fc); + } + // turn off (disable) the highlighter plugin + if (this.highlighter) { + this.highlighter.show = false; + } + } + + if (!this.isTrendline && plot) { + plot.plugins.lineRenderer = {}; + plot.postInitHooks.addOnce(postInit); + plot.postDrawHooks.addOnce(postPlotDraw); + plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove); + plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown); + plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp); + plot.eventListenerHooks.addOnce('jqplotClick', handleClick); + plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick); + } + + }; + + $.jqplot.LineRenderer.prototype.initBands = function(options, plot) { + // use bandData if no data specified in bands option + //var bd = this.renderer.bandData; + var bd = options.bandData || []; + var bands = this.renderer.bands; + bands.hiData = []; + bands.lowData = []; + var data = this.data; + bands._max = null; + bands._min = null; + // If 2 arrays, and each array greater than 2 elements, assume it is hi and low data bands of y values. + if (bd.length == 2) { + // Do we have an array of x,y values? + // like [[[1,1], [2,4], [3,3]], [[1,3], [2,6], [3,5]]] + if ($.isArray(bd[0][0])) { + // since an arbitrary array of points, spin through all of them to determine max and min lines. + + var p; + var bdminidx = 0, bdmaxidx = 0; + for (var i = 0, l = bd[0].length; i<l; i++) { + p = bd[0][i]; + if ((p[1] != null && p[1] > bands._max) || bands._max == null) { + bands._max = p[1]; + } + if ((p[1] != null && p[1] < bands._min) || bands._min == null) { + bands._min = p[1]; + } + } + for (var i = 0, l = bd[1].length; i<l; i++) { + p = bd[1][i]; + if ((p[1] != null && p[1] > bands._max) || bands._max == null) { + bands._max = p[1]; + bdmaxidx = 1; + } + if ((p[1] != null && p[1] < bands._min) || bands._min == null) { + bands._min = p[1]; + bdminidx = 1; + } + } + + if (bdmaxidx === bdminidx) { + bands.show = false; + } + + bands.hiData = bd[bdmaxidx]; + bands.lowData = bd[bdminidx]; + } + // else data is arrays of y values + // like [[1,4,3], [3,6,5]] + // must have same number of band data points as points in series + else if (bd[0].length === data.length && bd[1].length === data.length) { + var hi = (bd[0][0] > bd[1][0]) ? 0 : 1; + var low = (hi) ? 0 : 1; + for (var i=0, l=data.length; i < l; i++) { + bands.hiData.push([data[i][0], bd[hi][i]]); + bands.lowData.push([data[i][0], bd[low][i]]); + } + } + + // we don't have proper data array, don't show bands. + else { + bands.show = false; + } + } + + // if more than 2 arrays, have arrays of [ylow, yhi] values. + // note, can't distinguish case of [[ylow, yhi], [ylow, yhi]] from [[ylow, ylow], [yhi, yhi]] + // this is assumed to be of the latter form. + else if (bd.length > 2 && !$.isArray(bd[0][0])) { + var hi = (bd[0][0] > bd[0][1]) ? 0 : 1; + var low = (hi) ? 0 : 1; + for (var i=0, l=bd.length; i<l; i++) { + bands.hiData.push([data[i][0], bd[i][hi]]); + bands.lowData.push([data[i][0], bd[i][low]]); + } + } + + // don't have proper data, auto calculate + else { + var intrv = bands.interval; + var a = null; + var b = null; + var afunc = null; + var bfunc = null; + + if ($.isArray(intrv)) { + a = intrv[0]; + b = intrv[1]; + } + else { + a = intrv; + } + + if (isNaN(a)) { + // we have a string + if (a.charAt(a.length - 1) === '%') { + afunc = 'multiply'; + a = parseFloat(a)/100 + 1; + } + } + + else { + a = parseFloat(a); + afunc = 'add'; + } + + if (b !== null && isNaN(b)) { + // we have a string + if (b.charAt(b.length - 1) === '%') { + bfunc = 'multiply'; + b = parseFloat(b)/100 + 1; + } + } + + else if (b !== null) { + b = parseFloat(b); + bfunc = 'add'; + } + + if (a !== null) { + if (b === null) { + b = -a; + bfunc = afunc; + if (bfunc === 'multiply') { + b += 2; + } + } + + // make sure a always applies to hi band. + if (a < b) { + var temp = a; + a = b; + b = temp; + temp = afunc; + afunc = bfunc; + bfunc = temp; + } + + for (var i=0, l = data.length; i < l; i++) { + switch (afunc) { + case 'add': + bands.hiData.push([data[i][0], data[i][1] + a]); + break; + case 'multiply': + bands.hiData.push([data[i][0], data[i][1] * a]); + break; + } + switch (bfunc) { + case 'add': + bands.lowData.push([data[i][0], data[i][1] + b]); + break; + case 'multiply': + bands.lowData.push([data[i][0], data[i][1] * b]); + break; + } + } + } + + else { + bands.show = false; + } + } + + var hd = bands.hiData; + var ld = bands.lowData; + for (var i = 0, l = hd.length; i<l; i++) { + if ((hd[i][1] != null && hd[i][1] > bands._max) || bands._max == null) { + bands._max = hd[i][1]; + } + } + for (var i = 0, l = ld.length; i<l; i++) { + if ((ld[i][1] != null && ld[i][1] < bands._min) || bands._min == null) { + bands._min = ld[i][1]; + } + } + + // one last check for proper data + // these don't apply any more since allowing arbitrary x,y values + // if (bands.hiData.length != bands.lowData.length) { + // bands.show = false; + // } + + // if (bands.hiData.length != this.data.length) { + // bands.show = false; + // } + + if (bands.fillColor === null) { + var c = $.jqplot.getColorComponents(bands.color); + // now adjust alpha to differentiate fill + c[3] = c[3] * 0.5; + bands.fillColor = 'rgba(' + c[0] +', '+ c[1] +', '+ c[2] +', '+ c[3] + ')'; + } + }; + + function getSteps (d, f) { + return (3.4182054+f) * Math.pow(d, -0.3534992); + } + + function computeSteps (d1, d2) { + var s = Math.sqrt(Math.pow((d2[0]- d1[0]), 2) + Math.pow ((d2[1] - d1[1]), 2)); + return 5.7648 * Math.log(s) + 7.4456; + } + + function tanh (x) { + var a = (Math.exp(2*x) - 1) / (Math.exp(2*x) + 1); + return a; + } + + ////////// + // computeConstrainedSmoothedData + // An implementation of the constrained cubic spline interpolation + // method as presented in: + // + // Kruger, CJC, Constrained Cubic Spine Interpolation for Chemical Engineering Applications + // http://www.korf.co.uk/spline.pdf + // + // The implementation below borrows heavily from the sample Visual Basic + // implementation by CJC Kruger found in http://www.korf.co.uk/spline.xls + // + ///////// + + // called with scope of series + function computeConstrainedSmoothedData (gd) { + var smooth = this.renderer.smooth; + var dim = this.canvas.getWidth(); + var xp = this._xaxis.series_p2u; + var yp = this._yaxis.series_p2u; + var steps =null; + var _steps = null; + var dist = gd.length/dim; + var _smoothedData = []; + var _smoothedPlotData = []; + + if (!isNaN(parseFloat(smooth))) { + steps = parseFloat(smooth); + } + else { + steps = getSteps(dist, 0.5); + } + + var yy = []; + var xx = []; + + for (var i=0, l = gd.length; i<l; i++) { + yy.push(gd[i][1]); + xx.push(gd[i][0]); + } + + function dxx(x1, x0) { + if (x1 - x0 == 0) { + return Math.pow(10,10); + } + else { + return x1 - x0; + } + } + + var A, B, C, D; + // loop through each line segment. Have # points - 1 line segments. Nmber segments starting at 1. + var nmax = gd.length - 1; + for (var num = 1, gdl = gd.length; num<gdl; num++) { + var gxx = []; + var ggxx = []; + // point at each end of segment. + for (var j = 0; j < 2; j++) { + var i = num - 1 + j; // point number, 0 to # points. + + if (i == 0 || i == nmax) { + gxx[j] = Math.pow(10, 10); + } + else if (yy[i+1] - yy[i] == 0 || yy[i] - yy[i-1] == 0) { + gxx[j] = 0; + } + else if (((xx[i+1] - xx[i]) / (yy[i+1] - yy[i]) + (xx[i] - xx[i-1]) / (yy[i] - yy[i-1])) == 0 ) { + gxx[j] = 0; + } + else if ( (yy[i+1] - yy[i]) * (yy[i] - yy[i-1]) < 0 ) { + gxx[j] = 0; + } + + else { + gxx[j] = 2 / (dxx(xx[i + 1], xx[i]) / (yy[i + 1] - yy[i]) + dxx(xx[i], xx[i - 1]) / (yy[i] - yy[i - 1])); + } + } + + // Reset first derivative (slope) at first and last point + if (num == 1) { + // First point has 0 2nd derivative + gxx[0] = 3 / 2 * (yy[1] - yy[0]) / dxx(xx[1], xx[0]) - gxx[1] / 2; + } + else if (num == nmax) { + // Last point has 0 2nd derivative + gxx[1] = 3 / 2 * (yy[nmax] - yy[nmax - 1]) / dxx(xx[nmax], xx[nmax - 1]) - gxx[0] / 2; + } + + // Calc second derivative at points + ggxx[0] = -2 * (gxx[1] + 2 * gxx[0]) / dxx(xx[num], xx[num - 1]) + 6 * (yy[num] - yy[num - 1]) / Math.pow(dxx(xx[num], xx[num - 1]), 2); + ggxx[1] = 2 * (2 * gxx[1] + gxx[0]) / dxx(xx[num], xx[num - 1]) - 6 * (yy[num] - yy[num - 1]) / Math.pow(dxx(xx[num], xx[num - 1]), 2); + + // Calc constants for cubic interpolation + D = 1 / 6 * (ggxx[1] - ggxx[0]) / dxx(xx[num], xx[num - 1]); + C = 1 / 2 * (xx[num] * ggxx[0] - xx[num - 1] * ggxx[1]) / dxx(xx[num], xx[num - 1]); + B = (yy[num] - yy[num - 1] - C * (Math.pow(xx[num], 2) - Math.pow(xx[num - 1], 2)) - D * (Math.pow(xx[num], 3) - Math.pow(xx[num - 1], 3))) / dxx(xx[num], xx[num - 1]); + A = yy[num - 1] - B * xx[num - 1] - C * Math.pow(xx[num - 1], 2) - D * Math.pow(xx[num - 1], 3); + + var increment = (xx[num] - xx[num - 1]) / steps; + var temp, tempx; + + for (var j = 0, l = steps; j < l; j++) { + temp = []; + tempx = xx[num - 1] + j * increment; + temp.push(tempx); + temp.push(A + B * tempx + C * Math.pow(tempx, 2) + D * Math.pow(tempx, 3)); + _smoothedData.push(temp); + _smoothedPlotData.push([xp(temp[0]), yp(temp[1])]); + } + } + + _smoothedData.push(gd[i]); + _smoothedPlotData.push([xp(gd[i][0]), yp(gd[i][1])]); + + return [_smoothedData, _smoothedPlotData]; + } + + /////// + // computeHermiteSmoothedData + // A hermite spline smoothing of the plot data. + // This implementation is derived from the one posted + // by krypin on the jqplot-users mailing list: + // + // http://groups.google.com/group/jqplot-users/browse_thread/thread/748be6a445723cea?pli=1 + // + // with a blog post: + // + // http://blog.statscollector.com/a-plugin-renderer-for-jqplot-to-draw-a-hermite-spline/ + // + // and download of the original plugin: + // + // http://blog.statscollector.com/wp-content/uploads/2010/02/jqplot.hermiteSplineRenderer.js + ////////// + + // called with scope of series + function computeHermiteSmoothedData (gd) { + var smooth = this.renderer.smooth; + var tension = this.renderer.tension; + var dim = this.canvas.getWidth(); + var xp = this._xaxis.series_p2u; + var yp = this._yaxis.series_p2u; + var steps =null; + var _steps = null; + var a = null; + var a1 = null; + var a2 = null; + var slope = null; + var slope2 = null; + var temp = null; + var t, s, h1, h2, h3, h4; + var TiX, TiY, Ti1X, Ti1Y; + var pX, pY, p; + var sd = []; + var spd = []; + var dist = gd.length/dim; + var min, max, stretch, scale, shift; + var _smoothedData = []; + var _smoothedPlotData = []; + if (!isNaN(parseFloat(smooth))) { + steps = parseFloat(smooth); + } + else { + steps = getSteps(dist, 0.5); + } + if (!isNaN(parseFloat(tension))) { + tension = parseFloat(tension); + } + + for (var i=0, l = gd.length-1; i < l; i++) { + + if (tension === null) { + slope = Math.abs((gd[i+1][1] - gd[i][1]) / (gd[i+1][0] - gd[i][0])); + + min = 0.3; + max = 0.6; + stretch = (max - min)/2.0; + scale = 2.5; + shift = -1.4; + + temp = slope/scale + shift; + + a1 = stretch * tanh(temp) - stretch * tanh(shift) + min; + + // if have both left and right line segments, will use minimum tension. + if (i > 0) { + slope2 = Math.abs((gd[i][1] - gd[i-1][1]) / (gd[i][0] - gd[i-1][0])); + } + temp = slope2/scale + shift; + + a2 = stretch * tanh(temp) - stretch * tanh(shift) + min; + + a = (a1 + a2)/2.0; + + } + else { + a = tension; + } + for (t=0; t < steps; t++) { + s = t / steps; + h1 = (1 + 2*s)*Math.pow((1-s),2); + h2 = s*Math.pow((1-s),2); + h3 = Math.pow(s,2)*(3-2*s); + h4 = Math.pow(s,2)*(s-1); + + if (gd[i-1]) { + TiX = a * (gd[i+1][0] - gd[i-1][0]); + TiY = a * (gd[i+1][1] - gd[i-1][1]); + } else { + TiX = a * (gd[i+1][0] - gd[i][0]); + TiY = a * (gd[i+1][1] - gd[i][1]); + } + if (gd[i+2]) { + Ti1X = a * (gd[i+2][0] - gd[i][0]); + Ti1Y = a * (gd[i+2][1] - gd[i][1]); + } else { + Ti1X = a * (gd[i+1][0] - gd[i][0]); + Ti1Y = a * (gd[i+1][1] - gd[i][1]); + } + + pX = h1*gd[i][0] + h3*gd[i+1][0] + h2*TiX + h4*Ti1X; + pY = h1*gd[i][1] + h3*gd[i+1][1] + h2*TiY + h4*Ti1Y; + p = [pX, pY]; + + _smoothedData.push(p); + _smoothedPlotData.push([xp(pX), yp(pY)]); + } + } + _smoothedData.push(gd[l]); + _smoothedPlotData.push([xp(gd[l][0]), yp(gd[l][1])]); + + return [_smoothedData, _smoothedPlotData]; + } + + // setGridData + // converts the user data values to grid coordinates and stores them + // in the gridData array. + // Called with scope of a series. + $.jqplot.LineRenderer.prototype.setGridData = function(plot) { + // recalculate the grid data + var xp = this._xaxis.series_u2p; + var yp = this._yaxis.series_u2p; + var data = this._plotData; + var pdata = this._prevPlotData; + this.gridData = []; + this._prevGridData = []; + this.renderer._smoothedData = []; + this.renderer._smoothedPlotData = []; + this.renderer._hiBandGridData = []; + this.renderer._lowBandGridData = []; + this.renderer._hiBandSmoothedData = []; + this.renderer._lowBandSmoothedData = []; + var bands = this.renderer.bands; + var hasNull = false; + for (var i=0, l=data.length; i < l; i++) { + // if not a line series or if no nulls in data, push the converted point onto the array. + if (data[i][0] != null && data[i][1] != null) { + this.gridData.push([xp.call(this._xaxis, data[i][0]), yp.call(this._yaxis, data[i][1])]); + } + // else if there is a null, preserve it. + else if (data[i][0] == null) { + hasNull = true; + this.gridData.push([null, yp.call(this._yaxis, data[i][1])]); + } + else if (data[i][1] == null) { + hasNull = true; + this.gridData.push([xp.call(this._xaxis, data[i][0]), null]); + } + // if not a line series or if no nulls in data, push the converted point onto the array. + if (pdata[i] != null && pdata[i][0] != null && pdata[i][1] != null) { + this._prevGridData.push([xp.call(this._xaxis, pdata[i][0]), yp.call(this._yaxis, pdata[i][1])]); + } + // else if there is a null, preserve it. + else if (pdata[i] != null && pdata[i][0] == null) { + this._prevGridData.push([null, yp.call(this._yaxis, pdata[i][1])]); + } + else if (pdata[i] != null && pdata[i][0] != null && pdata[i][1] == null) { + this._prevGridData.push([xp.call(this._xaxis, pdata[i][0]), null]); + } + } + + // don't do smoothing or bands on broken lines. + if (hasNull) { + this.renderer.smooth = false; + if (this._type === 'line') { + bands.show = false; + } + } + + if (this._type === 'line' && bands.show) { + for (var i=0, l=bands.hiData.length; i<l; i++) { + this.renderer._hiBandGridData.push([xp.call(this._xaxis, bands.hiData[i][0]), yp.call(this._yaxis, bands.hiData[i][1])]); + } + for (var i=0, l=bands.lowData.length; i<l; i++) { + this.renderer._lowBandGridData.push([xp.call(this._xaxis, bands.lowData[i][0]), yp.call(this._yaxis, bands.lowData[i][1])]); + } + } + + // calculate smoothed data if enough points and no nulls + if (this._type === 'line' && this.renderer.smooth && this.gridData.length > 2) { + var ret; + if (this.renderer.constrainSmoothing) { + ret = computeConstrainedSmoothedData.call(this, this.gridData); + this.renderer._smoothedData = ret[0]; + this.renderer._smoothedPlotData = ret[1]; + + if (bands.show) { + ret = computeConstrainedSmoothedData.call(this, this.renderer._hiBandGridData); + this.renderer._hiBandSmoothedData = ret[0]; + ret = computeConstrainedSmoothedData.call(this, this.renderer._lowBandGridData); + this.renderer._lowBandSmoothedData = ret[0]; + } + + ret = null; + } + else { + ret = computeHermiteSmoothedData.call(this, this.gridData); + this.renderer._smoothedData = ret[0]; + this.renderer._smoothedPlotData = ret[1]; + + if (bands.show) { + ret = computeHermiteSmoothedData.call(this, this.renderer._hiBandGridData); + this.renderer._hiBandSmoothedData = ret[0]; + ret = computeHermiteSmoothedData.call(this, this.renderer._lowBandGridData); + this.renderer._lowBandSmoothedData = ret[0]; + } + + ret = null; + } + } + }; + + // makeGridData + // converts any arbitrary data values to grid coordinates and + // returns them. This method exists so that plugins can use a series' + // linerenderer to generate grid data points without overwriting the + // grid data associated with that series. + // Called with scope of a series. + $.jqplot.LineRenderer.prototype.makeGridData = function(data, plot) { + // recalculate the grid data + var xp = this._xaxis.series_u2p; + var yp = this._yaxis.series_u2p; + var gd = []; + var pgd = []; + this.renderer._smoothedData = []; + this.renderer._smoothedPlotData = []; + this.renderer._hiBandGridData = []; + this.renderer._lowBandGridData = []; + this.renderer._hiBandSmoothedData = []; + this.renderer._lowBandSmoothedData = []; + var bands = this.renderer.bands; + var hasNull = false; + for (var i=0; i<data.length; i++) { + // if not a line series or if no nulls in data, push the converted point onto the array. + if (data[i][0] != null && data[i][1] != null) { + gd.push([xp.call(this._xaxis, data[i][0]), yp.call(this._yaxis, data[i][1])]); + } + // else if there is a null, preserve it. + else if (data[i][0] == null) { + hasNull = true; + gd.push([null, yp.call(this._yaxis, data[i][1])]); + } + else if (data[i][1] == null) { + hasNull = true; + gd.push([xp.call(this._xaxis, data[i][0]), null]); + } + } + + // don't do smoothing or bands on broken lines. + if (hasNull) { + this.renderer.smooth = false; + if (this._type === 'line') { + bands.show = false; + } + } + + if (this._type === 'line' && bands.show) { + for (var i=0, l=bands.hiData.length; i<l; i++) { + this.renderer._hiBandGridData.push([xp.call(this._xaxis, bands.hiData[i][0]), yp.call(this._yaxis, bands.hiData[i][1])]); + } + for (var i=0, l=bands.lowData.length; i<l; i++) { + this.renderer._lowBandGridData.push([xp.call(this._xaxis, bands.lowData[i][0]), yp.call(this._yaxis, bands.lowData[i][1])]); + } + } + + if (this._type === 'line' && this.renderer.smooth && gd.length > 2) { + var ret; + if (this.renderer.constrainSmoothing) { + ret = computeConstrainedSmoothedData.call(this, gd); + this.renderer._smoothedData = ret[0]; + this.renderer._smoothedPlotData = ret[1]; + + if (bands.show) { + ret = computeConstrainedSmoothedData.call(this, this.renderer._hiBandGridData); + this.renderer._hiBandSmoothedData = ret[0]; + ret = computeConstrainedSmoothedData.call(this, this.renderer._lowBandGridData); + this.renderer._lowBandSmoothedData = ret[0]; + } + + ret = null; + } + else { + ret = computeHermiteSmoothedData.call(this, gd); + this.renderer._smoothedData = ret[0]; + this.renderer._smoothedPlotData = ret[1]; + + if (bands.show) { + ret = computeHermiteSmoothedData.call(this, this.renderer._hiBandGridData); + this.renderer._hiBandSmoothedData = ret[0]; + ret = computeHermiteSmoothedData.call(this, this.renderer._lowBandGridData); + this.renderer._lowBandSmoothedData = ret[0]; + } + + ret = null; + } + } + return gd; + }; + + + // called within scope of series. + $.jqplot.LineRenderer.prototype.draw = function(ctx, gd, options, plot) { + var i; + // get a copy of the options, so we don't modify the original object. + var opts = $.extend(true, {}, options); + var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow; + var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine; + var fill = (opts.fill != undefined) ? opts.fill : this.fill; + var fillAndStroke = (opts.fillAndStroke != undefined) ? opts.fillAndStroke : this.fillAndStroke; + var xmin, ymin, xmax, ymax; + ctx.save(); + if (gd.length) { + if (showLine) { + // if we fill, we'll have to add points to close the curve. + if (fill) { + if (this.fillToZero) { + // have to break line up into shapes at axis crossings + var negativeColor = this.negativeColor; + if (! this.useNegativeColors) { + negativeColor = opts.fillStyle; + } + var isnegative = false; + var posfs = opts.fillStyle; + + // if stoking line as well as filling, get a copy of line data. + if (fillAndStroke) { + var fasgd = gd.slice(0); + } + // if not stacked, fill down to axis + if (this.index == 0 || !this._stack) { + + var tempgd = []; + var pd = (this.renderer.smooth) ? this.renderer._smoothedPlotData : this._plotData; + this._areaPoints = []; + var pyzero = this._yaxis.series_u2p(this.fillToValue); + var pxzero = this._xaxis.series_u2p(this.fillToValue); + + opts.closePath = true; + + if (this.fillAxis == 'y') { + tempgd.push([gd[0][0], pyzero]); + this._areaPoints.push([gd[0][0], pyzero]); + + for (var i=0; i<gd.length-1; i++) { + tempgd.push(gd[i]); + this._areaPoints.push(gd[i]); + // do we have an axis crossing? + if (pd[i][1] * pd[i+1][1] < 0) { + if (pd[i][1] < 0) { + isnegative = true; + opts.fillStyle = negativeColor; + } + else { + isnegative = false; + opts.fillStyle = posfs; + } + + var xintercept = gd[i][0] + (gd[i+1][0] - gd[i][0]) * (pyzero-gd[i][1])/(gd[i+1][1] - gd[i][1]); + tempgd.push([xintercept, pyzero]); + this._areaPoints.push([xintercept, pyzero]); + // now draw this shape and shadow. + if (shadow) { + this.renderer.shadowRenderer.draw(ctx, tempgd, opts); + } + this.renderer.shapeRenderer.draw(ctx, tempgd, opts); + // now empty temp array and continue + tempgd = [[xintercept, pyzero]]; + // this._areaPoints = [[xintercept, pyzero]]; + } + } + if (pd[gd.length-1][1] < 0) { + isnegative = true; + opts.fillStyle = negativeColor; + } + else { + isnegative = false; + opts.fillStyle = posfs; + } + tempgd.push(gd[gd.length-1]); + this._areaPoints.push(gd[gd.length-1]); + tempgd.push([gd[gd.length-1][0], pyzero]); + this._areaPoints.push([gd[gd.length-1][0], pyzero]); + } + // now draw the last area. + if (shadow) { + this.renderer.shadowRenderer.draw(ctx, tempgd, opts); + } + this.renderer.shapeRenderer.draw(ctx, tempgd, opts); + + + // var gridymin = this._yaxis.series_u2p(0); + // // IE doesn't return new length on unshift + // gd.unshift([gd[0][0], gridymin]); + // len = gd.length; + // gd.push([gd[len - 1][0], gridymin]); + } + // if stacked, fill to line below + else { + var prev = this._prevGridData; + for (var i=prev.length; i>0; i--) { + gd.push(prev[i-1]); + // this._areaPoints.push(prev[i-1]); + } + if (shadow) { + this.renderer.shadowRenderer.draw(ctx, gd, opts); + } + this._areaPoints = gd; + this.renderer.shapeRenderer.draw(ctx, gd, opts); + } + } + ///////////////////////// + // Not filled to zero + //////////////////////// + else { + // if stoking line as well as filling, get a copy of line data. + if (fillAndStroke) { + var fasgd = gd.slice(0); + } + // if not stacked, fill down to axis + if (this.index == 0 || !this._stack) { + // var gridymin = this._yaxis.series_u2p(this._yaxis.min) - this.gridBorderWidth / 2; + var gridymin = ctx.canvas.height; + // IE doesn't return new length on unshift + gd.unshift([gd[0][0], gridymin]); + var len = gd.length; + gd.push([gd[len - 1][0], gridymin]); + } + // if stacked, fill to line below + else { + var prev = this._prevGridData; + for (var i=prev.length; i>0; i--) { + gd.push(prev[i-1]); + } + } + this._areaPoints = gd; + + if (shadow) { + this.renderer.shadowRenderer.draw(ctx, gd, opts); + } + + this.renderer.shapeRenderer.draw(ctx, gd, opts); + } + if (fillAndStroke) { + var fasopts = $.extend(true, {}, opts, {fill:false, closePath:false}); + this.renderer.shapeRenderer.draw(ctx, fasgd, fasopts); + ////////// + // TODO: figure out some way to do shadows nicely + // if (shadow) { + // this.renderer.shadowRenderer.draw(ctx, fasgd, fasopts); + // } + // now draw the markers + if (this.markerRenderer.show) { + if (this.renderer.smooth) { + fasgd = this.gridData; + } + for (i=0; i<fasgd.length; i++) { + this.markerRenderer.draw(fasgd[i][0], fasgd[i][1], ctx, opts.markerOptions); + } + } + } + } + else { + + if (this.renderer.bands.show) { + var bdat; + var bopts = $.extend(true, {}, opts); + if (this.renderer.bands.showLines) { + bdat = (this.renderer.smooth) ? this.renderer._hiBandSmoothedData : this.renderer._hiBandGridData; + this.renderer.shapeRenderer.draw(ctx, bdat, opts); + bdat = (this.renderer.smooth) ? this.renderer._lowBandSmoothedData : this.renderer._lowBandGridData; + this.renderer.shapeRenderer.draw(ctx, bdat, bopts); + } + + if (this.renderer.bands.fill) { + if (this.renderer.smooth) { + bdat = this.renderer._hiBandSmoothedData.concat(this.renderer._lowBandSmoothedData.reverse()); + } + else { + bdat = this.renderer._hiBandGridData.concat(this.renderer._lowBandGridData.reverse()); + } + this._areaPoints = bdat; + bopts.closePath = true; + bopts.fill = true; + bopts.fillStyle = this.renderer.bands.fillColor; + this.renderer.shapeRenderer.draw(ctx, bdat, bopts); + } + } + + if (shadow) { + this.renderer.shadowRenderer.draw(ctx, gd, opts); + } + + this.renderer.shapeRenderer.draw(ctx, gd, opts); + } + } + // calculate the bounding box + var xmin = xmax = ymin = ymax = null; + for (i=0; i<this._areaPoints.length; i++) { + var p = this._areaPoints[i]; + if (xmin > p[0] || xmin == null) { + xmin = p[0]; + } + if (ymax < p[1] || ymax == null) { + ymax = p[1]; + } + if (xmax < p[0] || xmax == null) { + xmax = p[0]; + } + if (ymin > p[1] || ymin == null) { + ymin = p[1]; + } + } + + if (this.type === 'line' && this.renderer.bands.show) { + ymax = this._yaxis.series_u2p(this.renderer.bands._min); + ymin = this._yaxis.series_u2p(this.renderer.bands._max); + } + + this._boundingBox = [[xmin, ymax], [xmax, ymin]]; + + // now draw the markers + if (this.markerRenderer.show && !fill) { + if (this.renderer.smooth) { + gd = this.gridData; + } + for (i=0; i<gd.length; i++) { + if (gd[i][0] != null && gd[i][1] != null) { + this.markerRenderer.draw(gd[i][0], gd[i][1], ctx, opts.markerOptions); + } + } + } + } + + ctx.restore(); + }; + + $.jqplot.LineRenderer.prototype.drawShadow = function(ctx, gd, options) { + // This is a no-op, shadows drawn with lines. + }; + + // called with scope of plot. + // make sure to not leave anything highlighted. + function postInit(target, data, options) { + for (var i=0; i<this.series.length; i++) { + if (this.series[i].renderer.constructor == $.jqplot.LineRenderer) { + // don't allow mouseover and mousedown at same time. + if (this.series[i].highlightMouseOver) { + this.series[i].highlightMouseDown = false; + } + } + } + } + + // called within context of plot + // create a canvas which we can draw on. + // insert it before the eventCanvas, so eventCanvas will still capture events. + function postPlotDraw() { + // Memory Leaks patch + if (this.plugins.lineRenderer && this.plugins.lineRenderer.highlightCanvas) { + this.plugins.lineRenderer.highlightCanvas.resetCanvas(); + this.plugins.lineRenderer.highlightCanvas = null; + } + + this.plugins.lineRenderer.highlightedSeriesIndex = null; + this.plugins.lineRenderer.highlightCanvas = new $.jqplot.GenericCanvas(); + + this.eventCanvas._elem.before(this.plugins.lineRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-lineRenderer-highlight-canvas', this._plotDimensions, this)); + this.plugins.lineRenderer.highlightCanvas.setContext(); + this.eventCanvas._elem.bind('mouseleave', {plot:this}, function (ev) { unhighlight(ev.data.plot); }); + } + + function highlight (plot, sidx, pidx, points) { + var s = plot.series[sidx]; + var canvas = plot.plugins.lineRenderer.highlightCanvas; + canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height); + s._highlightedPoint = pidx; + plot.plugins.lineRenderer.highlightedSeriesIndex = sidx; + var opts = {fillStyle: s.highlightColor}; + if (s.type === 'line' && s.renderer.bands.show) { + opts.fill = true; + opts.closePath = true; + } + s.renderer.shapeRenderer.draw(canvas._ctx, points, opts); + canvas = null; + } + + function unhighlight (plot) { + var canvas = plot.plugins.lineRenderer.highlightCanvas; + canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height); + for (var i=0; i<plot.series.length; i++) { + plot.series[i]._highlightedPoint = null; + } + plot.plugins.lineRenderer.highlightedSeriesIndex = null; + plot.target.trigger('jqplotDataUnhighlight'); + canvas = null; + } + + + function handleMove(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var evt1 = jQuery.Event('jqplotDataMouseOver'); + evt1.pageX = ev.pageX; + evt1.pageY = ev.pageY; + plot.target.trigger(evt1, ins); + if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.lineRenderer.highlightedSeriesIndex)) { + var evt = jQuery.Event('jqplotDataHighlight'); + evt.which = ev.which; + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + highlight (plot, neighbor.seriesIndex, neighbor.pointIndex, neighbor.points); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + } + + function handleMouseDown(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.lineRenderer.highlightedSeriesIndex)) { + var evt = jQuery.Event('jqplotDataHighlight'); + evt.which = ev.which; + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + highlight (plot, neighbor.seriesIndex, neighbor.pointIndex, neighbor.points); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + } + + function handleMouseUp(ev, gridpos, datapos, neighbor, plot) { + var idx = plot.plugins.lineRenderer.highlightedSeriesIndex; + if (idx != null && plot.series[idx].highlightMouseDown) { + unhighlight(plot); + } + } + + function handleClick(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var evt = jQuery.Event('jqplotDataClick'); + evt.which = ev.which; + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + } + } + + function handleRightClick(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var idx = plot.plugins.lineRenderer.highlightedSeriesIndex; + if (idx != null && plot.series[idx].highlightMouseDown) { + unhighlight(plot); + } + var evt = jQuery.Event('jqplotDataRightClick'); + evt.which = ev.which; + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + } + } + + + // class: $.jqplot.LinearAxisRenderer + // The default jqPlot axis renderer, creating a numeric axis. + $.jqplot.LinearAxisRenderer = function() { + }; + + // called with scope of axis object. + $.jqplot.LinearAxisRenderer.prototype.init = function(options){ + // prop: breakPoints + // EXPERIMENTAL!! Use at your own risk! + // Works only with linear axes and the default tick renderer. + // Array of [start, stop] points to create a broken axis. + // Broken axes have a "jump" in them, which is an immediate + // transition from a smaller value to a larger value. + // Currently, axis ticks MUST be manually assigned if using breakPoints + // by using the axis ticks array option. + this.breakPoints = null; + // prop: breakTickLabel + // Label to use at the axis break if breakPoints are specified. + this.breakTickLabel = "≈"; + // prop: drawBaseline + // True to draw the axis baseline. + this.drawBaseline = true; + // prop: baselineWidth + // width of the baseline in pixels. + this.baselineWidth = null; + // prop: baselineColor + // CSS color spec for the baseline. + this.baselineColor = null; + // prop: forceTickAt0 + // This will ensure that there is always a tick mark at 0. + // If data range is strictly positive or negative, + // this will force 0 to be inside the axis bounds unless + // the appropriate axis pad (pad, padMin or padMax) is set + // to 0, then this will force an axis min or max value at 0. + // This has know effect when any of the following options + // are set: autoscale, min, max, numberTicks or tickInterval. + this.forceTickAt0 = false; + // prop: forceTickAt100 + // This will ensure that there is always a tick mark at 100. + // If data range is strictly above or below 100, + // this will force 100 to be inside the axis bounds unless + // the appropriate axis pad (pad, padMin or padMax) is set + // to 0, then this will force an axis min or max value at 100. + // This has know effect when any of the following options + // are set: autoscale, min, max, numberTicks or tickInterval. + this.forceTickAt100 = false; + // prop: tickInset + // Controls the amount to inset the first and last ticks from + // the edges of the grid, in multiples of the tick interval. + // 0 is no inset, 0.5 is one half a tick interval, 1 is a full + // tick interval, etc. + this.tickInset = 0; + // prop: minorTicks + // Number of ticks to add between "major" ticks. + // Major ticks are ticks supplied by user or auto computed. + // Minor ticks cannot be created by user. + this.minorTicks = 0; + // prop: alignTicks + // true to align tick marks across opposed axes + // such as from the y2axis to yaxis. + this.alignTicks = false; + this._autoFormatString = ''; + this._overrideFormatString = false; + this._scalefact = 1.0; + $.extend(true, this, options); + if (this.breakPoints) { + if (!$.isArray(this.breakPoints)) { + this.breakPoints = null; + } + else if (this.breakPoints.length < 2 || this.breakPoints[1] <= this.breakPoints[0]) { + this.breakPoints = null; + } + } + if (this.numberTicks != null && this.numberTicks < 2) { + this.numberTicks = 2; + } + this.resetDataBounds(); + }; + + // called with scope of axis + $.jqplot.LinearAxisRenderer.prototype.draw = function(ctx, plot) { + if (this.show) { + // populate the axis label and value properties. + // createTicks is a method on the renderer, but + // call it within the scope of the axis. + this.renderer.createTicks.call(this, plot); + // fill a div with axes labels in the right direction. + // Need to pregenerate each axis to get it's bounds and + // position it and the labels correctly on the plot. + var dim=0; + var temp; + // Added for theming. + if (this._elem) { + // Memory Leaks patch + //this._elem.empty(); + this._elem.emptyForce(); + this._elem = null; + } + + this._elem = $(document.createElement('div')); + this._elem.addClass('jqplot-axis jqplot-'+this.name); + this._elem.css('position', 'absolute'); + + + if (this.name == 'xaxis' || this.name == 'x2axis') { + this._elem.width(this._plotDimensions.width); + } + else { + this._elem.height(this._plotDimensions.height); + } + + // create a _label object. + this.labelOptions.axis = this.name; + this._label = new this.labelRenderer(this.labelOptions); + if (this._label.show) { + var elem = this._label.draw(ctx, plot); + elem.appendTo(this._elem); + elem = null; + } + + var t = this._ticks; + var tick; + for (var i=0; i<t.length; i++) { + tick = t[i]; + if (tick.show && tick.showLabel && (!tick.isMinorTick || this.showMinorTicks)) { + this._elem.append(tick.draw(ctx, plot)); + } + } + tick = null; + t = null; + } + return this._elem; + }; + + // called with scope of an axis + $.jqplot.LinearAxisRenderer.prototype.reset = function() { + this.min = this._options.min; + this.max = this._options.max; + this.tickInterval = this._options.tickInterval; + this.numberTicks = this._options.numberTicks; + this._autoFormatString = ''; + if (this._overrideFormatString && this.tickOptions && this.tickOptions.formatString) { + this.tickOptions.formatString = ''; + } + + // this._ticks = this.__ticks; + }; + + // called with scope of axis + $.jqplot.LinearAxisRenderer.prototype.set = function() { + var dim = 0; + var temp; + var w = 0; + var h = 0; + var lshow = (this._label == null) ? false : this._label.show; + if (this.show) { + var t = this._ticks; + var tick; + for (var i=0; i<t.length; i++) { + tick = t[i]; + if (!tick._breakTick && tick.show && tick.showLabel && (!tick.isMinorTick || this.showMinorTicks)) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + temp = tick._elem.outerHeight(true); + } + else { + temp = tick._elem.outerWidth(true); + } + if (temp > dim) { + dim = temp; + } + } + } + tick = null; + t = null; + + if (lshow) { + w = this._label._elem.outerWidth(true); + h = this._label._elem.outerHeight(true); + } + if (this.name == 'xaxis') { + dim = dim + h; + this._elem.css({'height':dim+'px', left:'0px', bottom:'0px'}); + } + else if (this.name == 'x2axis') { + dim = dim + h; + this._elem.css({'height':dim+'px', left:'0px', top:'0px'}); + } + else if (this.name == 'yaxis') { + dim = dim + w; + this._elem.css({'width':dim+'px', left:'0px', top:'0px'}); + if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) { + this._label._elem.css('width', w+'px'); + } + } + else { + dim = dim + w; + this._elem.css({'width':dim+'px', right:'0px', top:'0px'}); + if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) { + this._label._elem.css('width', w+'px'); + } + } + } + }; + + // called with scope of axis + $.jqplot.LinearAxisRenderer.prototype.createTicks = function(plot) { + // we're are operating on an axis here + var ticks = this._ticks; + var userTicks = this.ticks; + var name = this.name; + // databounds were set on axis initialization. + var db = this._dataBounds; + var dim = (this.name.charAt(0) === 'x') ? this._plotDimensions.width : this._plotDimensions.height; + var interval; + var min, max; + var pos1, pos2; + var tt, i; + // get a copy of user's settings for min/max. + var userMin = this.min; + var userMax = this.max; + var userNT = this.numberTicks; + var userTI = this.tickInterval; + + var threshold = 30; + this._scalefact = (Math.max(dim, threshold+1) - threshold)/300.0; + + // if we already have ticks, use them. + // ticks must be in order of increasing value. + + if (userTicks.length) { + // ticks could be 1D or 2D array of [val, val, ,,,] or [[val, label], [val, label], ...] or mixed + for (i=0; i<userTicks.length; i++){ + var ut = userTicks[i]; + var t = new this.tickRenderer(this.tickOptions); + if ($.isArray(ut)) { + t.value = ut[0]; + if (this.breakPoints) { + if (ut[0] == this.breakPoints[0]) { + t.label = this.breakTickLabel; + t._breakTick = true; + t.showGridline = false; + t.showMark = false; + } + else if (ut[0] > this.breakPoints[0] && ut[0] <= this.breakPoints[1]) { + t.show = false; + t.showGridline = false; + t.label = ut[1]; + } + else { + t.label = ut[1]; + } + } + else { + t.label = ut[1]; + } + t.setTick(ut[0], this.name); + this._ticks.push(t); + } + + else if ($.isPlainObject(ut)) { + $.extend(true, t, ut); + t.axis = this.name; + this._ticks.push(t); + } + + else { + t.value = ut; + if (this.breakPoints) { + if (ut == this.breakPoints[0]) { + t.label = this.breakTickLabel; + t._breakTick = true; + t.showGridline = false; + t.showMark = false; + } + else if (ut > this.breakPoints[0] && ut <= this.breakPoints[1]) { + t.show = false; + t.showGridline = false; + } + } + t.setTick(ut, this.name); + this._ticks.push(t); + } + } + this.numberTicks = userTicks.length; + this.min = this._ticks[0].value; + this.max = this._ticks[this.numberTicks-1].value; + this.tickInterval = (this.max - this.min) / (this.numberTicks - 1); + } + + // we don't have any ticks yet, let's make some! + else { + if (name == 'xaxis' || name == 'x2axis') { + dim = this._plotDimensions.width; + } + else { + dim = this._plotDimensions.height; + } + + var _numberTicks = this.numberTicks; + + // if aligning this axis, use number of ticks from previous axis. + // Do I need to reset somehow if alignTicks is changed and then graph is replotted?? + if (this.alignTicks) { + if (this.name === 'x2axis' && plot.axes.xaxis.show) { + _numberTicks = plot.axes.xaxis.numberTicks; + } + else if (this.name.charAt(0) === 'y' && this.name !== 'yaxis' && this.name !== 'yMidAxis' && plot.axes.yaxis.show) { + _numberTicks = plot.axes.yaxis.numberTicks; + } + } + + min = ((this.min != null) ? this.min : db.min); + max = ((this.max != null) ? this.max : db.max); + + var range = max - min; + var rmin, rmax; + var temp; + + if (this.tickOptions == null || !this.tickOptions.formatString) { + this._overrideFormatString = true; + } + + // Doing complete autoscaling + if (this.min == null || this.max == null && this.tickInterval == null && !this.autoscale) { + // Check if user must have tick at 0 or 100 and ensure they are in range. + // The autoscaling algorithm will always place ticks at 0 and 100 if they are in range. + if (this.forceTickAt0) { + if (min > 0) { + min = 0; + } + if (max < 0) { + max = 0; + } + } + + if (this.forceTickAt100) { + if (min > 100) { + min = 100; + } + if (max < 100) { + max = 100; + } + } + + var keepMin = false, + keepMax = false; + + if (this.min != null) { + keepMin = true; + } + + else if (this.max != null) { + keepMax = true; + } + + // var threshold = 30; + // var tdim = Math.max(dim, threshold+1); + // this._scalefact = (tdim-threshold)/300.0; + var ret = $.jqplot.LinearTickGenerator(min, max, this._scalefact, _numberTicks, keepMin, keepMax); + // calculate a padded max and min, points should be less than these + // so that they aren't too close to the edges of the plot. + // User can adjust how much padding is allowed with pad, padMin and PadMax options. + // If min or max is set, don't pad that end of axis. + var tumin = (this.min != null) ? min : min + range*(this.padMin - 1); + var tumax = (this.max != null) ? max : max - range*(this.padMax - 1); + + // if they're equal, we shouldn't have to do anything, right? + // if (min <=tumin || max >= tumax) { + if (min <tumin || max > tumax) { + tumin = (this.min != null) ? min : min - range*(this.padMin - 1); + tumax = (this.max != null) ? max : max + range*(this.padMax - 1); + ret = $.jqplot.LinearTickGenerator(tumin, tumax, this._scalefact, _numberTicks, keepMin, keepMax); + } + + this.min = ret[0]; + this.max = ret[1]; + // if numberTicks specified, it should return the same. + this.numberTicks = ret[2]; + this._autoFormatString = ret[3]; + this.tickInterval = ret[4]; + } + + // User has specified some axis scale related option, can use auto algorithm + else { + + // if min and max are same, space them out a bit + if (min == max) { + var adj = 0.05; + if (min > 0) { + adj = Math.max(Math.log(min)/Math.LN10, 0.05); + } + min -= adj; + max += adj; + } + + // autoscale. Can't autoscale if min or max is supplied. + // Will use numberTicks and tickInterval if supplied. Ticks + // across multiple axes may not line up depending on how + // bars are to be plotted. + if (this.autoscale && this.min == null && this.max == null) { + var rrange, ti, margin; + var forceMinZero = false; + var forceZeroLine = false; + var intervals = {min:null, max:null, average:null, stddev:null}; + // if any series are bars, or if any are fill to zero, and if this + // is the axis to fill toward, check to see if we can start axis at zero. + for (var i=0; i<this._series.length; i++) { + var s = this._series[i]; + var faname = (s.fillAxis == 'x') ? s._xaxis.name : s._yaxis.name; + // check to see if this is the fill axis + if (this.name == faname) { + var vals = s._plotValues[s.fillAxis]; + var vmin = vals[0]; + var vmax = vals[0]; + for (var j=1; j<vals.length; j++) { + if (vals[j] < vmin) { + vmin = vals[j]; + } + else if (vals[j] > vmax) { + vmax = vals[j]; + } + } + var dp = (vmax - vmin) / vmax; + // is this sries a bar? + if (s.renderer.constructor == $.jqplot.BarRenderer) { + // if no negative values and could also check range. + if (vmin >= 0 && (s.fillToZero || dp > 0.1)) { + forceMinZero = true; + } + else { + forceMinZero = false; + if (s.fill && s.fillToZero && vmin < 0 && vmax > 0) { + forceZeroLine = true; + } + else { + forceZeroLine = false; + } + } + } + + // if not a bar and filling, use appropriate method. + else if (s.fill) { + if (vmin >= 0 && (s.fillToZero || dp > 0.1)) { + forceMinZero = true; + } + else if (vmin < 0 && vmax > 0 && s.fillToZero) { + forceMinZero = false; + forceZeroLine = true; + } + else { + forceMinZero = false; + forceZeroLine = false; + } + } + + // if not a bar and not filling, only change existing state + // if it doesn't make sense + else if (vmin < 0) { + forceMinZero = false; + } + } + } + + // check if we need make axis min at 0. + if (forceMinZero) { + // compute number of ticks + this.numberTicks = 2 + Math.ceil((dim-(this.tickSpacing-1))/this.tickSpacing); + this.min = 0; + userMin = 0; + // what order is this range? + // what tick interval does that give us? + ti = max/(this.numberTicks-1); + temp = Math.pow(10, Math.abs(Math.floor(Math.log(ti)/Math.LN10))); + if (ti/temp == parseInt(ti/temp, 10)) { + ti += temp; + } + this.tickInterval = Math.ceil(ti/temp) * temp; + this.max = this.tickInterval * (this.numberTicks - 1); + } + + // check if we need to make sure there is a tick at 0. + else if (forceZeroLine) { + // compute number of ticks + this.numberTicks = 2 + Math.ceil((dim-(this.tickSpacing-1))/this.tickSpacing); + var ntmin = Math.ceil(Math.abs(min)/range*(this.numberTicks-1)); + var ntmax = this.numberTicks - 1 - ntmin; + ti = Math.max(Math.abs(min/ntmin), Math.abs(max/ntmax)); + temp = Math.pow(10, Math.abs(Math.floor(Math.log(ti)/Math.LN10))); + this.tickInterval = Math.ceil(ti/temp) * temp; + this.max = this.tickInterval * ntmax; + this.min = -this.tickInterval * ntmin; + } + + // if nothing else, do autoscaling which will try to line up ticks across axes. + else { + if (this.numberTicks == null){ + if (this.tickInterval) { + this.numberTicks = 3 + Math.ceil(range / this.tickInterval); + } + else { + this.numberTicks = 2 + Math.ceil((dim-(this.tickSpacing-1))/this.tickSpacing); + } + } + + if (this.tickInterval == null) { + // get a tick interval + ti = range/(this.numberTicks - 1); + + if (ti < 1) { + temp = Math.pow(10, Math.abs(Math.floor(Math.log(ti)/Math.LN10))); + } + else { + temp = 1; + } + this.tickInterval = Math.ceil(ti*temp*this.pad)/temp; + } + else { + temp = 1 / this.tickInterval; + } + + // try to compute a nicer, more even tick interval + // temp = Math.pow(10, Math.floor(Math.log(ti)/Math.LN10)); + // this.tickInterval = Math.ceil(ti/temp) * temp; + rrange = this.tickInterval * (this.numberTicks - 1); + margin = (rrange - range)/2; + + if (this.min == null) { + this.min = Math.floor(temp*(min-margin))/temp; + } + if (this.max == null) { + this.max = this.min + rrange; + } + } + + // Compute a somewhat decent format string if it is needed. + // get precision of interval and determine a format string. + var sf = $.jqplot.getSignificantFigures(this.tickInterval); + + var fstr; + + // if we have only a whole number, use integer formatting + if (sf.digitsLeft >= sf.significantDigits) { + fstr = '%d'; + } + + else { + var temp = Math.max(0, 5 - sf.digitsLeft); + temp = Math.min(temp, sf.digitsRight); + fstr = '%.'+ temp + 'f'; + } + + this._autoFormatString = fstr; + } + + // Use the default algorithm which pads each axis to make the chart + // centered nicely on the grid. + else { + + rmin = (this.min != null) ? this.min : min - range*(this.padMin - 1); + rmax = (this.max != null) ? this.max : max + range*(this.padMax - 1); + range = rmax - rmin; + + if (this.numberTicks == null){ + // if tickInterval is specified by user, we will ignore computed maximum. + // max will be equal or greater to fit even # of ticks. + if (this.tickInterval != null) { + this.numberTicks = Math.ceil((rmax - rmin)/this.tickInterval)+1; + } + else if (dim > 100) { + this.numberTicks = parseInt(3+(dim-100)/75, 10); + } + else { + this.numberTicks = 2; + } + } + + if (this.tickInterval == null) { + this.tickInterval = range / (this.numberTicks-1); + } + + if (this.max == null) { + rmax = rmin + this.tickInterval*(this.numberTicks - 1); + } + if (this.min == null) { + rmin = rmax - this.tickInterval*(this.numberTicks - 1); + } + + // get precision of interval and determine a format string. + var sf = $.jqplot.getSignificantFigures(this.tickInterval); + + var fstr; + + // if we have only a whole number, use integer formatting + if (sf.digitsLeft >= sf.significantDigits) { + fstr = '%d'; + } + + else { + var temp = Math.max(0, 5 - sf.digitsLeft); + temp = Math.min(temp, sf.digitsRight); + fstr = '%.'+ temp + 'f'; + } + + + this._autoFormatString = fstr; + + this.min = rmin; + this.max = rmax; + } + + if (this.renderer.constructor == $.jqplot.LinearAxisRenderer && this._autoFormatString == '') { + // fix for misleading tick display with small range and low precision. + range = this.max - this.min; + // figure out precision + var temptick = new this.tickRenderer(this.tickOptions); + // use the tick formatString or, the default. + var fs = temptick.formatString || $.jqplot.config.defaultTickFormatString; + var fs = fs.match($.jqplot.sprintf.regex)[0]; + var precision = 0; + if (fs) { + if (fs.search(/[fFeEgGpP]/) > -1) { + var m = fs.match(/\%\.(\d{0,})?[eEfFgGpP]/); + if (m) { + precision = parseInt(m[1], 10); + } + else { + precision = 6; + } + } + else if (fs.search(/[di]/) > -1) { + precision = 0; + } + // fact will be <= 1; + var fact = Math.pow(10, -precision); + if (this.tickInterval < fact) { + // need to correct underrange + if (userNT == null && userTI == null) { + this.tickInterval = fact; + if (userMax == null && userMin == null) { + // this.min = Math.floor((this._dataBounds.min - this.tickInterval)/fact) * fact; + this.min = Math.floor(this._dataBounds.min/fact) * fact; + if (this.min == this._dataBounds.min) { + this.min = this._dataBounds.min - this.tickInterval; + } + // this.max = Math.ceil((this._dataBounds.max + this.tickInterval)/fact) * fact; + this.max = Math.ceil(this._dataBounds.max/fact) * fact; + if (this.max == this._dataBounds.max) { + this.max = this._dataBounds.max + this.tickInterval; + } + var n = (this.max - this.min)/this.tickInterval; + n = n.toFixed(11); + n = Math.ceil(n); + this.numberTicks = n + 1; + } + else if (userMax == null) { + // add one tick for top of range. + var n = (this._dataBounds.max - this.min) / this.tickInterval; + n = n.toFixed(11); + this.numberTicks = Math.ceil(n) + 2; + this.max = this.min + this.tickInterval * (this.numberTicks-1); + } + else if (userMin == null) { + // add one tick for bottom of range. + var n = (this.max - this._dataBounds.min) / this.tickInterval; + n = n.toFixed(11); + this.numberTicks = Math.ceil(n) + 2; + this.min = this.max - this.tickInterval * (this.numberTicks-1); + } + else { + // calculate a number of ticks so max is within axis scale + this.numberTicks = Math.ceil((userMax - userMin)/this.tickInterval) + 1; + // if user's min and max don't fit evenly in ticks, adjust. + // This takes care of cases such as user min set to 0, max set to 3.5 but tick + // format string set to %d (integer ticks) + this.min = Math.floor(userMin*Math.pow(10, precision))/Math.pow(10, precision); + this.max = Math.ceil(userMax*Math.pow(10, precision))/Math.pow(10, precision); + // this.max = this.min + this.tickInterval*(this.numberTicks-1); + this.numberTicks = Math.ceil((this.max - this.min)/this.tickInterval) + 1; + } + } + } + } + } + + } + + if (this._overrideFormatString && this._autoFormatString != '') { + this.tickOptions = this.tickOptions || {}; + this.tickOptions.formatString = this._autoFormatString; + } + + var t, to; + for (var i=0; i<this.numberTicks; i++){ + tt = this.min + i * this.tickInterval; + t = new this.tickRenderer(this.tickOptions); + // var t = new $.jqplot.AxisTickRenderer(this.tickOptions); + + t.setTick(tt, this.name); + this._ticks.push(t); + + if (i < this.numberTicks - 1) { + for (var j=0; j<this.minorTicks; j++) { + tt += this.tickInterval/(this.minorTicks+1); + to = $.extend(true, {}, this.tickOptions, {name:this.name, value:tt, label:'', isMinorTick:true}); + t = new this.tickRenderer(to); + this._ticks.push(t); + } + } + t = null; + } + } + + if (this.tickInset) { + this.min = this.min - this.tickInset * this.tickInterval; + this.max = this.max + this.tickInset * this.tickInterval; + } + + ticks = null; + }; + + // Used to reset just the values of the ticks and then repack, which will + // recalculate the positioning functions. It is assuemd that the + // number of ticks is the same and the values of the new array are at the + // proper interval. + // This method needs to be called with the scope of an axis object, like: + // + // > plot.axes.yaxis.renderer.resetTickValues.call(plot.axes.yaxis, yarr); + // + $.jqplot.LinearAxisRenderer.prototype.resetTickValues = function(opts) { + if ($.isArray(opts) && opts.length == this._ticks.length) { + var t; + for (var i=0; i<opts.length; i++) { + t = this._ticks[i]; + t.value = opts[i]; + t.label = t.formatter(t.formatString, opts[i]); + t.label = t.prefix + t.label; + t._elem.html(t.label); + } + t = null; + this.min = $.jqplot.arrayMin(opts); + this.max = $.jqplot.arrayMax(opts); + this.pack(); + } + // Not implemented yet. + // else if ($.isPlainObject(opts)) { + // + // } + }; + + // called with scope of axis + $.jqplot.LinearAxisRenderer.prototype.pack = function(pos, offsets) { + // Add defaults for repacking from resetTickValues function. + pos = pos || {}; + offsets = offsets || this._offsets; + + var ticks = this._ticks; + var max = this.max; + var min = this.min; + var offmax = offsets.max; + var offmin = offsets.min; + var lshow = (this._label == null) ? false : this._label.show; + + for (var p in pos) { + this._elem.css(p, pos[p]); + } + + this._offsets = offsets; + // pixellength will be + for x axes and - for y axes becasue pixels always measured from top left. + var pixellength = offmax - offmin; + var unitlength = max - min; + + // point to unit and unit to point conversions references to Plot DOM element top left corner. + if (this.breakPoints) { + unitlength = unitlength - this.breakPoints[1] + this.breakPoints[0]; + + this.p2u = function(p){ + return (p - offmin) * unitlength / pixellength + min; + }; + + this.u2p = function(u){ + if (u > this.breakPoints[0] && u < this.breakPoints[1]){ + u = this.breakPoints[0]; + } + if (u <= this.breakPoints[0]) { + return (u - min) * pixellength / unitlength + offmin; + } + else { + return (u - this.breakPoints[1] + this.breakPoints[0] - min) * pixellength / unitlength + offmin; + } + }; + + if (this.name.charAt(0) == 'x'){ + this.series_u2p = function(u){ + if (u > this.breakPoints[0] && u < this.breakPoints[1]){ + u = this.breakPoints[0]; + } + if (u <= this.breakPoints[0]) { + return (u - min) * pixellength / unitlength; + } + else { + return (u - this.breakPoints[1] + this.breakPoints[0] - min) * pixellength / unitlength; + } + }; + this.series_p2u = function(p){ + return p * unitlength / pixellength + min; + }; + } + + else { + this.series_u2p = function(u){ + if (u > this.breakPoints[0] && u < this.breakPoints[1]){ + u = this.breakPoints[0]; + } + if (u >= this.breakPoints[1]) { + return (u - max) * pixellength / unitlength; + } + else { + return (u + this.breakPoints[1] - this.breakPoints[0] - max) * pixellength / unitlength; + } + }; + this.series_p2u = function(p){ + return p * unitlength / pixellength + max; + }; + } + } + else { + this.p2u = function(p){ + return (p - offmin) * unitlength / pixellength + min; + }; + + this.u2p = function(u){ + return (u - min) * pixellength / unitlength + offmin; + }; + + if (this.name == 'xaxis' || this.name == 'x2axis'){ + this.series_u2p = function(u){ + return (u - min) * pixellength / unitlength; + }; + this.series_p2u = function(p){ + return p * unitlength / pixellength + min; + }; + } + + else { + this.series_u2p = function(u){ + return (u - max) * pixellength / unitlength; + }; + this.series_p2u = function(p){ + return p * unitlength / pixellength + max; + }; + } + } + + if (this.show) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + for (var i=0; i<ticks.length; i++) { + var t = ticks[i]; + if (t.show && t.showLabel) { + var shim; + + if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) { + // will need to adjust auto positioning based on which axis this is. + var temp = (this.name == 'xaxis') ? 1 : -1; + switch (t.labelPosition) { + case 'auto': + // position at end + if (temp * t.angle < 0) { + shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + } + // position at start + else { + shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2; + } + break; + case 'end': + shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + break; + case 'start': + shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2; + break; + case 'middle': + shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + break; + default: + shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + break; + } + } + else { + shim = -t.getWidth()/2; + } + var val = this.u2p(t.value) + shim + 'px'; + t._elem.css('left', val); + t.pack(); + } + } + if (lshow) { + var w = this._label._elem.outerWidth(true); + this._label._elem.css('left', offmin + pixellength/2 - w/2 + 'px'); + if (this.name == 'xaxis') { + this._label._elem.css('bottom', '0px'); + } + else { + this._label._elem.css('top', '0px'); + } + this._label.pack(); + } + } + else { + for (var i=0; i<ticks.length; i++) { + var t = ticks[i]; + if (t.show && t.showLabel) { + var shim; + if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) { + // will need to adjust auto positioning based on which axis this is. + var temp = (this.name == 'yaxis') ? 1 : -1; + switch (t.labelPosition) { + case 'auto': + // position at end + case 'end': + if (temp * t.angle < 0) { + shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2; + } + else { + shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2; + } + break; + case 'start': + if (t.angle > 0) { + shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2; + } + else { + shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2; + } + break; + case 'middle': + // if (t.angle > 0) { + // shim = -t.getHeight()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + // } + // else { + // shim = -t.getHeight()/2 - t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2; + // } + shim = -t.getHeight()/2; + break; + default: + shim = -t.getHeight()/2; + break; + } + } + else { + shim = -t.getHeight()/2; + } + + var val = this.u2p(t.value) + shim + 'px'; + t._elem.css('top', val); + t.pack(); + } + } + if (lshow) { + var h = this._label._elem.outerHeight(true); + this._label._elem.css('top', offmax - pixellength/2 - h/2 + 'px'); + if (this.name == 'yaxis') { + this._label._elem.css('left', '0px'); + } + else { + this._label._elem.css('right', '0px'); + } + this._label.pack(); + } + } + } + + ticks = null; + }; + + + /** + * The following code was generaously given to me a while back by Scott Prahl. + * He did a good job at computing axes min, max and number of ticks for the + * case where the user has not set any scale related parameters (tickInterval, + * numberTicks, min or max). I had ignored this use case for a long time, + * focusing on the more difficult case where user has set some option controlling + * tick generation. Anyway, about time I got this into jqPlot. + * Thanks Scott!! + */ + + /** + * Copyright (c) 2010 Scott Prahl + * The next three routines are currently available for use in all personal + * or commercial projects under both the MIT and GPL version 2.0 licenses. + * This means that you can choose the license that best suits your project + * and use it accordingly. + */ + + // A good format string depends on the interval. If the interval is greater + // than 1 then there is no need to show any decimal digits. If it is < 1.0, then + // use the magnitude of the interval to determine the number of digits to show. + function bestFormatString (interval) + { + var fstr; + interval = Math.abs(interval); + if (interval >= 10) { + fstr = '%d'; + } + + else if (interval > 1) { + if (interval === parseInt(interval, 10)) { + fstr = '%d'; + } + else { + fstr = '%.1f'; + } + } + + else { + var expv = -Math.floor(Math.log(interval)/Math.LN10); + fstr = '%.' + expv + 'f'; + } + + return fstr; + } + + var _factors = [0.1, 0.2, 0.3, 0.4, 0.5, 0.8, 1, 2, 3, 4, 5]; + + var _getLowerFactor = function(f) { + var i = _factors.indexOf(f); + if (i > 0) { + return _factors[i-1]; + } + else { + return _factors[_factors.length - 1] / 100; + } + }; + + var _getHigherFactor = function(f) { + var i = _factors.indexOf(f); + if (i < _factors.length-1) { + return _factors[i+1]; + } + else { + return _factors[0] * 100; + } + }; + + // Given a fixed minimum and maximum and a target number ot ticks + // figure out the best interval and + // return min, max, number ticks, format string and tick interval + function bestConstrainedInterval(min, max, nttarget) { + // run through possible number to ticks and see which interval is best + var low = Math.floor(nttarget/2); + var hi = Math.ceil(nttarget*1.5); + var badness = Number.MAX_VALUE; + var r = (max - min); + var temp; + var sd; + var bestNT; + var gsf = $.jqplot.getSignificantFigures; + var fsd; + var fs; + var currentNT; + var bestPrec; + + for (var i=0, l=hi-low+1; i<l; i++) { + currentNT = low + i; + temp = r/(currentNT-1); + sd = gsf(temp); + + temp = Math.abs(nttarget - currentNT) + sd.digitsRight; + if (temp < badness) { + badness = temp; + bestNT = currentNT; + bestPrec = sd.digitsRight; + } + else if (temp === badness) { + // let nicer ticks trump number ot ticks + if (sd.digitsRight < bestPrec) { + bestNT = currentNT; + bestPrec = sd.digitsRight; + } + } + + } + + fsd = Math.max(bestPrec, Math.max(gsf(min).digitsRight, gsf(max).digitsRight)); + if (fsd === 0) { + fs = '%d'; + } + else { + fs = '%.' + fsd + 'f'; + } + temp = r / (bestNT - 1); + // min, max, number ticks, format string, tick interval + return [min, max, bestNT, fs, temp]; + } + + // This will return an interval of form 2 * 10^n, 5 * 10^n or 10 * 10^n + // it is based soley on the range and number of ticks. So if user specifies + // number of ticks, use this. + function bestInterval(range, numberTicks) { + numberTicks = numberTicks || 7; + var minimum = range / (numberTicks - 1); + var magnitude = Math.pow(10, Math.floor(Math.log(minimum) / Math.LN10)); + var residual = minimum / magnitude; + var interval; + // "nicest" ranges are 1, 2, 5 or powers of these. + // for magnitudes below 1, only allow these. + if (magnitude < 1) { + if (residual > 5) { + interval = 10 * magnitude; + } + else if (residual > 2) { + interval = 5 * magnitude; + } + else if (residual > 1) { + interval = 2 * magnitude; + } + else { + interval = magnitude; + } + } + // for large ranges (whole integers), allow intervals like 3, 4 or powers of these. + // this helps a lot with poor choices for number of ticks. + else { + if (residual > 5) { + interval = 10 * magnitude; + } + else if (residual > 4) { + interval = 5 * magnitude; + } + else if (residual > 3) { + interval = 4 * magnitude; + } + else if (residual > 2) { + interval = 3 * magnitude; + } + else if (residual > 1) { + interval = 2 * magnitude; + } + else { + interval = magnitude; + } + } + + return interval; + } + + // This will return an interval of form 2 * 10^n, 5 * 10^n or 10 * 10^n + // it is based soley on the range of data, number of ticks must be computed later. + function bestLinearInterval(range, scalefact) { + scalefact = scalefact || 1; + var expv = Math.floor(Math.log(range)/Math.LN10); + var magnitude = Math.pow(10, expv); + // 0 < f < 10 + var f = range / magnitude; + var fact; + // for large plots, scalefact will decrease f and increase number of ticks. + // for small plots, scalefact will increase f and decrease number of ticks. + f = f/scalefact; + + // for large plots, smaller interval, more ticks. + if (f<=0.38) { + fact = 0.1; + } + else if (f<=1.6) { + fact = 0.2; + } + else if (f<=4.0) { + fact = 0.5; + } + else if (f<=8.0) { + fact = 1.0; + } + // for very small plots, larger interval, less ticks in number ticks + else if (f<=16.0) { + fact = 2; + } + else { + fact = 5; + } + + return fact*magnitude; + } + + function bestLinearComponents(range, scalefact) { + var expv = Math.floor(Math.log(range)/Math.LN10); + var magnitude = Math.pow(10, expv); + // 0 < f < 10 + var f = range / magnitude; + var interval; + var fact; + // for large plots, scalefact will decrease f and increase number of ticks. + // for small plots, scalefact will increase f and decrease number of ticks. + f = f/scalefact; + + // for large plots, smaller interval, more ticks. + if (f<=0.38) { + fact = 0.1; + } + else if (f<=1.6) { + fact = 0.2; + } + else if (f<=4.0) { + fact = 0.5; + } + else if (f<=8.0) { + fact = 1.0; + } + // for very small plots, larger interval, less ticks in number ticks + else if (f<=16.0) { + fact = 2; + } + // else if (f<=20.0) { + // fact = 3; + // } + // else if (f<=24.0) { + // fact = 4; + // } + else { + fact = 5; + } + + interval = fact * magnitude; + + return [interval, fact, magnitude]; + } + + // Given the min and max for a dataset, return suitable endpoints + // for the graphing, a good number for the number of ticks, and a + // format string so that extraneous digits are not displayed. + // returned is an array containing [min, max, nTicks, format] + $.jqplot.LinearTickGenerator = function(axis_min, axis_max, scalefact, numberTicks, keepMin, keepMax) { + // Set to preserve EITHER min OR max. + // If min is preserved, max must be free. + keepMin = (keepMin === null) ? false : keepMin; + keepMax = (keepMax === null || keepMin) ? false : keepMax; + // if endpoints are equal try to include zero otherwise include one + if (axis_min === axis_max) { + axis_max = (axis_max) ? 0 : 1; + } + + scalefact = scalefact || 1.0; + + // make sure range is positive + if (axis_max < axis_min) { + var a = axis_max; + axis_max = axis_min; + axis_min = a; + } + + var r = []; + var ss = bestLinearInterval(axis_max - axis_min, scalefact); + + var gsf = $.jqplot.getSignificantFigures; + + if (numberTicks == null) { + + // Figure out the axis min, max and number of ticks + // the min and max will be some multiple of the tick interval, + // 1*10^n, 2*10^n or 5*10^n. This gaurantees that, if the + // axis min is negative, 0 will be a tick. + if (!keepMin && !keepMax) { + r[0] = Math.floor(axis_min / ss) * ss; // min + r[1] = Math.ceil(axis_max / ss) * ss; // max + r[2] = Math.round((r[1]-r[0])/ss+1.0); // number of ticks + r[3] = bestFormatString(ss); // format string + r[4] = ss; // tick Interval + } + + else if (keepMin) { + r[0] = axis_min; // min + r[2] = Math.ceil((axis_max - axis_min) / ss + 1.0); // number of ticks + r[1] = axis_min + (r[2] - 1) * ss; // max + var digitsMin = gsf(axis_min).digitsRight; + var digitsSS = gsf(ss).digitsRight; + if (digitsMin < digitsSS) { + r[3] = bestFormatString(ss); // format string + } + else { + r[3] = '%.' + digitsMin + 'f'; + } + r[4] = ss; // tick Interval + } + + else if (keepMax) { + r[1] = axis_max; // max + r[2] = Math.ceil((axis_max - axis_min) / ss + 1.0); // number of ticks + r[0] = axis_max - (r[2] - 1) * ss; // min + var digitsMax = gsf(axis_max).digitsRight; + var digitsSS = gsf(ss).digitsRight; + if (digitsMax < digitsSS) { + r[3] = bestFormatString(ss); // format string + } + else { + r[3] = '%.' + digitsMax + 'f'; + } + r[4] = ss; // tick Interval + } + } + + else { + var tempr = []; + + // Figure out the axis min, max and number of ticks + // the min and max will be some multiple of the tick interval, + // 1*10^n, 2*10^n or 5*10^n. This gaurantees that, if the + // axis min is negative, 0 will be a tick. + tempr[0] = Math.floor(axis_min / ss) * ss; // min + tempr[1] = Math.ceil(axis_max / ss) * ss; // max + tempr[2] = Math.round((tempr[1]-tempr[0])/ss+1.0); // number of ticks + tempr[3] = bestFormatString(ss); // format string + tempr[4] = ss; // tick Interval + + // first, see if we happen to get the right number of ticks + if (tempr[2] === numberTicks) { + r = tempr; + } + + else { + + var newti = bestInterval(tempr[1] - tempr[0], numberTicks); + + r[0] = tempr[0]; // min + r[2] = numberTicks; // number of ticks + r[4] = newti; // tick interval + r[3] = bestFormatString(newti); // format string + r[1] = r[0] + (r[2] - 1) * r[4]; // max + } + } + + return r; + }; + + $.jqplot.LinearTickGenerator.bestLinearInterval = bestLinearInterval; + $.jqplot.LinearTickGenerator.bestInterval = bestInterval; + $.jqplot.LinearTickGenerator.bestLinearComponents = bestLinearComponents; + $.jqplot.LinearTickGenerator.bestConstrainedInterval = bestConstrainedInterval; + + + // class: $.jqplot.MarkerRenderer + // The default jqPlot marker renderer, rendering the points on the line. + $.jqplot.MarkerRenderer = function(options){ + // Group: Properties + + // prop: show + // wether or not to show the marker. + this.show = true; + // prop: style + // One of diamond, circle, square, x, plus, dash, filledDiamond, filledCircle, filledSquare + this.style = 'filledCircle'; + // prop: lineWidth + // size of the line for non-filled markers. + this.lineWidth = 2; + // prop: size + // Size of the marker (diameter or circle, length of edge of square, etc.) + this.size = 9.0; + // prop: color + // color of marker. Will be set to color of series by default on init. + this.color = '#666666'; + // prop: shadow + // wether or not to draw a shadow on the line + this.shadow = true; + // prop: shadowAngle + // Shadow angle in degrees + this.shadowAngle = 45; + // prop: shadowOffset + // Shadow offset from line in pixels + this.shadowOffset = 1; + // prop: shadowDepth + // Number of times shadow is stroked, each stroke offset shadowOffset from the last. + this.shadowDepth = 3; + // prop: shadowAlpha + // Alpha channel transparency of shadow. 0 = transparent. + this.shadowAlpha = '0.07'; + // prop: shadowRenderer + // Renderer that will draws the shadows on the marker. + this.shadowRenderer = new $.jqplot.ShadowRenderer(); + // prop: shapeRenderer + // Renderer that will draw the marker. + this.shapeRenderer = new $.jqplot.ShapeRenderer(); + + $.extend(true, this, options); + }; + + $.jqplot.MarkerRenderer.prototype.init = function(options) { + $.extend(true, this, options); + var sdopt = {angle:this.shadowAngle, offset:this.shadowOffset, alpha:this.shadowAlpha, lineWidth:this.lineWidth, depth:this.shadowDepth, closePath:true}; + if (this.style.indexOf('filled') != -1) { + sdopt.fill = true; + } + if (this.style.indexOf('ircle') != -1) { + sdopt.isarc = true; + sdopt.closePath = false; + } + this.shadowRenderer.init(sdopt); + + var shopt = {fill:false, isarc:false, strokeStyle:this.color, fillStyle:this.color, lineWidth:this.lineWidth, closePath:true}; + if (this.style.indexOf('filled') != -1) { + shopt.fill = true; + } + if (this.style.indexOf('ircle') != -1) { + shopt.isarc = true; + shopt.closePath = false; + } + this.shapeRenderer.init(shopt); + }; + + $.jqplot.MarkerRenderer.prototype.drawDiamond = function(x, y, ctx, fill, options) { + var stretch = 1.2; + var dx = this.size/2/stretch; + var dy = this.size/2*stretch; + var points = [[x-dx, y], [x, y+dy], [x+dx, y], [x, y-dy]]; + if (this.shadow) { + this.shadowRenderer.draw(ctx, points); + } + this.shapeRenderer.draw(ctx, points, options); + }; + + $.jqplot.MarkerRenderer.prototype.drawPlus = function(x, y, ctx, fill, options) { + var stretch = 1.0; + var dx = this.size/2*stretch; + var dy = this.size/2*stretch; + var points1 = [[x, y-dy], [x, y+dy]]; + var points2 = [[x+dx, y], [x-dx, y]]; + var opts = $.extend(true, {}, this.options, {closePath:false}); + if (this.shadow) { + this.shadowRenderer.draw(ctx, points1, {closePath:false}); + this.shadowRenderer.draw(ctx, points2, {closePath:false}); + } + this.shapeRenderer.draw(ctx, points1, opts); + this.shapeRenderer.draw(ctx, points2, opts); + }; + + $.jqplot.MarkerRenderer.prototype.drawX = function(x, y, ctx, fill, options) { + var stretch = 1.0; + var dx = this.size/2*stretch; + var dy = this.size/2*stretch; + var opts = $.extend(true, {}, this.options, {closePath:false}); + var points1 = [[x-dx, y-dy], [x+dx, y+dy]]; + var points2 = [[x-dx, y+dy], [x+dx, y-dy]]; + if (this.shadow) { + this.shadowRenderer.draw(ctx, points1, {closePath:false}); + this.shadowRenderer.draw(ctx, points2, {closePath:false}); + } + this.shapeRenderer.draw(ctx, points1, opts); + this.shapeRenderer.draw(ctx, points2, opts); + }; + + $.jqplot.MarkerRenderer.prototype.drawDash = function(x, y, ctx, fill, options) { + var stretch = 1.0; + var dx = this.size/2*stretch; + var dy = this.size/2*stretch; + var points = [[x-dx, y], [x+dx, y]]; + if (this.shadow) { + this.shadowRenderer.draw(ctx, points); + } + this.shapeRenderer.draw(ctx, points, options); + }; + + $.jqplot.MarkerRenderer.prototype.drawLine = function(p1, p2, ctx, fill, options) { + var points = [p1, p2]; + if (this.shadow) { + this.shadowRenderer.draw(ctx, points); + } + this.shapeRenderer.draw(ctx, points, options); + }; + + $.jqplot.MarkerRenderer.prototype.drawSquare = function(x, y, ctx, fill, options) { + var stretch = 1.0; + var dx = this.size/2/stretch; + var dy = this.size/2*stretch; + var points = [[x-dx, y-dy], [x-dx, y+dy], [x+dx, y+dy], [x+dx, y-dy]]; + if (this.shadow) { + this.shadowRenderer.draw(ctx, points); + } + this.shapeRenderer.draw(ctx, points, options); + }; + + $.jqplot.MarkerRenderer.prototype.drawCircle = function(x, y, ctx, fill, options) { + var radius = this.size/2; + var end = 2*Math.PI; + var points = [x, y, radius, 0, end, true]; + if (this.shadow) { + this.shadowRenderer.draw(ctx, points); + } + this.shapeRenderer.draw(ctx, points, options); + }; + + $.jqplot.MarkerRenderer.prototype.draw = function(x, y, ctx, options) { + options = options || {}; + // hack here b/c shape renderer uses canvas based color style options + // and marker uses css style names. + if (options.show == null || options.show != false) { + if (options.color && !options.fillStyle) { + options.fillStyle = options.color; + } + if (options.color && !options.strokeStyle) { + options.strokeStyle = options.color; + } + switch (this.style) { + case 'diamond': + this.drawDiamond(x,y,ctx, false, options); + break; + case 'filledDiamond': + this.drawDiamond(x,y,ctx, true, options); + break; + case 'circle': + this.drawCircle(x,y,ctx, false, options); + break; + case 'filledCircle': + this.drawCircle(x,y,ctx, true, options); + break; + case 'square': + this.drawSquare(x,y,ctx, false, options); + break; + case 'filledSquare': + this.drawSquare(x,y,ctx, true, options); + break; + case 'x': + this.drawX(x,y,ctx, true, options); + break; + case 'plus': + this.drawPlus(x,y,ctx, true, options); + break; + case 'dash': + this.drawDash(x,y,ctx, true, options); + break; + case 'line': + this.drawLine(x, y, ctx, false, options); + break; + default: + this.drawDiamond(x,y,ctx, false, options); + break; + } + } + }; + + // class: $.jqplot.shadowRenderer + // The default jqPlot shadow renderer, rendering shadows behind shapes. + $.jqplot.ShadowRenderer = function(options){ + // Group: Properties + + // prop: angle + // Angle of the shadow in degrees. Measured counter-clockwise from the x axis. + this.angle = 45; + // prop: offset + // Pixel offset at the given shadow angle of each shadow stroke from the last stroke. + this.offset = 1; + // prop: alpha + // alpha transparency of shadow stroke. + this.alpha = 0.07; + // prop: lineWidth + // width of the shadow line stroke. + this.lineWidth = 1.5; + // prop: lineJoin + // How line segments of the shadow are joined. + this.lineJoin = 'miter'; + // prop: lineCap + // how ends of the shadow line are rendered. + this.lineCap = 'round'; + // prop; closePath + // whether line path segment is closed upon itself. + this.closePath = false; + // prop: fill + // whether to fill the shape. + this.fill = false; + // prop: depth + // how many times the shadow is stroked. Each stroke will be offset by offset at angle degrees. + this.depth = 3; + this.strokeStyle = 'rgba(0,0,0,0.1)'; + // prop: isarc + // wether the shadow is an arc or not. + this.isarc = false; + + $.extend(true, this, options); + }; + + $.jqplot.ShadowRenderer.prototype.init = function(options) { + $.extend(true, this, options); + }; + + // function: draw + // draws an transparent black (i.e. gray) shadow. + // + // ctx - canvas drawing context + // points - array of points or [x, y, radius, start angle (rad), end angle (rad)] + $.jqplot.ShadowRenderer.prototype.draw = function(ctx, points, options) { + ctx.save(); + var opts = (options != null) ? options : {}; + var fill = (opts.fill != null) ? opts.fill : this.fill; + var fillRect = (opts.fillRect != null) ? opts.fillRect : this.fillRect; + var closePath = (opts.closePath != null) ? opts.closePath : this.closePath; + var offset = (opts.offset != null) ? opts.offset : this.offset; + var alpha = (opts.alpha != null) ? opts.alpha : this.alpha; + var depth = (opts.depth != null) ? opts.depth : this.depth; + var isarc = (opts.isarc != null) ? opts.isarc : this.isarc; + var linePattern = (opts.linePattern != null) ? opts.linePattern : this.linePattern; + ctx.lineWidth = (opts.lineWidth != null) ? opts.lineWidth : this.lineWidth; + ctx.lineJoin = (opts.lineJoin != null) ? opts.lineJoin : this.lineJoin; + ctx.lineCap = (opts.lineCap != null) ? opts.lineCap : this.lineCap; + ctx.strokeStyle = opts.strokeStyle || this.strokeStyle || 'rgba(0,0,0,'+alpha+')'; + ctx.fillStyle = opts.fillStyle || this.fillStyle || 'rgba(0,0,0,'+alpha+')'; + for (var j=0; j<depth; j++) { + var ctxPattern = $.jqplot.LinePattern(ctx, linePattern); + ctx.translate(Math.cos(this.angle*Math.PI/180)*offset, Math.sin(this.angle*Math.PI/180)*offset); + ctxPattern.beginPath(); + if (isarc) { + ctx.arc(points[0], points[1], points[2], points[3], points[4], true); + } + else if (fillRect) { + if (fillRect) { + ctx.fillRect(points[0], points[1], points[2], points[3]); + } + } + else if (points && points.length){ + var move = true; + for (var i=0; i<points.length; i++) { + // skip to the first non-null point and move to it. + if (points[i][0] != null && points[i][1] != null) { + if (move) { + ctxPattern.moveTo(points[i][0], points[i][1]); + move = false; + } + else { + ctxPattern.lineTo(points[i][0], points[i][1]); + } + } + else { + move = true; + } + } + + } + if (closePath) { + ctxPattern.closePath(); + } + if (fill) { + ctx.fill(); + } + else { + ctx.stroke(); + } + } + ctx.restore(); + }; + + // class: $.jqplot.shapeRenderer + // The default jqPlot shape renderer. Given a set of points will + // plot them and either stroke a line (fill = false) or fill them (fill = true). + // If a filled shape is desired, closePath = true must also be set to close + // the shape. + $.jqplot.ShapeRenderer = function(options){ + + this.lineWidth = 1.5; + // prop: linePattern + // line pattern 'dashed', 'dotted', 'solid', some combination + // of '-' and '.' characters such as '.-.' or a numerical array like + // [draw, skip, draw, skip, ...] such as [1, 10] to draw a dotted line, + // [1, 10, 20, 10] to draw a dot-dash line, and so on. + this.linePattern = 'solid'; + // prop: lineJoin + // How line segments of the shadow are joined. + this.lineJoin = 'miter'; + // prop: lineCap + // how ends of the shadow line are rendered. + this.lineCap = 'round'; + // prop; closePath + // whether line path segment is closed upon itself. + this.closePath = false; + // prop: fill + // whether to fill the shape. + this.fill = false; + // prop: isarc + // wether the shadow is an arc or not. + this.isarc = false; + // prop: fillRect + // true to draw shape as a filled rectangle. + this.fillRect = false; + // prop: strokeRect + // true to draw shape as a stroked rectangle. + this.strokeRect = false; + // prop: clearRect + // true to cear a rectangle. + this.clearRect = false; + // prop: strokeStyle + // css color spec for the stoke style + this.strokeStyle = '#999999'; + // prop: fillStyle + // css color spec for the fill style. + this.fillStyle = '#999999'; + + $.extend(true, this, options); + }; + + $.jqplot.ShapeRenderer.prototype.init = function(options) { + $.extend(true, this, options); + }; + + // function: draw + // draws the shape. + // + // ctx - canvas drawing context + // points - array of points for shapes or + // [x, y, width, height] for rectangles or + // [x, y, radius, start angle (rad), end angle (rad)] for circles and arcs. + $.jqplot.ShapeRenderer.prototype.draw = function(ctx, points, options) { + ctx.save(); + var opts = (options != null) ? options : {}; + var fill = (opts.fill != null) ? opts.fill : this.fill; + var closePath = (opts.closePath != null) ? opts.closePath : this.closePath; + var fillRect = (opts.fillRect != null) ? opts.fillRect : this.fillRect; + var strokeRect = (opts.strokeRect != null) ? opts.strokeRect : this.strokeRect; + var clearRect = (opts.clearRect != null) ? opts.clearRect : this.clearRect; + var isarc = (opts.isarc != null) ? opts.isarc : this.isarc; + var linePattern = (opts.linePattern != null) ? opts.linePattern : this.linePattern; + var ctxPattern = $.jqplot.LinePattern(ctx, linePattern); + ctx.lineWidth = opts.lineWidth || this.lineWidth; + ctx.lineJoin = opts.lineJoin || this.lineJoin; + ctx.lineCap = opts.lineCap || this.lineCap; + ctx.strokeStyle = (opts.strokeStyle || opts.color) || this.strokeStyle; + ctx.fillStyle = opts.fillStyle || this.fillStyle; + ctx.beginPath(); + if (isarc) { + ctx.arc(points[0], points[1], points[2], points[3], points[4], true); + if (closePath) { + ctx.closePath(); + } + if (fill) { + ctx.fill(); + } + else { + ctx.stroke(); + } + ctx.restore(); + return; + } + else if (clearRect) { + ctx.clearRect(points[0], points[1], points[2], points[3]); + ctx.restore(); + return; + } + else if (fillRect || strokeRect) { + if (fillRect) { + ctx.fillRect(points[0], points[1], points[2], points[3]); + } + if (strokeRect) { + ctx.strokeRect(points[0], points[1], points[2], points[3]); + ctx.restore(); + return; + } + } + else if (points && points.length){ + var move = true; + for (var i=0; i<points.length; i++) { + // skip to the first non-null point and move to it. + if (points[i][0] != null && points[i][1] != null) { + if (move) { + ctxPattern.moveTo(points[i][0], points[i][1]); + move = false; + } + else { + ctxPattern.lineTo(points[i][0], points[i][1]); + } + } + else { + move = true; + } + } + if (closePath) { + ctxPattern.closePath(); + } + if (fill) { + ctx.fill(); + } + else { + ctx.stroke(); + } + } + ctx.restore(); + }; + + // class $.jqplot.TableLegendRenderer + // The default legend renderer for jqPlot. + $.jqplot.TableLegendRenderer = function(){ + // + }; + + $.jqplot.TableLegendRenderer.prototype.init = function(options) { + $.extend(true, this, options); + }; + + $.jqplot.TableLegendRenderer.prototype.addrow = function (label, color, pad, reverse) { + var rs = (pad) ? this.rowSpacing+'px' : '0px'; + var tr; + var td; + var elem; + var div0; + var div1; + elem = document.createElement('tr'); + tr = $(elem); + tr.addClass('jqplot-table-legend'); + elem = null; + + if (reverse){ + tr.prependTo(this._elem); + } + + else{ + tr.appendTo(this._elem); + } + + if (this.showSwatches) { + td = $(document.createElement('td')); + td.addClass('jqplot-table-legend jqplot-table-legend-swatch'); + td.css({textAlign: 'center', paddingTop: rs}); + + div0 = $(document.createElement('div')); + div0.addClass('jqplot-table-legend-swatch-outline'); + div1 = $(document.createElement('div')); + div1.addClass('jqplot-table-legend-swatch'); + div1.css({backgroundColor: color, borderColor: color}); + + tr.append(td.append(div0.append(div1))); + + // $('<td class="jqplot-table-legend" style="text-align:center;padding-top:'+rs+';">'+ + // '<div><div class="jqplot-table-legend-swatch" style="background-color:'+color+';border-color:'+color+';"></div>'+ + // '</div></td>').appendTo(tr); + } + if (this.showLabels) { + td = $(document.createElement('td')); + td.addClass('jqplot-table-legend jqplot-table-legend-label'); + td.css('paddingTop', rs); + tr.append(td); + + // elem = $('<td class="jqplot-table-legend" style="padding-top:'+rs+';"></td>'); + // elem.appendTo(tr); + if (this.escapeHtml) { + td.text(label); + } + else { + td.html(label); + } + } + td = null; + div0 = null; + div1 = null; + tr = null; + elem = null; + }; + + // called with scope of legend + $.jqplot.TableLegendRenderer.prototype.draw = function() { + if (this._elem) { + this._elem.emptyForce(); + this._elem = null; + } + + if (this.show) { + var series = this._series; + // make a table. one line label per row. + var elem = document.createElement('table'); + this._elem = $(elem); + this._elem.addClass('jqplot-table-legend'); + + var ss = {position:'absolute'}; + if (this.background) { + ss['background'] = this.background; + } + if (this.border) { + ss['border'] = this.border; + } + if (this.fontSize) { + ss['fontSize'] = this.fontSize; + } + if (this.fontFamily) { + ss['fontFamily'] = this.fontFamily; + } + if (this.textColor) { + ss['textColor'] = this.textColor; + } + if (this.marginTop != null) { + ss['marginTop'] = this.marginTop; + } + if (this.marginBottom != null) { + ss['marginBottom'] = this.marginBottom; + } + if (this.marginLeft != null) { + ss['marginLeft'] = this.marginLeft; + } + if (this.marginRight != null) { + ss['marginRight'] = this.marginRight; + } + + + var pad = false, + reverse = false, + s; + for (var i = 0; i< series.length; i++) { + s = series[i]; + if (s._stack || s.renderer.constructor == $.jqplot.BezierCurveRenderer){ + reverse = true; + } + if (s.show && s.showLabel) { + var lt = this.labels[i] || s.label.toString(); + if (lt) { + var color = s.color; + if (reverse && i < series.length - 1){ + pad = true; + } + else if (reverse && i == series.length - 1){ + pad = false; + } + this.renderer.addrow.call(this, lt, color, pad, reverse); + pad = true; + } + // let plugins add more rows to legend. Used by trend line plugin. + for (var j=0; j<$.jqplot.addLegendRowHooks.length; j++) { + var item = $.jqplot.addLegendRowHooks[j].call(this, s); + if (item) { + this.renderer.addrow.call(this, item.label, item.color, pad); + pad = true; + } + } + lt = null; + } + } + } + return this._elem; + }; + + $.jqplot.TableLegendRenderer.prototype.pack = function(offsets) { + if (this.show) { + if (this.placement == 'insideGrid') { + switch (this.location) { + case 'nw': + var a = offsets.left; + var b = offsets.top; + this._elem.css('left', a); + this._elem.css('top', b); + break; + case 'n': + var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + var b = offsets.top; + this._elem.css('left', a); + this._elem.css('top', b); + break; + case 'ne': + var a = offsets.right; + var b = offsets.top; + this._elem.css({right:a, top:b}); + break; + case 'e': + var a = offsets.right; + var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + this._elem.css({right:a, top:b}); + break; + case 'se': + var a = offsets.right; + var b = offsets.bottom; + this._elem.css({right:a, bottom:b}); + break; + case 's': + var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + var b = offsets.bottom; + this._elem.css({left:a, bottom:b}); + break; + case 'sw': + var a = offsets.left; + var b = offsets.bottom; + this._elem.css({left:a, bottom:b}); + break; + case 'w': + var a = offsets.left; + var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + this._elem.css({left:a, top:b}); + break; + default: // same as 'se' + var a = offsets.right; + var b = offsets.bottom; + this._elem.css({right:a, bottom:b}); + break; + } + + } + else if (this.placement == 'outside'){ + switch (this.location) { + case 'nw': + var a = this._plotDimensions.width - offsets.left; + var b = offsets.top; + this._elem.css('right', a); + this._elem.css('top', b); + break; + case 'n': + var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + var b = this._plotDimensions.height - offsets.top; + this._elem.css('left', a); + this._elem.css('bottom', b); + break; + case 'ne': + var a = this._plotDimensions.width - offsets.right; + var b = offsets.top; + this._elem.css({left:a, top:b}); + break; + case 'e': + var a = this._plotDimensions.width - offsets.right; + var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + this._elem.css({left:a, top:b}); + break; + case 'se': + var a = this._plotDimensions.width - offsets.right; + var b = offsets.bottom; + this._elem.css({left:a, bottom:b}); + break; + case 's': + var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + var b = this._plotDimensions.height - offsets.bottom; + this._elem.css({left:a, top:b}); + break; + case 'sw': + var a = this._plotDimensions.width - offsets.left; + var b = offsets.bottom; + this._elem.css({right:a, bottom:b}); + break; + case 'w': + var a = this._plotDimensions.width - offsets.left; + var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + this._elem.css({right:a, top:b}); + break; + default: // same as 'se' + var a = offsets.right; + var b = offsets.bottom; + this._elem.css({right:a, bottom:b}); + break; + } + } + else { + switch (this.location) { + case 'nw': + this._elem.css({left:0, top:offsets.top}); + break; + case 'n': + var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + this._elem.css({left: a, top:offsets.top}); + break; + case 'ne': + this._elem.css({right:0, top:offsets.top}); + break; + case 'e': + var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + this._elem.css({right:offsets.right, top:b}); + break; + case 'se': + this._elem.css({right:offsets.right, bottom:offsets.bottom}); + break; + case 's': + var a = (offsets.left + (this._plotDimensions.width - offsets.right))/2 - this.getWidth()/2; + this._elem.css({left: a, bottom:offsets.bottom}); + break; + case 'sw': + this._elem.css({left:offsets.left, bottom:offsets.bottom}); + break; + case 'w': + var b = (offsets.top + (this._plotDimensions.height - offsets.bottom))/2 - this.getHeight()/2; + this._elem.css({left:offsets.left, top:b}); + break; + default: // same as 'se' + this._elem.css({right:offsets.right, bottom:offsets.bottom}); + break; + } + } + } + }; + + /** + * Class: $.jqplot.ThemeEngine + * Theme Engine provides a programatic way to change some of the more + * common jqplot styling options such as fonts, colors and grid options. + * A theme engine instance is created with each plot. The theme engine + * manages a collection of themes which can be modified, added to, or + * applied to the plot. + * + * The themeEngine class is not instantiated directly. + * When a plot is initialized, the current plot options are scanned + * an a default theme named "Default" is created. This theme is + * used as the basis for other themes added to the theme engine and + * is always available. + * + * A theme is a simple javascript object with styling parameters for + * various entities of the plot. A theme has the form: + * + * + * > { + * > _name:f "Default", + * > target: { + * > backgroundColor: "transparent" + * > }, + * > legend: { + * > textColor: null, + * > fontFamily: null, + * > fontSize: null, + * > border: null, + * > background: null + * > }, + * > title: { + * > textColor: "rgb(102, 102, 102)", + * > fontFamily: "'Trebuchet MS',Arial,Helvetica,sans-serif", + * > fontSize: "19.2px", + * > textAlign: "center" + * > }, + * > seriesStyles: {}, + * > series: [{ + * > color: "#4bb2c5", + * > lineWidth: 2.5, + * > linePattern: "solid", + * > shadow: true, + * > fillColor: "#4bb2c5", + * > showMarker: true, + * > markerOptions: { + * > color: "#4bb2c5", + * > show: true, + * > style: 'filledCircle', + * > lineWidth: 1.5, + * > size: 4, + * > shadow: true + * > } + * > }], + * > grid: { + * > drawGridlines: true, + * > gridLineColor: "#cccccc", + * > gridLineWidth: 1, + * > backgroundColor: "#fffdf6", + * > borderColor: "#999999", + * > borderWidth: 2, + * > shadow: true + * > }, + * > axesStyles: { + * > label: {}, + * > ticks: {} + * > }, + * > axes: { + * > xaxis: { + * > borderColor: "#999999", + * > borderWidth: 2, + * > ticks: { + * > show: true, + * > showGridline: true, + * > showLabel: true, + * > showMark: true, + * > size: 4, + * > textColor: "", + * > whiteSpace: "nowrap", + * > fontSize: "12px", + * > fontFamily: "'Trebuchet MS',Arial,Helvetica,sans-serif" + * > }, + * > label: { + * > textColor: "rgb(102, 102, 102)", + * > whiteSpace: "normal", + * > fontSize: "14.6667px", + * > fontFamily: "'Trebuchet MS',Arial,Helvetica,sans-serif", + * > fontWeight: "400" + * > } + * > }, + * > yaxis: { + * > borderColor: "#999999", + * > borderWidth: 2, + * > ticks: { + * > show: true, + * > showGridline: true, + * > showLabel: true, + * > showMark: true, + * > size: 4, + * > textColor: "", + * > whiteSpace: "nowrap", + * > fontSize: "12px", + * > fontFamily: "'Trebuchet MS',Arial,Helvetica,sans-serif" + * > }, + * > label: { + * > textColor: null, + * > whiteSpace: null, + * > fontSize: null, + * > fontFamily: null, + * > fontWeight: null + * > } + * > }, + * > x2axis: {... + * > }, + * > ... + * > y9axis: {... + * > } + * > } + * > } + * + * "seriesStyles" is a style object that will be applied to all series in the plot. + * It will forcibly override any styles applied on the individual series. "axesStyles" is + * a style object that will be applied to all axes in the plot. It will also forcibly + * override any styles on the individual axes. + * + * The example shown above has series options for a line series. Options for other + * series types are shown below: + * + * Bar Series: + * + * > { + * > color: "#4bb2c5", + * > seriesColors: ["#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"], + * > lineWidth: 2.5, + * > shadow: true, + * > barPadding: 2, + * > barMargin: 10, + * > barWidth: 15.09375, + * > highlightColors: ["rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)", "rgb(129,201,214)"] + * > } + * + * Pie Series: + * + * > { + * > seriesColors: ["#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"], + * > padding: 20, + * > sliceMargin: 0, + * > fill: true, + * > shadow: true, + * > startAngle: 0, + * > lineWidth: 2.5, + * > highlightColors: ["rgb(129,201,214)", "rgb(240,189,104)", "rgb(214,202,165)", "rgb(137,180,158)", "rgb(168,180,137)", "rgb(180,174,89)", "rgb(180,113,161)", "rgb(129,141,236)", "rgb(227,205,120)", "rgb(255,138,76)", "rgb(76,169,219)", "rgb(215,126,190)", "rgb(220,232,135)", "rgb(200,167,96)", "rgb(103,202,235)", "rgb(208,154,215)"] + * > } + * + * Funnel Series: + * + * > { + * > color: "#4bb2c5", + * > lineWidth: 2, + * > shadow: true, + * > padding: { + * > top: 20, + * > right: 20, + * > bottom: 20, + * > left: 20 + * > }, + * > sectionMargin: 6, + * > seriesColors: ["#4bb2c5", "#EAA228", "#c5b47f", "#579575", "#839557", "#958c12", "#953579", "#4b5de4", "#d8b83f", "#ff5800", "#0085cc", "#c747a3", "#cddf54", "#FBD178", "#26B4E3", "#bd70c7"], + * > highlightColors: ["rgb(147,208,220)", "rgb(242,199,126)", "rgb(220,210,178)", "rgb(154,191,172)", "rgb(180,191,154)", "rgb(191,186,112)", "rgb(191,133,174)", "rgb(147,157,238)", "rgb(231,212,139)", "rgb(255,154,102)", "rgb(102,181,224)", "rgb(221,144,199)", "rgb(225,235,152)", "rgb(200,167,96)", "rgb(124,210,238)", "rgb(215,169,221)"] + * > } + * + */ + $.jqplot.ThemeEngine = function(){ + // Group: Properties + // + // prop: themes + // hash of themes managed by the theme engine. + // Indexed by theme name. + this.themes = {}; + // prop: activeTheme + // Pointer to currently active theme + this.activeTheme=null; + + }; + + // called with scope of plot + $.jqplot.ThemeEngine.prototype.init = function() { + // get the Default theme from the current plot settings. + var th = new $.jqplot.Theme({_name:'Default'}); + var n, i, nn; + + for (n in th.target) { + if (n == "textColor") { + th.target[n] = this.target.css('color'); + } + else { + th.target[n] = this.target.css(n); + } + } + + if (this.title.show && this.title._elem) { + for (n in th.title) { + if (n == "textColor") { + th.title[n] = this.title._elem.css('color'); + } + else { + th.title[n] = this.title._elem.css(n); + } + } + } + + for (n in th.grid) { + th.grid[n] = this.grid[n]; + } + if (th.grid.backgroundColor == null && this.grid.background != null) { + th.grid.backgroundColor = this.grid.background; + } + if (this.legend.show && this.legend._elem) { + for (n in th.legend) { + if (n == 'textColor') { + th.legend[n] = this.legend._elem.css('color'); + } + else { + th.legend[n] = this.legend._elem.css(n); + } + } + } + var s; + + for (i=0; i<this.series.length; i++) { + s = this.series[i]; + if (s.renderer.constructor == $.jqplot.LineRenderer) { + th.series.push(new LineSeriesProperties()); + } + else if (s.renderer.constructor == $.jqplot.BarRenderer) { + th.series.push(new BarSeriesProperties()); + } + else if (s.renderer.constructor == $.jqplot.PieRenderer) { + th.series.push(new PieSeriesProperties()); + } + else if (s.renderer.constructor == $.jqplot.DonutRenderer) { + th.series.push(new DonutSeriesProperties()); + } + else if (s.renderer.constructor == $.jqplot.FunnelRenderer) { + th.series.push(new FunnelSeriesProperties()); + } + else if (s.renderer.constructor == $.jqplot.MeterGaugeRenderer) { + th.series.push(new MeterSeriesProperties()); + } + else { + th.series.push({}); + } + for (n in th.series[i]) { + th.series[i][n] = s[n]; + } + } + var a, ax; + for (n in this.axes) { + ax = this.axes[n]; + a = th.axes[n] = new AxisProperties(); + a.borderColor = ax.borderColor; + a.borderWidth = ax.borderWidth; + if (ax._ticks && ax._ticks[0]) { + for (nn in a.ticks) { + if (ax._ticks[0].hasOwnProperty(nn)) { + a.ticks[nn] = ax._ticks[0][nn]; + } + else if (ax._ticks[0]._elem){ + a.ticks[nn] = ax._ticks[0]._elem.css(nn); + } + } + } + if (ax._label && ax._label.show) { + for (nn in a.label) { + // a.label[nn] = ax._label._elem.css(nn); + if (ax._label[nn]) { + a.label[nn] = ax._label[nn]; + } + else if (ax._label._elem){ + if (nn == 'textColor') { + a.label[nn] = ax._label._elem.css('color'); + } + else { + a.label[nn] = ax._label._elem.css(nn); + } + } + } + } + } + this.themeEngine._add(th); + this.themeEngine.activeTheme = this.themeEngine.themes[th._name]; + }; + /** + * Group: methods + * + * method: get + * + * Get and return the named theme or the active theme if no name given. + * + * parameter: + * + * name - name of theme to get. + * + * returns: + * + * Theme instance of given name. + */ + $.jqplot.ThemeEngine.prototype.get = function(name) { + if (!name) { + // return the active theme + return this.activeTheme; + } + else { + return this.themes[name]; + } + }; + + function numericalOrder(a,b) { return a-b; } + + /** + * method: getThemeNames + * + * Return the list of theme names in this manager in alpha-numerical order. + * + * parameter: + * + * None + * + * returns: + * + * A the list of theme names in this manager in alpha-numerical order. + */ + $.jqplot.ThemeEngine.prototype.getThemeNames = function() { + var tn = []; + for (var n in this.themes) { + tn.push(n); + } + return tn.sort(numericalOrder); + }; + + /** + * method: getThemes + * + * Return a list of themes in alpha-numerical order by name. + * + * parameter: + * + * None + * + * returns: + * + * A list of themes in alpha-numerical order by name. + */ + $.jqplot.ThemeEngine.prototype.getThemes = function() { + var tn = []; + var themes = []; + for (var n in this.themes) { + tn.push(n); + } + tn.sort(numericalOrder); + for (var i=0; i<tn.length; i++) { + themes.push(this.themes[tn[i]]); + } + return themes; + }; + + $.jqplot.ThemeEngine.prototype.activate = function(plot, name) { + // sometimes need to redraw whole plot. + var redrawPlot = false; + if (!name && this.activeTheme && this.activeTheme._name) { + name = this.activeTheme._name; + } + if (!this.themes.hasOwnProperty(name)) { + throw new Error("No theme of that name"); + } + else { + var th = this.themes[name]; + this.activeTheme = th; + var val, checkBorderColor = false, checkBorderWidth = false; + var arr = ['xaxis', 'x2axis', 'yaxis', 'y2axis']; + + for (i=0; i<arr.length; i++) { + var ax = arr[i]; + if (th.axesStyles.borderColor != null) { + plot.axes[ax].borderColor = th.axesStyles.borderColor; + } + if (th.axesStyles.borderWidth != null) { + plot.axes[ax].borderWidth = th.axesStyles.borderWidth; + } + } + + for (var axname in plot.axes) { + var axis = plot.axes[axname]; + if (axis.show) { + var thaxis = th.axes[axname] || {}; + var thaxstyle = th.axesStyles; + var thax = $.jqplot.extend(true, {}, thaxis, thaxstyle); + val = (th.axesStyles.borderColor != null) ? th.axesStyles.borderColor : thax.borderColor; + if (thax.borderColor != null) { + axis.borderColor = thax.borderColor; + redrawPlot = true; + } + val = (th.axesStyles.borderWidth != null) ? th.axesStyles.borderWidth : thax.borderWidth; + if (thax.borderWidth != null) { + axis.borderWidth = thax.borderWidth; + redrawPlot = true; + } + if (axis._ticks && axis._ticks[0]) { + for (var nn in thax.ticks) { + // val = null; + // if (th.axesStyles.ticks && th.axesStyles.ticks[nn] != null) { + // val = th.axesStyles.ticks[nn]; + // } + // else if (thax.ticks[nn] != null){ + // val = thax.ticks[nn] + // } + val = thax.ticks[nn]; + if (val != null) { + axis.tickOptions[nn] = val; + axis._ticks = []; + redrawPlot = true; + } + } + } + if (axis._label && axis._label.show) { + for (var nn in thax.label) { + // val = null; + // if (th.axesStyles.label && th.axesStyles.label[nn] != null) { + // val = th.axesStyles.label[nn]; + // } + // else if (thax.label && thax.label[nn] != null){ + // val = thax.label[nn] + // } + val = thax.label[nn]; + if (val != null) { + axis.labelOptions[nn] = val; + redrawPlot = true; + } + } + } + + } + } + + for (var n in th.grid) { + if (th.grid[n] != null) { + plot.grid[n] = th.grid[n]; + } + } + if (!redrawPlot) { + plot.grid.draw(); + } + + if (plot.legend.show) { + for (n in th.legend) { + if (th.legend[n] != null) { + plot.legend[n] = th.legend[n]; + } + } + } + if (plot.title.show) { + for (n in th.title) { + if (th.title[n] != null) { + plot.title[n] = th.title[n]; + } + } + } + + var i; + for (i=0; i<th.series.length; i++) { + var opts = {}; + var redrawSeries = false; + for (n in th.series[i]) { + val = (th.seriesStyles[n] != null) ? th.seriesStyles[n] : th.series[i][n]; + if (val != null) { + opts[n] = val; + if (n == 'color') { + plot.series[i].renderer.shapeRenderer.fillStyle = val; + plot.series[i].renderer.shapeRenderer.strokeStyle = val; + plot.series[i][n] = val; + } + else if ((n == 'lineWidth') || (n == 'linePattern')) { + plot.series[i].renderer.shapeRenderer[n] = val; + plot.series[i][n] = val; + } + else if (n == 'markerOptions') { + merge (plot.series[i].markerOptions, val); + merge (plot.series[i].markerRenderer, val); + } + else { + plot.series[i][n] = val; + } + redrawPlot = true; + } + } + } + + if (redrawPlot) { + plot.target.empty(); + plot.draw(); + } + + for (n in th.target) { + if (th.target[n] != null) { + plot.target.css(n, th.target[n]); + } + } + } + + }; + + $.jqplot.ThemeEngine.prototype._add = function(theme, name) { + if (name) { + theme._name = name; + } + if (!theme._name) { + theme._name = Date.parse(new Date()); + } + if (!this.themes.hasOwnProperty(theme._name)) { + this.themes[theme._name] = theme; + } + else { + throw new Error("jqplot.ThemeEngine Error: Theme already in use"); + } + }; + + // method remove + // Delete the named theme, return true on success, false on failure. + + + /** + * method: remove + * + * Remove the given theme from the themeEngine. + * + * parameters: + * + * name - name of the theme to remove. + * + * returns: + * + * true on success, false on failure. + */ + $.jqplot.ThemeEngine.prototype.remove = function(name) { + if (name == 'Default') { + return false; + } + return delete this.themes[name]; + }; + + /** + * method: newTheme + * + * Create a new theme based on the default theme, adding it the themeEngine. + * + * parameters: + * + * name - name of the new theme. + * obj - optional object of styles to be applied to this new theme. + * + * returns: + * + * new Theme object. + */ + $.jqplot.ThemeEngine.prototype.newTheme = function(name, obj) { + if (typeof(name) == 'object') { + obj = obj || name; + name = null; + } + if (obj && obj._name) { + name = obj._name; + } + else { + name = name || Date.parse(new Date()); + } + // var th = new $.jqplot.Theme(name); + var th = this.copy(this.themes['Default']._name, name); + $.jqplot.extend(th, obj); + return th; + }; + + // function clone(obj) { + // return eval(obj.toSource()); + // } + + function clone(obj){ + if(obj == null || typeof(obj) != 'object'){ + return obj; + } + + var temp = new obj.constructor(); + for(var key in obj){ + temp[key] = clone(obj[key]); + } + return temp; + } + + $.jqplot.clone = clone; + + function merge(obj1, obj2) { + if (obj2 == null || typeof(obj2) != 'object') { + return; + } + for (var key in obj2) { + if (key == 'highlightColors') { + obj1[key] = clone(obj2[key]); + } + if (obj2[key] != null && typeof(obj2[key]) == 'object') { + if (!obj1.hasOwnProperty(key)) { + obj1[key] = {}; + } + merge(obj1[key], obj2[key]); + } + else { + obj1[key] = obj2[key]; + } + } + } + + $.jqplot.merge = merge; + + // Use the jQuery 1.3.2 extend function since behaviour in jQuery 1.4 seems problematic + $.jqplot.extend = function() { + // copy reference to target object + var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !toString.call(target) === "[object Function]" ) { + target = {}; + } + + for ( ; i < length; i++ ){ + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( var name in options ) { + var src = target[ name ], copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging object values + if ( deep && copy && typeof copy === "object" && !copy.nodeType ) { + target[ name ] = $.jqplot.extend( deep, + // Never move original objects, clone them + src || ( copy.length != null ? [ ] : { } ) + , copy ); + } + // Don't bring in undefined values + else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + // Return the modified object + return target; + }; + + /** + * method: rename + * + * Rename a theme. + * + * parameters: + * + * oldName - current name of the theme. + * newName - desired name of the theme. + * + * returns: + * + * new Theme object. + */ + $.jqplot.ThemeEngine.prototype.rename = function (oldName, newName) { + if (oldName == 'Default' || newName == 'Default') { + throw new Error ("jqplot.ThemeEngine Error: Cannot rename from/to Default"); + } + if (this.themes.hasOwnProperty(newName)) { + throw new Error ("jqplot.ThemeEngine Error: New name already in use."); + } + else if (this.themes.hasOwnProperty(oldName)) { + var th = this.copy (oldName, newName); + this.remove(oldName); + return th; + } + throw new Error("jqplot.ThemeEngine Error: Old name or new name invalid"); + }; + + /** + * method: copy + * + * Create a copy of an existing theme in the themeEngine, adding it the themeEngine. + * + * parameters: + * + * sourceName - name of the existing theme. + * targetName - name of the copy. + * obj - optional object of style parameter to apply to the new theme. + * + * returns: + * + * new Theme object. + */ + $.jqplot.ThemeEngine.prototype.copy = function (sourceName, targetName, obj) { + if (targetName == 'Default') { + throw new Error ("jqplot.ThemeEngine Error: Cannot copy over Default theme"); + } + if (!this.themes.hasOwnProperty(sourceName)) { + var s = "jqplot.ThemeEngine Error: Source name invalid"; + throw new Error(s); + } + if (this.themes.hasOwnProperty(targetName)) { + var s = "jqplot.ThemeEngine Error: Target name invalid"; + throw new Error(s); + } + else { + var th = clone(this.themes[sourceName]); + th._name = targetName; + $.jqplot.extend(true, th, obj); + this._add(th); + return th; + } + }; + + + $.jqplot.Theme = function(name, obj) { + if (typeof(name) == 'object') { + obj = obj || name; + name = null; + } + name = name || Date.parse(new Date()); + this._name = name; + this.target = { + backgroundColor: null + }; + this.legend = { + textColor: null, + fontFamily: null, + fontSize: null, + border: null, + background: null + }; + this.title = { + textColor: null, + fontFamily: null, + fontSize: null, + textAlign: null + }; + this.seriesStyles = {}; + this.series = []; + this.grid = { + drawGridlines: null, + gridLineColor: null, + gridLineWidth: null, + backgroundColor: null, + borderColor: null, + borderWidth: null, + shadow: null + }; + this.axesStyles = {label:{}, ticks:{}}; + this.axes = {}; + if (typeof(obj) == 'string') { + this._name = obj; + } + else if(typeof(obj) == 'object') { + $.jqplot.extend(true, this, obj); + } + }; + + var AxisProperties = function() { + this.borderColor = null; + this.borderWidth = null; + this.ticks = new AxisTicks(); + this.label = new AxisLabel(); + }; + + var AxisTicks = function() { + this.show = null; + this.showGridline = null; + this.showLabel = null; + this.showMark = null; + this.size = null; + this.textColor = null; + this.whiteSpace = null; + this.fontSize = null; + this.fontFamily = null; + }; + + var AxisLabel = function() { + this.textColor = null; + this.whiteSpace = null; + this.fontSize = null; + this.fontFamily = null; + this.fontWeight = null; + }; + + var LineSeriesProperties = function() { + this.color=null; + this.lineWidth=null; + this.linePattern=null; + this.shadow=null; + this.fillColor=null; + this.showMarker=null; + this.markerOptions = new MarkerOptions(); + }; + + var MarkerOptions = function() { + this.show = null; + this.style = null; + this.lineWidth = null; + this.size = null; + this.color = null; + this.shadow = null; + }; + + var BarSeriesProperties = function() { + this.color=null; + this.seriesColors=null; + this.lineWidth=null; + this.shadow=null; + this.barPadding=null; + this.barMargin=null; + this.barWidth=null; + this.highlightColors=null; + }; + + var PieSeriesProperties = function() { + this.seriesColors=null; + this.padding=null; + this.sliceMargin=null; + this.fill=null; + this.shadow=null; + this.startAngle=null; + this.lineWidth=null; + this.highlightColors=null; + }; + + var DonutSeriesProperties = function() { + this.seriesColors=null; + this.padding=null; + this.sliceMargin=null; + this.fill=null; + this.shadow=null; + this.startAngle=null; + this.lineWidth=null; + this.innerDiameter=null; + this.thickness=null; + this.ringMargin=null; + this.highlightColors=null; + }; + + var FunnelSeriesProperties = function() { + this.color=null; + this.lineWidth=null; + this.shadow=null; + this.padding=null; + this.sectionMargin=null; + this.seriesColors=null; + this.highlightColors=null; + }; + + var MeterSeriesProperties = function() { + this.padding=null; + this.backgroundColor=null; + this.ringColor=null; + this.tickColor=null; + this.ringWidth=null; + this.intervalColors=null; + this.intervalInnerRadius=null; + this.intervalOuterRadius=null; + this.hubRadius=null; + this.needleThickness=null; + this.needlePad=null; + }; + + + + + $.fn.jqplotChildText = function() { + return $(this).contents().filter(function() { + return this.nodeType == 3; // Node.TEXT_NODE not defined in I7 + }).text(); + }; + + // Returns font style as abbreviation for "font" property. + $.fn.jqplotGetComputedFontStyle = function() { + var css = window.getComputedStyle ? window.getComputedStyle(this[0], "") : this[0].currentStyle; + var attrs = css['font-style'] ? ['font-style', 'font-weight', 'font-size', 'font-family'] : ['fontStyle', 'fontWeight', 'fontSize', 'fontFamily']; + var style = []; + + for (var i=0 ; i < attrs.length; ++i) { + var attr = String(css[attrs[i]]); + + if (attr && attr != 'normal') { + style.push(attr); + } + } + return style.join(' '); + }; + + /** + * Namespace: $.fn + * jQuery namespace to attach functions to jQuery elements. + * + */ + + $.fn.jqplotToImageCanvas = function(options) { + + options = options || {}; + var x_offset = (options.x_offset == null) ? 0 : options.x_offset; + var y_offset = (options.y_offset == null) ? 0 : options.y_offset; + var backgroundColor = (options.backgroundColor == null) ? 'rgb(255,255,255)' : options.backgroundColor; + + if ($(this).width() == 0 || $(this).height() == 0) { + return null; + } + + // excanvas and hence IE < 9 do not support toDataURL and cannot export images. + if ($.jqplot.use_excanvas) { + return null; + } + + var newCanvas = document.createElement("canvas"); + var h = $(this).outerHeight(true); + var w = $(this).outerWidth(true); + var offs = $(this).offset(); + var plotleft = offs.left; + var plottop = offs.top; + var transx = 0, transy = 0; + + // have to check if any elements are hanging outside of plot area before rendering, + // since changing width of canvas will erase canvas. + + var clses = ['jqplot-table-legend', 'jqplot-xaxis-tick', 'jqplot-x2axis-tick', 'jqplot-yaxis-tick', 'jqplot-y2axis-tick', 'jqplot-y3axis-tick', + 'jqplot-y4axis-tick', 'jqplot-y5axis-tick', 'jqplot-y6axis-tick', 'jqplot-y7axis-tick', 'jqplot-y8axis-tick', 'jqplot-y9axis-tick', + 'jqplot-xaxis-label', 'jqplot-x2axis-label', 'jqplot-yaxis-label', 'jqplot-y2axis-label', 'jqplot-y3axis-label', 'jqplot-y4axis-label', + 'jqplot-y5axis-label', 'jqplot-y6axis-label', 'jqplot-y7axis-label', 'jqplot-y8axis-label', 'jqplot-y9axis-label' ]; + + var temptop, templeft, tempbottom, tempright; + + for (var i = 0; i < clses.length; i++) { + $(this).find('.'+clses[i]).each(function() { + temptop = $(this).offset().top - plottop; + templeft = $(this).offset().left - plotleft; + tempright = templeft + $(this).outerWidth(true) + transx; + tempbottom = temptop + $(this).outerHeight(true) + transy; + if (templeft < -transx) { + w = w - transx - templeft; + transx = -templeft; + } + if (temptop < -transy) { + h = h - transy - temptop; + transy = - temptop; + } + if (tempright > w) { + w = tempright; + } + if (tempbottom > h) { + h = tempbottom; + } + }); + } + + newCanvas.width = w + Number(x_offset); + newCanvas.height = h + Number(y_offset); + + var newContext = newCanvas.getContext("2d"); + + newContext.save(); + newContext.fillStyle = backgroundColor; + newContext.fillRect(0,0, newCanvas.width, newCanvas.height); + newContext.restore(); + + newContext.translate(transx, transy); + newContext.textAlign = 'left'; + newContext.textBaseline = 'top'; + + function getLineheight(el) { + var lineheight = parseInt($(el).css('line-height'), 10); + + if (isNaN(lineheight)) { + lineheight = parseInt($(el).css('font-size'), 10) * 1.2; + } + return lineheight; + } + + function writeWrappedText (el, context, text, left, top, canvasWidth) { + var lineheight = getLineheight(el); + var tagwidth = $(el).innerWidth(); + var tagheight = $(el).innerHeight(); + var words = text.split(/\s+/); + var wl = words.length; + var w = ''; + var breaks = []; + var temptop = top; + var templeft = left; + + for (var i=0; i<wl; i++) { + w += words[i]; + if (context.measureText(w).width > tagwidth) { + breaks.push(i); + w = ''; + i--; + } + } + if (breaks.length === 0) { + // center text if necessary + if ($(el).css('textAlign') === 'center') { + templeft = left + (canvasWidth - context.measureText(w).width)/2 - transx; + } + context.fillText(text, templeft, top); + } + else { + w = words.slice(0, breaks[0]).join(' '); + // center text if necessary + if ($(el).css('textAlign') === 'center') { + templeft = left + (canvasWidth - context.measureText(w).width)/2 - transx; + } + context.fillText(w, templeft, temptop); + temptop += lineheight; + for (var i=1, l=breaks.length; i<l; i++) { + w = words.slice(breaks[i-1], breaks[i]).join(' '); + // center text if necessary + if ($(el).css('textAlign') === 'center') { + templeft = left + (canvasWidth - context.measureText(w).width)/2 - transx; + } + context.fillText(w, templeft, temptop); + temptop += lineheight; + } + w = words.slice(breaks[i-1], words.length).join(' '); + // center text if necessary + if ($(el).css('textAlign') === 'center') { + templeft = left + (canvasWidth - context.measureText(w).width)/2 - transx; + } + context.fillText(w, templeft, temptop); + } + + } + + function _jqpToImage(el, x_offset, y_offset) { + var tagname = el.tagName.toLowerCase(); + var p = $(el).position(); + var css = window.getComputedStyle ? window.getComputedStyle(el, "") : el.currentStyle; // for IE < 9 + var left = x_offset + p.left + parseInt(css.marginLeft, 10) + parseInt(css.borderLeftWidth, 10) + parseInt(css.paddingLeft, 10); + var top = y_offset + p.top + parseInt(css.marginTop, 10) + parseInt(css.borderTopWidth, 10)+ parseInt(css.paddingTop, 10); + var w = newCanvas.width; + // var left = x_offset + p.left + $(el).css('marginLeft') + $(el).css('borderLeftWidth') + + // somehow in here, for divs within divs, the width of the inner div should be used instead of the canvas. + + if ((tagname == 'div' || tagname == 'span') && !$(el).hasClass('jqplot-highlighter-tooltip')) { + $(el).children().each(function() { + _jqpToImage(this, left, top); + }); + var text = $(el).jqplotChildText(); + + if (text) { + newContext.font = $(el).jqplotGetComputedFontStyle(); + newContext.fillStyle = $(el).css('color'); + + writeWrappedText(el, newContext, text, left, top, w); + } + } + + // handle the standard table legend + + else if (tagname === 'table' && $(el).hasClass('jqplot-table-legend')) { + newContext.strokeStyle = $(el).css('border-top-color'); + newContext.fillStyle = $(el).css('background-color'); + newContext.fillRect(left, top, $(el).innerWidth(), $(el).innerHeight()); + if (parseInt($(el).css('border-top-width'), 10) > 0) { + newContext.strokeRect(left, top, $(el).innerWidth(), $(el).innerHeight()); + } + + // find all the swatches + $(el).find('div.jqplot-table-legend-swatch-outline').each(function() { + // get the first div and stroke it + var elem = $(this); + newContext.strokeStyle = elem.css('border-top-color'); + var l = left + elem.position().left; + var t = top + elem.position().top; + newContext.strokeRect(l, t, elem.innerWidth(), elem.innerHeight()); + + // now fill the swatch + + l += parseInt(elem.css('padding-left'), 10); + t += parseInt(elem.css('padding-top'), 10); + var h = elem.innerHeight() - 2 * parseInt(elem.css('padding-top'), 10); + var w = elem.innerWidth() - 2 * parseInt(elem.css('padding-left'), 10); + + var swatch = elem.children('div.jqplot-table-legend-swatch'); + newContext.fillStyle = swatch.css('background-color'); + newContext.fillRect(l, t, w, h); + }); + + // now add text + + $(el).find('td.jqplot-table-legend-label').each(function(){ + var elem = $(this); + var l = left + elem.position().left; + var t = top + elem.position().top + parseInt(elem.css('padding-top'), 10); + newContext.font = elem.jqplotGetComputedFontStyle(); + newContext.fillStyle = elem.css('color'); + writeWrappedText(elem, newContext, elem.text(), l, t, w); + }); + + var elem = null; + } + + else if (tagname == 'canvas') { + newContext.drawImage(el, left, top); + } + } + $(this).children().each(function() { + _jqpToImage(this, x_offset, y_offset); + }); + return newCanvas; + }; + + // return the raw image data string. + // Should work on canvas supporting browsers. + $.fn.jqplotToImageStr = function(options) { + var imgCanvas = $(this).jqplotToImageCanvas(options); + if (imgCanvas) { + return imgCanvas.toDataURL("image/png"); + } + else { + return null; + } + }; + + // return a DOM <img> element and return it. + // Should work on canvas supporting browsers. + $.fn.jqplotToImageElem = function(options) { + var elem = document.createElement("img"); + var str = $(this).jqplotToImageStr(options); + elem.src = str; + return elem; + }; + + // return a string for an <img> element and return it. + // Should work on canvas supporting browsers. + $.fn.jqplotToImageElemStr = function(options) { + var str = '<img src='+$(this).jqplotToImageStr(options)+' />'; + return str; + }; + + // Not gauranteed to work, even on canvas supporting browsers due to + // limitations with location.href and browser support. + $.fn.jqplotSaveImage = function() { + var imgData = $(this).jqplotToImageStr({}); + if (imgData) { + window.location.href = imgData.replace("image/png", "image/octet-stream"); + } + + }; + + // Not gauranteed to work, even on canvas supporting browsers due to + // limitations with window.open and arbitrary data. + $.fn.jqplotViewImage = function() { + var imgStr = $(this).jqplotToImageElemStr({}); + var imgData = $(this).jqplotToImageStr({}); + if (imgStr) { + var w = window.open(''); + w.document.open("image/png"); + w.document.write(imgStr); + w.document.close(); + w = null; + } + }; + + + + + /** + * @description + * <p>Object with extended date parsing and formatting capabilities. + * This library borrows many concepts and ideas from the Date Instance + * Methods by Ken Snyder along with some parts of Ken's actual code.</p> + * + * <p>jsDate takes a different approach by not extending the built-in + * Date Object, improving date parsing, allowing for multiple formatting + * syntaxes and multiple and more easily expandable localization.</p> + * + * @author Chris Leonello + * @date #date# + * @version #VERSION# + * @copyright (c) 2010 Chris Leonello + * jsDate is currently available for use in all personal or commercial projects + * under both the MIT and GPL version 2.0 licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * <p>Ken's origianl Date Instance Methods and copyright notice:</p> + * <pre> + * Ken Snyder (ken d snyder at gmail dot com) + * 2008-09-10 + * version 2.0.2 (http://kendsnyder.com/sandbox/date/) + * Creative Commons Attribution License 3.0 (http://creativecommons.org/licenses/by/3.0/) + * </pre> + * + * @class + * @name jsDate + * @param {String | Number | Array | Date Object | Options Object} arguments Optional arguments, either a parsable date/time string, + * a JavaScript timestamp, an array of numbers of form [year, month, day, hours, minutes, seconds, milliseconds], + * a Date object, or an options object of form {syntax: "perl", date:some Date} where all options are optional. + */ + + var jsDate = function () { + + this.syntax = jsDate.config.syntax; + this._type = "jsDate"; + this.proxy = new Date(); + this.options = {}; + this.locale = jsDate.regional.getLocale(); + this.formatString = ''; + this.defaultCentury = jsDate.config.defaultCentury; + + switch ( arguments.length ) { + case 0: + break; + case 1: + // other objects either won't have a _type property or, + // if they do, it shouldn't be set to "jsDate", so + // assume it is an options argument. + if (get_type(arguments[0]) == "[object Object]" && arguments[0]._type != "jsDate") { + var opts = this.options = arguments[0]; + this.syntax = opts.syntax || this.syntax; + this.defaultCentury = opts.defaultCentury || this.defaultCentury; + this.proxy = jsDate.createDate(opts.date); + } + else { + this.proxy = jsDate.createDate(arguments[0]); + } + break; + default: + var a = []; + for ( var i=0; i<arguments.length; i++ ) { + a.push(arguments[i]); + } + // this should be the current date/time? + this.proxy = new Date(); + this.proxy.setFullYear.apply( this.proxy, a.slice(0,3) ); + if ( a.slice(3).length ) { + this.proxy.setHours.apply( this.proxy, a.slice(3) ); + } + break; + } + }; + + /** + * @namespace Configuration options that will be used as defaults for all instances on the page. + * @property {String} defaultLocale The default locale to use [en]. + * @property {String} syntax The default syntax to use [perl]. + * @property {Number} defaultCentury The default centry for 2 digit dates. + */ + jsDate.config = { + defaultLocale: 'en', + syntax: 'perl', + defaultCentury: 1900 + }; + + /** + * Add an arbitrary amount to the currently stored date + * + * @param {Number} number + * @param {String} unit + * @returns {jsDate} + */ + + jsDate.prototype.add = function(number, unit) { + var factor = multipliers[unit] || multipliers.day; + if (typeof factor == 'number') { + this.proxy.setTime(this.proxy.getTime() + (factor * number)); + } else { + factor.add(this, number); + } + return this; + }; + + /** + * Create a new jqplot.date object with the same date + * + * @returns {jsDate} + */ + + jsDate.prototype.clone = function() { + return new jsDate(this.proxy.getTime()); + }; + + /** + * Get the UTC TimeZone Offset of this date in milliseconds. + * + * @returns {Number} + */ + + jsDate.prototype.getUtcOffset = function() { + return this.proxy.getTimezoneOffset() * 60000; + }; + + /** + * Find the difference between this jsDate and another date. + * + * @param {String| Number| Array| jsDate Object| Date Object} dateObj + * @param {String} unit + * @param {Boolean} allowDecimal + * @returns {Number} Number of units difference between dates. + */ + + jsDate.prototype.diff = function(dateObj, unit, allowDecimal) { + // ensure we have a Date object + dateObj = new jsDate(dateObj); + if (dateObj === null) { + return null; + } + // get the multiplying factor integer or factor function + var factor = multipliers[unit] || multipliers.day; + if (typeof factor == 'number') { + // multiply + var unitDiff = (this.proxy.getTime() - dateObj.proxy.getTime()) / factor; + } else { + // run function + var unitDiff = factor.diff(this.proxy, dateObj.proxy); + } + // if decimals are not allowed, round toward zero + return (allowDecimal ? unitDiff : Math[unitDiff > 0 ? 'floor' : 'ceil'](unitDiff)); + }; + + /** + * Get the abbreviated name of the current week day + * + * @returns {String} + */ + + jsDate.prototype.getAbbrDayName = function() { + return jsDate.regional[this.locale]["dayNamesShort"][this.proxy.getDay()]; + }; + + /** + * Get the abbreviated name of the current month + * + * @returns {String} + */ + + jsDate.prototype.getAbbrMonthName = function() { + return jsDate.regional[this.locale]["monthNamesShort"][this.proxy.getMonth()]; + }; + + /** + * Get UPPER CASE AM or PM for the current time + * + * @returns {String} + */ + + jsDate.prototype.getAMPM = function() { + return this.proxy.getHours() >= 12 ? 'PM' : 'AM'; + }; + + /** + * Get lower case am or pm for the current time + * + * @returns {String} + */ + + jsDate.prototype.getAmPm = function() { + return this.proxy.getHours() >= 12 ? 'pm' : 'am'; + }; + + /** + * Get the century (19 for 20th Century) + * + * @returns {Integer} Century (19 for 20th century). + */ + jsDate.prototype.getCentury = function() { + return parseInt(this.proxy.getFullYear()/100, 10); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getDate = function() { + return this.proxy.getDate(); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getDay = function() { + return this.proxy.getDay(); + }; + + /** + * Get the Day of week 1 (Monday) thru 7 (Sunday) + * + * @returns {Integer} Day of week 1 (Monday) thru 7 (Sunday) + */ + jsDate.prototype.getDayOfWeek = function() { + var dow = this.proxy.getDay(); + return dow===0?7:dow; + }; + + /** + * Get the day of the year + * + * @returns {Integer} 1 - 366, day of the year + */ + jsDate.prototype.getDayOfYear = function() { + var d = this.proxy; + var ms = d - new Date('' + d.getFullYear() + '/1/1 GMT'); + ms += d.getTimezoneOffset()*60000; + d = null; + return parseInt(ms/60000/60/24, 10)+1; + }; + + /** + * Get the name of the current week day + * + * @returns {String} + */ + + jsDate.prototype.getDayName = function() { + return jsDate.regional[this.locale]["dayNames"][this.proxy.getDay()]; + }; + + /** + * Get the week number of the given year, starting with the first Sunday as the first week + * @returns {Integer} Week number (13 for the 13th full week of the year). + */ + jsDate.prototype.getFullWeekOfYear = function() { + var d = this.proxy; + var doy = this.getDayOfYear(); + var rdow = 6-d.getDay(); + var woy = parseInt((doy+rdow)/7, 10); + return woy; + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getFullYear = function() { + return this.proxy.getFullYear(); + }; + + /** + * Get the GMT offset in hours and minutes (e.g. +06:30) + * + * @returns {String} + */ + + jsDate.prototype.getGmtOffset = function() { + // divide the minutes offset by 60 + var hours = this.proxy.getTimezoneOffset() / 60; + // decide if we are ahead of or behind GMT + var prefix = hours < 0 ? '+' : '-'; + // remove the negative sign if any + hours = Math.abs(hours); + // add the +/- to the padded number of hours to : to the padded minutes + return prefix + addZeros(Math.floor(hours), 2) + ':' + addZeros((hours % 1) * 60, 2); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getHours = function() { + return this.proxy.getHours(); + }; + + /** + * Get the current hour on a 12-hour scheme + * + * @returns {Integer} + */ + + jsDate.prototype.getHours12 = function() { + var hours = this.proxy.getHours(); + return hours > 12 ? hours - 12 : (hours == 0 ? 12 : hours); + }; + + + jsDate.prototype.getIsoWeek = function() { + var d = this.proxy; + var woy = d.getWeekOfYear(); + var dow1_1 = (new Date('' + d.getFullYear() + '/1/1')).getDay(); + // First week is 01 and not 00 as in the case of %U and %W, + // so we add 1 to the final result except if day 1 of the year + // is a Monday (then %W returns 01). + // We also need to subtract 1 if the day 1 of the year is + // Friday-Sunday, so the resulting equation becomes: + var idow = woy + (dow1_1 > 4 || dow1_1 <= 1 ? 0 : 1); + if(idow == 53 && (new Date('' + d.getFullYear() + '/12/31')).getDay() < 4) + { + idow = 1; + } + else if(idow === 0) + { + d = new jsDate(new Date('' + (d.getFullYear()-1) + '/12/31')); + idow = d.getIsoWeek(); + } + d = null; + return idow; + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getMilliseconds = function() { + return this.proxy.getMilliseconds(); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getMinutes = function() { + return this.proxy.getMinutes(); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getMonth = function() { + return this.proxy.getMonth(); + }; + + /** + * Get the name of the current month + * + * @returns {String} + */ + + jsDate.prototype.getMonthName = function() { + return jsDate.regional[this.locale]["monthNames"][this.proxy.getMonth()]; + }; + + /** + * Get the number of the current month, 1-12 + * + * @returns {Integer} + */ + + jsDate.prototype.getMonthNumber = function() { + return this.proxy.getMonth() + 1; + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getSeconds = function() { + return this.proxy.getSeconds(); + }; + + /** + * Return a proper two-digit year integer + * + * @returns {Integer} + */ + + jsDate.prototype.getShortYear = function() { + return this.proxy.getYear() % 100; + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getTime = function() { + return this.proxy.getTime(); + }; + + /** + * Get the timezone abbreviation + * + * @returns {String} Abbreviation for the timezone + */ + jsDate.prototype.getTimezoneAbbr = function() { + return this.proxy.toString().replace(/^.*\(([^)]+)\)$/, '$1'); + }; + + /** + * Get the browser-reported name for the current timezone (e.g. MDT, Mountain Daylight Time) + * + * @returns {String} + */ + jsDate.prototype.getTimezoneName = function() { + var match = /(?:\((.+)\)$| ([A-Z]{3}) )/.exec(this.toString()); + return match[1] || match[2] || 'GMT' + this.getGmtOffset(); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getTimezoneOffset = function() { + return this.proxy.getTimezoneOffset(); + }; + + + /** + * Get the week number of the given year, starting with the first Monday as the first week + * @returns {Integer} Week number (13 for the 13th week of the year). + */ + jsDate.prototype.getWeekOfYear = function() { + var doy = this.getDayOfYear(); + var rdow = 7 - this.getDayOfWeek(); + var woy = parseInt((doy+rdow)/7, 10); + return woy; + }; + + /** + * Get the current date as a Unix timestamp + * + * @returns {Integer} + */ + + jsDate.prototype.getUnix = function() { + return Math.round(this.proxy.getTime() / 1000, 0); + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.getYear = function() { + return this.proxy.getYear(); + }; + + /** + * Return a date one day ahead (or any other unit) + * + * @param {String} unit Optional, year | month | day | week | hour | minute | second | millisecond + * @returns {jsDate} + */ + + jsDate.prototype.next = function(unit) { + unit = unit || 'day'; + return this.clone().add(1, unit); + }; + + /** + * Set the jsDate instance to a new date. + * + * @param {String | Number | Array | Date Object | jsDate Object | Options Object} arguments Optional arguments, + * either a parsable date/time string, + * a JavaScript timestamp, an array of numbers of form [year, month, day, hours, minutes, seconds, milliseconds], + * a Date object, jsDate Object or an options object of form {syntax: "perl", date:some Date} where all options are optional. + */ + jsDate.prototype.set = function() { + switch ( arguments.length ) { + case 0: + this.proxy = new Date(); + break; + case 1: + // other objects either won't have a _type property or, + // if they do, it shouldn't be set to "jsDate", so + // assume it is an options argument. + if (get_type(arguments[0]) == "[object Object]" && arguments[0]._type != "jsDate") { + var opts = this.options = arguments[0]; + this.syntax = opts.syntax || this.syntax; + this.defaultCentury = opts.defaultCentury || this.defaultCentury; + this.proxy = jsDate.createDate(opts.date); + } + else { + this.proxy = jsDate.createDate(arguments[0]); + } + break; + default: + var a = []; + for ( var i=0; i<arguments.length; i++ ) { + a.push(arguments[i]); + } + // this should be the current date/time + this.proxy = new Date(); + this.proxy.setFullYear.apply( this.proxy, a.slice(0,3) ); + if ( a.slice(3).length ) { + this.proxy.setHours.apply( this.proxy, a.slice(3) ); + } + break; + } + return this; + }; + + /** + * Sets the day of the month for a specified date according to local time. + * @param {Integer} dayValue An integer from 1 to 31, representing the day of the month. + */ + jsDate.prototype.setDate = function(n) { + this.proxy.setDate(n); + return this; + }; + + /** + * Sets the full year for a specified date according to local time. + * @param {Integer} yearValue The numeric value of the year, for example, 1995. + * @param {Integer} monthValue Optional, between 0 and 11 representing the months January through December. + * @param {Integer} dayValue Optional, between 1 and 31 representing the day of the month. If you specify the dayValue parameter, you must also specify the monthValue. + */ + jsDate.prototype.setFullYear = function() { + this.proxy.setFullYear.apply(this.proxy, arguments); + return this; + }; + + /** + * Sets the hours for a specified date according to local time. + * + * @param {Integer} hoursValue An integer between 0 and 23, representing the hour. + * @param {Integer} minutesValue Optional, An integer between 0 and 59, representing the minutes. + * @param {Integer} secondsValue Optional, An integer between 0 and 59, representing the seconds. + * If you specify the secondsValue parameter, you must also specify the minutesValue. + * @param {Integer} msValue Optional, A number between 0 and 999, representing the milliseconds. + * If you specify the msValue parameter, you must also specify the minutesValue and secondsValue. + */ + jsDate.prototype.setHours = function() { + this.proxy.setHours.apply(this.proxy, arguments); + return this; + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.setMilliseconds = function(n) { + this.proxy.setMilliseconds(n); + return this; + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.setMinutes = function() { + this.proxy.setMinutes.apply(this.proxy, arguments); + return this; + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.setMonth = function() { + this.proxy.setMonth.apply(this.proxy, arguments); + return this; + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.setSeconds = function() { + this.proxy.setSeconds.apply(this.proxy, arguments); + return this; + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.setTime = function(n) { + this.proxy.setTime(n); + return this; + }; + + /** + * Implements Date functionality + */ + jsDate.prototype.setYear = function() { + this.proxy.setYear.apply(this.proxy, arguments); + return this; + }; + + /** + * Provide a formatted string representation of this date. + * + * @param {String} formatString A format string. + * See: {@link jsDate.formats}. + * @returns {String} Date String. + */ + + jsDate.prototype.strftime = function(formatString) { + formatString = formatString || this.formatString || jsDate.regional[this.locale]['formatString']; + return jsDate.strftime(this, formatString, this.syntax); + }; + + /** + * Return a String representation of this jsDate object. + * @returns {String} Date string. + */ + + jsDate.prototype.toString = function() { + return this.proxy.toString(); + }; + + /** + * Convert the current date to an 8-digit integer (%Y%m%d) + * + * @returns {Integer} + */ + + jsDate.prototype.toYmdInt = function() { + return (this.proxy.getFullYear() * 10000) + (this.getMonthNumber() * 100) + this.proxy.getDate(); + }; + + /** + * @namespace Holds localizations for month/day names. + * <p>jsDate attempts to detect locale when loaded and defaults to 'en'. + * If a localization is detected which is not available, jsDate defaults to 'en'. + * Additional localizations can be added after jsDate loads. After adding a localization, + * call the jsDate.regional.getLocale() method. Currently, en, fr and de are defined.</p> + * + * <p>Localizations must be an object and have the following properties defined: monthNames, monthNamesShort, dayNames, dayNamesShort and Localizations are added like:</p> + * <pre class="code"> + * jsDate.regional['en'] = { + * monthNames : 'January February March April May June July August September October November December'.split(' '), + * monthNamesShort : 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split(' '), + * dayNames : 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday'.split(' '), + * dayNamesShort : 'Sun Mon Tue Wed Thu Fri Sat'.split(' ') + * }; + * </pre> + * <p>After adding localizations, call <code>jsDate.regional.getLocale();</code> to update the locale setting with the + * new localizations.</p> + */ + + jsDate.regional = { + 'en': { + monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'], + monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun','Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], + dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], + dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], + formatString: '%Y-%m-%d %H:%M:%S' + }, + + 'fr': { + monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre'], + monthNamesShort: ['Jan','Fév','Mar','Avr','Mai','Jun','Jul','Aoû','Sep','Oct','Nov','Déc'], + dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'], + dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'], + formatString: '%Y-%m-%d %H:%M:%S' + }, + + 'de': { + monthNames: ['Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'], + monthNamesShort: ['Jan','Feb','Mär','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'], + dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'], + dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'], + formatString: '%Y-%m-%d %H:%M:%S' + }, + + 'es': { + monthNames: ['Enero','Febrero','Marzo','Abril','Mayo','Junio', 'Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'], + monthNamesShort: ['Ene','Feb','Mar','Abr','May','Jun', 'Jul','Ago','Sep','Oct','Nov','Dic'], + dayNames: ['Domingo','Lunes','Martes','Miércoles','Jueves','Viernes','Sábado'], + dayNamesShort: ['Dom','Lun','Mar','Mié','Juv','Vie','Sáb'], + formatString: '%Y-%m-%d %H:%M:%S' + }, + + 'ru': { + monthNames: ['Январь','Февраль','Март','Ðпрель','Май','Июнь','Июль','ÐвгуÑÑ‚','СентÑбрь','ОктÑбрь','ÐоÑбрь','Декабрь'], + monthNamesShort: ['Янв','Фев','Мар','Ðпр','Май','Июн','Июл','Ðвг','Сен','Окт','ÐоÑ','Дек'], + dayNames: ['воÑкреÑенье','понедельник','вторник','Ñреда','четверг','пÑтница','Ñуббота'], + dayNamesShort: ['вÑк','пнд','втр','Ñрд','чтв','птн','Ñбт'], + formatString: '%Y-%m-%d %H:%M:%S' + }, + + 'ar': { + monthNames: ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'آذار', 'ØØ²ÙŠØ±Ø§Ù†','تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'], + monthNamesShort: ['1','2','3','4','5','6','7','8','9','10','11','12'], + dayNames: ['السبت', 'Ø§Ù„Ø£ØØ¯', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة'], + dayNamesShort: ['سبت', 'Ø£ØØ¯', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة'], + formatString: '%Y-%m-%d %H:%M:%S' + }, + + 'pt': { + monthNames: ['Janeiro','Fevereiro','Março','Abril','Maio','Junho','Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'], + monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'], + dayNames: ['Domingo','Segunda-feira','Terça-feira','Quarta-feira','Quinta-feira','Sexta-feira','Sábado'], + dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'], + formatString: '%Y-%m-%d %H:%M:%S' + }, + + 'pt-BR': { + monthNames: ['Janeiro','Fevereiro','Março','Abril','Maio','Junho', 'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'], + monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'], + dayNames: ['Domingo','Segunda-feira','Terça-feira','Quarta-feira','Quinta-feira','Sexta-feira','Sábado'], + dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'], + formatString: '%Y-%m-%d %H:%M:%S' + } + + + }; + + // Set english variants to 'en' + jsDate.regional['en-US'] = jsDate.regional['en-GB'] = jsDate.regional['en']; + + /** + * Try to determine the users locale based on the lang attribute of the html page. Defaults to 'en' + * if it cannot figure out a locale of if the locale does not have a localization defined. + * @returns {String} locale + */ + + jsDate.regional.getLocale = function () { + var l = jsDate.config.defaultLocale; + + if ( document && document.getElementsByTagName('html') && document.getElementsByTagName('html')[0].lang ) { + l = document.getElementsByTagName('html')[0].lang; + if (!jsDate.regional.hasOwnProperty(l)) { + l = jsDate.config.defaultLocale; + } + } + + return l; + }; + + // ms in day + var day = 24 * 60 * 60 * 1000; + + // padd a number with zeros + var addZeros = function(num, digits) { + num = String(num); + var i = digits - num.length; + var s = String(Math.pow(10, i)).slice(1); + return s.concat(num); + }; + + // representations used for calculating differences between dates. + // This borrows heavily from Ken Snyder's work. + var multipliers = { + millisecond: 1, + second: 1000, + minute: 60 * 1000, + hour: 60 * 60 * 1000, + day: day, + week: 7 * day, + month: { + // add a number of months + add: function(d, number) { + // add any years needed (increments of 12) + multipliers.year.add(d, Math[number > 0 ? 'floor' : 'ceil'](number / 12)); + // ensure that we properly wrap betwen December and January + // 11 % 12 = 11 + // 12 % 12 = 0 + var prevMonth = d.getMonth() + (number % 12); + if (prevMonth == 12) { + prevMonth = 0; + d.setYear(d.getFullYear() + 1); + } else if (prevMonth == -1) { + prevMonth = 11; + d.setYear(d.getFullYear() - 1); + } + d.setMonth(prevMonth); + }, + // get the number of months between two Date objects (decimal to the nearest day) + diff: function(d1, d2) { + // get the number of years + var diffYears = d1.getFullYear() - d2.getFullYear(); + // get the number of remaining months + var diffMonths = d1.getMonth() - d2.getMonth() + (diffYears * 12); + // get the number of remaining days + var diffDays = d1.getDate() - d2.getDate(); + // return the month difference with the days difference as a decimal + return diffMonths + (diffDays / 30); + } + }, + year: { + // add a number of years + add: function(d, number) { + d.setYear(d.getFullYear() + Math[number > 0 ? 'floor' : 'ceil'](number)); + }, + // get the number of years between two Date objects (decimal to the nearest day) + diff: function(d1, d2) { + return multipliers.month.diff(d1, d2) / 12; + } + } + }; + // + // Alias each multiplier with an 's' to allow 'year' and 'years' for example. + // This comes from Ken Snyders work. + // + for (var unit in multipliers) { + if (unit.substring(unit.length - 1) != 's') { // IE will iterate newly added properties :| + multipliers[unit + 's'] = multipliers[unit]; + } + } + + // + // take a jsDate instance and a format code and return the formatted value. + // This is a somewhat modified version of Ken Snyder's method. + // + var format = function(d, code, syntax) { + // if shorcut codes are used, recursively expand those. + if (jsDate.formats[syntax]["shortcuts"][code]) { + return jsDate.strftime(d, jsDate.formats[syntax]["shortcuts"][code], syntax); + } else { + // get the format code function and addZeros() argument + var getter = (jsDate.formats[syntax]["codes"][code] || '').split('.'); + var nbr = d['get' + getter[0]] ? d['get' + getter[0]]() : ''; + if (getter[1]) { + nbr = addZeros(nbr, getter[1]); + } + return nbr; + } + }; + + /** + * @static + * Static function for convert a date to a string according to a given format. Also acts as namespace for strftime format codes. + * <p>strftime formatting can be accomplished without creating a jsDate object by calling jsDate.strftime():</p> + * <pre class="code"> + * var formattedDate = jsDate.strftime('Feb 8, 2006 8:48:32', '%Y-%m-%d %H:%M:%S'); + * </pre> + * @param {String | Number | Array | jsDate Object | Date Object} date A parsable date string, JavaScript time stamp, Array of form [year, month, day, hours, minutes, seconds, milliseconds], jsDate Object or Date object. + * @param {String} formatString String with embedded date formatting codes. + * See: {@link jsDate.formats}. + * @param {String} syntax Optional syntax to use [default perl]. + * @param {String} locale Optional locale to use. + * @returns {String} Formatted representation of the date. + */ + // + // Logic as implemented here is very similar to Ken Snyder's Date Instance Methods. + // + jsDate.strftime = function(d, formatString, syntax, locale) { + var syn = 'perl'; + var loc = jsDate.regional.getLocale(); + + // check if syntax and locale are available or reversed + if (syntax && jsDate.formats.hasOwnProperty(syntax)) { + syn = syntax; + } + else if (syntax && jsDate.regional.hasOwnProperty(syntax)) { + loc = syntax; + } + + if (locale && jsDate.formats.hasOwnProperty(locale)) { + syn = locale; + } + else if (locale && jsDate.regional.hasOwnProperty(locale)) { + loc = locale; + } + + if (get_type(d) != "[object Object]" || d._type != "jsDate") { + d = new jsDate(d); + d.locale = loc; + } + if (!formatString) { + formatString = d.formatString || jsDate.regional[loc]['formatString']; + } + // default the format string to year-month-day + var source = formatString || '%Y-%m-%d', + result = '', + match; + // replace each format code + while (source.length > 0) { + if (match = source.match(jsDate.formats[syn].codes.matcher)) { + result += source.slice(0, match.index); + result += (match[1] || '') + format(d, match[2], syn); + source = source.slice(match.index + match[0].length); + } else { + result += source; + source = ''; + } + } + return result; + }; + + /** + * @namespace + * Namespace to hold format codes and format shortcuts. "perl" and "php" format codes + * and shortcuts are defined by default. Additional codes and shortcuts can be + * added like: + * + * <pre class="code"> + * jsDate.formats["perl"] = { + * "codes": { + * matcher: /someregex/, + * Y: "fullYear", // name of "get" method without the "get", + * ..., // more codes + * }, + * "shortcuts": { + * F: '%Y-%m-%d', + * ..., // more shortcuts + * } + * }; + * </pre> + * + * <p>Additionally, ISO and SQL shortcuts are defined and can be accesses via: + * <code>jsDate.formats.ISO</code> and <code>jsDate.formats.SQL</code> + */ + + jsDate.formats = { + ISO:'%Y-%m-%dT%H:%M:%S.%N%G', + SQL:'%Y-%m-%d %H:%M:%S' + }; + + /** + * Perl format codes and shortcuts for strftime. + * + * A hash (object) of codes where each code must be an array where the first member is + * the name of a Date.prototype or jsDate.prototype function to call + * and optionally a second member indicating the number to pass to addZeros() + * + * <p>The following format codes are defined:</p> + * + * <pre class="code"> + * Code Result Description + * == Years == + * %Y 2008 Four-digit year + * %y 08 Two-digit year + * + * == Months == + * %m 09 Two-digit month + * %#m 9 One or two-digit month + * %B September Full month name + * %b Sep Abbreviated month name + * + * == Days == + * %d 05 Two-digit day of month + * %#d 5 One or two-digit day of month + * %e 5 One or two-digit day of month + * %A Sunday Full name of the day of the week + * %a Sun Abbreviated name of the day of the week + * %w 0 Number of the day of the week (0 = Sunday, 6 = Saturday) + * + * == Hours == + * %H 23 Hours in 24-hour format (two digits) + * %#H 3 Hours in 24-hour integer format (one or two digits) + * %I 11 Hours in 12-hour format (two digits) + * %#I 3 Hours in 12-hour integer format (one or two digits) + * %p PM AM or PM + * + * == Minutes == + * %M 09 Minutes (two digits) + * %#M 9 Minutes (one or two digits) + * + * == Seconds == + * %S 02 Seconds (two digits) + * %#S 2 Seconds (one or two digits) + * %s 1206567625723 Unix timestamp (Seconds past 1970-01-01 00:00:00) + * + * == Milliseconds == + * %N 008 Milliseconds (three digits) + * %#N 8 Milliseconds (one to three digits) + * + * == Timezone == + * %O 360 difference in minutes between local time and GMT + * %Z Mountain Standard Time Name of timezone as reported by browser + * %G 06:00 Hours and minutes between GMT + * + * == Shortcuts == + * %F 2008-03-26 %Y-%m-%d + * %T 05:06:30 %H:%M:%S + * %X 05:06:30 %H:%M:%S + * %x 03/26/08 %m/%d/%y + * %D 03/26/08 %m/%d/%y + * %#c Wed Mar 26 15:31:00 2008 %a %b %e %H:%M:%S %Y + * %v 3-Sep-2008 %e-%b-%Y + * %R 15:31 %H:%M + * %r 03:31:00 PM %I:%M:%S %p + * + * == Characters == + * %n \n Newline + * %t \t Tab + * %% % Percent Symbol + * </pre> + * + * <p>Formatting shortcuts that will be translated into their longer version. + * Be sure that format shortcuts do not refer to themselves: this will cause an infinite loop.</p> + * + * <p>Format codes and format shortcuts can be redefined after the jsDate + * module is imported.</p> + * + * <p>Note that if you redefine the whole hash (object), you must supply a "matcher" + * regex for the parser. The default matcher is:</p> + * + * <code>/()%(#?(%|[a-z]))/i</code> + * + * <p>which corresponds to the Perl syntax used by default.</p> + * + * <p>By customizing the matcher and format codes, nearly any strftime functionality is possible.</p> + */ + + jsDate.formats.perl = { + codes: { + // + // 2-part regex matcher for format codes + // + // first match must be the character before the code (to account for escaping) + // second match must be the format code character(s) + // + matcher: /()%(#?(%|[a-z]))/i, + // year + Y: 'FullYear', + y: 'ShortYear.2', + // month + m: 'MonthNumber.2', + '#m': 'MonthNumber', + B: 'MonthName', + b: 'AbbrMonthName', + // day + d: 'Date.2', + '#d': 'Date', + e: 'Date', + A: 'DayName', + a: 'AbbrDayName', + w: 'Day', + // hours + H: 'Hours.2', + '#H': 'Hours', + I: 'Hours12.2', + '#I': 'Hours12', + p: 'AMPM', + // minutes + M: 'Minutes.2', + '#M': 'Minutes', + // seconds + S: 'Seconds.2', + '#S': 'Seconds', + s: 'Unix', + // milliseconds + N: 'Milliseconds.3', + '#N': 'Milliseconds', + // timezone + O: 'TimezoneOffset', + Z: 'TimezoneName', + G: 'GmtOffset' + }, + + shortcuts: { + // date + F: '%Y-%m-%d', + // time + T: '%H:%M:%S', + X: '%H:%M:%S', + // local format date + x: '%m/%d/%y', + D: '%m/%d/%y', + // local format extended + '#c': '%a %b %e %H:%M:%S %Y', + // local format short + v: '%e-%b-%Y', + R: '%H:%M', + r: '%I:%M:%S %p', + // tab and newline + t: '\t', + n: '\n', + '%': '%' + } + }; + + /** + * PHP format codes and shortcuts for strftime. + * + * A hash (object) of codes where each code must be an array where the first member is + * the name of a Date.prototype or jsDate.prototype function to call + * and optionally a second member indicating the number to pass to addZeros() + * + * <p>The following format codes are defined:</p> + * + * <pre class="code"> + * Code Result Description + * === Days === + * %a Sun through Sat An abbreviated textual representation of the day + * %A Sunday - Saturday A full textual representation of the day + * %d 01 to 31 Two-digit day of the month (with leading zeros) + * %e 1 to 31 Day of the month, with a space preceding single digits. + * %j 001 to 366 Day of the year, 3 digits with leading zeros + * %u 1 - 7 (Mon - Sun) ISO-8601 numeric representation of the day of the week + * %w 0 - 6 (Sun - Sat) Numeric representation of the day of the week + * + * === Week === + * %U 13 Full Week number, starting with the first Sunday as the first week + * %V 01 through 53 ISO-8601:1988 week number, starting with the first week of the year + * with at least 4 weekdays, with Monday being the start of the week + * %W 46 A numeric representation of the week of the year, + * starting with the first Monday as the first week + * === Month === + * %b Jan through Dec Abbreviated month name, based on the locale + * %B January - December Full month name, based on the locale + * %h Jan through Dec Abbreviated month name, based on the locale (an alias of %b) + * %m 01 - 12 (Jan - Dec) Two digit representation of the month + * + * === Year === + * %C 19 Two digit century (year/100, truncated to an integer) + * %y 09 for 2009 Two digit year + * %Y 2038 Four digit year + * + * === Time === + * %H 00 through 23 Two digit representation of the hour in 24-hour format + * %I 01 through 12 Two digit representation of the hour in 12-hour format + * %l 1 through 12 Hour in 12-hour format, with a space preceeding single digits + * %M 00 through 59 Two digit representation of the minute + * %p AM/PM UPPER-CASE 'AM' or 'PM' based on the given time + * %P am/pm lower-case 'am' or 'pm' based on the given time + * %r 09:34:17 PM Same as %I:%M:%S %p + * %R 00:35 Same as %H:%M + * %S 00 through 59 Two digit representation of the second + * %T 21:34:17 Same as %H:%M:%S + * %X 03:59:16 Preferred time representation based on locale, without the date + * %z -0500 or EST Either the time zone offset from UTC or the abbreviation + * %Z -0500 or EST The time zone offset/abbreviation option NOT given by %z + * + * === Time and Date === + * %D 02/05/09 Same as %m/%d/%y + * %F 2009-02-05 Same as %Y-%m-%d (commonly used in database datestamps) + * %s 305815200 Unix Epoch Time timestamp (same as the time() function) + * %x 02/05/09 Preferred date representation, without the time + * + * === Miscellaneous === + * %n --- A newline character (\n) + * %t --- A Tab character (\t) + * %% --- A literal percentage character (%) + * </pre> + */ + + jsDate.formats.php = { + codes: { + // + // 2-part regex matcher for format codes + // + // first match must be the character before the code (to account for escaping) + // second match must be the format code character(s) + // + matcher: /()%((%|[a-z]))/i, + // day + a: 'AbbrDayName', + A: 'DayName', + d: 'Date.2', + e: 'Date', + j: 'DayOfYear.3', + u: 'DayOfWeek', + w: 'Day', + // week + U: 'FullWeekOfYear.2', + V: 'IsoWeek.2', + W: 'WeekOfYear.2', + // month + b: 'AbbrMonthName', + B: 'MonthName', + m: 'MonthNumber.2', + h: 'AbbrMonthName', + // year + C: 'Century.2', + y: 'ShortYear.2', + Y: 'FullYear', + // time + H: 'Hours.2', + I: 'Hours12.2', + l: 'Hours12', + p: 'AMPM', + P: 'AmPm', + M: 'Minutes.2', + S: 'Seconds.2', + s: 'Unix', + O: 'TimezoneOffset', + z: 'GmtOffset', + Z: 'TimezoneAbbr' + }, + + shortcuts: { + D: '%m/%d/%y', + F: '%Y-%m-%d', + T: '%H:%M:%S', + X: '%H:%M:%S', + x: '%m/%d/%y', + R: '%H:%M', + r: '%I:%M:%S %p', + t: '\t', + n: '\n', + '%': '%' + } + }; + // + // Conceptually, the logic implemented here is similar to Ken Snyder's Date Instance Methods. + // I use his idea of a set of parsers which can be regular expressions or functions, + // iterating through those, and then seeing if Date.parse() will create a date. + // The parser expressions and functions are a little different and some bugs have been + // worked out. Also, a lot of "pre-parsing" is done to fix implementation + // variations of Date.parse() between browsers. + // + jsDate.createDate = function(date) { + // if passing in multiple arguments, try Date constructor + if (date == null) { + return new Date(); + } + // If the passed value is already a date object, return it + if (date instanceof Date) { + return date; + } + // if (typeof date == 'number') return new Date(date * 1000); + // If the passed value is an integer, interpret it as a javascript timestamp + if (typeof date == 'number') { + return new Date(date); + } + + // Before passing strings into Date.parse(), have to normalize them for certain conditions. + // If strings are not formatted staccording to the EcmaScript spec, results from Date parse will be implementation dependent. + // + // For example: + // * FF and Opera assume 2 digit dates are pre y2k, Chome assumes <50 is pre y2k, 50+ is 21st century. + // * Chrome will correctly parse '1984-1-25' into localtime, FF and Opera will not parse. + // * Both FF, Chrome and Opera will parse '1984/1/25' into localtime. + + // remove leading and trailing spaces + var parsable = String(date).replace(/^\s*(.+)\s*$/g, '$1'); + + // replace dahses (-) with slashes (/) in dates like n[nnn]/n[n]/n[nnn] + parsable = parsable.replace(/^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,4})/, "$1/$2/$3"); + + ///////// + // Need to check for '15-Dec-09' also. + // FF will not parse, but Chrome will. + // Chrome will set date to 2009 as well. + ///////// + + // first check for 'dd-mmm-yyyy' or 'dd/mmm/yyyy' like '15-Dec-2010' + parsable = parsable.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{4})/i, "$1 $2 $3"); + + // Now check for 'dd-mmm-yy' or 'dd/mmm/yy' and normalize years to default century. + var match = parsable.match(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i); + if (match && match.length > 3) { + var m3 = parseFloat(match[3]); + var ny = jsDate.config.defaultCentury + m3; + ny = String(ny); + + // now replace 2 digit year with 4 digit year + parsable = parsable.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i, match[1] +' '+ match[2] +' '+ ny); + + } + + // Check for '1/19/70 8:14PM' + // where starts with mm/dd/yy or yy/mm/dd and have something after + // Check if 1st postiion is greater than 31, assume it is year. + // Assme all 2 digit years are 1900's. + // Finally, change them into US style mm/dd/yyyy representations. + match = parsable.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})[^0-9]/); + + function h1(parsable, match) { + var m1 = parseFloat(match[1]); + var m2 = parseFloat(match[2]); + var m3 = parseFloat(match[3]); + var cent = jsDate.config.defaultCentury; + var ny, nd, nm, str; + + if (m1 > 31) { // first number is a year + nd = m3; + nm = m2; + ny = cent + m1; + } + + else { // last number is the year + nd = m2; + nm = m1; + ny = cent + m3; + } + + str = nm+'/'+nd+'/'+ny; + + // now replace 2 digit year with 4 digit year + return parsable.replace(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})/, str); + + } + + if (match && match.length > 3) { + parsable = h1(parsable, match); + } + + // Now check for '1/19/70' with nothing after and do as above + var match = parsable.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})$/); + + if (match && match.length > 3) { + parsable = h1(parsable, match); + } + + + var i = 0; + var length = jsDate.matchers.length; + var pattern, + ms, + current = parsable, + obj; + while (i < length) { + ms = Date.parse(current); + if (!isNaN(ms)) { + return new Date(ms); + } + pattern = jsDate.matchers[i]; + if (typeof pattern == 'function') { + obj = pattern.call(jsDate, current); + if (obj instanceof Date) { + return obj; + } + } else { + current = parsable.replace(pattern[0], pattern[1]); + } + i++; + } + return NaN; + }; + + + /** + * @static + * Handy static utility function to return the number of days in a given month. + * @param {Integer} year Year + * @param {Integer} month Month (1-12) + * @returns {Integer} Number of days in the month. + */ + // + // handy utility method Borrowed right from Ken Snyder's Date Instance Mehtods. + // + jsDate.daysInMonth = function(year, month) { + if (month == 2) { + return new Date(year, 1, 29).getDate() == 29 ? 29 : 28; + } + return [undefined,31,undefined,31,30,31,30,31,31,30,31,30,31][month]; + }; + + + // + // An Array of regular expressions or functions that will attempt to match the date string. + // Functions are called with scope of a jsDate instance. + // + jsDate.matchers = [ + // convert dd.mmm.yyyy to mm/dd/yyyy (world date to US date). + [/(3[01]|[0-2]\d)\s*\.\s*(1[0-2]|0\d)\s*\.\s*([1-9]\d{3})/, '$2/$1/$3'], + // convert yyyy-mm-dd to mm/dd/yyyy (ISO date to US date). + [/([1-9]\d{3})\s*-\s*(1[0-2]|0\d)\s*-\s*(3[01]|[0-2]\d)/, '$2/$3/$1'], + // Handle 12 hour or 24 hour time with milliseconds am/pm and optional date part. + function(str) { + var match = str.match(/^(?:(.+)\s+)?([012]?\d)(?:\s*\:\s*(\d\d))?(?:\s*\:\s*(\d\d(\.\d*)?))?\s*(am|pm)?\s*$/i); + // opt. date hour opt. minute opt. second opt. msec opt. am or pm + if (match) { + if (match[1]) { + var d = this.createDate(match[1]); + if (isNaN(d)) { + return; + } + } else { + var d = new Date(); + d.setMilliseconds(0); + } + var hour = parseFloat(match[2]); + if (match[6]) { + hour = match[6].toLowerCase() == 'am' ? (hour == 12 ? 0 : hour) : (hour == 12 ? 12 : hour + 12); + } + d.setHours(hour, parseInt(match[3] || 0, 10), parseInt(match[4] || 0, 10), ((parseFloat(match[5] || 0)) || 0)*1000); + return d; + } + else { + return str; + } + }, + // Handle ISO timestamp with time zone. + function(str) { + var match = str.match(/^(?:(.+))[T|\s+]([012]\d)(?:\:(\d\d))(?:\:(\d\d))(?:\.\d+)([\+\-]\d\d\:\d\d)$/i); + if (match) { + if (match[1]) { + var d = this.createDate(match[1]); + if (isNaN(d)) { + return; + } + } else { + var d = new Date(); + d.setMilliseconds(0); + } + var hour = parseFloat(match[2]); + d.setHours(hour, parseInt(match[3], 10), parseInt(match[4], 10), parseFloat(match[5])*1000); + return d; + } + else { + return str; + } + }, + // Try to match ambiguous strings like 12/8/22. + // Use FF date assumption that 2 digit years are 20th century (i.e. 1900's). + // This may be redundant with pre processing of date already performed. + function(str) { + var match = str.match(/^([0-3]?\d)\s*[-\/.\s]{1}\s*([a-zA-Z]{3,9})\s*[-\/.\s]{1}\s*([0-3]?\d)$/); + if (match) { + var d = new Date(); + var cent = jsDate.config.defaultCentury; + var m1 = parseFloat(match[1]); + var m3 = parseFloat(match[3]); + var ny, nd, nm; + if (m1 > 31) { // first number is a year + nd = m3; + ny = cent + m1; + } + + else { // last number is the year + nd = m1; + ny = cent + m3; + } + + var nm = inArray(match[2], jsDate.regional[jsDate.regional.getLocale()]["monthNamesShort"]); + + if (nm == -1) { + nm = inArray(match[2], jsDate.regional[jsDate.regional.getLocale()]["monthNames"]); + } + + d.setFullYear(ny, nm, nd); + d.setHours(0,0,0,0); + return d; + } + + else { + return str; + } + } + ]; + + // + // I think John Reisig published this method on his blog, ejohn. + // + function inArray( elem, array ) { + if ( array.indexOf ) { + return array.indexOf( elem ); + } + + for ( var i = 0, length = array.length; i < length; i++ ) { + if ( array[ i ] === elem ) { + return i; + } + } + + return -1; + } + + // + // Thanks to Kangax, Christian Sciberras and Stack Overflow for this method. + // + function get_type(thing){ + if(thing===null) return "[object Null]"; // special case + return Object.prototype.toString.call(thing); + } + + $.jsDate = jsDate; + + + /** + * JavaScript printf/sprintf functions. + * + * This code has been adapted from the publicly available sprintf methods + * by Ash Searle. His original header follows: + * + * This code is unrestricted: you are free to use it however you like. + * + * The functions should work as expected, performing left or right alignment, + * truncating strings, outputting numbers with a required precision etc. + * + * For complex cases, these functions follow the Perl implementations of + * (s)printf, allowing arguments to be passed out-of-order, and to set the + * precision or length of the output based on arguments instead of fixed + * numbers. + * + * See http://perldoc.perl.org/functions/sprintf.html for more information. + * + * Implemented: + * - zero and space-padding + * - right and left-alignment, + * - base X prefix (binary, octal and hex) + * - positive number prefix + * - (minimum) width + * - precision / truncation / maximum width + * - out of order arguments + * + * Not implemented (yet): + * - vector flag + * - size (bytes, words, long-words etc.) + * + * Will not implement: + * - %n or %p (no pass-by-reference in JavaScript) + * + * @version 2007.04.27 + * @author Ash Searle + * + * You can see the original work and comments on his blog: + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + */ + + /** + * @Modifications 2009.05.26 + * @author Chris Leonello + * + * Added %p %P specifier + * Acts like %g or %G but will not add more significant digits to the output than present in the input. + * Example: + * Format: '%.3p', Input: 0.012, Output: 0.012 + * Format: '%.3g', Input: 0.012, Output: 0.0120 + * Format: '%.4p', Input: 12.0, Output: 12.0 + * Format: '%.4g', Input: 12.0, Output: 12.00 + * Format: '%.4p', Input: 4.321e-5, Output: 4.321e-5 + * Format: '%.4g', Input: 4.321e-5, Output: 4.3210e-5 + * + * Example: + * >>> $.jqplot.sprintf('%.2f, %d', 23.3452, 43.23) + * "23.35, 43" + * >>> $.jqplot.sprintf("no value: %n, decimal with thousands separator: %'d", 23.3452, 433524) + * "no value: , decimal with thousands separator: 433,524" + */ + $.jqplot.sprintf = function() { + function pad(str, len, chr, leftJustify) { + var padding = (str.length >= len) ? '' : Array(1 + len - str.length >>> 0).join(chr); + return leftJustify ? str + padding : padding + str; + + } + + function thousand_separate(value) { + var value_str = new String(value); + for (var i=10; i>0; i--) { + if (value_str == (value_str = value_str.replace(/^(\d+)(\d{3})/, "$1"+$.jqplot.sprintf.thousandsSeparator+"$2"))) break; + } + return value_str; + } + + function justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace) { + var diff = minWidth - value.length; + if (diff > 0) { + var spchar = ' '; + if (htmlSpace) { spchar = ' '; } + if (leftJustify || !zeroPad) { + value = pad(value, minWidth, spchar, leftJustify); + } else { + value = value.slice(0, prefix.length) + pad('', diff, '0', true) + value.slice(prefix.length); + } + } + return value; + } + + function formatBaseX(value, base, prefix, leftJustify, minWidth, precision, zeroPad, htmlSpace) { + // Note: casts negative numbers to positive ones + var number = value >>> 0; + prefix = prefix && number && {'2': '0b', '8': '0', '16': '0x'}[base] || ''; + value = prefix + pad(number.toString(base), precision || 0, '0', false); + return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace); + } + + function formatString(value, leftJustify, minWidth, precision, zeroPad, htmlSpace) { + if (precision != null) { + value = value.slice(0, precision); + } + return justify(value, '', leftJustify, minWidth, zeroPad, htmlSpace); + } + + var a = arguments, i = 0, format = a[i++]; + + return format.replace($.jqplot.sprintf.regex, function(substring, valueIndex, flags, minWidth, _, precision, type) { + if (substring == '%%') { return '%'; } + + // parse flags + var leftJustify = false, positivePrefix = '', zeroPad = false, prefixBaseX = false, htmlSpace = false, thousandSeparation = false; + for (var j = 0; flags && j < flags.length; j++) switch (flags.charAt(j)) { + case ' ': positivePrefix = ' '; break; + case '+': positivePrefix = '+'; break; + case '-': leftJustify = true; break; + case '0': zeroPad = true; break; + case '#': prefixBaseX = true; break; + case '&': htmlSpace = true; break; + case '\'': thousandSeparation = true; break; + } + + // parameters may be null, undefined, empty-string or real valued + // we want to ignore null, undefined and empty-string values + + if (!minWidth) { + minWidth = 0; + } + else if (minWidth == '*') { + minWidth = +a[i++]; + } + else if (minWidth.charAt(0) == '*') { + minWidth = +a[minWidth.slice(1, -1)]; + } + else { + minWidth = +minWidth; + } + + // Note: undocumented perl feature: + if (minWidth < 0) { + minWidth = -minWidth; + leftJustify = true; + } + + if (!isFinite(minWidth)) { + throw new Error('$.jqplot.sprintf: (minimum-)width must be finite'); + } + + if (!precision) { + precision = 'fFeE'.indexOf(type) > -1 ? 6 : (type == 'd') ? 0 : void(0); + } + else if (precision == '*') { + precision = +a[i++]; + } + else if (precision.charAt(0) == '*') { + precision = +a[precision.slice(1, -1)]; + } + else { + precision = +precision; + } + + // grab value using valueIndex if required? + var value = valueIndex ? a[valueIndex.slice(0, -1)] : a[i++]; + + switch (type) { + case 's': { + if (value == null) { + return ''; + } + return formatString(String(value), leftJustify, minWidth, precision, zeroPad, htmlSpace); + } + case 'c': return formatString(String.fromCharCode(+value), leftJustify, minWidth, precision, zeroPad, htmlSpace); + case 'b': return formatBaseX(value, 2, prefixBaseX, leftJustify, minWidth, precision, zeroPad,htmlSpace); + case 'o': return formatBaseX(value, 8, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace); + case 'x': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace); + case 'X': return formatBaseX(value, 16, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace).toUpperCase(); + case 'u': return formatBaseX(value, 10, prefixBaseX, leftJustify, minWidth, precision, zeroPad, htmlSpace); + case 'i': { + var number = parseInt(+value, 10); + if (isNaN(number)) { + return ''; + } + var prefix = number < 0 ? '-' : positivePrefix; + var number_str = thousandSeparation ? thousand_separate(String(Math.abs(number))): String(Math.abs(number)); + value = prefix + pad(number_str, precision, '0', false); + //value = prefix + pad(String(Math.abs(number)), precision, '0', false); + return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace); + } + case 'd': { + var number = Math.round(+value); + if (isNaN(number)) { + return ''; + } + var prefix = number < 0 ? '-' : positivePrefix; + var number_str = thousandSeparation ? thousand_separate(String(Math.abs(number))): String(Math.abs(number)); + value = prefix + pad(number_str, precision, '0', false); + return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace); + } + case 'e': + case 'E': + case 'f': + case 'F': + case 'g': + case 'G': + { + var number = +value; + if (isNaN(number)) { + return ''; + } + var prefix = number < 0 ? '-' : positivePrefix; + var method = ['toExponential', 'toFixed', 'toPrecision']['efg'.indexOf(type.toLowerCase())]; + var textTransform = ['toString', 'toUpperCase']['eEfFgG'.indexOf(type) % 2]; + var number_str = Math.abs(number)[method](precision); + number_str = thousandSeparation ? thousand_separate(number_str): number_str; + value = prefix + number_str; + var justified = justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace)[textTransform](); + + if ($.jqplot.sprintf.decimalMark !== '.' && $.jqplot.sprintf.decimalMark !== $.jqplot.sprintf.thousandsSeparator) { + return justified.replace(/\./, $.jqplot.sprintf.decimalMark); + } else { + return justified; + } + } + case 'p': + case 'P': + { + // make sure number is a number + var number = +value; + if (isNaN(number)) { + return ''; + } + var prefix = number < 0 ? '-' : positivePrefix; + + var parts = String(Number(Math.abs(number)).toExponential()).split(/e|E/); + var sd = (parts[0].indexOf('.') != -1) ? parts[0].length - 1 : parts[0].length; + var zeros = (parts[1] < 0) ? -parts[1] - 1 : 0; + + if (Math.abs(number) < 1) { + if (sd + zeros <= precision) { + value = prefix + Math.abs(number).toPrecision(sd); + } + else { + if (sd <= precision - 1) { + value = prefix + Math.abs(number).toExponential(sd-1); + } + else { + value = prefix + Math.abs(number).toExponential(precision-1); + } + } + } + else { + var prec = (sd <= precision) ? sd : precision; + value = prefix + Math.abs(number).toPrecision(prec); + } + var textTransform = ['toString', 'toUpperCase']['pP'.indexOf(type) % 2]; + return justify(value, prefix, leftJustify, minWidth, zeroPad, htmlSpace)[textTransform](); + } + case 'n': return ''; + default: return substring; + } + }); + }; + + $.jqplot.sprintf.thousandsSeparator = ','; + // Specifies the decimal mark for floating point values. By default a period '.' + // is used. If you change this value to for example a comma be sure to also + // change the thousands separator or else this won't work since a simple String + // replace is used (replacing all periods with the mark specified here). + $.jqplot.sprintf.decimalMark = '.'; + + $.jqplot.sprintf.regex = /%%|%(\d+\$)?([-+#0&\' ]*)(\*\d+\$|\*|\d+)?(\.(\*\d+\$|\*|\d+))?([nAscboxXuidfegpEGP])/g; + + $.jqplot.getSignificantFigures = function(number) { + var parts = String(Number(Math.abs(number)).toExponential()).split(/e|E/); + // total significant digits + var sd = (parts[0].indexOf('.') != -1) ? parts[0].length - 1 : parts[0].length; + var zeros = (parts[1] < 0) ? -parts[1] - 1 : 0; + // exponent + var expn = parseInt(parts[1], 10); + // digits to the left of the decimal place + var dleft = (expn + 1 > 0) ? expn + 1 : 0; + // digits to the right of the decimal place + var dright = (sd <= dleft) ? 0 : sd - expn - 1; + return {significantDigits: sd, digitsLeft: dleft, digitsRight: dright, zeros: zeros, exponent: expn} ; + }; + + $.jqplot.getPrecision = function(number) { + return $.jqplot.getSignificantFigures(number).digitsRight; + }; + +})(jQuery); + + + var backCompat = $.uiBackCompat !== false; + + $.jqplot.effects = { + effect: {} + }; + + // prefix used for storing data on .data() + var dataSpace = "jqplot.storage."; + + /******************************************************************************/ + /*********************************** EFFECTS **********************************/ + /******************************************************************************/ + + $.extend( $.jqplot.effects, { + version: "1.9pre", + + // Saves a set of properties in a data storage + save: function( element, set ) { + for( var i=0; i < set.length; i++ ) { + if ( set[ i ] !== null ) { + element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); + } + } + }, + + // Restores a set of previously saved properties from a data storage + restore: function( element, set ) { + for( var i=0; i < set.length; i++ ) { + if ( set[ i ] !== null ) { + element.css( set[ i ], element.data( dataSpace + set[ i ] ) ); + } + } + }, + + setMode: function( el, mode ) { + if (mode === "toggle") { + mode = el.is( ":hidden" ) ? "show" : "hide"; + } + return mode; + }, + + // Wraps the element around a wrapper that copies position properties + createWrapper: function( element ) { + + // if the element is already wrapped, return it + if ( element.parent().is( ".ui-effects-wrapper" )) { + return element.parent(); + } + + // wrap the element + var props = { + width: element.outerWidth(true), + height: element.outerHeight(true), + "float": element.css( "float" ) + }, + wrapper = $( "<div></div>" ) + .addClass( "ui-effects-wrapper" ) + .css({ + fontSize: "100%", + background: "transparent", + border: "none", + margin: 0, + padding: 0 + }), + // Store the size in case width/height are defined in % - Fixes #5245 + size = { + width: element.width(), + height: element.height() + }, + active = document.activeElement; + + element.wrap( wrapper ); + + // Fixes #7595 - Elements lose focus when wrapped. + if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { + $( active ).focus(); + } + + wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element + + // transfer positioning properties to the wrapper + if ( element.css( "position" ) === "static" ) { + wrapper.css({ position: "relative" }); + element.css({ position: "relative" }); + } else { + $.extend( props, { + position: element.css( "position" ), + zIndex: element.css( "z-index" ) + }); + $.each([ "top", "left", "bottom", "right" ], function(i, pos) { + props[ pos ] = element.css( pos ); + if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { + props[ pos ] = "auto"; + } + }); + element.css({ + position: "relative", + top: 0, + left: 0, + right: "auto", + bottom: "auto" + }); + } + element.css(size); + + return wrapper.css( props ).show(); + }, + + removeWrapper: function( element ) { + var active = document.activeElement; + + if ( element.parent().is( ".ui-effects-wrapper" ) ) { + element.parent().replaceWith( element ); + + // Fixes #7595 - Elements lose focus when wrapped. + if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { + $( active ).focus(); + } + } + + + return element; + } + }); + + // return an effect options object for the given parameters: + function _normalizeArguments( effect, options, speed, callback ) { + + // short path for passing an effect options object: + if ( $.isPlainObject( effect ) ) { + return effect; + } + + // convert to an object + effect = { effect: effect }; + + // catch (effect) + if ( options === undefined ) { + options = {}; + } + + // catch (effect, callback) + if ( $.isFunction( options ) ) { + callback = options; + speed = null; + options = {}; + } + + // catch (effect, speed, ?) + if ( $.type( options ) === "number" || $.fx.speeds[ options ]) { + callback = speed; + speed = options; + options = {}; + } + + // catch (effect, options, callback) + if ( $.isFunction( speed ) ) { + callback = speed; + speed = null; + } + + // add options to effect + if ( options ) { + $.extend( effect, options ); + } + + speed = speed || options.duration; + effect.duration = $.fx.off ? 0 : typeof speed === "number" + ? speed : speed in $.fx.speeds ? $.fx.speeds[ speed ] : $.fx.speeds._default; + + effect.complete = callback || options.complete; + + return effect; + } + + function standardSpeed( speed ) { + // valid standard speeds + if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) { + return true; + } + + // invalid strings - treat as "normal" speed + if ( typeof speed === "string" && !$.jqplot.effects.effect[ speed ] ) { + // TODO: remove in 2.0 (#7115) + if ( backCompat && $.jqplot.effects[ speed ] ) { + return false; + } + return true; + } + + return false; + } + + $.fn.extend({ + jqplotEffect: function( effect, options, speed, callback ) { + var args = _normalizeArguments.apply( this, arguments ), + mode = args.mode, + queue = args.queue, + effectMethod = $.jqplot.effects.effect[ args.effect ], + + // DEPRECATED: remove in 2.0 (#7115) + oldEffectMethod = !effectMethod && backCompat && $.jqplot.effects[ args.effect ]; + + if ( $.fx.off || !( effectMethod || oldEffectMethod ) ) { + // delegate to the original method (e.g., .show()) if possible + if ( mode ) { + return this[ mode ]( args.duration, args.complete ); + } else { + return this.each( function() { + if ( args.complete ) { + args.complete.call( this ); + } + }); + } + } + + function run( next ) { + var elem = $( this ), + complete = args.complete, + mode = args.mode; + + function done() { + if ( $.isFunction( complete ) ) { + complete.call( elem[0] ); + } + if ( $.isFunction( next ) ) { + next(); + } + } + + // if the element is hiddden and mode is hide, + // or element is visible and mode is show + if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { + done(); + } else { + effectMethod.call( elem[0], args, done ); + } + } + + // TODO: remove this check in 2.0, effectMethod will always be true + if ( effectMethod ) { + return queue === false ? this.each( run ) : this.queue( queue || "fx", run ); + } else { + // DEPRECATED: remove in 2.0 (#7115) + return oldEffectMethod.call(this, { + options: args, + duration: args.duration, + callback: args.complete, + mode: args.mode + }); + } + } + }); + + + + + var rvertical = /up|down|vertical/, + rpositivemotion = /up|left|vertical|horizontal/; + + $.jqplot.effects.effect.blind = function( o, done ) { + // Create element + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], + mode = $.jqplot.effects.setMode( el, o.mode || "hide" ), + direction = o.direction || "up", + vertical = rvertical.test( direction ), + ref = vertical ? "height" : "width", + ref2 = vertical ? "top" : "left", + motion = rpositivemotion.test( direction ), + animation = {}, + show = mode === "show", + wrapper, distance, top; + + // // if already wrapped, the wrapper's properties are my property. #6245 + if ( el.parent().is( ".ui-effects-wrapper" ) ) { + $.jqplot.effects.save( el.parent(), props ); + } else { + $.jqplot.effects.save( el, props ); + } + el.show(); + top = parseInt(el.css('top'), 10); + wrapper = $.jqplot.effects.createWrapper( el ).css({ + overflow: "hidden" + }); + + distance = vertical ? wrapper[ ref ]() + top : wrapper[ ref ](); + + animation[ ref ] = show ? String(distance) : '0'; + if ( !motion ) { + el + .css( vertical ? "bottom" : "right", 0 ) + .css( vertical ? "top" : "left", "" ) + .css({ position: "absolute" }); + animation[ ref2 ] = show ? '0' : String(distance); + } + + // // start at 0 if we are showing + if ( show ) { + wrapper.css( ref, 0 ); + if ( ! motion ) { + wrapper.css( ref2, distance ); + } + } + + // // Animate + wrapper.animate( animation, { + duration: o.duration, + easing: o.easing, + queue: false, + complete: function() { + if ( mode === "hide" ) { + el.hide(); + } + $.jqplot.effects.restore( el, props ); + $.jqplot.effects.removeWrapper( el ); + done(); + } + }); + + }; + + diff --git a/hugo/js/jqplot/plugins/jqplot.barRenderer.js b/hugo/js/jqplot/plugins/jqplot.barRenderer.js new file mode 100644 index 0000000..c1be235 --- /dev/null +++ b/hugo/js/jqplot/plugins/jqplot.barRenderer.js @@ -0,0 +1,797 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.4 + * Revision: 1121 + * + * Copyright (c) 2009-2012 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + + // Class: $.jqplot.BarRenderer + // A plugin renderer for jqPlot to draw a bar plot. + // Draws series as a line. + + $.jqplot.BarRenderer = function(){ + $.jqplot.LineRenderer.call(this); + }; + + $.jqplot.BarRenderer.prototype = new $.jqplot.LineRenderer(); + $.jqplot.BarRenderer.prototype.constructor = $.jqplot.BarRenderer; + + // called with scope of series. + $.jqplot.BarRenderer.prototype.init = function(options, plot) { + // Group: Properties + // + // prop: barPadding + // Number of pixels between adjacent bars at the same axis value. + this.barPadding = 8; + // prop: barMargin + // Number of pixels between groups of bars at adjacent axis values. + this.barMargin = 10; + // prop: barDirection + // 'vertical' = up and down bars, 'horizontal' = side to side bars + this.barDirection = 'vertical'; + // prop: barWidth + // Width of the bar in pixels (auto by devaul). null = calculated automatically. + this.barWidth = null; + // prop: shadowOffset + // offset of the shadow from the slice and offset of + // each succesive stroke of the shadow from the last. + this.shadowOffset = 2; + // prop: shadowDepth + // number of strokes to apply to the shadow, + // each stroke offset shadowOffset from the last. + this.shadowDepth = 5; + // prop: shadowAlpha + // transparency of the shadow (0 = transparent, 1 = opaque) + this.shadowAlpha = 0.08; + // prop: waterfall + // true to enable waterfall plot. + this.waterfall = false; + // prop: groups + // group bars into this many groups + this.groups = 1; + // prop: varyBarColor + // true to color each bar of a series separately rather than + // have every bar of a given series the same color. + // If used for non-stacked multiple series bar plots, user should + // specify a separate 'seriesColors' array for each series. + // Otherwise, each series will set their bars to the same color array. + // This option has no Effect for stacked bar charts and is disabled. + this.varyBarColor = false; + // prop: highlightMouseOver + // True to highlight slice when moused over. + // This must be false to enable highlightMouseDown to highlight when clicking on a slice. + this.highlightMouseOver = true; + // prop: highlightMouseDown + // True to highlight when a mouse button is pressed over a slice. + // This will be disabled if highlightMouseOver is true. + this.highlightMouseDown = false; + // prop: highlightColors + // an array of colors to use when highlighting a bar. + this.highlightColors = []; + // prop: transposedData + // NOT IMPLEMENTED YET. True if this is a horizontal bar plot and + // x and y values are "transposed". Tranposed, or "swapped", data is + // required prior to rev. 894 builds of jqPlot with horizontal bars. + // Allows backward compatability of bar renderer horizontal bars with + // old style data sets. + this.transposedData = true; + this.renderer.animation = { + show: false, + direction: 'down', + speed: 3000, + _supported: true + }; + this._type = 'bar'; + + // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver + if (options.highlightMouseDown && options.highlightMouseOver == null) { + options.highlightMouseOver = false; + } + + ////// + // This is probably wrong here. + // After going back and forth on wether renderer should be the thing + // or extend the thing, it seems that it it best if it is a property + // on the thing. This should be something that is commonized + // among series renderers in the future. + ////// + $.extend(true, this, options); + + // really should probably do this + $.extend(true, this.renderer, options); + // fill is still needed to properly draw the legend. + // bars have to be filled. + this.fill = true; + + // if horizontal bar and animating, reset the default direction + if (this.barDirection === 'horizontal' && this.rendererOptions.animation && this.rendererOptions.animation.direction == null) { + this.renderer.animation.direction = 'left'; + } + + if (this.waterfall) { + this.fillToZero = false; + this.disableStack = true; + } + + if (this.barDirection == 'vertical' ) { + this._primaryAxis = '_xaxis'; + this._stackAxis = 'y'; + this.fillAxis = 'y'; + } + else { + this._primaryAxis = '_yaxis'; + this._stackAxis = 'x'; + this.fillAxis = 'x'; + } + // index of the currenty highlighted point, if any + this._highlightedPoint = null; + // total number of values for all bar series, total number of bar series, and position of this series + this._plotSeriesInfo = null; + // Array of actual data colors used for each data point. + this._dataColors = []; + this._barPoints = []; + + // set the shape renderer options + var opts = {lineJoin:'miter', lineCap:'round', fill:true, isarc:false, strokeStyle:this.color, fillStyle:this.color, closePath:this.fill}; + this.renderer.shapeRenderer.init(opts); + // set the shadow renderer options + var sopts = {lineJoin:'miter', lineCap:'round', fill:true, isarc:false, angle:this.shadowAngle, offset:this.shadowOffset, alpha:this.shadowAlpha, depth:this.shadowDepth, closePath:this.fill}; + this.renderer.shadowRenderer.init(sopts); + + plot.postInitHooks.addOnce(postInit); + plot.postDrawHooks.addOnce(postPlotDraw); + plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove); + plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown); + plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp); + plot.eventListenerHooks.addOnce('jqplotClick', handleClick); + plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick); + }; + + // called with scope of series + function barPreInit(target, data, seriesDefaults, options) { + if (this.rendererOptions.barDirection == 'horizontal') { + this._stackAxis = 'x'; + this._primaryAxis = '_yaxis'; + } + if (this.rendererOptions.waterfall == true) { + this._data = $.extend(true, [], this.data); + var sum = 0; + var pos = (!this.rendererOptions.barDirection || this.rendererOptions.barDirection === 'vertical' || this.transposedData === false) ? 1 : 0; + for(var i=0; i<this.data.length; i++) { + sum += this.data[i][pos]; + if (i>0) { + this.data[i][pos] += this.data[i-1][pos]; + } + } + this.data[this.data.length] = (pos == 1) ? [this.data.length+1, sum] : [sum, this.data.length+1]; + this._data[this._data.length] = (pos == 1) ? [this._data.length+1, sum] : [sum, this._data.length+1]; + } + if (this.rendererOptions.groups > 1) { + this.breakOnNull = true; + var l = this.data.length; + var skip = parseInt(l/this.rendererOptions.groups, 10); + var count = 0; + for (var i=skip; i<l; i+=skip) { + this.data.splice(i+count, 0, [null, null]); + this._plotData.splice(i+count, 0, [null, null]); + this._stackData.splice(i+count, 0, [null, null]); + count++; + } + for (i=0; i<this.data.length; i++) { + if (this._primaryAxis == '_xaxis') { + this.data[i][0] = i+1; + this._plotData[i][0] = i+1; + this._stackData[i][0] = i+1; + } + else { + this.data[i][1] = i+1; + this._plotData[i][1] = i+1; + this._stackData[i][1] = i+1; + } + } + } + } + + $.jqplot.preSeriesInitHooks.push(barPreInit); + + // needs to be called with scope of series, not renderer. + $.jqplot.BarRenderer.prototype.calcSeriesNumbers = function() { + var nvals = 0; + var nseries = 0; + var paxis = this[this._primaryAxis]; + var s, series, pos; + // loop through all series on this axis + for (var i=0; i < paxis._series.length; i++) { + series = paxis._series[i]; + if (series === this) { + pos = i; + } + // is the series rendered as a bar? + if (series.renderer.constructor == $.jqplot.BarRenderer) { + // gridData may not be computed yet, use data length insted + nvals += series.data.length; + nseries += 1; + } + } + // return total number of values for all bar series, total number of bar series, and position of this series + return [nvals, nseries, pos]; + }; + + $.jqplot.BarRenderer.prototype.setBarWidth = function() { + // need to know how many data values we have on the approprate axis and figure it out. + var i; + var nvals = 0; + var nseries = 0; + var paxis = this[this._primaryAxis]; + var s, series, pos; + var temp = this._plotSeriesInfo = this.renderer.calcSeriesNumbers.call(this); + nvals = temp[0]; + nseries = temp[1]; + var nticks = paxis.numberTicks; + var nbins = (nticks-1)/2; + // so, now we have total number of axis values. + if (paxis.name == 'xaxis' || paxis.name == 'x2axis') { + if (this._stack) { + this.barWidth = (paxis._offsets.max - paxis._offsets.min) / nvals * nseries - this.barMargin; + } + else { + this.barWidth = ((paxis._offsets.max - paxis._offsets.min)/nbins - this.barPadding * (nseries-1) - this.barMargin*2)/nseries; + // this.barWidth = (paxis._offsets.max - paxis._offsets.min) / nvals - this.barPadding - this.barMargin/nseries; + } + } + else { + if (this._stack) { + this.barWidth = (paxis._offsets.min - paxis._offsets.max) / nvals * nseries - this.barMargin; + } + else { + this.barWidth = ((paxis._offsets.min - paxis._offsets.max)/nbins - this.barPadding * (nseries-1) - this.barMargin*2)/nseries; + // this.barWidth = (paxis._offsets.min - paxis._offsets.max) / nvals - this.barPadding - this.barMargin/nseries; + } + } + return [nvals, nseries]; + }; + + function computeHighlightColors (colors) { + var ret = []; + for (var i=0; i<colors.length; i++){ + var rgba = $.jqplot.getColorComponents(colors[i]); + var newrgb = [rgba[0], rgba[1], rgba[2]]; + var sum = newrgb[0] + newrgb[1] + newrgb[2]; + for (var j=0; j<3; j++) { + // when darkening, lowest color component can be is 60. + newrgb[j] = (sum > 570) ? newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]); + newrgb[j] = parseInt(newrgb[j], 10); + } + ret.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')'); + } + return ret; + } + + function getStart(sidx, didx, comp, plot, axis) { + // check if sign change + var seriesIndex = sidx, + prevSeriesIndex = sidx - 1, + start, + prevVal, + aidx = (axis === 'x') ? 0 : 1; + + // is this not the first series? + if (seriesIndex > 0) { + prevVal = plot.series[prevSeriesIndex]._plotData[didx][aidx]; + + // is there a sign change + if ((comp * prevVal) < 0) { + start = getStart(prevSeriesIndex, didx, comp, plot, axis); + } + + // no sign change. + else { + start = plot.series[prevSeriesIndex].gridData[didx][aidx]; + } + + } + + // if first series, return value at 0 + else { + + start = (aidx === 0) ? plot.series[seriesIndex]._xaxis.series_u2p(0) : plot.series[seriesIndex]._yaxis.series_u2p(0); + } + + return start; + } + + + $.jqplot.BarRenderer.prototype.draw = function(ctx, gridData, options, plot) { + var i; + // Ughhh, have to make a copy of options b/c it may be modified later. + var opts = $.extend({}, options); + var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow; + var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine; + var fill = (opts.fill != undefined) ? opts.fill : this.fill; + var xaxis = this.xaxis; + var yaxis = this.yaxis; + var xp = this._xaxis.series_u2p; + var yp = this._yaxis.series_u2p; + var pointx, pointy; + // clear out data colors. + this._dataColors = []; + this._barPoints = []; + + if (this.barWidth == null) { + this.renderer.setBarWidth.call(this); + } + + var temp = this._plotSeriesInfo = this.renderer.calcSeriesNumbers.call(this); + var nvals = temp[0]; + var nseries = temp[1]; + var pos = temp[2]; + var points = []; + + if (this._stack) { + this._barNudge = 0; + } + else { + this._barNudge = (-Math.abs(nseries/2 - 0.5) + pos) * (this.barWidth + this.barPadding); + } + if (showLine) { + var negativeColors = new $.jqplot.ColorGenerator(this.negativeSeriesColors); + var positiveColors = new $.jqplot.ColorGenerator(this.seriesColors); + var negativeColor = negativeColors.get(this.index); + if (! this.useNegativeColors) { + negativeColor = opts.fillStyle; + } + var positiveColor = opts.fillStyle; + var base; + var xstart; + var ystart; + + if (this.barDirection == 'vertical') { + for (var i=0; i<gridData.length; i++) { + if (!this._stack && this.data[i][1] == null) { + continue; + } + points = []; + base = gridData[i][0] + this._barNudge; + + // stacked + if (this._stack && this._prevGridData.length) { + ystart = getStart(this.index, i, this._plotData[i][1], plot, 'y'); + } + + // not stacked + else { + if (this.fillToZero) { + ystart = this._yaxis.series_u2p(0); + } + else if (this.waterfall && i > 0 && i < this.gridData.length-1) { + ystart = this.gridData[i-1][1]; + } + else if (this.waterfall && i == 0 && i < this.gridData.length-1) { + if (this._yaxis.min <= 0 && this._yaxis.max >= 0) { + ystart = this._yaxis.series_u2p(0); + } + else if (this._yaxis.min > 0) { + ystart = ctx.canvas.height; + } + else { + ystart = 0; + } + } + else if (this.waterfall && i == this.gridData.length - 1) { + if (this._yaxis.min <= 0 && this._yaxis.max >= 0) { + ystart = this._yaxis.series_u2p(0); + } + else if (this._yaxis.min > 0) { + ystart = ctx.canvas.height; + } + else { + ystart = 0; + } + } + else { + ystart = ctx.canvas.height; + } + } + if ((this.fillToZero && this._plotData[i][1] < 0) || (this.waterfall && this._data[i][1] < 0)) { + if (this.varyBarColor && !this._stack) { + if (this.useNegativeColors) { + opts.fillStyle = negativeColors.next(); + } + else { + opts.fillStyle = positiveColors.next(); + } + } + else { + opts.fillStyle = negativeColor; + } + } + else { + if (this.varyBarColor && !this._stack) { + opts.fillStyle = positiveColors.next(); + } + else { + opts.fillStyle = positiveColor; + } + } + + if (!this.fillToZero || this._plotData[i][1] >= 0) { + points.push([base-this.barWidth/2, ystart]); + points.push([base-this.barWidth/2, gridData[i][1]]); + points.push([base+this.barWidth/2, gridData[i][1]]); + points.push([base+this.barWidth/2, ystart]); + } + // for negative bars make sure points are always ordered clockwise + else { + points.push([base-this.barWidth/2, gridData[i][1]]); + points.push([base-this.barWidth/2, ystart]); + points.push([base+this.barWidth/2, ystart]); + points.push([base+this.barWidth/2, gridData[i][1]]); + } + this._barPoints.push(points); + // now draw the shadows if not stacked. + // for stacked plots, they are predrawn by drawShadow + if (shadow && !this._stack) { + var sopts = $.extend(true, {}, opts); + // need to get rid of fillStyle on shadow. + delete sopts.fillStyle; + this.renderer.shadowRenderer.draw(ctx, points, sopts); + } + var clr = opts.fillStyle || this.color; + this._dataColors.push(clr); + this.renderer.shapeRenderer.draw(ctx, points, opts); + } + } + + else if (this.barDirection == 'horizontal'){ + for (var i=0; i<gridData.length; i++) { + if (!this._stack && this.data[i][0] == null) { + continue; + } + points = []; + base = gridData[i][1] - this._barNudge; + xstart; + + if (this._stack && this._prevGridData.length) { + xstart = getStart(this.index, i, this._plotData[i][0], plot, 'x'); + } + // not stacked + else { + if (this.fillToZero) { + xstart = this._xaxis.series_u2p(0); + } + else if (this.waterfall && i > 0 && i < this.gridData.length-1) { + xstart = this.gridData[i-1][0]; + } + else if (this.waterfall && i == 0 && i < this.gridData.length-1) { + if (this._xaxis.min <= 0 && this._xaxis.max >= 0) { + xstart = this._xaxis.series_u2p(0); + } + else if (this._xaxis.min > 0) { + xstart = 0; + } + else { + xstart = 0; + } + } + else if (this.waterfall && i == this.gridData.length - 1) { + if (this._xaxis.min <= 0 && this._xaxis.max >= 0) { + xstart = this._xaxis.series_u2p(0); + } + else if (this._xaxis.min > 0) { + xstart = 0; + } + else { + xstart = ctx.canvas.width; + } + } + else { + xstart = 0; + } + } + if ((this.fillToZero && this._plotData[i][1] < 0) || (this.waterfall && this._data[i][1] < 0)) { + if (this.varyBarColor && !this._stack) { + if (this.useNegativeColors) { + opts.fillStyle = negativeColors.next(); + } + else { + opts.fillStyle = positiveColors.next(); + } + } + } + else { + if (this.varyBarColor && !this._stack) { + opts.fillStyle = positiveColors.next(); + } + else { + opts.fillStyle = positiveColor; + } + } + + + if (!this.fillToZero || this._plotData[i][0] >= 0) { + points.push([xstart, base + this.barWidth / 2]); + points.push([xstart, base - this.barWidth / 2]); + points.push([gridData[i][0], base - this.barWidth / 2]); + points.push([gridData[i][0], base + this.barWidth / 2]); + } + else { + points.push([gridData[i][0], base + this.barWidth / 2]); + points.push([gridData[i][0], base - this.barWidth / 2]); + points.push([xstart, base - this.barWidth / 2]); + points.push([xstart, base + this.barWidth / 2]); + } + + this._barPoints.push(points); + // now draw the shadows if not stacked. + // for stacked plots, they are predrawn by drawShadow + if (shadow && !this._stack) { + var sopts = $.extend(true, {}, opts); + delete sopts.fillStyle; + this.renderer.shadowRenderer.draw(ctx, points, sopts); + } + var clr = opts.fillStyle || this.color; + this._dataColors.push(clr); + this.renderer.shapeRenderer.draw(ctx, points, opts); + } + } + } + + if (this.highlightColors.length == 0) { + this.highlightColors = $.jqplot.computeHighlightColors(this._dataColors); + } + + else if (typeof(this.highlightColors) == 'string') { + var temp = this.highlightColors; + this.highlightColors = []; + for (var i=0; i<this._dataColors.length; i++) { + this.highlightColors.push(temp); + } + } + + }; + + + // for stacked plots, shadows will be pre drawn by drawShadow. + $.jqplot.BarRenderer.prototype.drawShadow = function(ctx, gridData, options, plot) { + var i; + var opts = (options != undefined) ? options : {}; + var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow; + var showLine = (opts.showLine != undefined) ? opts.showLine : this.showLine; + var fill = (opts.fill != undefined) ? opts.fill : this.fill; + var xaxis = this.xaxis; + var yaxis = this.yaxis; + var xp = this._xaxis.series_u2p; + var yp = this._yaxis.series_u2p; + var pointx, points, pointy, nvals, nseries, pos; + + if (this._stack && this.shadow) { + if (this.barWidth == null) { + this.renderer.setBarWidth.call(this); + } + + var temp = this._plotSeriesInfo = this.renderer.calcSeriesNumbers.call(this); + nvals = temp[0]; + nseries = temp[1]; + pos = temp[2]; + + if (this._stack) { + this._barNudge = 0; + } + else { + this._barNudge = (-Math.abs(nseries/2 - 0.5) + pos) * (this.barWidth + this.barPadding); + } + if (showLine) { + + if (this.barDirection == 'vertical') { + for (var i=0; i<gridData.length; i++) { + if (this.data[i][1] == null) { + continue; + } + points = []; + var base = gridData[i][0] + this._barNudge; + var ystart; + + if (this._stack && this._prevGridData.length) { + ystart = getStart(this.index, i, this._plotData[i][1], plot, 'y'); + } + else { + if (this.fillToZero) { + ystart = this._yaxis.series_u2p(0); + } + else { + ystart = ctx.canvas.height; + } + } + + points.push([base-this.barWidth/2, ystart]); + points.push([base-this.barWidth/2, gridData[i][1]]); + points.push([base+this.barWidth/2, gridData[i][1]]); + points.push([base+this.barWidth/2, ystart]); + this.renderer.shadowRenderer.draw(ctx, points, opts); + } + } + + else if (this.barDirection == 'horizontal'){ + for (var i=0; i<gridData.length; i++) { + if (this.data[i][0] == null) { + continue; + } + points = []; + var base = gridData[i][1] - this._barNudge; + var xstart; + + if (this._stack && this._prevGridData.length) { + xstart = getStart(this.index, i, this._plotData[i][0], plot, 'x'); + } + else { + if (this.fillToZero) { + xstart = this._xaxis.series_u2p(0); + } + else { + xstart = 0; + } + } + + points.push([xstart, base+this.barWidth/2]); + points.push([gridData[i][0], base+this.barWidth/2]); + points.push([gridData[i][0], base-this.barWidth/2]); + points.push([xstart, base-this.barWidth/2]); + this.renderer.shadowRenderer.draw(ctx, points, opts); + } + } + } + + } + }; + + function postInit(target, data, options) { + for (var i=0; i<this.series.length; i++) { + if (this.series[i].renderer.constructor == $.jqplot.BarRenderer) { + // don't allow mouseover and mousedown at same time. + if (this.series[i].highlightMouseOver) { + this.series[i].highlightMouseDown = false; + } + } + } + } + + // called within context of plot + // create a canvas which we can draw on. + // insert it before the eventCanvas, so eventCanvas will still capture events. + function postPlotDraw() { + // Memory Leaks patch + if (this.plugins.barRenderer && this.plugins.barRenderer.highlightCanvas) { + + this.plugins.barRenderer.highlightCanvas.resetCanvas(); + this.plugins.barRenderer.highlightCanvas = null; + } + + this.plugins.barRenderer = {highlightedSeriesIndex:null}; + this.plugins.barRenderer.highlightCanvas = new $.jqplot.GenericCanvas(); + + this.eventCanvas._elem.before(this.plugins.barRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-barRenderer-highlight-canvas', this._plotDimensions, this)); + this.plugins.barRenderer.highlightCanvas.setContext(); + this.eventCanvas._elem.bind('mouseleave', {plot:this}, function (ev) { unhighlight(ev.data.plot); }); + } + + function highlight (plot, sidx, pidx, points) { + var s = plot.series[sidx]; + var canvas = plot.plugins.barRenderer.highlightCanvas; + canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height); + s._highlightedPoint = pidx; + plot.plugins.barRenderer.highlightedSeriesIndex = sidx; + var opts = {fillStyle: s.highlightColors[pidx]}; + s.renderer.shapeRenderer.draw(canvas._ctx, points, opts); + canvas = null; + } + + function unhighlight (plot) { + var canvas = plot.plugins.barRenderer.highlightCanvas; + canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height); + for (var i=0; i<plot.series.length; i++) { + plot.series[i]._highlightedPoint = null; + } + plot.plugins.barRenderer.highlightedSeriesIndex = null; + plot.target.trigger('jqplotDataUnhighlight'); + canvas = null; + } + + + function handleMove(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var evt1 = jQuery.Event('jqplotDataMouseOver'); + evt1.pageX = ev.pageX; + evt1.pageY = ev.pageY; + plot.target.trigger(evt1, ins); + if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.barRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) { + var evt = jQuery.Event('jqplotDataHighlight'); + evt.which = ev.which; + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + highlight (plot, neighbor.seriesIndex, neighbor.pointIndex, neighbor.points); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + } + + function handleMouseDown(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.barRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) { + var evt = jQuery.Event('jqplotDataHighlight'); + evt.which = ev.which; + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + highlight (plot, neighbor.seriesIndex, neighbor.pointIndex, neighbor.points); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + } + + function handleMouseUp(ev, gridpos, datapos, neighbor, plot) { + var idx = plot.plugins.barRenderer.highlightedSeriesIndex; + if (idx != null && plot.series[idx].highlightMouseDown) { + unhighlight(plot); + } + } + + function handleClick(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var evt = jQuery.Event('jqplotDataClick'); + evt.which = ev.which; + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + } + } + + function handleRightClick(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var idx = plot.plugins.barRenderer.highlightedSeriesIndex; + if (idx != null && plot.series[idx].highlightMouseDown) { + unhighlight(plot); + } + var evt = jQuery.Event('jqplotDataRightClick'); + evt.which = ev.which; + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + } + } + + +})(jQuery);
\ No newline at end of file diff --git a/hugo/js/jqplot/plugins/jqplot.byteFormatter.js b/hugo/js/jqplot/plugins/jqplot.byteFormatter.js new file mode 100644 index 0000000..7a18370 --- /dev/null +++ b/hugo/js/jqplot/plugins/jqplot.byteFormatter.js @@ -0,0 +1,46 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * jqplot formatter for byte values + * + * @package phpMyAdmin + */ +(function($) { + "use strict"; + var formatByte = function (val, index) { + var units = [ + PMA_messages.strB, + PMA_messages.strKiB, + PMA_messages.strMiB, + PMA_messages.strGiB, + PMA_messages.strTiB, + PMA_messages.strPiB, + PMA_messages.strEiB + ]; + while (val >= 1024 && index <= 6) { + val /= 1024; + index++; + } + var format = '%.1f'; + if (Math.floor(val) === val) { + format = '%.0f'; + } + return $.jqplot.sprintf( + format + ' ' + units[index], val + ); + }; + /** + * The index indicates what unit the incoming data will be in. + * 0 for bytes, 1 for kilobytes and so on... + */ + $.jqplot.byteFormatter = function (index) { + index = index || 0; + return function (format, val) { + if (typeof val === 'number') { + val = parseFloat(val) || 0; + return formatByte(val, index); + } else { + return String(val); + } + }; + }; +})(jQuery); diff --git a/hugo/js/jqplot/plugins/jqplot.canvasAxisLabelRenderer.js b/hugo/js/jqplot/plugins/jqplot.canvasAxisLabelRenderer.js new file mode 100644 index 0000000..1840439 --- /dev/null +++ b/hugo/js/jqplot/plugins/jqplot.canvasAxisLabelRenderer.js @@ -0,0 +1,203 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.4 + * Revision: 1121 + * + * Copyright (c) 2009-2012 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + /** + * Class: $.jqplot.CanvasAxisLabelRenderer + * Renderer to draw axis labels with a canvas element to support advanced + * featrues such as rotated text. This renderer uses a separate rendering engine + * to draw the text on the canvas. Two modes of rendering the text are available. + * If the browser has native font support for canvas fonts (currently Mozila 3.5 + * and Safari 4), you can enable text rendering with the canvas fillText method. + * You do so by setting the "enableFontSupport" option to true. + * + * Browsers lacking native font support will have the text drawn on the canvas + * using the Hershey font metrics. Even if the "enableFontSupport" option is true + * non-supporting browsers will still render with the Hershey font. + * + */ + $.jqplot.CanvasAxisLabelRenderer = function(options) { + // Group: Properties + + // prop: angle + // angle of text, measured clockwise from x axis. + this.angle = 0; + // name of the axis associated with this tick + this.axis; + // prop: show + // wether or not to show the tick (mark and label). + this.show = true; + // prop: showLabel + // wether or not to show the label. + this.showLabel = true; + // prop: label + // label for the axis. + this.label = ''; + // prop: fontFamily + // CSS spec for the font-family css attribute. + // Applies only to browsers supporting native font rendering in the + // canvas tag. Currently Mozilla 3.5 and Safari 4. + this.fontFamily = '"Trebuchet MS", Arial, Helvetica, sans-serif'; + // prop: fontSize + // CSS spec for font size. + this.fontSize = '11pt'; + // prop: fontWeight + // CSS spec for fontWeight: normal, bold, bolder, lighter or a number 100 - 900 + this.fontWeight = 'normal'; + // prop: fontStretch + // Multiplier to condense or expand font width. + // Applies only to browsers which don't support canvas native font rendering. + this.fontStretch = 1.0; + // prop: textColor + // css spec for the color attribute. + this.textColor = '#666666'; + // prop: enableFontSupport + // true to turn on native canvas font support in Mozilla 3.5+ and Safari 4+. + // If true, label will be drawn with canvas tag native support for fonts. + // If false, label will be drawn with Hershey font metrics. + this.enableFontSupport = true; + // prop: pt2px + // Point to pixel scaling factor, used for computing height of bounding box + // around a label. The labels text renderer has a default setting of 1.4, which + // should be suitable for most fonts. Leave as null to use default. If tops of + // letters appear clipped, increase this. If bounding box seems too big, decrease. + // This is an issue only with the native font renderering capabilities of Mozilla + // 3.5 and Safari 4 since they do not provide a method to determine the font height. + this.pt2px = null; + + this._elem; + this._ctx; + this._plotWidth; + this._plotHeight; + this._plotDimensions = {height:null, width:null}; + + $.extend(true, this, options); + + if (options.angle == null && this.axis != 'xaxis' && this.axis != 'x2axis') { + this.angle = -90; + } + + var ropts = {fontSize:this.fontSize, fontWeight:this.fontWeight, fontStretch:this.fontStretch, fillStyle:this.textColor, angle:this.getAngleRad(), fontFamily:this.fontFamily}; + if (this.pt2px) { + ropts.pt2px = this.pt2px; + } + + if (this.enableFontSupport) { + if ($.jqplot.support_canvas_text()) { + this._textRenderer = new $.jqplot.CanvasFontRenderer(ropts); + } + + else { + this._textRenderer = new $.jqplot.CanvasTextRenderer(ropts); + } + } + else { + this._textRenderer = new $.jqplot.CanvasTextRenderer(ropts); + } + }; + + $.jqplot.CanvasAxisLabelRenderer.prototype.init = function(options) { + $.extend(true, this, options); + this._textRenderer.init({fontSize:this.fontSize, fontWeight:this.fontWeight, fontStretch:this.fontStretch, fillStyle:this.textColor, angle:this.getAngleRad(), fontFamily:this.fontFamily}); + }; + + // return width along the x axis + // will check first to see if an element exists. + // if not, will return the computed text box width. + $.jqplot.CanvasAxisLabelRenderer.prototype.getWidth = function(ctx) { + if (this._elem) { + return this._elem.outerWidth(true); + } + else { + var tr = this._textRenderer; + var l = tr.getWidth(ctx); + var h = tr.getHeight(ctx); + var w = Math.abs(Math.sin(tr.angle)*h) + Math.abs(Math.cos(tr.angle)*l); + return w; + } + }; + + // return height along the y axis. + $.jqplot.CanvasAxisLabelRenderer.prototype.getHeight = function(ctx) { + if (this._elem) { + return this._elem.outerHeight(true); + } + else { + var tr = this._textRenderer; + var l = tr.getWidth(ctx); + var h = tr.getHeight(ctx); + var w = Math.abs(Math.cos(tr.angle)*h) + Math.abs(Math.sin(tr.angle)*l); + return w; + } + }; + + $.jqplot.CanvasAxisLabelRenderer.prototype.getAngleRad = function() { + var a = this.angle * Math.PI/180; + return a; + }; + + $.jqplot.CanvasAxisLabelRenderer.prototype.draw = function(ctx, plot) { + // Memory Leaks patch + if (this._elem) { + if ($.jqplot.use_excanvas && window.G_vmlCanvasManager.uninitElement !== undefined) { + window.G_vmlCanvasManager.uninitElement(this._elem.get(0)); + } + + this._elem.emptyForce(); + this._elem = null; + } + + // create a canvas here, but can't draw on it untill it is appended + // to dom for IE compatability. + var elem = plot.canvasManager.getCanvas(); + + this._textRenderer.setText(this.label, ctx); + var w = this.getWidth(ctx); + var h = this.getHeight(ctx); + elem.width = w; + elem.height = h; + elem.style.width = w; + elem.style.height = h; + + elem = plot.canvasManager.initCanvas(elem); + + this._elem = $(elem); + this._elem.css({ position: 'absolute'}); + this._elem.addClass('jqplot-'+this.axis+'-label'); + + elem = null; + return this._elem; + }; + + $.jqplot.CanvasAxisLabelRenderer.prototype.pack = function() { + this._textRenderer.draw(this._elem.get(0).getContext("2d"), this.label); + }; + +})(jQuery);
\ No newline at end of file diff --git a/hugo/js/jqplot/plugins/jqplot.canvasTextRenderer.js b/hugo/js/jqplot/plugins/jqplot.canvasTextRenderer.js new file mode 100644 index 0000000..53f2530 --- /dev/null +++ b/hugo/js/jqplot/plugins/jqplot.canvasTextRenderer.js @@ -0,0 +1,449 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.4 + * Revision: 1121 + * + * Copyright (c) 2009-2012 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + * included jsDate library by Chris Leonello: + * + * Copyright (c) 2010-2012 Chris Leonello + * + * jsDate is currently available for use in all personal or commercial projects + * under both the MIT and GPL version 2.0 licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * jsDate borrows many concepts and ideas from the Date Instance + * Methods by Ken Snyder along with some parts of Ken's actual code. + * + * Ken's origianl Date Instance Methods and copyright notice: + * + * Ken Snyder (ken d snyder at gmail dot com) + * 2008-09-10 + * version 2.0.2 (http://kendsnyder.com/sandbox/date/) + * Creative Commons Attribution License 3.0 (http://creativecommons.org/licenses/by/3.0/) + * + * jqplotToImage function based on Larry Siden's export-jqplot-to-png.js. + * Larry has generously given permission to adapt his code for inclusion + * into jqPlot. + * + * Larry's original code can be found here: + * + * https://github.com/lsiden/export-jqplot-to-png + * + * + */ + +(function($) { + // This code is a modified version of the canvastext.js code, copyright below: + // + // This code is released to the public domain by Jim Studt, 2007. + // He may keep some sort of up to date copy at http://www.federated.com/~jim/canvastext/ + // + $.jqplot.CanvasTextRenderer = function(options){ + this.fontStyle = 'normal'; // normal, italic, oblique [not implemented] + this.fontVariant = 'normal'; // normal, small caps [not implemented] + this.fontWeight = 'normal'; // normal, bold, bolder, lighter, 100 - 900 + this.fontSize = '10px'; + this.fontFamily = 'sans-serif'; + this.fontStretch = 1.0; + this.fillStyle = '#666666'; + this.angle = 0; + this.textAlign = 'start'; + this.textBaseline = 'alphabetic'; + this.text; + this.width; + this.height; + this.pt2px = 1.28; + + $.extend(true, this, options); + this.normalizedFontSize = this.normalizeFontSize(this.fontSize); + this.setHeight(); + }; + + $.jqplot.CanvasTextRenderer.prototype.init = function(options) { + $.extend(true, this, options); + this.normalizedFontSize = this.normalizeFontSize(this.fontSize); + this.setHeight(); + }; + + // convert css spec into point size + // returns float + $.jqplot.CanvasTextRenderer.prototype.normalizeFontSize = function(sz) { + sz = String(sz); + var n = parseFloat(sz); + if (sz.indexOf('px') > -1) { + return n/this.pt2px; + } + else if (sz.indexOf('pt') > -1) { + return n; + } + else if (sz.indexOf('em') > -1) { + return n*12; + } + else if (sz.indexOf('%') > -1) { + return n*12/100; + } + // default to pixels; + else { + return n/this.pt2px; + } + }; + + + $.jqplot.CanvasTextRenderer.prototype.fontWeight2Float = function(w) { + // w = normal | bold | bolder | lighter | 100 | 200 | 300 | 400 | 500 | 600 | 700 | 800 | 900 + // return values adjusted for Hershey font. + if (Number(w)) { + return w/400; + } + else { + switch (w) { + case 'normal': + return 1; + break; + case 'bold': + return 1.75; + break; + case 'bolder': + return 2.25; + break; + case 'lighter': + return 0.75; + break; + default: + return 1; + break; + } + } + }; + + $.jqplot.CanvasTextRenderer.prototype.getText = function() { + return this.text; + }; + + $.jqplot.CanvasTextRenderer.prototype.setText = function(t, ctx) { + this.text = t; + this.setWidth(ctx); + return this; + }; + + $.jqplot.CanvasTextRenderer.prototype.getWidth = function(ctx) { + return this.width; + }; + + $.jqplot.CanvasTextRenderer.prototype.setWidth = function(ctx, w) { + if (!w) { + this.width = this.measure(ctx, this.text); + } + else { + this.width = w; + } + return this; + }; + + // return height in pixels. + $.jqplot.CanvasTextRenderer.prototype.getHeight = function(ctx) { + return this.height; + }; + + // w - height in pt + // set heigh in px + $.jqplot.CanvasTextRenderer.prototype.setHeight = function(w) { + if (!w) { + //height = this.fontSize /0.75; + this.height = this.normalizedFontSize * this.pt2px; + } + else { + this.height = w; + } + return this; + }; + + $.jqplot.CanvasTextRenderer.prototype.letter = function (ch) + { + return this.letters[ch]; + }; + + $.jqplot.CanvasTextRenderer.prototype.ascent = function() + { + return this.normalizedFontSize; + }; + + $.jqplot.CanvasTextRenderer.prototype.descent = function() + { + return 7.0*this.normalizedFontSize/25.0; + }; + + $.jqplot.CanvasTextRenderer.prototype.measure = function(ctx, str) + { + var total = 0; + var len = str.length; + + for (var i = 0; i < len; i++) { + var c = this.letter(str.charAt(i)); + if (c) { + total += c.width * this.normalizedFontSize / 25.0 * this.fontStretch; + } + } + return total; + }; + + $.jqplot.CanvasTextRenderer.prototype.draw = function(ctx,str) + { + var x = 0; + // leave room at bottom for descenders. + var y = this.height*0.72; + var total = 0; + var len = str.length; + var mag = this.normalizedFontSize / 25.0; + + ctx.save(); + var tx, ty; + + // 1st quadrant + if ((-Math.PI/2 <= this.angle && this.angle <= 0) || (Math.PI*3/2 <= this.angle && this.angle <= Math.PI*2)) { + tx = 0; + ty = -Math.sin(this.angle) * this.width; + } + // 4th quadrant + else if ((0 < this.angle && this.angle <= Math.PI/2) || (-Math.PI*2 <= this.angle && this.angle <= -Math.PI*3/2)) { + tx = Math.sin(this.angle) * this.height; + ty = 0; + } + // 2nd quadrant + else if ((-Math.PI < this.angle && this.angle < -Math.PI/2) || (Math.PI <= this.angle && this.angle <= Math.PI*3/2)) { + tx = -Math.cos(this.angle) * this.width; + ty = -Math.sin(this.angle) * this.width - Math.cos(this.angle) * this.height; + } + // 3rd quadrant + else if ((-Math.PI*3/2 < this.angle && this.angle < Math.PI) || (Math.PI/2 < this.angle && this.angle < Math.PI)) { + tx = Math.sin(this.angle) * this.height - Math.cos(this.angle)*this.width; + ty = -Math.cos(this.angle) * this.height; + } + + ctx.strokeStyle = this.fillStyle; + ctx.fillStyle = this.fillStyle; + ctx.translate(tx, ty); + ctx.rotate(this.angle); + ctx.lineCap = "round"; + // multiplier was 2.0 + var fact = (this.normalizedFontSize > 30) ? 2.0 : 2 + (30 - this.normalizedFontSize)/20; + ctx.lineWidth = fact * mag * this.fontWeight2Float(this.fontWeight); + + for ( var i = 0; i < len; i++) { + var c = this.letter( str.charAt(i)); + if ( !c) { + continue; + } + + ctx.beginPath(); + + var penUp = 1; + var needStroke = 0; + for ( var j = 0; j < c.points.length; j++) { + var a = c.points[j]; + if ( a[0] == -1 && a[1] == -1) { + penUp = 1; + continue; + } + if ( penUp) { + ctx.moveTo( x + a[0]*mag*this.fontStretch, y - a[1]*mag); + penUp = false; + } else { + ctx.lineTo( x + a[0]*mag*this.fontStretch, y - a[1]*mag); + } + } + ctx.stroke(); + x += c.width*mag*this.fontStretch; + } + ctx.restore(); + return total; + }; + + $.jqplot.CanvasTextRenderer.prototype.letters = { + ' ': { width: 16, points: [] }, + '!': { width: 10, points: [[5,21],[5,7],[-1,-1],[5,2],[4,1],[5,0],[6,1],[5,2]] }, + '"': { width: 16, points: [[4,21],[4,14],[-1,-1],[12,21],[12,14]] }, + '#': { width: 21, points: [[11,25],[4,-7],[-1,-1],[17,25],[10,-7],[-1,-1],[4,12],[18,12],[-1,-1],[3,6],[17,6]] }, + '$': { width: 20, points: [[8,25],[8,-4],[-1,-1],[12,25],[12,-4],[-1,-1],[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]] }, + '%': { width: 24, points: [[21,21],[3,0],[-1,-1],[8,21],[10,19],[10,17],[9,15],[7,14],[5,14],[3,16],[3,18],[4,20],[6,21],[8,21],[10,20],[13,19],[16,19],[19,20],[21,21],[-1,-1],[17,7],[15,6],[14,4],[14,2],[16,0],[18,0],[20,1],[21,3],[21,5],[19,7],[17,7]] }, + '&': { width: 26, points: [[23,12],[23,13],[22,14],[21,14],[20,13],[19,11],[17,6],[15,3],[13,1],[11,0],[7,0],[5,1],[4,2],[3,4],[3,6],[4,8],[5,9],[12,13],[13,14],[14,16],[14,18],[13,20],[11,21],[9,20],[8,18],[8,16],[9,13],[11,10],[16,3],[18,1],[20,0],[22,0],[23,1],[23,2]] }, + '\'': { width: 10, points: [[5,19],[4,20],[5,21],[6,20],[6,18],[5,16],[4,15]] }, + '(': { width: 14, points: [[11,25],[9,23],[7,20],[5,16],[4,11],[4,7],[5,2],[7,-2],[9,-5],[11,-7]] }, + ')': { width: 14, points: [[3,25],[5,23],[7,20],[9,16],[10,11],[10,7],[9,2],[7,-2],[5,-5],[3,-7]] }, + '*': { width: 16, points: [[8,21],[8,9],[-1,-1],[3,18],[13,12],[-1,-1],[13,18],[3,12]] }, + '+': { width: 26, points: [[13,18],[13,0],[-1,-1],[4,9],[22,9]] }, + ',': { width: 10, points: [[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]] }, + '-': { width: 18, points: [[6,9],[12,9]] }, + '.': { width: 10, points: [[5,2],[4,1],[5,0],[6,1],[5,2]] }, + '/': { width: 22, points: [[20,25],[2,-7]] }, + '0': { width: 20, points: [[9,21],[6,20],[4,17],[3,12],[3,9],[4,4],[6,1],[9,0],[11,0],[14,1],[16,4],[17,9],[17,12],[16,17],[14,20],[11,21],[9,21]] }, + '1': { width: 20, points: [[6,17],[8,18],[11,21],[11,0]] }, + '2': { width: 20, points: [[4,16],[4,17],[5,19],[6,20],[8,21],[12,21],[14,20],[15,19],[16,17],[16,15],[15,13],[13,10],[3,0],[17,0]] }, + '3': { width: 20, points: [[5,21],[16,21],[10,13],[13,13],[15,12],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]] }, + '4': { width: 20, points: [[13,21],[3,7],[18,7],[-1,-1],[13,21],[13,0]] }, + '5': { width: 20, points: [[15,21],[5,21],[4,12],[5,13],[8,14],[11,14],[14,13],[16,11],[17,8],[17,6],[16,3],[14,1],[11,0],[8,0],[5,1],[4,2],[3,4]] }, + '6': { width: 20, points: [[16,18],[15,20],[12,21],[10,21],[7,20],[5,17],[4,12],[4,7],[5,3],[7,1],[10,0],[11,0],[14,1],[16,3],[17,6],[17,7],[16,10],[14,12],[11,13],[10,13],[7,12],[5,10],[4,7]] }, + '7': { width: 20, points: [[17,21],[7,0],[-1,-1],[3,21],[17,21]] }, + '8': { width: 20, points: [[8,21],[5,20],[4,18],[4,16],[5,14],[7,13],[11,12],[14,11],[16,9],[17,7],[17,4],[16,2],[15,1],[12,0],[8,0],[5,1],[4,2],[3,4],[3,7],[4,9],[6,11],[9,12],[13,13],[15,14],[16,16],[16,18],[15,20],[12,21],[8,21]] }, + '9': { width: 20, points: [[16,14],[15,11],[13,9],[10,8],[9,8],[6,9],[4,11],[3,14],[3,15],[4,18],[6,20],[9,21],[10,21],[13,20],[15,18],[16,14],[16,9],[15,4],[13,1],[10,0],[8,0],[5,1],[4,3]] }, + ':': { width: 10, points: [[5,14],[4,13],[5,12],[6,13],[5,14],[-1,-1],[5,2],[4,1],[5,0],[6,1],[5,2]] }, + ';': { width: 10, points: [[5,14],[4,13],[5,12],[6,13],[5,14],[-1,-1],[6,1],[5,0],[4,1],[5,2],[6,1],[6,-1],[5,-3],[4,-4]] }, + '<': { width: 24, points: [[20,18],[4,9],[20,0]] }, + '=': { width: 26, points: [[4,12],[22,12],[-1,-1],[4,6],[22,6]] }, + '>': { width: 24, points: [[4,18],[20,9],[4,0]] }, + '?': { width: 18, points: [[3,16],[3,17],[4,19],[5,20],[7,21],[11,21],[13,20],[14,19],[15,17],[15,15],[14,13],[13,12],[9,10],[9,7],[-1,-1],[9,2],[8,1],[9,0],[10,1],[9,2]] }, + '@': { width: 27, points: [[18,13],[17,15],[15,16],[12,16],[10,15],[9,14],[8,11],[8,8],[9,6],[11,5],[14,5],[16,6],[17,8],[-1,-1],[12,16],[10,14],[9,11],[9,8],[10,6],[11,5],[-1,-1],[18,16],[17,8],[17,6],[19,5],[21,5],[23,7],[24,10],[24,12],[23,15],[22,17],[20,19],[18,20],[15,21],[12,21],[9,20],[7,19],[5,17],[4,15],[3,12],[3,9],[4,6],[5,4],[7,2],[9,1],[12,0],[15,0],[18,1],[20,2],[21,3],[-1,-1],[19,16],[18,8],[18,6],[19,5]] }, + 'A': { width: 18, points: [[9,21],[1,0],[-1,-1],[9,21],[17,0],[-1,-1],[4,7],[14,7]] }, + 'B': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[-1,-1],[4,11],[13,11],[16,10],[17,9],[18,7],[18,4],[17,2],[16,1],[13,0],[4,0]] }, + 'C': { width: 21, points: [[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5]] }, + 'D': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[11,21],[14,20],[16,18],[17,16],[18,13],[18,8],[17,5],[16,3],[14,1],[11,0],[4,0]] }, + 'E': { width: 19, points: [[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11],[-1,-1],[4,0],[17,0]] }, + 'F': { width: 18, points: [[4,21],[4,0],[-1,-1],[4,21],[17,21],[-1,-1],[4,11],[12,11]] }, + 'G': { width: 21, points: [[18,16],[17,18],[15,20],[13,21],[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[18,8],[-1,-1],[13,8],[18,8]] }, + 'H': { width: 22, points: [[4,21],[4,0],[-1,-1],[18,21],[18,0],[-1,-1],[4,11],[18,11]] }, + 'I': { width: 8, points: [[4,21],[4,0]] }, + 'J': { width: 16, points: [[12,21],[12,5],[11,2],[10,1],[8,0],[6,0],[4,1],[3,2],[2,5],[2,7]] }, + 'K': { width: 21, points: [[4,21],[4,0],[-1,-1],[18,21],[4,7],[-1,-1],[9,12],[18,0]] }, + 'L': { width: 17, points: [[4,21],[4,0],[-1,-1],[4,0],[16,0]] }, + 'M': { width: 24, points: [[4,21],[4,0],[-1,-1],[4,21],[12,0],[-1,-1],[20,21],[12,0],[-1,-1],[20,21],[20,0]] }, + 'N': { width: 22, points: [[4,21],[4,0],[-1,-1],[4,21],[18,0],[-1,-1],[18,21],[18,0]] }, + 'O': { width: 22, points: [[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21]] }, + 'P': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,14],[17,12],[16,11],[13,10],[4,10]] }, + 'Q': { width: 22, points: [[9,21],[7,20],[5,18],[4,16],[3,13],[3,8],[4,5],[5,3],[7,1],[9,0],[13,0],[15,1],[17,3],[18,5],[19,8],[19,13],[18,16],[17,18],[15,20],[13,21],[9,21],[-1,-1],[12,4],[18,-2]] }, + 'R': { width: 21, points: [[4,21],[4,0],[-1,-1],[4,21],[13,21],[16,20],[17,19],[18,17],[18,15],[17,13],[16,12],[13,11],[4,11],[-1,-1],[11,11],[18,0]] }, + 'S': { width: 20, points: [[17,18],[15,20],[12,21],[8,21],[5,20],[3,18],[3,16],[4,14],[5,13],[7,12],[13,10],[15,9],[16,8],[17,6],[17,3],[15,1],[12,0],[8,0],[5,1],[3,3]] }, + 'T': { width: 16, points: [[8,21],[8,0],[-1,-1],[1,21],[15,21]] }, + 'U': { width: 22, points: [[4,21],[4,6],[5,3],[7,1],[10,0],[12,0],[15,1],[17,3],[18,6],[18,21]] }, + 'V': { width: 18, points: [[1,21],[9,0],[-1,-1],[17,21],[9,0]] }, + 'W': { width: 24, points: [[2,21],[7,0],[-1,-1],[12,21],[7,0],[-1,-1],[12,21],[17,0],[-1,-1],[22,21],[17,0]] }, + 'X': { width: 20, points: [[3,21],[17,0],[-1,-1],[17,21],[3,0]] }, + 'Y': { width: 18, points: [[1,21],[9,11],[9,0],[-1,-1],[17,21],[9,11]] }, + 'Z': { width: 20, points: [[17,21],[3,0],[-1,-1],[3,21],[17,21],[-1,-1],[3,0],[17,0]] }, + '[': { width: 14, points: [[4,25],[4,-7],[-1,-1],[5,25],[5,-7],[-1,-1],[4,25],[11,25],[-1,-1],[4,-7],[11,-7]] }, + '\\': { width: 14, points: [[0,21],[14,-3]] }, + ']': { width: 14, points: [[9,25],[9,-7],[-1,-1],[10,25],[10,-7],[-1,-1],[3,25],[10,25],[-1,-1],[3,-7],[10,-7]] }, + '^': { width: 16, points: [[6,15],[8,18],[10,15],[-1,-1],[3,12],[8,17],[13,12],[-1,-1],[8,17],[8,0]] }, + '_': { width: 16, points: [[0,-2],[16,-2]] }, + '`': { width: 10, points: [[6,21],[5,20],[4,18],[4,16],[5,15],[6,16],[5,17]] }, + 'a': { width: 19, points: [[15,14],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, + 'b': { width: 19, points: [[4,21],[4,0],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]] }, + 'c': { width: 18, points: [[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, + 'd': { width: 19, points: [[15,21],[15,0],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, + 'e': { width: 18, points: [[3,8],[15,8],[15,10],[14,12],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, + 'f': { width: 12, points: [[10,21],[8,21],[6,20],[5,17],[5,0],[-1,-1],[2,14],[9,14]] }, + 'g': { width: 19, points: [[15,14],[15,-2],[14,-5],[13,-6],[11,-7],[8,-7],[6,-6],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, + 'h': { width: 19, points: [[4,21],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]] }, + 'i': { width: 8, points: [[3,21],[4,20],[5,21],[4,22],[3,21],[-1,-1],[4,14],[4,0]] }, + 'j': { width: 10, points: [[5,21],[6,20],[7,21],[6,22],[5,21],[-1,-1],[6,14],[6,-3],[5,-6],[3,-7],[1,-7]] }, + 'k': { width: 17, points: [[4,21],[4,0],[-1,-1],[14,14],[4,4],[-1,-1],[8,8],[15,0]] }, + 'l': { width: 8, points: [[4,21],[4,0]] }, + 'm': { width: 30, points: [[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0],[-1,-1],[15,10],[18,13],[20,14],[23,14],[25,13],[26,10],[26,0]] }, + 'n': { width: 19, points: [[4,14],[4,0],[-1,-1],[4,10],[7,13],[9,14],[12,14],[14,13],[15,10],[15,0]] }, + 'o': { width: 19, points: [[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3],[16,6],[16,8],[15,11],[13,13],[11,14],[8,14]] }, + 'p': { width: 19, points: [[4,14],[4,-7],[-1,-1],[4,11],[6,13],[8,14],[11,14],[13,13],[15,11],[16,8],[16,6],[15,3],[13,1],[11,0],[8,0],[6,1],[4,3]] }, + 'q': { width: 19, points: [[15,14],[15,-7],[-1,-1],[15,11],[13,13],[11,14],[8,14],[6,13],[4,11],[3,8],[3,6],[4,3],[6,1],[8,0],[11,0],[13,1],[15,3]] }, + 'r': { width: 13, points: [[4,14],[4,0],[-1,-1],[4,8],[5,11],[7,13],[9,14],[12,14]] }, + 's': { width: 17, points: [[14,11],[13,13],[10,14],[7,14],[4,13],[3,11],[4,9],[6,8],[11,7],[13,6],[14,4],[14,3],[13,1],[10,0],[7,0],[4,1],[3,3]] }, + 't': { width: 12, points: [[5,21],[5,4],[6,1],[8,0],[10,0],[-1,-1],[2,14],[9,14]] }, + 'u': { width: 19, points: [[4,14],[4,4],[5,1],[7,0],[10,0],[12,1],[15,4],[-1,-1],[15,14],[15,0]] }, + 'v': { width: 16, points: [[2,14],[8,0],[-1,-1],[14,14],[8,0]] }, + 'w': { width: 22, points: [[3,14],[7,0],[-1,-1],[11,14],[7,0],[-1,-1],[11,14],[15,0],[-1,-1],[19,14],[15,0]] }, + 'x': { width: 17, points: [[3,14],[14,0],[-1,-1],[14,14],[3,0]] }, + 'y': { width: 16, points: [[2,14],[8,0],[-1,-1],[14,14],[8,0],[6,-4],[4,-6],[2,-7],[1,-7]] }, + 'z': { width: 17, points: [[14,14],[3,0],[-1,-1],[3,14],[14,14],[-1,-1],[3,0],[14,0]] }, + '{': { width: 14, points: [[9,25],[7,24],[6,23],[5,21],[5,19],[6,17],[7,16],[8,14],[8,12],[6,10],[-1,-1],[7,24],[6,22],[6,20],[7,18],[8,17],[9,15],[9,13],[8,11],[4,9],[8,7],[9,5],[9,3],[8,1],[7,0],[6,-2],[6,-4],[7,-6],[-1,-1],[6,8],[8,6],[8,4],[7,2],[6,1],[5,-1],[5,-3],[6,-5],[7,-6],[9,-7]] }, + '|': { width: 8, points: [[4,25],[4,-7]] }, + '}': { width: 14, points: [[5,25],[7,24],[8,23],[9,21],[9,19],[8,17],[7,16],[6,14],[6,12],[8,10],[-1,-1],[7,24],[8,22],[8,20],[7,18],[6,17],[5,15],[5,13],[6,11],[10,9],[6,7],[5,5],[5,3],[6,1],[7,0],[8,-2],[8,-4],[7,-6],[-1,-1],[8,8],[6,6],[6,4],[7,2],[8,1],[9,-1],[9,-3],[8,-5],[7,-6],[5,-7]] }, + '~': { width: 24, points: [[3,6],[3,8],[4,11],[6,12],[8,12],[10,11],[14,8],[16,7],[18,7],[20,8],[21,10],[-1,-1],[3,8],[4,10],[6,11],[8,11],[10,10],[14,7],[16,6],[18,6],[20,7],[21,10],[21,12]] } + }; + + $.jqplot.CanvasFontRenderer = function(options) { + options = options || {}; + if (!options.pt2px) { + options.pt2px = 1.5; + } + $.jqplot.CanvasTextRenderer.call(this, options); + }; + + $.jqplot.CanvasFontRenderer.prototype = new $.jqplot.CanvasTextRenderer({}); + $.jqplot.CanvasFontRenderer.prototype.constructor = $.jqplot.CanvasFontRenderer; + + $.jqplot.CanvasFontRenderer.prototype.measure = function(ctx, str) + { + // var fstyle = this.fontStyle+' '+this.fontVariant+' '+this.fontWeight+' '+this.fontSize+' '+this.fontFamily; + var fstyle = this.fontSize+' '+this.fontFamily; + ctx.save(); + ctx.font = fstyle; + var w = ctx.measureText(str).width; + ctx.restore(); + return w; + }; + + $.jqplot.CanvasFontRenderer.prototype.draw = function(ctx, str) + { + var x = 0; + // leave room at bottom for descenders. + var y = this.height*0.72; + //var y = 12; + + ctx.save(); + var tx, ty; + + // 1st quadrant + if ((-Math.PI/2 <= this.angle && this.angle <= 0) || (Math.PI*3/2 <= this.angle && this.angle <= Math.PI*2)) { + tx = 0; + ty = -Math.sin(this.angle) * this.width; + } + // 4th quadrant + else if ((0 < this.angle && this.angle <= Math.PI/2) || (-Math.PI*2 <= this.angle && this.angle <= -Math.PI*3/2)) { + tx = Math.sin(this.angle) * this.height; + ty = 0; + } + // 2nd quadrant + else if ((-Math.PI < this.angle && this.angle < -Math.PI/2) || (Math.PI <= this.angle && this.angle <= Math.PI*3/2)) { + tx = -Math.cos(this.angle) * this.width; + ty = -Math.sin(this.angle) * this.width - Math.cos(this.angle) * this.height; + } + // 3rd quadrant + else if ((-Math.PI*3/2 < this.angle && this.angle < Math.PI) || (Math.PI/2 < this.angle && this.angle < Math.PI)) { + tx = Math.sin(this.angle) * this.height - Math.cos(this.angle)*this.width; + ty = -Math.cos(this.angle) * this.height; + } + ctx.strokeStyle = this.fillStyle; + ctx.fillStyle = this.fillStyle; + // var fstyle = this.fontStyle+' '+this.fontVariant+' '+this.fontWeight+' '+this.fontSize+' '+this.fontFamily; + var fstyle = this.fontSize+' '+this.fontFamily; + ctx.font = fstyle; + ctx.translate(tx, ty); + ctx.rotate(this.angle); + ctx.fillText(str, x, y); + // ctx.strokeText(str, x, y); + + ctx.restore(); + }; + +})(jQuery);
\ No newline at end of file diff --git a/hugo/js/jqplot/plugins/jqplot.categoryAxisRenderer.js b/hugo/js/jqplot/plugins/jqplot.categoryAxisRenderer.js new file mode 100644 index 0000000..4cea2de --- /dev/null +++ b/hugo/js/jqplot/plugins/jqplot.categoryAxisRenderer.js @@ -0,0 +1,673 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.4 + * Revision: 1121 + * + * Copyright (c) 2009-2012 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + /** + * class: $.jqplot.CategoryAxisRenderer + * A plugin for jqPlot to render a category style axis, with equal pixel spacing between y data values of a series. + * + * To use this renderer, include the plugin in your source + * > <script type="text/javascript" language="javascript" src="plugins/jqplot.categoryAxisRenderer.js"></script> + * + * and supply the appropriate options to your plot + * + * > {axes:{xaxis:{renderer:$.jqplot.CategoryAxisRenderer}}} + **/ + $.jqplot.CategoryAxisRenderer = function(options) { + $.jqplot.LinearAxisRenderer.call(this); + // prop: sortMergedLabels + // True to sort tick labels when labels are created by merging + // x axis values from multiple series. That is, say you have + // two series like: + // > line1 = [[2006, 4], [2008, 9], [2009, 16]]; + // > line2 = [[2006, 3], [2007, 7], [2008, 6]]; + // If no label array is specified, tick labels will be collected + // from the x values of the series. With sortMergedLabels + // set to true, tick labels will be: + // > [2006, 2007, 2008, 2009] + // With sortMergedLabels set to false, tick labels will be: + // > [2006, 2008, 2009, 2007] + // + // Note, this property is specified on the renderOptions for the + // axes when creating a plot: + // > axes:{xaxis:{renderer:$.jqplot.CategoryAxisRenderer, rendererOptions:{sortMergedLabels:true}}} + this.sortMergedLabels = false; + }; + + $.jqplot.CategoryAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer(); + $.jqplot.CategoryAxisRenderer.prototype.constructor = $.jqplot.CategoryAxisRenderer; + + $.jqplot.CategoryAxisRenderer.prototype.init = function(options){ + this.groups = 1; + this.groupLabels = []; + this._groupLabels = []; + this._grouped = false; + this._barsPerGroup = null; + this.reverse = false; + // prop: tickRenderer + // A class of a rendering engine for creating the ticks labels displayed on the plot, + // See <$.jqplot.AxisTickRenderer>. + // this.tickRenderer = $.jqplot.AxisTickRenderer; + // this.labelRenderer = $.jqplot.AxisLabelRenderer; + $.extend(true, this, {tickOptions:{formatString:'%d'}}, options); + var db = this._dataBounds; + // Go through all the series attached to this axis and find + // the min/max bounds for this axis. + for (var i=0; i<this._series.length; i++) { + var s = this._series[i]; + if (s.groups) { + this.groups = s.groups; + } + var d = s.data; + + for (var j=0; j<d.length; j++) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + if (d[j][0] < db.min || db.min == null) { + db.min = d[j][0]; + } + if (d[j][0] > db.max || db.max == null) { + db.max = d[j][0]; + } + } + else { + if (d[j][1] < db.min || db.min == null) { + db.min = d[j][1]; + } + if (d[j][1] > db.max || db.max == null) { + db.max = d[j][1]; + } + } + } + } + + if (this.groupLabels.length) { + this.groups = this.groupLabels.length; + } + }; + + + $.jqplot.CategoryAxisRenderer.prototype.createTicks = function() { + // we're are operating on an axis here + var ticks = this._ticks; + var userTicks = this.ticks; + var name = this.name; + // databounds were set on axis initialization. + var db = this._dataBounds; + var dim, interval; + var min, max; + var pos1, pos2; + var tt, i; + + // if we already have ticks, use them. + if (userTicks.length) { + // adjust with blanks if we have groups + if (this.groups > 1 && !this._grouped) { + var l = userTicks.length; + var skip = parseInt(l/this.groups, 10); + var count = 0; + for (var i=skip; i<l; i+=skip) { + userTicks.splice(i+count, 0, ' '); + count++; + } + this._grouped = true; + } + this.min = 0.5; + this.max = userTicks.length + 0.5; + var range = this.max - this.min; + this.numberTicks = 2*userTicks.length + 1; + for (i=0; i<userTicks.length; i++){ + tt = this.min + 2 * i * range / (this.numberTicks-1); + // need a marker before and after the tick + var t = new this.tickRenderer(this.tickOptions); + t.showLabel = false; + // t.showMark = true; + t.setTick(tt, this.name); + this._ticks.push(t); + var t = new this.tickRenderer(this.tickOptions); + t.label = userTicks[i]; + // t.showLabel = true; + t.showMark = false; + t.showGridline = false; + t.setTick(tt+0.5, this.name); + this._ticks.push(t); + } + // now add the last tick at the end + var t = new this.tickRenderer(this.tickOptions); + t.showLabel = false; + // t.showMark = true; + t.setTick(tt+1, this.name); + this._ticks.push(t); + } + + // we don't have any ticks yet, let's make some! + else { + if (name == 'xaxis' || name == 'x2axis') { + dim = this._plotDimensions.width; + } + else { + dim = this._plotDimensions.height; + } + + // if min, max and number of ticks specified, user can't specify interval. + if (this.min != null && this.max != null && this.numberTicks != null) { + this.tickInterval = null; + } + + // if max, min, and interval specified and interval won't fit, ignore interval. + if (this.min != null && this.max != null && this.tickInterval != null) { + if (parseInt((this.max-this.min)/this.tickInterval, 10) != (this.max-this.min)/this.tickInterval) { + this.tickInterval = null; + } + } + + // find out how many categories are in the lines and collect labels + var labels = []; + var numcats = 0; + var min = 0.5; + var max, val; + var isMerged = false; + for (var i=0; i<this._series.length; i++) { + var s = this._series[i]; + for (var j=0; j<s.data.length; j++) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + val = s.data[j][0]; + } + else { + val = s.data[j][1]; + } + if ($.inArray(val, labels) == -1) { + isMerged = true; + numcats += 1; + labels.push(val); + } + } + } + + if (isMerged && this.sortMergedLabels) { + labels.sort(function(a,b) { return a - b; }); + } + + // keep a reference to these tick labels to use for redrawing plot (see bug #57) + this.ticks = labels; + + // now bin the data values to the right lables. + for (var i=0; i<this._series.length; i++) { + var s = this._series[i]; + for (var j=0; j<s.data.length; j++) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + val = s.data[j][0]; + } + else { + val = s.data[j][1]; + } + // for category axis, force the values into category bins. + // we should have the value in the label array now. + var idx = $.inArray(val, labels)+1; + if (this.name == 'xaxis' || this.name == 'x2axis') { + s.data[j][0] = idx; + } + else { + s.data[j][1] = idx; + } + } + } + + // adjust with blanks if we have groups + if (this.groups > 1 && !this._grouped) { + var l = labels.length; + var skip = parseInt(l/this.groups, 10); + var count = 0; + for (var i=skip; i<l; i+=skip+1) { + labels[i] = ' '; + } + this._grouped = true; + } + + max = numcats + 0.5; + if (this.numberTicks == null) { + this.numberTicks = 2*numcats + 1; + } + + var range = max - min; + this.min = min; + this.max = max; + var track = 0; + + // todo: adjust this so more ticks displayed. + var maxVisibleTicks = parseInt(3+dim/10, 10); + var skip = parseInt(numcats/maxVisibleTicks, 10); + + if (this.tickInterval == null) { + + this.tickInterval = range / (this.numberTicks-1); + + } + // if tickInterval is specified, we will ignore any computed maximum. + for (var i=0; i<this.numberTicks; i++){ + tt = this.min + i * this.tickInterval; + var t = new this.tickRenderer(this.tickOptions); + // if even tick, it isn't a category, it's a divider + if (i/2 == parseInt(i/2, 10)) { + t.showLabel = false; + t.showMark = true; + } + else { + if (skip>0 && track<skip) { + t.showLabel = false; + track += 1; + } + else { + t.showLabel = true; + track = 0; + } + t.label = t.formatter(t.formatString, labels[(i-1)/2]); + t.showMark = false; + t.showGridline = false; + } + t.setTick(tt, this.name); + this._ticks.push(t); + } + } + + }; + + // called with scope of axis + $.jqplot.CategoryAxisRenderer.prototype.draw = function(ctx, plot) { + if (this.show) { + // populate the axis label and value properties. + // createTicks is a method on the renderer, but + // call it within the scope of the axis. + this.renderer.createTicks.call(this); + // fill a div with axes labels in the right direction. + // Need to pregenerate each axis to get it's bounds and + // position it and the labels correctly on the plot. + var dim=0; + var temp; + // Added for theming. + if (this._elem) { + // this._elem.empty(); + // Memory Leaks patch + this._elem.emptyForce(); + } + + this._elem = this._elem || $('<div class="jqplot-axis jqplot-'+this.name+'" style="position:absolute;"></div>'); + + if (this.name == 'xaxis' || this.name == 'x2axis') { + this._elem.width(this._plotDimensions.width); + } + else { + this._elem.height(this._plotDimensions.height); + } + + // create a _label object. + this.labelOptions.axis = this.name; + this._label = new this.labelRenderer(this.labelOptions); + if (this._label.show) { + var elem = this._label.draw(ctx, plot); + elem.appendTo(this._elem); + } + + var t = this._ticks; + for (var i=0; i<t.length; i++) { + var tick = t[i]; + if (tick.showLabel && (!tick.isMinorTick || this.showMinorTicks)) { + var elem = tick.draw(ctx, plot); + elem.appendTo(this._elem); + } + } + + this._groupLabels = []; + // now make group labels + for (var i=0; i<this.groupLabels.length; i++) + { + var elem = $('<div style="position:absolute;" class="jqplot-'+this.name+'-groupLabel"></div>'); + elem.html(this.groupLabels[i]); + this._groupLabels.push(elem); + elem.appendTo(this._elem); + } + } + return this._elem; + }; + + // called with scope of axis + $.jqplot.CategoryAxisRenderer.prototype.set = function() { + var dim = 0; + var temp; + var w = 0; + var h = 0; + var lshow = (this._label == null) ? false : this._label.show; + if (this.show) { + var t = this._ticks; + for (var i=0; i<t.length; i++) { + var tick = t[i]; + if (tick.showLabel && (!tick.isMinorTick || this.showMinorTicks)) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + temp = tick._elem.outerHeight(true); + } + else { + temp = tick._elem.outerWidth(true); + } + if (temp > dim) { + dim = temp; + } + } + } + + var dim2 = 0; + for (var i=0; i<this._groupLabels.length; i++) { + var l = this._groupLabels[i]; + if (this.name == 'xaxis' || this.name == 'x2axis') { + temp = l.outerHeight(true); + } + else { + temp = l.outerWidth(true); + } + if (temp > dim2) { + dim2 = temp; + } + } + + if (lshow) { + w = this._label._elem.outerWidth(true); + h = this._label._elem.outerHeight(true); + } + if (this.name == 'xaxis') { + dim += dim2 + h; + this._elem.css({'height':dim+'px', left:'0px', bottom:'0px'}); + } + else if (this.name == 'x2axis') { + dim += dim2 + h; + this._elem.css({'height':dim+'px', left:'0px', top:'0px'}); + } + else if (this.name == 'yaxis') { + dim += dim2 + w; + this._elem.css({'width':dim+'px', left:'0px', top:'0px'}); + if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) { + this._label._elem.css('width', w+'px'); + } + } + else { + dim += dim2 + w; + this._elem.css({'width':dim+'px', right:'0px', top:'0px'}); + if (lshow && this._label.constructor == $.jqplot.AxisLabelRenderer) { + this._label._elem.css('width', w+'px'); + } + } + } + }; + + // called with scope of axis + $.jqplot.CategoryAxisRenderer.prototype.pack = function(pos, offsets) { + var ticks = this._ticks; + var max = this.max; + var min = this.min; + var offmax = offsets.max; + var offmin = offsets.min; + var lshow = (this._label == null) ? false : this._label.show; + var i; + + for (var p in pos) { + this._elem.css(p, pos[p]); + } + + this._offsets = offsets; + // pixellength will be + for x axes and - for y axes becasue pixels always measured from top left. + var pixellength = offmax - offmin; + var unitlength = max - min; + + if (!this.reverse) { + // point to unit and unit to point conversions references to Plot DOM element top left corner. + + this.u2p = function(u){ + return (u - min) * pixellength / unitlength + offmin; + }; + + this.p2u = function(p){ + return (p - offmin) * unitlength / pixellength + min; + }; + + if (this.name == 'xaxis' || this.name == 'x2axis'){ + this.series_u2p = function(u){ + return (u - min) * pixellength / unitlength; + }; + this.series_p2u = function(p){ + return p * unitlength / pixellength + min; + }; + } + + else { + this.series_u2p = function(u){ + return (u - max) * pixellength / unitlength; + }; + this.series_p2u = function(p){ + return p * unitlength / pixellength + max; + }; + } + } + + else { + // point to unit and unit to point conversions references to Plot DOM element top left corner. + + this.u2p = function(u){ + return offmin + (max - u) * pixellength / unitlength; + }; + + this.p2u = function(p){ + return min + (p - offmin) * unitlength / pixellength; + }; + + if (this.name == 'xaxis' || this.name == 'x2axis'){ + this.series_u2p = function(u){ + return (max - u) * pixellength / unitlength; + }; + this.series_p2u = function(p){ + return p * unitlength / pixellength + max; + }; + } + + else { + this.series_u2p = function(u){ + return (min - u) * pixellength / unitlength; + }; + this.series_p2u = function(p){ + return p * unitlength / pixellength + min; + }; + } + + } + + + if (this.show) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + for (i=0; i<ticks.length; i++) { + var t = ticks[i]; + if (t.show && t.showLabel) { + var shim; + + if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) { + // will need to adjust auto positioning based on which axis this is. + var temp = (this.name == 'xaxis') ? 1 : -1; + switch (t.labelPosition) { + case 'auto': + // position at end + if (temp * t.angle < 0) { + shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + } + // position at start + else { + shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2; + } + break; + case 'end': + shim = -t.getWidth() + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + break; + case 'start': + shim = -t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2; + break; + case 'middle': + shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + break; + default: + shim = -t.getWidth()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + break; + } + } + else { + shim = -t.getWidth()/2; + } + var val = this.u2p(t.value) + shim + 'px'; + t._elem.css('left', val); + t.pack(); + } + } + + var labeledge=['bottom', 0]; + if (lshow) { + var w = this._label._elem.outerWidth(true); + this._label._elem.css('left', offmin + pixellength/2 - w/2 + 'px'); + if (this.name == 'xaxis') { + this._label._elem.css('bottom', '0px'); + labeledge = ['bottom', this._label._elem.outerHeight(true)]; + } + else { + this._label._elem.css('top', '0px'); + labeledge = ['top', this._label._elem.outerHeight(true)]; + } + this._label.pack(); + } + + // draw the group labels + var step = parseInt(this._ticks.length/this.groups, 10); + for (i=0; i<this._groupLabels.length; i++) { + var mid = 0; + var count = 0; + for (var j=i*step; j<=(i+1)*step; j++) { + if (this._ticks[j]._elem && this._ticks[j].label != " ") { + var t = this._ticks[j]._elem; + var p = t.position(); + mid += p.left + t.outerWidth(true)/2; + count++; + } + } + mid = mid/count; + this._groupLabels[i].css({'left':(mid - this._groupLabels[i].outerWidth(true)/2)}); + this._groupLabels[i].css(labeledge[0], labeledge[1]); + } + } + else { + for (i=0; i<ticks.length; i++) { + var t = ticks[i]; + if (t.show && t.showLabel) { + var shim; + if (t.constructor == $.jqplot.CanvasAxisTickRenderer && t.angle) { + // will need to adjust auto positioning based on which axis this is. + var temp = (this.name == 'yaxis') ? 1 : -1; + switch (t.labelPosition) { + case 'auto': + // position at end + case 'end': + if (temp * t.angle < 0) { + shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2; + } + else { + shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2; + } + break; + case 'start': + if (t.angle > 0) { + shim = -t._textRenderer.height * Math.cos(-t._textRenderer.angle) / 2; + } + else { + shim = -t.getHeight() + t._textRenderer.height * Math.cos(t._textRenderer.angle) / 2; + } + break; + case 'middle': + // if (t.angle > 0) { + // shim = -t.getHeight()/2 + t._textRenderer.height * Math.sin(-t._textRenderer.angle) / 2; + // } + // else { + // shim = -t.getHeight()/2 - t._textRenderer.height * Math.sin(t._textRenderer.angle) / 2; + // } + shim = -t.getHeight()/2; + break; + default: + shim = -t.getHeight()/2; + break; + } + } + else { + shim = -t.getHeight()/2; + } + + var val = this.u2p(t.value) + shim + 'px'; + t._elem.css('top', val); + t.pack(); + } + } + + var labeledge=['left', 0]; + if (lshow) { + var h = this._label._elem.outerHeight(true); + this._label._elem.css('top', offmax - pixellength/2 - h/2 + 'px'); + if (this.name == 'yaxis') { + this._label._elem.css('left', '0px'); + labeledge = ['left', this._label._elem.outerWidth(true)]; + } + else { + this._label._elem.css('right', '0px'); + labeledge = ['right', this._label._elem.outerWidth(true)]; + } + this._label.pack(); + } + + // draw the group labels, position top here, do left after label position. + var step = parseInt(this._ticks.length/this.groups, 10); + for (i=0; i<this._groupLabels.length; i++) { + var mid = 0; + var count = 0; + for (var j=i*step; j<=(i+1)*step; j++) { + if (this._ticks[j]._elem && this._ticks[j].label != " ") { + var t = this._ticks[j]._elem; + var p = t.position(); + mid += p.top + t.outerHeight()/2; + count++; + } + } + mid = mid/count; + this._groupLabels[i].css({'top':mid - this._groupLabels[i].outerHeight()/2}); + this._groupLabels[i].css(labeledge[0], labeledge[1]); + + } + } + } + }; + + +})(jQuery);
\ No newline at end of file diff --git a/hugo/js/jqplot/plugins/jqplot.cursor.js b/hugo/js/jqplot/plugins/jqplot.cursor.js new file mode 100644 index 0000000..0e58368 --- /dev/null +++ b/hugo/js/jqplot/plugins/jqplot.cursor.js @@ -0,0 +1,1108 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.4 + * Revision: 1121 + * + * Copyright (c) 2009-2012 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + + /** + * Class: $.jqplot.Cursor + * Plugin class representing the cursor as displayed on the plot. + */ + $.jqplot.Cursor = function(options) { + // Group: Properties + // + // prop: style + // CSS spec for cursor style + this.style = 'crosshair'; + this.previousCursor = 'auto'; + // prop: show + // wether to show the cursor or not. + this.show = $.jqplot.config.enablePlugins; + // prop: showTooltip + // show a cursor position tooltip. Location of the tooltip + // will be controlled by followMouse and tooltipLocation. + this.showTooltip = true; + // prop: followMouse + // Tooltip follows the mouse, it is not at a fixed location. + // Tooltip will show on the grid at the location given by + // tooltipLocation, offset from the grid edge by tooltipOffset. + this.followMouse = false; + // prop: tooltipLocation + // Where to position tooltip. If followMouse is true, this is + // relative to the cursor, otherwise, it is relative to the grid. + // One of 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw' + this.tooltipLocation = 'se'; + // prop: tooltipOffset + // Pixel offset of tooltip from the grid boudaries or cursor center. + this.tooltipOffset = 6; + // prop: showTooltipGridPosition + // show the grid pixel coordinates of the mouse. + this.showTooltipGridPosition = false; + // prop: showTooltipUnitPosition + // show the unit (data) coordinates of the mouse. + this.showTooltipUnitPosition = true; + // prop: showTooltipDataPosition + // Used with showVerticalLine to show intersecting data points in the tooltip. + this.showTooltipDataPosition = false; + // prop: tooltipFormatString + // sprintf format string for the tooltip. + // Uses Ash Searle's javascript sprintf implementation + // found here: http://hexmen.com/blog/2007/03/printf-sprintf/ + // See http://perldoc.perl.org/functions/sprintf.html for reference + // Note, if showTooltipDataPosition is true, the default tooltipFormatString + // will be set to the cursorLegendFormatString, not the default given here. + this.tooltipFormatString = '%.4P, %.4P'; + // prop: useAxesFormatters + // Use the x and y axes formatters to format the text in the tooltip. + this.useAxesFormatters = true; + // prop: tooltipAxisGroups + // Show position for the specified axes. + // This is an array like [['xaxis', 'yaxis'], ['xaxis', 'y2axis']] + // Default is to compute automatically for all visible axes. + this.tooltipAxisGroups = []; + // prop: zoom + // Enable plot zooming. + this.zoom = false; + // zoomProxy and zoomTarget properties are not directly set by user. + // They Will be set through call to zoomProxy method. + this.zoomProxy = false; + this.zoomTarget = false; + // prop: looseZoom + // Will expand zoom range to provide more rounded tick values. + // Works only with linear, log and date axes. + this.looseZoom = true; + // prop: clickReset + // Will reset plot zoom if single click on plot without drag. + this.clickReset = false; + // prop: dblClickReset + // Will reset plot zoom if double click on plot without drag. + this.dblClickReset = true; + // prop: showVerticalLine + // draw a vertical line across the plot which follows the cursor. + // When the line is near a data point, a special legend and/or tooltip can + // be updated with the data values. + this.showVerticalLine = false; + // prop: showHorizontalLine + // draw a horizontal line across the plot which follows the cursor. + this.showHorizontalLine = false; + // prop: constrainZoomTo + // 'none', 'x' or 'y' + this.constrainZoomTo = 'none'; + // // prop: autoscaleConstraint + // // when a constrained axis is specified, true will + // // auatoscale the adjacent axis. + // this.autoscaleConstraint = true; + this.shapeRenderer = new $.jqplot.ShapeRenderer(); + this._zoom = {start:[], end:[], started: false, zooming:false, isZoomed:false, axes:{start:{}, end:{}}, gridpos:{}, datapos:{}}; + this._tooltipElem; + this.zoomCanvas; + this.cursorCanvas; + // prop: intersectionThreshold + // pixel distance from data point or marker to consider cursor lines intersecting with point. + // If data point markers are not shown, this should be >= 1 or will often miss point intersections. + this.intersectionThreshold = 2; + // prop: showCursorLegend + // Replace the plot legend with an enhanced legend displaying intersection information. + this.showCursorLegend = false; + // prop: cursorLegendFormatString + // Format string used in the cursor legend. If showTooltipDataPosition is true, + // this will also be the default format string used by tooltipFormatString. + this.cursorLegendFormatString = $.jqplot.Cursor.cursorLegendFormatString; + // whether the cursor is over the grid or not. + this._oldHandlers = {onselectstart: null, ondrag: null, onmousedown: null}; + // prop: constrainOutsideZoom + // True to limit actual zoom area to edges of grid, even when zooming + // outside of plot area. That is, can't zoom out by mousing outside plot. + this.constrainOutsideZoom = true; + // prop: showTooltipOutsideZoom + // True will keep updating the tooltip when zooming of the grid. + this.showTooltipOutsideZoom = false; + // true if mouse is over grid, false if not. + this.onGrid = false; + $.extend(true, this, options); + }; + + $.jqplot.Cursor.cursorLegendFormatString = '%s x:%s, y:%s'; + + // called with scope of plot + $.jqplot.Cursor.init = function (target, data, opts){ + // add a cursor attribute to the plot + var options = opts || {}; + this.plugins.cursor = new $.jqplot.Cursor(options.cursor); + var c = this.plugins.cursor; + + if (c.show) { + $.jqplot.eventListenerHooks.push(['jqplotMouseEnter', handleMouseEnter]); + $.jqplot.eventListenerHooks.push(['jqplotMouseLeave', handleMouseLeave]); + $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMouseMove]); + + if (c.showCursorLegend) { + opts.legend = opts.legend || {}; + opts.legend.renderer = $.jqplot.CursorLegendRenderer; + opts.legend.formatString = this.plugins.cursor.cursorLegendFormatString; + opts.legend.show = true; + } + + if (c.zoom) { + $.jqplot.eventListenerHooks.push(['jqplotMouseDown', handleMouseDown]); + + if (c.clickReset) { + $.jqplot.eventListenerHooks.push(['jqplotClick', handleClick]); + } + + if (c.dblClickReset) { + $.jqplot.eventListenerHooks.push(['jqplotDblClick', handleDblClick]); + } + } + + this.resetZoom = function() { + var axes = this.axes; + if (!c.zoomProxy) { + for (var ax in axes) { + axes[ax].reset(); + axes[ax]._ticks = []; + // fake out tick creation algorithm to make sure original auto + // computed format string is used if _overrideFormatString is true + if (c._zoom.axes[ax] !== undefined) { + axes[ax]._autoFormatString = c._zoom.axes[ax].tickFormatString; + } + } + this.redraw(); + } + else { + var ctx = this.plugins.cursor.zoomCanvas._ctx; + ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height); + ctx = null; + } + this.plugins.cursor._zoom.isZoomed = false; + this.target.trigger('jqplotResetZoom', [this, this.plugins.cursor]); + }; + + + if (c.showTooltipDataPosition) { + c.showTooltipUnitPosition = false; + c.showTooltipGridPosition = false; + if (options.cursor.tooltipFormatString == undefined) { + c.tooltipFormatString = $.jqplot.Cursor.cursorLegendFormatString; + } + } + } + }; + + // called with context of plot + $.jqplot.Cursor.postDraw = function() { + var c = this.plugins.cursor; + + // Memory Leaks patch + if (c.zoomCanvas) { + c.zoomCanvas.resetCanvas(); + c.zoomCanvas = null; + } + + if (c.cursorCanvas) { + c.cursorCanvas.resetCanvas(); + c.cursorCanvas = null; + } + + if (c._tooltipElem) { + c._tooltipElem.emptyForce(); + c._tooltipElem = null; + } + + + if (c.zoom) { + c.zoomCanvas = new $.jqplot.GenericCanvas(); + this.eventCanvas._elem.before(c.zoomCanvas.createElement(this._gridPadding, 'jqplot-zoom-canvas', this._plotDimensions, this)); + c.zoomCanvas.setContext(); + } + + var elem = document.createElement('div'); + c._tooltipElem = $(elem); + elem = null; + c._tooltipElem.addClass('jqplot-cursor-tooltip'); + c._tooltipElem.css({position:'absolute', display:'none'}); + + + if (c.zoomCanvas) { + c.zoomCanvas._elem.before(c._tooltipElem); + } + + else { + this.eventCanvas._elem.before(c._tooltipElem); + } + + if (c.showVerticalLine || c.showHorizontalLine) { + c.cursorCanvas = new $.jqplot.GenericCanvas(); + this.eventCanvas._elem.before(c.cursorCanvas.createElement(this._gridPadding, 'jqplot-cursor-canvas', this._plotDimensions, this)); + c.cursorCanvas.setContext(); + } + + // if we are showing the positions in unit coordinates, and no axes groups + // were specified, create a default set. + if (c.showTooltipUnitPosition){ + if (c.tooltipAxisGroups.length === 0) { + var series = this.series; + var s; + var temp = []; + for (var i=0; i<series.length; i++) { + s = series[i]; + var ax = s.xaxis+','+s.yaxis; + if ($.inArray(ax, temp) == -1) { + temp.push(ax); + } + } + for (var i=0; i<temp.length; i++) { + c.tooltipAxisGroups.push(temp[i].split(',')); + } + } + } + }; + + // Group: methods + // + // method: $.jqplot.Cursor.zoomProxy + // links targetPlot to controllerPlot so that plot zooming of + // targetPlot will be controlled by zooming on the controllerPlot. + // controllerPlot will not actually zoom, but acts as an + // overview plot. Note, the zoom options must be set to true for + // zoomProxy to work. + $.jqplot.Cursor.zoomProxy = function(targetPlot, controllerPlot) { + var tc = targetPlot.plugins.cursor; + var cc = controllerPlot.plugins.cursor; + tc.zoomTarget = true; + tc.zoom = true; + tc.style = 'auto'; + tc.dblClickReset = false; + cc.zoom = true; + cc.zoomProxy = true; + + controllerPlot.target.bind('jqplotZoom', plotZoom); + controllerPlot.target.bind('jqplotResetZoom', plotReset); + + function plotZoom(ev, gridpos, datapos, plot, cursor) { + tc.doZoom(gridpos, datapos, targetPlot, cursor); + } + + function plotReset(ev, plot, cursor) { + targetPlot.resetZoom(); + } + }; + + $.jqplot.Cursor.prototype.resetZoom = function(plot, cursor) { + var axes = plot.axes; + var cax = cursor._zoom.axes; + if (!plot.plugins.cursor.zoomProxy && cursor._zoom.isZoomed) { + for (var ax in axes) { + // axes[ax]._ticks = []; + // axes[ax].min = cax[ax].min; + // axes[ax].max = cax[ax].max; + // axes[ax].numberTicks = cax[ax].numberTicks; + // axes[ax].tickInterval = cax[ax].tickInterval; + // // for date axes + // axes[ax].daTickInterval = cax[ax].daTickInterval; + axes[ax].reset(); + axes[ax]._ticks = []; + // fake out tick creation algorithm to make sure original auto + // computed format string is used if _overrideFormatString is true + axes[ax]._autoFormatString = cax[ax].tickFormatString; + } + plot.redraw(); + cursor._zoom.isZoomed = false; + } + else { + var ctx = cursor.zoomCanvas._ctx; + ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height); + ctx = null; + } + plot.target.trigger('jqplotResetZoom', [plot, cursor]); + }; + + $.jqplot.Cursor.resetZoom = function(plot) { + plot.resetZoom(); + }; + + $.jqplot.Cursor.prototype.doZoom = function (gridpos, datapos, plot, cursor) { + var c = cursor; + var axes = plot.axes; + var zaxes = c._zoom.axes; + var start = zaxes.start; + var end = zaxes.end; + var min, max, dp, span, + newmin, newmax, curax, _numberTicks, ret; + var ctx = plot.plugins.cursor.zoomCanvas._ctx; + // don't zoom if zoom area is too small (in pixels) + if ((c.constrainZoomTo == 'none' && Math.abs(gridpos.x - c._zoom.start[0]) > 6 && Math.abs(gridpos.y - c._zoom.start[1]) > 6) || (c.constrainZoomTo == 'x' && Math.abs(gridpos.x - c._zoom.start[0]) > 6) || (c.constrainZoomTo == 'y' && Math.abs(gridpos.y - c._zoom.start[1]) > 6)) { + if (!plot.plugins.cursor.zoomProxy) { + for (var ax in datapos) { + // make a copy of the original axes to revert back. + if (c._zoom.axes[ax] == undefined) { + c._zoom.axes[ax] = {}; + c._zoom.axes[ax].numberTicks = axes[ax].numberTicks; + c._zoom.axes[ax].tickInterval = axes[ax].tickInterval; + // for date axes... + c._zoom.axes[ax].daTickInterval = axes[ax].daTickInterval; + c._zoom.axes[ax].min = axes[ax].min; + c._zoom.axes[ax].max = axes[ax].max; + c._zoom.axes[ax].tickFormatString = (axes[ax].tickOptions != null) ? axes[ax].tickOptions.formatString : ''; + } + + + if ((c.constrainZoomTo == 'none') || (c.constrainZoomTo == 'x' && ax.charAt(0) == 'x') || (c.constrainZoomTo == 'y' && ax.charAt(0) == 'y')) { + dp = datapos[ax]; + if (dp != null) { + if (dp > start[ax]) { + newmin = start[ax]; + newmax = dp; + } + else { + span = start[ax] - dp; + newmin = dp; + newmax = start[ax]; + } + + curax = axes[ax]; + + _numberTicks = null; + + // if aligning this axis, use number of ticks from previous axis. + // Do I need to reset somehow if alignTicks is changed and then graph is replotted?? + if (curax.alignTicks) { + if (curax.name === 'x2axis' && plot.axes.xaxis.show) { + _numberTicks = plot.axes.xaxis.numberTicks; + } + else if (curax.name.charAt(0) === 'y' && curax.name !== 'yaxis' && curax.name !== 'yMidAxis' && plot.axes.yaxis.show) { + _numberTicks = plot.axes.yaxis.numberTicks; + } + } + + if (this.looseZoom && (axes[ax].renderer.constructor === $.jqplot.LinearAxisRenderer || axes[ax].renderer.constructor === $.jqplot.LogAxisRenderer )) { //} || axes[ax].renderer.constructor === $.jqplot.DateAxisRenderer)) { + + ret = $.jqplot.LinearTickGenerator(newmin, newmax, curax._scalefact, _numberTicks); + + // if new minimum is less than "true" minimum of axis display, adjust it + if (axes[ax].tickInset && ret[0] < axes[ax].min + axes[ax].tickInset * axes[ax].tickInterval) { + ret[0] += ret[4]; + ret[2] -= 1; + } + + // if new maximum is greater than "true" max of axis display, adjust it + if (axes[ax].tickInset && ret[1] > axes[ax].max - axes[ax].tickInset * axes[ax].tickInterval) { + ret[1] -= ret[4]; + ret[2] -= 1; + } + + // for log axes, don't fall below current minimum, this will look bad and can't have 0 in range anyway. + if (axes[ax].renderer.constructor === $.jqplot.LogAxisRenderer && ret[0] < axes[ax].min) { + // remove a tick and shift min up + ret[0] += ret[4]; + ret[2] -= 1; + } + + axes[ax].min = ret[0]; + axes[ax].max = ret[1]; + axes[ax]._autoFormatString = ret[3]; + axes[ax].numberTicks = ret[2]; + axes[ax].tickInterval = ret[4]; + // for date axes... + axes[ax].daTickInterval = [ret[4]/1000, 'seconds']; + } + else { + axes[ax].min = newmin; + axes[ax].max = newmax; + axes[ax].tickInterval = null; + axes[ax].numberTicks = null; + // for date axes... + axes[ax].daTickInterval = null; + } + + axes[ax]._ticks = []; + } + } + + // if ((c.constrainZoomTo == 'x' && ax.charAt(0) == 'y' && c.autoscaleConstraint) || (c.constrainZoomTo == 'y' && ax.charAt(0) == 'x' && c.autoscaleConstraint)) { + // dp = datapos[ax]; + // if (dp != null) { + // axes[ax].max == null; + // axes[ax].min = null; + // } + // } + } + ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height); + plot.redraw(); + c._zoom.isZoomed = true; + ctx = null; + } + plot.target.trigger('jqplotZoom', [gridpos, datapos, plot, cursor]); + } + }; + + $.jqplot.preInitHooks.push($.jqplot.Cursor.init); + $.jqplot.postDrawHooks.push($.jqplot.Cursor.postDraw); + + function updateTooltip(gridpos, datapos, plot) { + var c = plot.plugins.cursor; + var s = ''; + var addbr = false; + if (c.showTooltipGridPosition) { + s = gridpos.x+', '+gridpos.y; + addbr = true; + } + if (c.showTooltipUnitPosition) { + var g; + for (var i=0; i<c.tooltipAxisGroups.length; i++) { + g = c.tooltipAxisGroups[i]; + if (addbr) { + s += '<br />'; + } + if (c.useAxesFormatters) { + for (var j=0; j<g.length; j++) { + if (j) { + s += ', '; + } + var af = plot.axes[g[j]]._ticks[0].formatter; + var afstr = plot.axes[g[j]]._ticks[0].formatString; + s += af(afstr, datapos[g[j]]); + } + } + else { + s += $.jqplot.sprintf(c.tooltipFormatString, datapos[g[0]], datapos[g[1]]); + } + addbr = true; + } + } + + if (c.showTooltipDataPosition) { + var series = plot.series; + var ret = getIntersectingPoints(plot, gridpos.x, gridpos.y); + var addbr = false; + + for (var i = 0; i< series.length; i++) { + if (series[i].show) { + var idx = series[i].index; + var label = series[i].label.toString(); + var cellid = $.inArray(idx, ret.indices); + var sx = undefined; + var sy = undefined; + if (cellid != -1) { + var data = ret.data[cellid].data; + if (c.useAxesFormatters) { + var xf = series[i]._xaxis._ticks[0].formatter; + var yf = series[i]._yaxis._ticks[0].formatter; + var xfstr = series[i]._xaxis._ticks[0].formatString; + var yfstr = series[i]._yaxis._ticks[0].formatString; + sx = xf(xfstr, data[0]); + sy = yf(yfstr, data[1]); + } + else { + sx = data[0]; + sy = data[1]; + } + if (addbr) { + s += '<br />'; + } + s += $.jqplot.sprintf(c.tooltipFormatString, label, sx, sy); + addbr = true; + } + } + } + + } + c._tooltipElem.html(s); + } + + function moveLine(gridpos, plot) { + var c = plot.plugins.cursor; + var ctx = c.cursorCanvas._ctx; + ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height); + if (c.showVerticalLine) { + c.shapeRenderer.draw(ctx, [[gridpos.x, 0], [gridpos.x, ctx.canvas.height]]); + } + if (c.showHorizontalLine) { + c.shapeRenderer.draw(ctx, [[0, gridpos.y], [ctx.canvas.width, gridpos.y]]); + } + var ret = getIntersectingPoints(plot, gridpos.x, gridpos.y); + if (c.showCursorLegend) { + var cells = $(plot.targetId + ' td.jqplot-cursor-legend-label'); + for (var i=0; i<cells.length; i++) { + var idx = $(cells[i]).data('seriesIndex'); + var series = plot.series[idx]; + var label = series.label.toString(); + var cellid = $.inArray(idx, ret.indices); + var sx = undefined; + var sy = undefined; + if (cellid != -1) { + var data = ret.data[cellid].data; + if (c.useAxesFormatters) { + var xf = series._xaxis._ticks[0].formatter; + var yf = series._yaxis._ticks[0].formatter; + var xfstr = series._xaxis._ticks[0].formatString; + var yfstr = series._yaxis._ticks[0].formatString; + sx = xf(xfstr, data[0]); + sy = yf(yfstr, data[1]); + } + else { + sx = data[0]; + sy = data[1]; + } + } + if (plot.legend.escapeHtml) { + $(cells[i]).text($.jqplot.sprintf(c.cursorLegendFormatString, label, sx, sy)); + } + else { + $(cells[i]).html($.jqplot.sprintf(c.cursorLegendFormatString, label, sx, sy)); + } + } + } + ctx = null; + } + + function getIntersectingPoints(plot, x, y) { + var ret = {indices:[], data:[]}; + var s, i, d0, d, j, r, p; + var threshold; + var c = plot.plugins.cursor; + for (var i=0; i<plot.series.length; i++) { + s = plot.series[i]; + r = s.renderer; + if (s.show) { + threshold = c.intersectionThreshold; + if (s.showMarker) { + threshold += s.markerRenderer.size/2; + } + for (var j=0; j<s.gridData.length; j++) { + p = s.gridData[j]; + // check vertical line + if (c.showVerticalLine) { + if (Math.abs(x-p[0]) <= threshold) { + ret.indices.push(i); + ret.data.push({seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]}); + } + } + } + } + } + return ret; + } + + function moveTooltip(gridpos, plot) { + var c = plot.plugins.cursor; + var elem = c._tooltipElem; + switch (c.tooltipLocation) { + case 'nw': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset; + var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true); + break; + case 'n': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2; + var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true); + break; + case 'ne': + var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset; + var y = gridpos.y + plot._gridPadding.top - c.tooltipOffset - elem.outerHeight(true); + break; + case 'e': + var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset; + var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2; + break; + case 'se': + var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset; + var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset; + break; + case 's': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2; + var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset; + break; + case 'sw': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset; + var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset; + break; + case 'w': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - c.tooltipOffset; + var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2; + break; + default: + var x = gridpos.x + plot._gridPadding.left + c.tooltipOffset; + var y = gridpos.y + plot._gridPadding.top + c.tooltipOffset; + break; + } + + elem.css('left', x); + elem.css('top', y); + elem = null; + } + + function positionTooltip(plot) { + // fake a grid for positioning + var grid = plot._gridPadding; + var c = plot.plugins.cursor; + var elem = c._tooltipElem; + switch (c.tooltipLocation) { + case 'nw': + var a = grid.left + c.tooltipOffset; + var b = grid.top + c.tooltipOffset; + elem.css('left', a); + elem.css('top', b); + break; + case 'n': + var a = (grid.left + (plot._plotDimensions.width - grid.right))/2 - elem.outerWidth(true)/2; + var b = grid.top + c.tooltipOffset; + elem.css('left', a); + elem.css('top', b); + break; + case 'ne': + var a = grid.right + c.tooltipOffset; + var b = grid.top + c.tooltipOffset; + elem.css({right:a, top:b}); + break; + case 'e': + var a = grid.right + c.tooltipOffset; + var b = (grid.top + (plot._plotDimensions.height - grid.bottom))/2 - elem.outerHeight(true)/2; + elem.css({right:a, top:b}); + break; + case 'se': + var a = grid.right + c.tooltipOffset; + var b = grid.bottom + c.tooltipOffset; + elem.css({right:a, bottom:b}); + break; + case 's': + var a = (grid.left + (plot._plotDimensions.width - grid.right))/2 - elem.outerWidth(true)/2; + var b = grid.bottom + c.tooltipOffset; + elem.css({left:a, bottom:b}); + break; + case 'sw': + var a = grid.left + c.tooltipOffset; + var b = grid.bottom + c.tooltipOffset; + elem.css({left:a, bottom:b}); + break; + case 'w': + var a = grid.left + c.tooltipOffset; + var b = (grid.top + (plot._plotDimensions.height - grid.bottom))/2 - elem.outerHeight(true)/2; + elem.css({left:a, top:b}); + break; + default: // same as 'se' + var a = grid.right - c.tooltipOffset; + var b = grid.bottom + c.tooltipOffset; + elem.css({right:a, bottom:b}); + break; + } + elem = null; + } + + function handleClick (ev, gridpos, datapos, neighbor, plot) { + ev.preventDefault(); + ev.stopImmediatePropagation(); + var c = plot.plugins.cursor; + if (c.clickReset) { + c.resetZoom(plot, c); + } + var sel = window.getSelection; + if (document.selection && document.selection.empty) + { + document.selection.empty(); + } + else if (sel && !sel().isCollapsed) { + sel().collapse(); + } + return false; + } + + function handleDblClick (ev, gridpos, datapos, neighbor, plot) { + ev.preventDefault(); + ev.stopImmediatePropagation(); + var c = plot.plugins.cursor; + if (c.dblClickReset) { + c.resetZoom(plot, c); + } + var sel = window.getSelection; + if (document.selection && document.selection.empty) + { + document.selection.empty(); + } + else if (sel && !sel().isCollapsed) { + sel().collapse(); + } + return false; + } + + function handleMouseLeave(ev, gridpos, datapos, neighbor, plot) { + var c = plot.plugins.cursor; + c.onGrid = false; + if (c.show) { + $(ev.target).css('cursor', c.previousCursor); + if (c.showTooltip && !(c._zoom.zooming && c.showTooltipOutsideZoom && !c.constrainOutsideZoom)) { + c._tooltipElem.empty(); + c._tooltipElem.hide(); + } + if (c.zoom) { + c._zoom.gridpos = gridpos; + c._zoom.datapos = datapos; + } + if (c.showVerticalLine || c.showHorizontalLine) { + var ctx = c.cursorCanvas._ctx; + ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height); + ctx = null; + } + if (c.showCursorLegend) { + var cells = $(plot.targetId + ' td.jqplot-cursor-legend-label'); + for (var i=0; i<cells.length; i++) { + var idx = $(cells[i]).data('seriesIndex'); + var series = plot.series[idx]; + var label = series.label.toString(); + if (plot.legend.escapeHtml) { + $(cells[i]).text($.jqplot.sprintf(c.cursorLegendFormatString, label, undefined, undefined)); + } + else { + $(cells[i]).html($.jqplot.sprintf(c.cursorLegendFormatString, label, undefined, undefined)); + } + + } + } + } + } + + function handleMouseEnter(ev, gridpos, datapos, neighbor, plot) { + var c = plot.plugins.cursor; + c.onGrid = true; + if (c.show) { + c.previousCursor = ev.target.style.cursor; + ev.target.style.cursor = c.style; + if (c.showTooltip) { + updateTooltip(gridpos, datapos, plot); + if (c.followMouse) { + moveTooltip(gridpos, plot); + } + else { + positionTooltip(plot); + } + c._tooltipElem.show(); + } + if (c.showVerticalLine || c.showHorizontalLine) { + moveLine(gridpos, plot); + } + } + + } + + function handleMouseMove(ev, gridpos, datapos, neighbor, plot) { + var c = plot.plugins.cursor; + if (c.show) { + if (c.showTooltip) { + updateTooltip(gridpos, datapos, plot); + if (c.followMouse) { + moveTooltip(gridpos, plot); + } + } + if (c.showVerticalLine || c.showHorizontalLine) { + moveLine(gridpos, plot); + } + } + } + + function getEventPosition(ev) { + var plot = ev.data.plot; + var go = plot.eventCanvas._elem.offset(); + var gridPos = {x:ev.pageX - go.left, y:ev.pageY - go.top}; + ////// + // TO DO: handle yMidAxis + ////// + var dataPos = {xaxis:null, yaxis:null, x2axis:null, y2axis:null, y3axis:null, y4axis:null, y5axis:null, y6axis:null, y7axis:null, y8axis:null, y9axis:null, yMidAxis:null}; + var an = ['xaxis', 'yaxis', 'x2axis', 'y2axis', 'y3axis', 'y4axis', 'y5axis', 'y6axis', 'y7axis', 'y8axis', 'y9axis', 'yMidAxis']; + var ax = plot.axes; + var n, axis; + for (n=11; n>0; n--) { + axis = an[n-1]; + if (ax[axis].show) { + dataPos[axis] = ax[axis].series_p2u(gridPos[axis.charAt(0)]); + } + } + + return {offsets:go, gridPos:gridPos, dataPos:dataPos}; + } + + function handleZoomMove(ev) { + var plot = ev.data.plot; + var c = plot.plugins.cursor; + // don't do anything if not on grid. + if (c.show && c.zoom && c._zoom.started && !c.zoomTarget) { + ev.preventDefault(); + var ctx = c.zoomCanvas._ctx; + var positions = getEventPosition(ev); + var gridpos = positions.gridPos; + var datapos = positions.dataPos; + c._zoom.gridpos = gridpos; + c._zoom.datapos = datapos; + c._zoom.zooming = true; + var xpos = gridpos.x; + var ypos = gridpos.y; + var height = ctx.canvas.height; + var width = ctx.canvas.width; + if (c.showTooltip && !c.onGrid && c.showTooltipOutsideZoom) { + updateTooltip(gridpos, datapos, plot); + if (c.followMouse) { + moveTooltip(gridpos, plot); + } + } + if (c.constrainZoomTo == 'x') { + c._zoom.end = [xpos, height]; + } + else if (c.constrainZoomTo == 'y') { + c._zoom.end = [width, ypos]; + } + else { + c._zoom.end = [xpos, ypos]; + } + var sel = window.getSelection; + if (document.selection && document.selection.empty) + { + document.selection.empty(); + } + else if (sel && !sel().isCollapsed) { + sel().collapse(); + } + drawZoomBox.call(c); + ctx = null; + } + } + + function handleMouseDown(ev, gridpos, datapos, neighbor, plot) { + var c = plot.plugins.cursor; + if(plot.plugins.mobile){ + $(document).one('vmouseup.jqplot_cursor', {plot:plot}, handleMouseUp); + } else { + $(document).one('mouseup.jqplot_cursor', {plot:plot}, handleMouseUp); + } + var axes = plot.axes; + if (document.onselectstart != undefined) { + c._oldHandlers.onselectstart = document.onselectstart; + document.onselectstart = function () { return false; }; + } + if (document.ondrag != undefined) { + c._oldHandlers.ondrag = document.ondrag; + document.ondrag = function () { return false; }; + } + if (document.onmousedown != undefined) { + c._oldHandlers.onmousedown = document.onmousedown; + document.onmousedown = function () { return false; }; + } + if (c.zoom) { + if (!c.zoomProxy) { + var ctx = c.zoomCanvas._ctx; + ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height); + ctx = null; + } + if (c.constrainZoomTo == 'x') { + c._zoom.start = [gridpos.x, 0]; + } + else if (c.constrainZoomTo == 'y') { + c._zoom.start = [0, gridpos.y]; + } + else { + c._zoom.start = [gridpos.x, gridpos.y]; + } + c._zoom.started = true; + for (var ax in datapos) { + // get zoom starting position. + c._zoom.axes.start[ax] = datapos[ax]; + } + if(plot.plugins.mobile){ + $(document).bind('vmousemove.jqplotCursor', {plot:plot}, handleZoomMove); + } else { + $(document).bind('mousemove.jqplotCursor', {plot:plot}, handleZoomMove); + } + + } + } + + function handleMouseUp(ev) { + var plot = ev.data.plot; + var c = plot.plugins.cursor; + if (c.zoom && c._zoom.zooming && !c.zoomTarget) { + var xpos = c._zoom.gridpos.x; + var ypos = c._zoom.gridpos.y; + var datapos = c._zoom.datapos; + var height = c.zoomCanvas._ctx.canvas.height; + var width = c.zoomCanvas._ctx.canvas.width; + var axes = plot.axes; + + if (c.constrainOutsideZoom && !c.onGrid) { + if (xpos < 0) { xpos = 0; } + else if (xpos > width) { xpos = width; } + if (ypos < 0) { ypos = 0; } + else if (ypos > height) { ypos = height; } + + for (var axis in datapos) { + if (datapos[axis]) { + if (axis.charAt(0) == 'x') { + datapos[axis] = axes[axis].series_p2u(xpos); + } + else { + datapos[axis] = axes[axis].series_p2u(ypos); + } + } + } + } + + if (c.constrainZoomTo == 'x') { + ypos = height; + } + else if (c.constrainZoomTo == 'y') { + xpos = width; + } + c._zoom.end = [xpos, ypos]; + c._zoom.gridpos = {x:xpos, y:ypos}; + + c.doZoom(c._zoom.gridpos, datapos, plot, c); + } + c._zoom.started = false; + c._zoom.zooming = false; + + $(document).unbind('mousemove.jqplotCursor', handleZoomMove); + + if (document.onselectstart != undefined && c._oldHandlers.onselectstart != null){ + document.onselectstart = c._oldHandlers.onselectstart; + c._oldHandlers.onselectstart = null; + } + if (document.ondrag != undefined && c._oldHandlers.ondrag != null){ + document.ondrag = c._oldHandlers.ondrag; + c._oldHandlers.ondrag = null; + } + if (document.onmousedown != undefined && c._oldHandlers.onmousedown != null){ + document.onmousedown = c._oldHandlers.onmousedown; + c._oldHandlers.onmousedown = null; + } + + } + + function drawZoomBox() { + var start = this._zoom.start; + var end = this._zoom.end; + var ctx = this.zoomCanvas._ctx; + var l, t, h, w; + if (end[0] > start[0]) { + l = start[0]; + w = end[0] - start[0]; + } + else { + l = end[0]; + w = start[0] - end[0]; + } + if (end[1] > start[1]) { + t = start[1]; + h = end[1] - start[1]; + } + else { + t = end[1]; + h = start[1] - end[1]; + } + ctx.fillStyle = 'rgba(0,0,0,0.2)'; + ctx.strokeStyle = '#999999'; + ctx.lineWidth = 1.0; + ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height); + ctx.fillRect(0,0,ctx.canvas.width, ctx.canvas.height); + ctx.clearRect(l, t, w, h); + // IE won't show transparent fill rect, so stroke a rect also. + ctx.strokeRect(l,t,w,h); + ctx = null; + } + + $.jqplot.CursorLegendRenderer = function(options) { + $.jqplot.TableLegendRenderer.call(this, options); + this.formatString = '%s'; + }; + + $.jqplot.CursorLegendRenderer.prototype = new $.jqplot.TableLegendRenderer(); + $.jqplot.CursorLegendRenderer.prototype.constructor = $.jqplot.CursorLegendRenderer; + + // called in context of a Legend + $.jqplot.CursorLegendRenderer.prototype.draw = function() { + if (this._elem) { + this._elem.emptyForce(); + this._elem = null; + } + if (this.show) { + var series = this._series, s; + // make a table. one line label per row. + var elem = document.createElement('div'); + this._elem = $(elem); + elem = null; + this._elem.addClass('jqplot-legend jqplot-cursor-legend'); + this._elem.css('position', 'absolute'); + + var pad = false; + for (var i = 0; i< series.length; i++) { + s = series[i]; + if (s.show && s.showLabel) { + var lt = $.jqplot.sprintf(this.formatString, s.label.toString()); + if (lt) { + var color = s.color; + if (s._stack && !s.fill) { + color = ''; + } + addrow.call(this, lt, color, pad, i); + pad = true; + } + // let plugins add more rows to legend. Used by trend line plugin. + for (var j=0; j<$.jqplot.addLegendRowHooks.length; j++) { + var item = $.jqplot.addLegendRowHooks[j].call(this, s); + if (item) { + addrow.call(this, item.label, item.color, pad); + pad = true; + } + } + } + } + series = s = null; + delete series; + delete s; + } + + function addrow(label, color, pad, idx) { + var rs = (pad) ? this.rowSpacing : '0'; + var tr = $('<tr class="jqplot-legend jqplot-cursor-legend"></tr>').appendTo(this._elem); + tr.data('seriesIndex', idx); + $('<td class="jqplot-legend jqplot-cursor-legend-swatch" style="padding-top:'+rs+';">'+ + '<div style="border:1px solid #cccccc;padding:0.2em;">'+ + '<div class="jqplot-cursor-legend-swatch" style="background-color:'+color+';"></div>'+ + '</div></td>').appendTo(tr); + var td = $('<td class="jqplot-legend jqplot-cursor-legend-label" style="vertical-align:middle;padding-top:'+rs+';"></td>'); + td.appendTo(tr); + td.data('seriesIndex', idx); + if (this.escapeHtml) { + td.text(label); + } + else { + td.html(label); + } + tr = null; + td = null; + } + return this._elem; + }; + +})(jQuery); diff --git a/hugo/js/jqplot/plugins/jqplot.dateAxisRenderer.js b/hugo/js/jqplot/plugins/jqplot.dateAxisRenderer.js new file mode 100644 index 0000000..ec4211d --- /dev/null +++ b/hugo/js/jqplot/plugins/jqplot.dateAxisRenderer.js @@ -0,0 +1,737 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.4 + * Revision: 1121 + * + * Copyright (c) 2009-2012 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + /** + * Class: $.jqplot.DateAxisRenderer + * A plugin for a jqPlot to render an axis as a series of date values. + * This renderer has no options beyond those supplied by the <Axis> class. + * It supplies it's own tick formatter, so the tickOptions.formatter option + * should not be overridden. + * + * Thanks to Ken Synder for his enhanced Date instance methods which are + * included with this code <http://kendsnyder.com/sandbox/date/>. + * + * To use this renderer, include the plugin in your source + * > <script type="text/javascript" language="javascript" src="plugins/jqplot.dateAxisRenderer.js"></script> + * + * and supply the appropriate options to your plot + * + * > {axes:{xaxis:{renderer:$.jqplot.DateAxisRenderer}}} + * + * Dates can be passed into the axis in almost any recognizable value and + * will be parsed. They will be rendered on the axis in the format + * specified by tickOptions.formatString. e.g. tickOptions.formatString = '%Y-%m-%d'. + * + * Accecptable format codes + * are: + * + * > Code Result Description + * > == Years == + * > %Y 2008 Four-digit year + * > %y 08 Two-digit year + * > == Months == + * > %m 09 Two-digit month + * > %#m 9 One or two-digit month + * > %B September Full month name + * > %b Sep Abbreviated month name + * > == Days == + * > %d 05 Two-digit day of month + * > %#d 5 One or two-digit day of month + * > %e 5 One or two-digit day of month + * > %A Sunday Full name of the day of the week + * > %a Sun Abbreviated name of the day of the week + * > %w 0 Number of the day of the week (0 = Sunday, 6 = Saturday) + * > %o th The ordinal suffix string following the day of the month + * > == Hours == + * > %H 23 Hours in 24-hour format (two digits) + * > %#H 3 Hours in 24-hour integer format (one or two digits) + * > %I 11 Hours in 12-hour format (two digits) + * > %#I 3 Hours in 12-hour integer format (one or two digits) + * > %p PM AM or PM + * > == Minutes == + * > %M 09 Minutes (two digits) + * > %#M 9 Minutes (one or two digits) + * > == Seconds == + * > %S 02 Seconds (two digits) + * > %#S 2 Seconds (one or two digits) + * > %s 1206567625723 Unix timestamp (Seconds past 1970-01-01 00:00:00) + * > == Milliseconds == + * > %N 008 Milliseconds (three digits) + * > %#N 8 Milliseconds (one to three digits) + * > == Timezone == + * > %O 360 difference in minutes between local time and GMT + * > %Z Mountain Standard Time Name of timezone as reported by browser + * > %G -06:00 Hours and minutes between GMT + * > == Shortcuts == + * > %F 2008-03-26 %Y-%m-%d + * > %T 05:06:30 %H:%M:%S + * > %X 05:06:30 %H:%M:%S + * > %x 03/26/08 %m/%d/%y + * > %D 03/26/08 %m/%d/%y + * > %#c Wed Mar 26 15:31:00 2008 %a %b %e %H:%M:%S %Y + * > %v 3-Sep-2008 %e-%b-%Y + * > %R 15:31 %H:%M + * > %r 3:31:00 PM %I:%M:%S %p + * > == Characters == + * > %n \n Newline + * > %t \t Tab + * > %% % Percent Symbol + */ + $.jqplot.DateAxisRenderer = function() { + $.jqplot.LinearAxisRenderer.call(this); + this.date = new $.jsDate(); + }; + + var second = 1000; + var minute = 60 * second; + var hour = 60 * minute; + var day = 24 * hour; + var week = 7 * day; + + // these are less definitive + var month = 30.4368499 * day; + var year = 365.242199 * day; + + var daysInMonths = [31,28,31,30,31,30,31,30,31,30,31,30]; + // array of consistent nice intervals. Longer intervals + // will depend on days in month, days in year, etc. + var niceFormatStrings = ['%M:%S.%#N', '%M:%S.%#N', '%M:%S.%#N', '%M:%S', '%M:%S', '%M:%S', '%M:%S', '%H:%M:%S', '%H:%M:%S', '%H:%M', '%H:%M', '%H:%M', '%H:%M', '%H:%M', '%H:%M', '%a %H:%M', '%a %H:%M', '%b %e %H:%M', '%b %e %H:%M', '%b %e %H:%M', '%b %e %H:%M', '%v', '%v', '%v', '%v', '%v', '%v', '%v']; + var niceIntervals = [0.1*second, 0.2*second, 0.5*second, second, 2*second, 5*second, 10*second, 15*second, 30*second, minute, 2*minute, 5*minute, 10*minute, 15*minute, 30*minute, hour, 2*hour, 4*hour, 6*hour, 8*hour, 12*hour, day, 2*day, 3*day, 4*day, 5*day, week, 2*week]; + + var niceMonthlyIntervals = []; + + function bestDateInterval(min, max, titarget) { + // iterate through niceIntervals to find one closest to titarget + var badness = Number.MAX_VALUE; + var temp, bestTi, bestfmt; + for (var i=0, l=niceIntervals.length; i < l; i++) { + temp = Math.abs(titarget - niceIntervals[i]); + if (temp < badness) { + badness = temp; + bestTi = niceIntervals[i]; + bestfmt = niceFormatStrings[i]; + } + } + + return [bestTi, bestfmt]; + } + + $.jqplot.DateAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer(); + $.jqplot.DateAxisRenderer.prototype.constructor = $.jqplot.DateAxisRenderer; + + $.jqplot.DateTickFormatter = function(format, val) { + if (!format) { + format = '%Y/%m/%d'; + } + return $.jsDate.strftime(val, format); + }; + + $.jqplot.DateAxisRenderer.prototype.init = function(options){ + // prop: tickRenderer + // A class of a rendering engine for creating the ticks labels displayed on the plot, + // See <$.jqplot.AxisTickRenderer>. + // this.tickRenderer = $.jqplot.AxisTickRenderer; + // this.labelRenderer = $.jqplot.AxisLabelRenderer; + this.tickOptions.formatter = $.jqplot.DateTickFormatter; + // prop: tickInset + // Controls the amount to inset the first and last ticks from + // the edges of the grid, in multiples of the tick interval. + // 0 is no inset, 0.5 is one half a tick interval, 1 is a full + // tick interval, etc. + this.tickInset = 0; + // prop: drawBaseline + // True to draw the axis baseline. + this.drawBaseline = true; + // prop: baselineWidth + // width of the baseline in pixels. + this.baselineWidth = null; + // prop: baselineColor + // CSS color spec for the baseline. + this.baselineColor = null; + this.daTickInterval = null; + this._daTickInterval = null; + + $.extend(true, this, options); + + var db = this._dataBounds, + stats, + sum, + s, + d, + pd, + sd, + intv; + + // Go through all the series attached to this axis and find + // the min/max bounds for this axis. + for (var i=0; i<this._series.length; i++) { + stats = {intervals:[], frequencies:{}, sortedIntervals:[], min:null, max:null, mean:null}; + sum = 0; + s = this._series[i]; + d = s.data; + pd = s._plotData; + sd = s._stackData; + intv = 0; + + for (var j=0; j<d.length; j++) { + if (this.name == 'xaxis' || this.name == 'x2axis') { + d[j][0] = new $.jsDate(d[j][0]).getTime(); + pd[j][0] = new $.jsDate(d[j][0]).getTime(); + sd[j][0] = new $.jsDate(d[j][0]).getTime(); + if ((d[j][0] != null && d[j][0] < db.min) || db.min == null) { + db.min = d[j][0]; + } + if ((d[j][0] != null && d[j][0] > db.max) || db.max == null) { + db.max = d[j][0]; + } + if (j>0) { + intv = Math.abs(d[j][0] - d[j-1][0]); + stats.intervals.push(intv); + if (stats.frequencies.hasOwnProperty(intv)) { + stats.frequencies[intv] += 1; + } + else { + stats.frequencies[intv] = 1; + } + } + sum += intv; + + } + else { + d[j][1] = new $.jsDate(d[j][1]).getTime(); + pd[j][1] = new $.jsDate(d[j][1]).getTime(); + sd[j][1] = new $.jsDate(d[j][1]).getTime(); + if ((d[j][1] != null && d[j][1] < db.min) || db.min == null) { + db.min = d[j][1]; + } + if ((d[j][1] != null && d[j][1] > db.max) || db.max == null) { + db.max = d[j][1]; + } + if (j>0) { + intv = Math.abs(d[j][1] - d[j-1][1]); + stats.intervals.push(intv); + if (stats.frequencies.hasOwnProperty(intv)) { + stats.frequencies[intv] += 1; + } + else { + stats.frequencies[intv] = 1; + } + } + } + sum += intv; + } + + if (s.renderer.bands) { + if (s.renderer.bands.hiData.length) { + var bd = s.renderer.bands.hiData; + for (var j=0, l=bd.length; j < l; j++) { + if (this.name === 'xaxis' || this.name === 'x2axis') { + bd[j][0] = new $.jsDate(bd[j][0]).getTime(); + if ((bd[j][0] != null && bd[j][0] > db.max) || db.max == null) { + db.max = bd[j][0]; + } + } + else { + bd[j][1] = new $.jsDate(bd[j][1]).getTime(); + if ((bd[j][1] != null && bd[j][1] > db.max) || db.max == null) { + db.max = bd[j][1]; + } + } + } + } + if (s.renderer.bands.lowData.length) { + var bd = s.renderer.bands.lowData; + for (var j=0, l=bd.length; j < l; j++) { + if (this.name === 'xaxis' || this.name === 'x2axis') { + bd[j][0] = new $.jsDate(bd[j][0]).getTime(); + if ((bd[j][0] != null && bd[j][0] < db.min) || db.min == null) { + db.min = bd[j][0]; + } + } + else { + bd[j][1] = new $.jsDate(bd[j][1]).getTime(); + if ((bd[j][1] != null && bd[j][1] < db.min) || db.min == null) { + db.min = bd[j][1]; + } + } + } + } + } + + var tempf = 0, + tempn=0; + for (var n in stats.frequencies) { + stats.sortedIntervals.push({interval:n, frequency:stats.frequencies[n]}); + } + stats.sortedIntervals.sort(function(a, b){ + return b.frequency - a.frequency; + }); + + stats.min = $.jqplot.arrayMin(stats.intervals); + stats.max = $.jqplot.arrayMax(stats.intervals); + stats.mean = sum/d.length; + this._intervalStats.push(stats); + stats = sum = s = d = pd = sd = null; + } + db = null; + + }; + + // called with scope of an axis + $.jqplot.DateAxisRenderer.prototype.reset = function() { + this.min = this._options.min; + this.max = this._options.max; + this.tickInterval = this._options.tickInterval; + this.numberTicks = this._options.numberTicks; + this._autoFormatString = ''; + if (this._overrideFormatString && this.tickOptions && this.tickOptions.formatString) { + this.tickOptions.formatString = ''; + } + this.daTickInterval = this._daTickInterval; + // this._ticks = this.__ticks; + }; + + $.jqplot.DateAxisRenderer.prototype.createTicks = function(plot) { + // we're are operating on an axis here + var ticks = this._ticks; + var userTicks = this.ticks; + var name = this.name; + // databounds were set on axis initialization. + var db = this._dataBounds; + var iv = this._intervalStats; + var dim = (this.name.charAt(0) === 'x') ? this._plotDimensions.width : this._plotDimensions.height; + var interval; + var min, max; + var pos1, pos2; + var tt, i; + var threshold = 30; + var insetMult = 1; + + var tickInterval = this.tickInterval; + + // if we already have ticks, use them. + // ticks must be in order of increasing value. + + min = ((this.min != null) ? new $.jsDate(this.min).getTime() : db.min); + max = ((this.max != null) ? new $.jsDate(this.max).getTime() : db.max); + + // see if we're zooming. if we are, don't use the min and max we're given, + // but compute some nice ones. They will be reset later. + + var cursor = plot.plugins.cursor; + + if (cursor && cursor._zoom && cursor._zoom.zooming) { + this.min = null; + this.max = null; + } + + var range = max - min; + + if (this.tickOptions == null || !this.tickOptions.formatString) { + this._overrideFormatString = true; + } + + if (userTicks.length) { + // ticks could be 1D or 2D array of [val, val, ,,,] or [[val, label], [val, label], ...] or mixed + for (i=0; i<userTicks.length; i++){ + var ut = userTicks[i]; + var t = new this.tickRenderer(this.tickOptions); + if (ut.constructor == Array) { + t.value = new $.jsDate(ut[0]).getTime(); + t.label = ut[1]; + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(t.value, this.name); + this._ticks.push(t); + } + + else { + t.value = new $.jsDate(ut).getTime(); + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(t.value, this.name); + this._ticks.push(t); + } + } + this.numberTicks = userTicks.length; + this.min = this._ticks[0].value; + this.max = this._ticks[this.numberTicks-1].value; + this.daTickInterval = [(this.max - this.min) / (this.numberTicks - 1)/1000, 'seconds']; + } + + //////// + // We don't have any ticks yet, let's make some! + //////// + + // special case when there is only one point, make three tick marks to center the point + else if (this.min == null && this.max == null && db.min == db.max) + { + var onePointOpts = $.extend(true, {}, this.tickOptions, {name: this.name, value: null}); + var delta = 300000; + this.min = db.min - delta; + this.max = db.max + delta; + this.numberTicks = 3; + + for(var i=this.min;i<=this.max;i+= delta) + { + onePointOpts.value = i; + + var t = new this.tickRenderer(onePointOpts); + + if (this._overrideFormatString && this._autoFormatString != '') { + t.formatString = this._autoFormatString; + } + + t.showLabel = false; + t.showMark = false; + + this._ticks.push(t); + } + + if(this.showTicks) { + this._ticks[1].showLabel = true; + } + if(this.showTickMarks) { + this._ticks[1].showTickMarks = true; + } + } + // if user specified min and max are null, we set those to make best ticks. + else if (this.min == null && this.max == null) { + + var opts = $.extend(true, {}, this.tickOptions, {name: this.name, value: null}); + + // want to find a nice interval + var nttarget, + titarget; + + // if no tickInterval or numberTicks options specified, make a good guess. + if (!this.tickInterval && !this.numberTicks) { + var tdim = Math.max(dim, threshold+1); + // how many ticks to put on the axis? + // date labels tend to be long. If ticks not rotated, + // don't use too many and have a high spacing factor. + // If we are rotating ticks, use a lower factor. + var spacingFactor = 115; + if (this.tickRenderer === $.jqplot.CanvasAxisTickRenderer && this.tickOptions.angle) { + spacingFactor = 115 - 40 * Math.abs(Math.sin(this.tickOptions.angle/180*Math.PI)); + } + + nttarget = Math.ceil((tdim-threshold)/spacingFactor + 1); + titarget = (max - min) / (nttarget - 1); + } + + // If tickInterval is specified, we'll try to honor it. + // Not gauranteed to get this interval, but we'll get as close as + // we can. + // tickInterval will be used before numberTicks, that is if + // both are specified, numberTicks will be ignored. + else if (this.tickInterval) { + titarget = this.tickInterval; + } + + // if numberTicks specified, try to honor it. + // Not gauranteed, but will try to get close. + else if (this.numberTicks) { + nttarget = this.numberTicks; + titarget = (max - min) / (nttarget - 1); + } + + // If we can use an interval of 2 weeks or less, pick best one + if (titarget <= 19*day) { + var ret = bestDateInterval(min, max, titarget); + var tempti = ret[0]; + this._autoFormatString = ret[1]; + + min = Math.floor(min/tempti) * tempti; + min = new $.jsDate(min); + min = min.getTime() + min.getUtcOffset(); + + nttarget = Math.ceil((max - min) / tempti) + 1; + this.min = min; + this.max = min + (nttarget - 1) * tempti; + + // if max is less than max, add an interval + if (this.max < max) { + this.max += tempti; + nttarget += 1; + } + this.tickInterval = tempti; + this.numberTicks = nttarget; + + for (var i=0; i<nttarget; i++) { + opts.value = this.min + i * tempti; + t = new this.tickRenderer(opts); + + if (this._overrideFormatString && this._autoFormatString != '') { + t.formatString = this._autoFormatString; + } + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + this._ticks.push(t); + } + + insetMult = this.tickInterval; + } + + // should we use a monthly interval? + else if (titarget <= 9 * month) { + + this._autoFormatString = '%v'; + + // how many months in an interval? + var intv = Math.round(titarget/month); + if (intv < 1) { + intv = 1; + } + else if (intv > 6) { + intv = 6; + } + + // figure out the starting month and ending month. + var mstart = new $.jsDate(min).setDate(1).setHours(0,0,0,0); + + // See if max ends exactly on a month + var tempmend = new $.jsDate(max); + var mend = new $.jsDate(max).setDate(1).setHours(0,0,0,0); + + if (tempmend.getTime() !== mend.getTime()) { + mend = mend.add(1, 'month'); + } + + var nmonths = mend.diff(mstart, 'month'); + + nttarget = Math.ceil(nmonths/intv) + 1; + + this.min = mstart.getTime(); + this.max = mstart.clone().add((nttarget - 1) * intv, 'month').getTime(); + this.numberTicks = nttarget; + + for (var i=0; i<nttarget; i++) { + if (i === 0) { + opts.value = mstart.getTime(); + } + else { + opts.value = mstart.add(intv, 'month').getTime(); + } + t = new this.tickRenderer(opts); + + if (this._overrideFormatString && this._autoFormatString != '') { + t.formatString = this._autoFormatString; + } + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + this._ticks.push(t); + } + + insetMult = intv * month; + } + + // use yearly intervals + else { + + this._autoFormatString = '%v'; + + // how many years in an interval? + var intv = Math.round(titarget/year); + if (intv < 1) { + intv = 1; + } + + // figure out the starting and ending years. + var mstart = new $.jsDate(min).setMonth(0, 1).setHours(0,0,0,0); + var mend = new $.jsDate(max).add(1, 'year').setMonth(0, 1).setHours(0,0,0,0); + + var nyears = mend.diff(mstart, 'year'); + + nttarget = Math.ceil(nyears/intv) + 1; + + this.min = mstart.getTime(); + this.max = mstart.clone().add((nttarget - 1) * intv, 'year').getTime(); + this.numberTicks = nttarget; + + for (var i=0; i<nttarget; i++) { + if (i === 0) { + opts.value = mstart.getTime(); + } + else { + opts.value = mstart.add(intv, 'year').getTime(); + } + t = new this.tickRenderer(opts); + + if (this._overrideFormatString && this._autoFormatString != '') { + t.formatString = this._autoFormatString; + } + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + this._ticks.push(t); + } + + insetMult = intv * year; + } + } + + //////// + // Some option(s) specified, work around that. + //////// + + else { + if (name == 'xaxis' || name == 'x2axis') { + dim = this._plotDimensions.width; + } + else { + dim = this._plotDimensions.height; + } + + // if min, max and number of ticks specified, user can't specify interval. + if (this.min != null && this.max != null && this.numberTicks != null) { + this.tickInterval = null; + } + + // if user specified a tick interval, convert to usable. + if (this.tickInterval != null) + { + // if interval is a number or can be converted to one, use it. + // Assume it is in SECONDS!!! + if (Number(this.tickInterval)) { + this.daTickInterval = [Number(this.tickInterval), 'seconds']; + } + // else, parse out something we can build from. + else if (typeof this.tickInterval == "string") { + var parts = this.tickInterval.split(' '); + if (parts.length == 1) { + this.daTickInterval = [1, parts[0]]; + } + else if (parts.length == 2) { + this.daTickInterval = [parts[0], parts[1]]; + } + } + } + + // if min and max are same, space them out a bit + if (min == max) { + var adj = 24*60*60*500; // 1/2 day + min -= adj; + max += adj; + } + + range = max - min; + + var optNumTicks = 2 + parseInt(Math.max(0, dim-100)/100, 10); + + + var rmin, rmax; + + rmin = (this.min != null) ? new $.jsDate(this.min).getTime() : min - range/2*(this.padMin - 1); + rmax = (this.max != null) ? new $.jsDate(this.max).getTime() : max + range/2*(this.padMax - 1); + this.min = rmin; + this.max = rmax; + range = this.max - this.min; + + if (this.numberTicks == null){ + // if tickInterval is specified by user, we will ignore computed maximum. + // max will be equal or greater to fit even # of ticks. + if (this.daTickInterval != null) { + var nc = new $.jsDate(this.max).diff(this.min, this.daTickInterval[1], true); + this.numberTicks = Math.ceil(nc/this.daTickInterval[0]) +1; + // this.max = new $.jsDate(this.min).add(this.numberTicks-1, this.daTickInterval[1]).getTime(); + this.max = new $.jsDate(this.min).add((this.numberTicks-1) * this.daTickInterval[0], this.daTickInterval[1]).getTime(); + } + else if (dim > 200) { + this.numberTicks = parseInt(3+(dim-200)/100, 10); + } + else { + this.numberTicks = 2; + } + } + + insetMult = range / (this.numberTicks-1)/1000; + + if (this.daTickInterval == null) { + this.daTickInterval = [insetMult, 'seconds']; + } + + + for (var i=0; i<this.numberTicks; i++){ + var min = new $.jsDate(this.min); + tt = min.add(i*this.daTickInterval[0], this.daTickInterval[1]).getTime(); + var t = new this.tickRenderer(this.tickOptions); + // var t = new $.jqplot.AxisTickRenderer(this.tickOptions); + if (!this.showTicks) { + t.showLabel = false; + t.showMark = false; + } + else if (!this.showTickMarks) { + t.showMark = false; + } + t.setTick(tt, this.name); + this._ticks.push(t); + } + } + + if (this.tickInset) { + this.min = this.min - this.tickInset * insetMult; + this.max = this.max + this.tickInset * insetMult; + } + + if (this._daTickInterval == null) { + this._daTickInterval = this.daTickInterval; + } + + ticks = null; + }; + +})(jQuery); + diff --git a/hugo/js/jqplot/plugins/jqplot.highlighter.js b/hugo/js/jqplot/plugins/jqplot.highlighter.js new file mode 100644 index 0000000..2e8c5da --- /dev/null +++ b/hugo/js/jqplot/plugins/jqplot.highlighter.js @@ -0,0 +1,465 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.4 + * Revision: 1121 + * + * Copyright (c) 2009-2012 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + $.jqplot.eventListenerHooks.push(['jqplotMouseMove', handleMove]); + + /** + * Class: $.jqplot.Highlighter + * Plugin which will highlight data points when they are moused over. + * + * To use this plugin, include the js + * file in your source: + * + * > <script type="text/javascript" src="plugins/jqplot.highlighter.js"></script> + * + * A tooltip providing information about the data point is enabled by default. + * To disable the tooltip, set "showTooltip" to false. + * + * You can control what data is displayed in the tooltip with various + * options. The "tooltipAxes" option controls wether the x, y or both + * data values are displayed. + * + * Some chart types (e.g. hi-low-close) have more than one y value per + * data point. To display the additional values in the tooltip, set the + * "yvalues" option to the desired number of y values present (3 for a hlc chart). + * + * By default, data values will be formatted with the same formatting + * specifiers as used to format the axis ticks. A custom format code + * can be supplied with the tooltipFormatString option. This will apply + * to all values in the tooltip. + * + * For more complete control, the "formatString" option can be set. This + * Allows conplete control over tooltip formatting. Values are passed to + * the format string in an order determined by the "tooltipAxes" and "yvalues" + * options. So, if you have a hi-low-close chart and you just want to display + * the hi-low-close values in the tooltip, you could set a formatString like: + * + * > highlighter: { + * > tooltipAxes: 'y', + * > yvalues: 3, + * > formatString:'<table class="jqplot-highlighter"> + * > <tr><td>hi:</td><td>%s</td></tr> + * > <tr><td>low:</td><td>%s</td></tr> + * > <tr><td>close:</td><td>%s</td></tr></table>' + * > } + * + */ + $.jqplot.Highlighter = function(options) { + // Group: Properties + // + //prop: show + // true to show the highlight. + this.show = $.jqplot.config.enablePlugins; + // prop: markerRenderer + // Renderer used to draw the marker of the highlighted point. + // Renderer will assimilate attributes from the data point being highlighted, + // so no attributes need set on the renderer directly. + // Default is to turn off shadow drawing on the highlighted point. + this.markerRenderer = new $.jqplot.MarkerRenderer({shadow:false}); + // prop: showMarker + // true to show the marker + this.showMarker = true; + // prop: lineWidthAdjust + // Pixels to add to the lineWidth of the highlight. + this.lineWidthAdjust = 2.5; + // prop: sizeAdjust + // Pixels to add to the overall size of the highlight. + this.sizeAdjust = 5; + // prop: showTooltip + // Show a tooltip with data point values. + this.showTooltip = true; + // prop: tooltipLocation + // Where to position tooltip, 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw' + this.tooltipLocation = 'nw'; + // prop: fadeTooltip + // true = fade in/out tooltip, flase = show/hide tooltip + this.fadeTooltip = true; + // prop: tooltipFadeSpeed + // 'slow', 'def', 'fast', or number of milliseconds. + this.tooltipFadeSpeed = "fast"; + // prop: tooltipOffset + // Pixel offset of tooltip from the highlight. + this.tooltipOffset = 2; + // prop: tooltipAxes + // Which axes to display in tooltip, 'x', 'y' or 'both', 'xy' or 'yx' + // 'both' and 'xy' are equivalent, 'yx' reverses order of labels. + this.tooltipAxes = 'both'; + // prop; tooltipSeparator + // String to use to separate x and y axes in tooltip. + this.tooltipSeparator = ', '; + // prop; tooltipContentEditor + // Function used to edit/augment/replace the formatted tooltip contents. + // Called as str = tooltipContentEditor(str, seriesIndex, pointIndex) + // where str is the generated tooltip html and seriesIndex and pointIndex identify + // the data point being highlighted. Should return the html for the tooltip contents. + this.tooltipContentEditor = null; + // prop: useAxesFormatters + // Use the x and y axes formatters to format the text in the tooltip. + this.useAxesFormatters = true; + // prop: tooltipFormatString + // sprintf format string for the tooltip. + // Uses Ash Searle's javascript sprintf implementation + // found here: http://hexmen.com/blog/2007/03/printf-sprintf/ + // See http://perldoc.perl.org/functions/sprintf.html for reference. + // Additional "p" and "P" format specifiers added by Chris Leonello. + this.tooltipFormatString = '%.5P'; + // prop: formatString + // alternative to tooltipFormatString + // will format the whole tooltip text, populating with x, y values as + // indicated by tooltipAxes option. So, you could have a tooltip like: + // 'Date: %s, number of cats: %d' to format the whole tooltip at one go. + // If useAxesFormatters is true, values will be formatted according to + // Axes formatters and you can populate your tooltip string with + // %s placeholders. + this.formatString = null; + // prop: yvalues + // Number of y values to expect in the data point array. + // Typically this is 1. Certain plots, like OHLC, will + // have more y values in each data point array. + this.yvalues = 1; + // prop: bringSeriesToFront + // This option requires jQuery 1.4+ + // True to bring the series of the highlighted point to the front + // of other series. + this.bringSeriesToFront = false; + this._tooltipElem; + this.isHighlighting = false; + this.currentNeighbor = null; + + $.extend(true, this, options); + }; + + var locations = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w']; + var locationIndicies = {'nw':0, 'n':1, 'ne':2, 'e':3, 'se':4, 's':5, 'sw':6, 'w':7}; + var oppositeLocations = ['se', 's', 'sw', 'w', 'nw', 'n', 'ne', 'e']; + + // axis.renderer.tickrenderer.formatter + + // called with scope of plot + $.jqplot.Highlighter.init = function (target, data, opts){ + var options = opts || {}; + // add a highlighter attribute to the plot + this.plugins.highlighter = new $.jqplot.Highlighter(options.highlighter); + }; + + // called within scope of series + $.jqplot.Highlighter.parseOptions = function (defaults, options) { + // Add a showHighlight option to the series + // and set it to true by default. + this.showHighlight = true; + }; + + // called within context of plot + // create a canvas which we can draw on. + // insert it before the eventCanvas, so eventCanvas will still capture events. + $.jqplot.Highlighter.postPlotDraw = function() { + // Memory Leaks patch + if (this.plugins.highlighter && this.plugins.highlighter.highlightCanvas) { + this.plugins.highlighter.highlightCanvas.resetCanvas(); + this.plugins.highlighter.highlightCanvas = null; + } + + if (this.plugins.highlighter && this.plugins.highlighter._tooltipElem) { + this.plugins.highlighter._tooltipElem.emptyForce(); + this.plugins.highlighter._tooltipElem = null; + } + + this.plugins.highlighter.highlightCanvas = new $.jqplot.GenericCanvas(); + + this.eventCanvas._elem.before(this.plugins.highlighter.highlightCanvas.createElement(this._gridPadding, 'jqplot-highlight-canvas', this._plotDimensions, this)); + this.plugins.highlighter.highlightCanvas.setContext(); + + var elem = document.createElement('div'); + this.plugins.highlighter._tooltipElem = $(elem); + elem = null; + this.plugins.highlighter._tooltipElem.addClass('jqplot-highlighter-tooltip'); + this.plugins.highlighter._tooltipElem.css({position:'absolute', display:'none'}); + + this.eventCanvas._elem.before(this.plugins.highlighter._tooltipElem); + }; + + $.jqplot.preInitHooks.push($.jqplot.Highlighter.init); + $.jqplot.preParseSeriesOptionsHooks.push($.jqplot.Highlighter.parseOptions); + $.jqplot.postDrawHooks.push($.jqplot.Highlighter.postPlotDraw); + + function draw(plot, neighbor) { + var hl = plot.plugins.highlighter; + var s = plot.series[neighbor.seriesIndex]; + var smr = s.markerRenderer; + var mr = hl.markerRenderer; + mr.style = smr.style; + mr.lineWidth = smr.lineWidth + hl.lineWidthAdjust; + mr.size = smr.size + hl.sizeAdjust; + var rgba = $.jqplot.getColorComponents(smr.color); + var newrgb = [rgba[0], rgba[1], rgba[2]]; + var alpha = (rgba[3] >= 0.6) ? rgba[3]*0.6 : rgba[3]*(2-rgba[3]); + mr.color = 'rgba('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+','+alpha+')'; + mr.init(); + mr.draw(s.gridData[neighbor.pointIndex][0], s.gridData[neighbor.pointIndex][1], hl.highlightCanvas._ctx); + } + + function showTooltip(plot, series, neighbor) { + // neighbor looks like: {seriesIndex: i, pointIndex:j, gridData:p, data:s.data[j]} + // gridData should be x,y pixel coords on the grid. + // add the plot._gridPadding to that to get x,y in the target. + var hl = plot.plugins.highlighter; + var elem = hl._tooltipElem; + var serieshl = series.highlighter || {}; + + var opts = $.extend(true, {}, hl, serieshl); + + if (opts.useAxesFormatters) { + var xf = series._xaxis._ticks[0].formatter; + var yf = series._yaxis._ticks[0].formatter; + var xfstr = series._xaxis._ticks[0].formatString; + var yfstr = series._yaxis._ticks[0].formatString; + var str; + var xstr = xf(xfstr, neighbor.data[0]); + var ystrs = []; + for (var i=1; i<opts.yvalues+1; i++) { + ystrs.push(yf(yfstr, neighbor.data[i])); + } + if (typeof opts.formatString === 'string') { + switch (opts.tooltipAxes) { + case 'both': + case 'xy': + ystrs.unshift(xstr); + ystrs.unshift(opts.formatString); + str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs); + break; + case 'yx': + ystrs.push(xstr); + ystrs.unshift(opts.formatString); + str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs); + break; + case 'x': + str = $.jqplot.sprintf.apply($.jqplot.sprintf, [opts.formatString, xstr]); + break; + case 'y': + ystrs.unshift(opts.formatString); + str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs); + break; + default: // same as xy + ystrs.unshift(xstr); + ystrs.unshift(opts.formatString); + str = $.jqplot.sprintf.apply($.jqplot.sprintf, ystrs); + break; + } + } + else { + switch (opts.tooltipAxes) { + case 'both': + case 'xy': + str = xstr; + for (var i=0; i<ystrs.length; i++) { + str += opts.tooltipSeparator + ystrs[i]; + } + break; + case 'yx': + str = ''; + for (var i=0; i<ystrs.length; i++) { + str += ystrs[i] + opts.tooltipSeparator; + } + str += xstr; + break; + case 'x': + str = xstr; + break; + case 'y': + str = ystrs.join(opts.tooltipSeparator); + break; + default: // same as 'xy' + str = xstr; + for (var i=0; i<ystrs.length; i++) { + str += opts.tooltipSeparator + ystrs[i]; + } + break; + + } + } + } + else { + var str; + if (typeof opts.formatString === 'string') { + str = $.jqplot.sprintf.apply($.jqplot.sprintf, [opts.formatString].concat(neighbor.data)); + } + + else { + if (opts.tooltipAxes == 'both' || opts.tooltipAxes == 'xy') { + str = $.jqplot.sprintf(opts.tooltipFormatString, neighbor.data[0]) + opts.tooltipSeparator + $.jqplot.sprintf(opts.tooltipFormatString, neighbor.data[1]); + } + else if (opts.tooltipAxes == 'yx') { + str = $.jqplot.sprintf(opts.tooltipFormatString, neighbor.data[1]) + opts.tooltipSeparator + $.jqplot.sprintf(opts.tooltipFormatString, neighbor.data[0]); + } + else if (opts.tooltipAxes == 'x') { + str = $.jqplot.sprintf(opts.tooltipFormatString, neighbor.data[0]); + } + else if (opts.tooltipAxes == 'y') { + str = $.jqplot.sprintf(opts.tooltipFormatString, neighbor.data[1]); + } + } + } + if ($.isFunction(opts.tooltipContentEditor)) { + // args str, seriesIndex, pointIndex are essential so the hook can look up + // extra data for the point. + str = opts.tooltipContentEditor(str, neighbor.seriesIndex, neighbor.pointIndex, plot); + } + elem.html(str); + var gridpos = {x:neighbor.gridData[0], y:neighbor.gridData[1]}; + var ms = 0; + var fact = 0.707; + if (series.markerRenderer.show == true) { + ms = (series.markerRenderer.size + opts.sizeAdjust)/2; + } + + var loc = locations; + if (series.fillToZero && series.fill && neighbor.data[1] < 0) { + loc = oppositeLocations; + } + + switch (loc[locationIndicies[opts.tooltipLocation]]) { + case 'nw': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset - fact * ms; + var y = gridpos.y + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true) - fact * ms; + break; + case 'n': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2; + var y = gridpos.y + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true) - ms; + break; + case 'ne': + var x = gridpos.x + plot._gridPadding.left + opts.tooltipOffset + fact * ms; + var y = gridpos.y + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true) - fact * ms; + break; + case 'e': + var x = gridpos.x + plot._gridPadding.left + opts.tooltipOffset + ms; + var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2; + break; + case 'se': + var x = gridpos.x + plot._gridPadding.left + opts.tooltipOffset + fact * ms; + var y = gridpos.y + plot._gridPadding.top + opts.tooltipOffset + fact * ms; + break; + case 's': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true)/2; + var y = gridpos.y + plot._gridPadding.top + opts.tooltipOffset + ms; + break; + case 'sw': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset - fact * ms; + var y = gridpos.y + plot._gridPadding.top + opts.tooltipOffset + fact * ms; + break; + case 'w': + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset - ms; + var y = gridpos.y + plot._gridPadding.top - elem.outerHeight(true)/2; + break; + default: // same as 'nw' + var x = gridpos.x + plot._gridPadding.left - elem.outerWidth(true) - opts.tooltipOffset - fact * ms; + var y = gridpos.y + plot._gridPadding.top - opts.tooltipOffset - elem.outerHeight(true) - fact * ms; + break; + } + elem.css('left', x); + elem.css('top', y); + if (opts.fadeTooltip) { + // Fix for stacked up animations. Thnanks Trevor! + elem.stop(true,true).fadeIn(opts.tooltipFadeSpeed); + } + else { + elem.show(); + } + elem = null; + + } + + function handleMove(ev, gridpos, datapos, neighbor, plot) { + var hl = plot.plugins.highlighter; + var c = plot.plugins.cursor; + if (hl.show) { + if (neighbor == null && hl.isHighlighting) { + var evt = jQuery.Event('jqplotHighlighterUnhighlight'); + plot.target.trigger(evt); + + var ctx = hl.highlightCanvas._ctx; + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + if (hl.fadeTooltip) { + hl._tooltipElem.fadeOut(hl.tooltipFadeSpeed); + } + else { + hl._tooltipElem.hide(); + } + if (hl.bringSeriesToFront) { + plot.restorePreviousSeriesOrder(); + } + hl.isHighlighting = false; + hl.currentNeighbor = null; + ctx = null; + } + else if (neighbor != null && plot.series[neighbor.seriesIndex].showHighlight && !hl.isHighlighting) { + var evt = jQuery.Event('jqplotHighlighterHighlight'); + evt.which = ev.which; + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data, plot]; + plot.target.trigger(evt, ins); + + hl.isHighlighting = true; + hl.currentNeighbor = neighbor; + if (hl.showMarker) { + draw(plot, neighbor); + } + if (hl.showTooltip && (!c || !c._zoom.started)) { + showTooltip(plot, plot.series[neighbor.seriesIndex], neighbor); + } + if (hl.bringSeriesToFront) { + plot.moveSeriesToFront(neighbor.seriesIndex); + } + } + // check to see if we're highlighting the wrong point. + else if (neighbor != null && hl.isHighlighting && hl.currentNeighbor != neighbor) { + // highlighting the wrong point. + + // if new series allows highlighting, highlight new point. + if (plot.series[neighbor.seriesIndex].showHighlight) { + var ctx = hl.highlightCanvas._ctx; + ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); + hl.isHighlighting = true; + hl.currentNeighbor = neighbor; + if (hl.showMarker) { + draw(plot, neighbor); + } + if (hl.showTooltip && (!c || !c._zoom.started)) { + showTooltip(plot, plot.series[neighbor.seriesIndex], neighbor); + } + if (hl.bringSeriesToFront) { + plot.moveSeriesToFront(neighbor.seriesIndex); + } + } + } + } + } +})(jQuery);
\ No newline at end of file diff --git a/hugo/js/jqplot/plugins/jqplot.pieRenderer.js b/hugo/js/jqplot/plugins/jqplot.pieRenderer.js new file mode 100644 index 0000000..2479885 --- /dev/null +++ b/hugo/js/jqplot/plugins/jqplot.pieRenderer.js @@ -0,0 +1,904 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.4 + * Revision: 1121 + * + * Copyright (c) 2009-2012 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + /** + * Class: $.jqplot.PieRenderer + * Plugin renderer to draw a pie chart. + * x values, if present, will be used as slice labels. + * y values give slice size. + * + * To use this renderer, you need to include the + * pie renderer plugin, for example: + * + * > <script type="text/javascript" src="plugins/jqplot.pieRenderer.js"></script> + * + * Properties described here are passed into the $.jqplot function + * as options on the series renderer. For example: + * + * > plot2 = $.jqplot('chart2', [s1, s2], { + * > seriesDefaults: { + * > renderer:$.jqplot.PieRenderer, + * > rendererOptions:{ + * > sliceMargin: 2, + * > startAngle: -90 + * > } + * > } + * > }); + * + * A pie plot will trigger events on the plot target + * according to user interaction. All events return the event object, + * the series index, the point (slice) index, and the point data for + * the appropriate slice. + * + * 'jqplotDataMouseOver' - triggered when user mouseing over a slice. + * 'jqplotDataHighlight' - triggered the first time user mouses over a slice, + * if highlighting is enabled. + * 'jqplotDataUnhighlight' - triggered when a user moves the mouse out of + * a highlighted slice. + * 'jqplotDataClick' - triggered when the user clicks on a slice. + * 'jqplotDataRightClick' - tiggered when the user right clicks on a slice if + * the "captureRightClick" option is set to true on the plot. + */ + $.jqplot.PieRenderer = function(){ + $.jqplot.LineRenderer.call(this); + }; + + $.jqplot.PieRenderer.prototype = new $.jqplot.LineRenderer(); + $.jqplot.PieRenderer.prototype.constructor = $.jqplot.PieRenderer; + + // called with scope of a series + $.jqplot.PieRenderer.prototype.init = function(options, plot) { + // Group: Properties + // + // prop: diameter + // Outer diameter of the pie, auto computed by default + this.diameter = null; + // prop: padding + // padding between the pie and plot edges, legend, etc. + this.padding = 20; + // prop: sliceMargin + // angular spacing between pie slices in degrees. + this.sliceMargin = 0; + // prop: fill + // true or false, wether to fil the slices. + this.fill = true; + // prop: shadowOffset + // offset of the shadow from the slice and offset of + // each succesive stroke of the shadow from the last. + this.shadowOffset = 2; + // prop: shadowAlpha + // transparency of the shadow (0 = transparent, 1 = opaque) + this.shadowAlpha = 0.07; + // prop: shadowDepth + // number of strokes to apply to the shadow, + // each stroke offset shadowOffset from the last. + this.shadowDepth = 5; + // prop: highlightMouseOver + // True to highlight slice when moused over. + // This must be false to enable highlightMouseDown to highlight when clicking on a slice. + this.highlightMouseOver = true; + // prop: highlightMouseDown + // True to highlight when a mouse button is pressed over a slice. + // This will be disabled if highlightMouseOver is true. + this.highlightMouseDown = false; + // prop: highlightColors + // an array of colors to use when highlighting a slice. + this.highlightColors = []; + // prop: dataLabels + // Either 'label', 'value', 'percent' or an array of labels to place on the pie slices. + // Defaults to percentage of each pie slice. + this.dataLabels = 'percent'; + // prop: showDataLabels + // true to show data labels on slices. + this.showDataLabels = false; + // prop: dataLabelFormatString + // Format string for data labels. If none, '%s' is used for "label" and for arrays, '%d' for value and '%d%%' for percentage. + this.dataLabelFormatString = null; + // prop: dataLabelThreshold + // Threshhold in percentage (0-100) of pie area, below which no label will be displayed. + // This applies to all label types, not just to percentage labels. + this.dataLabelThreshold = 3; + // prop: dataLabelPositionFactor + // A Multiplier (0-1) of the pie radius which controls position of label on slice. + // Increasing will slide label toward edge of pie, decreasing will slide label toward center of pie. + this.dataLabelPositionFactor = 0.52; + // prop: dataLabelNudge + // Number of pixels to slide the label away from (+) or toward (-) the center of the pie. + this.dataLabelNudge = 2; + // prop: dataLabelCenterOn + // True to center the data label at its position. + // False to set the inside facing edge of the label at its position. + this.dataLabelCenterOn = true; + // prop: startAngle + // Angle to start drawing pie in degrees. + // According to orientation of canvas coordinate system: + // 0 = on the positive x axis + // -90 = on the positive y axis. + // 90 = on the negaive y axis. + // 180 or - 180 = on the negative x axis. + this.startAngle = 0; + this.tickRenderer = $.jqplot.PieTickRenderer; + // Used as check for conditions where pie shouldn't be drawn. + this._drawData = true; + this._type = 'pie'; + + // if user has passed in highlightMouseDown option and not set highlightMouseOver, disable highlightMouseOver + if (options.highlightMouseDown && options.highlightMouseOver == null) { + options.highlightMouseOver = false; + } + + $.extend(true, this, options); + + if (this.sliceMargin < 0) { + this.sliceMargin = 0; + } + + this._diameter = null; + this._radius = null; + // array of [start,end] angles arrays, one for each slice. In radians. + this._sliceAngles = []; + // index of the currenty highlighted point, if any + this._highlightedPoint = null; + + // set highlight colors if none provided + if (this.highlightColors.length == 0) { + for (var i=0; i<this.seriesColors.length; i++){ + var rgba = $.jqplot.getColorComponents(this.seriesColors[i]); + var newrgb = [rgba[0], rgba[1], rgba[2]]; + var sum = newrgb[0] + newrgb[1] + newrgb[2]; + for (var j=0; j<3; j++) { + // when darkening, lowest color component can be is 60. + newrgb[j] = (sum > 570) ? newrgb[j] * 0.8 : newrgb[j] + 0.3 * (255 - newrgb[j]); + newrgb[j] = parseInt(newrgb[j], 10); + } + this.highlightColors.push('rgb('+newrgb[0]+','+newrgb[1]+','+newrgb[2]+')'); + } + } + + this.highlightColorGenerator = new $.jqplot.ColorGenerator(this.highlightColors); + + plot.postParseOptionsHooks.addOnce(postParseOptions); + plot.postInitHooks.addOnce(postInit); + plot.eventListenerHooks.addOnce('jqplotMouseMove', handleMove); + plot.eventListenerHooks.addOnce('jqplotMouseDown', handleMouseDown); + plot.eventListenerHooks.addOnce('jqplotMouseUp', handleMouseUp); + plot.eventListenerHooks.addOnce('jqplotClick', handleClick); + plot.eventListenerHooks.addOnce('jqplotRightClick', handleRightClick); + plot.postDrawHooks.addOnce(postPlotDraw); + }; + + $.jqplot.PieRenderer.prototype.setGridData = function(plot) { + // set gridData property. This will hold angle in radians of each data point. + var stack = []; + var td = []; + var sa = this.startAngle/180*Math.PI; + var tot = 0; + // don't know if we have any valid data yet, so set plot to not draw. + this._drawData = false; + for (var i=0; i<this.data.length; i++){ + if (this.data[i][1] != 0) { + // we have data, O.K. to draw. + this._drawData = true; + } + stack.push(this.data[i][1]); + td.push([this.data[i][0]]); + if (i>0) { + stack[i] += stack[i-1]; + } + tot += this.data[i][1]; + } + var fact = Math.PI*2/stack[stack.length - 1]; + + for (var i=0; i<stack.length; i++) { + td[i][1] = stack[i] * fact; + td[i][2] = this.data[i][1]/tot; + } + this.gridData = td; + }; + + $.jqplot.PieRenderer.prototype.makeGridData = function(data, plot) { + var stack = []; + var td = []; + var tot = 0; + var sa = this.startAngle/180*Math.PI; + // don't know if we have any valid data yet, so set plot to not draw. + this._drawData = false; + for (var i=0; i<data.length; i++){ + if (this.data[i][1] != 0) { + // we have data, O.K. to draw. + this._drawData = true; + } + stack.push(data[i][1]); + td.push([data[i][0]]); + if (i>0) { + stack[i] += stack[i-1]; + } + tot += data[i][1]; + } + var fact = Math.PI*2/stack[stack.length - 1]; + + for (var i=0; i<stack.length; i++) { + td[i][1] = stack[i] * fact; + td[i][2] = data[i][1]/tot; + } + return td; + }; + + function calcRadiusAdjustment(ang) { + return Math.sin((ang - (ang-Math.PI) / 8 / Math.PI )/2.0); + } + + function calcRPrime(ang1, ang2, sliceMargin, fill, lineWidth) { + var rprime = 0; + var ang = ang2 - ang1; + var absang = Math.abs(ang); + var sm = sliceMargin; + if (fill == false) { + sm += lineWidth; + } + + if (sm > 0 && absang > 0.01 && absang < 6.282) { + rprime = parseFloat(sm) / 2.0 / calcRadiusAdjustment(ang); + } + + return rprime; + } + + $.jqplot.PieRenderer.prototype.drawSlice = function (ctx, ang1, ang2, color, isShadow) { + if (this._drawData) { + var r = this._radius; + var fill = this.fill; + var lineWidth = this.lineWidth; + var sm = this.sliceMargin; + if (this.fill == false) { + sm += this.lineWidth; + } + ctx.save(); + ctx.translate(this._center[0], this._center[1]); + + var rprime = calcRPrime(ang1, ang2, this.sliceMargin, this.fill, this.lineWidth); + + var transx = rprime * Math.cos((ang1 + ang2) / 2.0); + var transy = rprime * Math.sin((ang1 + ang2) / 2.0); + + if ((ang2 - ang1) <= Math.PI) { + r -= rprime; + } + else { + r += rprime; + } + + ctx.translate(transx, transy); + + if (isShadow) { + for (var i=0, l=this.shadowDepth; i<l; i++) { + ctx.save(); + ctx.translate(this.shadowOffset*Math.cos(this.shadowAngle/180*Math.PI), this.shadowOffset*Math.sin(this.shadowAngle/180*Math.PI)); + doDraw(r); + } + for (var i=0, l=this.shadowDepth; i<l; i++) { + ctx.restore(); + } + } + + else { + doDraw(r); + } + ctx.restore(); + } + + function doDraw (rad) { + // Fix for IE and Chrome that can't seem to draw circles correctly. + // ang2 should always be <= 2 pi since that is the way the data is converted. + // 2Pi = 6.2831853, Pi = 3.1415927 + if (ang2 > 6.282 + this.startAngle) { + ang2 = 6.282 + this.startAngle; + if (ang1 > ang2) { + ang1 = 6.281 + this.startAngle; + } + } + // Fix for IE, where it can't seem to handle 0 degree angles. Also avoids + // ugly line on unfilled pies. + if (ang1 >= ang2) { + return; + } + + ctx.beginPath(); + ctx.fillStyle = color; + ctx.strokeStyle = color; + ctx.lineWidth = lineWidth; + ctx.arc(0, 0, rad, ang1, ang2, false); + ctx.lineTo(0,0); + ctx.closePath(); + + if (fill) { + ctx.fill(); + } + else { + ctx.stroke(); + } + } + }; + + // called with scope of series + $.jqplot.PieRenderer.prototype.draw = function (ctx, gd, options, plot) { + var i; + var opts = (options != undefined) ? options : {}; + // offset and direction of offset due to legend placement + var offx = 0; + var offy = 0; + var trans = 1; + var colorGenerator = new $.jqplot.ColorGenerator(this.seriesColors); + if (options.legendInfo && options.legendInfo.placement == 'insideGrid') { + var li = options.legendInfo; + switch (li.location) { + case 'nw': + offx = li.width + li.xoffset; + break; + case 'w': + offx = li.width + li.xoffset; + break; + case 'sw': + offx = li.width + li.xoffset; + break; + case 'ne': + offx = li.width + li.xoffset; + trans = -1; + break; + case 'e': + offx = li.width + li.xoffset; + trans = -1; + break; + case 'se': + offx = li.width + li.xoffset; + trans = -1; + break; + case 'n': + offy = li.height + li.yoffset; + break; + case 's': + offy = li.height + li.yoffset; + trans = -1; + break; + default: + break; + } + } + + var shadow = (opts.shadow != undefined) ? opts.shadow : this.shadow; + var fill = (opts.fill != undefined) ? opts.fill : this.fill; + var cw = ctx.canvas.width; + var ch = ctx.canvas.height; + var w = cw - offx - 2 * this.padding; + var h = ch - offy - 2 * this.padding; + var mindim = Math.min(w,h); + var d = mindim; + + // Fixes issue #272. Thanks hugwijst! + // reset slice angles array. + this._sliceAngles = []; + + var sm = this.sliceMargin; + if (this.fill == false) { + sm += this.lineWidth; + } + + var rprime; + var maxrprime = 0; + + var ang, ang1, ang2, shadowColor; + var sa = this.startAngle / 180 * Math.PI; + + // have to pre-draw shadows, so loop throgh here and calculate some values also. + for (var i=0, l=gd.length; i<l; i++) { + ang1 = (i == 0) ? sa : gd[i-1][1] + sa; + ang2 = gd[i][1] + sa; + + this._sliceAngles.push([ang1, ang2]); + + rprime = calcRPrime(ang1, ang2, this.sliceMargin, this.fill, this.lineWidth); + + if (Math.abs(ang2-ang1) > Math.PI) { + maxrprime = Math.max(rprime, maxrprime); + } + } + + if (this.diameter != null && this.diameter > 0) { + this._diameter = this.diameter - 2*maxrprime; + } + else { + this._diameter = d - 2*maxrprime; + } + + // Need to check for undersized pie. This can happen if + // plot area too small and legend is too big. + if (this._diameter < 6) { + $.jqplot.log('Diameter of pie too small, not rendering.'); + return; + } + + var r = this._radius = this._diameter/2; + + this._center = [(cw - trans * offx)/2 + trans * offx + maxrprime * Math.cos(sa), (ch - trans*offy)/2 + trans * offy + maxrprime * Math.sin(sa)]; + + if (this.shadow) { + for (var i=0, l=gd.length; i<l; i++) { + shadowColor = 'rgba(0,0,0,'+this.shadowAlpha+')'; + this.renderer.drawSlice.call (this, ctx, this._sliceAngles[i][0], this._sliceAngles[i][1], shadowColor, true); + } + } + + for (var i=0; i<gd.length; i++) { + + this.renderer.drawSlice.call (this, ctx, this._sliceAngles[i][0], this._sliceAngles[i][1], colorGenerator.next(), false); + + if (this.showDataLabels && gd[i][2]*100 >= this.dataLabelThreshold) { + var fstr, avgang = (this._sliceAngles[i][0] + this._sliceAngles[i][1])/2, label; + + if (this.dataLabels == 'label') { + fstr = this.dataLabelFormatString || '%s'; + label = $.jqplot.sprintf(fstr, gd[i][0]); + } + else if (this.dataLabels == 'value') { + fstr = this.dataLabelFormatString || '%d'; + label = $.jqplot.sprintf(fstr, this.data[i][1]); + } + else if (this.dataLabels == 'percent') { + fstr = this.dataLabelFormatString || '%d%%'; + label = $.jqplot.sprintf(fstr, gd[i][2]*100); + } + else if (this.dataLabels.constructor == Array) { + fstr = this.dataLabelFormatString || '%s'; + label = $.jqplot.sprintf(fstr, this.dataLabels[i]); + } + + var fact = (this._radius ) * this.dataLabelPositionFactor + this.sliceMargin + this.dataLabelNudge; + + var x = this._center[0] + Math.cos(avgang) * fact + this.canvas._offsets.left; + var y = this._center[1] + Math.sin(avgang) * fact + this.canvas._offsets.top; + + var labelelem = $('<div class="jqplot-pie-series jqplot-data-label" style="position:absolute;">' + label + '</div>').insertBefore(plot.eventCanvas._elem); + if (this.dataLabelCenterOn) { + x -= labelelem.width()/2; + y -= labelelem.height()/2; + } + else { + x -= labelelem.width() * Math.sin(avgang/2); + y -= labelelem.height()/2; + } + x = Math.round(x); + y = Math.round(y); + labelelem.css({left: x, top: y}); + } + } + }; + + $.jqplot.PieAxisRenderer = function() { + $.jqplot.LinearAxisRenderer.call(this); + }; + + $.jqplot.PieAxisRenderer.prototype = new $.jqplot.LinearAxisRenderer(); + $.jqplot.PieAxisRenderer.prototype.constructor = $.jqplot.PieAxisRenderer; + + + // There are no traditional axes on a pie chart. We just need to provide + // dummy objects with properties so the plot will render. + // called with scope of axis object. + $.jqplot.PieAxisRenderer.prototype.init = function(options){ + // + this.tickRenderer = $.jqplot.PieTickRenderer; + $.extend(true, this, options); + // I don't think I'm going to need _dataBounds here. + // have to go Axis scaling in a way to fit chart onto plot area + // and provide u2p and p2u functionality for mouse cursor, etc. + // for convienence set _dataBounds to 0 and 100 and + // set min/max to 0 and 100. + this._dataBounds = {min:0, max:100}; + this.min = 0; + this.max = 100; + this.showTicks = false; + this.ticks = []; + this.showMark = false; + this.show = false; + }; + + + + + $.jqplot.PieLegendRenderer = function(){ + $.jqplot.TableLegendRenderer.call(this); + }; + + $.jqplot.PieLegendRenderer.prototype = new $.jqplot.TableLegendRenderer(); + $.jqplot.PieLegendRenderer.prototype.constructor = $.jqplot.PieLegendRenderer; + + /** + * Class: $.jqplot.PieLegendRenderer + * Legend Renderer specific to pie plots. Set by default + * when user creates a pie plot. + */ + $.jqplot.PieLegendRenderer.prototype.init = function(options) { + // Group: Properties + // + // prop: numberRows + // Maximum number of rows in the legend. 0 or null for unlimited. + this.numberRows = null; + // prop: numberColumns + // Maximum number of columns in the legend. 0 or null for unlimited. + this.numberColumns = null; + $.extend(true, this, options); + }; + + // called with context of legend + $.jqplot.PieLegendRenderer.prototype.draw = function() { + var legend = this; + if (this.show) { + var series = this._series; + + + this._elem = $(document.createElement('table')); + this._elem.addClass('jqplot-table-legend'); + + var ss = {position:'absolute'}; + if (this.background) { + ss['background'] = this.background; + } + if (this.border) { + ss['border'] = this.border; + } + if (this.fontSize) { + ss['fontSize'] = this.fontSize; + } + if (this.fontFamily) { + ss['fontFamily'] = this.fontFamily; + } + if (this.textColor) { + ss['textColor'] = this.textColor; + } + if (this.marginTop != null) { + ss['marginTop'] = this.marginTop; + } + if (this.marginBottom != null) { + ss['marginBottom'] = this.marginBottom; + } + if (this.marginLeft != null) { + ss['marginLeft'] = this.marginLeft; + } + if (this.marginRight != null) { + ss['marginRight'] = this.marginRight; + } + + this._elem.css(ss); + + // Pie charts legends don't go by number of series, but by number of data points + // in the series. Refactor things here for that. + + var pad = false, + reverse = false, + nr, + nc; + var s = series[0]; + var colorGenerator = new $.jqplot.ColorGenerator(s.seriesColors); + + if (s.show) { + var pd = s.data; + if (this.numberRows) { + nr = this.numberRows; + if (!this.numberColumns){ + nc = Math.ceil(pd.length/nr); + } + else{ + nc = this.numberColumns; + } + } + else if (this.numberColumns) { + nc = this.numberColumns; + nr = Math.ceil(pd.length/this.numberColumns); + } + else { + nr = pd.length; + nc = 1; + } + + var i, j; + var tr, td1, td2; + var lt, rs, color; + var idx = 0; + var div0, div1; + + for (i=0; i<nr; i++) { + tr = $(document.createElement('tr')); + tr.addClass('jqplot-table-legend'); + + if (reverse){ + tr.prependTo(this._elem); + } + + else{ + tr.appendTo(this._elem); + } + + for (j=0; j<nc; j++) { + if (idx < pd.length){ + lt = this.labels[idx] || pd[idx][0].toString(); + color = colorGenerator.next(); + if (!reverse){ + if (i>0){ + pad = true; + } + else{ + pad = false; + } + } + else{ + if (i == nr -1){ + pad = false; + } + else{ + pad = true; + } + } + rs = (pad) ? this.rowSpacing : '0'; + + + + td1 = $(document.createElement('td')); + td1.addClass('jqplot-table-legend jqplot-table-legend-swatch'); + td1.css({textAlign: 'center', paddingTop: rs}); + + div0 = $(document.createElement('div')); + div0.addClass('jqplot-table-legend-swatch-outline'); + div1 = $(document.createElement('div')); + div1.addClass('jqplot-table-legend-swatch'); + div1.css({backgroundColor: color, borderColor: color}); + td1.append(div0.append(div1)); + + td2 = $(document.createElement('td')); + td2.addClass('jqplot-table-legend jqplot-table-legend-label'); + td2.css('paddingTop', rs); + + if (this.escapeHtml){ + td2.text(lt); + } + else { + td2.html(lt); + } + if (reverse) { + td2.prependTo(tr); + td1.prependTo(tr); + } + else { + td1.appendTo(tr); + td2.appendTo(tr); + } + pad = true; + } + idx++; + } + } + } + } + return this._elem; + }; + + $.jqplot.PieRenderer.prototype.handleMove = function(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + plot.target.trigger('jqplotDataMouseOver', ins); + if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) { + plot.target.trigger('jqplotDataHighlight', ins); + highlight (plot, ins[0], ins[1]); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + }; + + + // this.eventCanvas._elem.bind($.jqplot.eventListenerHooks[i][0], {plot:this}, $.jqplot.eventListenerHooks[i][1]); + + // setup default renderers for axes and legend so user doesn't have to + // called with scope of plot + function preInit(target, data, options) { + options = options || {}; + options.axesDefaults = options.axesDefaults || {}; + options.legend = options.legend || {}; + options.seriesDefaults = options.seriesDefaults || {}; + // only set these if there is a pie series + var setopts = false; + if (options.seriesDefaults.renderer == $.jqplot.PieRenderer) { + setopts = true; + } + else if (options.series) { + for (var i=0; i < options.series.length; i++) { + if (options.series[i].renderer == $.jqplot.PieRenderer) { + setopts = true; + } + } + } + + if (setopts) { + options.axesDefaults.renderer = $.jqplot.PieAxisRenderer; + options.legend.renderer = $.jqplot.PieLegendRenderer; + options.legend.preDraw = true; + options.seriesDefaults.pointLabels = {show: false}; + } + } + + function postInit(target, data, options) { + for (var i=0; i<this.series.length; i++) { + if (this.series[i].renderer.constructor == $.jqplot.PieRenderer) { + // don't allow mouseover and mousedown at same time. + if (this.series[i].highlightMouseOver) { + this.series[i].highlightMouseDown = false; + } + } + } + } + + // called with scope of plot + function postParseOptions(options) { + for (var i=0; i<this.series.length; i++) { + this.series[i].seriesColors = this.seriesColors; + this.series[i].colorGenerator = $.jqplot.colorGenerator; + } + } + + function highlight (plot, sidx, pidx) { + var s = plot.series[sidx]; + var canvas = plot.plugins.pieRenderer.highlightCanvas; + canvas._ctx.clearRect(0,0,canvas._ctx.canvas.width, canvas._ctx.canvas.height); + s._highlightedPoint = pidx; + plot.plugins.pieRenderer.highlightedSeriesIndex = sidx; + s.renderer.drawSlice.call(s, canvas._ctx, s._sliceAngles[pidx][0], s._sliceAngles[pidx][1], s.highlightColorGenerator.get(pidx), false); + } + + function unhighlight (plot) { + var canvas = plot.plugins.pieRenderer.highlightCanvas; + canvas._ctx.clearRect(0,0, canvas._ctx.canvas.width, canvas._ctx.canvas.height); + for (var i=0; i<plot.series.length; i++) { + plot.series[i]._highlightedPoint = null; + } + plot.plugins.pieRenderer.highlightedSeriesIndex = null; + plot.target.trigger('jqplotDataUnhighlight'); + } + + function handleMove(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var evt1 = jQuery.Event('jqplotDataMouseOver'); + evt1.pageX = ev.pageX; + evt1.pageY = ev.pageY; + plot.target.trigger(evt1, ins); + if (plot.series[ins[0]].highlightMouseOver && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) { + var evt = jQuery.Event('jqplotDataHighlight'); + evt.which = ev.which; + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + highlight (plot, ins[0], ins[1]); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + } + + function handleMouseDown(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + if (plot.series[ins[0]].highlightMouseDown && !(ins[0] == plot.plugins.pieRenderer.highlightedSeriesIndex && ins[1] == plot.series[ins[0]]._highlightedPoint)) { + var evt = jQuery.Event('jqplotDataHighlight'); + evt.which = ev.which; + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + highlight (plot, ins[0], ins[1]); + } + } + else if (neighbor == null) { + unhighlight (plot); + } + } + + function handleMouseUp(ev, gridpos, datapos, neighbor, plot) { + var idx = plot.plugins.pieRenderer.highlightedSeriesIndex; + if (idx != null && plot.series[idx].highlightMouseDown) { + unhighlight(plot); + } + } + + function handleClick(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var evt = jQuery.Event('jqplotDataClick'); + evt.which = ev.which; + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + } + } + + function handleRightClick(ev, gridpos, datapos, neighbor, plot) { + if (neighbor) { + var ins = [neighbor.seriesIndex, neighbor.pointIndex, neighbor.data]; + var idx = plot.plugins.pieRenderer.highlightedSeriesIndex; + if (idx != null && plot.series[idx].highlightMouseDown) { + unhighlight(plot); + } + var evt = jQuery.Event('jqplotDataRightClick'); + evt.which = ev.which; + evt.pageX = ev.pageX; + evt.pageY = ev.pageY; + plot.target.trigger(evt, ins); + } + } + + // called within context of plot + // create a canvas which we can draw on. + // insert it before the eventCanvas, so eventCanvas will still capture events. + function postPlotDraw() { + // Memory Leaks patch + if (this.plugins.pieRenderer && this.plugins.pieRenderer.highlightCanvas) { + this.plugins.pieRenderer.highlightCanvas.resetCanvas(); + this.plugins.pieRenderer.highlightCanvas = null; + } + + this.plugins.pieRenderer = {highlightedSeriesIndex:null}; + this.plugins.pieRenderer.highlightCanvas = new $.jqplot.GenericCanvas(); + + // do we have any data labels? if so, put highlight canvas before those + var labels = $(this.targetId+' .jqplot-data-label'); + if (labels.length) { + $(labels[0]).before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-pieRenderer-highlight-canvas', this._plotDimensions, this)); + } + // else put highlight canvas before event canvas. + else { + this.eventCanvas._elem.before(this.plugins.pieRenderer.highlightCanvas.createElement(this._gridPadding, 'jqplot-pieRenderer-highlight-canvas', this._plotDimensions, this)); + } + + var hctx = this.plugins.pieRenderer.highlightCanvas.setContext(); + this.eventCanvas._elem.bind('mouseleave', {plot:this}, function (ev) { unhighlight(ev.data.plot); }); + } + + $.jqplot.preInitHooks.push(preInit); + + $.jqplot.PieTickRenderer = function() { + $.jqplot.AxisTickRenderer.call(this); + }; + + $.jqplot.PieTickRenderer.prototype = new $.jqplot.AxisTickRenderer(); + $.jqplot.PieTickRenderer.prototype.constructor = $.jqplot.PieTickRenderer; + +})(jQuery); + +
\ No newline at end of file diff --git a/hugo/js/jqplot/plugins/jqplot.pointLabels.js b/hugo/js/jqplot/plugins/jqplot.pointLabels.js new file mode 100644 index 0000000..c20a9c4 --- /dev/null +++ b/hugo/js/jqplot/plugins/jqplot.pointLabels.js @@ -0,0 +1,379 @@ +/** + * jqPlot + * Pure JavaScript plotting plugin using jQuery + * + * Version: 1.0.4 + * Revision: 1121 + * + * Copyright (c) 2009-2012 Chris Leonello + * jqPlot is currently available for use in all personal or commercial projects + * under both the MIT (http://www.opensource.org/licenses/mit-license.php) and GPL + * version 2.0 (http://www.gnu.org/licenses/gpl-2.0.html) licenses. This means that you can + * choose the license that best suits your project and use it accordingly. + * + * Although not required, the author would appreciate an email letting him + * know of any substantial use of jqPlot. You can reach the author at: + * chris at jqplot dot com or see http://www.jqplot.com/info.php . + * + * If you are feeling kind and generous, consider supporting the project by + * making a donation at: http://www.jqplot.com/donate.php . + * + * sprintf functions contained in jqplot.sprintf.js by Ash Searle: + * + * version 2007.04.27 + * author Ash Searle + * http://hexmen.com/blog/2007/03/printf-sprintf/ + * http://hexmen.com/js/sprintf.js + * The author (Ash Searle) has placed this code in the public domain: + * "This code is unrestricted: you are free to use it however you like." + * + */ +(function($) { + + /** + * Class: $.jqplot.PointLabels + * Plugin for putting labels at the data points. + * + * To use this plugin, include the js + * file in your source: + * + * > <script type="text/javascript" src="plugins/jqplot.pointLabels.js"></script> + * + * By default, the last value in the data ponit array in the data series is used + * for the label. For most series renderers, extra data can be added to the + * data point arrays and the last value will be used as the label. + * + * For instance, + * this series: + * + * > [[1,4], [3,5], [7,2]] + * + * Would, by default, use the y values in the labels. + * Extra data can be added to the series like so: + * + * > [[1,4,'mid'], [3 5,'hi'], [7,2,'low']] + * + * And now the point labels would be 'mid', 'low', and 'hi'. + * + * Options to the point labels and a custom labels array can be passed into the + * "pointLabels" option on the series option like so: + * + * > series:[{pointLabels:{ + * > labels:['mid', 'hi', 'low'], + * > location:'se', + * > ypadding: 12 + * > } + * > }] + * + * A custom labels array in the options takes precendence over any labels + * in the series data. If you have a custom labels array in the options, + * but still want to use values from the series array as labels, set the + * "labelsFromSeries" option to true. + * + * By default, html entities (<, >, etc.) are escaped in point labels. + * If you want to include actual html markup in the labels, + * set the "escapeHTML" option to false. + * + */ + $.jqplot.PointLabels = function(options) { + // Group: Properties + // + // prop: show + // show the labels or not. + this.show = $.jqplot.config.enablePlugins; + // prop: location + // compass location where to position the label around the point. + // 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw' + this.location = 'n'; + // prop: labelsFromSeries + // true to use labels within data point arrays. + this.labelsFromSeries = false; + // prop: seriesLabelIndex + // array index for location of labels within data point arrays. + // if null, will use the last element of the data point array. + this.seriesLabelIndex = null; + // prop: labels + // array of arrays of labels, one array for each series. + this.labels = []; + // actual labels that will get displayed. + // needed to preserve user specified labels in labels array. + this._labels = []; + // prop: stackedValue + // true to display value as stacked in a stacked plot. + // no effect if labels is specified. + this.stackedValue = false; + // prop: ypadding + // vertical padding in pixels between point and label + this.ypadding = 6; + // prop: xpadding + // horizontal padding in pixels between point and label + this.xpadding = 6; + // prop: escapeHTML + // true to escape html entities in the labels. + // If you want to include markup in the labels, set to false. + this.escapeHTML = true; + // prop: edgeTolerance + // Number of pixels that the label must be away from an axis + // boundary in order to be drawn. Negative values will allow overlap + // with the grid boundaries. + this.edgeTolerance = -5; + // prop: formatter + // A class of a formatter for the tick text. sprintf by default. + this.formatter = $.jqplot.DefaultTickFormatter; + // prop: formatString + // string passed to the formatter. + this.formatString = ''; + // prop: hideZeros + // true to not show a label for a value which is 0. + this.hideZeros = false; + this._elems = []; + + $.extend(true, this, options); + }; + + var locations = ['nw', 'n', 'ne', 'e', 'se', 's', 'sw', 'w']; + var locationIndicies = {'nw':0, 'n':1, 'ne':2, 'e':3, 'se':4, 's':5, 'sw':6, 'w':7}; + var oppositeLocations = ['se', 's', 'sw', 'w', 'nw', 'n', 'ne', 'e']; + + // called with scope of a series + $.jqplot.PointLabels.init = function (target, data, seriesDefaults, opts, plot){ + var options = $.extend(true, {}, seriesDefaults, opts); + options.pointLabels = options.pointLabels || {}; + if (this.renderer.constructor === $.jqplot.BarRenderer && this.barDirection === 'horizontal' && !options.pointLabels.location) { + options.pointLabels.location = 'e'; + } + // add a pointLabels attribute to the series plugins + this.plugins.pointLabels = new $.jqplot.PointLabels(options.pointLabels); + this.plugins.pointLabels.setLabels.call(this); + }; + + // called with scope of series + $.jqplot.PointLabels.prototype.setLabels = function() { + var p = this.plugins.pointLabels; + var labelIdx; + if (p.seriesLabelIndex != null) { + labelIdx = p.seriesLabelIndex; + } + else if (this.renderer.constructor === $.jqplot.BarRenderer && this.barDirection === 'horizontal') { + labelIdx = 0; + } + else { + labelIdx = (this._plotData.length === 0) ? 0 : this._plotData[0].length -1; + } + p._labels = []; + if (p.labels.length === 0 || p.labelsFromSeries) { + if (p.stackedValue) { + if (this._plotData.length && this._plotData[0].length){ + // var idx = p.seriesLabelIndex || this._plotData[0].length -1; + for (var i=0; i<this._plotData.length; i++) { + p._labels.push(this._plotData[i][labelIdx]); + } + } + } + else { + // var d = this._plotData; + var d = this.data; + if (this.renderer.constructor === $.jqplot.BarRenderer && this.waterfall) { + d = this._data; + } + if (d.length && d[0].length) { + // var idx = p.seriesLabelIndex || d[0].length -1; + for (var i=0; i<d.length; i++) { + p._labels.push(d[i][labelIdx]); + } + } + d = null; + } + } + else if (p.labels.length){ + p._labels = p.labels; + } + }; + + $.jqplot.PointLabels.prototype.xOffset = function(elem, location, padding) { + location = location || this.location; + padding = padding || this.xpadding; + var offset; + + switch (location) { + case 'nw': + offset = -elem.outerWidth(true) - this.xpadding; + break; + case 'n': + offset = -elem.outerWidth(true)/2; + break; + case 'ne': + offset = this.xpadding; + break; + case 'e': + offset = this.xpadding; + break; + case 'se': + offset = this.xpadding; + break; + case 's': + offset = -elem.outerWidth(true)/2; + break; + case 'sw': + offset = -elem.outerWidth(true) - this.xpadding; + break; + case 'w': + offset = -elem.outerWidth(true) - this.xpadding; + break; + default: // same as 'nw' + offset = -elem.outerWidth(true) - this.xpadding; + break; + } + return offset; + }; + + $.jqplot.PointLabels.prototype.yOffset = function(elem, location, padding) { + location = location || this.location; + padding = padding || this.xpadding; + var offset; + + switch (location) { + case 'nw': + offset = -elem.outerHeight(true) - this.ypadding; + break; + case 'n': + offset = -elem.outerHeight(true) - this.ypadding; + break; + case 'ne': + offset = -elem.outerHeight(true) - this.ypadding; + break; + case 'e': + offset = -elem.outerHeight(true)/2; + break; + case 'se': + offset = this.ypadding; + break; + case 's': + offset = this.ypadding; + break; + case 'sw': + offset = this.ypadding; + break; + case 'w': + offset = -elem.outerHeight(true)/2; + break; + default: // same as 'nw' + offset = -elem.outerHeight(true) - this.ypadding; + break; + } + return offset; + }; + + // called with scope of series + $.jqplot.PointLabels.draw = function (sctx, options, plot) { + var p = this.plugins.pointLabels; + // set labels again in case they have changed. + p.setLabels.call(this); + // remove any previous labels + for (var i=0; i<p._elems.length; i++) { + // Memory Leaks patch + // p._elems[i].remove(); + p._elems[i].emptyForce(); + } + p._elems.splice(0, p._elems.length); + + if (p.show) { + var ax = '_'+this._stackAxis+'axis'; + + if (!p.formatString) { + p.formatString = this[ax]._ticks[0].formatString; + p.formatter = this[ax]._ticks[0].formatter; + } + + var pd = this._plotData; + var ppd = this._prevPlotData; + var xax = this._xaxis; + var yax = this._yaxis; + var elem, helem; + + for (var i=0, l=p._labels.length; i < l; i++) { + var label = p._labels[i]; + + if (p.hideZeros && parseInt(p._labels[i], 10) == 0) { + label = ''; + } + + if (label != null) { + label = p.formatter(p.formatString, label); + } + + helem = document.createElement('div'); + p._elems[i] = $(helem); + + elem = p._elems[i]; + + + elem.addClass('jqplot-point-label jqplot-series-'+this.index+' jqplot-point-'+i); + elem.css('position', 'absolute'); + elem.insertAfter(sctx.canvas); + + if (p.escapeHTML) { + elem.text(label); + } + else { + elem.html(label); + } + var location = p.location; + if ((this.fillToZero && pd[i][1] < 0) || (this.fillToZero && this._type === 'bar' && this.barDirection === 'horizontal' && pd[i][0] < 0) || (this.waterfall && parseInt(label, 10)) < 0) { + location = oppositeLocations[locationIndicies[location]]; + } + + + var ell = xax.u2p(pd[i][0]) + p.xOffset(elem, location); + var elt = yax.u2p(pd[i][1]) + p.yOffset(elem, location); + + // we have stacked chart but are not showing stacked values, + // place labels in center. + if (this._stack && !p.stackedValue) { + if (this.barDirection === "vertical") { + elt = (this._barPoints[i][0][1] + this._barPoints[i][1][1]) / 2 + plot._gridPadding.top - 0.5 * elem.outerHeight(true); + } + else { + ell = (this._barPoints[i][2][0] + this._barPoints[i][0][0]) / 2 + plot._gridPadding.left - 0.5 * elem.outerWidth(true); + } + } + + if (this.renderer.constructor == $.jqplot.BarRenderer) { + if (this.barDirection == "vertical") { + ell += this._barNudge; + } + else { + elt -= this._barNudge; + } + } + elem.css('left', ell); + elem.css('top', elt); + var elr = ell + elem.width(); + var elb = elt + elem.height(); + var et = p.edgeTolerance; + var scl = $(sctx.canvas).position().left; + var sct = $(sctx.canvas).position().top; + var scr = sctx.canvas.width + scl; + var scb = sctx.canvas.height + sct; + // if label is outside of allowed area, remove it + if (ell - et < scl || elt - et < sct || elr + et > scr || elb + et > scb) { + elem.remove(); + } + + elem = null; + helem = null; + } + + // finally, animate them if the series is animated + // if (this.renderer.animation && this.renderer.animation._supported && this.renderer.animation.show && plot._drawCount < 2) { + // var sel = '.jqplot-point-label.jqplot-series-'+this.index; + // $(sel).hide(); + // $(sel).fadeIn(1000); + // } + + } + }; + + $.jqplot.postSeriesInitHooks.push($.jqplot.PointLabels.init); + $.jqplot.postDrawSeriesHooks.push($.jqplot.PointLabels.draw); +})(jQuery);
\ No newline at end of file diff --git a/hugo/js/jquery/jquery-1.8.3.min.js b/hugo/js/jquery/jquery-1.8.3.min.js new file mode 100644 index 0000000..83589da --- /dev/null +++ b/hugo/js/jquery/jquery-1.8.3.min.js @@ -0,0 +1,2 @@ +/*! jQuery v1.8.3 jquery.com | jquery.org/license */
+(function(e,t){function _(e){var t=M[e]={};return v.each(e.split(y),function(e,n){t[n]=!0}),t}function H(e,n,r){if(r===t&&e.nodeType===1){var i="data-"+n.replace(P,"-$1").toLowerCase();r=e.getAttribute(i);if(typeof r=="string"){try{r=r==="true"?!0:r==="false"?!1:r==="null"?null:+r+""===r?+r:D.test(r)?v.parseJSON(r):r}catch(s){}v.data(e,n,r)}else r=t}return r}function B(e){var t;for(t in e){if(t==="data"&&v.isEmptyObject(e[t]))continue;if(t!=="toJSON")return!1}return!0}function et(){return!1}function tt(){return!0}function ut(e){return!e||!e.parentNode||e.parentNode.nodeType===11}function at(e,t){do e=e[t];while(e&&e.nodeType!==1);return e}function ft(e,t,n){t=t||0;if(v.isFunction(t))return v.grep(e,function(e,r){var i=!!t.call(e,r,e);return i===n});if(t.nodeType)return v.grep(e,function(e,r){return e===t===n});if(typeof t=="string"){var r=v.grep(e,function(e){return e.nodeType===1});if(it.test(t))return v.filter(t,r,!n);t=v.filter(t,r)}return v.grep(e,function(e,r){return v.inArray(e,t)>=0===n})}function lt(e){var t=ct.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}function Lt(e,t){return e.getElementsByTagName(t)[0]||e.appendChild(e.ownerDocument.createElement(t))}function At(e,t){if(t.nodeType!==1||!v.hasData(e))return;var n,r,i,s=v._data(e),o=v._data(t,s),u=s.events;if(u){delete o.handle,o.events={};for(n in u)for(r=0,i=u[n].length;r<i;r++)v.event.add(t,n,u[n][r])}o.data&&(o.data=v.extend({},o.data))}function Ot(e,t){var n;if(t.nodeType!==1)return;t.clearAttributes&&t.clearAttributes(),t.mergeAttributes&&t.mergeAttributes(e),n=t.nodeName.toLowerCase(),n==="object"?(t.parentNode&&(t.outerHTML=e.outerHTML),v.support.html5Clone&&e.innerHTML&&!v.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):n==="input"&&Et.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):n==="option"?t.selected=e.defaultSelected:n==="input"||n==="textarea"?t.defaultValue=e.defaultValue:n==="script"&&t.text!==e.text&&(t.text=e.text),t.removeAttribute(v.expando)}function Mt(e){return typeof e.getElementsByTagName!="undefined"?e.getElementsByTagName("*"):typeof e.querySelectorAll!="undefined"?e.querySelectorAll("*"):[]}function _t(e){Et.test(e.type)&&(e.defaultChecked=e.checked)}function Qt(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=Jt.length;while(i--){t=Jt[i]+n;if(t in e)return t}return r}function Gt(e,t){return e=t||e,v.css(e,"display")==="none"||!v.contains(e.ownerDocument,e)}function Yt(e,t){var n,r,i=[],s=0,o=e.length;for(;s<o;s++){n=e[s];if(!n.style)continue;i[s]=v._data(n,"olddisplay"),t?(!i[s]&&n.style.display==="none"&&(n.style.display=""),n.style.display===""&&Gt(n)&&(i[s]=v._data(n,"olddisplay",nn(n.nodeName)))):(r=Dt(n,"display"),!i[s]&&r!=="none"&&v._data(n,"olddisplay",r))}for(s=0;s<o;s++){n=e[s];if(!n.style)continue;if(!t||n.style.display==="none"||n.style.display==="")n.style.display=t?i[s]||"":"none"}return e}function Zt(e,t,n){var r=Rt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function en(e,t,n,r){var i=n===(r?"border":"content")?4:t==="width"?1:0,s=0;for(;i<4;i+=2)n==="margin"&&(s+=v.css(e,n+$t[i],!0)),r?(n==="content"&&(s-=parseFloat(Dt(e,"padding"+$t[i]))||0),n!=="margin"&&(s-=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0)):(s+=parseFloat(Dt(e,"padding"+$t[i]))||0,n!=="padding"&&(s+=parseFloat(Dt(e,"border"+$t[i]+"Width"))||0));return s}function tn(e,t,n){var r=t==="width"?e.offsetWidth:e.offsetHeight,i=!0,s=v.support.boxSizing&&v.css(e,"boxSizing")==="border-box";if(r<=0||r==null){r=Dt(e,t);if(r<0||r==null)r=e.style[t];if(Ut.test(r))return r;i=s&&(v.support.boxSizingReliable||r===e.style[t]),r=parseFloat(r)||0}return r+en(e,t,n||(s?"border":"content"),i)+"px"}function nn(e){if(Wt[e])return Wt[e];var t=v("<"+e+">").appendTo(i.body),n=t.css("display");t.remove();if(n==="none"||n===""){Pt=i.body.appendChild(Pt||v.extend(i.createElement("iframe"),{frameBorder:0,width:0,height:0}));if(!Ht||!Pt.createElement)Ht=(Pt.contentWindow||Pt.contentDocument).document,Ht.write("<!doctype html><html><body>"),Ht.close();t=Ht.body.appendChild(Ht.createElement(e)),n=Dt(t,"display"),i.body.removeChild(Pt)}return Wt[e]=n,n}function fn(e,t,n,r){var i;if(v.isArray(t))v.each(t,function(t,i){n||sn.test(e)?r(e,i):fn(e+"["+(typeof i=="object"?t:"")+"]",i,n,r)});else if(!n&&v.type(t)==="object")for(i in t)fn(e+"["+i+"]",t[i],n,r);else r(e,t)}function Cn(e){return function(t,n){typeof t!="string"&&(n=t,t="*");var r,i,s,o=t.toLowerCase().split(y),u=0,a=o.length;if(v.isFunction(n))for(;u<a;u++)r=o[u],s=/^\+/.test(r),s&&(r=r.substr(1)||"*"),i=e[r]=e[r]||[],i[s?"unshift":"push"](n)}}function kn(e,n,r,i,s,o){s=s||n.dataTypes[0],o=o||{},o[s]=!0;var u,a=e[s],f=0,l=a?a.length:0,c=e===Sn;for(;f<l&&(c||!u);f++)u=a[f](n,r,i),typeof u=="string"&&(!c||o[u]?u=t:(n.dataTypes.unshift(u),u=kn(e,n,r,i,u,o)));return(c||!u)&&!o["*"]&&(u=kn(e,n,r,i,"*",o)),u}function Ln(e,n){var r,i,s=v.ajaxSettings.flatOptions||{};for(r in n)n[r]!==t&&((s[r]?e:i||(i={}))[r]=n[r]);i&&v.extend(!0,e,i)}function An(e,n,r){var i,s,o,u,a=e.contents,f=e.dataTypes,l=e.responseFields;for(s in l)s in r&&(n[l[s]]=r[s]);while(f[0]==="*")f.shift(),i===t&&(i=e.mimeType||n.getResponseHeader("content-type"));if(i)for(s in a)if(a[s]&&a[s].test(i)){f.unshift(s);break}if(f[0]in r)o=f[0];else{for(s in r){if(!f[0]||e.converters[s+" "+f[0]]){o=s;break}u||(u=s)}o=o||u}if(o)return o!==f[0]&&f.unshift(o),r[o]}function On(e,t){var n,r,i,s,o=e.dataTypes.slice(),u=o[0],a={},f=0;e.dataFilter&&(t=e.dataFilter(t,e.dataType));if(o[1])for(n in e.converters)a[n.toLowerCase()]=e.converters[n];for(;i=o[++f];)if(i!=="*"){if(u!=="*"&&u!==i){n=a[u+" "+i]||a["* "+i];if(!n)for(r in a){s=r.split(" ");if(s[1]===i){n=a[u+" "+s[0]]||a["* "+s[0]];if(n){n===!0?n=a[r]:a[r]!==!0&&(i=s[0],o.splice(f--,0,i));break}}}if(n!==!0)if(n&&e["throws"])t=n(t);else try{t=n(t)}catch(l){return{state:"parsererror",error:n?l:"No conversion from "+u+" to "+i}}}u=i}return{state:"success",data:t}}function Fn(){try{return new e.XMLHttpRequest}catch(t){}}function In(){try{return new e.ActiveXObject("Microsoft.XMLHTTP")}catch(t){}}function $n(){return setTimeout(function(){qn=t},0),qn=v.now()}function Jn(e,t){v.each(t,function(t,n){var r=(Vn[t]||[]).concat(Vn["*"]),i=0,s=r.length;for(;i<s;i++)if(r[i].call(e,t,n))return})}function Kn(e,t,n){var r,i=0,s=0,o=Xn.length,u=v.Deferred().always(function(){delete a.elem}),a=function(){var t=qn||$n(),n=Math.max(0,f.startTime+f.duration-t),r=n/f.duration||0,i=1-r,s=0,o=f.tweens.length;for(;s<o;s++)f.tweens[s].run(i);return u.notifyWith(e,[f,i,n]),i<1&&o?n:(u.resolveWith(e,[f]),!1)},f=u.promise({elem:e,props:v.extend({},t),opts:v.extend(!0,{specialEasing:{}},n),originalProperties:t,originalOptions:n,startTime:qn||$n(),duration:n.duration,tweens:[],createTween:function(t,n,r){var i=v.Tween(e,f.opts,t,n,f.opts.specialEasing[t]||f.opts.easing);return f.tweens.push(i),i},stop:function(t){var n=0,r=t?f.tweens.length:0;for(;n<r;n++)f.tweens[n].run(1);return t?u.resolveWith(e,[f,t]):u.rejectWith(e,[f,t]),this}}),l=f.props;Qn(l,f.opts.specialEasing);for(;i<o;i++){r=Xn[i].call(f,e,l,f.opts);if(r)return r}return Jn(f,l),v.isFunction(f.opts.start)&&f.opts.start.call(e,f),v.fx.timer(v.extend(a,{anim:f,queue:f.opts.queue,elem:e})),f.progress(f.opts.progress).done(f.opts.done,f.opts.complete).fail(f.opts.fail).always(f.opts.always)}function Qn(e,t){var n,r,i,s,o;for(n in e){r=v.camelCase(n),i=t[r],s=e[n],v.isArray(s)&&(i=s[1],s=e[n]=s[0]),n!==r&&(e[r]=s,delete e[n]),o=v.cssHooks[r];if(o&&"expand"in o){s=o.expand(s),delete e[r];for(n in s)n in e||(e[n]=s[n],t[n]=i)}else t[r]=i}}function Gn(e,t,n){var r,i,s,o,u,a,f,l,c,h=this,p=e.style,d={},m=[],g=e.nodeType&&Gt(e);n.queue||(l=v._queueHooks(e,"fx"),l.unqueued==null&&(l.unqueued=0,c=l.empty.fire,l.empty.fire=function(){l.unqueued||c()}),l.unqueued++,h.always(function(){h.always(function(){l.unqueued--,v.queue(e,"fx").length||l.empty.fire()})})),e.nodeType===1&&("height"in t||"width"in t)&&(n.overflow=[p.overflow,p.overflowX,p.overflowY],v.css(e,"display")==="inline"&&v.css(e,"float")==="none"&&(!v.support.inlineBlockNeedsLayout||nn(e.nodeName)==="inline"?p.display="inline-block":p.zoom=1)),n.overflow&&(p.overflow="hidden",v.support.shrinkWrapBlocks||h.done(function(){p.overflow=n.overflow[0],p.overflowX=n.overflow[1],p.overflowY=n.overflow[2]}));for(r in t){s=t[r];if(Un.exec(s)){delete t[r],a=a||s==="toggle";if(s===(g?"hide":"show"))continue;m.push(r)}}o=m.length;if(o){u=v._data(e,"fxshow")||v._data(e,"fxshow",{}),"hidden"in u&&(g=u.hidden),a&&(u.hidden=!g),g?v(e).show():h.done(function(){v(e).hide()}),h.done(function(){var t;v.removeData(e,"fxshow",!0);for(t in d)v.style(e,t,d[t])});for(r=0;r<o;r++)i=m[r],f=h.createTween(i,g?u[i]:0),d[i]=u[i]||v.style(e,i),i in u||(u[i]=f.start,g&&(f.end=f.start,f.start=i==="width"||i==="height"?1:0))}}function Yn(e,t,n,r,i){return new Yn.prototype.init(e,t,n,r,i)}function Zn(e,t){var n,r={height:e},i=0;t=t?1:0;for(;i<4;i+=2-t)n=$t[i],r["margin"+n]=r["padding"+n]=e;return t&&(r.opacity=r.width=e),r}function tr(e){return v.isWindow(e)?e:e.nodeType===9?e.defaultView||e.parentWindow:!1}var n,r,i=e.document,s=e.location,o=e.navigator,u=e.jQuery,a=e.$,f=Array.prototype.push,l=Array.prototype.slice,c=Array.prototype.indexOf,h=Object.prototype.toString,p=Object.prototype.hasOwnProperty,d=String.prototype.trim,v=function(e,t){return new v.fn.init(e,t,n)},m=/[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source,g=/\S/,y=/\s+/,b=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,w=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,E=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,S=/^[\],:{}\s]*$/,x=/(?:^|:|,)(?:\s*\[)+/g,T=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,N=/"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g,C=/^-ms-/,k=/-([\da-z])/gi,L=function(e,t){return(t+"").toUpperCase()},A=function(){i.addEventListener?(i.removeEventListener("DOMContentLoaded",A,!1),v.ready()):i.readyState==="complete"&&(i.detachEvent("onreadystatechange",A),v.ready())},O={};v.fn=v.prototype={constructor:v,init:function(e,n,r){var s,o,u,a;if(!e)return this;if(e.nodeType)return this.context=this[0]=e,this.length=1,this;if(typeof e=="string"){e.charAt(0)==="<"&&e.charAt(e.length-1)===">"&&e.length>=3?s=[null,e,null]:s=w.exec(e);if(s&&(s[1]||!n)){if(s[1])return n=n instanceof v?n[0]:n,a=n&&n.nodeType?n.ownerDocument||n:i,e=v.parseHTML(s[1],a,!0),E.test(s[1])&&v.isPlainObject(n)&&this.attr.call(e,n,!0),v.merge(this,e);o=i.getElementById(s[2]);if(o&&o.parentNode){if(o.id!==s[2])return r.find(e);this.length=1,this[0]=o}return this.context=i,this.selector=e,this}return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e)}return v.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),v.makeArray(e,this))},selector:"",jquery:"1.8.3",length:0,size:function(){return this.length},toArray:function(){return l.call(this)},get:function(e){return e==null?this.toArray():e<0?this[this.length+e]:this[e]},pushStack:function(e,t,n){var r=v.merge(this.constructor(),e);return r.prevObject=this,r.context=this.context,t==="find"?r.selector=this.selector+(this.selector?" ":"")+n:t&&(r.selector=this.selector+"."+t+"("+n+")"),r},each:function(e,t){return v.each(this,e,t)},ready:function(e){return v.ready.promise().done(e),this},eq:function(e){return e=+e,e===-1?this.slice(e):this.slice(e,e+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(l.apply(this,arguments),"slice",l.call(arguments).join(","))},map:function(e){return this.pushStack(v.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:[].sort,splice:[].splice},v.fn.init.prototype=v.fn,v.extend=v.fn.extend=function(){var e,n,r,i,s,o,u=arguments[0]||{},a=1,f=arguments.length,l=!1;typeof u=="boolean"&&(l=u,u=arguments[1]||{},a=2),typeof u!="object"&&!v.isFunction(u)&&(u={}),f===a&&(u=this,--a);for(;a<f;a++)if((e=arguments[a])!=null)for(n in e){r=u[n],i=e[n];if(u===i)continue;l&&i&&(v.isPlainObject(i)||(s=v.isArray(i)))?(s?(s=!1,o=r&&v.isArray(r)?r:[]):o=r&&v.isPlainObject(r)?r:{},u[n]=v.extend(l,o,i)):i!==t&&(u[n]=i)}return u},v.extend({noConflict:function(t){return e.$===v&&(e.$=a),t&&e.jQuery===v&&(e.jQuery=u),v},isReady:!1,readyWait:1,holdReady:function(e){e?v.readyWait++:v.ready(!0)},ready:function(e){if(e===!0?--v.readyWait:v.isReady)return;if(!i.body)return setTimeout(v.ready,1);v.isReady=!0;if(e!==!0&&--v.readyWait>0)return;r.resolveWith(i,[v]),v.fn.trigger&&v(i).trigger("ready").off("ready")},isFunction:function(e){return v.type(e)==="function"},isArray:Array.isArray||function(e){return v.type(e)==="array"},isWindow:function(e){return e!=null&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return e==null?String(e):O[h.call(e)]||"object"},isPlainObject:function(e){if(!e||v.type(e)!=="object"||e.nodeType||v.isWindow(e))return!1;try{if(e.constructor&&!p.call(e,"constructor")&&!p.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(n){return!1}var r;for(r in e);return r===t||p.call(e,r)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw new Error(e)},parseHTML:function(e,t,n){var r;return!e||typeof e!="string"?null:(typeof t=="boolean"&&(n=t,t=0),t=t||i,(r=E.exec(e))?[t.createElement(r[1])]:(r=v.buildFragment([e],t,n?null:[]),v.merge([],(r.cacheable?v.clone(r.fragment):r.fragment).childNodes)))},parseJSON:function(t){if(!t||typeof t!="string")return null;t=v.trim(t);if(e.JSON&&e.JSON.parse)return e.JSON.parse(t);if(S.test(t.replace(T,"@").replace(N,"]").replace(x,"")))return(new Function("return "+t))();v.error("Invalid JSON: "+t)},parseXML:function(n){var r,i;if(!n||typeof n!="string")return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(s){r=t}return(!r||!r.documentElement||r.getElementsByTagName("parsererror").length)&&v.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&g.test(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(C,"ms-").replace(k,L)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,n,r){var i,s=0,o=e.length,u=o===t||v.isFunction(e);if(r){if(u){for(i in e)if(n.apply(e[i],r)===!1)break}else for(;s<o;)if(n.apply(e[s++],r)===!1)break}else if(u){for(i in e)if(n.call(e[i],i,e[i])===!1)break}else for(;s<o;)if(n.call(e[s],s,e[s++])===!1)break;return e},trim:d&&!d.call("\ufeff\u00a0")?function(e){return e==null?"":d.call(e)}:function(e){return e==null?"":(e+"").replace(b,"")},makeArray:function(e,t){var n,r=t||[];return e!=null&&(n=v.type(e),e.length==null||n==="string"||n==="function"||n==="regexp"||v.isWindow(e)?f.call(r,e):v.merge(r,e)),r},inArray:function(e,t,n){var r;if(t){if(c)return c.call(t,e,n);r=t.length,n=n?n<0?Math.max(0,r+n):n:0;for(;n<r;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,s=0;if(typeof r=="number")for(;s<r;s++)e[i++]=n[s];else while(n[s]!==t)e[i++]=n[s++];return e.length=i,e},grep:function(e,t,n){var r,i=[],s=0,o=e.length;n=!!n;for(;s<o;s++)r=!!t(e[s],s),n!==r&&i.push(e[s]);return i},map:function(e,n,r){var i,s,o=[],u=0,a=e.length,f=e instanceof v||a!==t&&typeof a=="number"&&(a>0&&e[0]&&e[a-1]||a===0||v.isArray(e));if(f)for(;u<a;u++)i=n(e[u],u,r),i!=null&&(o[o.length]=i);else for(s in e)i=n(e[s],s,r),i!=null&&(o[o.length]=i);return o.concat.apply([],o)},guid:1,proxy:function(e,n){var r,i,s;return typeof n=="string"&&(r=e[n],n=e,e=r),v.isFunction(e)?(i=l.call(arguments,2),s=function(){return e.apply(n,i.concat(l.call(arguments)))},s.guid=e.guid=e.guid||v.guid++,s):t},access:function(e,n,r,i,s,o,u){var a,f=r==null,l=0,c=e.length;if(r&&typeof r=="object"){for(l in r)v.access(e,n,l,r[l],1,o,i);s=1}else if(i!==t){a=u===t&&v.isFunction(i),f&&(a?(a=n,n=function(e,t,n){return a.call(v(e),n)}):(n.call(e,i),n=null));if(n)for(;l<c;l++)n(e[l],r,a?i.call(e[l],l,n(e[l],r)):i,u);s=1}return s?e:f?n.call(e):c?n(e[0],r):o},now:function(){return(new Date).getTime()}}),v.ready.promise=function(t){if(!r){r=v.Deferred();if(i.readyState==="complete")setTimeout(v.ready,1);else if(i.addEventListener)i.addEventListener("DOMContentLoaded",A,!1),e.addEventListener("load",v.ready,!1);else{i.attachEvent("onreadystatechange",A),e.attachEvent("onload",v.ready);var n=!1;try{n=e.frameElement==null&&i.documentElement}catch(s){}n&&n.doScroll&&function o(){if(!v.isReady){try{n.doScroll("left")}catch(e){return setTimeout(o,50)}v.ready()}}()}}return r.promise(t)},v.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(e,t){O["[object "+t+"]"]=t.toLowerCase()}),n=v(i);var M={};v.Callbacks=function(e){e=typeof e=="string"?M[e]||_(e):v.extend({},e);var n,r,i,s,o,u,a=[],f=!e.once&&[],l=function(t){n=e.memory&&t,r=!0,u=s||0,s=0,o=a.length,i=!0;for(;a&&u<o;u++)if(a[u].apply(t[0],t[1])===!1&&e.stopOnFalse){n=!1;break}i=!1,a&&(f?f.length&&l(f.shift()):n?a=[]:c.disable())},c={add:function(){if(a){var t=a.length;(function r(t){v.each(t,function(t,n){var i=v.type(n);i==="function"?(!e.unique||!c.has(n))&&a.push(n):n&&n.length&&i!=="string"&&r(n)})})(arguments),i?o=a.length:n&&(s=t,l(n))}return this},remove:function(){return a&&v.each(arguments,function(e,t){var n;while((n=v.inArray(t,a,n))>-1)a.splice(n,1),i&&(n<=o&&o--,n<=u&&u--)}),this},has:function(e){return v.inArray(e,a)>-1},empty:function(){return a=[],this},disable:function(){return a=f=n=t,this},disabled:function(){return!a},lock:function(){return f=t,n||c.disable(),this},locked:function(){return!f},fireWith:function(e,t){return t=t||[],t=[e,t.slice?t.slice():t],a&&(!r||f)&&(i?f.push(t):l(t)),this},fire:function(){return c.fireWith(this,arguments),this},fired:function(){return!!r}};return c},v.extend({Deferred:function(e){var t=[["resolve","done",v.Callbacks("once memory"),"resolved"],["reject","fail",v.Callbacks("once memory"),"rejected"],["notify","progress",v.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return v.Deferred(function(n){v.each(t,function(t,r){var s=r[0],o=e[t];i[r[1]](v.isFunction(o)?function(){var e=o.apply(this,arguments);e&&v.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[s+"With"](this===i?n:this,[e])}:n[s])}),e=null}).promise()},promise:function(e){return e!=null?v.extend(e,r):r}},i={};return r.pipe=r.then,v.each(t,function(e,s){var o=s[2],u=s[3];r[s[1]]=o.add,u&&o.add(function(){n=u},t[e^1][2].disable,t[2][2].lock),i[s[0]]=o.fire,i[s[0]+"With"]=o.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=l.call(arguments),r=n.length,i=r!==1||e&&v.isFunction(e.promise)?r:0,s=i===1?e:v.Deferred(),o=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?l.call(arguments):r,n===u?s.notifyWith(t,n):--i||s.resolveWith(t,n)}},u,a,f;if(r>1){u=new Array(r),a=new Array(r),f=new Array(r);for(;t<r;t++)n[t]&&v.isFunction(n[t].promise)?n[t].promise().done(o(t,f,n)).fail(s.reject).progress(o(t,a,u)):--i}return i||s.resolveWith(f,n),s.promise()}}),v.support=function(){var t,n,r,s,o,u,a,f,l,c,h,p=i.createElement("div");p.setAttribute("className","t"),p.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",n=p.getElementsByTagName("*"),r=p.getElementsByTagName("a")[0];if(!n||!r||!n.length)return{};s=i.createElement("select"),o=s.appendChild(i.createElement("option")),u=p.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(r.getAttribute("style")),hrefNormalized:r.getAttribute("href")==="/a",opacity:/^0.5/.test(r.style.opacity),cssFloat:!!r.style.cssFloat,checkOn:u.value==="on",optSelected:o.selected,getSetAttribute:p.className!=="t",enctype:!!i.createElement("form").enctype,html5Clone:i.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",boxModel:i.compatMode==="CSS1Compat",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,boxSizingReliable:!0,pixelPosition:!1},u.checked=!0,t.noCloneChecked=u.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!o.disabled;try{delete p.test}catch(d){t.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",h=function(){t.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick"),p.detachEvent("onclick",h)),u=i.createElement("input"),u.value="t",u.setAttribute("type","radio"),t.radioValue=u.value==="t",u.setAttribute("checked","checked"),u.setAttribute("name","t"),p.appendChild(u),a=i.createDocumentFragment(),a.appendChild(p.lastChild),t.checkClone=a.cloneNode(!0).cloneNode(!0).lastChild.checked,t.appendChecked=u.checked,a.removeChild(u),a.appendChild(p);if(p.attachEvent)for(l in{submit:!0,change:!0,focusin:!0})f="on"+l,c=f in p,c||(p.setAttribute(f,"return;"),c=typeof p[f]=="function"),t[l+"Bubbles"]=c;return v(function(){var n,r,s,o,u="padding:0;margin:0;border:0;display:block;overflow:hidden;",a=i.getElementsByTagName("body")[0];if(!a)return;n=i.createElement("div"),n.style.cssText="visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px",a.insertBefore(n,a.firstChild),r=i.createElement("div"),n.appendChild(r),r.innerHTML="<table><tr><td></td><td>t</td></tr></table>",s=r.getElementsByTagName("td"),s[0].style.cssText="padding:0;margin:0;border:0;display:none",c=s[0].offsetHeight===0,s[0].style.display="",s[1].style.display="none",t.reliableHiddenOffsets=c&&s[0].offsetHeight===0,r.innerHTML="",r.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",t.boxSizing=r.offsetWidth===4,t.doesNotIncludeMarginInBodyOffset=a.offsetTop!==1,e.getComputedStyle&&(t.pixelPosition=(e.getComputedStyle(r,null)||{}).top!=="1%",t.boxSizingReliable=(e.getComputedStyle(r,null)||{width:"4px"}).width==="4px",o=i.createElement("div"),o.style.cssText=r.style.cssText=u,o.style.marginRight=o.style.width="0",r.style.width="1px",r.appendChild(o),t.reliableMarginRight=!parseFloat((e.getComputedStyle(o,null)||{}).marginRight)),typeof r.style.zoom!="undefined"&&(r.innerHTML="",r.style.cssText=u+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=r.offsetWidth===3,r.style.display="block",r.style.overflow="visible",r.innerHTML="<div></div>",r.firstChild.style.width="5px",t.shrinkWrapBlocks=r.offsetWidth!==3,n.style.zoom=1),a.removeChild(n),n=r=s=o=null}),a.removeChild(p),n=r=s=o=u=a=p=null,t}();var D=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;v.extend({cache:{},deletedIds:[],uuid:0,expando:"jQuery"+(v.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(e){return e=e.nodeType?v.cache[e[v.expando]]:e[v.expando],!!e&&!B(e)},data:function(e,n,r,i){if(!v.acceptData(e))return;var s,o,u=v.expando,a=typeof n=="string",f=e.nodeType,l=f?v.cache:e,c=f?e[u]:e[u]&&u;if((!c||!l[c]||!i&&!l[c].data)&&a&&r===t)return;c||(f?e[u]=c=v.deletedIds.pop()||v.guid++:c=u),l[c]||(l[c]={},f||(l[c].toJSON=v.noop));if(typeof n=="object"||typeof n=="function")i?l[c]=v.extend(l[c],n):l[c].data=v.extend(l[c].data,n);return s=l[c],i||(s.data||(s.data={}),s=s.data),r!==t&&(s[v.camelCase(n)]=r),a?(o=s[n],o==null&&(o=s[v.camelCase(n)])):o=s,o},removeData:function(e,t,n){if(!v.acceptData(e))return;var r,i,s,o=e.nodeType,u=o?v.cache:e,a=o?e[v.expando]:v.expando;if(!u[a])return;if(t){r=n?u[a]:u[a].data;if(r){v.isArray(t)||(t in r?t=[t]:(t=v.camelCase(t),t in r?t=[t]:t=t.split(" ")));for(i=0,s=t.length;i<s;i++)delete r[t[i]];if(!(n?B:v.isEmptyObject)(r))return}}if(!n){delete u[a].data;if(!B(u[a]))return}o?v.cleanData([e],!0):v.support.deleteExpando||u!=u.window?delete u[a]:u[a]=null},_data:function(e,t,n){return v.data(e,t,n,!0)},acceptData:function(e){var t=e.nodeName&&v.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),v.fn.extend({data:function(e,n){var r,i,s,o,u,a=this[0],f=0,l=null;if(e===t){if(this.length){l=v.data(a);if(a.nodeType===1&&!v._data(a,"parsedAttrs")){s=a.attributes;for(u=s.length;f<u;f++)o=s[f].name,o.indexOf("data-")||(o=v.camelCase(o.substring(5)),H(a,o,l[o]));v._data(a,"parsedAttrs",!0)}}return l}return typeof e=="object"?this.each(function(){v.data(this,e)}):(r=e.split(".",2),r[1]=r[1]?"."+r[1]:"",i=r[1]+"!",v.access(this,function(n){if(n===t)return l=this.triggerHandler("getData"+i,[r[0]]),l===t&&a&&(l=v.data(a,e),l=H(a,e,l)),l===t&&r[1]?this.data(r[0]):l;r[1]=n,this.each(function(){var t=v(this);t.triggerHandler("setData"+i,r),v.data(this,e,n),t.triggerHandler("changeData"+i,r)})},null,n,arguments.length>1,null,!1))},removeData:function(e){return this.each(function(){v.removeData(this,e)})}}),v.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=v._data(e,t),n&&(!r||v.isArray(n)?r=v._data(e,t,v.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=v.queue(e,t),r=n.length,i=n.shift(),s=v._queueHooks(e,t),o=function(){v.dequeue(e,t)};i==="inprogress"&&(i=n.shift(),r--),i&&(t==="fx"&&n.unshift("inprogress"),delete s.stop,i.call(e,o,s)),!r&&s&&s.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return v._data(e,n)||v._data(e,n,{empty:v.Callbacks("once memory").add(function(){v.removeData(e,t+"queue",!0),v.removeData(e,n,!0)})})}}),v.fn.extend({queue:function(e,n){var r=2;return typeof e!="string"&&(n=e,e="fx",r--),arguments.length<r?v.queue(this[0],e):n===t?this:this.each(function(){var t=v.queue(this,e,n);v._queueHooks(this,e),e==="fx"&&t[0]!=="inprogress"&&v.dequeue(this,e)})},dequeue:function(e){return this.each(function(){v.dequeue(this,e)})},delay:function(e,t){return e=v.fx?v.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,s=v.Deferred(),o=this,u=this.length,a=function(){--i||s.resolveWith(o,[o])};typeof e!="string"&&(n=e,e=t),e=e||"fx";while(u--)r=v._data(o[u],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(a));return a(),s.promise(n)}});var j,F,I,q=/[\t\r\n]/g,R=/\r/g,U=/^(?:button|input)$/i,z=/^(?:button|input|object|select|textarea)$/i,W=/^a(?:rea|)$/i,X=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,V=v.support.getSetAttribute;v.fn.extend({attr:function(e,t){return v.access(this,v.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){v.removeAttr(this,e)})},prop:function(e,t){return v.access(this,v.prop,e,t,arguments.length>1)},removeProp:function(e){return e=v.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,s,o,u;if(v.isFunction(e))return this.each(function(t){v(this).addClass(e.call(this,t,this.className))});if(e&&typeof e=="string"){t=e.split(y);for(n=0,r=this.length;n<r;n++){i=this[n];if(i.nodeType===1)if(!i.className&&t.length===1)i.className=e;else{s=" "+i.className+" ";for(o=0,u=t.length;o<u;o++)s.indexOf(" "+t[o]+" ")<0&&(s+=t[o]+" ");i.className=v.trim(s)}}}return this},removeClass:function(e){var n,r,i,s,o,u,a;if(v.isFunction(e))return this.each(function(t){v(this).removeClass(e.call(this,t,this.className))});if(e&&typeof e=="string"||e===t){n=(e||"").split(y);for(u=0,a=this.length;u<a;u++){i=this[u];if(i.nodeType===1&&i.className){r=(" "+i.className+" ").replace(q," ");for(s=0,o=n.length;s<o;s++)while(r.indexOf(" "+n[s]+" ")>=0)r=r.replace(" "+n[s]+" "," ");i.className=e?v.trim(r):""}}}return this},toggleClass:function(e,t){var n=typeof e,r=typeof t=="boolean";return v.isFunction(e)?this.each(function(n){v(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if(n==="string"){var i,s=0,o=v(this),u=t,a=e.split(y);while(i=a[s++])u=r?u:!o.hasClass(i),o[u?"addClass":"removeClass"](i)}else if(n==="undefined"||n==="boolean")this.className&&v._data(this,"__className__",this.className),this.className=this.className||e===!1?"":v._data(this,"__className__")||""})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;n<r;n++)if(this[n].nodeType===1&&(" "+this[n].className+" ").replace(q," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,s=this[0];if(!arguments.length){if(s)return n=v.valHooks[s.type]||v.valHooks[s.nodeName.toLowerCase()],n&&"get"in n&&(r=n.get(s,"value"))!==t?r:(r=s.value,typeof r=="string"?r.replace(R,""):r==null?"":r);return}return i=v.isFunction(e),this.each(function(r){var s,o=v(this);if(this.nodeType!==1)return;i?s=e.call(this,r,o.val()):s=e,s==null?s="":typeof s=="number"?s+="":v.isArray(s)&&(s=v.map(s,function(e){return e==null?"":e+""})),n=v.valHooks[this.type]||v.valHooks[this.nodeName.toLowerCase()];if(!n||!("set"in n)||n.set(this,s,"value")===t)this.value=s})}}),v.extend({valHooks:{option:{get:function(e){var t=e.attributes.value;return!t||t.specified?e.value:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,s=e.type==="select-one"||i<0,o=s?null:[],u=s?i+1:r.length,a=i<0?u:s?i:0;for(;a<u;a++){n=r[a];if((n.selected||a===i)&&(v.support.optDisabled?!n.disabled:n.getAttribute("disabled")===null)&&(!n.parentNode.disabled||!v.nodeName(n.parentNode,"optgroup"))){t=v(n).val();if(s)return t;o.push(t)}}return o},set:function(e,t){var n=v.makeArray(t);return v(e).find("option").each(function(){this.selected=v.inArray(v(this).val(),n)>=0}),n.length||(e.selectedIndex=-1),n}}},attrFn:{},attr:function(e,n,r,i){var s,o,u,a=e.nodeType;if(!e||a===3||a===8||a===2)return;if(i&&v.isFunction(v.fn[n]))return v(e)[n](r);if(typeof e.getAttribute=="undefined")return v.prop(e,n,r);u=a!==1||!v.isXMLDoc(e),u&&(n=n.toLowerCase(),o=v.attrHooks[n]||(X.test(n)?F:j));if(r!==t){if(r===null){v.removeAttr(e,n);return}return o&&"set"in o&&u&&(s=o.set(e,r,n))!==t?s:(e.setAttribute(n,r+""),r)}return o&&"get"in o&&u&&(s=o.get(e,n))!==null?s:(s=e.getAttribute(n),s===null?t:s)},removeAttr:function(e,t){var n,r,i,s,o=0;if(t&&e.nodeType===1){r=t.split(y);for(;o<r.length;o++)i=r[o],i&&(n=v.propFix[i]||i,s=X.test(i),s||v.attr(e,i,""),e.removeAttribute(V?i:n),s&&n in e&&(e[n]=!1))}},attrHooks:{type:{set:function(e,t){if(U.test(e.nodeName)&&e.parentNode)v.error("type property can't be changed");else if(!v.support.radioValue&&t==="radio"&&v.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}},value:{get:function(e,t){return j&&v.nodeName(e,"button")?j.get(e,t):t in e?e.value:null},set:function(e,t,n){if(j&&v.nodeName(e,"button"))return j.set(e,t,n);e.value=t}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(e,n,r){var i,s,o,u=e.nodeType;if(!e||u===3||u===8||u===2)return;return o=u!==1||!v.isXMLDoc(e),o&&(n=v.propFix[n]||n,s=v.propHooks[n]),r!==t?s&&"set"in s&&(i=s.set(e,r,n))!==t?i:e[n]=r:s&&"get"in s&&(i=s.get(e,n))!==null?i:e[n]},propHooks:{tabIndex:{get:function(e){var n=e.getAttributeNode("tabindex");return n&&n.specified?parseInt(n.value,10):z.test(e.nodeName)||W.test(e.nodeName)&&e.href?0:t}}}}),F={get:function(e,n){var r,i=v.prop(e,n);return i===!0||typeof i!="boolean"&&(r=e.getAttributeNode(n))&&r.nodeValue!==!1?n.toLowerCase():t},set:function(e,t,n){var r;return t===!1?v.removeAttr(e,n):(r=v.propFix[n]||n,r in e&&(e[r]=!0),e.setAttribute(n,n.toLowerCase())),n}},V||(I={name:!0,id:!0,coords:!0},j=v.valHooks.button={get:function(e,n){var r;return r=e.getAttributeNode(n),r&&(I[n]?r.value!=="":r.specified)?r.value:t},set:function(e,t,n){var r=e.getAttributeNode(n);return r||(r=i.createAttribute(n),e.setAttributeNode(r)),r.value=t+""}},v.each(["width","height"],function(e,t){v.attrHooks[t]=v.extend(v.attrHooks[t],{set:function(e,n){if(n==="")return e.setAttribute(t,"auto"),n}})}),v.attrHooks.contenteditable={get:j.get,set:function(e,t,n){t===""&&(t="false"),j.set(e,t,n)}}),v.support.hrefNormalized||v.each(["href","src","width","height"],function(e,n){v.attrHooks[n]=v.extend(v.attrHooks[n],{get:function(e){var r=e.getAttribute(n,2);return r===null?t:r}})}),v.support.style||(v.attrHooks.style={get:function(e){return e.style.cssText.toLowerCase()||t},set:function(e,t){return e.style.cssText=t+""}}),v.support.optSelected||(v.propHooks.selected=v.extend(v.propHooks.selected,{get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}})),v.support.enctype||(v.propFix.enctype="encoding"),v.support.checkOn||v.each(["radio","checkbox"],function(){v.valHooks[this]={get:function(e){return e.getAttribute("value")===null?"on":e.value}}}),v.each(["radio","checkbox"],function(){v.valHooks[this]=v.extend(v.valHooks[this],{set:function(e,t){if(v.isArray(t))return e.checked=v.inArray(v(e).val(),t)>=0}})});var $=/^(?:textarea|input|select)$/i,J=/^([^\.]*|)(?:\.(.+)|)$/,K=/(?:^|\s)hover(\.\S+|)\b/,Q=/^key/,G=/^(?:mouse|contextmenu)|click/,Y=/^(?:focusinfocus|focusoutblur)$/,Z=function(e){return v.event.special.hover?e:e.replace(K,"mouseenter$1 mouseleave$1")};v.event={add:function(e,n,r,i,s){var o,u,a,f,l,c,h,p,d,m,g;if(e.nodeType===3||e.nodeType===8||!n||!r||!(o=v._data(e)))return;r.handler&&(d=r,r=d.handler,s=d.selector),r.guid||(r.guid=v.guid++),a=o.events,a||(o.events=a={}),u=o.handle,u||(o.handle=u=function(e){return typeof v=="undefined"||!!e&&v.event.triggered===e.type?t:v.event.dispatch.apply(u.elem,arguments)},u.elem=e),n=v.trim(Z(n)).split(" ");for(f=0;f<n.length;f++){l=J.exec(n[f])||[],c=l[1],h=(l[2]||"").split(".").sort(),g=v.event.special[c]||{},c=(s?g.delegateType:g.bindType)||c,g=v.event.special[c]||{},p=v.extend({type:c,origType:l[1],data:i,handler:r,guid:r.guid,selector:s,needsContext:s&&v.expr.match.needsContext.test(s),namespace:h.join(".")},d),m=a[c];if(!m){m=a[c]=[],m.delegateCount=0;if(!g.setup||g.setup.call(e,i,h,u)===!1)e.addEventListener?e.addEventListener(c,u,!1):e.attachEvent&&e.attachEvent("on"+c,u)}g.add&&(g.add.call(e,p),p.handler.guid||(p.handler.guid=r.guid)),s?m.splice(m.delegateCount++,0,p):m.push(p),v.event.global[c]=!0}e=null},global:{},remove:function(e,t,n,r,i){var s,o,u,a,f,l,c,h,p,d,m,g=v.hasData(e)&&v._data(e);if(!g||!(h=g.events))return;t=v.trim(Z(t||"")).split(" ");for(s=0;s<t.length;s++){o=J.exec(t[s])||[],u=a=o[1],f=o[2];if(!u){for(u in h)v.event.remove(e,u+t[s],n,r,!0);continue}p=v.event.special[u]||{},u=(r?p.delegateType:p.bindType)||u,d=h[u]||[],l=d.length,f=f?new RegExp("(^|\\.)"+f.split(".").sort().join("\\.(?:.*\\.|)")+"(\\.|$)"):null;for(c=0;c<d.length;c++)m=d[c],(i||a===m.origType)&&(!n||n.guid===m.guid)&&(!f||f.test(m.namespace))&&(!r||r===m.selector||r==="**"&&m.selector)&&(d.splice(c--,1),m.selector&&d.delegateCount--,p.remove&&p.remove.call(e,m));d.length===0&&l!==d.length&&((!p.teardown||p.teardown.call(e,f,g.handle)===!1)&&v.removeEvent(e,u,g.handle),delete h[u])}v.isEmptyObject(h)&&(delete g.handle,v.removeData(e,"events",!0))},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(n,r,s,o){if(!s||s.nodeType!==3&&s.nodeType!==8){var u,a,f,l,c,h,p,d,m,g,y=n.type||n,b=[];if(Y.test(y+v.event.triggered))return;y.indexOf("!")>=0&&(y=y.slice(0,-1),a=!0),y.indexOf(".")>=0&&(b=y.split("."),y=b.shift(),b.sort());if((!s||v.event.customEvent[y])&&!v.event.global[y])return;n=typeof n=="object"?n[v.expando]?n:new v.Event(y,n):new v.Event(y),n.type=y,n.isTrigger=!0,n.exclusive=a,n.namespace=b.join("."),n.namespace_re=n.namespace?new RegExp("(^|\\.)"+b.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,h=y.indexOf(":")<0?"on"+y:"";if(!s){u=v.cache;for(f in u)u[f].events&&u[f].events[y]&&v.event.trigger(n,r,u[f].handle.elem,!0);return}n.result=t,n.target||(n.target=s),r=r!=null?v.makeArray(r):[],r.unshift(n),p=v.event.special[y]||{};if(p.trigger&&p.trigger.apply(s,r)===!1)return;m=[[s,p.bindType||y]];if(!o&&!p.noBubble&&!v.isWindow(s)){g=p.delegateType||y,l=Y.test(g+y)?s:s.parentNode;for(c=s;l;l=l.parentNode)m.push([l,g]),c=l;c===(s.ownerDocument||i)&&m.push([c.defaultView||c.parentWindow||e,g])}for(f=0;f<m.length&&!n.isPropagationStopped();f++)l=m[f][0],n.type=m[f][1],d=(v._data(l,"events")||{})[n.type]&&v._data(l,"handle"),d&&d.apply(l,r),d=h&&l[h],d&&v.acceptData(l)&&d.apply&&d.apply(l,r)===!1&&n.preventDefault();return n.type=y,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(s.ownerDocument,r)===!1)&&(y!=="click"||!v.nodeName(s,"a"))&&v.acceptData(s)&&h&&s[y]&&(y!=="focus"&&y!=="blur"||n.target.offsetWidth!==0)&&!v.isWindow(s)&&(c=s[h],c&&(s[h]=null),v.event.triggered=y,s[y](),v.event.triggered=t,c&&(s[h]=c)),n.result}return},dispatch:function(n){n=v.event.fix(n||e.event);var r,i,s,o,u,a,f,c,h,p,d=(v._data(this,"events")||{})[n.type]||[],m=d.delegateCount,g=l.call(arguments),y=!n.exclusive&&!n.namespace,b=v.event.special[n.type]||{},w=[];g[0]=n,n.delegateTarget=this;if(b.preDispatch&&b.preDispatch.call(this,n)===!1)return;if(m&&(!n.button||n.type!=="click"))for(s=n.target;s!=this;s=s.parentNode||this)if(s.disabled!==!0||n.type!=="click"){u={},f=[];for(r=0;r<m;r++)c=d[r],h=c.selector,u[h]===t&&(u[h]=c.needsContext?v(h,this).index(s)>=0:v.find(h,this,null,[s]).length),u[h]&&f.push(c);f.length&&w.push({elem:s,matches:f})}d.length>m&&w.push({elem:this,matches:d.slice(m)});for(r=0;r<w.length&&!n.isPropagationStopped();r++){a=w[r],n.currentTarget=a.elem;for(i=0;i<a.matches.length&&!n.isImmediatePropagationStopped();i++){c=a.matches[i];if(y||!n.namespace&&!c.namespace||n.namespace_re&&n.namespace_re.test(c.namespace))n.data=c.data,n.handleObj=c,o=((v.event.special[c.origType]||{}).handle||c.handler).apply(a.elem,g),o!==t&&(n.result=o,o===!1&&(n.preventDefault(),n.stopPropagation()))}}return b.postDispatch&&b.postDispatch.call(this,n),n.result},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return e.which==null&&(e.which=t.charCode!=null?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,s,o,u=n.button,a=n.fromElement;return e.pageX==null&&n.clientX!=null&&(r=e.target.ownerDocument||i,s=r.documentElement,o=r.body,e.pageX=n.clientX+(s&&s.scrollLeft||o&&o.scrollLeft||0)-(s&&s.clientLeft||o&&o.clientLeft||0),e.pageY=n.clientY+(s&&s.scrollTop||o&&o.scrollTop||0)-(s&&s.clientTop||o&&o.clientTop||0)),!e.relatedTarget&&a&&(e.relatedTarget=a===e.target?n.toElement:a),!e.which&&u!==t&&(e.which=u&1?1:u&2?3:u&4?2:0),e}},fix:function(e){if(e[v.expando])return e;var t,n,r=e,s=v.event.fixHooks[e.type]||{},o=s.props?this.props.concat(s.props):this.props;e=v.Event(r);for(t=o.length;t;)n=o[--t],e[n]=r[n];return e.target||(e.target=r.srcElement||i),e.target.nodeType===3&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,r):e},special:{load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(e,t,n){v.isWindow(this)&&(this.onbeforeunload=n)},teardown:function(e,t){this.onbeforeunload===t&&(this.onbeforeunload=null)}}},simulate:function(e,t,n,r){var i=v.extend(new v.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?v.event.trigger(i,null,t):v.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},v.event.handle=v.event.dispatch,v.removeEvent=i.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]=="undefined"&&(e[r]=null),e.detachEvent(r,n))},v.Event=function(e,t){if(!(this instanceof v.Event))return new v.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?tt:et):this.type=e,t&&v.extend(this,t),this.timeStamp=e&&e.timeStamp||v.now(),this[v.expando]=!0},v.Event.prototype={preventDefault:function(){this.isDefaultPrevented=tt;var e=this.originalEvent;if(!e)return;e.preventDefault?e.preventDefault():e.returnValue=!1},stopPropagation:function(){this.isPropagationStopped=tt;var e=this.originalEvent;if(!e)return;e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=tt,this.stopPropagation()},isDefaultPrevented:et,isPropagationStopped:et,isImmediatePropagationStopped:et},v.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){v.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,s=e.handleObj,o=s.selector;if(!i||i!==r&&!v.contains(r,i))e.type=s.origType,n=s.handler.apply(this,arguments),e.type=t;return n}}}),v.support.submitBubbles||(v.event.special.submit={setup:function(){if(v.nodeName(this,"form"))return!1;v.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=v.nodeName(n,"input")||v.nodeName(n,"button")?n.form:t;r&&!v._data(r,"_submit_attached")&&(v.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),v._data(r,"_submit_attached",!0))})},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&v.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){if(v.nodeName(this,"form"))return!1;v.event.remove(this,"._submit")}}),v.support.changeBubbles||(v.event.special.change={setup:function(){if($.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")v.event.add(this,"propertychange._change",function(e){e.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),v.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),v.event.simulate("change",this,e,!0)});return!1}v.event.add(this,"beforeactivate._change",function(e){var t=e.target;$.test(t.nodeName)&&!v._data(t,"_change_attached")&&(v.event.add(t,"change._change",function(e){this.parentNode&&!e.isSimulated&&!e.isTrigger&&v.event.simulate("change",this.parentNode,e,!0)}),v._data(t,"_change_attached",!0))})},handle:function(e){var t=e.target;if(this!==t||e.isSimulated||e.isTrigger||t.type!=="radio"&&t.type!=="checkbox")return e.handleObj.handler.apply(this,arguments)},teardown:function(){return v.event.remove(this,"._change"),!$.test(this.nodeName)}}),v.support.focusinBubbles||v.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){v.event.simulate(t,e.target,v.event.fix(e),!0)};v.event.special[t]={setup:function(){n++===0&&i.addEventListener(e,r,!0)},teardown:function(){--n===0&&i.removeEventListener(e,r,!0)}}}),v.fn.extend({on:function(e,n,r,i,s){var o,u;if(typeof e=="object"){typeof n!="string"&&(r=r||n,n=t);for(u in e)this.on(u,n,r,e[u],s);return this}r==null&&i==null?(i=n,r=n=t):i==null&&(typeof n=="string"?(i=r,r=t):(i=r,r=n,n=t));if(i===!1)i=et;else if(!i)return this;return s===1&&(o=i,i=function(e){return v().off(e),o.apply(this,arguments)},i.guid=o.guid||(o.guid=v.guid++)),this.each(function(){v.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,s;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,v(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if(typeof e=="object"){for(s in e)this.off(s,n,e[s]);return this}if(n===!1||typeof n=="function")r=n,n=t;return r===!1&&(r=et),this.each(function(){v.event.remove(this,e,r,n)})},bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},live:function(e,t,n){return v(this.context).on(e,this.selector,t,n),this},die:function(e,t){return v(this.context).off(e,this.selector||"**",t),this},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return arguments.length===1?this.off(e,"**"):this.off(t,e||"**",n)},trigger:function(e,t){return this.each(function(){v.event.trigger(e,t,this)})},triggerHandler:function(e,t){if(this[0])return v.event.trigger(e,t,this[0],!0)},toggle:function(e){var t=arguments,n=e.guid||v.guid++,r=0,i=function(n){var i=(v._data(this,"lastToggle"+e.guid)||0)%r;return v._data(this,"lastToggle"+e.guid,i+1),n.preventDefault(),t[i].apply(this,arguments)||!1};i.guid=n;while(r<t.length)t[r++].guid=n;return this.click(i)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),v.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(e,t){v.fn[t]=function(e,n){return n==null&&(n=e,e=null),arguments.length>0?this.on(t,null,e,n):this.trigger(t)},Q.test(t)&&(v.event.fixHooks[t]=v.event.keyHooks),G.test(t)&&(v.event.fixHooks[t]=v.event.mouseHooks)}),function(e,t){function nt(e,t,n,r){n=n||[],t=t||g;var i,s,a,f,l=t.nodeType;if(!e||typeof e!="string")return n;if(l!==1&&l!==9)return[];a=o(t);if(!a&&!r)if(i=R.exec(e))if(f=i[1]){if(l===9){s=t.getElementById(f);if(!s||!s.parentNode)return n;if(s.id===f)return n.push(s),n}else if(t.ownerDocument&&(s=t.ownerDocument.getElementById(f))&&u(t,s)&&s.id===f)return n.push(s),n}else{if(i[2])return S.apply(n,x.call(t.getElementsByTagName(e),0)),n;if((f=i[3])&&Z&&t.getElementsByClassName)return S.apply(n,x.call(t.getElementsByClassName(f),0)),n}return vt(e.replace(j,"$1"),t,n,r,a)}function rt(e){return function(t){var n=t.nodeName.toLowerCase();return n==="input"&&t.type===e}}function it(e){return function(t){var n=t.nodeName.toLowerCase();return(n==="input"||n==="button")&&t.type===e}}function st(e){return N(function(t){return t=+t,N(function(n,r){var i,s=e([],n.length,t),o=s.length;while(o--)n[i=s[o]]&&(n[i]=!(r[i]=n[i]))})})}function ot(e,t,n){if(e===t)return n;var r=e.nextSibling;while(r){if(r===t)return-1;r=r.nextSibling}return 1}function ut(e,t){var n,r,s,o,u,a,f,l=L[d][e+" "];if(l)return t?0:l.slice(0);u=e,a=[],f=i.preFilter;while(u){if(!n||(r=F.exec(u)))r&&(u=u.slice(r[0].length)||u),a.push(s=[]);n=!1;if(r=I.exec(u))s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=r[0].replace(j," ");for(o in i.filter)(r=J[o].exec(u))&&(!f[o]||(r=f[o](r)))&&(s.push(n=new m(r.shift())),u=u.slice(n.length),n.type=o,n.matches=r);if(!n)break}return t?u.length:u?nt.error(e):L(e,a).slice(0)}function at(e,t,r){var i=t.dir,s=r&&t.dir==="parentNode",o=w++;return t.first?function(t,n,r){while(t=t[i])if(s||t.nodeType===1)return e(t,n,r)}:function(t,r,u){if(!u){var a,f=b+" "+o+" ",l=f+n;while(t=t[i])if(s||t.nodeType===1){if((a=t[d])===l)return t.sizset;if(typeof a=="string"&&a.indexOf(f)===0){if(t.sizset)return t}else{t[d]=l;if(e(t,r,u))return t.sizset=!0,t;t.sizset=!1}}}else while(t=t[i])if(s||t.nodeType===1)if(e(t,r,u))return t}}function ft(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function lt(e,t,n,r,i){var s,o=[],u=0,a=e.length,f=t!=null;for(;u<a;u++)if(s=e[u])if(!n||n(s,r,i))o.push(s),f&&t.push(u);return o}function ct(e,t,n,r,i,s){return r&&!r[d]&&(r=ct(r)),i&&!i[d]&&(i=ct(i,s)),N(function(s,o,u,a){var f,l,c,h=[],p=[],d=o.length,v=s||dt(t||"*",u.nodeType?[u]:u,[]),m=e&&(s||!t)?lt(v,h,e,u,a):v,g=n?i||(s?e:d||r)?[]:o:m;n&&n(m,g,u,a);if(r){f=lt(g,p),r(f,[],u,a),l=f.length;while(l--)if(c=f[l])g[p[l]]=!(m[p[l]]=c)}if(s){if(i||e){if(i){f=[],l=g.length;while(l--)(c=g[l])&&f.push(m[l]=c);i(null,g=[],f,a)}l=g.length;while(l--)(c=g[l])&&(f=i?T.call(s,c):h[l])>-1&&(s[f]=!(o[f]=c))}}else g=lt(g===o?g.splice(d,g.length):g),i?i(null,o,g,a):S.apply(o,g)})}function ht(e){var t,n,r,s=e.length,o=i.relative[e[0].type],u=o||i.relative[" "],a=o?1:0,f=at(function(e){return e===t},u,!0),l=at(function(e){return T.call(t,e)>-1},u,!0),h=[function(e,n,r){return!o&&(r||n!==c)||((t=n).nodeType?f(e,n,r):l(e,n,r))}];for(;a<s;a++)if(n=i.relative[e[a].type])h=[at(ft(h),n)];else{n=i.filter[e[a].type].apply(null,e[a].matches);if(n[d]){r=++a;for(;r<s;r++)if(i.relative[e[r].type])break;return ct(a>1&&ft(h),a>1&&e.slice(0,a-1).join("").replace(j,"$1"),n,a<r&&ht(e.slice(a,r)),r<s&&ht(e=e.slice(r)),r<s&&e.join(""))}h.push(n)}return ft(h)}function pt(e,t){var r=t.length>0,s=e.length>0,o=function(u,a,f,l,h){var p,d,v,m=[],y=0,w="0",x=u&&[],T=h!=null,N=c,C=u||s&&i.find.TAG("*",h&&a.parentNode||a),k=b+=N==null?1:Math.E;T&&(c=a!==g&&a,n=o.el);for(;(p=C[w])!=null;w++){if(s&&p){for(d=0;v=e[d];d++)if(v(p,a,f)){l.push(p);break}T&&(b=k,n=++o.el)}r&&((p=!v&&p)&&y--,u&&x.push(p))}y+=w;if(r&&w!==y){for(d=0;v=t[d];d++)v(x,m,a,f);if(u){if(y>0)while(w--)!x[w]&&!m[w]&&(m[w]=E.call(l));m=lt(m)}S.apply(l,m),T&&!u&&m.length>0&&y+t.length>1&&nt.uniqueSort(l)}return T&&(b=k,c=N),x};return o.el=0,r?N(o):o}function dt(e,t,n){var r=0,i=t.length;for(;r<i;r++)nt(e,t[r],n);return n}function vt(e,t,n,r,s){var o,u,f,l,c,h=ut(e),p=h.length;if(!r&&h.length===1){u=h[0]=h[0].slice(0);if(u.length>2&&(f=u[0]).type==="ID"&&t.nodeType===9&&!s&&i.relative[u[1].type]){t=i.find.ID(f.matches[0].replace($,""),t,s)[0];if(!t)return n;e=e.slice(u.shift().length)}for(o=J.POS.test(e)?-1:u.length-1;o>=0;o--){f=u[o];if(i.relative[l=f.type])break;if(c=i.find[l])if(r=c(f.matches[0].replace($,""),z.test(u[0].type)&&t.parentNode||t,s)){u.splice(o,1),e=r.length&&u.join("");if(!e)return S.apply(n,x.call(r,0)),n;break}}}return a(e,h)(r,t,s,n,z.test(e)),n}function mt(){}var n,r,i,s,o,u,a,f,l,c,h=!0,p="undefined",d=("sizcache"+Math.random()).replace(".",""),m=String,g=e.document,y=g.documentElement,b=0,w=0,E=[].pop,S=[].push,x=[].slice,T=[].indexOf||function(e){var t=0,n=this.length;for(;t<n;t++)if(this[t]===e)return t;return-1},N=function(e,t){return e[d]=t==null||t,e},C=function(){var e={},t=[];return N(function(n,r){return t.push(n)>i.cacheLength&&delete e[t.shift()],e[n+" "]=r},e)},k=C(),L=C(),A=C(),O="[\\x20\\t\\r\\n\\f]",M="(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+",_=M.replace("w","w#"),D="([*^$|!~]?=)",P="\\["+O+"*("+M+")"+O+"*(?:"+D+O+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+_+")|)|)"+O+"*\\]",H=":("+M+")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:"+P+")|[^:]|\\\\.)*|.*))\\)|)",B=":(even|odd|eq|gt|lt|nth|first|last)(?:\\("+O+"*((?:-\\d)?\\d*)"+O+"*\\)|)(?=[^-]|$)",j=new RegExp("^"+O+"+|((?:^|[^\\\\])(?:\\\\.)*)"+O+"+$","g"),F=new RegExp("^"+O+"*,"+O+"*"),I=new RegExp("^"+O+"*([\\x20\\t\\r\\n\\f>+~])"+O+"*"),q=new RegExp(H),R=/^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/,U=/^:not/,z=/[\x20\t\r\n\f]*[+~]/,W=/:not\($/,X=/h\d/i,V=/input|select|textarea|button/i,$=/\\(?!\\)/g,J={ID:new RegExp("^#("+M+")"),CLASS:new RegExp("^\\.("+M+")"),NAME:new RegExp("^\\[name=['\"]?("+M+")['\"]?\\]"),TAG:new RegExp("^("+M.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+H),POS:new RegExp(B,"i"),CHILD:new RegExp("^:(only|nth|first|last)-child(?:\\("+O+"*(even|odd|(([+-]|)(\\d*)n|)"+O+"*(?:([+-]|)"+O+"*(\\d+)|))"+O+"*\\)|)","i"),needsContext:new RegExp("^"+O+"*[>+~]|"+B,"i")},K=function(e){var t=g.createElement("div");try{return e(t)}catch(n){return!1}finally{t=null}},Q=K(function(e){return e.appendChild(g.createComment("")),!e.getElementsByTagName("*").length}),G=K(function(e){return e.innerHTML="<a href='#'></a>",e.firstChild&&typeof e.firstChild.getAttribute!==p&&e.firstChild.getAttribute("href")==="#"}),Y=K(function(e){e.innerHTML="<select></select>";var t=typeof e.lastChild.getAttribute("multiple");return t!=="boolean"&&t!=="string"}),Z=K(function(e){return e.innerHTML="<div class='hidden e'></div><div class='hidden'></div>",!e.getElementsByClassName||!e.getElementsByClassName("e").length?!1:(e.lastChild.className="e",e.getElementsByClassName("e").length===2)}),et=K(function(e){e.id=d+0,e.innerHTML="<a name='"+d+"'></a><div name='"+d+"'></div>",y.insertBefore(e,y.firstChild);var t=g.getElementsByName&&g.getElementsByName(d).length===2+g.getElementsByName(d+0).length;return r=!g.getElementById(d),y.removeChild(e),t});try{x.call(y.childNodes,0)[0].nodeType}catch(tt){x=function(e){var t,n=[];for(;t=this[e];e++)n.push(t);return n}}nt.matches=function(e,t){return nt(e,null,null,t)},nt.matchesSelector=function(e,t){return nt(t,null,null,[e]).length>0},s=nt.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(i===1||i===9||i===11){if(typeof e.textContent=="string")return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=s(e)}else if(i===3||i===4)return e.nodeValue}else for(;t=e[r];r++)n+=s(t);return n},o=nt.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?t.nodeName!=="HTML":!1},u=nt.contains=y.contains?function(e,t){var n=e.nodeType===9?e.documentElement:e,r=t&&t.parentNode;return e===r||!!(r&&r.nodeType===1&&n.contains&&n.contains(r))}:y.compareDocumentPosition?function(e,t){return t&&!!(e.compareDocumentPosition(t)&16)}:function(e,t){while(t=t.parentNode)if(t===e)return!0;return!1},nt.attr=function(e,t){var n,r=o(e);return r||(t=t.toLowerCase()),(n=i.attrHandle[t])?n(e):r||Y?e.getAttribute(t):(n=e.getAttributeNode(t),n?typeof e[t]=="boolean"?e[t]?t:null:n.specified?n.value:null:null)},i=nt.selectors={cacheLength:50,createPseudo:N,match:J,attrHandle:G?{}:{href:function(e){return e.getAttribute("href",2)},type:function(e){return e.getAttribute("type")}},find:{ID:r?function(e,t,n){if(typeof t.getElementById!==p&&!n){var r=t.getElementById(e);return r&&r.parentNode?[r]:[]}}:function(e,n,r){if(typeof n.getElementById!==p&&!r){var i=n.getElementById(e);return i?i.id===e||typeof i.getAttributeNode!==p&&i.getAttributeNode("id").value===e?[i]:t:[]}},TAG:Q?function(e,t){if(typeof t.getElementsByTagName!==p)return t.getElementsByTagName(e)}:function(e,t){var n=t.getElementsByTagName(e);if(e==="*"){var r,i=[],s=0;for(;r=n[s];s++)r.nodeType===1&&i.push(r);return i}return n},NAME:et&&function(e,t){if(typeof t.getElementsByName!==p)return t.getElementsByName(name)},CLASS:Z&&function(e,t,n){if(typeof t.getElementsByClassName!==p&&!n)return t.getElementsByClassName(e)}},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace($,""),e[3]=(e[4]||e[5]||"").replace($,""),e[2]==="~="&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),e[1]==="nth"?(e[2]||nt.error(e[0]),e[3]=+(e[3]?e[4]+(e[5]||1):2*(e[2]==="even"||e[2]==="odd")),e[4]=+(e[6]+e[7]||e[2]==="odd")):e[2]&&nt.error(e[0]),e},PSEUDO:function(e){var t,n;if(J.CHILD.test(e[0]))return null;if(e[3])e[2]=e[3];else if(t=e[4])q.test(t)&&(n=ut(t,!0))&&(n=t.indexOf(")",t.length-n)-t.length)&&(t=t.slice(0,n),e[0]=e[0].slice(0,n)),e[2]=t;return e.slice(0,3)}},filter:{ID:r?function(e){return e=e.replace($,""),function(t){return t.getAttribute("id")===e}}:function(e){return e=e.replace($,""),function(t){var n=typeof t.getAttributeNode!==p&&t.getAttributeNode("id");return n&&n.value===e}},TAG:function(e){return e==="*"?function(){return!0}:(e=e.replace($,"").toLowerCase(),function(t){return t.nodeName&&t.nodeName.toLowerCase()===e})},CLASS:function(e){var t=k[d][e+" "];return t||(t=new RegExp("(^|"+O+")"+e+"("+O+"|$)"))&&k(e,function(e){return t.test(e.className||typeof e.getAttribute!==p&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r,i){var s=nt.attr(r,e);return s==null?t==="!=":t?(s+="",t==="="?s===n:t==="!="?s!==n:t==="^="?n&&s.indexOf(n)===0:t==="*="?n&&s.indexOf(n)>-1:t==="$="?n&&s.substr(s.length-n.length)===n:t==="~="?(" "+s+" ").indexOf(n)>-1:t==="|="?s===n||s.substr(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r){return e==="nth"?function(e){var t,i,s=e.parentNode;if(n===1&&r===0)return!0;if(s){i=0;for(t=s.firstChild;t;t=t.nextSibling)if(t.nodeType===1){i++;if(e===t)break}}return i-=r,i===n||i%n===0&&i/n>=0}:function(t){var n=t;switch(e){case"only":case"first":while(n=n.previousSibling)if(n.nodeType===1)return!1;if(e==="first")return!0;n=t;case"last":while(n=n.nextSibling)if(n.nodeType===1)return!1;return!0}}},PSEUDO:function(e,t){var n,r=i.pseudos[e]||i.setFilters[e.toLowerCase()]||nt.error("unsupported pseudo: "+e);return r[d]?r(t):r.length>1?(n=[e,e,"",t],i.setFilters.hasOwnProperty(e.toLowerCase())?N(function(e,n){var i,s=r(e,t),o=s.length;while(o--)i=T.call(e,s[o]),e[i]=!(n[i]=s[o])}):function(e){return r(e,0,n)}):r}},pseudos:{not:N(function(e){var t=[],n=[],r=a(e.replace(j,"$1"));return r[d]?N(function(e,t,n,i){var s,o=r(e,null,i,[]),u=e.length;while(u--)if(s=o[u])e[u]=!(t[u]=s)}):function(e,i,s){return t[0]=e,r(t,null,s,n),!n.pop()}}),has:N(function(e){return function(t){return nt(e,t).length>0}}),contains:N(function(e){return function(t){return(t.textContent||t.innerText||s(t)).indexOf(e)>-1}}),enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&!!e.checked||t==="option"&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},parent:function(e){return!i.pseudos.empty(e)},empty:function(e){var t;e=e.firstChild;while(e){if(e.nodeName>"@"||(t=e.nodeType)===3||t===4)return!1;e=e.nextSibling}return!0},header:function(e){return X.test(e.nodeName)},text:function(e){var t,n;return e.nodeName.toLowerCase()==="input"&&(t=e.type)==="text"&&((n=e.getAttribute("type"))==null||n.toLowerCase()===t)},radio:rt("radio"),checkbox:rt("checkbox"),file:rt("file"),password:rt("password"),image:rt("image"),submit:it("submit"),reset:it("reset"),button:function(e){var t=e.nodeName.toLowerCase();return t==="input"&&e.type==="button"||t==="button"},input:function(e){return V.test(e.nodeName)},focus:function(e){var t=e.ownerDocument;return e===t.activeElement&&(!t.hasFocus||t.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},active:function(e){return e===e.ownerDocument.activeElement},first:st(function(){return[0]}),last:st(function(e,t){return[t-1]}),eq:st(function(e,t,n){return[n<0?n+t:n]}),even:st(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:st(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:st(function(e,t,n){for(var r=n<0?n+t:n;--r>=0;)e.push(r);return e}),gt:st(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}},f=y.compareDocumentPosition?function(e,t){return e===t?(l=!0,0):(!e.compareDocumentPosition||!t.compareDocumentPosition?e.compareDocumentPosition:e.compareDocumentPosition(t)&4)?-1:1}:function(e,t){if(e===t)return l=!0,0;if(e.sourceIndex&&t.sourceIndex)return e.sourceIndex-t.sourceIndex;var n,r,i=[],s=[],o=e.parentNode,u=t.parentNode,a=o;if(o===u)return ot(e,t);if(!o)return-1;if(!u)return 1;while(a)i.unshift(a),a=a.parentNode;a=u;while(a)s.unshift(a),a=a.parentNode;n=i.length,r=s.length;for(var f=0;f<n&&f<r;f++)if(i[f]!==s[f])return ot(i[f],s[f]);return f===n?ot(e,s[f],-1):ot(i[f],t,1)},[0,0].sort(f),h=!l,nt.uniqueSort=function(e){var t,n=[],r=1,i=0;l=h,e.sort(f);if(l){for(;t=e[r];r++)t===e[r-1]&&(i=n.push(r));while(i--)e.splice(n[i],1)}return e},nt.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},a=nt.compile=function(e,t){var n,r=[],i=[],s=A[d][e+" "];if(!s){t||(t=ut(e)),n=t.length;while(n--)s=ht(t[n]),s[d]?r.push(s):i.push(s);s=A(e,pt(i,r))}return s},g.querySelectorAll&&function(){var e,t=vt,n=/'|\\/g,r=/\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g,i=[":focus"],s=[":active"],u=y.matchesSelector||y.mozMatchesSelector||y.webkitMatchesSelector||y.oMatchesSelector||y.msMatchesSelector;K(function(e){e.innerHTML="<select><option selected=''></option></select>",e.querySelectorAll("[selected]").length||i.push("\\["+O+"*(?:checked|disabled|ismap|multiple|readonly|selected|value)"),e.querySelectorAll(":checked").length||i.push(":checked")}),K(function(e){e.innerHTML="<p test=''></p>",e.querySelectorAll("[test^='']").length&&i.push("[*^$]="+O+"*(?:\"\"|'')"),e.innerHTML="<input type='hidden'/>",e.querySelectorAll(":enabled").length||i.push(":enabled",":disabled")}),i=new RegExp(i.join("|")),vt=function(e,r,s,o,u){if(!o&&!u&&!i.test(e)){var a,f,l=!0,c=d,h=r,p=r.nodeType===9&&e;if(r.nodeType===1&&r.nodeName.toLowerCase()!=="object"){a=ut(e),(l=r.getAttribute("id"))?c=l.replace(n,"\\$&"):r.setAttribute("id",c),c="[id='"+c+"'] ",f=a.length;while(f--)a[f]=c+a[f].join("");h=z.test(e)&&r.parentNode||r,p=a.join(",")}if(p)try{return S.apply(s,x.call(h.querySelectorAll(p),0)),s}catch(v){}finally{l||r.removeAttribute("id")}}return t(e,r,s,o,u)},u&&(K(function(t){e=u.call(t,"div");try{u.call(t,"[test!='']:sizzle"),s.push("!=",H)}catch(n){}}),s=new RegExp(s.join("|")),nt.matchesSelector=function(t,n){n=n.replace(r,"='$1']");if(!o(t)&&!s.test(n)&&!i.test(n))try{var a=u.call(t,n);if(a||e||t.document&&t.document.nodeType!==11)return a}catch(f){}return nt(n,null,null,[t]).length>0})}(),i.pseudos.nth=i.pseudos.eq,i.filters=mt.prototype=i.pseudos,i.setFilters=new mt,nt.attr=v.attr,v.find=nt,v.expr=nt.selectors,v.expr[":"]=v.expr.pseudos,v.unique=nt.uniqueSort,v.text=nt.getText,v.isXMLDoc=nt.isXML,v.contains=nt.contains}(e);var nt=/Until$/,rt=/^(?:parents|prev(?:Until|All))/,it=/^.[^:#\[\.,]*$/,st=v.expr.match.needsContext,ot={children:!0,contents:!0,next:!0,prev:!0};v.fn.extend({find:function(e){var t,n,r,i,s,o,u=this;if(typeof e!="string")return v(e).filter(function(){for(t=0,n=u.length;t<n;t++)if(v.contains(u[t],this))return!0});o=this.pushStack("","find",e);for(t=0,n=this.length;t<n;t++){r=o.length,v.find(e,this[t],o);if(t>0)for(i=r;i<o.length;i++)for(s=0;s<r;s++)if(o[s]===o[i]){o.splice(i--,1);break}}return o},has:function(e){var t,n=v(e,this),r=n.length;return this.filter(function(){for(t=0;t<r;t++)if(v.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e,!1),"not",e)},filter:function(e){return this.pushStack(ft(this,e,!0),"filter",e)},is:function(e){return!!e&&(typeof e=="string"?st.test(e)?v(e,this.context).index(this[0])>=0:v.filter(e,this).length>0:this.filter(e).length>0)},closest:function(e,t){var n,r=0,i=this.length,s=[],o=st.test(e)||typeof e!="string"?v(e,t||this.context):0;for(;r<i;r++){n=this[r];while(n&&n.ownerDocument&&n!==t&&n.nodeType!==11){if(o?o.index(n)>-1:v.find.matchesSelector(n,e)){s.push(n);break}n=n.parentNode}}return s=s.length>1?v.unique(s):s,this.pushStack(s,"closest",e)},index:function(e){return e?typeof e=="string"?v.inArray(this[0],v(e)):v.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.prevAll().length:-1},add:function(e,t){var n=typeof e=="string"?v(e,t):v.makeArray(e&&e.nodeType?[e]:e),r=v.merge(this.get(),n);return this.pushStack(ut(n[0])||ut(r[0])?r:v.unique(r))},addBack:function(e){return this.add(e==null?this.prevObject:this.prevObject.filter(e))}}),v.fn.andSelf=v.fn.addBack,v.each({parent:function(e){var t=e.parentNode;return t&&t.nodeType!==11?t:null},parents:function(e){return v.dir(e,"parentNode")},parentsUntil:function(e,t,n){return v.dir(e,"parentNode",n)},next:function(e){return at(e,"nextSibling")},prev:function(e){return at(e,"previousSibling")},nextAll:function(e){return v.dir(e,"nextSibling")},prevAll:function(e){return v.dir(e,"previousSibling")},nextUntil:function(e,t,n){return v.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return v.dir(e,"previousSibling",n)},siblings:function(e){return v.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return v.sibling(e.firstChild)},contents:function(e){return v.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:v.merge([],e.childNodes)}},function(e,t){v.fn[e]=function(n,r){var i=v.map(this,t,n);return nt.test(e)||(r=n),r&&typeof r=="string"&&(i=v.filter(r,i)),i=this.length>1&&!ot[e]?v.unique(i):i,this.length>1&&rt.test(e)&&(i=i.reverse()),this.pushStack(i,e,l.call(arguments).join(","))}}),v.extend({filter:function(e,t,n){return n&&(e=":not("+e+")"),t.length===1?v.find.matchesSelector(t[0],e)?[t[0]]:[]:v.find.matches(e,t)},dir:function(e,n,r){var i=[],s=e[n];while(s&&s.nodeType!==9&&(r===t||s.nodeType!==1||!v(s).is(r)))s.nodeType===1&&i.push(s),s=s[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)e.nodeType===1&&e!==t&&n.push(e);return n}});var ct="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",ht=/ jQuery\d+="(?:null|\d+)"/g,pt=/^\s+/,dt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,vt=/<([\w:]+)/,mt=/<tbody/i,gt=/<|&#?\w+;/,yt=/<(?:script|style|link)/i,bt=/<(?:script|object|embed|option|style)/i,wt=new RegExp("<(?:"+ct+")[\\s/>]","i"),Et=/^(?:checkbox|radio)$/,St=/checked\s*(?:[^=]|=\s*.checked.)/i,xt=/\/(java|ecma)script/i,Tt=/^\s*<!(?:\[CDATA\[|\-\-)|[\]\-]{2}>\s*$/g,Nt={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},Ct=lt(i),kt=Ct.appendChild(i.createElement("div"));Nt.optgroup=Nt.option,Nt.tbody=Nt.tfoot=Nt.colgroup=Nt.caption=Nt.thead,Nt.th=Nt.td,v.support.htmlSerialize||(Nt._default=[1,"X<div>","</div>"]),v.fn.extend({text:function(e){return v.access(this,function(e){return e===t?v.text(this):this.empty().append((this[0]&&this[0].ownerDocument||i).createTextNode(e))},null,e,arguments.length)},wrapAll:function(e){if(v.isFunction(e))return this.each(function(t){v(this).wrapAll(e.call(this,t))});if(this[0]){var t=v(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&e.firstChild.nodeType===1)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return v.isFunction(e)?this.each(function(t){v(this).wrapInner(e.call(this,t))}):this.each(function(){var t=v(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=v.isFunction(e);return this.each(function(n){v(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){v.nodeName(this,"body")||v(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.appendChild(e)})},prepend:function(){return this.domManip(arguments,!0,function(e){(this.nodeType===1||this.nodeType===11)&&this.insertBefore(e,this.firstChild)})},before:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(e,this),"before",this.selector)}},after:function(){if(!ut(this[0]))return this.domManip(arguments,!1,function(e){this.parentNode.insertBefore(e,this.nextSibling)});if(arguments.length){var e=v.clean(arguments);return this.pushStack(v.merge(this,e),"after",this.selector)}},remove:function(e,t){var n,r=0;for(;(n=this[r])!=null;r++)if(!e||v.filter(e,[n]).length)!t&&n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),v.cleanData([n])),n.parentNode&&n.parentNode.removeChild(n);return this},empty:function(){var e,t=0;for(;(e=this[t])!=null;t++){e.nodeType===1&&v.cleanData(e.getElementsByTagName("*"));while(e.firstChild)e.removeChild(e.firstChild)}return this},clone:function(e,t){return e=e==null?!1:e,t=t==null?e:t,this.map(function(){return v.clone(this,e,t)})},html:function(e){return v.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return n.nodeType===1?n.innerHTML.replace(ht,""):t;if(typeof e=="string"&&!yt.test(e)&&(v.support.htmlSerialize||!wt.test(e))&&(v.support.leadingWhitespace||!pt.test(e))&&!Nt[(vt.exec(e)||["",""])[1].toLowerCase()]){e=e.replace(dt,"<$1></$2>");try{for(;r<i;r++)n=this[r]||{},n.nodeType===1&&(v.cleanData(n.getElementsByTagName("*")),n.innerHTML=e);n=0}catch(s){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(e){return ut(this[0])?this.length?this.pushStack(v(v.isFunction(e)?e():e),"replaceWith",e):this:v.isFunction(e)?this.each(function(t){var n=v(this),r=n.html();n.replaceWith(e.call(this,t,r))}):(typeof e!="string"&&(e=v(e).detach()),this.each(function(){var t=this.nextSibling,n=this.parentNode;v(this).remove(),t?v(t).before(e):v(n).append(e)}))},detach:function(e){return this.remove(e,!0)},domManip:function(e,n,r){e=[].concat.apply([],e);var i,s,o,u,a=0,f=e[0],l=[],c=this.length;if(!v.support.checkClone&&c>1&&typeof f=="string"&&St.test(f))return this.each(function(){v(this).domManip(e,n,r)});if(v.isFunction(f))return this.each(function(i){var s=v(this);e[0]=f.call(this,i,n?s.html():t),s.domManip(e,n,r)});if(this[0]){i=v.buildFragment(e,this,l),o=i.fragment,s=o.firstChild,o.childNodes.length===1&&(o=s);if(s){n=n&&v.nodeName(s,"tr");for(u=i.cacheable||c-1;a<c;a++)r.call(n&&v.nodeName(this[a],"table")?Lt(this[a],"tbody"):this[a],a===u?o:v.clone(o,!0,!0))}o=s=null,l.length&&v.each(l,function(e,t){t.src?v.ajax?v.ajax({url:t.src,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0}):v.error("no ajax"):v.globalEval((t.text||t.textContent||t.innerHTML||"").replace(Tt,"")),t.parentNode&&t.parentNode.removeChild(t)})}return this}}),v.buildFragment=function(e,n,r){var s,o,u,a=e[0];return n=n||i,n=!n.nodeType&&n[0]||n,n=n.ownerDocument||n,e.length===1&&typeof a=="string"&&a.length<512&&n===i&&a.charAt(0)==="<"&&!bt.test(a)&&(v.support.checkClone||!St.test(a))&&(v.support.html5Clone||!wt.test(a))&&(o=!0,s=v.fragments[a],u=s!==t),s||(s=n.createDocumentFragment(),v.clean(e,n,s,r),o&&(v.fragments[a]=u&&s)),{fragment:s,cacheable:o}},v.fragments={},v.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){v.fn[e]=function(n){var r,i=0,s=[],o=v(n),u=o.length,a=this.length===1&&this[0].parentNode;if((a==null||a&&a.nodeType===11&&a.childNodes.length===1)&&u===1)return o[t](this[0]),this;for(;i<u;i++)r=(i>0?this.clone(!0):this).get(),v(o[i])[t](r),s=s.concat(r);return this.pushStack(s,e,o.selector)}}),v.extend({clone:function(e,t,n){var r,i,s,o;v.support.html5Clone||v.isXMLDoc(e)||!wt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(kt.innerHTML=e.outerHTML,kt.removeChild(o=kt.firstChild));if((!v.support.noCloneEvent||!v.support.noCloneChecked)&&(e.nodeType===1||e.nodeType===11)&&!v.isXMLDoc(e)){Ot(e,o),r=Mt(e),i=Mt(o);for(s=0;r[s];++s)i[s]&&Ot(r[s],i[s])}if(t){At(e,o);if(n){r=Mt(e),i=Mt(o);for(s=0;r[s];++s)At(r[s],i[s])}}return r=i=null,o},clean:function(e,t,n,r){var s,o,u,a,f,l,c,h,p,d,m,g,y=t===i&&Ct,b=[];if(!t||typeof t.createDocumentFragment=="undefined")t=i;for(s=0;(u=e[s])!=null;s++){typeof u=="number"&&(u+="");if(!u)continue;if(typeof u=="string")if(!gt.test(u))u=t.createTextNode(u);else{y=y||lt(t),c=t.createElement("div"),y.appendChild(c),u=u.replace(dt,"<$1></$2>"),a=(vt.exec(u)||["",""])[1].toLowerCase(),f=Nt[a]||Nt._default,l=f[0],c.innerHTML=f[1]+u+f[2];while(l--)c=c.lastChild;if(!v.support.tbody){h=mt.test(u),p=a==="table"&&!h?c.firstChild&&c.firstChild.childNodes:f[1]==="<table>"&&!h?c.childNodes:[];for(o=p.length-1;o>=0;--o)v.nodeName(p[o],"tbody")&&!p[o].childNodes.length&&p[o].parentNode.removeChild(p[o])}!v.support.leadingWhitespace&&pt.test(u)&&c.insertBefore(t.createTextNode(pt.exec(u)[0]),c.firstChild),u=c.childNodes,c.parentNode.removeChild(c)}u.nodeType?b.push(u):v.merge(b,u)}c&&(u=c=y=null);if(!v.support.appendChecked)for(s=0;(u=b[s])!=null;s++)v.nodeName(u,"input")?_t(u):typeof u.getElementsByTagName!="undefined"&&v.grep(u.getElementsByTagName("input"),_t);if(n){m=function(e){if(!e.type||xt.test(e.type))return r?r.push(e.parentNode?e.parentNode.removeChild(e):e):n.appendChild(e)};for(s=0;(u=b[s])!=null;s++)if(!v.nodeName(u,"script")||!m(u))n.appendChild(u),typeof u.getElementsByTagName!="undefined"&&(g=v.grep(v.merge([],u.getElementsByTagName("script")),m),b.splice.apply(b,[s+1,0].concat(g)),s+=g.length)}return b},cleanData:function(e,t){var n,r,i,s,o=0,u=v.expando,a=v.cache,f=v.support.deleteExpando,l=v.event.special;for(;(i=e[o])!=null;o++)if(t||v.acceptData(i)){r=i[u],n=r&&a[r];if(n){if(n.events)for(s in n.events)l[s]?v.event.remove(i,s):v.removeEvent(i,s,n.handle);a[r]&&(delete a[r],f?delete i[u]:i.removeAttribute?i.removeAttribute(u):i[u]=null,v.deletedIds.push(r))}}}}),function(){var e,t;v.uaMatch=function(e){e=e.toLowerCase();var t=/(chrome)[ \/]([\w.]+)/.exec(e)||/(webkit)[ \/]([\w.]+)/.exec(e)||/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(e)||/(msie) ([\w.]+)/.exec(e)||e.indexOf("compatible")<0&&/(mozilla)(?:.*? rv:([\w.]+)|)/.exec(e)||[];return{browser:t[1]||"",version:t[2]||"0"}},e=v.uaMatch(o.userAgent),t={},e.browser&&(t[e.browser]=!0,t.version=e.version),t.chrome?t.webkit=!0:t.webkit&&(t.safari=!0),v.browser=t,v.sub=function(){function e(t,n){return new e.fn.init(t,n)}v.extend(!0,e,this),e.superclass=this,e.fn=e.prototype=this(),e.fn.constructor=e,e.sub=this.sub,e.fn.init=function(r,i){return i&&i instanceof v&&!(i instanceof e)&&(i=e(i)),v.fn.init.call(this,r,i,t)},e.fn.init.prototype=e.fn;var t=e(i);return e}}();var Dt,Pt,Ht,Bt=/alpha\([^)]*\)/i,jt=/opacity=([^)]*)/,Ft=/^(top|right|bottom|left)$/,It=/^(none|table(?!-c[ea]).+)/,qt=/^margin/,Rt=new RegExp("^("+m+")(.*)$","i"),Ut=new RegExp("^("+m+")(?!px)[a-z%]+$","i"),zt=new RegExp("^([-+])=("+m+")","i"),Wt={BODY:"block"},Xt={position:"absolute",visibility:"hidden",display:"block"},Vt={letterSpacing:0,fontWeight:400},$t=["Top","Right","Bottom","Left"],Jt=["Webkit","O","Moz","ms"],Kt=v.fn.toggle;v.fn.extend({css:function(e,n){return v.access(this,function(e,n,r){return r!==t?v.style(e,n,r):v.css(e,n)},e,n,arguments.length>1)},show:function(){return Yt(this,!0)},hide:function(){return Yt(this)},toggle:function(e,t){var n=typeof e=="boolean";return v.isFunction(e)&&v.isFunction(t)?Kt.apply(this,arguments):this.each(function(){(n?e:Gt(this))?v(this).show():v(this).hide()})}}),v.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Dt(e,"opacity");return n===""?"1":n}}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":v.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(!e||e.nodeType===3||e.nodeType===8||!e.style)return;var s,o,u,a=v.camelCase(n),f=e.style;n=v.cssProps[a]||(v.cssProps[a]=Qt(f,a)),u=v.cssHooks[n]||v.cssHooks[a];if(r===t)return u&&"get"in u&&(s=u.get(e,!1,i))!==t?s:f[n];o=typeof r,o==="string"&&(s=zt.exec(r))&&(r=(s[1]+1)*s[2]+parseFloat(v.css(e,n)),o="number");if(r==null||o==="number"&&isNaN(r))return;o==="number"&&!v.cssNumber[a]&&(r+="px");if(!u||!("set"in u)||(r=u.set(e,r,i))!==t)try{f[n]=r}catch(l){}},css:function(e,n,r,i){var s,o,u,a=v.camelCase(n);return n=v.cssProps[a]||(v.cssProps[a]=Qt(e.style,a)),u=v.cssHooks[n]||v.cssHooks[a],u&&"get"in u&&(s=u.get(e,!0,i)),s===t&&(s=Dt(e,n)),s==="normal"&&n in Vt&&(s=Vt[n]),r||i!==t?(o=parseFloat(s),r||v.isNumeric(o)?o||0:s):s},swap:function(e,t,n){var r,i,s={};for(i in t)s[i]=e.style[i],e.style[i]=t[i];r=n.call(e);for(i in t)e.style[i]=s[i];return r}}),e.getComputedStyle?Dt=function(t,n){var r,i,s,o,u=e.getComputedStyle(t,null),a=t.style;return u&&(r=u.getPropertyValue(n)||u[n],r===""&&!v.contains(t.ownerDocument,t)&&(r=v.style(t,n)),Ut.test(r)&&qt.test(n)&&(i=a.width,s=a.minWidth,o=a.maxWidth,a.minWidth=a.maxWidth=a.width=r,r=u.width,a.width=i,a.minWidth=s,a.maxWidth=o)),r}:i.documentElement.currentStyle&&(Dt=function(e,t){var n,r,i=e.currentStyle&&e.currentStyle[t],s=e.style;return i==null&&s&&s[t]&&(i=s[t]),Ut.test(i)&&!Ft.test(t)&&(n=s.left,r=e.runtimeStyle&&e.runtimeStyle.left,r&&(e.runtimeStyle.left=e.currentStyle.left),s.left=t==="fontSize"?"1em":i,i=s.pixelLeft+"px",s.left=n,r&&(e.runtimeStyle.left=r)),i===""?"auto":i}),v.each(["height","width"],function(e,t){v.cssHooks[t]={get:function(e,n,r){if(n)return e.offsetWidth===0&&It.test(Dt(e,"display"))?v.swap(e,Xt,function(){return tn(e,t,r)}):tn(e,t,r)},set:function(e,n,r){return Zt(e,n,r?en(e,t,r,v.support.boxSizing&&v.css(e,"boxSizing")==="border-box"):0)}}}),v.support.opacity||(v.cssHooks.opacity={get:function(e,t){return jt.test((t&&e.currentStyle?e.currentStyle.filter:e.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":t?"1":""},set:function(e,t){var n=e.style,r=e.currentStyle,i=v.isNumeric(t)?"alpha(opacity="+t*100+")":"",s=r&&r.filter||n.filter||"";n.zoom=1;if(t>=1&&v.trim(s.replace(Bt,""))===""&&n.removeAttribute){n.removeAttribute("filter");if(r&&!r.filter)return}n.filter=Bt.test(s)?s.replace(Bt,i):s+" "+i}}),v(function(){v.support.reliableMarginRight||(v.cssHooks.marginRight={get:function(e,t){return v.swap(e,{display:"inline-block"},function(){if(t)return Dt(e,"marginRight")})}}),!v.support.pixelPosition&&v.fn.position&&v.each(["top","left"],function(e,t){v.cssHooks[t]={get:function(e,n){if(n){var r=Dt(e,t);return Ut.test(r)?v(e).position()[t]+"px":r}}}})}),v.expr&&v.expr.filters&&(v.expr.filters.hidden=function(e){return e.offsetWidth===0&&e.offsetHeight===0||!v.support.reliableHiddenOffsets&&(e.style&&e.style.display||Dt(e,"display"))==="none"},v.expr.filters.visible=function(e){return!v.expr.filters.hidden(e)}),v.each({margin:"",padding:"",border:"Width"},function(e,t){v.cssHooks[e+t]={expand:function(n){var r,i=typeof n=="string"?n.split(" "):[n],s={};for(r=0;r<4;r++)s[e+$t[r]+t]=i[r]||i[r-2]||i[0];return s}},qt.test(e)||(v.cssHooks[e+t].set=Zt)});var rn=/%20/g,sn=/\[\]$/,on=/\r?\n/g,un=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,an=/^(?:select|textarea)/i;v.fn.extend({serialize:function(){return v.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?v.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||an.test(this.nodeName)||un.test(this.type))}).map(function(e,t){var n=v(this).val();return n==null?null:v.isArray(n)?v.map(n,function(e,n){return{name:t.name,value:e.replace(on,"\r\n")}}):{name:t.name,value:n.replace(on,"\r\n")}}).get()}}),v.param=function(e,n){var r,i=[],s=function(e,t){t=v.isFunction(t)?t():t==null?"":t,i[i.length]=encodeURIComponent(e)+"="+encodeURIComponent(t)};n===t&&(n=v.ajaxSettings&&v.ajaxSettings.traditional);if(v.isArray(e)||e.jquery&&!v.isPlainObject(e))v.each(e,function(){s(this.name,this.value)});else for(r in e)fn(r,e[r],n,s);return i.join("&").replace(rn,"+")};var ln,cn,hn=/#.*$/,pn=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,dn=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,vn=/^(?:GET|HEAD)$/,mn=/^\/\//,gn=/\?/,yn=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bn=/([?&])_=[^&]*/,wn=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/,En=v.fn.load,Sn={},xn={},Tn=["*/"]+["*"];try{cn=s.href}catch(Nn){cn=i.createElement("a"),cn.href="",cn=cn.href}ln=wn.exec(cn.toLowerCase())||[],v.fn.load=function(e,n,r){if(typeof e!="string"&&En)return En.apply(this,arguments);if(!this.length)return this;var i,s,o,u=this,a=e.indexOf(" ");return a>=0&&(i=e.slice(a,e.length),e=e.slice(0,a)),v.isFunction(n)?(r=n,n=t):n&&typeof n=="object"&&(s="POST"),v.ajax({url:e,type:s,dataType:"html",data:n,complete:function(e,t){r&&u.each(r,o||[e.responseText,t,e])}}).done(function(e){o=arguments,u.html(i?v("<div>").append(e.replace(yn,"")).find(i):e)}),this},v.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(e,t){v.fn[t]=function(e){return this.on(t,e)}}),v.each(["get","post"],function(e,n){v[n]=function(e,r,i,s){return v.isFunction(r)&&(s=s||i,i=r,r=t),v.ajax({type:n,url:e,data:r,success:i,dataType:s})}}),v.extend({getScript:function(e,n){return v.get(e,t,n,"script")},getJSON:function(e,t,n){return v.get(e,t,n,"json")},ajaxSetup:function(e,t){return t?Ln(e,v.ajaxSettings):(t=e,e=v.ajaxSettings),Ln(e,t),e},ajaxSettings:{url:cn,isLocal:dn.test(ln[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":Tn},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":e.String,"text html":!0,"text json":v.parseJSON,"text xml":v.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:Cn(Sn),ajaxTransport:Cn(xn),ajax:function(e,n){function T(e,n,s,a){var l,y,b,w,S,T=n;if(E===2)return;E=2,u&&clearTimeout(u),o=t,i=a||"",x.readyState=e>0?4:0,s&&(w=An(c,x,s));if(e>=200&&e<300||e===304)c.ifModified&&(S=x.getResponseHeader("Last-Modified"),S&&(v.lastModified[r]=S),S=x.getResponseHeader("Etag"),S&&(v.etag[r]=S)),e===304?(T="notmodified",l=!0):(l=On(c,w),T=l.state,y=l.data,b=l.error,l=!b);else{b=T;if(!T||e)T="error",e<0&&(e=0)}x.status=e,x.statusText=(n||T)+"",l?d.resolveWith(h,[y,T,x]):d.rejectWith(h,[x,T,b]),x.statusCode(g),g=t,f&&p.trigger("ajax"+(l?"Success":"Error"),[x,c,l?y:b]),m.fireWith(h,[x,T]),f&&(p.trigger("ajaxComplete",[x,c]),--v.active||v.event.trigger("ajaxStop"))}typeof e=="object"&&(n=e,e=t),n=n||{};var r,i,s,o,u,a,f,l,c=v.ajaxSetup({},n),h=c.context||c,p=h!==c&&(h.nodeType||h instanceof v)?v(h):v.event,d=v.Deferred(),m=v.Callbacks("once memory"),g=c.statusCode||{},b={},w={},E=0,S="canceled",x={readyState:0,setRequestHeader:function(e,t){if(!E){var n=e.toLowerCase();e=w[n]=w[n]||e,b[e]=t}return this},getAllResponseHeaders:function(){return E===2?i:null},getResponseHeader:function(e){var n;if(E===2){if(!s){s={};while(n=pn.exec(i))s[n[1].toLowerCase()]=n[2]}n=s[e.toLowerCase()]}return n===t?null:n},overrideMimeType:function(e){return E||(c.mimeType=e),this},abort:function(e){return e=e||S,o&&o.abort(e),T(0,e),this}};d.promise(x),x.success=x.done,x.error=x.fail,x.complete=m.add,x.statusCode=function(e){if(e){var t;if(E<2)for(t in e)g[t]=[g[t],e[t]];else t=e[x.status],x.always(t)}return this},c.url=((e||c.url)+"").replace(hn,"").replace(mn,ln[1]+"//"),c.dataTypes=v.trim(c.dataType||"*").toLowerCase().split(y),c.crossDomain==null&&(a=wn.exec(c.url.toLowerCase()),c.crossDomain=!(!a||a[1]===ln[1]&&a[2]===ln[2]&&(a[3]||(a[1]==="http:"?80:443))==(ln[3]||(ln[1]==="http:"?80:443)))),c.data&&c.processData&&typeof c.data!="string"&&(c.data=v.param(c.data,c.traditional)),kn(Sn,c,n,x);if(E===2)return x;f=c.global,c.type=c.type.toUpperCase(),c.hasContent=!vn.test(c.type),f&&v.active++===0&&v.event.trigger("ajaxStart");if(!c.hasContent){c.data&&(c.url+=(gn.test(c.url)?"&":"?")+c.data,delete c.data),r=c.url;if(c.cache===!1){var N=v.now(),C=c.url.replace(bn,"$1_="+N);c.url=C+(C===c.url?(gn.test(c.url)?"&":"?")+"_="+N:"")}}(c.data&&c.hasContent&&c.contentType!==!1||n.contentType)&&x.setRequestHeader("Content-Type",c.contentType),c.ifModified&&(r=r||c.url,v.lastModified[r]&&x.setRequestHeader("If-Modified-Since",v.lastModified[r]),v.etag[r]&&x.setRequestHeader("If-None-Match",v.etag[r])),x.setRequestHeader("Accept",c.dataTypes[0]&&c.accepts[c.dataTypes[0]]?c.accepts[c.dataTypes[0]]+(c.dataTypes[0]!=="*"?", "+Tn+"; q=0.01":""):c.accepts["*"]);for(l in c.headers)x.setRequestHeader(l,c.headers[l]);if(!c.beforeSend||c.beforeSend.call(h,x,c)!==!1&&E!==2){S="abort";for(l in{success:1,error:1,complete:1})x[l](c[l]);o=kn(xn,c,n,x);if(!o)T(-1,"No Transport");else{x.readyState=1,f&&p.trigger("ajaxSend",[x,c]),c.async&&c.timeout>0&&(u=setTimeout(function(){x.abort("timeout")},c.timeout));try{E=1,o.send(b,T)}catch(k){if(!(E<2))throw k;T(-1,k)}}return x}return x.abort()},active:0,lastModified:{},etag:{}});var Mn=[],_n=/\?/,Dn=/(=)\?(?=&|$)|\?\?/,Pn=v.now();v.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Mn.pop()||v.expando+"_"+Pn++;return this[e]=!0,e}}),v.ajaxPrefilter("json jsonp",function(n,r,i){var s,o,u,a=n.data,f=n.url,l=n.jsonp!==!1,c=l&&Dn.test(f),h=l&&!c&&typeof a=="string"&&!(n.contentType||"").indexOf("application/x-www-form-urlencoded")&&Dn.test(a);if(n.dataTypes[0]==="jsonp"||c||h)return s=n.jsonpCallback=v.isFunction(n.jsonpCallback)?n.jsonpCallback():n.jsonpCallback,o=e[s],c?n.url=f.replace(Dn,"$1"+s):h?n.data=a.replace(Dn,"$1"+s):l&&(n.url+=(_n.test(f)?"&":"?")+n.jsonp+"="+s),n.converters["script json"]=function(){return u||v.error(s+" was not called"),u[0]},n.dataTypes[0]="json",e[s]=function(){u=arguments},i.always(function(){e[s]=o,n[s]&&(n.jsonpCallback=r.jsonpCallback,Mn.push(s)),u&&v.isFunction(o)&&o(u[0]),u=o=t}),"script"}),v.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(e){return v.globalEval(e),e}}}),v.ajaxPrefilter("script",function(e){e.cache===t&&(e.cache=!1),e.crossDomain&&(e.type="GET",e.global=!1)}),v.ajaxTransport("script",function(e){if(e.crossDomain){var n,r=i.head||i.getElementsByTagName("head")[0]||i.documentElement;return{send:function(s,o){n=i.createElement("script"),n.async="async",e.scriptCharset&&(n.charset=e.scriptCharset),n.src=e.url,n.onload=n.onreadystatechange=function(e,i){if(i||!n.readyState||/loaded|complete/.test(n.readyState))n.onload=n.onreadystatechange=null,r&&n.parentNode&&r.removeChild(n),n=t,i||o(200,"success")},r.insertBefore(n,r.firstChild)},abort:function(){n&&n.onload(0,1)}}}});var Hn,Bn=e.ActiveXObject?function(){for(var e in Hn)Hn[e](0,1)}:!1,jn=0;v.ajaxSettings.xhr=e.ActiveXObject?function(){return!this.isLocal&&Fn()||In()}:Fn,function(e){v.extend(v.support,{ajax:!!e,cors:!!e&&"withCredentials"in e})}(v.ajaxSettings.xhr()),v.support.ajax&&v.ajaxTransport(function(n){if(!n.crossDomain||v.support.cors){var r;return{send:function(i,s){var o,u,a=n.xhr();n.username?a.open(n.type,n.url,n.async,n.username,n.password):a.open(n.type,n.url,n.async);if(n.xhrFields)for(u in n.xhrFields)a[u]=n.xhrFields[u];n.mimeType&&a.overrideMimeType&&a.overrideMimeType(n.mimeType),!n.crossDomain&&!i["X-Requested-With"]&&(i["X-Requested-With"]="XMLHttpRequest");try{for(u in i)a.setRequestHeader(u,i[u])}catch(f){}a.send(n.hasContent&&n.data||null),r=function(e,i){var u,f,l,c,h;try{if(r&&(i||a.readyState===4)){r=t,o&&(a.onreadystatechange=v.noop,Bn&&delete Hn[o]);if(i)a.readyState!==4&&a.abort();else{u=a.status,l=a.getAllResponseHeaders(),c={},h=a.responseXML,h&&h.documentElement&&(c.xml=h);try{c.text=a.responseText}catch(p){}try{f=a.statusText}catch(p){f=""}!u&&n.isLocal&&!n.crossDomain?u=c.text?200:404:u===1223&&(u=204)}}}catch(d){i||s(-1,d)}c&&s(u,f,c,l)},n.async?a.readyState===4?setTimeout(r,0):(o=++jn,Bn&&(Hn||(Hn={},v(e).unload(Bn)),Hn[o]=r),a.onreadystatechange=r):r()},abort:function(){r&&r(0,1)}}}});var qn,Rn,Un=/^(?:toggle|show|hide)$/,zn=new RegExp("^(?:([-+])=|)("+m+")([a-z%]*)$","i"),Wn=/queueHooks$/,Xn=[Gn],Vn={"*":[function(e,t){var n,r,i=this.createTween(e,t),s=zn.exec(t),o=i.cur(),u=+o||0,a=1,f=20;if(s){n=+s[2],r=s[3]||(v.cssNumber[e]?"":"px");if(r!=="px"&&u){u=v.css(i.elem,e,!0)||n||1;do a=a||".5",u/=a,v.style(i.elem,e,u+r);while(a!==(a=i.cur()/o)&&a!==1&&--f)}i.unit=r,i.start=u,i.end=s[1]?u+(s[1]+1)*n:n}return i}]};v.Animation=v.extend(Kn,{tweener:function(e,t){v.isFunction(e)?(t=e,e=["*"]):e=e.split(" ");var n,r=0,i=e.length;for(;r<i;r++)n=e[r],Vn[n]=Vn[n]||[],Vn[n].unshift(t)},prefilter:function(e,t){t?Xn.unshift(e):Xn.push(e)}}),v.Tween=Yn,Yn.prototype={constructor:Yn,init:function(e,t,n,r,i,s){this.elem=e,this.prop=n,this.easing=i||"swing",this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=s||(v.cssNumber[n]?"":"px")},cur:function(){var e=Yn.propHooks[this.prop];return e&&e.get?e.get(this):Yn.propHooks._default.get(this)},run:function(e){var t,n=Yn.propHooks[this.prop];return this.options.duration?this.pos=t=v.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):Yn.propHooks._default.set(this),this}},Yn.prototype.init.prototype=Yn.prototype,Yn.propHooks={_default:{get:function(e){var t;return e.elem[e.prop]==null||!!e.elem.style&&e.elem.style[e.prop]!=null?(t=v.css(e.elem,e.prop,!1,""),!t||t==="auto"?0:t):e.elem[e.prop]},set:function(e){v.fx.step[e.prop]?v.fx.step[e.prop](e):e.elem.style&&(e.elem.style[v.cssProps[e.prop]]!=null||v.cssHooks[e.prop])?v.style(e.elem,e.prop,e.now+e.unit):e.elem[e.prop]=e.now}}},Yn.propHooks.scrollTop=Yn.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},v.each(["toggle","show","hide"],function(e,t){var n=v.fn[t];v.fn[t]=function(r,i,s){return r==null||typeof r=="boolean"||!e&&v.isFunction(r)&&v.isFunction(i)?n.apply(this,arguments):this.animate(Zn(t,!0),r,i,s)}}),v.fn.extend({fadeTo:function(e,t,n,r){return this.filter(Gt).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(e,t,n,r){var i=v.isEmptyObject(e),s=v.speed(t,n,r),o=function(){var t=Kn(this,v.extend({},e),s);i&&t.stop(!0)};return i||s.queue===!1?this.each(o):this.queue(s.queue,o)},stop:function(e,n,r){var i=function(e){var t=e.stop;delete e.stop,t(r)};return typeof e!="string"&&(r=n,n=e,e=t),n&&e!==!1&&this.queue(e||"fx",[]),this.each(function(){var t=!0,n=e!=null&&e+"queueHooks",s=v.timers,o=v._data(this);if(n)o[n]&&o[n].stop&&i(o[n]);else for(n in o)o[n]&&o[n].stop&&Wn.test(n)&&i(o[n]);for(n=s.length;n--;)s[n].elem===this&&(e==null||s[n].queue===e)&&(s[n].anim.stop(r),t=!1,s.splice(n,1));(t||!r)&&v.dequeue(this,e)})}}),v.each({slideDown:Zn("show"),slideUp:Zn("hide"),slideToggle:Zn("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,t){v.fn[e]=function(e,n,r){return this.animate(t,e,n,r)}}),v.speed=function(e,t,n){var r=e&&typeof e=="object"?v.extend({},e):{complete:n||!n&&t||v.isFunction(e)&&e,duration:e,easing:n&&t||t&&!v.isFunction(t)&&t};r.duration=v.fx.off?0:typeof r.duration=="number"?r.duration:r.duration in v.fx.speeds?v.fx.speeds[r.duration]:v.fx.speeds._default;if(r.queue==null||r.queue===!0)r.queue="fx";return r.old=r.complete,r.complete=function(){v.isFunction(r.old)&&r.old.call(this),r.queue&&v.dequeue(this,r.queue)},r},v.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2}},v.timers=[],v.fx=Yn.prototype.init,v.fx.tick=function(){var e,n=v.timers,r=0;qn=v.now();for(;r<n.length;r++)e=n[r],!e()&&n[r]===e&&n.splice(r--,1);n.length||v.fx.stop(),qn=t},v.fx.timer=function(e){e()&&v.timers.push(e)&&!Rn&&(Rn=setInterval(v.fx.tick,v.fx.interval))},v.fx.interval=13,v.fx.stop=function(){clearInterval(Rn),Rn=null},v.fx.speeds={slow:600,fast:200,_default:400},v.fx.step={},v.expr&&v.expr.filters&&(v.expr.filters.animated=function(e){return v.grep(v.timers,function(t){return e===t.elem}).length});var er=/^(?:body|html)$/i;v.fn.offset=function(e){if(arguments.length)return e===t?this:this.each(function(t){v.offset.setOffset(this,e,t)});var n,r,i,s,o,u,a,f={top:0,left:0},l=this[0],c=l&&l.ownerDocument;if(!c)return;return(r=c.body)===l?v.offset.bodyOffset(l):(n=c.documentElement,v.contains(n,l)?(typeof l.getBoundingClientRect!="undefined"&&(f=l.getBoundingClientRect()),i=tr(c),s=n.clientTop||r.clientTop||0,o=n.clientLeft||r.clientLeft||0,u=i.pageYOffset||n.scrollTop,a=i.pageXOffset||n.scrollLeft,{top:f.top+u-s,left:f.left+a-o}):f)},v.offset={bodyOffset:function(e){var t=e.offsetTop,n=e.offsetLeft;return v.support.doesNotIncludeMarginInBodyOffset&&(t+=parseFloat(v.css(e,"marginTop"))||0,n+=parseFloat(v.css(e,"marginLeft"))||0),{top:t,left:n}},setOffset:function(e,t,n){var r=v.css(e,"position");r==="static"&&(e.style.position="relative");var i=v(e),s=i.offset(),o=v.css(e,"top"),u=v.css(e,"left"),a=(r==="absolute"||r==="fixed")&&v.inArray("auto",[o,u])>-1,f={},l={},c,h;a?(l=i.position(),c=l.top,h=l.left):(c=parseFloat(o)||0,h=parseFloat(u)||0),v.isFunction(t)&&(t=t.call(e,n,s)),t.top!=null&&(f.top=t.top-s.top+c),t.left!=null&&(f.left=t.left-s.left+h),"using"in t?t.using.call(e,f):i.css(f)}},v.fn.extend({position:function(){if(!this[0])return;var e=this[0],t=this.offsetParent(),n=this.offset(),r=er.test(t[0].nodeName)?{top:0,left:0}:t.offset();return n.top-=parseFloat(v.css(e,"marginTop"))||0,n.left-=parseFloat(v.css(e,"marginLeft"))||0,r.top+=parseFloat(v.css(t[0],"borderTopWidth"))||0,r.left+=parseFloat(v.css(t[0],"borderLeftWidth"))||0,{top:n.top-r.top,left:n.left-r.left}},offsetParent:function(){return this.map(function(){var e=this.offsetParent||i.body;while(e&&!er.test(e.nodeName)&&v.css(e,"position")==="static")e=e.offsetParent;return e||i.body})}}),v.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(e,n){var r=/Y/.test(n);v.fn[e]=function(i){return v.access(this,function(e,i,s){var o=tr(e);if(s===t)return o?n in o?o[n]:o.document.documentElement[i]:e[i];o?o.scrollTo(r?v(o).scrollLeft():s,r?s:v(o).scrollTop()):e[i]=s},e,i,arguments.length,null)}}),v.each({Height:"height",Width:"width"},function(e,n){v.each({padding:"inner"+e,content:n,"":"outer"+e},function(r,i){v.fn[i]=function(i,s){var o=arguments.length&&(r||typeof i!="boolean"),u=r||(i===!0||s===!0?"margin":"border");return v.access(this,function(n,r,i){var s;return v.isWindow(n)?n.document.documentElement["client"+e]:n.nodeType===9?(s=n.documentElement,Math.max(n.body["scroll"+e],s["scroll"+e],n.body["offset"+e],s["offset"+e],s["client"+e])):i===t?v.css(n,r,i,u):v.style(n,r,i,u)},n,o?i:t,o,null)}})}),e.jQuery=e.$=v,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return v})})(window);
\ No newline at end of file diff --git a/hugo/js/jquery/jquery-ui-1.9.2.custom.min.js b/hugo/js/jquery/jquery-ui-1.9.2.custom.min.js new file mode 100644 index 0000000..2dc4c48 --- /dev/null +++ b/hugo/js/jquery/jquery-ui-1.9.2.custom.min.js @@ -0,0 +1,6 @@ +/*! jQuery UI - v1.9.2 - 2013-06-24 +* http://jqueryui.com +* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js +* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */ + +(function(e,t){function i(t,n){var r,i,o,u=t.nodeName.toLowerCase();return"area"===u?(r=t.parentNode,i=r.name,!t.href||!i||r.nodeName.toLowerCase()!=="map"?!1:(o=e("img[usemap=#"+i+"]")[0],!!o&&s(o))):(/input|select|textarea|button|object/.test(u)?!t.disabled:"a"===u?t.href||n:n)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().andSelf().filter(function(){return e.css(this,"visibility")==="hidden"}).length}var n=0,r=/^ui-id-\d+$/;e.ui=e.ui||{};if(e.ui.version)return;e.extend(e.ui,{version:"1.9.2",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({_focus:e.fn.focus,focus:function(t,n){return typeof t=="number"?this.each(function(){var r=this;setTimeout(function(){e(r).focus(),n&&n.call(r)},t)}):this._focus.apply(this,arguments)},scrollParent:function(){var t;return e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?t=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):t=this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(n){if(n!==t)return this.css("zIndex",n);if(this.length){var r=e(this[0]),i,s;while(r.length&&r[0]!==document){i=r.css("position");if(i==="absolute"||i==="relative"||i==="fixed"){s=parseInt(r.css("zIndex"),10);if(!isNaN(s)&&s!==0)return s}r=r.parent()}}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++n)})},removeUniqueId:function(){return this.each(function(){r.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(n){return!!e.data(n,t)}}):function(t,n,r){return!!e.data(t,r[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var n=e.attr(t,"tabindex"),r=isNaN(n);return(r||n>=0)&&i(t,!r)}}),e(function(){var t=document.body,n=t.appendChild(n=document.createElement("div"));n.offsetHeight,e.extend(n.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),e.support.minHeight=n.offsetHeight===100,e.support.selectstart="onselectstart"in n,t.removeChild(n).style.display="none"}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(n,r){function u(t,n,r,s){return e.each(i,function(){n-=parseFloat(e.css(t,"padding"+this))||0,r&&(n-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(n-=parseFloat(e.css(t,"margin"+this))||0)}),n}var i=r==="Width"?["Left","Right"]:["Top","Bottom"],s=r.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+r]=function(n){return n===t?o["inner"+r].call(this):this.each(function(){e(this).css(s,u(this,n)+"px")})},e.fn["outer"+r]=function(t,n){return typeof t!="number"?o["outer"+r].call(this,t):this.each(function(){e(this).css(s,u(this,t,!0,n)+"px")})}}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(n){return arguments.length?t.call(this,e.camelCase(n)):t.call(this)}}(e.fn.removeData)),function(){var t=/msie ([\w.]+)/.exec(navigator.userAgent.toLowerCase())||[];e.ui.ie=t.length?!0:!1,e.ui.ie6=parseFloat(t[1],10)===6}(),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,n,r){var i,s=e.ui[t].prototype;for(i in r)s.plugins[i]=s.plugins[i]||[],s.plugins[i].push([n,r[i]])},call:function(e,t,n){var r,i=e.plugins[t];if(!i||!e.element[0].parentNode||e.element[0].parentNode.nodeType===11)return;for(r=0;r<i.length;r++)e.options[i[r][0]]&&i[r][1].apply(e.element,n)}},contains:e.contains,hasScroll:function(t,n){if(e(t).css("overflow")==="hidden")return!1;var r=n&&n==="left"?"scrollLeft":"scrollTop",i=!1;return t[r]>0?!0:(t[r]=1,i=t[r]>0,t[r]=0,i)},isOverAxis:function(e,t,n){return e>t&&e<t+n},isOver:function(t,n,r,i,s,o){return e.ui.isOverAxis(t,r,s)&&e.ui.isOverAxis(n,i,o)}})})(jQuery);(function(e,t){var n=0,r=Array.prototype.slice,i=e.cleanData;e.cleanData=function(t){for(var n=0,r;(r=t[n])!=null;n++)try{e(r).triggerHandler("remove")}catch(s){}i(t)},e.widget=function(t,n,r){var i,s,o,u,a=t.split(".")[0];t=t.split(".")[1],i=a+"-"+t,r||(r=n,n=e.Widget),e.expr[":"][i.toLowerCase()]=function(t){return!!e.data(t,i)},e[a]=e[a]||{},s=e[a][t],o=e[a][t]=function(e,t){if(!this._createWidget)return new o(e,t);arguments.length&&this._createWidget(e,t)},e.extend(o,s,{version:r.version,_proto:e.extend({},r),_childConstructors:[]}),u=new n,u.options=e.widget.extend({},u.options),e.each(r,function(t,i){e.isFunction(i)&&(r[t]=function(){var e=function(){return n.prototype[t].apply(this,arguments)},r=function(e){return n.prototype[t].apply(this,e)};return function(){var t=this._super,n=this._superApply,s;return this._super=e,this._superApply=r,s=i.apply(this,arguments),this._super=t,this._superApply=n,s}}())}),o.prototype=e.widget.extend(u,{widgetEventPrefix:s?u.widgetEventPrefix:t},r,{constructor:o,namespace:a,widgetName:t,widgetBaseClass:i,widgetFullName:i}),s?(e.each(s._childConstructors,function(t,n){var r=n.prototype;e.widget(r.namespace+"."+r.widgetName,o,n._proto)}),delete s._childConstructors):n._childConstructors.push(o),e.widget.bridge(t,o)},e.widget.extend=function(n){var i=r.call(arguments,1),s=0,o=i.length,u,a;for(;s<o;s++)for(u in i[s])a=i[s][u],i[s].hasOwnProperty(u)&&a!==t&&(e.isPlainObject(a)?n[u]=e.isPlainObject(n[u])?e.widget.extend({},n[u],a):e.widget.extend({},a):n[u]=a);return n},e.widget.bridge=function(n,i){var s=i.prototype.widgetFullName||n;e.fn[n]=function(o){var u=typeof o=="string",a=r.call(arguments,1),f=this;return o=!u&&a.length?e.widget.extend.apply(null,[o].concat(a)):o,u?this.each(function(){var r,i=e.data(this,s);if(!i)return e.error("cannot call methods on "+n+" prior to initialization; "+"attempted to call method '"+o+"'");if(!e.isFunction(i[o])||o.charAt(0)==="_")return e.error("no such method '"+o+"' for "+n+" widget instance");r=i[o].apply(i,a);if(r!==i&&r!==t)return f=r&&r.jquery?f.pushStack(r.get()):r,!1}):this.each(function(){var t=e.data(this,s);t?t.option(o||{})._init():e.data(this,s,new i(o,this))}),f}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,r){r=e(r||this.defaultElement||this)[0],this.element=e(r),this.uuid=n++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),r!==this&&(e.data(r,this.widgetName,this),e.data(r,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===r&&this.destroy()}}),this.document=e(r.style?r.ownerDocument:r.document||r),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(n,r){var i=n,s,o,u;if(arguments.length===0)return e.widget.extend({},this.options);if(typeof n=="string"){i={},s=n.split("."),n=s.shift();if(s.length){o=i[n]=e.widget.extend({},this.options[n]);for(u=0;u<s.length-1;u++)o[s[u]]=o[s[u]]||{},o=o[s[u]];n=s.pop();if(r===t)return o[n]===t?null:o[n];o[n]=r}else{if(r===t)return this.options[n]===t?null:this.options[n];i[n]=r}}return this._setOptions(i),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,e==="disabled"&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(t,n,r){var i,s=this;typeof t!="boolean"&&(r=n,n=t,t=!1),r?(n=i=e(n),this.bindings=this.bindings.add(n)):(r=n,n=this.element,i=this.widget()),e.each(r,function(r,o){function u(){if(!t&&(s.options.disabled===!0||e(this).hasClass("ui-state-disabled")))return;return(typeof o=="string"?s[o]:o).apply(s,arguments)}typeof o!="string"&&(u.guid=o.guid=o.guid||u.guid||e.guid++);var a=r.match(/^(\w+)\s*(.*)$/),f=a[1]+s.eventNamespace,l=a[2];l?i.delegate(l,f,u):n.bind(f,u)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function n(){return(typeof e=="string"?r[e]:e).apply(r,arguments)}var r=this;return setTimeout(n,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,n,r){var i,s,o=this.options[t];r=r||{},n=e.Event(n),n.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),n.target=this.element[0],s=n.originalEvent;if(s)for(i in s)i in n||(n[i]=s[i]);return this.element.trigger(n,r),!(e.isFunction(o)&&o.apply(this.element[0],[n].concat(r))===!1||n.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,n){e.Widget.prototype["_"+t]=function(r,i,s){typeof i=="string"&&(i={effect:i});var o,u=i?i===!0||typeof i=="number"?n:i.effect||n:t;i=i||{},typeof i=="number"&&(i={duration:i}),o=!e.isEmptyObject(i),i.complete=s,i.delay&&r.delay(i.delay),o&&e.effects&&(e.effects.effect[u]||e.uiBackCompat!==!1&&e.effects[u])?r[t](i):u!==t&&r[u]?r[u](i.duration,i.easing,s):r.queue(function(n){e(this)[t](),s&&s.call(r[0]),n()})}}),e.uiBackCompat!==!1&&(e.Widget.prototype._getCreateOptions=function(){return e.metadata&&e.metadata.get(this.element[0])[this.widgetName]})})(jQuery);(function(e,t){var n=!1;e(document).mouseup(function(e){n=!1}),e.widget("ui.mouse",{version:"1.9.2",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(n){if(!0===e.data(n.target,t.widgetName+".preventClickEvent"))return e.removeData(n.target,t.widgetName+".preventClickEvent"),n.stopImmediatePropagation(),!1}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(t){if(n)return;this._mouseStarted&&this._mouseUp(t),this._mouseDownEvent=t;var r=this,i=t.which===1,s=typeof this.options.cancel=="string"&&t.target.nodeName?e(t.target).closest(this.options.cancel).length:!1;if(!i||s||!this._mouseCapture(t))return!0;this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){r.mouseDelayMet=!0},this.options.delay));if(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)){this._mouseStarted=this._mouseStart(t)!==!1;if(!this._mouseStarted)return t.preventDefault(),!0}return!0===e.data(t.target,this.widgetName+".preventClickEvent")&&e.removeData(t.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return r._mouseMove(e)},this._mouseUpDelegate=function(e){return r._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),t.preventDefault(),n=!0,!0},_mouseMove:function(t){return!e.ui.ie||document.documentMode>=9||!!t.button?this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted):this._mouseUp(t)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(e){return this.mouseDelayMet},_mouseStart:function(e){},_mouseDrag:function(e){},_mouseStop:function(e){},_mouseCapture:function(e){return!0}})})(jQuery);(function(e,t){function h(e,t,n){return[parseInt(e[0],10)*(l.test(e[0])?t/100:1),parseInt(e[1],10)*(l.test(e[1])?n/100:1)]}function p(t,n){return parseInt(e.css(t,n),10)||0}e.ui=e.ui||{};var n,r=Math.max,i=Math.abs,s=Math.round,o=/left|center|right/,u=/top|center|bottom/,a=/[\+\-]\d+%?/,f=/^\w+/,l=/%$/,c=e.fn.position;e.position={scrollbarWidth:function(){if(n!==t)return n;var r,i,s=e("<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=s.children()[0];return e("body").append(s),r=o.offsetWidth,s.css("overflow","scroll"),i=o.offsetWidth,r===i&&(i=s[0].clientWidth),s.remove(),n=r-i},getScrollInfo:function(t){var n=t.isWindow?"":t.element.css("overflow-x"),r=t.isWindow?"":t.element.css("overflow-y"),i=n==="scroll"||n==="auto"&&t.width<t.element[0].scrollWidth,s=r==="scroll"||r==="auto"&&t.height<t.element[0].scrollHeight;return{width:i?e.position.scrollbarWidth():0,height:s?e.position.scrollbarWidth():0}},getWithinInfo:function(t){var n=e(t||window),r=e.isWindow(n[0]);return{element:n,isWindow:r,offset:n.offset()||{left:0,top:0},scrollLeft:n.scrollLeft(),scrollTop:n.scrollTop(),width:r?n.width():n.outerWidth(),height:r?n.height():n.outerHeight()}}},e.fn.position=function(t){if(!t||!t.of)return c.apply(this,arguments);t=e.extend({},t);var n,l,d,v,m,g=e(t.of),y=e.position.getWithinInfo(t.within),b=e.position.getScrollInfo(y),w=g[0],E=(t.collision||"flip").split(" "),S={};return w.nodeType===9?(l=g.width(),d=g.height(),v={top:0,left:0}):e.isWindow(w)?(l=g.width(),d=g.height(),v={top:g.scrollTop(),left:g.scrollLeft()}):w.preventDefault?(t.at="left top",l=d=0,v={top:w.pageY,left:w.pageX}):(l=g.outerWidth(),d=g.outerHeight(),v=g.offset()),m=e.extend({},v),e.each(["my","at"],function(){var e=(t[this]||"").split(" "),n,r;e.length===1&&(e=o.test(e[0])?e.concat(["center"]):u.test(e[0])?["center"].concat(e):["center","center"]),e[0]=o.test(e[0])?e[0]:"center",e[1]=u.test(e[1])?e[1]:"center",n=a.exec(e[0]),r=a.exec(e[1]),S[this]=[n?n[0]:0,r?r[0]:0],t[this]=[f.exec(e[0])[0],f.exec(e[1])[0]]}),E.length===1&&(E[1]=E[0]),t.at[0]==="right"?m.left+=l:t.at[0]==="center"&&(m.left+=l/2),t.at[1]==="bottom"?m.top+=d:t.at[1]==="center"&&(m.top+=d/2),n=h(S.at,l,d),m.left+=n[0],m.top+=n[1],this.each(function(){var o,u,a=e(this),f=a.outerWidth(),c=a.outerHeight(),w=p(this,"marginLeft"),x=p(this,"marginTop"),T=f+w+p(this,"marginRight")+b.width,N=c+x+p(this,"marginBottom")+b.height,C=e.extend({},m),k=h(S.my,a.outerWidth(),a.outerHeight());t.my[0]==="right"?C.left-=f:t.my[0]==="center"&&(C.left-=f/2),t.my[1]==="bottom"?C.top-=c:t.my[1]==="center"&&(C.top-=c/2),C.left+=k[0],C.top+=k[1],e.support.offsetFractions||(C.left=s(C.left),C.top=s(C.top)),o={marginLeft:w,marginTop:x},e.each(["left","top"],function(r,i){e.ui.position[E[r]]&&e.ui.position[E[r]][i](C,{targetWidth:l,targetHeight:d,elemWidth:f,elemHeight:c,collisionPosition:o,collisionWidth:T,collisionHeight:N,offset:[n[0]+k[0],n[1]+k[1]],my:t.my,at:t.at,within:y,elem:a})}),e.fn.bgiframe&&a.bgiframe(),t.using&&(u=function(e){var n=v.left-C.left,s=n+l-f,o=v.top-C.top,u=o+d-c,h={target:{element:g,left:v.left,top:v.top,width:l,height:d},element:{element:a,left:C.left,top:C.top,width:f,height:c},horizontal:s<0?"left":n>0?"right":"center",vertical:u<0?"top":o>0?"bottom":"middle"};l<f&&i(n+s)<l&&(h.horizontal="center"),d<c&&i(o+u)<d&&(h.vertical="middle"),r(i(n),i(s))>r(i(o),i(u))?h.important="horizontal":h.important="vertical",t.using.call(this,e,h)}),a.offset(e.extend(C,{using:u}))})},e.ui.position={fit:{left:function(e,t){var n=t.within,i=n.isWindow?n.scrollLeft:n.offset.left,s=n.width,o=e.left-t.collisionPosition.marginLeft,u=i-o,a=o+t.collisionWidth-s-i,f;t.collisionWidth>s?u>0&&a<=0?(f=e.left+u+t.collisionWidth-s-i,e.left+=u-f):a>0&&u<=0?e.left=i:u>a?e.left=i+s-t.collisionWidth:e.left=i:u>0?e.left+=u:a>0?e.left-=a:e.left=r(e.left-o,e.left)},top:function(e,t){var n=t.within,i=n.isWindow?n.scrollTop:n.offset.top,s=t.within.height,o=e.top-t.collisionPosition.marginTop,u=i-o,a=o+t.collisionHeight-s-i,f;t.collisionHeight>s?u>0&&a<=0?(f=e.top+u+t.collisionHeight-s-i,e.top+=u-f):a>0&&u<=0?e.top=i:u>a?e.top=i+s-t.collisionHeight:e.top=i:u>0?e.top+=u:a>0?e.top-=a:e.top=r(e.top-o,e.top)}},flip:{left:function(e,t){var n=t.within,r=n.offset.left+n.scrollLeft,s=n.width,o=n.isWindow?n.scrollLeft:n.offset.left,u=e.left-t.collisionPosition.marginLeft,a=u-o,f=u+t.collisionWidth-s-o,l=t.my[0]==="left"?-t.elemWidth:t.my[0]==="right"?t.elemWidth:0,c=t.at[0]==="left"?t.targetWidth:t.at[0]==="right"?-t.targetWidth:0,h=-2*t.offset[0],p,d;if(a<0){p=e.left+l+c+h+t.collisionWidth-s-r;if(p<0||p<i(a))e.left+=l+c+h}else if(f>0){d=e.left-t.collisionPosition.marginLeft+l+c+h-o;if(d>0||i(d)<f)e.left+=l+c+h}},top:function(e,t){var n=t.within,r=n.offset.top+n.scrollTop,s=n.height,o=n.isWindow?n.scrollTop:n.offset.top,u=e.top-t.collisionPosition.marginTop,a=u-o,f=u+t.collisionHeight-s-o,l=t.my[1]==="top",c=l?-t.elemHeight:t.my[1]==="bottom"?t.elemHeight:0,h=t.at[1]==="top"?t.targetHeight:t.at[1]==="bottom"?-t.targetHeight:0,p=-2*t.offset[1],d,v;a<0?(v=e.top+c+h+p+t.collisionHeight-s-r,e.top+c+h+p>a&&(v<0||v<i(a))&&(e.top+=c+h+p)):f>0&&(d=e.top-t.collisionPosition.marginTop+c+h+p-o,e.top+c+h+p>f&&(d>0||i(d)<f)&&(e.top+=c+h+p))}},flipfit:{left:function(){e.ui.position.flip.left.apply(this,arguments),e.ui.position.fit.left.apply(this,arguments)},top:function(){e.ui.position.flip.top.apply(this,arguments),e.ui.position.fit.top.apply(this,arguments)}}},function(){var t,n,r,i,s,o=document.getElementsByTagName("body")[0],u=document.createElement("div");t=document.createElement(o?"div":"body"),r={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},o&&e.extend(r,{position:"absolute",left:"-1000px",top:"-1000px"});for(s in r)t.style[s]=r[s];t.appendChild(u),n=o||document.documentElement,n.insertBefore(t,n.firstChild),u.style.cssText="position: absolute; left: 10.7432222px;",i=e(u).offset().left,e.support.offsetFractions=i>10&&i<11,t.innerHTML="",n.removeChild(t)}(),e.uiBackCompat!==!1&&function(e){var n=e.fn.position;e.fn.position=function(r){if(!r||!r.offset)return n.call(this,r);var i=r.offset.split(" "),s=r.at.split(" ");return i.length===1&&(i[1]=i[0]),/^\d/.test(i[0])&&(i[0]="+"+i[0]),/^\d/.test(i[1])&&(i[1]="+"+i[1]),s.length===1&&(/left|center|right/.test(s[0])?s[1]="center":(s[1]=s[0],s[0]="center")),n.call(this,e.extend(r,{at:s[0]+i[0]+" "+s[1]+i[1],offset:t}))}}(jQuery)})(jQuery);(function(e,t){e.widget("ui.draggable",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1},_create:function(){this.options.helper=="original"&&!/^(?:r|a|f)/.test(this.element.css("position"))&&(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},_destroy:function(){this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy()},_mouseCapture:function(t){var n=this.options;return this.helper||n.disabled||e(t.target).is(".ui-resizable-handle")?!1:(this.handle=this._getHandle(t),this.handle?(e(n.iframeFix===!0?"iframe":n.iframeFix).each(function(){e('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(e(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(t){var n=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,n.cursorAt&&this._adjustOffsetFromHelper(n.cursorAt),n.containment&&this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_mouseDrag:function(t,n){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute");if(!n){var r=this._uiHash();if(this._trigger("drag",t,r)===!1)return this._mouseUp({}),!1;this.position=r.position}if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";return e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var n=!1;e.ui.ddmanager&&!this.options.dropBehaviour&&(n=e.ui.ddmanager.drop(this,t)),this.dropped&&(n=this.dropped,this.dropped=!1);var r=this.element[0],i=!1;while(r&&(r=r.parentNode))r==document&&(i=!0);if(!i&&this.options.helper==="original")return!1;if(this.options.revert=="invalid"&&!n||this.options.revert=="valid"&&n||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,n)){var s=this;e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){s._trigger("stop",t)!==!1&&s._clear()})}else this._trigger("stop",t)!==!1&&this._clear();return!1},_mouseUp:function(t){return e("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){var n=!this.options.handle||!e(this.options.handle,this.element).length?!0:!1;return e(this.options.handle,this.element).find("*").andSelf().each(function(){this==t.target&&(n=!0)}),n},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t])):n.helper=="clone"?this.element.clone().removeAttr("id"):this.element;return r.parents("body").length||r.appendTo(n.appendTo=="parent"?this.element[0].parentNode:n.appendTo),r[0]!=this.element[0]&&!/(fixed|absolute)/.test(r.css("position"))&&r.css("position","absolute"),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&e.ui.ie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var e=this.element.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t=this.options;t.containment=="parent"&&(t.containment=this.helper[0].parentNode);if(t.containment=="document"||t.containment=="window")this.containment=[t.containment=="document"?0:e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,t.containment=="document"?0:e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,(t.containment=="document"?0:e(window).scrollLeft())+e(t.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(t.containment=="document"?0:e(window).scrollTop())+(e(t.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(t.containment)&&t.containment.constructor!=Array){var n=e(t.containment),r=n[0];if(!r)return;var i=n.offset(),s=e(r).css("overflow")!="hidden";this.containment=[(parseInt(e(r).css("borderLeftWidth"),10)||0)+(parseInt(e(r).css("paddingLeft"),10)||0),(parseInt(e(r).css("borderTopWidth"),10)||0)+(parseInt(e(r).css("paddingTop"),10)||0),(s?Math.max(r.scrollWidth,r.offsetWidth):r.offsetWidth)-(parseInt(e(r).css("borderLeftWidth"),10)||0)-(parseInt(e(r).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(s?Math.max(r.scrollHeight,r.offsetHeight):r.offsetHeight)-(parseInt(e(r).css("borderTopWidth"),10)||0)-(parseInt(e(r).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=n}else t.containment.constructor==Array&&(this.containment=t.containment)},_convertPositionTo:function(t,n){n||(n=this.position);var r=t=="absolute"?1:-1,i=this.options,s=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(s[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():o?0:s.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():o?0:s.scrollLeft())*r}},_generatePosition:function(t){var n=this.options,r=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,i=/(html|body)/i.test(r[0].tagName),s=t.pageX,o=t.pageY;if(this.originalPosition){var u;if(this.containment){if(this.relative_container){var a=this.relative_container.offset();u=[this.containment[0]+a.left,this.containment[1]+a.top,this.containment[2]+a.left,this.containment[3]+a.top]}else u=this.containment;t.pageX-this.offset.click.left<u[0]&&(s=u[0]+this.offset.click.left),t.pageY-this.offset.click.top<u[1]&&(o=u[1]+this.offset.click.top),t.pageX-this.offset.click.left>u[2]&&(s=u[2]+this.offset.click.left),t.pageY-this.offset.click.top>u[3]&&(o=u[3]+this.offset.click.top)}if(n.grid){var f=n.grid[1]?this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1]:this.originalPageY;o=u?f-this.offset.click.top<u[1]||f-this.offset.click.top>u[3]?f-this.offset.click.top<u[1]?f+n.grid[1]:f-n.grid[1]:f:f;var l=n.grid[0]?this.originalPageX+Math.round((s-this.originalPageX)/n.grid[0])*n.grid[0]:this.originalPageX;s=u?l-this.offset.click.left<u[0]||l-this.offset.click.left>u[2]?l-this.offset.click.left<u[0]?l+n.grid[0]:l-n.grid[0]:l:l}}return{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():i?0:r.scrollTop()),left:s-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:r.scrollLeft())}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval&&this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(t,n,r){return r=r||this._uiHash(),e.ui.plugin.call(this,t,[n,r]),t=="drag"&&(this.positionAbs=this._convertPositionTo("absolute")),e.Widget.prototype._trigger.call(this,t,n,r)},plugins:{},_uiHash:function(e){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,n){var r=e(this).data("draggable"),i=r.options,s=e.extend({},n,{item:r.element});r.sortables=[],e(i.connectToSortable).each(function(){var n=e.data(this,"sortable");n&&!n.options.disabled&&(r.sortables.push({instance:n,shouldRevert:n.options.revert}),n.refreshPositions(),n._trigger("activate",t,s))})},stop:function(t,n){var r=e(this).data("draggable"),i=e.extend({},n,{item:r.element});e.each(r.sortables,function(){this.instance.isOver?(this.instance.isOver=0,r.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=!0),this.instance._mouseStop(t),this.instance.options.helper=this.instance.options._helper,r.options.helper=="original"&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",t,i))})},drag:function(t,n){var r=e(this).data("draggable"),i=this,s=function(t){var n=this.offset.click.top,r=this.offset.click.left,i=this.positionAbs.top,s=this.positionAbs.left,o=t.height,u=t.width,a=t.top,f=t.left;return e.ui.isOver(i+n,s+r,a,f,o,u)};e.each(r.sortables,function(s){var o=!1,u=this;this.instance.positionAbs=r.positionAbs,this.instance.helperProportions=r.helperProportions,this.instance.offset.click=r.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(o=!0,e.each(r.sortables,function(){return this.instance.positionAbs=r.positionAbs,this.instance.helperProportions=r.helperProportions,this.instance.offset.click=r.offset.click,this!=u&&this.instance._intersectsWith(this.instance.containerCache)&&e.ui.contains(u.instance.element[0],this.instance.element[0])&&(o=!1),o})),o?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=e(i).clone().removeAttr("id").appendTo(this.instance.element).data("sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return n.helper[0]},t.target=this.instance.currentItem[0],this.instance._mouseCapture(t,!0),this.instance._mouseStart(t,!0,!0),this.instance.offset.click.top=r.offset.click.top,this.instance.offset.click.left=r.offset.click.left,this.instance.offset.parent.left-=r.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=r.offset.parent.top-this.instance.offset.parent.top,r._trigger("toSortable",t),r.dropped=this.instance.element,r.currentItem=r.element,this.instance.fromOutside=r),this.instance.currentItem&&this.instance._mouseDrag(t)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",t,this.instance._uiHash(this.instance)),this.instance._mouseStop(t,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),r._trigger("fromSortable",t),r.dropped=!1)})}}),e.ui.plugin.add("draggable","cursor",{start:function(t,n){var r=e("body"),i=e(this).data("draggable").options;r.css("cursor")&&(i._cursor=r.css("cursor")),r.css("cursor",i.cursor)},stop:function(t,n){var r=e(this).data("draggable").options;r._cursor&&e("body").css("cursor",r._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,n){var r=e(n.helper),i=e(this).data("draggable").options;r.css("opacity")&&(i._opacity=r.css("opacity")),r.css("opacity",i.opacity)},stop:function(t,n){var r=e(this).data("draggable").options;r._opacity&&e(n.helper).css("opacity",r._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(t,n){var r=e(this).data("draggable");r.scrollParent[0]!=document&&r.scrollParent[0].tagName!="HTML"&&(r.overflowOffset=r.scrollParent.offset())},drag:function(t,n){var r=e(this).data("draggable"),i=r.options,s=!1;if(r.scrollParent[0]!=document&&r.scrollParent[0].tagName!="HTML"){if(!i.axis||i.axis!="x")r.overflowOffset.top+r.scrollParent[0].offsetHeight-t.pageY<i.scrollSensitivity?r.scrollParent[0].scrollTop=s=r.scrollParent[0].scrollTop+i.scrollSpeed:t.pageY-r.overflowOffset.top<i.scrollSensitivity&&(r.scrollParent[0].scrollTop=s=r.scrollParent[0].scrollTop-i.scrollSpeed);if(!i.axis||i.axis!="y")r.overflowOffset.left+r.scrollParent[0].offsetWidth-t.pageX<i.scrollSensitivity?r.scrollParent[0].scrollLeft=s=r.scrollParent[0].scrollLeft+i.scrollSpeed:t.pageX-r.overflowOffset.left<i.scrollSensitivity&&(r.scrollParent[0].scrollLeft=s=r.scrollParent[0].scrollLeft-i.scrollSpeed)}else{if(!i.axis||i.axis!="x")t.pageY-e(document).scrollTop()<i.scrollSensitivity?s=e(document).scrollTop(e(document).scrollTop()-i.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<i.scrollSensitivity&&(s=e(document).scrollTop(e(document).scrollTop()+i.scrollSpeed));if(!i.axis||i.axis!="y")t.pageX-e(document).scrollLeft()<i.scrollSensitivity?s=e(document).scrollLeft(e(document).scrollLeft()-i.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<i.scrollSensitivity&&(s=e(document).scrollLeft(e(document).scrollLeft()+i.scrollSpeed))}s!==!1&&e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(r,t)}}),e.ui.plugin.add("draggable","snap",{start:function(t,n){var r=e(this).data("draggable"),i=r.options;r.snapElements=[],e(i.snap.constructor!=String?i.snap.items||":data(draggable)":i.snap).each(function(){var t=e(this),n=t.offset();this!=r.element[0]&&r.snapElements.push({item:this,width:t.outerWidth(),height:t.outerHeight(),top:n.top,left:n.left})})},drag:function(t,n){var r=e(this).data("draggable"),i=r.options,s=i.snapTolerance,o=n.offset.left,u=o+r.helperProportions.width,a=n.offset.top,f=a+r.helperProportions.height;for(var l=r.snapElements.length-1;l>=0;l--){var c=r.snapElements[l].left,h=c+r.snapElements[l].width,p=r.snapElements[l].top,d=p+r.snapElements[l].height;if(!(c-s<o&&o<h+s&&p-s<a&&a<d+s||c-s<o&&o<h+s&&p-s<f&&f<d+s||c-s<u&&u<h+s&&p-s<a&&a<d+s||c-s<u&&u<h+s&&p-s<f&&f<d+s)){r.snapElements[l].snapping&&r.options.snap.release&&r.options.snap.release.call(r.element,t,e.extend(r._uiHash(),{snapItem:r.snapElements[l].item})),r.snapElements[l].snapping=!1;continue}if(i.snapMode!="inner"){var v=Math.abs(p-f)<=s,m=Math.abs(d-a)<=s,g=Math.abs(c-u)<=s,y=Math.abs(h-o)<=s;v&&(n.position.top=r._convertPositionTo("relative",{top:p-r.helperProportions.height,left:0}).top-r.margins.top),m&&(n.position.top=r._convertPositionTo("relative",{top:d,left:0}).top-r.margins.top),g&&(n.position.left=r._convertPositionTo("relative",{top:0,left:c-r.helperProportions.width}).left-r.margins.left),y&&(n.position.left=r._convertPositionTo("relative",{top:0,left:h}).left-r.margins.left)}var b=v||m||g||y;if(i.snapMode!="outer"){var v=Math.abs(p-a)<=s,m=Math.abs(d-f)<=s,g=Math.abs(c-o)<=s,y=Math.abs(h-u)<=s;v&&(n.position.top=r._convertPositionTo("relative",{top:p,left:0}).top-r.margins.top),m&&(n.position.top=r._convertPositionTo("relative",{top:d-r.helperProportions.height,left:0}).top-r.margins.top),g&&(n.position.left=r._convertPositionTo("relative",{top:0,left:c}).left-r.margins.left),y&&(n.position.left=r._convertPositionTo("relative",{top:0,left:h-r.helperProportions.width}).left-r.margins.left)}!r.snapElements[l].snapping&&(v||m||g||y||b)&&r.options.snap.snap&&r.options.snap.snap.call(r.element,t,e.extend(r._uiHash(),{snapItem:r.snapElements[l].item})),r.snapElements[l].snapping=v||m||g||y||b}}}),e.ui.plugin.add("draggable","stack",{start:function(t,n){var r=e(this).data("draggable").options,i=e.makeArray(e(r.stack)).sort(function(t,n){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(n).css("zIndex"),10)||0)});if(!i.length)return;var s=parseInt(i[0].style.zIndex)||0;e(i).each(function(e){this.style.zIndex=s+e}),this[0].style.zIndex=s+i.length}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,n){var r=e(n.helper),i=e(this).data("draggable").options;r.css("zIndex")&&(i._zIndex=r.css("zIndex")),r.css("zIndex",i.zIndex)},stop:function(t,n){var r=e(this).data("draggable").options;r._zIndex&&e(n.helper).css("zIndex",r._zIndex)}})})(jQuery);(function(e,t){e.widget("ui.droppable",{version:"1.9.2",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect"},_create:function(){var t=this.options,n=t.accept;this.isover=0,this.isout=1,this.accept=e.isFunction(n)?n:function(e){return e.is(n)},this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight},e.ui.ddmanager.droppables[t.scope]=e.ui.ddmanager.droppables[t.scope]||[],e.ui.ddmanager.droppables[t.scope].push(this),t.addClasses&&this.element.addClass("ui-droppable")},_destroy:function(){var t=e.ui.ddmanager.droppables[this.options.scope];for(var n=0;n<t.length;n++)t[n]==this&&t.splice(n,1);this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(t,n){t=="accept"&&(this.accept=e.isFunction(n)?n:function(e){return e.is(n)}),e.Widget.prototype._setOption.apply(this,arguments)},_activate:function(t){var n=e.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),n&&this._trigger("activate",t,this.ui(n))},_deactivate:function(t){var n=e.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),n&&this._trigger("deactivate",t,this.ui(n))},_over:function(t){var n=e.ui.ddmanager.current;if(!n||(n.currentItem||n.element)[0]==this.element[0])return;this.accept.call(this.element[0],n.currentItem||n.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",t,this.ui(n)))},_out:function(t){var n=e.ui.ddmanager.current;if(!n||(n.currentItem||n.element)[0]==this.element[0])return;this.accept.call(this.element[0],n.currentItem||n.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",t,this.ui(n)))},_drop:function(t,n){var r=n||e.ui.ddmanager.current;if(!r||(r.currentItem||r.element)[0]==this.element[0])return!1;var i=!1;return this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var t=e.data(this,"droppable");if(t.options.greedy&&!t.options.disabled&&t.options.scope==r.options.scope&&t.accept.call(t.element[0],r.currentItem||r.element)&&e.ui.intersect(r,e.extend(t,{offset:t.element.offset()}),t.options.tolerance))return i=!0,!1}),i?!1:this.accept.call(this.element[0],r.currentItem||r.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",t,this.ui(r)),this.element):!1},ui:function(e){return{draggable:e.currentItem||e.element,helper:e.helper,position:e.position,offset:e.positionAbs}}}),e.ui.intersect=function(t,n,r){if(!n.offset)return!1;var i=(t.positionAbs||t.position.absolute).left,s=i+t.helperProportions.width,o=(t.positionAbs||t.position.absolute).top,u=o+t.helperProportions.height,a=n.offset.left,f=a+n.proportions.width,l=n.offset.top,c=l+n.proportions.height;switch(r){case"fit":return a<=i&&s<=f&&l<=o&&u<=c;case"intersect":return a<i+t.helperProportions.width/2&&s-t.helperProportions.width/2<f&&l<o+t.helperProportions.height/2&&u-t.helperProportions.height/2<c;case"pointer":var h=(t.positionAbs||t.position.absolute).left+(t.clickOffset||t.offset.click).left,p=(t.positionAbs||t.position.absolute).top+(t.clickOffset||t.offset.click).top,d=e.ui.isOver(p,h,l,a,n.proportions.height,n.proportions.width);return d;case"touch":return(o>=l&&o<=c||u>=l&&u<=c||o<l&&u>c)&&(i>=a&&i<=f||s>=a&&s<=f||i<a&&s>f);default:return!1}},e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,n){var r=e.ui.ddmanager.droppables[t.options.scope]||[],i=n?n.type:null,s=(t.currentItem||t.element).find(":data(droppable)").andSelf();e:for(var o=0;o<r.length;o++){if(r[o].options.disabled||t&&!r[o].accept.call(r[o].element[0],t.currentItem||t.element))continue;for(var u=0;u<s.length;u++)if(s[u]==r[o].element[0]){r[o].proportions.height=0;continue e}r[o].visible=r[o].element.css("display")!="none";if(!r[o].visible)continue;i=="mousedown"&&r[o]._activate.call(r[o],n),r[o].offset=r[o].element.offset(),r[o].proportions={width:r[o].element[0].offsetWidth,height:r[o].element[0].offsetHeight}}},drop:function(t,n){var r=!1;return e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(!this.options)return;!this.options.disabled&&this.visible&&e.ui.intersect(t,this,this.options.tolerance)&&(r=this._drop.call(this,n)||r),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=1,this.isover=0,this._deactivate.call(this,n))}),r},dragStart:function(t,n){t.element.parentsUntil("body").bind("scroll.droppable",function(){t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,n)})},drag:function(t,n){t.options.refreshPositions&&e.ui.ddmanager.prepareOffsets(t,n),e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(this.options.disabled||this.greedyChild||!this.visible)return;var r=e.ui.intersect(t,this,this.options.tolerance),i=!r&&this.isover==1?"isout":r&&this.isover==0?"isover":null;if(!i)return;var s;if(this.options.greedy){var o=this.options.scope,u=this.element.parents(":data(droppable)").filter(function(){return e.data(this,"droppable").options.scope===o});u.length&&(s=e.data(u[0],"droppable"),s.greedyChild=i=="isover"?1:0)}s&&i=="isover"&&(s.isover=0,s.isout=1,s._out.call(s,n)),this[i]=1,this[i=="isout"?"isover":"isout"]=0,this[i=="isover"?"_over":"_out"].call(this,n),s&&i=="isout"&&(s.isout=0,s.isover=1,s._over.call(s,n))})},dragStop:function(t,n){t.element.parentsUntil("body").unbind("scroll.droppable"),t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,n)}}})(jQuery);(function(e,t){e.widget("ui.resizable",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1e3},_create:function(){var t=this,n=this.options;this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!n.aspectRatio,aspectRatio:n.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:n.helper||n.ghost||n.animate?n.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("resizable",this.element.data("resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=n.handles||(e(".ui-resizable-handle",this.element).length?{n:".ui-resizable-n",e:".ui-resizable-e",s:".ui-resizable-s",w:".ui-resizable-w",se:".ui-resizable-se",sw:".ui-resizable-sw",ne:".ui-resizable-ne",nw:".ui-resizable-nw"}:"e,s,se");if(this.handles.constructor==String){this.handles=="all"&&(this.handles="n,e,s,w,se,sw,ne,nw");var r=this.handles.split(",");this.handles={};for(var i=0;i<r.length;i++){var s=e.trim(r[i]),o="ui-resizable-"+s,u=e('<div class="ui-resizable-handle '+o+'"></div>');u.css({zIndex:n.zIndex}),"se"==s&&u.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(u)}}this._renderAxis=function(t){t=t||this.element;for(var n in this.handles){this.handles[n].constructor==String&&(this.handles[n]=e(this.handles[n],this.element).show());if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var r=e(this.handles[n],this.element),i=0;i=/sw|ne|nw|se|n|s/.test(n)?r.outerHeight():r.outerWidth();var s=["padding",/ne|nw|n/.test(n)?"Top":/se|sw|s/.test(n)?"Bottom":/^e$/.test(n)?"Right":"Left"].join("");t.css(s,i),this._proportionallyResize()}if(!e(this.handles[n]).length)continue}},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){if(!t.resizing){if(this.className)var e=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);t.axis=e&&e[1]?e[1]:"se"}}),n.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){if(n.disabled)return;e(this).removeClass("ui-resizable-autohide"),t._handles.show()}).mouseleave(function(){if(n.disabled)return;t.resizing||(e(this).addClass("ui-resizable-autohide"),t._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){t(this.element);var n=this.element;this.originalElement.css({position:n.css("position"),width:n.outerWidth(),height:n.outerHeight(),top:n.css("top"),left:n.css("left")}).insertAfter(n),n.remove()}return this.originalElement.css("resize",this.originalResizeStyle),t(this.originalElement),this},_mouseCapture:function(t){var n=!1;for(var r in this.handles)e(this.handles[r])[0]==t.target&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(t){var r=this.options,i=this.element.position(),s=this.element;this.resizing=!0,this.documentScroll={top:e(document).scrollTop(),left:e(document).scrollLeft()},(s.is(".ui-draggable")||/absolute/.test(s.css("position")))&&s.css({position:"absolute",top:i.top,left:i.left}),this._renderProxy();var o=n(this.helper.css("left")),u=n(this.helper.css("top"));r.containment&&(o+=e(r.containment).scrollLeft()||0,u+=e(r.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:o,top:u},this.size=this._helper?{width:s.outerWidth(),height:s.outerHeight()}:{width:s.width(),height:s.height()},this.originalSize=this._helper?{width:s.outerWidth(),height:s.outerHeight()}:{width:s.width(),height:s.height()},this.originalPosition={left:o,top:u},this.sizeDiff={width:s.outerWidth()-s.width(),height:s.outerHeight()-s.height()},this.originalMousePosition={left:t.pageX,top:t.pageY},this.aspectRatio=typeof r.aspectRatio=="number"?r.aspectRatio:this.originalSize.width/this.originalSize.height||1;var a=e(".ui-resizable-"+this.axis).css("cursor");return e("body").css("cursor",a=="auto"?this.axis+"-resize":a),s.addClass("ui-resizable-resizing"),this._propagate("start",t),!0},_mouseDrag:function(e){var t=this.helper,n=this.options,r={},i=this,s=this.originalMousePosition,o=this.axis,u=e.pageX-s.left||0,a=e.pageY-s.top||0,f=this._change[o];if(!f)return!1;var l=f.apply(this,[e,u,a]);this._updateVirtualBoundaries(e.shiftKey);if(this._aspectRatio||e.shiftKey)l=this._updateRatio(l,e);return l=this._respectSize(l,e),this._propagate("resize",e),t.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"}),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),this._updateCache(l),this._trigger("resize",e,this.ui()),!1},_mouseStop:function(t){this.resizing=!1;var n=this.options,r=this;if(this._helper){var i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),o=s&&e.ui.hasScroll(i[0],"left")?0:r.sizeDiff.height,u=s?0:r.sizeDiff.width,a={width:r.helper.width()-u,height:r.helper.height()-o},f=parseInt(r.element.css("left"),10)+(r.position.left-r.originalPosition.left)||null,l=parseInt(r.element.css("top"),10)+(r.position.top-r.originalPosition.top)||null;n.animate||this.element.css(e.extend(a,{top:l,left:f})),r.helper.height(r.size.height),r.helper.width(r.size.width),this._helper&&!n.animate&&this._proportionallyResize()}return e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t=this.options,n,i,s,o,u;u={minWidth:r(t.minWidth)?t.minWidth:0,maxWidth:r(t.maxWidth)?t.maxWidth:Infinity,minHeight:r(t.minHeight)?t.minHeight:0,maxHeight:r(t.maxHeight)?t.maxHeight:Infinity};if(this._aspectRatio||e)n=u.minHeight*this.aspectRatio,s=u.minWidth/this.aspectRatio,i=u.maxHeight*this.aspectRatio,o=u.maxWidth/this.aspectRatio,n>u.minWidth&&(u.minWidth=n),s>u.minHeight&&(u.minHeight=s),i<u.maxWidth&&(u.maxWidth=i),o<u.maxHeight&&(u.maxHeight=o);this._vBoundaries=u},_updateCache:function(e){var t=this.options;this.offset=this.helper.offset(),r(e.left)&&(this.position.left=e.left),r(e.top)&&(this.position.top=e.top),r(e.height)&&(this.size.height=e.height),r(e.width)&&(this.size.width=e.width)},_updateRatio:function(e,t){var n=this.options,i=this.position,s=this.size,o=this.axis;return r(e.height)?e.width=e.height*this.aspectRatio:r(e.width)&&(e.height=e.width/this.aspectRatio),o=="sw"&&(e.left=i.left+(s.width-e.width),e.top=null),o=="nw"&&(e.top=i.top+(s.height-e.height),e.left=i.left+(s.width-e.width)),e},_respectSize:function(e,t){var n=this.helper,i=this._vBoundaries,s=this._aspectRatio||t.shiftKey,o=this.axis,u=r(e.width)&&i.maxWidth&&i.maxWidth<e.width,a=r(e.height)&&i.maxHeight&&i.maxHeight<e.height,f=r(e.width)&&i.minWidth&&i.minWidth>e.width,l=r(e.height)&&i.minHeight&&i.minHeight>e.height;f&&(e.width=i.minWidth),l&&(e.height=i.minHeight),u&&(e.width=i.maxWidth),a&&(e.height=i.maxHeight);var c=this.originalPosition.left+this.originalSize.width,h=this.position.top+this.size.height,p=/sw|nw|w/.test(o),d=/nw|ne|n/.test(o);f&&p&&(e.left=c-i.minWidth),u&&p&&(e.left=c-i.maxWidth),l&&d&&(e.top=h-i.minHeight),a&&d&&(e.top=h-i.maxHeight);var v=!e.width&&!e.height;return v&&!e.left&&e.top?e.top=null:v&&!e.top&&e.left&&(e.left=null),e},_proportionallyResize:function(){var t=this.options;if(!this._proportionallyResizeElements.length)return;var n=this.helper||this.element;for(var r=0;r<this._proportionallyResizeElements.length;r++){var i=this._proportionallyResizeElements[r];if(!this.borderDif){var s=[i.css("borderTopWidth"),i.css("borderRightWidth"),i.css("borderBottomWidth"),i.css("borderLeftWidth")],o=[i.css("paddingTop"),i.css("paddingRight"),i.css("paddingBottom"),i.css("paddingLeft")];this.borderDif=e.map(s,function(e,t){var n=parseInt(e,10)||0,r=parseInt(o[t],10)||0;return n+r})}i.css({height:n.height()-this.borderDif[0]-this.borderDif[2]||0,width:n.width()-this.borderDif[1]-this.borderDif[3]||0})}},_renderProxy:function(){var t=this.element,n=this.options;this.elementOffset=t.offset();if(this._helper){this.helper=this.helper||e('<div style="overflow:hidden;"></div>');var r=e.ui.ie6?1:0,i=e.ui.ie6?2:-1;this.helper.addClass(this._helper).css({width:this.element.outerWidth()+i,height:this.element.outerHeight()+i,position:"absolute",left:this.elementOffset.left-r+"px",top:this.elementOffset.top-r+"px",zIndex:++n.zIndex}),this.helper.appendTo("body").disableSelection()}else this.helper=this.element},_change:{e:function(e,t,n){return{width:this.originalSize.width+t}},w:function(e,t,n){var r=this.options,i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,n){var r=this.options,i=this.originalSize,s=this.originalPosition;return{top:s.top+n,height:i.height-n}},s:function(e,t,n){return{height:this.originalSize.height+n}},se:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},sw:function(t,n,r){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,n,r]))},ne:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,n,r]))},nw:function(t,n,r){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,n,r]))}},_propagate:function(t,n){e.ui.plugin.call(this,t,[n,this.ui()]),t!="resize"&&this._trigger(t,n,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","alsoResize",{start:function(t,n){var r=e(this).data("resizable"),i=r.options,s=function(t){e(t).each(function(){var t=e(this);t.data("resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};typeof i.alsoResize=="object"&&!i.alsoResize.parentNode?i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)}):s(i.alsoResize)},resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.originalSize,o=r.originalPosition,u={height:r.size.height-s.height||0,width:r.size.width-s.width||0,top:r.position.top-o.top||0,left:r.position.left-o.left||0},a=function(t,r){e(t).each(function(){var t=e(this),i=e(this).data("resizable-alsoresize"),s={},o=r&&r.length?r:t.parents(n.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var n=(i[t]||0)+(u[t]||0);n&&n>=0&&(s[t]=n||null)}),t.css(s)})};typeof i.alsoResize=="object"&&!i.alsoResize.nodeType?e.each(i.alsoResize,function(e,t){a(e,t)}):a(i.alsoResize)},stop:function(t,n){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","animate",{stop:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r._proportionallyResizeElements,o=s.length&&/textarea/i.test(s[0].nodeName),u=o&&e.ui.hasScroll(s[0],"left")?0:r.sizeDiff.height,a=o?0:r.sizeDiff.width,f={width:r.size.width-a,height:r.size.height-u},l=parseInt(r.element.css("left"),10)+(r.position.left-r.originalPosition.left)||null,c=parseInt(r.element.css("top"),10)+(r.position.top-r.originalPosition.top)||null;r.element.animate(e.extend(f,c&&l?{top:c,left:l}:{}),{duration:i.animateDuration,easing:i.animateEasing,step:function(){var n={width:parseInt(r.element.css("width"),10),height:parseInt(r.element.css("height"),10),top:parseInt(r.element.css("top"),10),left:parseInt(r.element.css("left"),10)};s&&s.length&&e(s[0]).css({width:n.width,height:n.height}),r._updateCache(n),r._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(t,r){var i=e(this).data("resizable"),s=i.options,o=i.element,u=s.containment,a=u instanceof e?u.get(0):/parent/.test(u)?o.parent().get(0):u;if(!a)return;i.containerElement=e(a);if(/document/.test(u)||u==document)i.containerOffset={left:0,top:0},i.containerPosition={left:0,top:0},i.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight};else{var f=e(a),l=[];e(["Top","Right","Left","Bottom"]).each(function(e,t){l[e]=n(f.css("padding"+t))}),i.containerOffset=f.offset(),i.containerPosition=f.position(),i.containerSize={height:f.innerHeight()-l[3],width:f.innerWidth()-l[1]};var c=i.containerOffset,h=i.containerSize.height,p=i.containerSize.width,d=e.ui.hasScroll(a,"left")?a.scrollWidth:p,v=e.ui.hasScroll(a)?a.scrollHeight:h;i.parentData={element:a,left:c.left,top:c.top,width:d,height:v}}},resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.containerSize,o=r.containerOffset,u=r.size,a=r.position,f=r._aspectRatio||t.shiftKey,l={top:0,left:0},c=r.containerElement;c[0]!=document&&/static/.test(c.css("position"))&&(l=o),a.left<(r._helper?o.left:0)&&(r.size.width=r.size.width+(r._helper?r.position.left-o.left:r.position.left-l.left),f&&(r.size.height=r.size.width/r.aspectRatio),r.position.left=i.helper?o.left:0),a.top<(r._helper?o.top:0)&&(r.size.height=r.size.height+(r._helper?r.position.top-o.top:r.position.top),f&&(r.size.width=r.size.height*r.aspectRatio),r.position.top=r._helper?o.top:0),r.offset.left=r.parentData.left+r.position.left,r.offset.top=r.parentData.top+r.position.top;var h=Math.abs((r._helper?r.offset.left-l.left:r.offset.left-l.left)+r.sizeDiff.width),p=Math.abs((r._helper?r.offset.top-l.top:r.offset.top-o.top)+r.sizeDiff.height),d=r.containerElement.get(0)==r.element.parent().get(0),v=/relative|absolute/.test(r.containerElement.css("position"));d&&v&&(h-=r.parentData.left),h+r.size.width>=r.parentData.width&&(r.size.width=r.parentData.width-h,f&&(r.size.height=r.size.width/r.aspectRatio)),p+r.size.height>=r.parentData.height&&(r.size.height=r.parentData.height-p,f&&(r.size.width=r.size.height*r.aspectRatio))},stop:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.position,o=r.containerOffset,u=r.containerPosition,a=r.containerElement,f=e(r.helper),l=f.offset(),c=f.outerWidth()-r.sizeDiff.width,h=f.outerHeight()-r.sizeDiff.height;r._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:l.left-u.left-o.left,width:c,height:h}),r._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:l.left-u.left-o.left,width:c,height:h})}}),e.ui.plugin.add("resizable","ghost",{start:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.size;r.ghost=r.originalElement.clone(),r.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof i.ghost=="string"?i.ghost:""),r.ghost.appendTo(r.helper)},resize:function(t,n){var r=e(this).data("resizable"),i=r.options;r.ghost&&r.ghost.css({position:"relative",height:r.size.height,width:r.size.width})},stop:function(t,n){var r=e(this).data("resizable"),i=r.options;r.ghost&&r.helper&&r.helper.get(0).removeChild(r.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(t,n){var r=e(this).data("resizable"),i=r.options,s=r.size,o=r.originalSize,u=r.originalPosition,a=r.axis,f=i._aspectRatio||t.shiftKey;i.grid=typeof i.grid=="number"?[i.grid,i.grid]:i.grid;var l=Math.round((s.width-o.width)/(i.grid[0]||1))*(i.grid[0]||1),c=Math.round((s.height-o.height)/(i.grid[1]||1))*(i.grid[1]||1);/^(se|s|e)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c):/^(ne)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c,r.position.top=u.top-c):/^(sw)$/.test(a)?(r.size.width=o.width+l,r.size.height=o.height+c,r.position.left=u.left-l):(r.size.width=o.width+l,r.size.height=o.height+c,r.position.top=u.top-c,r.position.left=u.left-l)}});var n=function(e){return parseInt(e,10)||0},r=function(e){return!isNaN(parseInt(e,10))}})(jQuery);(function(e,t){e.widget("ui.selectable",e.ui.mouse,{version:"1.9.2",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch"},_create:function(){var t=this;this.element.addClass("ui-selectable"),this.dragged=!1;var n;this.refresh=function(){n=e(t.options.filter,t.element[0]),n.addClass("ui-selectee"),n.each(function(){var t=e(this),n=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:n.left,top:n.top,right:n.left+t.outerWidth(),bottom:n.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=n.addClass("ui-selectee"),this._mouseInit(),this.helper=e("<div class='ui-selectable-helper'></div>")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var n=this;this.opos=[t.pageX,t.pageY];if(this.options.disabled)return;var r=this.options;this.selectees=e(r.filter,this.element[0]),this._trigger("start",t),e(r.appendTo).append(this.helper),this.helper.css({left:t.clientX,top:t.clientY,width:0,height:0}),r.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var r=e.data(this,"selectable-item");r.startselected=!0,!t.metaKey&&!t.ctrlKey&&(r.$element.removeClass("ui-selected"),r.selected=!1,r.$element.addClass("ui-unselecting"),r.unselecting=!0,n._trigger("unselecting",t,{unselecting:r.element}))}),e(t.target).parents().andSelf().each(function(){var r=e.data(this,"selectable-item");if(r){var i=!t.metaKey&&!t.ctrlKey||!r.$element.hasClass("ui-selected");return r.$element.removeClass(i?"ui-unselecting":"ui-selected").addClass(i?"ui-selecting":"ui-unselecting"),r.unselecting=!i,r.selecting=i,r.selected=i,i?n._trigger("selecting",t,{selecting:r.element}):n._trigger("unselecting",t,{unselecting:r.element}),!1}})},_mouseDrag:function(t){var n=this;this.dragged=!0;if(this.options.disabled)return;var r=this.options,i=this.opos[0],s=this.opos[1],o=t.pageX,u=t.pageY;if(i>o){var a=o;o=i,i=a}if(s>u){var a=u;u=s,s=a}return this.helper.css({left:i,top:s,width:o-i,height:u-s}),this.selectees.each(function(){var a=e.data(this,"selectable-item");if(!a||a.element==n.element[0])return;var f=!1;r.tolerance=="touch"?f=!(a.left>o||a.right<i||a.top>u||a.bottom<s):r.tolerance=="fit"&&(f=a.left>i&&a.right<o&&a.top>s&&a.bottom<u),f?(a.selected&&(a.$element.removeClass("ui-selected"),a.selected=!1),a.unselecting&&(a.$element.removeClass("ui-unselecting"),a.unselecting=!1),a.selecting||(a.$element.addClass("ui-selecting"),a.selecting=!0,n._trigger("selecting",t,{selecting:a.element}))):(a.selecting&&((t.metaKey||t.ctrlKey)&&a.startselected?(a.$element.removeClass("ui-selecting"),a.selecting=!1,a.$element.addClass("ui-selected"),a.selected=!0):(a.$element.removeClass("ui-selecting"),a.selecting=!1,a.startselected&&(a.$element.addClass("ui-unselecting"),a.unselecting=!0),n._trigger("unselecting",t,{unselecting:a.element}))),a.selected&&!t.metaKey&&!t.ctrlKey&&!a.startselected&&(a.$element.removeClass("ui-selected"),a.selected=!1,a.$element.addClass("ui-unselecting"),a.unselecting=!0,n._trigger("unselecting",t,{unselecting:a.element})))}),!1},_mouseStop:function(t){var n=this;this.dragged=!1;var r=this.options;return e(".ui-unselecting",this.element[0]).each(function(){var r=e.data(this,"selectable-item");r.$element.removeClass("ui-unselecting"),r.unselecting=!1,r.startselected=!1,n._trigger("unselected",t,{unselected:r.element})}),e(".ui-selecting",this.element[0]).each(function(){var r=e.data(this,"selectable-item");r.$element.removeClass("ui-selecting").addClass("ui-selected"),r.selecting=!1,r.selected=!0,r.startselected=!0,n._trigger("selected",t,{selected:r.element})}),this._trigger("stop",t),this.helper.remove(),!1}})})(jQuery);(function(e,t){e.widget("ui.sortable",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3},_create:function(){var e=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?e.axis==="x"||/left|right/.test(this.items[0].item.css("float"))||/inline|table-cell/.test(this.items[0].item.css("display")):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var e=this.items.length-1;e>=0;e--)this.items[e].item.removeData(this.widgetName+"-item");return this},_setOption:function(t,n){t==="disabled"?(this.options[t]=n,this.widget().toggleClass("ui-sortable-disabled",!!n)):e.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(t,n){var r=this;if(this.reverting)return!1;if(this.options.disabled||this.options.type=="static")return!1;this._refreshItems(t);var i=null,s=e(t.target).parents().each(function(){if(e.data(this,r.widgetName+"-item")==r)return i=e(this),!1});e.data(t.target,r.widgetName+"-item")==r&&(i=e(t.target));if(!i)return!1;if(this.options.handle&&!n){var o=!1;e(this.options.handle,i).find("*").andSelf().each(function(){this==t.target&&(o=!0)});if(!o)return!1}return this.currentItem=i,this._removeCurrentsFromItems(),!0},_mouseStart:function(t,n,r){var i=this.options;this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!=this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),i.containment&&this._setContainment(),i.cursor&&(e("body").css("cursor")&&(this._storedCursor=e("body").css("cursor")),e("body").css("cursor",i.cursor)),i.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",i.opacity)),i.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",i.zIndex)),this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions();if(!r)for(var s=this.containers.length-1;s>=0;s--)this.containers[s]._trigger("activate",t,this._uiHash(this));return e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(t),!0},_mouseDrag:function(t){this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs);if(this.options.scroll){var n=this.options,r=!1;this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY<n.scrollSensitivity?this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop+n.scrollSpeed:t.pageY-this.overflowOffset.top<n.scrollSensitivity&&(this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop-n.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-t.pageX<n.scrollSensitivity?this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft+n.scrollSpeed:t.pageX-this.overflowOffset.left<n.scrollSensitivity&&(this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft-n.scrollSpeed)):(t.pageY-e(document).scrollTop()<n.scrollSensitivity?r=e(document).scrollTop(e(document).scrollTop()-n.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<n.scrollSensitivity&&(r=e(document).scrollTop(e(document).scrollTop()+n.scrollSpeed)),t.pageX-e(document).scrollLeft()<n.scrollSensitivity?r=e(document).scrollLeft(e(document).scrollLeft()-n.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<n.scrollSensitivity&&(r=e(document).scrollLeft(e(document).scrollLeft()+n.scrollSpeed))),r!==!1&&e.ui.ddmanager&&!n.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t)}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y")this.helper[0].style.left=this.position.left+"px";if(!this.options.axis||this.options.axis!="x")this.helper[0].style.top=this.position.top+"px";for(var i=this.items.length-1;i>=0;i--){var s=this.items[i],o=s.item[0],u=this._intersectsWithPointer(s);if(!u)continue;if(s.instance!==this.currentContainer)continue;if(o!=this.currentItem[0]&&this.placeholder[u==1?"next":"prev"]()[0]!=o&&!e.contains(this.placeholder[0],o)&&(this.options.type=="semi-dynamic"?!e.contains(this.element[0],o):!0)){this.direction=u==1?"down":"up";if(this.options.tolerance!="pointer"&&!this._intersectsWithSides(s))break;this._rearrange(t,s),this._trigger("change",t,this._uiHash());break}}return this._contactContainers(t),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),this._trigger("sort",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,n){if(!t)return;e.ui.ddmanager&&!this.options.dropBehaviour&&e.ui.ddmanager.drop(this,t);if(this.options.revert){var r=this,i=this.placeholder.offset();this.reverting=!0,e(this.helper).animate({left:i.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:i.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){r._clear(t)})}else this._clear(t,n);return!1},cancel:function(){if(this.dragging){this._mouseUp({target:null}),this.options.helper=="original"?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var t=this.containers.length-1;t>=0;t--)this.containers[t]._trigger("deactivate",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger("out",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.options.helper!="original"&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),e.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?e(this.domPosition.prev).after(this.currentItem):e(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},e(n).each(function(){var n=(e(t.item||this).attr(t.attribute||"id")||"").match(t.expression||/(.+)[-=_](.+)/);n&&r.push((t.key||n[1]+"[]")+"="+(t.key&&t.expression?n[1]:n[2]))}),!r.length&&t.key&&r.push(t.key+"="),r.join("&")},toArray:function(t){var n=this._getItemsAsjQuery(t&&t.connected),r=[];return t=t||{},n.each(function(){r.push(e(t.item||this).attr(t.attribute||"id")||"")}),r},_intersectsWith:function(e){var t=this.positionAbs.left,n=t+this.helperProportions.width,r=this.positionAbs.top,i=r+this.helperProportions.height,s=e.left,o=s+e.width,u=e.top,a=u+e.height,f=this.offset.click.top,l=this.offset.click.left,c=r+f>u&&r+f<a&&t+l>s&&t+l<o;return this.options.tolerance=="pointer"||this.options.forcePointerForContainers||this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>e[this.floating?"width":"height"]?c:s<t+this.helperProportions.width/2&&n-this.helperProportions.width/2<o&&u<r+this.helperProportions.height/2&&i-this.helperProportions.height/2<a},_intersectsWithPointer:function(t){var n=this.options.axis==="x"||e.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,t.top,t.height),r=this.options.axis==="y"||e.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,t.left,t.width),i=n&&r,s=this._getDragVerticalDirection(),o=this._getDragHorizontalDirection();return i?this.floating?o&&o=="right"||s=="down"?2:1:s&&(s=="down"?2:1):!1},_intersectsWithSides:function(t){var n=e.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),r=e.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),i=this._getDragVerticalDirection(),s=this._getDragHorizontalDirection();return this.floating&&s?s=="right"&&r||s=="left"&&!r:i&&(i=="down"&&n||i=="up"&&!n)},_getDragVerticalDirection:function(){var e=this.positionAbs.top-this.lastPositionAbs.top;return e!=0&&(e>0?"down":"up")},_getDragHorizontalDirection:function(){var e=this.positionAbs.left-this.lastPositionAbs.left;return e!=0&&(e>0?"right":"left")},refresh:function(e){return this._refreshItems(e),this.refreshPositions(),this},_connectWith:function(){var e=this.options;return e.connectWith.constructor==String?[e.connectWith]:e.connectWith},_getItemsAsjQuery:function(t){var n=[],r=[],i=this._connectWith();if(i&&t)for(var s=i.length-1;s>=0;s--){var o=e(i[s]);for(var u=o.length-1;u>=0;u--){var a=e.data(o[u],this.widgetName);a&&a!=this&&!a.options.disabled&&r.push([e.isFunction(a.options.items)?a.options.items.call(a.element):e(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a])}}r.push([e.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):e(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]);for(var s=r.length-1;s>=0;s--)r[s][0].each(function(){n.push(this)});return e(n)},_removeCurrentsFromItems:function(){var t=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=e.grep(this.items,function(e){for(var n=0;n<t.length;n++)if(t[n]==e.item[0])return!1;return!0})},_refreshItems:function(t){this.items=[],this.containers=[this];var n=this.items,r=[[e.isFunction(this.options.items)?this.options.items.call(this.element[0],t,{item:this.currentItem}):e(this.options.items,this.element),this]],i=this._connectWith();if(i&&this.ready)for(var s=i.length-1;s>=0;s--){var o=e(i[s]);for(var u=o.length-1;u>=0;u--){var a=e.data(o[u],this.widgetName);a&&a!=this&&!a.options.disabled&&(r.push([e.isFunction(a.options.items)?a.options.items.call(a.element[0],t,{item:this.currentItem}):e(a.options.items,a.element),a]),this.containers.push(a))}}for(var s=r.length-1;s>=0;s--){var f=r[s][1],l=r[s][0];for(var u=0,c=l.length;u<c;u++){var h=e(l[u]);h.data(this.widgetName+"-item",f),n.push({item:h,instance:f,width:0,height:0,left:0,top:0})}}},refreshPositions:function(t){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());for(var n=this.items.length-1;n>=0;n--){var r=this.items[n];if(r.instance!=this.currentContainer&&this.currentContainer&&r.item[0]!=this.currentItem[0])continue;var i=this.options.toleranceElement?e(this.options.toleranceElement,r.item):r.item;t||(r.width=i.outerWidth(),r.height=i.outerHeight());var s=i.offset();r.left=s.left,r.top=s.top}if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(var n=this.containers.length-1;n>=0;n--){var s=this.containers[n].element.offset();this.containers[n].containerCache.left=s.left,this.containers[n].containerCache.top=s.top,this.containers[n].containerCache.width=this.containers[n].element.outerWidth(),this.containers[n].containerCache.height=this.containers[n].element.outerHeight()}return this},_createPlaceholder:function(t){t=t||this;var n=t.options;if(!n.placeholder||n.placeholder.constructor==String){var r=n.placeholder;n.placeholder={element:function(){var n=e(document.createElement(t.currentItem[0].nodeName)).addClass(r||t.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];return r||(n.style.visibility="hidden"),n},update:function(e,i){if(r&&!n.forcePlaceholderSize)return;i.height()||i.height(t.currentItem.innerHeight()-parseInt(t.currentItem.css("paddingTop")||0,10)-parseInt(t.currentItem.css("paddingBottom")||0,10)),i.width()||i.width(t.currentItem.innerWidth()-parseInt(t.currentItem.css("paddingLeft")||0,10)-parseInt(t.currentItem.css("paddingRight")||0,10))}}}t.placeholder=e(n.placeholder.element.call(t.element,t.currentItem)),t.currentItem.after(t.placeholder),n.placeholder.update(t,t.placeholder)},_contactContainers:function(t){var n=null,r=null;for(var i=this.containers.length-1;i>=0;i--){if(e.contains(this.currentItem[0],this.containers[i].element[0]))continue;if(this._intersectsWith(this.containers[i].containerCache)){if(n&&e.contains(this.containers[i].element[0],n.element[0]))continue;n=this.containers[i],r=i}else this.containers[i].containerCache.over&&(this.containers[i]._trigger("out",t,this._uiHash(this)),this.containers[i].containerCache.over=0)}if(!n)return;if(this.containers.length===1)this.containers[r]._trigger("over",t,this._uiHash(this)),this.containers[r].containerCache.over=1;else{var s=1e4,o=null,u=this.containers[r].floating?"left":"top",a=this.containers[r].floating?"width":"height",f=this.positionAbs[u]+this.offset.click[u];for(var l=this.items.length-1;l>=0;l--){if(!e.contains(this.containers[r].element[0],this.items[l].item[0]))continue;if(this.items[l].item[0]==this.currentItem[0])continue;var c=this.items[l].item.offset()[u],h=!1;Math.abs(c-f)>Math.abs(c+this.items[l][a]-f)&&(h=!0,c+=this.items[l][a]),Math.abs(c-f)<s&&(s=Math.abs(c-f),o=this.items[l],this.direction=h?"up":"down")}if(!o&&!this.options.dropOnEmpty)return;this.currentContainer=this.containers[r],o?this._rearrange(t,o,null,!0):this._rearrange(t,null,this.containers[r].element,!0),this._trigger("change",t,this._uiHash()),this.containers[r]._trigger("change",t,this._uiHash(this)),this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[r]._trigger("over",t,this._uiHash(this)),this.containers[r].containerCache.over=1}},_createHelper:function(t){var n=this.options,r=e.isFunction(n.helper)?e(n.helper.apply(this.element[0],[t,this.currentItem])):n.helper=="clone"?this.currentItem.clone():this.currentItem;return r.parents("body").length||e(n.appendTo!="parent"?n.appendTo:this.currentItem[0].parentNode)[0].appendChild(r[0]),r[0]==this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(r[0].style.width==""||n.forceHelperSize)&&r.width(this.currentItem.width()),(r[0].style.height==""||n.forceHelperSize)&&r.height(this.currentItem.height()),r},_adjustOffsetFromHelper:function(t){typeof t=="string"&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop());if(this.offsetParent[0]==document.body||this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&e.ui.ie)t={top:0,left:0};return{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var e=this.currentItem.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t=this.options;t.containment=="parent"&&(t.containment=this.helper[0].parentNode);if(t.containment=="document"||t.containment=="window")this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,e(t.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(e(t.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top];if(!/^(document|window|parent)$/.test(t.containment)){var n=e(t.containment)[0],r=e(t.containment).offset(),i=e(n).css("overflow")!="hidden";this.containment=[r.left+(parseInt(e(n).css("borderLeftWidth"),10)||0)+(parseInt(e(n).css("paddingLeft"),10)||0)-this.margins.left,r.top+(parseInt(e(n).css("borderTopWidth"),10)||0)+(parseInt(e(n).css("paddingTop"),10)||0)-this.margins.top,r.left+(i?Math.max(n.scrollWidth,n.offsetWidth):n.offsetWidth)-(parseInt(e(n).css("borderLeftWidth"),10)||0)-(parseInt(e(n).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,r.top+(i?Math.max(n.scrollHeight,n.offsetHeight):n.offsetHeight)-(parseInt(e(n).css("borderTopWidth"),10)||0)-(parseInt(e(n).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(t,n){n||(n=this.position);var r=t=="absolute"?1:-1,i=this.options,s=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,o=/(html|body)/i.test(s[0].tagName);return{top:n.top+this.offset.relative.top*r+this.offset.parent.top*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():o?0:s.scrollTop())*r,left:n.left+this.offset.relative.left*r+this.offset.parent.left*r-(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():o?0:s.scrollLeft())*r}},_generatePosition:function(t){var n=this.options,r=this.cssPosition!="absolute"||this.scrollParent[0]!=document&&!!e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,i=/(html|body)/i.test(r[0].tagName);this.cssPosition=="relative"&&(this.scrollParent[0]==document||this.scrollParent[0]==this.offsetParent[0])&&(this.offset.relative=this._getRelativeOffset());var s=t.pageX,o=t.pageY;if(this.originalPosition){this.containment&&(t.pageX-this.offset.click.left<this.containment[0]&&(s=this.containment[0]+this.offset.click.left),t.pageY-this.offset.click.top<this.containment[1]&&(o=this.containment[1]+this.offset.click.top),t.pageX-this.offset.click.left>this.containment[2]&&(s=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top));if(n.grid){var u=this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1];o=this.containment?u-this.offset.click.top<this.containment[1]||u-this.offset.click.top>this.containment[3]?u-this.offset.click.top<this.containment[1]?u+n.grid[1]:u-n.grid[1]:u:u;var a=this.originalPageX+Math.round((s-this.originalPageX)/n.grid[0])*n.grid[0];s=this.containment?a-this.offset.click.left<this.containment[0]||a-this.offset.click.left>this.containment[2]?a-this.offset.click.left<this.containment[0]?a+n.grid[0]:a-n.grid[0]:a:a}}return{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():i?0:r.scrollTop()),left:s-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:r.scrollLeft())}},_rearrange:function(e,t,n,r){n?n[0].appendChild(this.placeholder[0]):t.item[0].parentNode.insertBefore(this.placeholder[0],this.direction=="down"?t.item[0]:t.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var i=this.counter;this._delay(function(){i==this.counter&&this.refreshPositions(!r)})},_clear:function(t,n){this.reverting=!1;var r=[];!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var i in this._storedCSS)if(this._storedCSS[i]=="auto"||this._storedCSS[i]=="static")this._storedCSS[i]="";this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();this.fromOutside&&!n&&r.push(function(e){this._trigger("receive",e,this._uiHash(this.fromOutside))}),(this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!n&&r.push(function(e){this._trigger("update",e,this._uiHash())}),this!==this.currentContainer&&(n||(r.push(function(e){this._trigger("remove",e,this._uiHash())}),r.push(function(e){return function(t){e._trigger("receive",t,this._uiHash(this))}}.call(this,this.currentContainer)),r.push(function(e){return function(t){e._trigger("update",t,this._uiHash(this))}}.call(this,this.currentContainer))));for(var i=this.containers.length-1;i>=0;i--)n||r.push(function(e){return function(t){e._trigger("deactivate",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over&&(r.push(function(e){return function(t){e._trigger("out",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over=0);this._storedCursor&&e("body").css("cursor",this._storedCursor),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex),this.dragging=!1;if(this.cancelHelperRemoval){if(!n){this._trigger("beforeStop",t,this._uiHash());for(var i=0;i<r.length;i++)r[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!1}n||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!=this.currentItem[0]&&this.helper.remove(),this.helper=null;if(!n){for(var i=0;i<r.length;i++)r[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){e.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(t){var n=t||this;return{helper:n.helper,placeholder:n.placeholder||e([]),position:n.position,originalPosition:n.originalPosition,offset:n.positionAbs,item:n.currentItem,sender:t?t.element:null}}})})(jQuery);(function(e,t){var n=0,r={},i={};r.height=r.paddingTop=r.paddingBottom=r.borderTopWidth=r.borderBottomWidth="hide",i.height=i.paddingTop=i.paddingBottom=i.borderTopWidth=i.borderBottomWidth="show",e.widget("ui.accordion",{version:"1.9.2",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},_create:function(){var t=this.accordionId="ui-accordion-"+(this.element.attr("id")||++n),r=this.options;this.prevShow=this.prevHide=e(),this.element.addClass("ui-accordion ui-widget ui-helper-reset"),this.headers=this.element.find(r.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all"),this._hoverable(this.headers),this._focusable(this.headers),this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").hide(),!r.collapsible&&(r.active===!1||r.active==null)&&(r.active=0),r.active<0&&(r.active+=this.headers.length),this.active=this._findActive(r.active).addClass("ui-accordion-header-active ui-state-active").toggleClass("ui-corner-all ui-corner-top"),this.active.next().addClass("ui-accordion-content-active").show(),this._createIcons(),this.refresh(),this.element.attr("role","tablist"),this.headers.attr("role","tab").each(function(n){var r=e(this),i=r.attr("id"),s=r.next(),o=s.attr("id");i||(i=t+"-header-"+n,r.attr("id",i)),o||(o=t+"-panel-"+n,s.attr("id",o)),r.attr("aria-controls",o),s.attr("aria-labelledby",i)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false",tabIndex:-1}).next().attr({"aria-expanded":"false","aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true",tabIndex:0}).next().attr({"aria-expanded":"true","aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._on(this.headers,{keydown:"_keydown"}),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._setupEvents(r.event)},_getCreateEventData:function(){return{header:this.active,content:this.active.length?this.active.next():e()}},_createIcons:function(){var t=this.options.icons;t&&(e("<span>").addClass("ui-accordion-header-icon ui-icon "+t.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(t.header).addClass(t.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var e;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.removeClass("ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top").removeAttr("role").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this._destroyIcons(),e=this.headers.next().css("display","").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this.options.heightStyle!=="content"&&e.css("height","")},_setOption:function(e,t){if(e==="active"){this._activate(t);return}e==="event"&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(t)),this._super(e,t),e==="collapsible"&&!t&&this.options.active===!1&&this._activate(0),e==="icons"&&(this._destroyIcons(),t&&this._createIcons()),e==="disabled"&&this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!t)},_keydown:function(t){if(t.altKey||t.ctrlKey)return;var n=e.ui.keyCode,r=this.headers.length,i=this.headers.index(t.target),s=!1;switch(t.keyCode){case n.RIGHT:case n.DOWN:s=this.headers[(i+1)%r];break;case n.LEFT:case n.UP:s=this.headers[(i-1+r)%r];break;case n.SPACE:case n.ENTER:this._eventHandler(t);break;case n.HOME:s=this.headers[0];break;case n.END:s=this.headers[r-1]}s&&(e(t.target).attr("tabIndex",-1),e(s).attr("tabIndex",0),s.focus(),t.preventDefault())},_panelKeyDown:function(t){t.keyCode===e.ui.keyCode.UP&&t.ctrlKey&&e(t.currentTarget).prev().focus()},refresh:function(){var t,n,r=this.options.heightStyle,i=this.element.parent();r==="fill"?(e.support.minHeight||(n=i.css("overflow"),i.css("overflow","hidden")),t=i.height(),this.element.siblings(":visible").each(function(){var n=e(this),r=n.css("position");if(r==="absolute"||r==="fixed")return;t-=n.outerHeight(!0)}),n&&i.css("overflow",n),this.headers.each(function(){t-=e(this).outerHeight(!0)}),this.headers.next().each(function(){e(this).height(Math.max(0,t-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):r==="auto"&&(t=0,this.headers.next().each(function(){t=Math.max(t,e(this).css("height","").height())}).height(t))},_activate:function(t){var n=this._findActive(t)[0];if(n===this.active[0])return;n=n||this.active[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return typeof t=="number"?this.headers.eq(t):e()},_setupEvents:function(t){var n={};if(!t)return;e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._on(this.headers,n)},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i[0]===r[0],o=s&&n.collapsible,u=o?e():i.next(),a=r.next(),f={oldHeader:r,oldPanel:a,newHeader:o?e():i,newPanel:u};t.preventDefault();if(s&&!n.collapsible||this._trigger("beforeActivate",t,f)===!1)return;n.active=o?!1:this.headers.index(i),this.active=s?e():i,this._toggle(f),r.removeClass("ui-accordion-header-active ui-state-active"),n.icons&&r.children(".ui-accordion-header-icon").removeClass(n.icons.activeHeader).addClass(n.icons.header),s||(i.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),n.icons&&i.children(".ui-accordion-header-icon").removeClass(n.icons.header).addClass(n.icons.activeHeader),i.next().addClass("ui-accordion-content-active"))},_toggle:function(t){var n=t.newPanel,r=this.prevShow.length?this.prevShow:t.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=n,this.prevHide=r,this.options.animate?this._animate(n,r,t):(r.hide(),n.show(),this._toggleComplete(t)),r.attr({"aria-expanded":"false","aria-hidden":"true"}),r.prev().attr("aria-selected","false"),n.length&&r.length?r.prev().attr("tabIndex",-1):n.length&&this.headers.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),n.attr({"aria-expanded":"true","aria-hidden":"false"}).prev().attr({"aria-selected":"true",tabIndex:0})},_animate:function(e,t,n){var s,o,u,a=this,f=0,l=e.length&&(!t.length||e.index()<t.index()),c=this.options.animate||{},h=l&&c.down||c,p=function(){a._toggleComplete(n)};typeof h=="number"&&(u=h),typeof h=="string"&&(o=h),o=o||h.easing||c.easing,u=u||h.duration||c.duration;if(!t.length)return e.animate(i,u,o,p);if(!e.length)return t.animate(r,u,o,p);s=e.show().outerHeight(),t.animate(r,{duration:u,easing:o,step:function(e,t){t.now=Math.round(e)}}),e.hide().animate(i,{duration:u,easing:o,complete:p,step:function(e,n){n.now=Math.round(e),n.prop!=="height"?f+=n.now:a.options.heightStyle!=="content"&&(n.now=Math.round(s-t.outerHeight()-f),f=0)}})},_toggleComplete:function(e){var t=e.oldPanel;t.removeClass("ui-accordion-content-active").prev().removeClass("ui-corner-top").addClass("ui-corner-all"),t.length&&(t.parent()[0].className=t.parent()[0].className),this._trigger("activate",null,e)}}),e.uiBackCompat!==!1&&(function(e,t){e.extend(t.options,{navigation:!1,navigationFilter:function(){return this.href.toLowerCase()===location.href.toLowerCase()}});var n=t._create;t._create=function(){if(this.options.navigation){var t=this,r=this.element.find(this.options.header),i=r.next(),s=r.add(i).find("a").filter(this.options.navigationFilter)[0];s&&r.add(i).each(function(n){if(e.contains(this,s))return t.options.active=Math.floor(n/2),!1})}n.call(this)}}(jQuery,jQuery.ui.accordion.prototype),function(e,t){e.extend(t.options,{heightStyle:null,autoHeight:!0,clearStyle:!1,fillSpace:!1});var n=t._create,r=t._setOption;e.extend(t,{_create:function(){this.options.heightStyle=this.options.heightStyle||this._mergeHeightStyle(),n.call(this)},_setOption:function(e){if(e==="autoHeight"||e==="clearStyle"||e==="fillSpace")this.options.heightStyle=this._mergeHeightStyle();r.apply(this,arguments)},_mergeHeightStyle:function(){var e=this.options;if(e.fillSpace)return"fill";if(e.clearStyle)return"content";if(e.autoHeight)return"auto"}})}(jQuery,jQuery.ui.accordion.prototype),function(e,t){e.extend(t.options.icons,{activeHeader:null,headerSelected:"ui-icon-triangle-1-s"});var n=t._createIcons;t._createIcons=function(){this.options.icons&&(this.options.icons.activeHeader=this.options.icons.activeHeader||this.options.icons.headerSelected),n.call(this)}}(jQuery,jQuery.ui.accordion.prototype),function(e,t){t.activate=t._activate;var n=t._findActive;t._findActive=function(e){return e===-1&&(e=!1),e&&typeof e!="number"&&(e=this.headers.index(this.headers.filter(e)),e===-1&&(e=!1)),n.call(this,e)}}(jQuery,jQuery.ui.accordion.prototype),jQuery.ui.accordion.prototype.resize=jQuery.ui.accordion.prototype.refresh,function(e,t){e.extend(t.options,{change:null,changestart:null});var n=t._trigger;t._trigger=function(e,t,r){var i=n.apply(this,arguments);return i?(e==="beforeActivate"?i=n.call(this,"changestart",t,{oldHeader:r.oldHeader,oldContent:r.oldPanel,newHeader:r.newHeader,newContent:r.newPanel}):e==="activate"&&(i=n.call(this,"change",t,{oldHeader:r.oldHeader,oldContent:r.oldPanel,newHeader:r.newHeader,newContent:r.newPanel})),i):!1}}(jQuery,jQuery.ui.accordion.prototype),function(e,t){e.extend(t.options,{animate:null,animated:"slide"});var n=t._create;t._create=function(){var e=this.options;e.animate===null&&(e.animated?e.animated==="slide"?e.animate=300:e.animated==="bounceslide"?e.animate={duration:200,down:{easing:"easeOutBounce",duration:1e3}}:e.animate=e.animated:e.animate=!1),n.call(this)}}(jQuery,jQuery.ui.accordion.prototype))})(jQuery);(function(e,t){var n=0;e.widget("ui.autocomplete",{version:"1.9.2",defaultElement:"<input>",options:{appendTo:"body",autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},pending:0,_create:function(){var t,n,r;this.isMultiLine=this._isMultiLine(),this.valueMethod=this.element[this.element.is("input,textarea")?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(i){if(this.element.prop("readOnly")){t=!0,r=!0,n=!0;return}t=!1,r=!1,n=!1;var s=e.ui.keyCode;switch(i.keyCode){case s.PAGE_UP:t=!0,this._move("previousPage",i);break;case s.PAGE_DOWN:t=!0,this._move("nextPage",i);break;case s.UP:t=!0,this._keyEvent("previous",i);break;case s.DOWN:t=!0,this._keyEvent("next",i);break;case s.ENTER:case s.NUMPAD_ENTER:this.menu.active&&(t=!0,i.preventDefault(),this.menu.select(i));break;case s.TAB:this.menu.active&&this.menu.select(i);break;case s.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(i),i.preventDefault());break;default:n=!0,this._searchTimeout(i)}},keypress:function(r){if(t){t=!1,r.preventDefault();return}if(n)return;var i=e.ui.keyCode;switch(r.keyCode){case i.PAGE_UP:this._move("previousPage",r);break;case i.PAGE_DOWN:this._move("nextPage",r);break;case i.UP:this._keyEvent("previous",r);break;case i.DOWN:this._keyEvent("next",r)}},input:function(e){if(r){r=!1,e.preventDefault();return}this._searchTimeout(e)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}clearTimeout(this.searching),this.close(e),this._change(e)}}),this._initSource(),this.menu=e("<ul>").addClass("ui-autocomplete").appendTo(this.document.find(this.options.appendTo||"body")[0]).menu({input:e(),role:null}).zIndex(this.element.zIndex()+1).hide().data("menu"),this._on(this.menu.element,{mousedown:function(t){t.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var n=this.menu.element[0];e(t.target).closest(".ui-menu-item").length||this._delay(function(){var t=this;this.document.one("mousedown",function(r){r.target!==t.element[0]&&r.target!==n&&!e.contains(n,r.target)&&t.close()})})},menufocus:function(t,n){if(this.isNewMenu){this.isNewMenu=!1;if(t.originalEvent&&/^mouse/.test(t.originalEvent.type)){this.menu.blur(),this.document.one("mousemove",function(){e(t.target).trigger(t.originalEvent)});return}}var r=n.item.data("ui-autocomplete-item")||n.item.data("item.autocomplete");!1!==this._trigger("focus",t,{item:r})?t.originalEvent&&/^key/.test(t.originalEvent.type)&&this._value(r.value):this.liveRegion.text(r.value)},menuselect:function(e,t){var n=t.item.data("ui-autocomplete-item")||t.item.data("item.autocomplete"),r=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=r,this._delay(function(){this.previous=r,this.selectedItem=n})),!1!==this._trigger("select",e,{item:n})&&this._value(n.value),this.term=this._value(),this.close(e),this.selectedItem=n}}),this.liveRegion=e("<span>",{role:"status","aria-live":"polite"}).addClass("ui-helper-hidden-accessible").insertAfter(this.element),e.fn.bgiframe&&this.menu.element.bgiframe(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(e,t){this._super(e,t),e==="source"&&this._initSource(),e==="appendTo"&&this.menu.element.appendTo(this.document.find(t||"body")[0]),e==="disabled"&&t&&this.xhr&&this.xhr.abort()},_isMultiLine:function(){return this.element.is("textarea")?!0:this.element.is("input")?!1:this.element.prop("isContentEditable")},_initSource:function(){var t,n,r=this;e.isArray(this.options.source)?(t=this.options.source,this.source=function(n,r){r(e.ui.autocomplete.filter(t,n.term))}):typeof this.options.source=="string"?(n=this.options.source,this.source=function(t,i){r.xhr&&r.xhr.abort(),r.xhr=e.ajax({url:n,data:t,dataType:"json",success:function(e){i(e)},error:function(){i([])}})}):this.source=this.options.source},_searchTimeout:function(e){clearTimeout(this.searching),this.searching=this._delay(function(){this.term!==this._value()&&(this.selectedItem=null,this.search(null,e))},this.options.delay)},search:function(e,t){e=e!=null?e:this._value(),this.term=this._value();if(e.length<this.options.minLength)return this.close(t);if(this._trigger("search",t)===!1)return;return this._search(e)},_search:function(e){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:e},this._response())},_response:function(){var e=this,t=++n;return function(r){t===n&&e.__response(r),e.pending--,e.pending||e.element.removeClass("ui-autocomplete-loading")}},__response:function(e){e&&(e=this._normalize(e)),this._trigger("response",null,{content:e}),!this.options.disabled&&e&&e.length&&!this.cancelSearch?(this._suggest(e),this._trigger("open")):this._close()},close:function(e){this.cancelSearch=!0,this._close(e)},_close:function(e){this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",e))},_change:function(e){this.previous!==this._value()&&this._trigger("change",e,{item:this.selectedItem})},_normalize:function(t){return t.length&&t[0].label&&t[0].value?t:e.map(t,function(t){return typeof t=="string"?{label:t,value:t}:e.extend({label:t.label||t.value,value:t.value||t.label},t)})},_suggest:function(t){var n=this.menu.element.empty().zIndex(this.element.zIndex()+1);this._renderMenu(n,t),this.menu.refresh(),n.show(),this._resizeMenu(),n.position(e.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next()},_resizeMenu:function(){var e=this.menu.element;e.outerWidth(Math.max(e.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(t,n){var r=this;e.each(n,function(e,n){r._renderItemData(t,n)})},_renderItemData:function(e,t){return this._renderItem(e,t).data("ui-autocomplete-item",t)},_renderItem:function(t,n){return e("<li>").append(e("<a>").text(n.label)).appendTo(t)},_move:function(e,t){if(!this.menu.element.is(":visible")){this.search(null,t);return}if(this.menu.isFirstItem()&&/^previous/.test(e)||this.menu.isLastItem()&&/^next/.test(e)){this._value(this.term),this.menu.blur();return}this.menu[e](t)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(e,t){if(!this.isMultiLine||this.menu.element.is(":visible"))this._move(e,t),t.preventDefault()}}),e.extend(e.ui.autocomplete,{escapeRegex:function(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(t,n){var r=new RegExp(e.ui.autocomplete.escapeRegex(n),"i");return e.grep(t,function(e){return r.test(e.label||e.value||e)})}}),e.widget("ui.autocomplete",e.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(e){return e+(e>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(e){var t;this._superApply(arguments);if(this.options.disabled||this.cancelSearch)return;e&&e.length?t=this.options.messages.results(e.length):t=this.options.messages.noResults,this.liveRegion.text(t)}})})(jQuery);(function(e,t){var n,r,i,s,o="ui-button ui-widget ui-state-default ui-corner-all",u="ui-state-hover ui-state-active ",a="ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",f=function(){var t=e(this).find(":ui-button");setTimeout(function(){t.button("refresh")},1)},l=function(t){var n=t.name,r=t.form,i=e([]);return n&&(r?i=e(r).find("[name='"+n+"']"):i=e("[name='"+n+"']",t.ownerDocument).filter(function(){return!this.form})),i};e.widget("ui.button",{version:"1.9.2",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,f),typeof this.options.disabled!="boolean"?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var t=this,u=this.options,a=this.type==="checkbox"||this.type==="radio",c=a?"":"ui-state-active",h="ui-state-focus";u.label===null&&(u.label=this.type==="input"?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(o).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){if(u.disabled)return;this===n&&e(this).addClass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){if(u.disabled)return;e(this).removeClass(c)}).bind("click"+this.eventNamespace,function(e){u.disabled&&(e.preventDefault(),e.stopImmediatePropagation())}),this.element.bind("focus"+this.eventNamespace,function(){t.buttonElement.addClass(h)}).bind("blur"+this.eventNamespace,function(){t.buttonElement.removeClass(h)}),a&&(this.element.bind("change"+this.eventNamespace,function(){if(s)return;t.refresh()}),this.buttonElement.bind("mousedown"+this.eventNamespace,function(e){if(u.disabled)return;s=!1,r=e.pageX,i=e.pageY}).bind("mouseup"+this.eventNamespace,function(e){if(u.disabled)return;if(r!==e.pageX||i!==e.pageY)s=!0})),this.type==="checkbox"?this.buttonElement.bind("click"+this.eventNamespace,function(){if(u.disabled||s)return!1;e(this).toggleClass("ui-state-active"),t.buttonElement.attr("aria-pressed",t.element[0].checked)}):this.type==="radio"?this.buttonElement.bind("click"+this.eventNamespace,function(){if(u.disabled||s)return!1;e(this).addClass("ui-state-active"),t.buttonElement.attr("aria-pressed","true");var n=t.element[0];l(n).not(n).map(function(){return e(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){if(u.disabled)return!1;e(this).addClass("ui-state-active"),n=this,t.document.one("mouseup",function(){n=null})}).bind("mouseup"+this.eventNamespace,function(){if(u.disabled)return!1;e(this).removeClass("ui-state-active")}).bind("keydown"+this.eventNamespace,function(t){if(u.disabled)return!1;(t.keyCode===e.ui.keyCode.SPACE||t.keyCode===e.ui.keyCode.ENTER)&&e(this).addClass("ui-state-active")}).bind("keyup"+this.eventNamespace,function(){e(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(t){t.keyCode===e.ui.keyCode.SPACE&&e(this).click()})),this._setOption("disabled",u.disabled),this._resetButton()},_determineButtonType:function(){var e,t,n;this.element.is("[type=checkbox]")?this.type="checkbox":this.element.is("[type=radio]")?this.type="radio":this.element.is("input")?this.type="input":this.type="button",this.type==="checkbox"||this.type==="radio"?(e=this.element.parents().last(),t="label[for='"+this.element.attr("id")+"']",this.buttonElement=e.find(t),this.buttonElement.length||(e=e.length?e.siblings():this.element.siblings(),this.buttonElement=e.filter(t),this.buttonElement.length||(this.buttonElement=e.find(t))),this.element.addClass("ui-helper-hidden-accessible"),n=this.element.is(":checked"),n&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",n)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(o+" "+u+" "+a).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(e,t){this._super(e,t);if(e==="disabled"){t?this.element.prop("disabled",!0):this.element.prop("disabled",!1);return}this._resetButton()},refresh:function(){var t=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");t!==this.options.disabled&&this._setOption("disabled",t),this.type==="radio"?l(this.element[0]).each(function(){e(this).is(":checked")?e(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):e(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):this.type==="checkbox"&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if(this.type==="input"){this.options.label&&this.element.val(this.options.label);return}var t=this.buttonElement.removeClass(a),n=e("<span></span>",this.document[0]).addClass("ui-button-text").html(this.options.label).appendTo(t.empty()).text(),r=this.options.icons,i=r.primary&&r.secondary,s=[];r.primary||r.secondary?(this.options.text&&s.push("ui-button-text-icon"+(i?"s":r.primary?"-primary":"-secondary")),r.primary&&t.prepend("<span class='ui-button-icon-primary ui-icon "+r.primary+"'></span>"),r.secondary&&t.append("<span class='ui-button-icon-secondary ui-icon "+r.secondary+"'></span>"),this.options.text||(s.push(i?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||t.attr("title",e.trim(n)))):s.push("ui-button-text-only"),t.addClass(s.join(" "))}}),e.widget("ui.buttonset",{version:"1.9.2",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(e,t){e==="disabled"&&this.buttons.button("option",e,t),this._super(e,t)},refresh:function(){var t=this.element.css("direction")==="rtl";this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(t?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(t?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return e(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}})})(jQuery);(function($,undefined){function Datepicker(){this.debug=!1,this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},$.extend(this._defaults,this.regional[""]),this.dpDiv=bindHover($('<div id="'+this._mainDivId+'" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))}function bindHover(e){var t="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return e.delegate(t,"mouseout",function(){$(this).removeClass("ui-state-hover"),this.className.indexOf("ui-datepicker-prev")!=-1&&$(this).removeClass("ui-datepicker-prev-hover"),this.className.indexOf("ui-datepicker-next")!=-1&&$(this).removeClass("ui-datepicker-next-hover")}).delegate(t,"mouseover",function(){$.datepicker._isDisabledDatepicker(instActive.inline?e.parent()[0]:instActive.input[0])||($(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),$(this).addClass("ui-state-hover"),this.className.indexOf("ui-datepicker-prev")!=-1&&$(this).addClass("ui-datepicker-prev-hover"),this.className.indexOf("ui-datepicker-next")!=-1&&$(this).addClass("ui-datepicker-next-hover"))})}function extendRemove(e,t){$.extend(e,t);for(var n in t)if(t[n]==null||t[n]==undefined)e[n]=t[n];return e}$.extend($.ui,{datepicker:{version:"1.9.2"}});var PROP_NAME="datepicker",dpuuid=(new Date).getTime(),instActive;$.extend(Datepicker.prototype,{markerClassName:"hasDatepicker",maxRows:4,log:function(){this.debug&&console.log.apply("",arguments)},_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(e){return extendRemove(this._defaults,e||{}),this},_attachDatepicker:function(target,settings){var inlineSettings=null;for(var attrName in this._defaults){var attrValue=target.getAttribute("date:"+attrName);if(attrValue){inlineSettings=inlineSettings||{};try{inlineSettings[attrName]=eval(attrValue)}catch(err){inlineSettings[attrName]=attrValue}}}var nodeName=target.nodeName.toLowerCase(),inline=nodeName=="div"||nodeName=="span";target.id||(this.uuid+=1,target.id="dp"+this.uuid);var inst=this._newInst($(target),inline);inst.settings=$.extend({},settings||{},inlineSettings||{}),nodeName=="input"?this._connectDatepicker(target,inst):inline&&this._inlineDatepicker(target,inst)},_newInst:function(e,t){var n=e[0].id.replace(/([^A-Za-z0-9_-])/g,"\\\\$1");return{id:n,input:e,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:t,dpDiv:t?bindHover($('<div class="'+this._inlineClass+' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')):this.dpDiv}},_connectDatepicker:function(e,t){var n=$(e);t.append=$([]),t.trigger=$([]);if(n.hasClass(this.markerClassName))return;this._attachments(n,t),n.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp).bind("setData.datepicker",function(e,n,r){t.settings[n]=r}).bind("getData.datepicker",function(e,n){return this._get(t,n)}),this._autoSize(t),$.data(e,PROP_NAME,t),t.settings.disabled&&this._disableDatepicker(e)},_attachments:function(e,t){var n=this._get(t,"appendText"),r=this._get(t,"isRTL");t.append&&t.append.remove(),n&&(t.append=$('<span class="'+this._appendClass+'">'+n+"</span>"),e[r?"before":"after"](t.append)),e.unbind("focus",this._showDatepicker),t.trigger&&t.trigger.remove();var i=this._get(t,"showOn");(i=="focus"||i=="both")&&e.focus(this._showDatepicker);if(i=="button"||i=="both"){var s=this._get(t,"buttonText"),o=this._get(t,"buttonImage");t.trigger=$(this._get(t,"buttonImageOnly")?$("<img/>").addClass(this._triggerClass).attr({src:o,alt:s,title:s}):$('<button type="button"></button>').addClass(this._triggerClass).html(o==""?s:$("<img/>").attr({src:o,alt:s,title:s}))),e[r?"before":"after"](t.trigger),t.trigger.click(function(){return $.datepicker._datepickerShowing&&$.datepicker._lastInput==e[0]?$.datepicker._hideDatepicker():$.datepicker._datepickerShowing&&$.datepicker._lastInput!=e[0]?($.datepicker._hideDatepicker(),$.datepicker._showDatepicker(e[0])):$.datepicker._showDatepicker(e[0]),!1})}},_autoSize:function(e){if(this._get(e,"autoSize")&&!e.inline){var t=new Date(2009,11,20),n=this._get(e,"dateFormat");if(n.match(/[DM]/)){var r=function(e){var t=0,n=0;for(var r=0;r<e.length;r++)e[r].length>t&&(t=e[r].length,n=r);return n};t.setMonth(r(this._get(e,n.match(/MM/)?"monthNames":"monthNamesShort"))),t.setDate(r(this._get(e,n.match(/DD/)?"dayNames":"dayNamesShort"))+20-t.getDay())}e.input.attr("size",this._formatDate(e,t).length)}},_inlineDatepicker:function(e,t){var n=$(e);if(n.hasClass(this.markerClassName))return;n.addClass(this.markerClassName).append(t.dpDiv).bind("setData.datepicker",function(e,n,r){t.settings[n]=r}).bind("getData.datepicker",function(e,n){return this._get(t,n)}),$.data(e,PROP_NAME,t),this._setDate(t,this._getDefaultDate(t),!0),this._updateDatepicker(t),this._updateAlternate(t),t.settings.disabled&&this._disableDatepicker(e),t.dpDiv.css("display","block")},_dialogDatepicker:function(e,t,n,r,i){var s=this._dialogInst;if(!s){this.uuid+=1;var o="dp"+this.uuid;this._dialogInput=$('<input type="text" id="'+o+'" style="position: absolute; top: -100px; width: 0px;"/>'),this._dialogInput.keydown(this._doKeyDown),$("body").append(this._dialogInput),s=this._dialogInst=this._newInst(this._dialogInput,!1),s.settings={},$.data(this._dialogInput[0],PROP_NAME,s)}extendRemove(s.settings,r||{}),t=t&&t.constructor==Date?this._formatDate(s,t):t,this._dialogInput.val(t),this._pos=i?i.length?i:[i.pageX,i.pageY]:null;if(!this._pos){var u=document.documentElement.clientWidth,a=document.documentElement.clientHeight,f=document.documentElement.scrollLeft||document.body.scrollLeft,l=document.documentElement.scrollTop||document.body.scrollTop;this._pos=[u/2-100+f,a/2-150+l]}return this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),s.settings.onSelect=n,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),$.blockUI&&$.blockUI(this.dpDiv),$.data(this._dialogInput[0],PROP_NAME,s),this},_destroyDatepicker:function(e){var t=$(e),n=$.data(e,PROP_NAME);if(!t.hasClass(this.markerClassName))return;var r=e.nodeName.toLowerCase();$.removeData(e,PROP_NAME),r=="input"?(n.append.remove(),n.trigger.remove(),t.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):(r=="div"||r=="span")&&t.removeClass(this.markerClassName).empty()},_enableDatepicker:function(e){var t=$(e),n=$.data(e,PROP_NAME);if(!t.hasClass(this.markerClassName))return;var r=e.nodeName.toLowerCase();if(r=="input")e.disabled=!1,n.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""});else if(r=="div"||r=="span"){var i=t.children("."+this._inlineClass);i.children().removeClass("ui-state-disabled"),i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)}this._disabledInputs=$.map(this._disabledInputs,function(t){return t==e?null:t})},_disableDatepicker:function(e){var t=$(e),n=$.data(e,PROP_NAME);if(!t.hasClass(this.markerClassName))return;var r=e.nodeName.toLowerCase();if(r=="input")e.disabled=!0,n.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"});else if(r=="div"||r=="span"){var i=t.children("."+this._inlineClass);i.children().addClass("ui-state-disabled"),i.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)}this._disabledInputs=$.map(this._disabledInputs,function(t){return t==e?null:t}),this._disabledInputs[this._disabledInputs.length]=e},_isDisabledDatepicker:function(e){if(!e)return!1;for(var t=0;t<this._disabledInputs.length;t++)if(this._disabledInputs[t]==e)return!0;return!1},_getInst:function(e){try{return $.data(e,PROP_NAME)}catch(t){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(e,t,n){var r=this._getInst(e);if(arguments.length==2&&typeof t=="string")return t=="defaults"?$.extend({},$.datepicker._defaults):r?t=="all"?$.extend({},r.settings):this._get(r,t):null;var i=t||{};typeof t=="string"&&(i={},i[t]=n);if(r){this._curInst==r&&this._hideDatepicker();var s=this._getDateDatepicker(e,!0),o=this._getMinMaxDate(r,"min"),u=this._getMinMaxDate(r,"max");extendRemove(r.settings,i),o!==null&&i.dateFormat!==undefined&&i.minDate===undefined&&(r.settings.minDate=this._formatDate(r,o)),u!==null&&i.dateFormat!==undefined&&i.maxDate===undefined&&(r.settings.maxDate=this._formatDate(r,u)),this._attachments($(e),r),this._autoSize(r),this._setDate(r,s),this._updateAlternate(r),this._updateDatepicker(r)}},_changeDatepicker:function(e,t,n){this._optionDatepicker(e,t,n)},_refreshDatepicker:function(e){var t=this._getInst(e);t&&this._updateDatepicker(t)},_setDateDatepicker:function(e,t){var n=this._getInst(e);n&&(this._setDate(n,t),this._updateDatepicker(n),this._updateAlternate(n))},_getDateDatepicker:function(e,t){var n=this._getInst(e);return n&&!n.inline&&this._setDateFromField(n,t),n?this._getDate(n):null},_doKeyDown:function(e){var t=$.datepicker._getInst(e.target),n=!0,r=t.dpDiv.is(".ui-datepicker-rtl");t._keyEvent=!0;if($.datepicker._datepickerShowing)switch(e.keyCode){case 9:$.datepicker._hideDatepicker(),n=!1;break;case 13:var i=$("td."+$.datepicker._dayOverClass+":not(."+$.datepicker._currentClass+")",t.dpDiv);i[0]&&$.datepicker._selectDay(e.target,t.selectedMonth,t.selectedYear,i[0]);var s=$.datepicker._get(t,"onSelect");if(s){var o=$.datepicker._formatDate(t);s.apply(t.input?t.input[0]:null,[o,t])}else $.datepicker._hideDatepicker();return!1;case 27:$.datepicker._hideDatepicker();break;case 33:$.datepicker._adjustDate(e.target,e.ctrlKey?-$.datepicker._get(t,"stepBigMonths"):-$.datepicker._get(t,"stepMonths"),"M");break;case 34:$.datepicker._adjustDate(e.target,e.ctrlKey?+$.datepicker._get(t,"stepBigMonths"):+$.datepicker._get(t,"stepMonths"),"M");break;case 35:(e.ctrlKey||e.metaKey)&&$.datepicker._clearDate(e.target),n=e.ctrlKey||e.metaKey;break;case 36:(e.ctrlKey||e.metaKey)&&$.datepicker._gotoToday(e.target),n=e.ctrlKey||e.metaKey;break;case 37:(e.ctrlKey||e.metaKey)&&$.datepicker._adjustDate(e.target,r?1:-1,"D"),n=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&$.datepicker._adjustDate(e.target,e.ctrlKey?-$.datepicker._get(t,"stepBigMonths"):-$.datepicker._get(t,"stepMonths"),"M");break;case 38:(e.ctrlKey||e.metaKey)&&$.datepicker._adjustDate(e.target,-7,"D"),n=e.ctrlKey||e.metaKey;break;case 39:(e.ctrlKey||e.metaKey)&&$.datepicker._adjustDate(e.target,r?-1:1,"D"),n=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&$.datepicker._adjustDate(e.target,e.ctrlKey?+$.datepicker._get(t,"stepBigMonths"):+$.datepicker._get(t,"stepMonths"),"M");break;case 40:(e.ctrlKey||e.metaKey)&&$.datepicker._adjustDate(e.target,7,"D"),n=e.ctrlKey||e.metaKey;break;default:n=!1}else e.keyCode==36&&e.ctrlKey?$.datepicker._showDatepicker(this):n=!1;n&&(e.preventDefault(),e.stopPropagation())},_doKeyPress:function(e){var t=$.datepicker._getInst(e.target);if($.datepicker._get(t,"constrainInput")){var n=$.datepicker._possibleChars($.datepicker._get(t,"dateFormat")),r=String.fromCharCode(e.charCode==undefined?e.keyCode:e.charCode);return e.ctrlKey||e.metaKey||r<" "||!n||n.indexOf(r)>-1}},_doKeyUp:function(e){var t=$.datepicker._getInst(e.target);if(t.input.val()!=t.lastVal)try{var n=$.datepicker.parseDate($.datepicker._get(t,"dateFormat"),t.input?t.input.val():null,$.datepicker._getFormatConfig(t));n&&($.datepicker._setDateFromField(t),$.datepicker._updateAlternate(t),$.datepicker._updateDatepicker(t))}catch(r){$.datepicker.log(r)}return!0},_showDatepicker:function(e){e=e.target||e,e.nodeName.toLowerCase()!="input"&&(e=$("input",e.parentNode)[0]);if($.datepicker._isDisabledDatepicker(e)||$.datepicker._lastInput==e)return;var t=$.datepicker._getInst(e);$.datepicker._curInst&&$.datepicker._curInst!=t&&($.datepicker._curInst.dpDiv.stop(!0,!0),t&&$.datepicker._datepickerShowing&&$.datepicker._hideDatepicker($.datepicker._curInst.input[0]));var n=$.datepicker._get(t,"beforeShow"),r=n?n.apply(e,[e,t]):{};if(r===!1)return;extendRemove(t.settings,r),t.lastVal=null,$.datepicker._lastInput=e,$.datepicker._setDateFromField(t),$.datepicker._inDialog&&(e.value=""),$.datepicker._pos||($.datepicker._pos=$.datepicker._findPos(e),$.datepicker._pos[1]+=e.offsetHeight);var i=!1;$(e).parents().each(function(){return i|=$(this).css("position")=="fixed",!i});var s={left:$.datepicker._pos[0],top:$.datepicker._pos[1]};$.datepicker._pos=null,t.dpDiv.empty(),t.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),$.datepicker._updateDatepicker(t),s=$.datepicker._checkOffset(t,s,i),t.dpDiv.css({position:$.datepicker._inDialog&&$.blockUI?"static":i?"fixed":"absolute",display:"none",left:s.left+"px",top:s.top+"px"});if(!t.inline){var o=$.datepicker._get(t,"showAnim"),u=$.datepicker._get(t,"duration"),a=function(){var e=t.dpDiv.find("iframe.ui-datepicker-cover");if(!!e.length){var n=$.datepicker._getBorders(t.dpDiv);e.css({left:-n[0],top:-n[1],width:t.dpDiv.outerWidth(),height:t.dpDiv.outerHeight()})}};t.dpDiv.zIndex($(e).zIndex()+1),$.datepicker._datepickerShowing=!0,$.effects&&($.effects.effect[o]||$.effects[o])?t.dpDiv.show(o,$.datepicker._get(t,"showOptions"),u,a):t.dpDiv[o||"show"](o?u:null,a),(!o||!u)&&a(),t.input.is(":visible")&&!t.input.is(":disabled")&&t.input.focus(),$.datepicker._curInst=t}},_updateDatepicker:function(e){this.maxRows=4;var t=$.datepicker._getBorders(e.dpDiv);instActive=e,e.dpDiv.empty().append(this._generateHTML(e)),this._attachHandlers(e);var n=e.dpDiv.find("iframe.ui-datepicker-cover");!n.length||n.css({left:-t[0],top:-t[1],width:e.dpDiv.outerWidth(),height:e.dpDiv.outerHeight()}),e.dpDiv.find("."+this._dayOverClass+" a").mouseover();var r=this._getNumberOfMonths(e),i=r[1],s=17;e.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),i>1&&e.dpDiv.addClass("ui-datepicker-multi-"+i).css("width",s*i+"em"),e.dpDiv[(r[0]!=1||r[1]!=1?"add":"remove")+"Class"]("ui-datepicker-multi"),e.dpDiv[(this._get(e,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),e==$.datepicker._curInst&&$.datepicker._datepickerShowing&&e.input&&e.input.is(":visible")&&!e.input.is(":disabled")&&e.input[0]!=document.activeElement&&e.input.focus();if(e.yearshtml){var o=e.yearshtml;setTimeout(function(){o===e.yearshtml&&e.yearshtml&&e.dpDiv.find("select.ui-datepicker-year:first").replaceWith(e.yearshtml),o=e.yearshtml=null},0)}},_getBorders:function(e){var t=function(e){return{thin:1,medium:2,thick:3}[e]||e};return[parseFloat(t(e.css("border-left-width"))),parseFloat(t(e.css("border-top-width")))]},_checkOffset:function(e,t,n){var r=e.dpDiv.outerWidth(),i=e.dpDiv.outerHeight(),s=e.input?e.input.outerWidth():0,o=e.input?e.input.outerHeight():0,u=document.documentElement.clientWidth+(n?0:$(document).scrollLeft()),a=document.documentElement.clientHeight+(n?0:$(document).scrollTop());return t.left-=this._get(e,"isRTL")?r-s:0,t.left-=n&&t.left==e.input.offset().left?$(document).scrollLeft():0,t.top-=n&&t.top==e.input.offset().top+o?$(document).scrollTop():0,t.left-=Math.min(t.left,t.left+r>u&&u>r?Math.abs(t.left+r-u):0),t.top-=Math.min(t.top,t.top+i>a&&a>i?Math.abs(i+o):0),t},_findPos:function(e){var t=this._getInst(e),n=this._get(t,"isRTL");while(e&&(e.type=="hidden"||e.nodeType!=1||$.expr.filters.hidden(e)))e=e[n?"previousSibling":"nextSibling"];var r=$(e).offset();return[r.left,r.top]},_hideDatepicker:function(e){var t=this._curInst;if(!t||e&&t!=$.data(e,PROP_NAME))return;if(this._datepickerShowing){var n=this._get(t,"showAnim"),r=this._get(t,"duration"),i=function(){$.datepicker._tidyDialog(t)};$.effects&&($.effects.effect[n]||$.effects[n])?t.dpDiv.hide(n,$.datepicker._get(t,"showOptions"),r,i):t.dpDiv[n=="slideDown"?"slideUp":n=="fadeIn"?"fadeOut":"hide"](n?r:null,i),n||i(),this._datepickerShowing=!1;var s=this._get(t,"onClose");s&&s.apply(t.input?t.input[0]:null,[t.input?t.input.val():"",t]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),$.blockUI&&($.unblockUI(),$("body").append(this.dpDiv))),this._inDialog=!1}},_tidyDialog:function(e){e.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(e){if(!$.datepicker._curInst)return;var t=$(e.target),n=$.datepicker._getInst(t[0]);(t[0].id!=$.datepicker._mainDivId&&t.parents("#"+$.datepicker._mainDivId).length==0&&!t.hasClass($.datepicker.markerClassName)&&!t.closest("."+$.datepicker._triggerClass).length&&$.datepicker._datepickerShowing&&(!$.datepicker._inDialog||!$.blockUI)||t.hasClass($.datepicker.markerClassName)&&$.datepicker._curInst!=n)&&$.datepicker._hideDatepicker()},_adjustDate:function(e,t,n){var r=$(e),i=this._getInst(r[0]);if(this._isDisabledDatepicker(r[0]))return;this._adjustInstDate(i,t+(n=="M"?this._get(i,"showCurrentAtPos"):0),n),this._updateDatepicker(i)},_gotoToday:function(e){var t=$(e),n=this._getInst(t[0]);if(this._get(n,"gotoCurrent")&&n.currentDay)n.selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear;else{var r=new Date;n.selectedDay=r.getDate(),n.drawMonth=n.selectedMonth=r.getMonth(),n.drawYear=n.selectedYear=r.getFullYear()}this._notifyChange(n),this._adjustDate(t)},_selectMonthYear:function(e,t,n){var r=$(e),i=this._getInst(r[0]);i["selected"+(n=="M"?"Month":"Year")]=i["draw"+(n=="M"?"Month":"Year")]=parseInt(t.options[t.selectedIndex].value,10),this._notifyChange(i),this._adjustDate(r)},_selectDay:function(e,t,n,r){var i=$(e);if($(r).hasClass(this._unselectableClass)||this._isDisabledDatepicker(i[0]))return;var s=this._getInst(i[0]);s.selectedDay=s.currentDay=$("a",r).html(),s.selectedMonth=s.currentMonth=t,s.selectedYear=s.currentYear=n,this._selectDate(e,this._formatDate(s,s.currentDay,s.currentMonth,s.currentYear))},_clearDate:function(e){var t=$(e),n=this._getInst(t[0]);this._selectDate(t,"")},_selectDate:function(e,t){var n=$(e),r=this._getInst(n[0]);t=t!=null?t:this._formatDate(r),r.input&&r.input.val(t),this._updateAlternate(r);var i=this._get(r,"onSelect");i?i.apply(r.input?r.input[0]:null,[t,r]):r.input&&r.input.trigger("change"),r.inline?this._updateDatepicker(r):(this._hideDatepicker(),this._lastInput=r.input[0],typeof r.input[0]!="object"&&r.input.focus(),this._lastInput=null)},_updateAlternate:function(e){var t=this._get(e,"altField");if(t){var n=this._get(e,"altFormat")||this._get(e,"dateFormat"),r=this._getDate(e),i=this.formatDate(n,r,this._getFormatConfig(e));$(t).each(function(){$(this).val(i)})}},noWeekends:function(e){var t=e.getDay();return[t>0&&t<6,""]},iso8601Week:function(e){var t=new Date(e.getTime());t.setDate(t.getDate()+4-(t.getDay()||7));var n=t.getTime();return t.setMonth(0),t.setDate(1),Math.floor(Math.round((n-t)/864e5)/7)+1},parseDate:function(e,t,n){if(e==null||t==null)throw"Invalid arguments";t=typeof t=="object"?t.toString():t+"";if(t=="")return null;var r=(n?n.shortYearCutoff:null)||this._defaults.shortYearCutoff;r=typeof r!="string"?r:(new Date).getFullYear()%100+parseInt(r,10);var i=(n?n.dayNamesShort:null)||this._defaults.dayNamesShort,s=(n?n.dayNames:null)||this._defaults.dayNames,o=(n?n.monthNamesShort:null)||this._defaults.monthNamesShort,u=(n?n.monthNames:null)||this._defaults.monthNames,a=-1,f=-1,l=-1,c=-1,h=!1,p=function(t){var n=y+1<e.length&&e.charAt(y+1)==t;return n&&y++,n},d=function(e){var n=p(e),r=e=="@"?14:e=="!"?20:e=="y"&&n?4:e=="o"?3:2,i=new RegExp("^\\d{1,"+r+"}"),s=t.substring(g).match(i);if(!s)throw"Missing number at position "+g;return g+=s[0].length,parseInt(s[0],10)},v=function(e,n,r){var i=$.map(p(e)?r:n,function(e,t){return[[t,e]]}).sort(function(e,t){return-(e[1].length-t[1].length)}),s=-1;$.each(i,function(e,n){var r=n[1];if(t.substr(g,r.length).toLowerCase()==r.toLowerCase())return s=n[0],g+=r.length,!1});if(s!=-1)return s+1;throw"Unknown name at position "+g},m=function(){if(t.charAt(g)!=e.charAt(y))throw"Unexpected literal at position "+g;g++},g=0;for(var y=0;y<e.length;y++)if(h)e.charAt(y)=="'"&&!p("'")?h=!1:m();else switch(e.charAt(y)){case"d":l=d("d");break;case"D":v("D",i,s);break;case"o":c=d("o");break;case"m":f=d("m");break;case"M":f=v("M",o,u);break;case"y":a=d("y");break;case"@":var b=new Date(d("@"));a=b.getFullYear(),f=b.getMonth()+1,l=b.getDate();break;case"!":var b=new Date((d("!")-this._ticksTo1970)/1e4);a=b.getFullYear(),f=b.getMonth()+1,l=b.getDate();break;case"'":p("'")?m():h=!0;break;default:m()}if(g<t.length){var w=t.substr(g);if(!/^\s+/.test(w))throw"Extra/unparsed characters found in date: "+w}a==-1?a=(new Date).getFullYear():a<100&&(a+=(new Date).getFullYear()-(new Date).getFullYear()%100+(a<=r?0:-100));if(c>-1){f=1,l=c;do{var E=this._getDaysInMonth(a,f-1);if(l<=E)break;f++,l-=E}while(!0)}var b=this._daylightSavingAdjust(new Date(a,f-1,l));if(b.getFullYear()!=a||b.getMonth()+1!=f||b.getDate()!=l)throw"Invalid date";return b},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925))*24*60*60*1e7,formatDate:function(e,t,n){if(!t)return"";var r=(n?n.dayNamesShort:null)||this._defaults.dayNamesShort,i=(n?n.dayNames:null)||this._defaults.dayNames,s=(n?n.monthNamesShort:null)||this._defaults.monthNamesShort,o=(n?n.monthNames:null)||this._defaults.monthNames,u=function(t){var n=h+1<e.length&&e.charAt(h+1)==t;return n&&h++,n},a=function(e,t,n){var r=""+t;if(u(e))while(r.length<n)r="0"+r;return r},f=function(e,t,n,r){return u(e)?r[t]:n[t]},l="",c=!1;if(t)for(var h=0;h<e.length;h++)if(c)e.charAt(h)=="'"&&!u("'")?c=!1:l+=e.charAt(h);else switch(e.charAt(h)){case"d":l+=a("d",t.getDate(),2);break;case"D":l+=f("D",t.getDay(),r,i);break;case"o":l+=a("o",Math.round(((new Date(t.getFullYear(),t.getMonth(),t.getDate())).getTime()-(new Date(t.getFullYear(),0,0)).getTime())/864e5),3);break;case"m":l+=a("m",t.getMonth()+1,2);break;case"M":l+=f("M",t.getMonth(),s,o);break;case"y":l+=u("y")?t.getFullYear():(t.getYear()%100<10?"0":"")+t.getYear()%100;break;case"@":l+=t.getTime();break;case"!":l+=t.getTime()*1e4+this._ticksTo1970;break;case"'":u("'")?l+="'":c=!0;break;default:l+=e.charAt(h)}return l},_possibleChars:function(e){var t="",n=!1,r=function(t){var n=i+1<e.length&&e.charAt(i+1)==t;return n&&i++,n};for(var i=0;i<e.length;i++)if(n)e.charAt(i)=="'"&&!r("'")?n=!1:t+=e.charAt(i);else switch(e.charAt(i)){case"d":case"m":case"y":case"@":t+="0123456789";break;case"D":case"M":return null;case"'":r("'")?t+="'":n=!0;break;default:t+=e.charAt(i)}return t},_get:function(e,t){return e.settings[t]!==undefined?e.settings[t]:this._defaults[t]},_setDateFromField:function(e,t){if(e.input.val()==e.lastVal)return;var n=this._get(e,"dateFormat"),r=e.lastVal=e.input?e.input.val():null,i,s;i=s=this._getDefaultDate(e);var o=this._getFormatConfig(e);try{i=this.parseDate(n,r,o)||s}catch(u){this.log(u),r=t?"":r}e.selectedDay=i.getDate(),e.drawMonth=e.selectedMonth=i.getMonth(),e.drawYear=e.selectedYear=i.getFullYear(),e.currentDay=r?i.getDate():0,e.currentMonth=r?i.getMonth():0,e.currentYear=r?i.getFullYear():0,this._adjustInstDate(e)},_getDefaultDate:function(e){return this._restrictMinMax(e,this._determineDate(e,this._get(e,"defaultDate"),new Date))},_determineDate:function(e,t,n){var r=function(e){var t=new Date;return t.setDate(t.getDate()+e),t},i=function(t){try{return $.datepicker.parseDate($.datepicker._get(e,"dateFormat"),t,$.datepicker._getFormatConfig(e))}catch(n){}var r=(t.toLowerCase().match(/^c/)?$.datepicker._getDate(e):null)||new Date,i=r.getFullYear(),s=r.getMonth(),o=r.getDate(),u=/([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,a=u.exec(t);while(a){switch(a[2]||"d"){case"d":case"D":o+=parseInt(a[1],10);break;case"w":case"W":o+=parseInt(a[1],10)*7;break;case"m":case"M":s+=parseInt(a[1],10),o=Math.min(o,$.datepicker._getDaysInMonth(i,s));break;case"y":case"Y":i+=parseInt(a[1],10),o=Math.min(o,$.datepicker._getDaysInMonth(i,s))}a=u.exec(t)}return new Date(i,s,o)},s=t==null||t===""?n:typeof t=="string"?i(t):typeof t=="number"?isNaN(t)?n:r(t):new Date(t.getTime());return s=s&&s.toString()=="Invalid Date"?n:s,s&&(s.setHours(0),s.setMinutes(0),s.setSeconds(0),s.setMilliseconds(0)),this._daylightSavingAdjust(s)},_daylightSavingAdjust:function(e){return e?(e.setHours(e.getHours()>12?e.getHours()+2:0),e):null},_setDate:function(e,t,n){var r=!t,i=e.selectedMonth,s=e.selectedYear,o=this._restrictMinMax(e,this._determineDate(e,t,new Date));e.selectedDay=e.currentDay=o.getDate(),e.drawMonth=e.selectedMonth=e.currentMonth=o.getMonth(),e.drawYear=e.selectedYear=e.currentYear=o.getFullYear(),(i!=e.selectedMonth||s!=e.selectedYear)&&!n&&this._notifyChange(e),this._adjustInstDate(e),e.input&&e.input.val(r?"":this._formatDate(e))},_getDate:function(e){var t=!e.currentYear||e.input&&e.input.val()==""?null:this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return t},_attachHandlers:function(e){var t=this._get(e,"stepMonths"),n="#"+e.id.replace(/\\\\/g,"\\");e.dpDiv.find("[data-handler]").map(function(){var e={prev:function(){window["DP_jQuery_"+dpuuid].datepicker._adjustDate(n,-t,"M")},next:function(){window["DP_jQuery_"+dpuuid].datepicker._adjustDate(n,+t,"M")},hide:function(){window["DP_jQuery_"+dpuuid].datepicker._hideDatepicker()},today:function(){window["DP_jQuery_"+dpuuid].datepicker._gotoToday(n)},selectDay:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectDay(n,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectMonthYear(n,this,"M"),!1},selectYear:function(){return window["DP_jQuery_"+dpuuid].datepicker._selectMonthYear(n,this,"Y"),!1}};$(this).bind(this.getAttribute("data-event"),e[this.getAttribute("data-handler")])})},_generateHTML:function(e){var t=new Date;t=this._daylightSavingAdjust(new Date(t.getFullYear(),t.getMonth(),t.getDate()));var n=this._get(e,"isRTL"),r=this._get(e,"showButtonPanel"),i=this._get(e,"hideIfNoPrevNext"),s=this._get(e,"navigationAsDateFormat"),o=this._getNumberOfMonths(e),u=this._get(e,"showCurrentAtPos"),a=this._get(e,"stepMonths"),f=o[0]!=1||o[1]!=1,l=this._daylightSavingAdjust(e.currentDay?new Date(e.currentYear,e.currentMonth,e.currentDay):new Date(9999,9,9)),c=this._getMinMaxDate(e,"min"),h=this._getMinMaxDate(e,"max"),p=e.drawMonth-u,d=e.drawYear;p<0&&(p+=12,d--);if(h){var v=this._daylightSavingAdjust(new Date(h.getFullYear(),h.getMonth()-o[0]*o[1]+1,h.getDate()));v=c&&v<c?c:v;while(this._daylightSavingAdjust(new Date(d,p,1))>v)p--,p<0&&(p=11,d--)}e.drawMonth=p,e.drawYear=d;var m=this._get(e,"prevText");m=s?this.formatDate(m,this._daylightSavingAdjust(new Date(d,p-a,1)),this._getFormatConfig(e)):m;var g=this._canAdjustMonth(e,-1,d,p)?'<a class="ui-datepicker-prev ui-corner-all" data-handler="prev" data-event="click" title="'+m+'"><span class="ui-icon ui-icon-circle-triangle-'+(n?"e":"w")+'">'+m+"</span></a>":i?"":'<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+m+'"><span class="ui-icon ui-icon-circle-triangle-'+(n?"e":"w")+'">'+m+"</span></a>",y=this._get(e,"nextText");y=s?this.formatDate(y,this._daylightSavingAdjust(new Date(d,p+a,1)),this._getFormatConfig(e)):y;var b=this._canAdjustMonth(e,1,d,p)?'<a class="ui-datepicker-next ui-corner-all" data-handler="next" data-event="click" title="'+y+'"><span class="ui-icon ui-icon-circle-triangle-'+(n?"w":"e")+'">'+y+"</span></a>":i?"":'<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+y+'"><span class="ui-icon ui-icon-circle-triangle-'+(n?"w":"e")+'">'+y+"</span></a>",w=this._get(e,"currentText"),E=this._get(e,"gotoCurrent")&&e.currentDay?l:t;w=s?this.formatDate(w,E,this._getFormatConfig(e)):w;var S=e.inline?"":'<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" data-handler="hide" data-event="click">'+this._get(e,"closeText")+"</button>",x=r?'<div class="ui-datepicker-buttonpane ui-widget-content">'+(n?S:"")+(this._isInRange(e,E)?'<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" data-handler="today" data-event="click">'+w+"</button>":"")+(n?"":S)+"</div>":"",T=parseInt(this._get(e,"firstDay"),10);T=isNaN(T)?0:T;var N=this._get(e,"showWeek"),C=this._get(e,"dayNames"),k=this._get(e,"dayNamesShort"),L=this._get(e,"dayNamesMin"),A=this._get(e,"monthNames"),O=this._get(e,"monthNamesShort"),M=this._get(e,"beforeShowDay"),_=this._get(e,"showOtherMonths"),D=this._get(e,"selectOtherMonths"),P=this._get(e,"calculateWeek")||this.iso8601Week,H=this._getDefaultDate(e),B="";for(var j=0;j<o[0];j++){var F="";this.maxRows=4;for(var I=0;I<o[1];I++){var q=this._daylightSavingAdjust(new Date(d,p,e.selectedDay)),R=" ui-corner-all",U="";if(f){U+='<div class="ui-datepicker-group';if(o[1]>1)switch(I){case 0:U+=" ui-datepicker-group-first",R=" ui-corner-"+(n?"right":"left");break;case o[1]-1:U+=" ui-datepicker-group-last",R=" ui-corner-"+(n?"left":"right");break;default:U+=" ui-datepicker-group-middle",R=""}U+='">'}U+='<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix'+R+'">'+(/all|left/.test(R)&&j==0?n?b:g:"")+(/all|right/.test(R)&&j==0?n?g:b:"")+this._generateMonthYearHeader(e,p,d,c,h,j>0||I>0,A,O)+'</div><table class="ui-datepicker-calendar"><thead>'+"<tr>";var z=N?'<th class="ui-datepicker-week-col">'+this._get(e,"weekHeader")+"</th>":"";for(var W=0;W<7;W++){var X=(W+T)%7;z+="<th"+((W+T+6)%7>=5?' class="ui-datepicker-week-end"':"")+">"+'<span title="'+C[X]+'">'+L[X]+"</span></th>"}U+=z+"</tr></thead><tbody>";var V=this._getDaysInMonth(d,p);d==e.selectedYear&&p==e.selectedMonth&&(e.selectedDay=Math.min(e.selectedDay,V));var J=(this._getFirstDayOfMonth(d,p)-T+7)%7,K=Math.ceil((J+V)/7),Q=f?this.maxRows>K?this.maxRows:K:K;this.maxRows=Q;var G=this._daylightSavingAdjust(new Date(d,p,1-J));for(var Y=0;Y<Q;Y++){U+="<tr>";var Z=N?'<td class="ui-datepicker-week-col">'+this._get(e,"calculateWeek")(G)+"</td>":"";for(var W=0;W<7;W++){var et=M?M.apply(e.input?e.input[0]:null,[G]):[!0,""],tt=G.getMonth()!=p,nt=tt&&!D||!et[0]||c&&G<c||h&&G>h;Z+='<td class="'+((W+T+6)%7>=5?" ui-datepicker-week-end":"")+(tt?" ui-datepicker-other-month":"")+(G.getTime()==q.getTime()&&p==e.selectedMonth&&e._keyEvent||H.getTime()==G.getTime()&&H.getTime()==q.getTime()?" "+this._dayOverClass:"")+(nt?" "+this._unselectableClass+" ui-state-disabled":"")+(tt&&!_?"":" "+et[1]+(G.getTime()==l.getTime()?" "+this._currentClass:"")+(G.getTime()==t.getTime()?" ui-datepicker-today":""))+'"'+((!tt||_)&&et[2]?' title="'+et[2]+'"':"")+(nt?"":' data-handler="selectDay" data-event="click" data-month="'+G.getMonth()+'" data-year="'+G.getFullYear()+'"')+">"+(tt&&!_?" ":nt?'<span class="ui-state-default">'+G.getDate()+"</span>":'<a class="ui-state-default'+(G.getTime()==t.getTime()?" ui-state-highlight":"")+(G.getTime()==l.getTime()?" ui-state-active":"")+(tt?" ui-priority-secondary":"")+'" href="#">'+G.getDate()+"</a>")+"</td>",G.setDate(G.getDate()+1),G=this._daylightSavingAdjust(G)}U+=Z+"</tr>"}p++,p>11&&(p=0,d++),U+="</tbody></table>"+(f?"</div>"+(o[0]>0&&I==o[1]-1?'<div class="ui-datepicker-row-break"></div>':""):""),F+=U}B+=F}return B+=x+($.ui.ie6&&!e.inline?'<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>':""),e._keyEvent=!1,B},_generateMonthYearHeader:function(e,t,n,r,i,s,o,u){var a=this._get(e,"changeMonth"),f=this._get(e,"changeYear"),l=this._get(e,"showMonthAfterYear"),c='<div class="ui-datepicker-title">',h="";if(s||!a)h+='<span class="ui-datepicker-month">'+o[t]+"</span>";else{var p=r&&r.getFullYear()==n,d=i&&i.getFullYear()==n;h+='<select class="ui-datepicker-month" data-handler="selectMonth" data-event="change">';for(var v=0;v<12;v++)(!p||v>=r.getMonth())&&(!d||v<=i.getMonth())&&(h+='<option value="'+v+'"'+(v==t?' selected="selected"':"")+">"+u[v]+"</option>");h+="</select>"}l||(c+=h+(s||!a||!f?" ":""));if(!e.yearshtml){e.yearshtml="";if(s||!f)c+='<span class="ui-datepicker-year">'+n+"</span>";else{var m=this._get(e,"yearRange").split(":"),g=(new Date).getFullYear(),y=function(e){var t=e.match(/c[+-].*/)?n+parseInt(e.substring(1),10):e.match(/[+-].*/)?g+parseInt(e,10):parseInt(e,10);return isNaN(t)?g:t},b=y(m[0]),w=Math.max(b,y(m[1]||""));b=r?Math.max(b,r.getFullYear()):b,w=i?Math.min(w,i.getFullYear()):w,e.yearshtml+='<select class="ui-datepicker-year" data-handler="selectYear" data-event="change">';for(;b<=w;b++)e.yearshtml+='<option value="'+b+'"'+(b==n?' selected="selected"':"")+">"+b+"</option>";e.yearshtml+="</select>",c+=e.yearshtml,e.yearshtml=null}}return c+=this._get(e,"yearSuffix"),l&&(c+=(s||!a||!f?" ":"")+h),c+="</div>",c},_adjustInstDate:function(e,t,n){var r=e.drawYear+(n=="Y"?t:0),i=e.drawMonth+(n=="M"?t:0),s=Math.min(e.selectedDay,this._getDaysInMonth(r,i))+(n=="D"?t:0),o=this._restrictMinMax(e,this._daylightSavingAdjust(new Date(r,i,s)));e.selectedDay=o.getDate(),e.drawMonth=e.selectedMonth=o.getMonth(),e.drawYear=e.selectedYear=o.getFullYear(),(n=="M"||n=="Y")&&this._notifyChange(e)},_restrictMinMax:function(e,t){var n=this._getMinMaxDate(e,"min"),r=this._getMinMaxDate(e,"max"),i=n&&t<n?n:t;return i=r&&i>r?r:i,i},_notifyChange:function(e){var t=this._get(e,"onChangeMonthYear");t&&t.apply(e.input?e.input[0]:null,[e.selectedYear,e.selectedMonth+1,e])},_getNumberOfMonths:function(e){var t=this._get(e,"numberOfMonths");return t==null?[1,1]:typeof t=="number"?[1,t]:t},_getMinMaxDate:function(e,t){return this._determineDate(e,this._get(e,t+"Date"),null)},_getDaysInMonth:function(e,t){return 32-this._daylightSavingAdjust(new Date(e,t,32)).getDate()},_getFirstDayOfMonth:function(e,t){return(new Date(e,t,1)).getDay()},_canAdjustMonth:function(e,t,n,r){var i=this._getNumberOfMonths(e),s=this._daylightSavingAdjust(new Date(n,r+(t<0?t:i[0]*i[1]),1));return t<0&&s.setDate(this._getDaysInMonth(s.getFullYear(),s.getMonth())),this._isInRange(e,s)},_isInRange:function(e,t){var n=this._getMinMaxDate(e,"min"),r=this._getMinMaxDate(e,"max");return(!n||t.getTime()>=n.getTime())&&(!r||t.getTime()<=r.getTime())},_getFormatConfig:function(e){var t=this._get(e,"shortYearCutoff");return t=typeof t!="string"?t:(new Date).getFullYear()%100+parseInt(t,10),{shortYearCutoff:t,dayNamesShort:this._get(e,"dayNamesShort"),dayNames:this._get(e,"dayNames"),monthNamesShort:this._get(e,"monthNamesShort"),monthNames:this._get(e,"monthNames")}},_formatDate:function(e,t,n,r){t||(e.currentDay=e.selectedDay,e.currentMonth=e.selectedMonth,e.currentYear=e.selectedYear);var i=t?typeof t=="object"?t:this._daylightSavingAdjust(new Date(r,n,t)):this._daylightSavingAdjust(new Date(e.currentYear,e.currentMonth,e.currentDay));return this.formatDate(this._get(e,"dateFormat"),i,this._getFormatConfig(e))}}),$.fn.datepicker=function(e){if(!this.length)return this;$.datepicker.initialized||($(document).mousedown($.datepicker._checkExternalClick).find(document.body).append($.datepicker.dpDiv),$.datepicker.initialized=!0);var t=Array.prototype.slice.call(arguments,1);return typeof e!="string"||e!="isDisabled"&&e!="getDate"&&e!="widget"?e=="option"&&arguments.length==2&&typeof arguments[1]=="string"?$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this[0]].concat(t)):this.each(function(){typeof e=="string"?$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this].concat(t)):$.datepicker._attachDatepicker(this,e)}):$.datepicker["_"+e+"Datepicker"].apply($.datepicker,[this[0]].concat(t))},$.datepicker=new Datepicker,$.datepicker.initialized=!1,$.datepicker.uuid=(new Date).getTime(),$.datepicker.version="1.9.2",window["DP_jQuery_"+dpuuid]=$})(jQuery);(function(e,t){var n="ui-dialog ui-widget ui-widget-content ui-corner-all ",r={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},i={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};e.widget("ui.dialog",{version:"1.9.2",options:{autoOpen:!0,buttons:{},closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:!1,maxWidth:!1,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(t){var n=e(this).css(t).offset().top;n<0&&e(this).css("top",t.top-n)}},resizable:!0,show:null,stack:!0,title:"",width:300,zIndex:1e3},_create:function(){this.originalTitle=this.element.attr("title"),typeof this.originalTitle!="string"&&(this.originalTitle=""),this.oldPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.options.title=this.options.title||this.originalTitle;var t=this,r=this.options,i=r.title||" ",s,o,u,a,f;s=(this.uiDialog=e("<div>")).addClass(n+r.dialogClass).css({display:"none",outline:0,zIndex:r.zIndex}).attr("tabIndex",-1).keydown(function(n){r.closeOnEscape&&!n.isDefaultPrevented()&&n.keyCode&&n.keyCode===e.ui.keyCode.ESCAPE&&(t.close(n),n.preventDefault())}).mousedown(function(e){t.moveToTop(!1,e)}).appendTo("body"),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(s),o=(this.uiDialogTitlebar=e("<div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").bind("mousedown",function(){s.focus()}).prependTo(s),u=e("<a href='#'></a>").addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").click(function(e){e.preventDefault(),t.close(e)}).appendTo(o),(this.uiDialogTitlebarCloseText=e("<span>")).addClass("ui-icon ui-icon-closethick").text(r.closeText).appendTo(u),a=e("<span>").uniqueId().addClass("ui-dialog-title").html(i).prependTo(o),f=(this.uiDialogButtonPane=e("<div>")).addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),(this.uiButtonSet=e("<div>")).addClass("ui-dialog-buttonset").appendTo(f),s.attr({role:"dialog","aria-labelledby":a.attr("id")}),o.find("*").add(o).disableSelection(),this._hoverable(u),this._focusable(u),r.draggable&&e.fn.draggable&&this._makeDraggable(),r.resizable&&e.fn.resizable&&this._makeResizable(),this._createButtons(r.buttons),this._isOpen=!1,e.fn.bgiframe&&s.bgiframe(),this._on(s,{keydown:function(t){if(!r.modal||t.keyCode!==e.ui.keyCode.TAB)return;var n=e(":tabbable",s),i=n.filter(":first"),o=n.filter(":last");if(t.target===o[0]&&!t.shiftKey)return i.focus(1),!1;if(t.target===i[0]&&t.shiftKey)return o.focus(1),!1}})},_init:function(){this.options.autoOpen&&this.open()},_destroy:function(){var e,t=this.oldPosition;this.overlay&&this.overlay.destroy(),this.uiDialog.hide(),this.element.removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body"),this.uiDialog.remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),e=t.parent.children().eq(t.index),e.length&&e[0]!==this.element[0]?e.before(this.element):t.parent.append(this.element)},widget:function(){return this.uiDialog},close:function(t){var n=this,r,i;if(!this._isOpen)return;if(!1===this._trigger("beforeClose",t))return;return this._isOpen=!1,this.overlay&&this.overlay.destroy(),this.options.hide?this._hide(this.uiDialog,this.options.hide,function(){n._trigger("close",t)}):(this.uiDialog.hide(),this._trigger("close",t)),e.ui.dialog.overlay.resize(),this.options.modal&&(r=0,e(".ui-dialog").each(function(){this!==n.uiDialog[0]&&(i=e(this).css("z-index"),isNaN(i)||(r=Math.max(r,i)))}),e.ui.dialog.maxZ=r),this},isOpen:function(){return this._isOpen},moveToTop:function(t,n){var r=this.options,i;return r.modal&&!t||!r.stack&&!r.modal?this._trigger("focus",n):(r.zIndex>e.ui.dialog.maxZ&&(e.ui.dialog.maxZ=r.zIndex),this.overlay&&(e.ui.dialog.maxZ+=1,e.ui.dialog.overlay.maxZ=e.ui.dialog.maxZ,this.overlay.$el.css("z-index",e.ui.dialog.overlay.maxZ)),i={scrollTop:this.element.scrollTop(),scrollLeft:this.element.scrollLeft()},e.ui.dialog.maxZ+=1,this.uiDialog.css("z-index",e.ui.dialog.maxZ),this.element.attr(i),this._trigger("focus",n),this)},open:function(){if(this._isOpen)return;var t,n=this.options,r=this.uiDialog;return this._size(),this._position(n.position),r.show(n.show),this.overlay=n.modal?new e.ui.dialog.overlay(this):null,this.moveToTop(!0),t=this.element.find(":tabbable"),t.length||(t=this.uiDialogButtonPane.find(":tabbable"),t.length||(t=r)),t.eq(0).focus(),this._isOpen=!0,this._trigger("open"),this},_createButtons:function(t){var n=this,r=!1;this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),typeof t=="object"&&t!==null&&e.each(t,function(){return!(r=!0)}),r?(e.each(t,function(t,r){var i,s;r=e.isFunction(r)?{click:r,text:t}:r,r=e.extend({type:"button"},r),s=r.click,r.click=function(){s.apply(n.element[0],arguments)},i=e("<button></button>",r).appendTo(n.uiButtonSet),e.fn.button&&i.button()}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog)):this.uiDialog.removeClass("ui-dialog-buttons")},_makeDraggable:function(){function r(e){return{position:e.position,offset:e.offset}}var t=this,n=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(n,i){e(this).addClass("ui-dialog-dragging"),t._trigger("dragStart",n,r(i))},drag:function(e,n){t._trigger("drag",e,r(n))},stop:function(i,s){n.position=[s.position.left-t.document.scrollLeft(),s.position.top-t.document.scrollTop()],e(this).removeClass("ui-dialog-dragging"),t._trigger("dragStop",i,r(s)),e.ui.dialog.overlay.resize()}})},_makeResizable:function(n){function u(e){return{originalPosition:e.originalPosition,originalSize:e.originalSize,position:e.position,size:e.size}}n=n===t?this.options.resizable:n;var r=this,i=this.options,s=this.uiDialog.css("position"),o=typeof n=="string"?n:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:i.maxWidth,maxHeight:i.maxHeight,minWidth:i.minWidth,minHeight:this._minHeight(),handles:o,start:function(t,n){e(this).addClass("ui-dialog-resizing"),r._trigger("resizeStart",t,u(n))},resize:function(e,t){r._trigger("resize",e,u(t))},stop:function(t,n){e(this).removeClass("ui-dialog-resizing"),i.height=e(this).height(),i.width=e(this).width(),r._trigger("resizeStop",t,u(n)),e.ui.dialog.overlay.resize()}}).css("position",s).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_minHeight:function(){var e=this.options;return e.height==="auto"?e.minHeight:Math.min(e.minHeight,e.height)},_position:function(t){var n=[],r=[0,0],i;if(t){if(typeof t=="string"||typeof t=="object"&&"0"in t)n=t.split?t.split(" "):[t[0],t[1]],n.length===1&&(n[1]=n[0]),e.each(["left","top"],function(e,t){+n[e]===n[e]&&(r[e]=n[e],n[e]=t)}),t={my:n[0]+(r[0]<0?r[0]:"+"+r[0])+" "+n[1]+(r[1]<0?r[1]:"+"+r[1]),at:n.join(" ")};t=e.extend({},e.ui.dialog.prototype.options.position,t)}else t=e.ui.dialog.prototype.options.position;i=this.uiDialog.is(":visible"),i||this.uiDialog.show(),this.uiDialog.position(t),i||this.uiDialog.hide()},_setOptions:function(t){var n=this,s={},o=!1;e.each(t,function(e,t){n._setOption(e,t),e in r&&(o=!0),e in i&&(s[e]=t)}),o&&this._size(),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option",s)},_setOption:function(t,r){var i,s,o=this.uiDialog;switch(t){case"buttons":this._createButtons(r);break;case"closeText":this.uiDialogTitlebarCloseText.text(""+r);break;case"dialogClass":o.removeClass(this.options.dialogClass).addClass(n+r);break;case"disabled":r?o.addClass("ui-dialog-disabled"):o.removeClass("ui-dialog-disabled");break;case"draggable":i=o.is(":data(draggable)"),i&&!r&&o.draggable("destroy"),!i&&r&&this._makeDraggable();break;case"position":this._position(r);break;case"resizable":s=o.is(":data(resizable)"),s&&!r&&o.resizable("destroy"),s&&typeof r=="string"&&o.resizable("option","handles",r),!s&&r!==!1&&this._makeResizable(r);break;case"title":e(".ui-dialog-title",this.uiDialogTitlebar).html(""+(r||" "))}this._super(t,r)},_size:function(){var t,n,r,i=this.options,s=this.uiDialog.is(":visible");this.element.show().css({width:"auto",minHeight:0,height:0}),i.minWidth>i.width&&(i.width=i.minWidth),t=this.uiDialog.css({height:"auto",width:i.width}).outerHeight(),n=Math.max(0,i.minHeight-t),i.height==="auto"?e.support.minHeight?this.element.css({minHeight:n,height:"auto"}):(this.uiDialog.show(),r=this.element.css("height","auto").height(),s||this.uiDialog.hide(),this.element.height(Math.max(r,n))):this.element.height(Math.max(i.height-t,0)),this.uiDialog.is(":data(resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())}}),e.extend(e.ui.dialog,{uuid:0,maxZ:0,getTitleId:function(e){var t=e.attr("id");return t||(this.uuid+=1,t=this.uuid),"ui-dialog-title-"+t},overlay:function(t){this.$el=e.ui.dialog.overlay.create(t)}}),e.extend(e.ui.dialog.overlay,{instances:[],oldInstances:[],maxZ:0,events:e.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(e){return e+".dialog-overlay"}).join(" "),create:function(t){this.instances.length===0&&(setTimeout(function(){e.ui.dialog.overlay.instances.length&&e(document).bind(e.ui.dialog.overlay.events,function(t){if(e(t.target).zIndex()<e.ui.dialog.overlay.maxZ)return!1})},1),e(window).bind("resize.dialog-overlay",e.ui.dialog.overlay.resize));var n=this.oldInstances.pop()||e("<div>").addClass("ui-widget-overlay");return e(document).bind("keydown.dialog-overlay",function(r){var i=e.ui.dialog.overlay.instances;i.length!==0&&i[i.length-1]===n&&t.options.closeOnEscape&&!r.isDefaultPrevented()&&r.keyCode&&r.keyCode===e.ui.keyCode.ESCAPE&&(t.close(r),r.preventDefault())}),n.appendTo(document.body).css({width:this.width(),height:this.height()}),e.fn.bgiframe&&n.bgiframe(),this.instances.push(n),n},destroy:function(t){var n=e.inArray(t,this.instances),r=0;n!==-1&&this.oldInstances.push(this.instances.splice(n,1)[0]),this.instances.length===0&&e([document,window]).unbind(".dialog-overlay"),t.height(0).width(0).remove(),e.each(this.instances,function(){r=Math.max(r,this.css("z-index"))}),this.maxZ=r},height:function(){var t,n;return e.ui.ie?(t=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight),n=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight),t<n?e(window).height()+"px":t+"px"):e(document).height()+"px"},width:function(){var t,n;return e.ui.ie?(t=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth),n=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth),t<n?e(window).width()+"px":t+"px"):e(document).width()+"px"},resize:function(){var t=e([]);e.each(e.ui.dialog.overlay.instances,function(){t=t.add(this)}),t.css({width:0,height:0}).css({width:e.ui.dialog.overlay.width(),height:e.ui.dialog.overlay.height()})}}),e.extend(e.ui.dialog.overlay.prototype,{destroy:function(){e.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);(function(e,t){var n=!1;e.widget("ui.menu",{version:"1.9.2",defaultElement:"<ul>",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}).bind("click"+this.eventNamespace,e.proxy(function(e){this.options.disabled&&e.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item > a":function(e){e.preventDefault()},"click .ui-state-disabled > a":function(e){e.preventDefault()},"click .ui-menu-item:has(a)":function(t){var r=e(t.target).closest(".ui-menu-item");!n&&r.not(".ui-state-disabled").length&&(n=!0,this.select(t),r.has(".ui-menu").length?this.expand(t):this.element.is(":focus")||(this.element.trigger("focus",[!0]),this.active&&this.active.parents(".ui-menu").length===1&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(t){var n=e(t.currentTarget);n.siblings().children(".ui-state-active").removeClass("ui-state-active"),this.focus(t,n)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(e,t){var n=this.active||this.element.children(".ui-menu-item").eq(0);t||this.focus(e,n)},blur:function(t){this._delay(function(){e.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(t)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(t){e(t.target).closest(".ui-menu").length||this.collapseAll(t),n=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").andSelf().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var t=e(this);t.data("ui-menu-submenu-carat")&&t.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(t){function a(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var n,r,i,s,o,u=!0;switch(t.keyCode){case e.ui.keyCode.PAGE_UP:this.previousPage(t);break;case e.ui.keyCode.PAGE_DOWN:this.nextPage(t);break;case e.ui.keyCode.HOME:this._move("first","first",t);break;case e.ui.keyCode.END:this._move("last","last",t);break;case e.ui.keyCode.UP:this.previous(t);break;case e.ui.keyCode.DOWN:this.next(t);break;case e.ui.keyCode.LEFT:this.collapse(t);break;case e.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(t);break;case e.ui.keyCode.ENTER:case e.ui.keyCode.SPACE:this._activate(t);break;case e.ui.keyCode.ESCAPE:this.collapse(t);break;default:u=!1,r=this.previousFilter||"",i=String.fromCharCode(t.keyCode),s=!1,clearTimeout(this.filterTimer),i===r?s=!0:i=r+i,o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())}),n=s&&n.index(this.active.next())!==-1?this.active.nextAll(".ui-menu-item"):n,n.length||(i=String.fromCharCode(t.keyCode),o=new RegExp("^"+a(i),"i"),n=this.activeMenu.children(".ui-menu-item").filter(function(){return o.test(e(this).children("a").text())})),n.length?(this.focus(t,n),n.length>1?(this.previousFilter=i,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}u&&t.preventDefault()},_activate:function(e){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(e):this.select(e))},refresh:function(){var t,n=this.options.icons.submenu,r=this.element.find(this.options.menus);r.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var t=e(this),r=t.prev("a"),i=e("<span>").addClass("ui-menu-icon ui-icon "+n).data("ui-menu-submenu-carat",!0);r.attr("aria-haspopup","true").prepend(i),t.attr("aria-labelledby",r.attr("id"))}),t=r.add(this.element),t.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex:-1,role:this._itemRole()}),t.children(":not(.ui-menu-item)").each(function(){var t=e(this);/[^\-—–\s]/.test(t.text())||t.addClass("ui-widget-content ui-menu-divider")}),t.children(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!e.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},focus:function(e,t){var n,r;this.blur(e,e&&e.type==="focus"),this._scrollIntoView(t),this.active=t.first(),r=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",r.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),e&&e.type==="keydown"?this._close():this.timer=this._delay(function(){this._close()},this.delay),n=t.children(".ui-menu"),n.length&&/^mouse/.test(e.type)&&this._startOpening(n),this.activeMenu=t.parent(),this._trigger("focus",e,{item:t})},_scrollIntoView:function(t){var n,r,i,s,o,u;this._hasScroll()&&(n=parseFloat(e.css(this.activeMenu[0],"borderTopWidth"))||0,r=parseFloat(e.css(this.activeMenu[0],"paddingTop"))||0,i=t.offset().top-this.activeMenu.offset().top-n-r,s=this.activeMenu.scrollTop(),o=this.activeMenu.height(),u=t.height(),i<0?this.activeMenu.scrollTop(s+i):i+u>o&&this.activeMenu.scrollTop(s+i-o+u))},blur:function(e,t){t||clearTimeout(this.timer);if(!this.active)return;this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",e,{item:this.active})},_startOpening:function(e){clearTimeout(this.timer);if(e.attr("aria-hidden")!=="true")return;this.timer=this._delay(function(){this._close(),this._open(e)},this.delay)},_open:function(t){var n=e.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(t.parents(".ui-menu")).hide().attr("aria-hidden","true"),t.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(n)},collapseAll:function(t,n){clearTimeout(this.timer),this.timer=this._delay(function(){var r=n?this.element:e(t&&t.target).closest(this.element.find(".ui-menu"));r.length||(r=this.element),this._close(r),this.blur(t),this.activeMenu=r},this.delay)},_close:function(e){e||(e=this.active?this.active.parent():this.element),e.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(e){var t=this.active&&this.active.parent().closest(".ui-menu-item",this.element);t&&t.length&&(this._close(),this.focus(e,t))},expand:function(e){var t=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();t&&t.length&&(this._open(t.parent()),this._delay(function(){this.focus(e,t)}))},next:function(e){this._move("next","first",e)},previous:function(e){this._move("prev","last",e)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(e,t,n){var r;this.active&&(e==="first"||e==="last"?r=this.active[e==="first"?"prevAll":"nextAll"](".ui-menu-item").eq(-1):r=this.active[e+"All"](".ui-menu-item").eq(0));if(!r||!r.length||!this.active)r=this.activeMenu.children(".ui-menu-item")[t]();this.focus(n,r)},nextPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isLastItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r-i<0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item")[this.active?"last":"first"]())},previousPage:function(t){var n,r,i;if(!this.active){this.next(t);return}if(this.isFirstItem())return;this._hasScroll()?(r=this.active.offset().top,i=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return n=e(this),n.offset().top-r+i>0}),this.focus(t,n)):this.focus(t,this.activeMenu.children(".ui-menu-item").first())},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(t){this.active=this.active||e(t.target).closest(".ui-menu-item");var n={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(t,!0),this._trigger("select",t,n)}})})(jQuery);(function(e,t){e.widget("ui.progressbar",{version:"1.9.2",options:{value:0,max:100},min:0,_create:function(){this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min,"aria-valuemax":this.options.max,"aria-valuenow":this._value()}),this.valueDiv=e("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element),this.oldValue=this._value(),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(e){return e===t?this._value():(this._setOption("value",e),this)},_setOption:function(e,t){e==="value"&&(this.options.value=t,this._refreshValue(),this._value()===this.options.max&&this._trigger("complete")),this._super(e,t)},_value:function(){var e=this.options.value;return typeof e!="number"&&(e=0),Math.min(this.options.max,Math.max(this.min,e))},_percentage:function(){return 100*this._value()/this.options.max},_refreshValue:function(){var e=this.value(),t=this._percentage();this.oldValue!==e&&(this.oldValue=e,this._trigger("change")),this.valueDiv.toggle(e>this.min).toggleClass("ui-corner-right",e===this.options.max).width(t.toFixed(0)+"%"),this.element.attr("aria-valuenow",e)}})})(jQuery);(function(e,t){var n=5;e.widget("ui.slider",e.ui.mouse,{version:"1.9.2",widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null},_create:function(){var t,r,i=this.options,s=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),o="<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",u=[];this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"+(i.disabled?" ui-slider-disabled ui-disabled":"")),this.range=e([]),i.range&&(i.range===!0&&(i.values||(i.values=[this._valueMin(),this._valueMin()]),i.values.length&&i.values.length!==2&&(i.values=[i.values[0],i.values[0]])),this.range=e("<div></div>").appendTo(this.element).addClass("ui-slider-range ui-widget-header"+(i.range==="min"||i.range==="max"?" ui-slider-range-"+i.range:""))),r=i.values&&i.values.length||1;for(t=s.length;t<r;t++)u.push(o);this.handles=s.add(e(u.join("")).appendTo(this.element)),this.handle=this.handles.eq(0),this.handles.add(this.range).filter("a").click(function(e){e.preventDefault()}).mouseenter(function(){i.disabled||e(this).addClass("ui-state-hover")}).mouseleave(function(){e(this).removeClass("ui-state-hover")}).focus(function(){i.disabled?e(this).blur():(e(".ui-slider .ui-state-focus").removeClass("ui-state-focus"),e(this).addClass("ui-state-focus"))}).blur(function(){e(this).removeClass("ui-state-focus")}),this.handles.each(function(t){e(this).data("ui-slider-handle-index",t)}),this._on(this.handles,{keydown:function(t){var r,i,s,o,u=e(t.target).data("ui-slider-handle-index");switch(t.keyCode){case e.ui.keyCode.HOME:case e.ui.keyCode.END:case e.ui.keyCode.PAGE_UP:case e.ui.keyCode.PAGE_DOWN:case e.ui.keyCode.UP:case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:case e.ui.keyCode.LEFT:t.preventDefault();if(!this._keySliding){this._keySliding=!0,e(t.target).addClass("ui-state-active"),r=this._start(t,u);if(r===!1)return}}o=this.options.step,this.options.values&&this.options.values.length?i=s=this.values(u):i=s=this.value();switch(t.keyCode){case e.ui.keyCode.HOME:s=this._valueMin();break;case e.ui.keyCode.END:s=this._valueMax();break;case e.ui.keyCode.PAGE_UP:s=this._trimAlignValue(i+(this._valueMax()-this._valueMin())/n);break;case e.ui.keyCode.PAGE_DOWN:s=this._trimAlignValue(i-(this._valueMax()-this._valueMin())/n);break;case e.ui.keyCode.UP:case e.ui.keyCode.RIGHT:if(i===this._valueMax())return;s=this._trimAlignValue(i+o);break;case e.ui.keyCode.DOWN:case e.ui.keyCode.LEFT:if(i===this._valueMin())return;s=this._trimAlignValue(i-o)}this._slide(t,u,s)},keyup:function(t){var n=e(t.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(t,n),this._change(t,n),e(t.target).removeClass("ui-state-active"))}}),this._refreshValue(),this._animateOff=!1},_destroy:function(){this.handles.remove(),this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-slider-disabled ui-widget ui-widget-content ui-corner-all"),this._mouseDestroy()},_mouseCapture:function(t){var n,r,i,s,o,u,a,f,l=this,c=this.options;return c.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),n={x:t.pageX,y:t.pageY},r=this._normValueFromMouse(n),i=this._valueMax()-this._valueMin()+1,this.handles.each(function(t){var n=Math.abs(r-l.values(t));i>n&&(i=n,s=e(this),o=t)}),c.range===!0&&this.values(1)===c.min&&(o+=1,s=e(this.handles[o])),u=this._start(t,o),u===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,s.addClass("ui-state-active").focus(),a=s.offset(),f=!e(t.target).parents().andSelf().is(".ui-slider-handle"),this._clickOffset=f?{left:0,top:0}:{left:t.pageX-a.left-s.width()/2,top:t.pageY-a.top-s.height()/2-(parseInt(s.css("borderTopWidth"),10)||0)-(parseInt(s.css("borderBottomWidth"),10)||0)+(parseInt(s.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(t,o,r),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(e){var t={x:e.pageX,y:e.pageY},n=this._normValueFromMouse(t);return this._slide(e,this._handleIndex,n),!1},_mouseStop:function(e){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(e,this._handleIndex),this._change(e,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation=this.options.orientation==="vertical"?"vertical":"horizontal"},_normValueFromMouse:function(e){var t,n,r,i,s;return this.orientation==="horizontal"?(t=this.elementSize.width,n=e.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(t=this.elementSize.height,n=e.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),r=n/t,r>1&&(r=1),r<0&&(r=0),this.orientation==="vertical"&&(r=1-r),i=this._valueMax()-this._valueMin(),s=this._valueMin()+r*i,this._trimAlignValue(s)},_start:function(e,t){var n={handle:this.handles[t],value:this.value()};return this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("start",e,n)},_slide:function(e,t,n){var r,i,s;this.options.values&&this.options.values.length?(r=this.values(t?0:1),this.options.values.length===2&&this.options.range===!0&&(t===0&&n>r||t===1&&n<r)&&(n=r),n!==this.values(t)&&(i=this.values(),i[t]=n,s=this._trigger("slide",e,{handle:this.handles[t],value:n,values:i}),r=this.values(t?0:1),s!==!1&&this.values(t,n,!0))):n!==this.value()&&(s=this._trigger("slide",e,{handle:this.handles[t],value:n}),s!==!1&&this.value(n))},_stop:function(e,t){var n={handle:this.handles[t],value:this.value()};this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("stop",e,n)},_change:function(e,t){if(!this._keySliding&&!this._mouseSliding){var n={handle:this.handles[t],value:this.value()};this.options.values&&this.options.values.length&&(n.value=this.values(t),n.values=this.values()),this._trigger("change",e,n)}},value:function(e){if(arguments.length){this.options.value=this._trimAlignValue(e),this._refreshValue(),this._change(null,0);return}return this._value()},values:function(t,n){var r,i,s;if(arguments.length>1){this.options.values[t]=this._trimAlignValue(n),this._refreshValue(),this._change(null,t);return}if(!arguments.length)return this._values();if(!e.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(t):this.value();r=this.options.values,i=arguments[0];for(s=0;s<r.length;s+=1)r[s]=this._trimAlignValue(i[s]),this._change(null,s);this._refreshValue()},_setOption:function(t,n){var r,i=0;e.isArray(this.options.values)&&(i=this.options.values.length),e.Widget.prototype._setOption.apply(this,arguments);switch(t){case"disabled":n?(this.handles.filter(".ui-state-focus").blur(),this.handles.removeClass("ui-state-hover"),this.handles.prop("disabled",!0),this.element.addClass("ui-disabled")):(this.handles.prop("disabled",!1),this.element.removeClass("ui-disabled"));break;case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":this._animateOff=!0,this._refreshValue();for(r=0;r<i;r+=1)this._change(null,r);this._animateOff=!1;break;case"min":case"max":this._animateOff=!0,this._refreshValue(),this._animateOff=!1}},_value:function(){var e=this.options.value;return e=this._trimAlignValue(e),e},_values:function(e){var t,n,r;if(arguments.length)return t=this.options.values[e],t=this._trimAlignValue(t),t;n=this.options.values.slice();for(r=0;r<n.length;r+=1)n[r]=this._trimAlignValue(n[r]);return n},_trimAlignValue:function(e){if(e<=this._valueMin())return this._valueMin();if(e>=this._valueMax())return this._valueMax();var t=this.options.step>0?this.options.step:1,n=(e-this._valueMin())%t,r=e-n;return Math.abs(n)*2>=t&&(r+=n>0?t:-t),parseFloat(r.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var t,n,r,i,s,o=this.options.range,u=this.options,a=this,f=this._animateOff?!1:u.animate,l={};this.options.values&&this.options.values.length?this.handles.each(function(r){n=(a.values(r)-a._valueMin())/(a._valueMax()-a._valueMin())*100,l[a.orientation==="horizontal"?"left":"bottom"]=n+"%",e(this).stop(1,1)[f?"animate":"css"](l,u.animate),a.options.range===!0&&(a.orientation==="horizontal"?(r===0&&a.range.stop(1,1)[f?"animate":"css"]({left:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({width:n-t+"%"},{queue:!1,duration:u.animate})):(r===0&&a.range.stop(1,1)[f?"animate":"css"]({bottom:n+"%"},u.animate),r===1&&a.range[f?"animate":"css"]({height:n-t+"%"},{queue:!1,duration:u.animate}))),t=n}):(r=this.value(),i=this._valueMin(),s=this._valueMax(),n=s!==i?(r-i)/(s-i)*100:0,l[this.orientation==="horizontal"?"left":"bottom"]=n+"%",this.handle.stop(1,1)[f?"animate":"css"](l,u.animate),o==="min"&&this.orientation==="horizontal"&&this.range.stop(1,1)[f?"animate":"css"]({width:n+"%"},u.animate),o==="max"&&this.orientation==="horizontal"&&this.range[f?"animate":"css"]({width:100-n+"%"},{queue:!1,duration:u.animate}),o==="min"&&this.orientation==="vertical"&&this.range.stop(1,1)[f?"animate":"css"]({height:n+"%"},u.animate),o==="max"&&this.orientation==="vertical"&&this.range[f?"animate":"css"]({height:100-n+"%"},{queue:!1,duration:u.animate}))}})})(jQuery);(function(e){function t(e){return function(){var t=this.element.val();e.apply(this,arguments),this._refresh(),t!==this.element.val()&&this._trigger("change")}}e.widget("ui.spinner",{version:"1.9.2",defaultElement:"<input>",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var t={},n=this.element;return e.each(["min","max","step"],function(e,r){var i=n.attr(r);i!==undefined&&i.length&&(t[r]=i)}),t},_events:{keydown:function(e){this._start(e)&&this._keydown(e)&&e.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(e){if(this.cancelBlur){delete this.cancelBlur;return}this._refresh(),this.previous!==this.element.val()&&this._trigger("change",e)},mousewheel:function(e,t){if(!t)return;if(!this.spinning&&!this._start(e))return!1;this._spin((t>0?1:-1)*this.options.step,e),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(e)},100),e.preventDefault()},"mousedown .ui-spinner-button":function(t){function r(){var e=this.element[0]===this.document[0].activeElement;e||(this.element.focus(),this.previous=n,this._delay(function(){this.previous=n}))}var n;n=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),t.preventDefault(),r.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,r.call(this)});if(this._start(t)===!1)return;this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(t){if(!e(t.currentTarget).hasClass("ui-state-active"))return;if(this._start(t)===!1)return!1;this._repeat(null,e(t.currentTarget).hasClass("ui-spinner-up")?1:-1,t)},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var e=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=e.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(e.height()*.5)&&e.height()>0&&e.height(e.height()),this.options.disabled&&this.disable()},_keydown:function(t){var n=this.options,r=e.ui.keyCode;switch(t.keyCode){case r.UP:return this._repeat(null,1,t),!0;case r.DOWN:return this._repeat(null,-1,t),!0;case r.PAGE_UP:return this._repeat(null,n.page,t),!0;case r.PAGE_DOWN:return this._repeat(null,-n.page,t),!0}return!1},_uiSpinnerHtml:function(){return"<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"},_buttonHtml:function(){return"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'><span class='ui-icon "+this.options.icons.up+"'>▲</span>"+"</a>"+"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>"+"<span class='ui-icon "+this.options.icons.down+"'>▼</span>"+"</a>"},_start:function(e){return!this.spinning&&this._trigger("start",e)===!1?!1:(this.counter||(this.counter=1),this.spinning=!0,!0)},_repeat:function(e,t,n){e=e||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,t,n)},e),this._spin(t*this.options.step,n)},_spin:function(e,t){var n=this.value()||0;this.counter||(this.counter=1),n=this._adjustValue(n+e*this._increment(this.counter));if(!this.spinning||this._trigger("spin",t,{value:n})!==!1)this._value(n),this.counter++},_increment:function(t){var n=this.options.incremental;return n?e.isFunction(n)?n(t):Math.floor(t*t*t/5e4-t*t/500+17*t/200+1):1},_precision:function(){var e=this._precisionOf(this.options.step);return this.options.min!==null&&(e=Math.max(e,this._precisionOf(this.options.min))),e},_precisionOf:function(e){var t=e.toString(),n=t.indexOf(".");return n===-1?0:t.length-n-1},_adjustValue:function(e){var t,n,r=this.options;return t=r.min!==null?r.min:0,n=e-t,n=Math.round(n/r.step)*r.step,e=t+n,e=parseFloat(e.toFixed(this._precision())),r.max!==null&&e>r.max?r.max:r.min!==null&&e<r.min?r.min:e},_stop:function(e){if(!this.spinning)return;clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",e)},_setOption:function(e,t){if(e==="culture"||e==="numberFormat"){var n=this._parse(this.element.val());this.options[e]=t,this.element.val(this._format(n));return}(e==="max"||e==="min"||e==="step")&&typeof t=="string"&&(t=this._parse(t)),this._super(e,t),e==="disabled"&&(t?(this.element.prop("disabled",!0),this.buttons.button("disable")):(this.element.prop("disabled",!1),this.buttons.button("enable")))},_setOptions:t(function(e){this._super(e),this._value(this.element.val())}),_parse:function(e){return typeof e=="string"&&e!==""&&(e=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(e,10,this.options.culture):+e),e===""||isNaN(e)?null:e},_format:function(e){return e===""?"":window.Globalize&&this.options.numberFormat?Globalize.format(e,this.options.numberFormat,this.options.culture):e},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},_value:function(e,t){var n;e!==""&&(n=this._parse(e),n!==null&&(t||(n=this._adjustValue(n)),e=this._format(n))),this.element.val(e),this._refresh()},_destroy:function(){this.element.removeClass("ui-spinner-input").prop("disabled",!1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:t(function(e){this._stepUp(e)}),_stepUp:function(e){this._spin((e||1)*this.options.step)},stepDown:t(function(e){this._stepDown(e)}),_stepDown:function(e){this._spin((e||1)*-this.options.step)},pageUp:t(function(e){this._stepUp((e||1)*this.options.page)}),pageDown:t(function(e){this._stepDown((e||1)*this.options.page)}),value:function(e){if(!arguments.length)return this._parse(this.element.val());t(this._value).call(this,e)},widget:function(){return this.uiSpinner}})})(jQuery);(function(e,t){function i(){return++n}function s(e){return e.hash.length>1&&e.href.replace(r,"")===location.href.replace(r,"").replace(/\s/g,"%20")}var n=0,r=/#.*$/;e.widget("ui.tabs",{version:"1.9.2",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var t=this,n=this.options,r=n.active,i=location.hash.substring(1);this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",n.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(t){e(this).is(".ui-state-disabled")&&t.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){e(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs();if(r===null){i&&this.tabs.each(function(t,n){if(e(n).attr("aria-controls")===i)return r=t,!1}),r===null&&(r=this.tabs.index(this.tabs.filter(".ui-tabs-active")));if(r===null||r===-1)r=this.tabs.length?0:!1}r!==!1&&(r=this.tabs.index(this.tabs.eq(r)),r===-1&&(r=n.collapsible?!1:0)),n.active=r,!n.collapsible&&n.active===!1&&this.anchors.length&&(n.active=0),e.isArray(n.disabled)&&(n.disabled=e.unique(n.disabled.concat(e.map(this.tabs.filter(".ui-state-disabled"),function(e){return t.tabs.index(e)}))).sort()),this.options.active!==!1&&this.anchors.length?this.active=this._findActive(this.options.active):this.active=e(),this._refresh(),this.active.length&&this.load(n.active)},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):e()}},_tabKeydown:function(t){var n=e(this.document[0].activeElement).closest("li"),r=this.tabs.index(n),i=!0;if(this._handlePageNav(t))return;switch(t.keyCode){case e.ui.keyCode.RIGHT:case e.ui.keyCode.DOWN:r++;break;case e.ui.keyCode.UP:case e.ui.keyCode.LEFT:i=!1,r--;break;case e.ui.keyCode.END:r=this.anchors.length-1;break;case e.ui.keyCode.HOME:r=0;break;case e.ui.keyCode.SPACE:t.preventDefault(),clearTimeout(this.activating),this._activate(r);return;case e.ui.keyCode.ENTER:t.preventDefault(),clearTimeout(this.activating),this._activate(r===this.options.active?!1:r);return;default:return}t.preventDefault(),clearTimeout(this.activating),r=this._focusNextTab(r,i),t.ctrlKey||(n.attr("aria-selected","false"),this.tabs.eq(r).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",r)},this.delay))},_panelKeydown:function(t){if(this._handlePageNav(t))return;t.ctrlKey&&t.keyCode===e.ui.keyCode.UP&&(t.preventDefault(),this.active.focus())},_handlePageNav:function(t){if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_UP)return this._activate(this._focusNextTab(this.options.active-1,!1)),!0;if(t.altKey&&t.keyCode===e.ui.keyCode.PAGE_DOWN)return this._activate(this._focusNextTab(this.options.active+1,!0)),!0},_findNextTab:function(t,n){function i(){return t>r&&(t=0),t<0&&(t=r),t}var r=this.tabs.length-1;while(e.inArray(i(),this.options.disabled)!==-1)t=n?t+1:t-1;return t},_focusNextTab:function(e,t){return e=this._findNextTab(e,t),this.tabs.eq(e).focus(),e},_setOption:function(e,t){if(e==="active"){this._activate(t);return}if(e==="disabled"){this._setupDisabled(t);return}this._super(e,t),e==="collapsible"&&(this.element.toggleClass("ui-tabs-collapsible",t),!t&&this.options.active===!1&&this._activate(0)),e==="event"&&this._setupEvents(t),e==="heightStyle"&&this._setupHeightStyle(t)},_tabId:function(e){return e.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(e){return e?e.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var t=this.options,n=this.tablist.children(":has(a[href])");t.disabled=e.map(n.filter(".ui-state-disabled"),function(e){return n.index(e)}),this._processTabs(),t.active===!1||!this.anchors.length?(t.active=!1,this.active=e()):this.active.length&&!e.contains(this.tablist[0],this.active[0])?this.tabs.length===t.disabled.length?(t.active=!1,this.active=e()):this._activate(this._findNextTab(Math.max(0,t.active-1),!1)):t.active=this.tabs.index(this.active),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var t=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return e("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=e(),this.anchors.each(function(n,r){var i,o,u,a=e(r).uniqueId().attr("id"),f=e(r).closest("li"),l=f.attr("aria-controls");s(r)?(i=r.hash,o=t.element.find(t._sanitizeSelector(i))):(u=t._tabId(f),i="#"+u,o=t.element.find(i),o.length||(o=t._createPanel(u),o.insertAfter(t.panels[n-1]||t.tablist)),o.attr("aria-live","polite")),o.length&&(t.panels=t.panels.add(o)),l&&f.data("ui-tabs-aria-controls",l),f.attr({"aria-controls":i.substring(1),"aria-labelledby":a}),o.attr("aria-labelledby",a)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(t){return e("<div>").attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(t){e.isArray(t)&&(t.length?t.length===this.anchors.length&&(t=!0):t=!1);for(var n=0,r;r=this.tabs[n];n++)t===!0||e.inArray(n,t)!==-1?e(r).addClass("ui-state-disabled").attr("aria-disabled","true"):e(r).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=t},_setupEvents:function(t){var n={click:function(e){e.preventDefault()}};t&&e.each(t.split(" "),function(e,t){n[t]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,n),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(t){var n,r,i=this.element.parent();t==="fill"?(e.support.minHeight||(r=i.css("overflow"),i.css("overflow","hidden")),n=i.height(),this.element.siblings(":visible").each(function(){var t=e(this),r=t.css("position");if(r==="absolute"||r==="fixed")return;n-=t.outerHeight(!0)}),r&&i.css("overflow",r),this.element.children().not(this.panels).each(function(){n-=e(this).outerHeight(!0)}),this.panels.each(function(){e(this).height(Math.max(0,n-e(this).innerHeight()+e(this).height()))}).css("overflow","auto")):t==="auto"&&(n=0,this.panels.each(function(){n=Math.max(n,e(this).height("").height())}).height(n))},_eventHandler:function(t){var n=this.options,r=this.active,i=e(t.currentTarget),s=i.closest("li"),o=s[0]===r[0],u=o&&n.collapsible,a=u?e():this._getPanelForTab(s),f=r.length?this._getPanelForTab(r):e(),l={oldTab:r,oldPanel:f,newTab:u?e():s,newPanel:a};t.preventDefault();if(s.hasClass("ui-state-disabled")||s.hasClass("ui-tabs-loading")||this.running||o&&!n.collapsible||this._trigger("beforeActivate",t,l)===!1)return;n.active=u?!1:this.tabs.index(s),this.active=o?e():s,this.xhr&&this.xhr.abort(),!f.length&&!a.length&&e.error("jQuery UI Tabs: Mismatching fragment identifier."),a.length&&this.load(this.tabs.index(s),t),this._toggle(t,l)},_toggle:function(t,n){function o(){r.running=!1,r._trigger("activate",t,n)}function u(){n.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),i.length&&r.options.show?r._show(i,r.options.show,o):(i.show(),o())}var r=this,i=n.newPanel,s=n.oldPanel;this.running=!0,s.length&&this.options.hide?this._hide(s,this.options.hide,function(){n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(n.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),s.hide(),u()),s.attr({"aria-expanded":"false","aria-hidden":"true"}),n.oldTab.attr("aria-selected","false"),i.length&&s.length?n.oldTab.attr("tabIndex",-1):i.length&&this.tabs.filter(function(){return e(this).attr("tabIndex")===0}).attr("tabIndex",-1),i.attr({"aria-expanded":"true","aria-hidden":"false"}),n.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(t){var n,r=this._findActive(t);if(r[0]===this.active[0])return;r.length||(r=this.active),n=r.find(".ui-tabs-anchor")[0],this._eventHandler({target:n,currentTarget:n,preventDefault:e.noop})},_findActive:function(t){return t===!1?e():this.tabs.eq(t)},_getIndex:function(e){return typeof e=="string"&&(e=this.anchors.index(this.anchors.filter("[href$='"+e+"']"))),e},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeData("href.tabs").removeData("load.tabs").removeUniqueId(),this.tabs.add(this.panels).each(function(){e.data(this,"ui-tabs-destroy")?e(this).remove():e(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var t=e(this),n=t.data("ui-tabs-aria-controls");n?t.attr("aria-controls",n):t.removeAttr("aria-controls")}),this.panels.show(),this.options.heightStyle!=="content"&&this.panels.css("height","")},enable:function(n){var r=this.options.disabled;if(r===!1)return;n===t?r=!1:(n=this._getIndex(n),e.isArray(r)?r=e.map(r,function(e){return e!==n?e:null}):r=e.map(this.tabs,function(e,t){return t!==n?t:null})),this._setupDisabled(r)},disable:function(n){var r=this.options.disabled;if(r===!0)return;if(n===t)r=!0;else{n=this._getIndex(n);if(e.inArray(n,r)!==-1)return;e.isArray(r)?r=e.merge([n],r).sort():r=[n]}this._setupDisabled(r)},load:function(t,n){t=this._getIndex(t);var r=this,i=this.tabs.eq(t),o=i.find(".ui-tabs-anchor"),u=this._getPanelForTab(i),a={tab:i,panel:u};if(s(o[0]))return;this.xhr=e.ajax(this._ajaxSettings(o,n,a)),this.xhr&&this.xhr.statusText!=="canceled"&&(i.addClass("ui-tabs-loading"),u.attr("aria-busy","true"),this.xhr.success(function(e){setTimeout(function(){u.html(e),r._trigger("load",n,a)},1)}).complete(function(e,t){setTimeout(function(){t==="abort"&&r.panels.stop(!1,!0),i.removeClass("ui-tabs-loading"),u.removeAttr("aria-busy"),e===r.xhr&&delete r.xhr},1)}))},_ajaxSettings:function(t,n,r){var i=this;return{url:t.attr("href"),beforeSend:function(t,s){return i._trigger("beforeLoad",n,e.extend({jqXHR:t,ajaxSettings:s},r))}}},_getPanelForTab:function(t){var n=e(t).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+n))}}),e.uiBackCompat!==!1&&(e.ui.tabs.prototype._ui=function(e,t){return{tab:e,panel:t,index:this.anchors.index(e)}},e.widget("ui.tabs",e.ui.tabs,{url:function(e,t){this.anchors.eq(e).attr("href",t)}}),e.widget("ui.tabs",e.ui.tabs,{options:{ajaxOptions:null,cache:!1},_create:function(){this._super();var t=this;this._on({tabsbeforeload:function(n,r){if(e.data(r.tab[0],"cache.tabs")){n.preventDefault();return}r.jqXHR.success(function(){t.options.cache&&e.data(r.tab[0],"cache.tabs",!0)})}})},_ajaxSettings:function(t,n,r){var i=this.options.ajaxOptions;return e.extend({},i,{error:function(e,t){try{i.error(e,t,r.tab.closest("li").index(),r.tab[0])}catch(n){}}},this._superApply(arguments))},_setOption:function(e,t){e==="cache"&&t===!1&&this.anchors.removeData("cache.tabs"),this._super(e,t)},_destroy:function(){this.anchors.removeData("cache.tabs"),this._super()},url:function(e){this.anchors.eq(e).removeData("cache.tabs"),this._superApply(arguments)}}),e.widget("ui.tabs",e.ui.tabs,{abort:function(){this.xhr&&this.xhr.abort()}}),e.widget("ui.tabs",e.ui.tabs,{options:{spinner:"<em>Loading…</em>"},_create:function(){this._super(),this._on({tabsbeforeload:function(e,t){if(e.target!==this.element[0]||!this.options.spinner)return;var n=t.tab.find("span"),r=n.html();n.html(this.options.spinner),t.jqXHR.complete(function(){n.html(r)})}})}}),e.widget("ui.tabs",e.ui.tabs,{options:{enable:null,disable:null},enable:function(t){var n=this.options,r;if(t&&n.disabled===!0||e.isArray(n.disabled)&&e.inArray(t,n.disabled)!==-1)r=!0;this._superApply(arguments),r&&this._trigger("enable",null,this._ui(this.anchors[t],this.panels[t]))},disable:function(t){var n=this.options,r;if(t&&n.disabled===!1||e.isArray(n.disabled)&&e.inArray(t,n.disabled)===-1)r=!0;this._superApply(arguments),r&&this._trigger("disable",null,this._ui(this.anchors[t],this.panels[t]))}}),e.widget("ui.tabs",e.ui.tabs,{options:{add:null,remove:null,tabTemplate:"<li><a href='#{href}'><span>#{label}</span></a></li>"},add:function(n,r,i){i===t&&(i=this.anchors.length);var s,o,u=this.options,a=e(u.tabTemplate.replace(/#\{href\}/g,n).replace(/#\{label\}/g,r)),f=n.indexOf("#")?this._tabId(a):n.replace("#","");return a.addClass("ui-state-default ui-corner-top").data("ui-tabs-destroy",!0),a.attr("aria-controls",f),s=i>=this.tabs.length,o=this.element.find("#"+f),o.length||(o=this._createPanel(f),s?i>0?o.insertAfter(this.panels.eq(-1)):o.appendTo(this.element):o.insertBefore(this.panels[i])),o.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").hide(),s?a.appendTo(this.tablist):a.insertBefore(this.tabs[i]),u.disabled=e.map(u.disabled,function(e){return e>=i?++e:e}),this.refresh(),this.tabs.length===1&&u.active===!1&&this.option("active",0),this._trigger("add",null,this._ui(this.anchors[i],this.panels[i])),this},remove:function(t){t=this._getIndex(t);var n=this.options,r=this.tabs.eq(t).remove(),i=this._getPanelForTab(r).remove();return r.hasClass("ui-tabs-active")&&this.anchors.length>2&&this._activate(t+(t+1<this.anchors.length?1:-1)),n.disabled=e.map(e.grep(n.disabled,function(e){return e!==t}),function(e){return e>=t?--e:e}),this.refresh(),this._trigger("remove",null,this._ui(r.find("a")[0],i[0])),this}}),e.widget("ui.tabs",e.ui.tabs,{length:function(){return this.anchors.length}}),e.widget("ui.tabs",e.ui.tabs,{options:{idPrefix:"ui-tabs-"},_tabId:function(t){var n=t.is("li")?t.find("a[href]"):t;return n=n[0],e(n).closest("li").attr("aria-controls")||n.title&&n.title.replace(/\s/g,"_").replace(/[^\w\u00c0-\uFFFF\-]/g,"")||this.options.idPrefix+i()}}),e.widget("ui.tabs",e.ui.tabs,{options:{panelTemplate:"<div></div>"},_createPanel:function(t){return e(this.options.panelTemplate).attr("id",t).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)}}),e.widget("ui.tabs",e.ui.tabs,{_create:function(){var e=this.options;e.active===null&&e.selected!==t&&(e.active=e.selected===-1?!1:e.selected),this._super(),e.selected=e.active,e.selected===!1&&(e.selected=-1)},_setOption:function(e,t){if(e!=="selected")return this._super(e,t);var n=this.options;this._super("active",t===-1?!1:t),n.selected=n.active,n.selected===!1&&(n.selected=-1)},_eventHandler:function(){this._superApply(arguments),this.options.selected=this.options.active,this.options.selected===!1&&(this.options.selected=-1)}}),e.widget("ui.tabs",e.ui.tabs,{options:{show:null,select:null},_create:function(){this._super(),this.options.active!==!1&&this._trigger("show",null,this._ui(this.active.find(".ui-tabs-anchor")[0],this._getPanelForTab(this.active)[0]))},_trigger:function(e,t,n){var r,i,s=this._superApply(arguments);return s?(e==="beforeActivate"?(r=n.newTab.length?n.newTab:n.oldTab,i=n.newPanel.length?n.newPanel:n.oldPanel,s=this._super("select",t,{tab:r.find(".ui-tabs-anchor")[0],panel:i[0],index:r.closest("li").index()})):e==="activate"&&n.newTab.length&&(s=this._super("show",t,{tab:n.newTab.find(".ui-tabs-anchor")[0],panel:n.newPanel[0],index:n.newTab.closest("li").index()})),s):!1}}),e.widget("ui.tabs",e.ui.tabs,{select:function(e){e=this._getIndex(e);if(e===-1){if(!this.options.collapsible||this.options.selected===-1)return;e=this.options.selected}this.anchors.eq(e).trigger(this.options.event+this.eventNamespace)}}),function(){var t=0;e.widget("ui.tabs",e.ui.tabs,{options:{cookie:null},_create:function(){var e=this.options,t;e.active==null&&e.cookie&&(t=parseInt(this._cookie(),10),t===-1&&(t=!1),e.active=t),this._super()},_cookie:function(n){var r=[this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+ ++t)];return arguments.length&&(r.push(n===!1?-1:n),r.push(this.options.cookie)),e.cookie.apply(null,r)},_refresh:function(){this._super(),this.options.cookie&&this._cookie(this.options.active,this.options.cookie)},_eventHandler:function(){this._superApply(arguments),this.options.cookie&&this._cookie(this.options.active,this.options.cookie)},_destroy:function(){this._super(),this.options.cookie&&this._cookie(null,this.options.cookie)}})}(),e.widget("ui.tabs",e.ui.tabs,{_trigger:function(t,n,r){var i=e.extend({},r);return t==="load"&&(i.panel=i.panel[0],i.tab=i.tab.find(".ui-tabs-anchor")[0]),this._super(t,n,i)}}),e.widget("ui.tabs",e.ui.tabs,{options:{fx:null},_getFx:function(){var t,n,r=this.options.fx;return r&&(e.isArray(r)?(t=r[0],n=r[1]):t=n=r),r?{show:n,hide:t}:null},_toggle:function(e,t){function o(){n.running=!1,n._trigger("activate",e,t)}function u(){t.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),r.length&&s.show?r.animate(s.show,s.show.duration,function(){o()}):(r.show(),o())}var n=this,r=t.newPanel,i=t.oldPanel,s=this._getFx();if(!s)return this._super(e,t);n.running=!0,i.length&&s.hide?i.animate(s.hide,s.hide.duration,function(){t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),u()}):(t.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),i.hide(),u())}}))})(jQuery);(function(e){function n(t,n){var r=(t.attr("aria-describedby")||"").split(/\s+/);r.push(n),t.data("ui-tooltip-id",n).attr("aria-describedby",e.trim(r.join(" ")))}function r(t){var n=t.data("ui-tooltip-id"),r=(t.attr("aria-describedby")||"").split(/\s+/),i=e.inArray(n,r);i!==-1&&r.splice(i,1),t.removeData("ui-tooltip-id"),r=e.trim(r.join(" ")),r?t.attr("aria-describedby",r):t.removeAttr("aria-describedby")}var t=0;e.widget("ui.tooltip",{version:"1.9.2",options:{content:function(){return e(this).attr("title")},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable()},_setOption:function(t,n){var r=this;if(t==="disabled"){this[n?"_disable":"_enable"](),this.options[t]=n;return}this._super(t,n),t==="content"&&e.each(this.tooltips,function(e,t){r._updateContent(t)})},_disable:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0)}),this.element.find(this.options.items).andSelf().each(function(){var t=e(this);t.is("[title]")&&t.data("ui-tooltip-title",t.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).andSelf().each(function(){var t=e(this);t.data("ui-tooltip-title")&&t.attr("title",t.data("ui-tooltip-title"))})},open:function(t){var n=this,r=e(t?t.target:this.element).closest(this.options.items);if(!r.length||r.data("ui-tooltip-id"))return;r.attr("title")&&r.data("ui-tooltip-title",r.attr("title")),r.data("ui-tooltip-open",!0),t&&t.type==="mouseover"&&r.parents().each(function(){var t=e(this),r;t.data("ui-tooltip-open")&&(r=e.Event("blur"),r.target=r.currentTarget=this,n.close(r,!0)),t.attr("title")&&(t.uniqueId(),n.parents[this.id]={element:this,title:t.attr("title")},t.attr("title",""))}),this._updateContent(r,t)},_updateContent:function(e,t){var n,r=this.options.content,i=this,s=t?t.type:null;if(typeof r=="string")return this._open(t,e,r);n=r.call(e[0],function(n){if(!e.data("ui-tooltip-open"))return;i._delay(function(){t&&(t.type=s),this._open(t,e,n)})}),n&&this._open(t,e,n)},_open:function(t,r,i){function f(e){a.of=e;if(s.is(":hidden"))return;s.position(a)}var s,o,u,a=e.extend({},this.options.position);if(!i)return;s=this._find(r);if(s.length){s.find(".ui-tooltip-content").html(i);return}r.is("[title]")&&(t&&t.type==="mouseover"?r.attr("title",""):r.removeAttr("title")),s=this._tooltip(r),n(r,s.attr("id")),s.find(".ui-tooltip-content").html(i),this.options.track&&t&&/^mouse/.test(t.type)?(this._on(this.document,{mousemove:f}),f(t)):s.position(e.extend({of:r},this.options.position)),s.hide(),this._show(s,this.options.show),this.options.show&&this.options.show.delay&&(u=setInterval(function(){s.is(":visible")&&(f(a.of),clearInterval(u))},e.fx.interval)),this._trigger("open",t,{tooltip:s}),o={keyup:function(t){if(t.keyCode===e.ui.keyCode.ESCAPE){var n=e.Event(t);n.currentTarget=r[0],this.close(n,!0)}},remove:function(){this._removeTooltip(s)}};if(!t||t.type==="mouseover")o.mouseleave="close";if(!t||t.type==="focusin")o.focusout="close";this._on(!0,r,o)},close:function(t){var n=this,i=e(t?t.currentTarget:this.element),s=this._find(i);if(this.closing)return;i.data("ui-tooltip-title")&&i.attr("title",i.data("ui-tooltip-title")),r(i),s.stop(!0),this._hide(s,this.options.hide,function(){n._removeTooltip(e(this))}),i.removeData("ui-tooltip-open"),this._off(i,"mouseleave focusout keyup"),i[0]!==this.element[0]&&this._off(i,"remove"),this._off(this.document,"mousemove"),t&&t.type==="mouseleave"&&e.each(this.parents,function(t,r){e(r.element).attr("title",r.title),delete n.parents[t]}),this.closing=!0,this._trigger("close",t,{tooltip:s}),this.closing=!1},_tooltip:function(n){var r="ui-tooltip-"+t++,i=e("<div>").attr({id:r,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return e("<div>").addClass("ui-tooltip-content").appendTo(i),i.appendTo(this.document[0].body),e.fn.bgiframe&&i.bgiframe(),this.tooltips[r]=n,i},_find:function(t){var n=t.data("ui-tooltip-id");return n?e("#"+n):e()},_removeTooltip:function(e){e.remove(),delete this.tooltips[e.attr("id")]},_destroy:function(){var t=this;e.each(this.tooltips,function(n,r){var i=e.Event("blur");i.target=i.currentTarget=r[0],t.close(i,!0),e("#"+n).remove(),r.data("ui-tooltip-title")&&(r.attr("title",r.data("ui-tooltip-title")),r.removeData("ui-tooltip-title"))})}})})(jQuery);jQuery.effects||function(e,t){var n=e.uiBackCompat!==!1,r="ui-effects-";e.effects={effect:{}},function(t,n){function p(e,t,n){var r=a[t.type]||{};return e==null?n||!t.def?null:t.def:(e=r.floor?~~e:parseFloat(e),isNaN(e)?t.def:r.mod?(e+r.mod)%r.mod:0>e?0:r.max<e?r.max:e)}function d(e){var n=o(),r=n._rgba=[];return e=e.toLowerCase(),h(s,function(t,i){var s,o=i.re.exec(e),a=o&&i.parse(o),f=i.space||"rgba";if(a)return s=n[f](a),n[u[f].cache]=s[u[f].cache],r=n._rgba=s._rgba,!1}),r.length?(r.join()==="0,0,0,0"&&t.extend(r,c.transparent),n):c[e]}function v(e,t,n){return n=(n+1)%1,n*6<1?e+(t-e)*n*6:n*2<1?t:n*3<2?e+(t-e)*(2/3-n)*6:e}var r="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor".split(" "),i=/^([\-+])=\s*(\d+\.?\d*)/,s=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1],e[2],e[3],e[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,parse:function(e){return[e[1]*2.55,e[2]*2.55,e[3]*2.55,e[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(e){return[parseInt(e[1],16),parseInt(e[2],16),parseInt(e[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(e){return[parseInt(e[1]+e[1],16),parseInt(e[2]+e[2],16),parseInt(e[3]+e[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(e){return[e[1],e[2]/100,e[3]/100,e[4]]}}],o=t.Color=function(e,n,r,i){return new t.Color.fn.parse(e,n,r,i)},u={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},a={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},f=o.support={},l=t("<p>")[0],c,h=t.each;l.style.cssText="background-color:rgba(1,1,1,.5)",f.rgba=l.style.backgroundColor.indexOf("rgba")>-1,h(u,function(e,t){t.cache="_"+e,t.props.alpha={idx:3,type:"percent",def:1}}),o.fn=t.extend(o.prototype,{parse:function(r,i,s,a){if(r===n)return this._rgba=[null,null,null,null],this;if(r.jquery||r.nodeType)r=t(r).css(i),i=n;var f=this,l=t.type(r),v=this._rgba=[];i!==n&&(r=[r,i,s,a],l="array");if(l==="string")return this.parse(d(r)||c._default);if(l==="array")return h(u.rgba.props,function(e,t){v[t.idx]=p(r[t.idx],t)}),this;if(l==="object")return r instanceof o?h(u,function(e,t){r[t.cache]&&(f[t.cache]=r[t.cache].slice())}):h(u,function(t,n){var i=n.cache;h(n.props,function(e,t){if(!f[i]&&n.to){if(e==="alpha"||r[e]==null)return;f[i]=n.to(f._rgba)}f[i][t.idx]=p(r[e],t,!0)}),f[i]&&e.inArray(null,f[i].slice(0,3))<0&&(f[i][3]=1,n.from&&(f._rgba=n.from(f[i])))}),this},is:function(e){var t=o(e),n=!0,r=this;return h(u,function(e,i){var s,o=t[i.cache];return o&&(s=r[i.cache]||i.to&&i.to(r._rgba)||[],h(i.props,function(e,t){if(o[t.idx]!=null)return n=o[t.idx]===s[t.idx],n})),n}),n},_space:function(){var e=[],t=this;return h(u,function(n,r){t[r.cache]&&e.push(n)}),e.pop()},transition:function(e,t){var n=o(e),r=n._space(),i=u[r],s=this.alpha()===0?o("transparent"):this,f=s[i.cache]||i.to(s._rgba),l=f.slice();return n=n[i.cache],h(i.props,function(e,r){var i=r.idx,s=f[i],o=n[i],u=a[r.type]||{};if(o===null)return;s===null?l[i]=o:(u.mod&&(o-s>u.mod/2?s+=u.mod:s-o>u.mod/2&&(s-=u.mod)),l[i]=p((o-s)*t+s,r))}),this[r](l)},blend:function(e){if(this._rgba[3]===1)return this;var n=this._rgba.slice(),r=n.pop(),i=o(e)._rgba;return o(t.map(n,function(e,t){return(1-r)*i[t]+r*e}))},toRgbaString:function(){var e="rgba(",n=t.map(this._rgba,function(e,t){return e==null?t>2?1:0:e});return n[3]===1&&(n.pop(),e="rgb("),e+n.join()+")"},toHslaString:function(){var e="hsla(",n=t.map(this.hsla(),function(e,t){return e==null&&(e=t>2?1:0),t&&t<3&&(e=Math.round(e*100)+"%"),e});return n[3]===1&&(n.pop(),e="hsl("),e+n.join()+")"},toHexString:function(e){var n=this._rgba.slice(),r=n.pop();return e&&n.push(~~(r*255)),"#"+t.map(n,function(e){return e=(e||0).toString(16),e.length===1?"0"+e:e}).join("")},toString:function(){return this._rgba[3]===0?"transparent":this.toRgbaString()}}),o.fn.parse.prototype=o.fn,u.hsla.to=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/255,n=e[1]/255,r=e[2]/255,i=e[3],s=Math.max(t,n,r),o=Math.min(t,n,r),u=s-o,a=s+o,f=a*.5,l,c;return o===s?l=0:t===s?l=60*(n-r)/u+360:n===s?l=60*(r-t)/u+120:l=60*(t-n)/u+240,f===0||f===1?c=f:f<=.5?c=u/a:c=u/(2-a),[Math.round(l)%360,c,f,i==null?1:i]},u.hsla.from=function(e){if(e[0]==null||e[1]==null||e[2]==null)return[null,null,null,e[3]];var t=e[0]/360,n=e[1],r=e[2],i=e[3],s=r<=.5?r*(1+n):r+n-r*n,o=2*r-s;return[Math.round(v(o,s,t+1/3)*255),Math.round(v(o,s,t)*255),Math.round(v(o,s,t-1/3)*255),i]},h(u,function(e,r){var s=r.props,u=r.cache,a=r.to,f=r.from;o.fn[e]=function(e){a&&!this[u]&&(this[u]=a(this._rgba));if(e===n)return this[u].slice();var r,i=t.type(e),l=i==="array"||i==="object"?e:arguments,c=this[u].slice();return h(s,function(e,t){var n=l[i==="object"?e:t.idx];n==null&&(n=c[t.idx]),c[t.idx]=p(n,t)}),f?(r=o(f(c)),r[u]=c,r):o(c)},h(s,function(n,r){if(o.fn[n])return;o.fn[n]=function(s){var o=t.type(s),u=n==="alpha"?this._hsla?"hsla":"rgba":e,a=this[u](),f=a[r.idx],l;return o==="undefined"?f:(o==="function"&&(s=s.call(this,f),o=t.type(s)),s==null&&r.empty?this:(o==="string"&&(l=i.exec(s),l&&(s=f+parseFloat(l[2])*(l[1]==="+"?1:-1))),a[r.idx]=s,this[u](a)))}})}),h(r,function(e,n){t.cssHooks[n]={set:function(e,r){var i,s,u="";if(t.type(r)!=="string"||(i=d(r))){r=o(i||r);if(!f.rgba&&r._rgba[3]!==1){s=n==="backgroundColor"?e.parentNode:e;while((u===""||u==="transparent")&&s&&s.style)try{u=t.css(s,"backgroundColor"),s=s.parentNode}catch(a){}r=r.blend(u&&u!=="transparent"?u:"_default")}r=r.toRgbaString()}try{e.style[n]=r}catch(l){}}},t.fx.step[n]=function(e){e.colorInit||(e.start=o(e.elem,n),e.end=o(e.end),e.colorInit=!0),t.cssHooks[n].set(e.elem,e.start.transition(e.end,e.pos))}}),t.cssHooks.borderColor={expand:function(e){var t={};return h(["Top","Right","Bottom","Left"],function(n,r){t["border"+r+"Color"]=e}),t}},c=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(jQuery),function(){function i(){var t=this.ownerDocument.defaultView?this.ownerDocument.defaultView.getComputedStyle(this,null):this.currentStyle,n={},r,i;if(t&&t.length&&t[0]&&t[t[0]]){i=t.length;while(i--)r=t[i],typeof t[r]=="string"&&(n[e.camelCase(r)]=t[r])}else for(r in t)typeof t[r]=="string"&&(n[r]=t[r]);return n}function s(t,n){var i={},s,o;for(s in n)o=n[s],t[s]!==o&&!r[s]&&(e.fx.step[s]||!isNaN(parseFloat(o)))&&(i[s]=o);return i}var n=["add","remove","toggle"],r={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};e.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(t,n){e.fx.step[n]=function(e){if(e.end!=="none"&&!e.setAttr||e.pos===1&&!e.setAttr)jQuery.style(e.elem,n,e.end),e.setAttr=!0}}),e.effects.animateClass=function(t,r,o,u){var a=e.speed(r,o,u);return this.queue(function(){var r=e(this),o=r.attr("class")||"",u,f=a.children?r.find("*").andSelf():r;f=f.map(function(){var t=e(this);return{el:t,start:i.call(this)}}),u=function(){e.each(n,function(e,n){t[n]&&r[n+"Class"](t[n])})},u(),f=f.map(function(){return this.end=i.call(this.el[0]),this.diff=s(this.start,this.end),this}),r.attr("class",o),f=f.map(function(){var t=this,n=e.Deferred(),r=jQuery.extend({},a,{queue:!1,complete:function(){n.resolve(t)}});return this.el.animate(this.diff,r),n.promise()}),e.when.apply(e,f.get()).done(function(){u(),e.each(arguments,function(){var t=this.el;e.each(this.diff,function(e){t.css(e,"")})}),a.complete.call(r[0])})})},e.fn.extend({_addClass:e.fn.addClass,addClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{add:t},n,r,i):this._addClass(t)},_removeClass:e.fn.removeClass,removeClass:function(t,n,r,i){return n?e.effects.animateClass.call(this,{remove:t},n,r,i):this._removeClass(t)},_toggleClass:e.fn.toggleClass,toggleClass:function(n,r,i,s,o){return typeof r=="boolean"||r===t?i?e.effects.animateClass.call(this,r?{add:n}:{remove:n},i,s,o):this._toggleClass(n,r):e.effects.animateClass.call(this,{toggle:n},r,i,s)},switchClass:function(t,n,r,i,s){return e.effects.animateClass.call(this,{add:n,remove:t},r,i,s)}})}(),function(){function i(t,n,r,i){e.isPlainObject(t)&&(n=t,t=t.effect),t={effect:t},n==null&&(n={}),e.isFunction(n)&&(i=n,r=null,n={});if(typeof n=="number"||e.fx.speeds[n])i=r,r=n,n={};return e.isFunction(r)&&(i=r,r=null),n&&e.extend(t,n),r=r||n.duration,t.duration=e.fx.off?0:typeof r=="number"?r:r in e.fx.speeds?e.fx.speeds[r]:e.fx.speeds._default,t.complete=i||n.complete,t}function s(t){return!t||typeof t=="number"||e.fx.speeds[t]?!0:typeof t=="string"&&!e.effects.effect[t]?n&&e.effects[t]?!1:!0:!1}e.extend(e.effects,{version:"1.9.2",save:function(e,t){for(var n=0;n<t.length;n++)t[n]!==null&&e.data(r+t[n],e[0].style[t[n]])},restore:function(e,n){var i,s;for(s=0;s<n.length;s++)n[s]!==null&&(i=e.data(r+n[s]),i===t&&(i=""),e.css(n[s],i))},setMode:function(e,t){return t==="toggle"&&(t=e.is(":hidden")?"show":"hide"),t},getBaseline:function(e,t){var n,r;switch(e[0]){case"top":n=0;break;case"middle":n=.5;break;case"bottom":n=1;break;default:n=e[0]/t.height}switch(e[1]){case"left":r=0;break;case"center":r=.5;break;case"right":r=1;break;default:r=e[1]/t.width}return{x:r,y:n}},createWrapper:function(t){if(t.parent().is(".ui-effects-wrapper"))return t.parent();var n={width:t.outerWidth(!0),height:t.outerHeight(!0),"float":t.css("float")},r=e("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),i={width:t.width(),height:t.height()},s=document.activeElement;try{s.id}catch(o){s=document.body}return t.wrap(r),(t[0]===s||e.contains(t[0],s))&&e(s).focus(),r=t.parent(),t.css("position")==="static"?(r.css({position:"relative"}),t.css({position:"relative"})):(e.extend(n,{position:t.css("position"),zIndex:t.css("z-index")}),e.each(["top","left","bottom","right"],function(e,r){n[r]=t.css(r),isNaN(parseInt(n[r],10))&&(n[r]="auto")}),t.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),t.css(i),r.css(n).show()},removeWrapper:function(t){var n=document.activeElement;return t.parent().is(".ui-effects-wrapper")&&(t.parent().replaceWith(t),(t[0]===n||e.contains(t[0],n))&&e(n).focus()),t},setTransition:function(t,n,r,i){return i=i||{},e.each(n,function(e,n){var s=t.cssUnit(n);s[0]>0&&(i[n]=s[0]*r+s[1])}),i}}),e.fn.extend({effect:function(){function a(n){function u(){e.isFunction(i)&&i.call(r[0]),e.isFunction(n)&&n()}var r=e(this),i=t.complete,s=t.mode;(r.is(":hidden")?s==="hide":s==="show")?u():o.call(r[0],t,u)}var t=i.apply(this,arguments),r=t.mode,s=t.queue,o=e.effects.effect[t.effect],u=!o&&n&&e.effects[t.effect];return e.fx.off||!o&&!u?r?this[r](t.duration,t.complete):this.each(function(){t.complete&&t.complete.call(this)}):o?s===!1?this.each(a):this.queue(s||"fx",a):u.call(this,{options:t,duration:t.duration,callback:t.complete,mode:t.mode})},_show:e.fn.show,show:function(e){if(s(e))return this._show.apply(this,arguments);var t=i.apply(this,arguments);return t.mode="show",this.effect.call(this,t)},_hide:e.fn.hide,hide:function(e){if(s(e))return this._hide.apply(this,arguments);var t=i.apply(this,arguments);return t.mode="hide",this.effect.call(this,t)},__toggle:e.fn.toggle,toggle:function(t){if(s(t)||typeof t=="boolean"||e.isFunction(t))return this.__toggle.apply(this,arguments);var n=i.apply(this,arguments);return n.mode="toggle",this.effect.call(this,n)},cssUnit:function(t){var n=this.css(t),r=[];return e.each(["em","px","%","pt"],function(e,t){n.indexOf(t)>0&&(r=[parseFloat(n),t])}),r}})}(),function(){var t={};e.each(["Quad","Cubic","Quart","Quint","Expo"],function(e,n){t[n]=function(t){return Math.pow(t,e+2)}}),e.extend(t,{Sine:function(e){return 1-Math.cos(e*Math.PI/2)},Circ:function(e){return 1-Math.sqrt(1-e*e)},Elastic:function(e){return e===0||e===1?e:-Math.pow(2,8*(e-1))*Math.sin(((e-1)*80-7.5)*Math.PI/15)},Back:function(e){return e*e*(3*e-2)},Bounce:function(e){var t,n=4;while(e<((t=Math.pow(2,--n))-1)/11);return 1/Math.pow(4,3-n)-7.5625*Math.pow((t*3-2)/22-e,2)}}),e.each(t,function(t,n){e.easing["easeIn"+t]=n,e.easing["easeOut"+t]=function(e){return 1-n(1-e)},e.easing["easeInOut"+t]=function(e){return e<.5?n(e*2)/2:1-n(e*-2+2)/2}})}()}(jQuery);(function(e,t){var n=/up|down|vertical/,r=/up|left|vertical|horizontal/;e.effects.effect.blind=function(t,i){var s=e(this),o=["position","top","bottom","left","right","height","width"],u=e.effects.setMode(s,t.mode||"hide"),a=t.direction||"up",f=n.test(a),l=f?"height":"width",c=f?"top":"left",h=r.test(a),p={},d=u==="show",v,m,g;s.parent().is(".ui-effects-wrapper")?e.effects.save(s.parent(),o):e.effects.save(s,o),s.show(),v=e.effects.createWrapper(s).css({overflow:"hidden"}),m=v[l](),g=parseFloat(v.css(c))||0,p[l]=d?m:0,h||(s.css(f?"bottom":"right",0).css(f?"top":"left","auto").css({position:"absolute"}),p[c]=d?g:m+g),d&&(v.css(l,0),h||v.css(c,g+m)),v.animate(p,{duration:t.duration,easing:t.easing,queue:!1,complete:function(){u==="hide"&&s.hide(),e.effects.restore(s,o),e.effects.removeWrapper(s),i()}})}})(jQuery);(function(e,t){e.effects.effect.bounce=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"effect"),o=s==="hide",u=s==="show",a=t.direction||"up",f=t.distance,l=t.times||5,c=l*2+(u||o?1:0),h=t.duration/c,p=t.easing,d=a==="up"||a==="down"?"top":"left",v=a==="up"||a==="left",m,g,y,b=r.queue(),w=b.length;(u||o)&&i.push("opacity"),e.effects.save(r,i),r.show(),e.effects.createWrapper(r),f||(f=r[d==="top"?"outerHeight":"outerWidth"]()/3),u&&(y={opacity:1},y[d]=0,r.css("opacity",0).css(d,v?-f*2:f*2).animate(y,h,p)),o&&(f/=Math.pow(2,l-1)),y={},y[d]=0;for(m=0;m<l;m++)g={},g[d]=(v?"-=":"+=")+f,r.animate(g,h,p).animate(y,h,p),f=o?f*2:f/2;o&&(g={opacity:0},g[d]=(v?"-=":"+=")+f,r.animate(g,h,p)),r.queue(function(){o&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}),w>1&&b.splice.apply(b,[1,0].concat(b.splice(w,c+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.clip=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"vertical",a=u==="vertical",f=a?"height":"width",l=a?"top":"left",c={},h,p,d;e.effects.save(r,i),r.show(),h=e.effects.createWrapper(r).css({overflow:"hidden"}),p=r[0].tagName==="IMG"?h:r,d=p[f](),o&&(p.css(f,0),p.css(l,d/2)),c[f]=o?d:0,c[l]=o?0:d/2,p.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){o||r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.drop=function(t,n){var r=e(this),i=["position","top","bottom","left","right","opacity","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left"?"pos":"neg",l={opacity:o?1:0},c;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),c=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0)/2,o&&r.css("opacity",0).css(a,f==="pos"?-c:c),l[a]=(o?f==="pos"?"+=":"-=":f==="pos"?"-=":"+=")+c,r.animate(l,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.explode=function(t,n){function y(){c.push(this),c.length===r*i&&b()}function b(){s.css({visibility:"visible"}),e(c).remove(),u||s.hide(),n()}var r=t.pieces?Math.round(Math.sqrt(t.pieces)):3,i=r,s=e(this),o=e.effects.setMode(s,t.mode||"hide"),u=o==="show",a=s.show().css("visibility","hidden").offset(),f=Math.ceil(s.outerWidth()/i),l=Math.ceil(s.outerHeight()/r),c=[],h,p,d,v,m,g;for(h=0;h<r;h++){v=a.top+h*l,g=h-(r-1)/2;for(p=0;p<i;p++)d=a.left+p*f,m=p-(i-1)/2,s.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-p*f,top:-h*l}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:f,height:l,left:d+(u?m*f:0),top:v+(u?g*l:0),opacity:u?0:1}).animate({left:d+(u?0:m*f),top:v+(u?0:g*l),opacity:u?1:0},t.duration||500,t.easing,y)}}})(jQuery);(function(e,t){e.effects.effect.fade=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"toggle");r.animate({opacity:i},{queue:!1,duration:t.duration,easing:t.easing,complete:n})}})(jQuery);(function(e,t){e.effects.effect.fold=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"hide"),o=s==="show",u=s==="hide",a=t.size||15,f=/([0-9]+)%/.exec(a),l=!!t.horizFirst,c=o!==l,h=c?["width","height"]:["height","width"],p=t.duration/2,d,v,m={},g={};e.effects.save(r,i),r.show(),d=e.effects.createWrapper(r).css({overflow:"hidden"}),v=c?[d.width(),d.height()]:[d.height(),d.width()],f&&(a=parseInt(f[1],10)/100*v[u?0:1]),o&&d.css(l?{height:0,width:a}:{height:a,width:0}),m[h[0]]=o?v[0]:a,g[h[1]]=o?v[1]:0,d.animate(m,p,t.easing).animate(g,p,t.easing,function(){u&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()})}})(jQuery);(function(e,t){e.effects.effect.highlight=function(t,n){var r=e(this),i=["backgroundImage","backgroundColor","opacity"],s=e.effects.setMode(r,t.mode||"show"),o={backgroundColor:r.css("backgroundColor")};s==="hide"&&(o.opacity=0),e.effects.save(r,i),r.show().css({backgroundImage:"none",backgroundColor:t.color||"#ffff99"}).animate(o,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),n()}})}})(jQuery);(function(e,t){e.effects.effect.pulsate=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"show"),s=i==="show",o=i==="hide",u=s||i==="hide",a=(t.times||5)*2+(u?1:0),f=t.duration/a,l=0,c=r.queue(),h=c.length,p;if(s||!r.is(":visible"))r.css("opacity",0).show(),l=1;for(p=1;p<a;p++)r.animate({opacity:l},f,t.easing),l=1-l;r.animate({opacity:l},f,t.easing),r.queue(function(){o&&r.hide(),n()}),h>1&&c.splice.apply(c,[1,0].concat(c.splice(h,a+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.puff=function(t,n){var r=e(this),i=e.effects.setMode(r,t.mode||"hide"),s=i==="hide",o=parseInt(t.percent,10)||150,u=o/100,a={height:r.height(),width:r.width(),outerHeight:r.outerHeight(),outerWidth:r.outerWidth()};e.extend(t,{effect:"scale",queue:!1,fade:!0,mode:i,complete:n,percent:s?o:100,from:s?a:{height:a.height*u,width:a.width*u,outerHeight:a.outerHeight*u,outerWidth:a.outerWidth*u}}),r.effect(t)},e.effects.effect.scale=function(t,n){var r=e(this),i=e.extend(!0,{},t),s=e.effects.setMode(r,t.mode||"effect"),o=parseInt(t.percent,10)||(parseInt(t.percent,10)===0?0:s==="hide"?0:100),u=t.direction||"both",a=t.origin,f={height:r.height(),width:r.width(),outerHeight:r.outerHeight(),outerWidth:r.outerWidth()},l={y:u!=="horizontal"?o/100:1,x:u!=="vertical"?o/100:1};i.effect="size",i.queue=!1,i.complete=n,s!=="effect"&&(i.origin=a||["middle","center"],i.restore=!0),i.from=t.from||(s==="show"?{height:0,width:0,outerHeight:0,outerWidth:0}:f),i.to={height:f.height*l.y,width:f.width*l.x,outerHeight:f.outerHeight*l.y,outerWidth:f.outerWidth*l.x},i.fade&&(s==="show"&&(i.from.opacity=0,i.to.opacity=1),s==="hide"&&(i.from.opacity=1,i.to.opacity=0)),r.effect(i)},e.effects.effect.size=function(t,n){var r,i,s,o=e(this),u=["position","top","bottom","left","right","width","height","overflow","opacity"],a=["position","top","bottom","left","right","overflow","opacity"],f=["width","height","overflow"],l=["fontSize"],c=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],h=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=e.effects.setMode(o,t.mode||"effect"),d=t.restore||p!=="effect",v=t.scale||"both",m=t.origin||["middle","center"],g=o.css("position"),y=d?u:a,b={height:0,width:0,outerHeight:0,outerWidth:0};p==="show"&&o.show(),r={height:o.height(),width:o.width(),outerHeight:o.outerHeight(),outerWidth:o.outerWidth()},t.mode==="toggle"&&p==="show"?(o.from=t.to||b,o.to=t.from||r):(o.from=t.from||(p==="show"?b:r),o.to=t.to||(p==="hide"?b:r)),s={from:{y:o.from.height/r.height,x:o.from.width/r.width},to:{y:o.to.height/r.height,x:o.to.width/r.width}};if(v==="box"||v==="both")s.from.y!==s.to.y&&(y=y.concat(c),o.from=e.effects.setTransition(o,c,s.from.y,o.from),o.to=e.effects.setTransition(o,c,s.to.y,o.to)),s.from.x!==s.to.x&&(y=y.concat(h),o.from=e.effects.setTransition(o,h,s.from.x,o.from),o.to=e.effects.setTransition(o,h,s.to.x,o.to));(v==="content"||v==="both")&&s.from.y!==s.to.y&&(y=y.concat(l).concat(f),o.from=e.effects.setTransition(o,l,s.from.y,o.from),o.to=e.effects.setTransition(o,l,s.to.y,o.to)),e.effects.save(o,y),o.show(),e.effects.createWrapper(o),o.css("overflow","hidden").css(o.from),m&&(i=e.effects.getBaseline(m,r),o.from.top=(r.outerHeight-o.outerHeight())*i.y,o.from.left=(r.outerWidth-o.outerWidth())*i.x,o.to.top=(r.outerHeight-o.to.outerHeight)*i.y,o.to.left=(r.outerWidth-o.to.outerWidth)*i.x),o.css(o.from);if(v==="content"||v==="both")c=c.concat(["marginTop","marginBottom"]).concat(l),h=h.concat(["marginLeft","marginRight"]),f=u.concat(c).concat(h),o.find("*[width]").each(function(){var n=e(this),r={height:n.height(),width:n.width(),outerHeight:n.outerHeight(),outerWidth:n.outerWidth()};d&&e.effects.save(n,f),n.from={height:r.height*s.from.y,width:r.width*s.from.x,outerHeight:r.outerHeight*s.from.y,outerWidth:r.outerWidth*s.from.x},n.to={height:r.height*s.to.y,width:r.width*s.to.x,outerHeight:r.height*s.to.y,outerWidth:r.width*s.to.x},s.from.y!==s.to.y&&(n.from=e.effects.setTransition(n,c,s.from.y,n.from),n.to=e.effects.setTransition(n,c,s.to.y,n.to)),s.from.x!==s.to.x&&(n.from=e.effects.setTransition(n,h,s.from.x,n.from),n.to=e.effects.setTransition(n,h,s.to.x,n.to)),n.css(n.from),n.animate(n.to,t.duration,t.easing,function(){d&&e.effects.restore(n,f)})});o.animate(o.to,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){o.to.opacity===0&&o.css("opacity",o.from.opacity),p==="hide"&&o.hide(),e.effects.restore(o,y),d||(g==="static"?o.css({position:"relative",top:o.to.top,left:o.to.left}):e.each(["top","left"],function(e,t){o.css(t,function(t,n){var r=parseInt(n,10),i=e?o.to.left:o.to.top;return n==="auto"?i+"px":r+i+"px"})})),e.effects.removeWrapper(o),n()}})}})(jQuery);(function(e,t){e.effects.effect.shake=function(t,n){var r=e(this),i=["position","top","bottom","left","right","height","width"],s=e.effects.setMode(r,t.mode||"effect"),o=t.direction||"left",u=t.distance||20,a=t.times||3,f=a*2+1,l=Math.round(t.duration/f),c=o==="up"||o==="down"?"top":"left",h=o==="up"||o==="left",p={},d={},v={},m,g=r.queue(),y=g.length;e.effects.save(r,i),r.show(),e.effects.createWrapper(r),p[c]=(h?"-=":"+=")+u,d[c]=(h?"+=":"-=")+u*2,v[c]=(h?"-=":"+=")+u*2,r.animate(p,l,t.easing);for(m=1;m<a;m++)r.animate(d,l,t.easing).animate(v,l,t.easing);r.animate(d,l,t.easing).animate(p,l/2,t.easing).queue(function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}),y>1&&g.splice.apply(g,[1,0].concat(g.splice(y,f+1))),r.dequeue()}})(jQuery);(function(e,t){e.effects.effect.slide=function(t,n){var r=e(this),i=["position","top","bottom","left","right","width","height"],s=e.effects.setMode(r,t.mode||"show"),o=s==="show",u=t.direction||"left",a=u==="up"||u==="down"?"top":"left",f=u==="up"||u==="left",l,c={};e.effects.save(r,i),r.show(),l=t.distance||r[a==="top"?"outerHeight":"outerWidth"](!0),e.effects.createWrapper(r).css({overflow:"hidden"}),o&&r.css(a,f?isNaN(l)?"-"+l:-l:l),c[a]=(o?f?"+=":"-=":f?"-=":"+=")+l,r.animate(c,{queue:!1,duration:t.duration,easing:t.easing,complete:function(){s==="hide"&&r.hide(),e.effects.restore(r,i),e.effects.removeWrapper(r),n()}})}})(jQuery);(function(e,t){e.effects.effect.transfer=function(t,n){var r=e(this),i=e(t.to),s=i.css("position")==="fixed",o=e("body"),u=s?o.scrollTop():0,a=s?o.scrollLeft():0,f=i.offset(),l={top:f.top-u,left:f.left-a,height:i.innerHeight(),width:i.innerWidth()},c=r.offset(),h=e('<div class="ui-effects-transfer"></div>').appendTo(document.body).addClass(t.className).css({top:c.top-u,left:c.left-a,height:r.innerHeight(),width:r.innerWidth(),position:s?"fixed":"absolute"}).animate(l,t.duration,t.easing,function(){h.remove(),n()})}})(jQuery);
\ No newline at end of file diff --git a/hugo/js/jquery/jquery-ui-timepicker-addon.js b/hugo/js/jquery/jquery-ui-timepicker-addon.js new file mode 100644 index 0000000..b8616da --- /dev/null +++ b/hugo/js/jquery/jquery-ui-timepicker-addon.js @@ -0,0 +1,1882 @@ +/* + * jQuery timepicker addon + * By: Trent Richardson [http://trentrichardson.com] + * Version 1.1.1 + * Last Modified: 11/07/2012 + * + * Copyright 2012 Trent Richardson + * You may use this project under MIT or GPL licenses. + * http://trentrichardson.com/Impromptu/GPL-LICENSE.txt + * http://trentrichardson.com/Impromptu/MIT-LICENSE.txt + */ + +/*jslint evil: true, white: false, undef: false, nomen: false */ + +(function($) { + + /* + * Lets not redefine timepicker, Prevent "Uncaught RangeError: Maximum call stack size exceeded" + */ + $.ui.timepicker = $.ui.timepicker || {}; + if ($.ui.timepicker.version) { + return; + } + + /* + * Extend jQueryUI, get it started with our version number + */ + $.extend($.ui, { + timepicker: { + version: "1.1.1" + } + }); + + /* + * Timepicker manager. + * Use the singleton instance of this class, $.timepicker, to interact with the time picker. + * Settings for (groups of) time pickers are maintained in an instance object, + * allowing multiple different settings on the same page. + */ + function Timepicker() { + this.regional = []; // Available regional settings, indexed by language code + this.regional[''] = { // Default regional settings + currentText: 'Now', + closeText: 'Done', + amNames: ['AM', 'A'], + pmNames: ['PM', 'P'], + timeFormat: 'HH:mm', + timeSuffix: '', + timeOnlyTitle: 'Choose Time', + timeText: 'Time', + hourText: 'Hour', + minuteText: 'Minute', + secondText: 'Second', + millisecText: 'Millisecond', + timezoneText: 'Time Zone', + isRTL: false + }; + this._defaults = { // Global defaults for all the datetime picker instances + showButtonPanel: true, + timeOnly: false, + showHour: true, + showMinute: true, + showSecond: false, + showMillisec: false, + showTimezone: false, + showTime: true, + stepHour: 1, + stepMinute: 1, + stepSecond: 1, + stepMillisec: 1, + hour: 0, + minute: 0, + second: 0, + millisec: 0, + timezone: null, + useLocalTimezone: false, + defaultTimezone: "+0000", + hourMin: 0, + minuteMin: 0, + secondMin: 0, + millisecMin: 0, + hourMax: 23, + minuteMax: 59, + secondMax: 59, + millisecMax: 999, + minDateTime: null, + maxDateTime: null, + onSelect: null, + hourGrid: 0, + minuteGrid: 0, + secondGrid: 0, + millisecGrid: 0, + alwaysSetTime: true, + separator: ' ', + altFieldTimeOnly: true, + altTimeFormat: null, + altSeparator: null, + altTimeSuffix: null, + pickerTimeFormat: null, + pickerTimeSuffix: null, + showTimepicker: true, + timezoneIso8601: false, + timezoneList: null, + addSliderAccess: false, + sliderAccessArgs: null, + controlType: 'slider', + defaultValue: null, + parse: 'strict' + }; + $.extend(this._defaults, this.regional['']); + } + + $.extend(Timepicker.prototype, { + $input: null, + $altInput: null, + $timeObj: null, + inst: null, + hour_slider: null, + minute_slider: null, + second_slider: null, + millisec_slider: null, + timezone_select: null, + hour: 0, + minute: 0, + second: 0, + millisec: 0, + timezone: null, + defaultTimezone: "+0000", + hourMinOriginal: null, + minuteMinOriginal: null, + secondMinOriginal: null, + millisecMinOriginal: null, + hourMaxOriginal: null, + minuteMaxOriginal: null, + secondMaxOriginal: null, + millisecMaxOriginal: null, + ampm: '', + formattedDate: '', + formattedTime: '', + formattedDateTime: '', + timezoneList: null, + units: ['hour','minute','second','millisec'], + control: null, + + /* + * Override the default settings for all instances of the time picker. + * @param settings object - the new settings to use as defaults (anonymous object) + * @return the manager object + */ + setDefaults: function(settings) { + extendRemove(this._defaults, settings || {}); + return this; + }, + + /* + * Create a new Timepicker instance + */ + _newInst: function($input, o) { + var tp_inst = new Timepicker(), + inlineSettings = {}, + fns = {}, + overrides, i; + + for (var attrName in this._defaults) { + if(this._defaults.hasOwnProperty(attrName)){ + var attrValue = $input.attr('time:' + attrName); + if (attrValue) { + try { + inlineSettings[attrName] = eval(attrValue); + } catch (err) { + inlineSettings[attrName] = attrValue; + } + } + } + } + overrides = { + beforeShow: function (input, dp_inst) { + if ($.isFunction(tp_inst._defaults.evnts.beforeShow)) { + return tp_inst._defaults.evnts.beforeShow.call($input[0], input, dp_inst, tp_inst); + } + }, + onChangeMonthYear: function (year, month, dp_inst) { + // Update the time as well : this prevents the time from disappearing from the $input field. + tp_inst._updateDateTime(dp_inst); + if ($.isFunction(tp_inst._defaults.evnts.onChangeMonthYear)) { + tp_inst._defaults.evnts.onChangeMonthYear.call($input[0], year, month, dp_inst, tp_inst); + } + }, + onClose: function (dateText, dp_inst) { + if (tp_inst.timeDefined === true && $input.val() !== '') { + tp_inst._updateDateTime(dp_inst); + } + if ($.isFunction(tp_inst._defaults.evnts.onClose)) { + tp_inst._defaults.evnts.onClose.call($input[0], dateText, dp_inst, tp_inst); + } + } + }; + for (i in overrides) { + if (overrides.hasOwnProperty(i)) { + fns[i] = o[i] || null; + } + } + tp_inst._defaults = $.extend({}, this._defaults, inlineSettings, o, overrides, { + evnts:fns, + timepicker: tp_inst // add timepicker as a property of datepicker: $.datepicker._get(dp_inst, 'timepicker'); + }); + tp_inst.amNames = $.map(tp_inst._defaults.amNames, function(val) { + return val.toUpperCase(); + }); + tp_inst.pmNames = $.map(tp_inst._defaults.pmNames, function(val) { + return val.toUpperCase(); + }); + + // controlType is string - key to our this._controls + if(typeof(tp_inst._defaults.controlType) === 'string'){ + if($.fn[tp_inst._defaults.controlType] === undefined){ + tp_inst._defaults.controlType = 'select'; + } + tp_inst.control = tp_inst._controls[tp_inst._defaults.controlType]; + } + // controlType is an object and must implement create, options, value methods + else{ + tp_inst.control = tp_inst._defaults.controlType; + } + + if (tp_inst._defaults.timezoneList === null) { + var timezoneList = ['-1200', '-1100', '-1000', '-0930', '-0900', '-0800', '-0700', '-0600', '-0500', '-0430', '-0400', '-0330', '-0300', '-0200', '-0100', '+0000', + '+0100', '+0200', '+0300', '+0330', '+0400', '+0430', '+0500', '+0530', '+0545', '+0600', '+0630', '+0700', '+0800', '+0845', '+0900', '+0930', + '+1000', '+1030', '+1100', '+1130', '+1200', '+1245', '+1300', '+1400']; + + if (tp_inst._defaults.timezoneIso8601) { + timezoneList = $.map(timezoneList, function(val) { + return val == '+0000' ? 'Z' : (val.substring(0, 3) + ':' + val.substring(3)); + }); + } + tp_inst._defaults.timezoneList = timezoneList; + } + + tp_inst.timezone = tp_inst._defaults.timezone; + tp_inst.hour = tp_inst._defaults.hour; + tp_inst.minute = tp_inst._defaults.minute; + tp_inst.second = tp_inst._defaults.second; + tp_inst.millisec = tp_inst._defaults.millisec; + tp_inst.ampm = ''; + tp_inst.$input = $input; + + if (o.altField) { + tp_inst.$altInput = $(o.altField).css({ + cursor: 'pointer' + }).focus(function() { + $input.trigger("focus"); + }); + } + + if (tp_inst._defaults.minDate === 0 || tp_inst._defaults.minDateTime === 0) { + tp_inst._defaults.minDate = new Date(); + } + if (tp_inst._defaults.maxDate === 0 || tp_inst._defaults.maxDateTime === 0) { + tp_inst._defaults.maxDate = new Date(); + } + + // datepicker needs minDate/maxDate, timepicker needs minDateTime/maxDateTime.. + if (tp_inst._defaults.minDate !== undefined && tp_inst._defaults.minDate instanceof Date) { + tp_inst._defaults.minDateTime = new Date(tp_inst._defaults.minDate.getTime()); + } + if (tp_inst._defaults.minDateTime !== undefined && tp_inst._defaults.minDateTime instanceof Date) { + tp_inst._defaults.minDate = new Date(tp_inst._defaults.minDateTime.getTime()); + } + if (tp_inst._defaults.maxDate !== undefined && tp_inst._defaults.maxDate instanceof Date) { + tp_inst._defaults.maxDateTime = new Date(tp_inst._defaults.maxDate.getTime()); + } + if (tp_inst._defaults.maxDateTime !== undefined && tp_inst._defaults.maxDateTime instanceof Date) { + tp_inst._defaults.maxDate = new Date(tp_inst._defaults.maxDateTime.getTime()); + } + tp_inst.$input.bind('focus', function() { + tp_inst._onFocus(); + }); + + return tp_inst; + }, + + /* + * add our sliders to the calendar + */ + _addTimePicker: function(dp_inst) { + var currDT = (this.$altInput && this._defaults.altFieldTimeOnly) ? this.$input.val() + ' ' + this.$altInput.val() : this.$input.val(); + + this.timeDefined = this._parseTime(currDT); + this._limitMinMaxDateTime(dp_inst, false); + this._injectTimePicker(); + }, + + /* + * parse the time string from input value or _setTime + */ + _parseTime: function(timeString, withDate) { + if (!this.inst) { + this.inst = $.datepicker._getInst(this.$input[0]); + } + + if (withDate || !this._defaults.timeOnly) { + var dp_dateFormat = $.datepicker._get(this.inst, 'dateFormat'); + try { + var parseRes = parseDateTimeInternal(dp_dateFormat, this._defaults.timeFormat, timeString, $.datepicker._getFormatConfig(this.inst), this._defaults); + if (!parseRes.timeObj) { + return false; + } + $.extend(this, parseRes.timeObj); + } catch (err) { + $.datepicker.log("Error parsing the date/time string: " + err + + "\ndate/time string = " + timeString + + "\ntimeFormat = " + this._defaults.timeFormat + + "\ndateFormat = " + dp_dateFormat); + return false; + } + return true; + } else { + var timeObj = $.datepicker.parseTime(this._defaults.timeFormat, timeString, this._defaults); + if (!timeObj) { + return false; + } + $.extend(this, timeObj); + return true; + } + }, + + /* + * generate and inject html for timepicker into ui datepicker + */ + _injectTimePicker: function() { + var $dp = this.inst.dpDiv, + o = this.inst.settings, + tp_inst = this, + litem = '', + uitem = '', + max = {}, + gridSize = {}, + size = null; + + // Prevent displaying twice + if ($dp.find("div.ui-timepicker-div").length === 0 && o.showTimepicker) { + var noDisplay = ' style="display:none;"', + html = '<div class="ui-timepicker-div'+ (o.isRTL? ' ui-timepicker-rtl' : '') +'"><dl>' + '<dt class="ui_tpicker_time_label"' + ((o.showTime) ? '' : noDisplay) + '>' + o.timeText + '</dt>' + + '<dd class="ui_tpicker_time"' + ((o.showTime) ? '' : noDisplay) + '></dd>'; + + // Create the markup + for(var i=0,l=this.units.length; i<l; i++){ + litem = this.units[i]; + uitem = litem.substr(0,1).toUpperCase() + litem.substr(1); + // Added by Peter Medeiros: + // - Figure out what the hour/minute/second max should be based on the step values. + // - Example: if stepMinute is 15, then minMax is 45. + max[litem] = parseInt((o[litem+'Max'] - ((o[litem+'Max'] - o[litem+'Min']) % o['step'+uitem])), 10); + gridSize[litem] = 0; + + html += '<dt class="ui_tpicker_'+ litem +'_label"' + ((o['show'+uitem]) ? '' : noDisplay) + '>' + o[litem +'Text'] + '</dt>' + + '<dd class="ui_tpicker_'+ litem +'"><div class="ui_tpicker_'+ litem +'_slider"' + ((o['show'+uitem]) ? '' : noDisplay) + '></div>'; + + if (o['show'+uitem] && o[litem+'Grid'] > 0) { + html += '<div style="padding-left: 1px"><table class="ui-tpicker-grid-label"><tr>'; + + if(litem == 'hour'){ + for (var h = o[litem+'Min']; h <= max[litem]; h += parseInt(o[litem+'Grid'], 10)) { + gridSize[litem]++; + var tmph = $.datepicker.formatTime(useAmpm(o.pickerTimeFormat || o.timeFormat)? 'hht':'HH', {hour:h}, o); + html += '<td data-for="'+litem+'">' + tmph + '</td>'; + } + } + else{ + for (var m = o[litem+'Min']; m <= max[litem]; m += parseInt(o[litem+'Grid'], 10)) { + gridSize[litem]++; + html += '<td data-for="'+litem+'">' + ((m < 10) ? '0' : '') + m + '</td>'; + } + } + + html += '</tr></table></div>'; + } + html += '</dd>'; + } + + // Timezone + html += '<dt class="ui_tpicker_timezone_label"' + ((o.showTimezone) ? '' : noDisplay) + '>' + o.timezoneText + '</dt>'; + html += '<dd class="ui_tpicker_timezone" ' + ((o.showTimezone) ? '' : noDisplay) + '></dd>'; + + // Create the elements from string + html += '</dl></div>'; + var $tp = $(html); + + // if we only want time picker... + if (o.timeOnly === true) { + $tp.prepend('<div class="ui-widget-header ui-helper-clearfix ui-corner-all">' + '<div class="ui-datepicker-title">' + o.timeOnlyTitle + '</div>' + '</div>'); + $dp.find('.ui-datepicker-header, .ui-datepicker-calendar').hide(); + } + + // add sliders, adjust grids, add events + for(var i=0,l=tp_inst.units.length; i<l; i++){ + litem = tp_inst.units[i]; + uitem = litem.substr(0,1).toUpperCase() + litem.substr(1); + + // add the slider + tp_inst[litem+'_slider'] = tp_inst.control.create(tp_inst, $tp.find('.ui_tpicker_'+litem+'_slider'), litem, tp_inst[litem], o[litem+'Min'], max[litem], o['step'+uitem]); + + // adjust the grid and add click event + if (o['show'+uitem] && o[litem+'Grid'] > 0) { + size = 100 * gridSize[litem] * o[litem+'Grid'] / (max[litem] - o[litem+'Min']); + $tp.find('.ui_tpicker_'+litem+' table').css({ + width: size + "%", + marginLeft: o.isRTL? '0' : ((size / (-2 * gridSize[litem])) + "%"), + marginRight: o.isRTL? ((size / (-2 * gridSize[litem])) + "%") : '0', + borderCollapse: 'collapse' + }).find("td").click(function(e){ + var $t = $(this), + h = $t.html(), + n = parseInt(h.replace(/[^0-9]/g),10), + ap = h.replace(/[^apm]/ig), + f = $t.data('for'); // loses scope, so we use data-for + + if(f == 'hour'){ + if(ap.indexOf('p') !== -1 && n < 12){ + n += 12; + } + else{ + if(ap.indexOf('a') !== -1 && n === 12){ + n = 0; + } + } + } + + tp_inst.control.value(tp_inst, tp_inst[f+'_slider'], litem, n); + + tp_inst._onTimeChange(); + tp_inst._onSelectHandler(); + }) + .css({ + cursor: 'pointer', + width: (100 / gridSize[litem]) + '%', + textAlign: 'center', + overflow: 'hidden' + }); + } // end if grid > 0 + } // end for loop + + // Add timezone options + this.timezone_select = $tp.find('.ui_tpicker_timezone').append('<select></select>').find("select"); + $.fn.append.apply(this.timezone_select, + $.map(o.timezoneList, function(val, idx) { + return $("<option />").val(typeof val == "object" ? val.value : val).text(typeof val == "object" ? val.label : val); + })); + if (typeof(this.timezone) != "undefined" && this.timezone !== null && this.timezone !== "") { + var local_date = new Date(this.inst.selectedYear, this.inst.selectedMonth, this.inst.selectedDay, 12); + var local_timezone = $.timepicker.timeZoneOffsetString(local_date); + if (local_timezone == this.timezone) { + selectLocalTimeZone(tp_inst); + } else { + this.timezone_select.val(this.timezone); + } + } else { + if (typeof(this.hour) != "undefined" && this.hour !== null && this.hour !== "") { + this.timezone_select.val(o.defaultTimezone); + } else { + selectLocalTimeZone(tp_inst); + } + } + this.timezone_select.change(function() { + tp_inst._defaults.useLocalTimezone = false; + tp_inst._onTimeChange(); + }); + // End timezone options + + // inject timepicker into datepicker + var $buttonPanel = $dp.find('.ui-datepicker-buttonpane'); + if ($buttonPanel.length) { + $buttonPanel.before($tp); + } else { + $dp.append($tp); + } + + this.$timeObj = $tp.find('.ui_tpicker_time'); + + if (this.inst !== null) { + var timeDefined = this.timeDefined; + this._onTimeChange(); + this.timeDefined = timeDefined; + } + + // slideAccess integration: http://trentrichardson.com/2011/11/11/jquery-ui-sliders-and-touch-accessibility/ + if (this._defaults.addSliderAccess) { + var sliderAccessArgs = this._defaults.sliderAccessArgs, + rtl = this._defaults.isRTL; + sliderAccessArgs.isRTL = rtl; + + setTimeout(function() { // fix for inline mode + if ($tp.find('.ui-slider-access').length === 0) { + $tp.find('.ui-slider:visible').sliderAccess(sliderAccessArgs); + + // fix any grids since sliders are shorter + var sliderAccessWidth = $tp.find('.ui-slider-access:eq(0)').outerWidth(true); + if (sliderAccessWidth) { + $tp.find('table:visible').each(function() { + var $g = $(this), + oldWidth = $g.outerWidth(), + oldMarginLeft = $g.css(rtl? 'marginRight':'marginLeft').toString().replace('%', ''), + newWidth = oldWidth - sliderAccessWidth, + newMarginLeft = ((oldMarginLeft * newWidth) / oldWidth) + '%', + css = { width: newWidth, marginRight: 0, marginLeft: 0 }; + css[rtl? 'marginRight':'marginLeft'] = newMarginLeft; + $g.css(css); + }); + } + } + }, 10); + } + // end slideAccess integration + + } + }, + + /* + * This function tries to limit the ability to go outside the + * min/max date range + */ + _limitMinMaxDateTime: function(dp_inst, adjustSliders) { + var o = this._defaults, + dp_date = new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay); + + if (!this._defaults.showTimepicker) { + return; + } // No time so nothing to check here + + if ($.datepicker._get(dp_inst, 'minDateTime') !== null && $.datepicker._get(dp_inst, 'minDateTime') !== undefined && dp_date) { + var minDateTime = $.datepicker._get(dp_inst, 'minDateTime'), + minDateTimeDate = new Date(minDateTime.getFullYear(), minDateTime.getMonth(), minDateTime.getDate(), 0, 0, 0, 0); + + if (this.hourMinOriginal === null || this.minuteMinOriginal === null || this.secondMinOriginal === null || this.millisecMinOriginal === null) { + this.hourMinOriginal = o.hourMin; + this.minuteMinOriginal = o.minuteMin; + this.secondMinOriginal = o.secondMin; + this.millisecMinOriginal = o.millisecMin; + } + + if (dp_inst.settings.timeOnly || minDateTimeDate.getTime() == dp_date.getTime()) { + this._defaults.hourMin = minDateTime.getHours(); + if (this.hour <= this._defaults.hourMin) { + this.hour = this._defaults.hourMin; + this._defaults.minuteMin = minDateTime.getMinutes(); + if (this.minute <= this._defaults.minuteMin) { + this.minute = this._defaults.minuteMin; + this._defaults.secondMin = minDateTime.getSeconds(); + if (this.second <= this._defaults.secondMin) { + this.second = this._defaults.secondMin; + this._defaults.millisecMin = minDateTime.getMilliseconds(); + } else { + if (this.millisec < this._defaults.millisecMin) { + this.millisec = this._defaults.millisecMin; + } + this._defaults.millisecMin = this.millisecMinOriginal; + } + } else { + this._defaults.secondMin = this.secondMinOriginal; + this._defaults.millisecMin = this.millisecMinOriginal; + } + } else { + this._defaults.minuteMin = this.minuteMinOriginal; + this._defaults.secondMin = this.secondMinOriginal; + this._defaults.millisecMin = this.millisecMinOriginal; + } + } else { + this._defaults.hourMin = this.hourMinOriginal; + this._defaults.minuteMin = this.minuteMinOriginal; + this._defaults.secondMin = this.secondMinOriginal; + this._defaults.millisecMin = this.millisecMinOriginal; + } + } + + if ($.datepicker._get(dp_inst, 'maxDateTime') !== null && $.datepicker._get(dp_inst, 'maxDateTime') !== undefined && dp_date) { + var maxDateTime = $.datepicker._get(dp_inst, 'maxDateTime'), + maxDateTimeDate = new Date(maxDateTime.getFullYear(), maxDateTime.getMonth(), maxDateTime.getDate(), 0, 0, 0, 0); + + if (this.hourMaxOriginal === null || this.minuteMaxOriginal === null || this.secondMaxOriginal === null) { + this.hourMaxOriginal = o.hourMax; + this.minuteMaxOriginal = o.minuteMax; + this.secondMaxOriginal = o.secondMax; + this.millisecMaxOriginal = o.millisecMax; + } + + if (dp_inst.settings.timeOnly || maxDateTimeDate.getTime() == dp_date.getTime()) { + this._defaults.hourMax = maxDateTime.getHours(); + if (this.hour >= this._defaults.hourMax) { + this.hour = this._defaults.hourMax; + this._defaults.minuteMax = maxDateTime.getMinutes(); + if (this.minute >= this._defaults.minuteMax) { + this.minute = this._defaults.minuteMax; + this._defaults.secondMax = maxDateTime.getSeconds(); + } else if (this.second >= this._defaults.secondMax) { + this.second = this._defaults.secondMax; + this._defaults.millisecMax = maxDateTime.getMilliseconds(); + } else { + if (this.millisec > this._defaults.millisecMax) { + this.millisec = this._defaults.millisecMax; + } + this._defaults.millisecMax = this.millisecMaxOriginal; + } + } else { + this._defaults.minuteMax = this.minuteMaxOriginal; + this._defaults.secondMax = this.secondMaxOriginal; + this._defaults.millisecMax = this.millisecMaxOriginal; + } + } else { + this._defaults.hourMax = this.hourMaxOriginal; + this._defaults.minuteMax = this.minuteMaxOriginal; + this._defaults.secondMax = this.secondMaxOriginal; + this._defaults.millisecMax = this.millisecMaxOriginal; + } + } + + if (adjustSliders !== undefined && adjustSliders === true) { + var hourMax = parseInt((this._defaults.hourMax - ((this._defaults.hourMax - this._defaults.hourMin) % this._defaults.stepHour)), 10), + minMax = parseInt((this._defaults.minuteMax - ((this._defaults.minuteMax - this._defaults.minuteMin) % this._defaults.stepMinute)), 10), + secMax = parseInt((this._defaults.secondMax - ((this._defaults.secondMax - this._defaults.secondMin) % this._defaults.stepSecond)), 10), + millisecMax = parseInt((this._defaults.millisecMax - ((this._defaults.millisecMax - this._defaults.millisecMin) % this._defaults.stepMillisec)), 10); + + if (this.hour_slider) { + this.control.options(this, this.hour_slider, 'hour', { min: this._defaults.hourMin, max: hourMax }); + this.control.value(this, this.hour_slider, 'hour', this.hour); + } + if (this.minute_slider) { + this.control.options(this, this.minute_slider, 'minute', { min: this._defaults.minuteMin, max: minMax }); + this.control.value(this, this.minute_slider, 'minute', this.minute); + } + if (this.second_slider) { + this.control.options(this, this.second_slider, 'second', { min: this._defaults.secondMin, max: secMax }); + this.control.value(this, this.second_slider, 'second', this.second); + } + if (this.millisec_slider) { + this.control.options(this, this.millisec_slider, 'millisec', { min: this._defaults.millisecMin, max: millisecMax }); + this.control.value(this, this.millisec_slider, 'millisec', this.millisec); + } + } + + }, + + /* + * when a slider moves, set the internal time... + * on time change is also called when the time is updated in the text field + */ + _onTimeChange: function() { + var hour = (this.hour_slider) ? this.control.value(this, this.hour_slider, 'hour') : false, + minute = (this.minute_slider) ? this.control.value(this, this.minute_slider, 'minute') : false, + second = (this.second_slider) ? this.control.value(this, this.second_slider, 'second') : false, + millisec = (this.millisec_slider) ? this.control.value(this, this.millisec_slider, 'millisec') : false, + timezone = (this.timezone_select) ? this.timezone_select.val() : false, + o = this._defaults, + pickerTimeFormat = o.pickerTimeFormat || o.timeFormat, + pickerTimeSuffix = o.pickerTimeSuffix || o.timeSuffix; + + if (typeof(hour) == 'object') { + hour = false; + } + if (typeof(minute) == 'object') { + minute = false; + } + if (typeof(second) == 'object') { + second = false; + } + if (typeof(millisec) == 'object') { + millisec = false; + } + if (typeof(timezone) == 'object') { + timezone = false; + } + + if (hour !== false) { + hour = parseInt(hour, 10); + } + if (minute !== false) { + minute = parseInt(minute, 10); + } + if (second !== false) { + second = parseInt(second, 10); + } + if (millisec !== false) { + millisec = parseInt(millisec, 10); + } + + var ampm = o[hour < 12 ? 'amNames' : 'pmNames'][0]; + + // If the update was done in the input field, the input field should not be updated. + // If the update was done using the sliders, update the input field. + var hasChanged = (hour != this.hour || minute != this.minute || second != this.second || millisec != this.millisec + || (this.ampm.length > 0 && (hour < 12) != ($.inArray(this.ampm.toUpperCase(), this.amNames) !== -1)) + || ((this.timezone === null && timezone != this.defaultTimezone) || (this.timezone !== null && timezone != this.timezone))); + + if (hasChanged) { + + if (hour !== false) { + this.hour = hour; + } + if (minute !== false) { + this.minute = minute; + } + if (second !== false) { + this.second = second; + } + if (millisec !== false) { + this.millisec = millisec; + } + if (timezone !== false) { + this.timezone = timezone; + } + + if (!this.inst) { + this.inst = $.datepicker._getInst(this.$input[0]); + } + + this._limitMinMaxDateTime(this.inst, true); + } + if (useAmpm(o.timeFormat)) { + this.ampm = ampm; + } + + // Updates the time within the timepicker + this.formattedTime = $.datepicker.formatTime(o.timeFormat, this, o); + if (this.$timeObj) { + if(pickerTimeFormat === o.timeFormat){ + this.$timeObj.text(this.formattedTime + pickerTimeSuffix); + } + else{ + this.$timeObj.text($.datepicker.formatTime(pickerTimeFormat, this, o) + pickerTimeSuffix); + } + } + + this.timeDefined = true; + if (hasChanged) { + this._updateDateTime(); + } + }, + + /* + * call custom onSelect. + * bind to sliders slidestop, and grid click. + */ + _onSelectHandler: function() { + var onSelect = this._defaults.onSelect || this.inst.settings.onSelect; + var inputEl = this.$input ? this.$input[0] : null; + if (onSelect && inputEl) { + onSelect.apply(inputEl, [this.formattedDateTime, this]); + } + }, + + /* + * update our input with the new date time.. + */ + _updateDateTime: function(dp_inst) { + dp_inst = this.inst || dp_inst; + var dt = $.datepicker._daylightSavingAdjust(new Date(dp_inst.selectedYear, dp_inst.selectedMonth, dp_inst.selectedDay)), + dateFmt = $.datepicker._get(dp_inst, 'dateFormat'), + formatCfg = $.datepicker._getFormatConfig(dp_inst), + timeAvailable = dt !== null && this.timeDefined; + this.formattedDate = $.datepicker.formatDate(dateFmt, (dt === null ? new Date() : dt), formatCfg); + var formattedDateTime = this.formattedDate; + + /* + * remove following lines to force every changes in date picker to change the input value + * Bug descriptions: when an input field has a default value, and click on the field to pop up the date picker. + * If the user manually empty the value in the input field, the date picker will never change selected value. + */ + //if (dp_inst.lastVal !== undefined && (dp_inst.lastVal.length > 0 && this.$input.val().length === 0)) { + // return; + //} + + if (this._defaults.timeOnly === true) { + formattedDateTime = this.formattedTime; + } else if (this._defaults.timeOnly !== true && (this._defaults.alwaysSetTime || timeAvailable)) { + formattedDateTime += this._defaults.separator + this.formattedTime + this._defaults.timeSuffix; + } + + this.formattedDateTime = formattedDateTime; + + if (!this._defaults.showTimepicker) { + this.$input.val(this.formattedDate); + } else if (this.$altInput && this._defaults.altFieldTimeOnly === true) { + this.$altInput.val(this.formattedTime); + this.$input.val(this.formattedDate); + } else if (this.$altInput) { + this.$input.val(formattedDateTime); + var altFormattedDateTime = '', + altSeparator = this._defaults.altSeparator ? this._defaults.altSeparator : this._defaults.separator, + altTimeSuffix = this._defaults.altTimeSuffix ? this._defaults.altTimeSuffix : this._defaults.timeSuffix; + + if (this._defaults.altFormat) altFormattedDateTime = $.datepicker.formatDate(this._defaults.altFormat, (dt === null ? new Date() : dt), formatCfg); + else altFormattedDateTime = this.formattedDate; + if (altFormattedDateTime) altFormattedDateTime += altSeparator; + if (this._defaults.altTimeFormat) altFormattedDateTime += $.datepicker.formatTime(this._defaults.altTimeFormat, this, this._defaults) + altTimeSuffix; + else altFormattedDateTime += this.formattedTime + altTimeSuffix; + this.$altInput.val(altFormattedDateTime); + } else { + this.$input.val(formattedDateTime); + } + + this.$input.trigger("change"); + }, + + _onFocus: function() { + if (!this.$input.val() && this._defaults.defaultValue) { + this.$input.val(this._defaults.defaultValue); + var inst = $.datepicker._getInst(this.$input.get(0)), + tp_inst = $.datepicker._get(inst, 'timepicker'); + if (tp_inst) { + if (tp_inst._defaults.timeOnly && (inst.input.val() != inst.lastVal)) { + try { + $.datepicker._updateDatepicker(inst); + } catch (err) { + $.datepicker.log(err); + } + } + } + } + }, + + /* + * Small abstraction to control types + * We can add more, just be sure to follow the pattern: create, options, value + */ + _controls: { + // slider methods + slider: { + create: function(tp_inst, obj, unit, val, min, max, step){ + var rtl = tp_inst._defaults.isRTL; // if rtl go -60->0 instead of 0->60 + return obj.prop('slide', null).slider({ + orientation: "horizontal", + value: rtl? val*-1 : val, + min: rtl? max*-1 : min, + max: rtl? min*-1 : max, + step: step, + slide: function(event, ui) { + tp_inst.control.value(tp_inst, $(this), unit, rtl? ui.value*-1:ui.value); + tp_inst._onTimeChange(); + }, + stop: function(event, ui) { + tp_inst._onSelectHandler(); + } + }); + }, + options: function(tp_inst, obj, unit, opts, val){ + if(tp_inst._defaults.isRTL){ + if(typeof(opts) == 'string'){ + if(opts == 'min' || opts == 'max'){ + if(val !== undefined) + return obj.slider(opts, val*-1); + return Math.abs(obj.slider(opts)); + } + return obj.slider(opts); + } + var min = opts.min, + max = opts.max; + opts.min = opts.max = null; + if(min !== undefined) + opts.max = min * -1; + if(max !== undefined) + opts.min = max * -1; + return obj.slider(opts); + } + if(typeof(opts) == 'string' && val !== undefined) + return obj.slider(opts, val); + return obj.slider(opts); + }, + value: function(tp_inst, obj, unit, val){ + if(tp_inst._defaults.isRTL){ + if(val !== undefined) + return obj.slider('value', val*-1); + return Math.abs(obj.slider('value')); + } + if(val !== undefined) + return obj.slider('value', val); + return obj.slider('value'); + } + }, + // select methods + select: { + create: function(tp_inst, obj, unit, val, min, max, step){ + var sel = '<select class="ui-timepicker-select" data-unit="'+ unit +'" data-min="'+ min +'" data-max="'+ max +'" data-step="'+ step +'">', + ul = tp_inst._defaults.timeFormat.indexOf('t') !== -1? 'toLowerCase':'toUpperCase', + m = 0; + + for(var i=min; i<=max; i+=step){ + sel += '<option value="'+ i +'"'+ (i==val? ' selected':'') +'>'; + if(unit == 'hour' && useAmpm(tp_inst._defaults.pickerTimeFormat || tp_inst._defaults.timeFormat)) + sel += $.datepicker.formatTime("hh TT", {hour:i}, tp_inst._defaults); + else if(unit == 'millisec' || i >= 10) sel += i; + else sel += '0'+ i.toString(); + sel += '</option>'; + } + sel += '</select>'; + + obj.children('select').remove(); + + $(sel).appendTo(obj).change(function(e){ + tp_inst._onTimeChange(); + tp_inst._onSelectHandler(); + }); + + return obj; + }, + options: function(tp_inst, obj, unit, opts, val){ + var o = {}, + $t = obj.children('select'); + if(typeof(opts) == 'string'){ + if(val === undefined) + return $t.data(opts); + o[opts] = val; + } + else o = opts; + return tp_inst.control.create(tp_inst, obj, $t.data('unit'), $t.val(), o.min || $t.data('min'), o.max || $t.data('max'), o.step || $t.data('step')); + }, + value: function(tp_inst, obj, unit, val){ + var $t = obj.children('select'); + if(val !== undefined) + return $t.val(val); + return $t.val(); + } + } + } // end _controls + + }); + + $.fn.extend({ + /* + * shorthand just to use timepicker.. + */ + timepicker: function(o) { + o = o || {}; + var tmp_args = Array.prototype.slice.call(arguments); + + if (typeof o == 'object') { + tmp_args[0] = $.extend(o, { + timeOnly: true + }); + } + + return $(this).each(function() { + $.fn.datetimepicker.apply($(this), tmp_args); + }); + }, + + /* + * extend timepicker to datepicker + */ + datetimepicker: function(o) { + o = o || {}; + var tmp_args = arguments; + + if (typeof(o) == 'string') { + if (o == 'getDate') { + return $.fn.datepicker.apply($(this[0]), tmp_args); + } else { + return this.each(function() { + var $t = $(this); + $t.datepicker.apply($t, tmp_args); + }); + } + } else { + return this.each(function() { + var $t = $(this); + $t.datepicker($.timepicker._newInst($t, o)._defaults); + }); + } + } + }); + + /* + * Public Utility to parse date and time + */ + $.datepicker.parseDateTime = function(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) { + var parseRes = parseDateTimeInternal(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings); + if (parseRes.timeObj) { + var t = parseRes.timeObj; + parseRes.date.setHours(t.hour, t.minute, t.second, t.millisec); + } + + return parseRes.date; + }; + + /* + * Public utility to parse time + */ + $.datepicker.parseTime = function(timeFormat, timeString, options) { + var o = extendRemove(extendRemove({}, $.timepicker._defaults), options || {}); + + // Strict parse requires the timeString to match the timeFormat exactly + var strictParse = function(f, s, o){ + + // pattern for standard and localized AM/PM markers + var getPatternAmpm = function(amNames, pmNames) { + var markers = []; + if (amNames) { + $.merge(markers, amNames); + } + if (pmNames) { + $.merge(markers, pmNames); + } + markers = $.map(markers, function(val) { + return val.replace(/[.*+?|()\[\]{}\\]/g, '\\$&'); + }); + return '(' + markers.join('|') + ')?'; + }; + + // figure out position of time elements.. cause js cant do named captures + var getFormatPositions = function(timeFormat) { + var finds = timeFormat.toLowerCase().match(/(h{1,2}|m{1,2}|s{1,2}|l{1}|t{1,2}|z|'.*?')/g), + orders = { + h: -1, + m: -1, + s: -1, + l: -1, + t: -1, + z: -1 + }; + + if (finds) { + for (var i = 0; i < finds.length; i++) { + if (orders[finds[i].toString().charAt(0)] == -1) { + orders[finds[i].toString().charAt(0)] = i + 1; + } + } + } + return orders; + }; + + var regstr = '^' + f.toString() + .replace(/([hH]{1,2}|mm?|ss?|[tT]{1,2}|[lz]|'.*?')/g, function (match) { + switch (match.charAt(0).toLowerCase()) { + case 'h': return '(\\d?\\d)'; + case 'm': return '(\\d?\\d)'; + case 's': return '(\\d?\\d)'; + case 'l': return '(\\d?\\d?\\d)'; + case 'z': return '(z|[-+]\\d\\d:?\\d\\d|\\S+)?'; + case 't': return getPatternAmpm(o.amNames, o.pmNames); + default: // literal escaped in quotes + return '(' + match.replace(/\'/g, "").replace(/(\.|\$|\^|\\|\/|\(|\)|\[|\]|\?|\+|\*)/g, function (m) { return "\\" + m; }) + ')?'; + } + }) + .replace(/\s/g, '\\s?') + + o.timeSuffix + '$', + order = getFormatPositions(f), + ampm = '', + treg; + + treg = s.match(new RegExp(regstr, 'i')); + + var resTime = { + hour: 0, + minute: 0, + second: 0, + millisec: 0 + }; + + if (treg) { + if (order.t !== -1) { + if (treg[order.t] === undefined || treg[order.t].length === 0) { + ampm = ''; + resTime.ampm = ''; + } else { + ampm = $.inArray(treg[order.t].toUpperCase(), o.amNames) !== -1 ? 'AM' : 'PM'; + resTime.ampm = o[ampm == 'AM' ? 'amNames' : 'pmNames'][0]; + } + } + + if (order.h !== -1) { + if (ampm == 'AM' && treg[order.h] == '12') { + resTime.hour = 0; // 12am = 0 hour + } else { + if (ampm == 'PM' && treg[order.h] != '12') { + resTime.hour = parseInt(treg[order.h], 10) + 12; // 12pm = 12 hour, any other pm = hour + 12 + } else { + resTime.hour = Number(treg[order.h]); + } + } + } + + if (order.m !== -1) { + resTime.minute = Number(treg[order.m]); + } + if (order.s !== -1) { + resTime.second = Number(treg[order.s]); + } + if (order.l !== -1) { + resTime.millisec = Number(treg[order.l]); + } + if (order.z !== -1 && treg[order.z] !== undefined) { + var tz = treg[order.z].toUpperCase(); + switch (tz.length) { + case 1: + // Z + tz = o.timezoneIso8601 ? 'Z' : '+0000'; + break; + case 5: + // +hhmm + if (o.timezoneIso8601) { + tz = tz.substring(1) == '0000' ? 'Z' : tz.substring(0, 3) + ':' + tz.substring(3); + } + break; + case 6: + // +hh:mm + if (!o.timezoneIso8601) { + tz = tz == 'Z' || tz.substring(1) == '00:00' ? '+0000' : tz.replace(/:/, ''); + } else { + if (tz.substring(1) == '00:00') { + tz = 'Z'; + } + } + break; + } + resTime.timezone = tz; + } + + + return resTime; + } + return false; + };// end strictParse + + // First try JS Date, if that fails, use strictParse + var looseParse = function(f,s,o){ + try{ + var d = new Date('2012-01-01 '+ s); + return { + hour: d.getHours(), + minutes: d.getMinutes(), + seconds: d.getSeconds(), + millisec: d.getMilliseconds(), + timezone: $.timepicker.timeZoneOffsetString(d) + }; + } + catch(err){ + try{ + return strictParse(f,s,o); + } + catch(err2){ + $.datepicker.log("Unable to parse \ntimeString: "+ s +"\ntimeFormat: "+ f); + } + } + return false; + }; // end looseParse + + if(typeof o.parse === "function"){ + return o.parse(timeFormat, timeString, o) + } + if(o.parse === 'loose'){ + return looseParse(timeFormat, timeString, o); + } + return strictParse(timeFormat, timeString, o); + }; + + /* + * Public utility to format the time + * format = string format of the time + * time = a {}, not a Date() for timezones + * options = essentially the regional[].. amNames, pmNames, ampm + */ + $.datepicker.formatTime = function(format, time, options) { + options = options || {}; + options = $.extend({}, $.timepicker._defaults, options); + time = $.extend({ + hour: 0, + minute: 0, + second: 0, + millisec: 0, + timezone: '+0000' + }, time); + + var tmptime = format, + ampmName = options.amNames[0], + hour = parseInt(time.hour, 10); + + if (hour > 11) { + ampmName = options.pmNames[0]; + } + + tmptime = tmptime.replace(/(?:HH?|hh?|mm?|ss?|[tT]{1,2}|[lz]|('.*?'|".*?"))/g, function(match) { + switch (match) { + case 'HH': + return ('0' + hour).slice(-2); + case 'H': + return hour; + case 'hh': + return ('0' + convert24to12(hour)).slice(-2); + case 'h': + return convert24to12(hour); + case 'mm': + return ('0' + time.minute).slice(-2); + case 'm': + return time.minute; + case 'ss': + return ('0' + time.second).slice(-2); + case 's': + return time.second; + case 'l': + return ('00' + time.millisec).slice(-3); + case 'z': + return time.timezone === null? options.defaultTimezone : time.timezone; + case 'T': + return ampmName.charAt(0).toUpperCase(); + case 'TT': + return ampmName.toUpperCase(); + case 't': + return ampmName.charAt(0).toLowerCase(); + case 'tt': + return ampmName.toLowerCase(); + default: + return match.replace(/\'/g, "") || "'"; + } + }); + + tmptime = $.trim(tmptime); + return tmptime; + }; + + /* + * the bad hack :/ override datepicker so it doesnt close on select + // inspired: http://stackoverflow.com/questions/1252512/jquery-datepicker-prevent-closing-picker-when-clicking-a-date/1762378#1762378 + */ + $.datepicker._base_selectDate = $.datepicker._selectDate; + $.datepicker._selectDate = function(id, dateStr) { + var inst = this._getInst($(id)[0]), + tp_inst = this._get(inst, 'timepicker'); + + if (tp_inst) { + tp_inst._limitMinMaxDateTime(inst, true); + inst.inline = inst.stay_open = true; + //This way the onSelect handler called from calendarpicker get the full dateTime + this._base_selectDate(id, dateStr); + inst.inline = inst.stay_open = false; + this._notifyChange(inst); + this._updateDatepicker(inst); + } else { + this._base_selectDate(id, dateStr); + } + }; + + /* + * second bad hack :/ override datepicker so it triggers an event when changing the input field + * and does not redraw the datepicker on every selectDate event + */ + $.datepicker._base_updateDatepicker = $.datepicker._updateDatepicker; + $.datepicker._updateDatepicker = function(inst) { + + // don't popup the datepicker if there is another instance already opened + var input = inst.input[0]; + if ($.datepicker._curInst && $.datepicker._curInst != inst && $.datepicker._datepickerShowing && $.datepicker._lastInput != input) { + return; + } + + if (typeof(inst.stay_open) !== 'boolean' || inst.stay_open === false) { + + this._base_updateDatepicker(inst); + + // Reload the time control when changing something in the input text field. + var tp_inst = this._get(inst, 'timepicker'); + if (tp_inst) { + tp_inst._addTimePicker(inst); + + if (tp_inst._defaults.useLocalTimezone) { //checks daylight saving with the new date. + var date = new Date(inst.selectedYear, inst.selectedMonth, inst.selectedDay, 12); + selectLocalTimeZone(tp_inst, date); + tp_inst._onTimeChange(); + } + } + } + }; + + /* + * third bad hack :/ override datepicker so it allows spaces and colon in the input field + */ + $.datepicker._base_doKeyPress = $.datepicker._doKeyPress; + $.datepicker._doKeyPress = function(event) { + var inst = $.datepicker._getInst(event.target), + tp_inst = $.datepicker._get(inst, 'timepicker'); + + if (tp_inst) { + if ($.datepicker._get(inst, 'constrainInput')) { + var ampm = useAmpm(tp_inst._defaults.timeFormat), + dateChars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')), + datetimeChars = tp_inst._defaults.timeFormat.toString() + .replace(/[hms]/g, '') + .replace(/TT/g, ampm ? 'APM' : '') + .replace(/Tt/g, ampm ? 'AaPpMm' : '') + .replace(/tT/g, ampm ? 'AaPpMm' : '') + .replace(/T/g, ampm ? 'AP' : '') + .replace(/tt/g, ampm ? 'apm' : '') + .replace(/t/g, ampm ? 'ap' : '') + + " " + tp_inst._defaults.separator + + tp_inst._defaults.timeSuffix + + (tp_inst._defaults.showTimezone ? tp_inst._defaults.timezoneList.join('') : '') + + (tp_inst._defaults.amNames.join('')) + (tp_inst._defaults.pmNames.join('')) + + dateChars, + chr = String.fromCharCode(event.charCode === undefined ? event.keyCode : event.charCode); + return event.ctrlKey || (chr < ' ' || !dateChars || datetimeChars.indexOf(chr) > -1); + } + } + + return $.datepicker._base_doKeyPress(event); + }; + + /* + * Fourth bad hack :/ override _updateAlternate function used in inline mode to init altField + */ + $.datepicker._base_updateAlternate = $.datepicker._updateAlternate; + /* Update any alternate field to synchronise with the main field. */ + $.datepicker._updateAlternate = function(inst) { + var tp_inst = this._get(inst, 'timepicker'); + if(tp_inst){ + var altField = tp_inst._defaults.altField; + if (altField) { // update alternate field too + var altFormat = tp_inst._defaults.altFormat || tp_inst._defaults.dateFormat, + date = this._getDate(inst), + formatCfg = $.datepicker._getFormatConfig(inst), + altFormattedDateTime = '', + altSeparator = tp_inst._defaults.altSeparator ? tp_inst._defaults.altSeparator : tp_inst._defaults.separator, + altTimeSuffix = tp_inst._defaults.altTimeSuffix ? tp_inst._defaults.altTimeSuffix : tp_inst._defaults.timeSuffix, + altTimeFormat = tp_inst._defaults.altTimeFormat !== null ? tp_inst._defaults.altTimeFormat : tp_inst._defaults.timeFormat; + + altFormattedDateTime += $.datepicker.formatTime(altTimeFormat, tp_inst, tp_inst._defaults) + altTimeSuffix; + if(!tp_inst._defaults.timeOnly && !tp_inst._defaults.altFieldTimeOnly){ + if(tp_inst._defaults.altFormat) + altFormattedDateTime = $.datepicker.formatDate(tp_inst._defaults.altFormat, (date === null ? new Date() : date), formatCfg) + altSeparator + altFormattedDateTime; + else altFormattedDateTime = tp_inst.formattedDate + altSeparator + altFormattedDateTime; + } + $(altField).val(altFormattedDateTime); + } + } + else{ + $.datepicker._base_updateAlternate(inst); + } + }; + + /* + * Override key up event to sync manual input changes. + */ + $.datepicker._base_doKeyUp = $.datepicker._doKeyUp; + $.datepicker._doKeyUp = function(event) { + var inst = $.datepicker._getInst(event.target), + tp_inst = $.datepicker._get(inst, 'timepicker'); + + if (tp_inst) { + if (tp_inst._defaults.timeOnly && (inst.input.val() != inst.lastVal)) { + try { + $.datepicker._updateDatepicker(inst); + } catch (err) { + $.datepicker.log(err); + } + } + } + + return $.datepicker._base_doKeyUp(event); + }; + + /* + * override "Today" button to also grab the time. + */ + $.datepicker._base_gotoToday = $.datepicker._gotoToday; + $.datepicker._gotoToday = function(id) { + var inst = this._getInst($(id)[0]), + $dp = inst.dpDiv; + this._base_gotoToday(id); + var tp_inst = this._get(inst, 'timepicker'); + selectLocalTimeZone(tp_inst); + var now = new Date(); + this._setTime(inst, now); + $('.ui-datepicker-today', $dp).click(); + }; + + /* + * Disable & enable the Time in the datetimepicker + */ + $.datepicker._disableTimepickerDatepicker = function(target) { + var inst = this._getInst(target); + if (!inst) { + return; + } + + var tp_inst = this._get(inst, 'timepicker'); + $(target).datepicker('getDate'); // Init selected[Year|Month|Day] + if (tp_inst) { + tp_inst._defaults.showTimepicker = false; + tp_inst._updateDateTime(inst); + } + }; + + $.datepicker._enableTimepickerDatepicker = function(target) { + var inst = this._getInst(target); + if (!inst) { + return; + } + + var tp_inst = this._get(inst, 'timepicker'); + $(target).datepicker('getDate'); // Init selected[Year|Month|Day] + if (tp_inst) { + tp_inst._defaults.showTimepicker = true; + tp_inst._addTimePicker(inst); // Could be disabled on page load + tp_inst._updateDateTime(inst); + } + }; + + /* + * Create our own set time function + */ + $.datepicker._setTime = function(inst, date) { + var tp_inst = this._get(inst, 'timepicker'); + if (tp_inst) { + var defaults = tp_inst._defaults; + + // calling _setTime with no date sets time to defaults + tp_inst.hour = date ? date.getHours() : defaults.hour; + tp_inst.minute = date ? date.getMinutes() : defaults.minute; + tp_inst.second = date ? date.getSeconds() : defaults.second; + tp_inst.millisec = date ? date.getMilliseconds() : defaults.millisec; + + //check if within min/max times.. + tp_inst._limitMinMaxDateTime(inst, true); + + tp_inst._onTimeChange(); + tp_inst._updateDateTime(inst); + } + }; + + /* + * Create new public method to set only time, callable as $().datepicker('setTime', date) + */ + $.datepicker._setTimeDatepicker = function(target, date, withDate) { + var inst = this._getInst(target); + if (!inst) { + return; + } + + var tp_inst = this._get(inst, 'timepicker'); + + if (tp_inst) { + this._setDateFromField(inst); + var tp_date; + if (date) { + if (typeof date == "string") { + tp_inst._parseTime(date, withDate); + tp_date = new Date(); + tp_date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec); + } else { + tp_date = new Date(date.getTime()); + } + if (tp_date.toString() == 'Invalid Date') { + tp_date = undefined; + } + this._setTime(inst, tp_date); + } + } + + }; + + /* + * override setDate() to allow setting time too within Date object + */ + $.datepicker._base_setDateDatepicker = $.datepicker._setDateDatepicker; + $.datepicker._setDateDatepicker = function(target, date) { + var inst = this._getInst(target); + if (!inst) { + return; + } + + var tp_date = (date instanceof Date) ? new Date(date.getTime()) : date; + + this._updateDatepicker(inst); + this._base_setDateDatepicker.apply(this, arguments); + this._setTimeDatepicker(target, tp_date, true); + }; + + /* + * override getDate() to allow getting time too within Date object + */ + $.datepicker._base_getDateDatepicker = $.datepicker._getDateDatepicker; + $.datepicker._getDateDatepicker = function(target, noDefault) { + var inst = this._getInst(target); + if (!inst) { + return; + } + + var tp_inst = this._get(inst, 'timepicker'); + + if (tp_inst) { + // if it hasn't yet been defined, grab from field + if(inst.lastVal === undefined){ + this._setDateFromField(inst, noDefault); + } + + var date = this._getDate(inst); + if (date && tp_inst._parseTime($(target).val(), tp_inst.timeOnly)) { + date.setHours(tp_inst.hour, tp_inst.minute, tp_inst.second, tp_inst.millisec); + } + return date; + } + return this._base_getDateDatepicker(target, noDefault); + }; + + /* + * override parseDate() because UI 1.8.14 throws an error about "Extra characters" + * An option in datapicker to ignore extra format characters would be nicer. + */ + $.datepicker._base_parseDate = $.datepicker.parseDate; + $.datepicker.parseDate = function(format, value, settings) { + var date; + try { + date = this._base_parseDate(format, value, settings); + } catch (err) { + // Hack! The error message ends with a colon, a space, and + // the "extra" characters. We rely on that instead of + // attempting to perfectly reproduce the parsing algorithm. + date = this._base_parseDate(format, value.substring(0,value.length-(err.length-err.indexOf(':')-2)), settings); + $.datepicker.log("Error parsing the date string: " + err + "\ndate string = " + value + "\ndate format = " + format); + } + return date; + }; + + /* + * override formatDate to set date with time to the input + */ + $.datepicker._base_formatDate = $.datepicker._formatDate; + $.datepicker._formatDate = function(inst, day, month, year) { + var tp_inst = this._get(inst, 'timepicker'); + if (tp_inst) { + tp_inst._updateDateTime(inst); + return tp_inst.$input.val(); + } + return this._base_formatDate(inst); + }; + + /* + * override options setter to add time to maxDate(Time) and minDate(Time). MaxDate + */ + $.datepicker._base_optionDatepicker = $.datepicker._optionDatepicker; + $.datepicker._optionDatepicker = function(target, name, value) { + var inst = this._getInst(target), + name_clone; + if (!inst) { + return null; + } + + var tp_inst = this._get(inst, 'timepicker'); + if (tp_inst) { + var min = null, + max = null, + onselect = null, + overrides = tp_inst._defaults.evnts, + fns = {}, + prop; + if (typeof name == 'string') { // if min/max was set with the string + if (name === 'minDate' || name === 'minDateTime') { + min = value; + } else if (name === 'maxDate' || name === 'maxDateTime') { + max = value; + } else if (name === 'onSelect') { + onselect = value; + } else if (overrides.hasOwnProperty(name)) { + if (typeof (value) === 'undefined') { + return overrides[name]; + } + fns[name] = value; + name_clone = {}; //empty results in exiting function after overrides updated + } + } else if (typeof name == 'object') { //if min/max was set with the JSON + if (name.minDate) { + min = name.minDate; + } else if (name.minDateTime) { + min = name.minDateTime; + } else if (name.maxDate) { + max = name.maxDate; + } else if (name.maxDateTime) { + max = name.maxDateTime; + } + for (prop in overrides) { + if (overrides.hasOwnProperty(prop) && name[prop]) { + fns[prop] = name[prop]; + } + } + } + for (prop in fns) { + if (fns.hasOwnProperty(prop)) { + overrides[prop] = fns[prop]; + if (!name_clone) { name_clone = $.extend({}, name);} + delete name_clone[prop]; + } + } + if (name_clone && isEmptyObject(name_clone)) { return; } + if (min) { //if min was set + if (min === 0) { + min = new Date(); + } else { + min = new Date(min); + } + tp_inst._defaults.minDate = min; + tp_inst._defaults.minDateTime = min; + } else if (max) { //if max was set + if (max === 0) { + max = new Date(); + } else { + max = new Date(max); + } + tp_inst._defaults.maxDate = max; + tp_inst._defaults.maxDateTime = max; + } else if (onselect) { + tp_inst._defaults.onSelect = onselect; + } + } + if (value === undefined) { + return this._base_optionDatepicker.call($.datepicker, target, name); + } + return this._base_optionDatepicker.call($.datepicker, target, name_clone || name, value); + }; + /* + * jQuery isEmptyObject does not check hasOwnProperty - if someone has added to the object prototype, + * it will return false for all objects + */ + var isEmptyObject = function(obj) { + var prop; + for (prop in obj) { + if (obj.hasOwnProperty(obj)) { + return false; + } + } + return true; + }; + + /* + * jQuery extend now ignores nulls! + */ + var extendRemove = function(target, props) { + $.extend(target, props); + for (var name in props) { + if (props[name] === null || props[name] === undefined) { + target[name] = props[name]; + } + } + return target; + }; + + /* + * Determine by the time format if should use ampm + * Returns true if should use ampm, false if not + */ + var useAmpm = function(timeFormat){ + return (timeFormat.indexOf('t') !== -1 && timeFormat.indexOf('h') !== -1); + }; + + /* + * Converts 24 hour format into 12 hour + * Returns 12 hour without leading 0 + */ + var convert24to12 = function(hour) { + if (hour > 12) { + hour = hour - 12; + } + + if (hour == 0) { + hour = 12; + } + + return String(hour); + }; + + /* + * Splits datetime string into date ans time substrings. + * Throws exception when date can't be parsed + * Returns [dateString, timeString] + */ + var splitDateTime = function(dateFormat, dateTimeString, dateSettings, timeSettings) { + try { + // The idea is to get the number separator occurances in datetime and the time format requested (since time has + // fewer unknowns, mostly numbers and am/pm). We will use the time pattern to split. + var separator = timeSettings && timeSettings.separator ? timeSettings.separator : $.timepicker._defaults.separator, + format = timeSettings && timeSettings.timeFormat ? timeSettings.timeFormat : $.timepicker._defaults.timeFormat, + timeParts = format.split(separator), // how many occurances of separator may be in our format? + timePartsLen = timeParts.length, + allParts = dateTimeString.split(separator), + allPartsLen = allParts.length; + + if (allPartsLen > 1) { + return [ + allParts.splice(0,allPartsLen-timePartsLen).join(separator), + allParts.splice(0,timePartsLen).join(separator) + ]; + } + + } catch (err) { + $.datepicker.log('Could not split the date from the time. Please check the following datetimepicker options' + + "\nthrown error: " + err + + "\ndateTimeString" + dateTimeString + + "\ndateFormat = " + dateFormat + + "\nseparator = " + timeSettings.separator + + "\ntimeFormat = " + timeSettings.timeFormat); + + if (err.indexOf(":") >= 0) { + // Hack! The error message ends with a colon, a space, and + // the "extra" characters. We rely on that instead of + // attempting to perfectly reproduce the parsing algorithm. + var dateStringLength = dateTimeString.length - (err.length - err.indexOf(':') - 2), + timeString = dateTimeString.substring(dateStringLength); + + return [$.trim(dateTimeString.substring(0, dateStringLength)), $.trim(dateTimeString.substring(dateStringLength))]; + + } else { + throw err; + } + } + return [dateTimeString, '']; + }; + + /* + * Internal function to parse datetime interval + * Returns: {date: Date, timeObj: Object}, where + * date - parsed date without time (type Date) + * timeObj = {hour: , minute: , second: , millisec: } - parsed time. Optional + */ + var parseDateTimeInternal = function(dateFormat, timeFormat, dateTimeString, dateSettings, timeSettings) { + var date; + var splitRes = splitDateTime(dateFormat, dateTimeString, dateSettings, timeSettings); + date = $.datepicker._base_parseDate(dateFormat, splitRes[0], dateSettings); + if (splitRes[1] !== '') { + var timeString = splitRes[1], + parsedTime = $.datepicker.parseTime(timeFormat, timeString, timeSettings); + + if (parsedTime === null) { + throw 'Wrong time format'; + } + return { + date: date, + timeObj: parsedTime + }; + } else { + return { + date: date + }; + } + }; + + /* + * Internal function to set timezone_select to the local timezone + */ + var selectLocalTimeZone = function(tp_inst, date) { + if (tp_inst && tp_inst.timezone_select) { + tp_inst._defaults.useLocalTimezone = true; + var now = typeof date !== 'undefined' ? date : new Date(); + var tzoffset = $.timepicker.timeZoneOffsetString(now); + if (tp_inst._defaults.timezoneIso8601) { + tzoffset = tzoffset.substring(0, 3) + ':' + tzoffset.substring(3); + } + tp_inst.timezone_select.val(tzoffset); + } + }; + + /* + * Create a Singleton Insance + */ + $.timepicker = new Timepicker(); + + /** + * Get the timezone offset as string from a date object (eg '+0530' for UTC+5.5) + * @param date + * @return string + */ + $.timepicker.timeZoneOffsetString = function(date) { + var off = date.getTimezoneOffset() * -1, + minutes = off % 60, + hours = (off - minutes) / 60; + return (off >= 0 ? '+' : '-') + ('0' + (hours * 101).toString()).substr(-2) + ('0' + (minutes * 101).toString()).substr(-2); + }; + + /** + * Calls `timepicker()` on the `startTime` and `endTime` elements, and configures them to + * enforce date range limits. + * n.b. The input value must be correctly formatted (reformatting is not supported) + * @param Element startTime + * @param Element endTime + * @param obj options Options for the timepicker() call + * @return jQuery + */ + $.timepicker.timeRange = function(startTime, endTime, options) { + return $.timepicker.handleRange('timepicker', startTime, endTime, options); + }; + + /** + * Calls `datetimepicker` on the `startTime` and `endTime` elements, and configures them to + * enforce date range limits. + * @param Element startTime + * @param Element endTime + * @param obj options Options for the `timepicker()` call. Also supports `reformat`, + * a boolean value that can be used to reformat the input values to the `dateFormat`. + * @param string method Can be used to specify the type of picker to be added + * @return jQuery + */ + $.timepicker.dateTimeRange = function(startTime, endTime, options) { + $.timepicker.dateRange(startTime, endTime, options, 'datetimepicker'); + }; + + /** + * Calls `method` on the `startTime` and `endTime` elements, and configures them to + * enforce date range limits. + * @param Element startTime + * @param Element endTime + * @param obj options Options for the `timepicker()` call. Also supports `reformat`, + * a boolean value that can be used to reformat the input values to the `dateFormat`. + * @param string method Can be used to specify the type of picker to be added + * @return jQuery + */ + $.timepicker.dateRange = function(startTime, endTime, options, method) { + method = method || 'datepicker'; + $.timepicker.handleRange(method, startTime, endTime, options); + }; + + /** + * Calls `method` on the `startTime` and `endTime` elements, and configures them to + * enforce date range limits. + * @param string method Can be used to specify the type of picker to be added + * @param Element startTime + * @param Element endTime + * @param obj options Options for the `timepicker()` call. Also supports `reformat`, + * a boolean value that can be used to reformat the input values to the `dateFormat`. + * @return jQuery + */ + $.timepicker.handleRange = function(method, startTime, endTime, options) { + $.fn[method].call(startTime, $.extend({ + onClose: function(dateText, inst) { + checkDates(this, endTime, dateText); + }, + onSelect: function(selectedDateTime) { + selected(this, endTime, 'minDate'); + } + }, options, options.start)); + $.fn[method].call(endTime, $.extend({ + onClose: function(dateText, inst) { + checkDates(this, startTime, dateText); + }, + onSelect: function(selectedDateTime) { + selected(this, startTime, 'maxDate'); + } + }, options, options.end)); + // timepicker doesn't provide access to its 'timeFormat' option, + // nor could I get datepicker.formatTime() to behave with times, so I + // have disabled reformatting for timepicker + if (method != 'timepicker' && options.reformat) { + $([startTime, endTime]).each(function() { + var format = $(this)[method].call($(this), 'option', 'dateFormat'), + date = new Date($(this).val()); + if ($(this).val() && date) { + $(this).val($.datepicker.formatDate(format, date)); + } + }); + } + checkDates(startTime, endTime, startTime.val()); + + function checkDates(changed, other, dateText) { + if (other.val() && (new Date(startTime.val()) > new Date(endTime.val()))) { + other.val(dateText); + } + } + selected(startTime, endTime, 'minDate'); + selected(endTime, startTime, 'maxDate'); + + function selected(changed, other, option) { + if (!$(changed).val()) { + return; + } + var date = $(changed)[method].call($(changed), 'getDate'); + // timepicker doesn't implement 'getDate' and returns a jQuery + if (date.getTime) { + $(other)[method].call($(other), 'option', option, date); + } + } + return $([startTime.get(0), endTime.get(0)]); + }; + + /* + * Keep up with the version + */ + $.timepicker.version = "1.1.1"; + +})(jQuery);
\ No newline at end of file diff --git a/hugo/js/jquery/jquery.ba-hashchange-1.3.js b/hugo/js/jquery/jquery.ba-hashchange-1.3.js new file mode 100644 index 0000000..47105f4 --- /dev/null +++ b/hugo/js/jquery/jquery.ba-hashchange-1.3.js @@ -0,0 +1,390 @@ +/*! + * jQuery hashchange event - v1.3 - 7/21/2010 + * http://benalman.com/projects/jquery-hashchange-plugin/ + * + * Copyright (c) 2010 "Cowboy" Ben Alman + * Dual licensed under the MIT and GPL licenses. + * http://benalman.com/about/license/ + */ + +// Script: jQuery hashchange event +// +// *Version: 1.3, Last updated: 7/21/2010* +// +// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/ +// GitHub - http://github.com/cowboy/jquery-hashchange/ +// Source - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js +// (Minified) - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (0.8kb gzipped) +// +// About: License +// +// Copyright (c) 2010 "Cowboy" Ben Alman, +// Dual licensed under the MIT and GPL licenses. +// http://benalman.com/about/license/ +// +// About: Examples +// +// These working examples, complete with fully commented code, illustrate a few +// ways in which this plugin can be used. +// +// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/ +// document.domain - http://benalman.com/code/projects/jquery-hashchange/examples/document_domain/ +// +// About: Support and Testing +// +// Information about what version or versions of jQuery this plugin has been +// tested with, what browsers it has been tested in, and where the unit tests +// reside (so you can test it yourself). +// +// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2 +// Browsers Tested - Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5, +// Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5. +// Unit Tests - http://benalman.com/code/projects/jquery-hashchange/unit/ +// +// About: Known issues +// +// While this jQuery hashchange event implementation is quite stable and +// robust, there are a few unfortunate browser bugs surrounding expected +// hashchange event-based behaviors, independent of any JavaScript +// window.onhashchange abstraction. See the following examples for more +// information: +// +// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/ +// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/ +// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/ +// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/ +// +// Also note that should a browser natively support the window.onhashchange +// event, but not report that it does, the fallback polling loop will be used. +// +// About: Release History +// +// 1.3 - (7/21/2010) Reorganized IE6/7 Iframe code to make it more +// "removable" for mobile-only development. Added IE6/7 document.title +// support. Attempted to make Iframe as hidden as possible by using +// techniques from http://www.paciellogroup.com/blog/?p=604. Added +// support for the "shortcut" format $(window).hashchange( fn ) and +// $(window).hashchange() like jQuery provides for built-in events. +// Renamed jQuery.hashchangeDelay to <jQuery.fn.hashchange.delay> and +// lowered its default value to 50. Added <jQuery.fn.hashchange.domain> +// and <jQuery.fn.hashchange.src> properties plus document-domain.html +// file to address access denied issues when setting document.domain in +// IE6/7. +// 1.2 - (2/11/2010) Fixed a bug where coming back to a page using this plugin +// from a page on another domain would cause an error in Safari 4. Also, +// IE6/7 Iframe is now inserted after the body (this actually works), +// which prevents the page from scrolling when the event is first bound. +// Event can also now be bound before DOM ready, but it won't be usable +// before then in IE6/7. +// 1.1 - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug +// where browser version is incorrectly reported as 8.0, despite +// inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag. +// 1.0 - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special +// window.onhashchange functionality into a separate plugin for users +// who want just the basic event & back button support, without all the +// extra awesomeness that BBQ provides. This plugin will be included as +// part of jQuery BBQ, but also be available separately. + +(function($,window,undefined){ + '$:nomunge'; // Used by YUI compressor. + + // Reused string. + var str_hashchange = 'hashchange', + + // Method / object references. + doc = document, + fake_onhashchange, + special = $.event.special, + + // Does the browser support window.onhashchange? Note that IE8 running in + // IE7 compatibility mode reports true for 'onhashchange' in window, even + // though the event isn't supported, so also test document.documentMode. + doc_mode = doc.documentMode, + supports_onhashchange = 'on' + str_hashchange in window && ( doc_mode === undefined || doc_mode > 7 ); + + // Get location.hash (or what you'd expect location.hash to be) sans any + // leading #. Thanks for making this necessary, Firefox! + function get_fragment( url ) { + url = url || location.href; + return '#' + url.replace( /^[^#]*#?(.*)$/, '$1' ); + }; + + // Method: jQuery.fn.hashchange + // + // Bind a handler to the window.onhashchange event or trigger all bound + // window.onhashchange event handlers. This behavior is consistent with + // jQuery's built-in event handlers. + // + // Usage: + // + // > jQuery(window).hashchange( [ handler ] ); + // + // Arguments: + // + // handler - (Function) Optional handler to be bound to the hashchange + // event. This is a "shortcut" for the more verbose form: + // jQuery(window).bind( 'hashchange', handler ). If handler is omitted, + // all bound window.onhashchange event handlers will be triggered. This + // is a shortcut for the more verbose + // jQuery(window).trigger( 'hashchange' ). These forms are described in + // the <hashchange event> section. + // + // Returns: + // + // (jQuery) The initial jQuery collection of elements. + + // Allow the "shortcut" format $(elem).hashchange( fn ) for binding and + // $(elem).hashchange() for triggering, like jQuery does for built-in events. + $.fn[ str_hashchange ] = function( fn ) { + return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange ); + }; + + // Property: jQuery.fn.hashchange.delay + // + // The numeric interval (in milliseconds) at which the <hashchange event> + // polling loop executes. Defaults to 50. + + // Property: jQuery.fn.hashchange.domain + // + // If you're setting document.domain in your JavaScript, and you want hash + // history to work in IE6/7, not only must this property be set, but you must + // also set document.domain BEFORE jQuery is loaded into the page. This + // property is only applicable if you are supporting IE6/7 (or IE8 operating + // in "IE7 compatibility" mode). + // + // In addition, the <jQuery.fn.hashchange.src> property must be set to the + // path of the included "document-domain.html" file, which can be renamed or + // modified if necessary (note that the document.domain specified must be the + // same in both your main JavaScript as well as in this file). + // + // Usage: + // + // jQuery.fn.hashchange.domain = document.domain; + + // Property: jQuery.fn.hashchange.src + // + // If, for some reason, you need to specify an Iframe src file (for example, + // when setting document.domain as in <jQuery.fn.hashchange.domain>), you can + // do so using this property. Note that when using this property, history + // won't be recorded in IE6/7 until the Iframe src file loads. This property + // is only applicable if you are supporting IE6/7 (or IE8 operating in "IE7 + // compatibility" mode). + // + // Usage: + // + // jQuery.fn.hashchange.src = 'path/to/file.html'; + + $.fn[ str_hashchange ].delay = 50; + /* + $.fn[ str_hashchange ].domain = null; + $.fn[ str_hashchange ].src = null; + */ + + // Event: hashchange event + // + // Fired when location.hash changes. In browsers that support it, the native + // HTML5 window.onhashchange event is used, otherwise a polling loop is + // initialized, running every <jQuery.fn.hashchange.delay> milliseconds to + // see if the hash has changed. In IE6/7 (and IE8 operating in "IE7 + // compatibility" mode), a hidden Iframe is created to allow the back button + // and hash-based history to work. + // + // Usage as described in <jQuery.fn.hashchange>: + // + // > // Bind an event handler. + // > jQuery(window).hashchange( function(e) { + // > var hash = location.hash; + // > ... + // > }); + // > + // > // Manually trigger the event handler. + // > jQuery(window).hashchange(); + // + // A more verbose usage that allows for event namespacing: + // + // > // Bind an event handler. + // > jQuery(window).bind( 'hashchange', function(e) { + // > var hash = location.hash; + // > ... + // > }); + // > + // > // Manually trigger the event handler. + // > jQuery(window).trigger( 'hashchange' ); + // + // Additional Notes: + // + // * The polling loop and Iframe are not created until at least one handler + // is actually bound to the 'hashchange' event. + // * If you need the bound handler(s) to execute immediately, in cases where + // a location.hash exists on page load, via bookmark or page refresh for + // example, use jQuery(window).hashchange() or the more verbose + // jQuery(window).trigger( 'hashchange' ). + // * The event can be bound before DOM ready, but since it won't be usable + // before then in IE6/7 (due to the necessary Iframe), recommended usage is + // to bind it inside a DOM ready handler. + + // Override existing $.event.special.hashchange methods (allowing this plugin + // to be defined after jQuery BBQ in BBQ's source code). + special[ str_hashchange ] = $.extend( special[ str_hashchange ], { + + // Called only when the first 'hashchange' event is bound to window. + setup: function() { + // If window.onhashchange is supported natively, there's nothing to do.. + if ( supports_onhashchange ) { return false; } + + // Otherwise, we need to create our own. And we don't want to call this + // until the user binds to the event, just in case they never do, since it + // will create a polling loop and possibly even a hidden Iframe. + $( fake_onhashchange.start ); + }, + + // Called only when the last 'hashchange' event is unbound from window. + teardown: function() { + // If window.onhashchange is supported natively, there's nothing to do.. + if ( supports_onhashchange ) { return false; } + + // Otherwise, we need to stop ours (if possible). + $( fake_onhashchange.stop ); + } + + }); + + // fake_onhashchange does all the work of triggering the window.onhashchange + // event for browsers that don't natively support it, including creating a + // polling loop to watch for hash changes and in IE 6/7 creating a hidden + // Iframe to enable back and forward. + fake_onhashchange = (function(){ + var self = {}, + timeout_id, + + // Remember the initial hash so it doesn't get triggered immediately. + last_hash = get_fragment(), + + fn_retval = function(val){ return val; }, + history_set = fn_retval, + history_get = fn_retval; + + // Start the polling loop. + self.start = function() { + timeout_id || poll(); + }; + + // Stop the polling loop. + self.stop = function() { + timeout_id && clearTimeout( timeout_id ); + timeout_id = undefined; + }; + + // This polling loop checks every $.fn.hashchange.delay milliseconds to see + // if location.hash has changed, and triggers the 'hashchange' event on + // window when necessary. + function poll() { + var hash = get_fragment(), + history_hash = history_get( last_hash ); + + if ( hash !== last_hash ) { + history_set( last_hash = hash, history_hash ); + + $(window).trigger( str_hashchange ); + + } else if ( history_hash !== last_hash ) { + location.href = location.href.replace( /#.*/, '' ) + history_hash; + } + + timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay ); + }; + + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + // vvvvvvvvvvvvvvvvvvv REMOVE IF NOT SUPPORTING IE6/7/8 vvvvvvvvvvvvvvvvvvv + // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + $.browser.msie && !supports_onhashchange && (function(){ + // Not only do IE6/7 need the "magical" Iframe treatment, but so does IE8 + // when running in "IE7 compatibility" mode. + + var iframe, + iframe_src; + + // When the event is bound and polling starts in IE 6/7, create a hidden + // Iframe for history handling. + self.start = function(){ + if ( !iframe ) { + iframe_src = $.fn[ str_hashchange ].src; + iframe_src = iframe_src && iframe_src + get_fragment(); + + // Create hidden Iframe. Attempt to make Iframe as hidden as possible + // by using techniques from http://www.paciellogroup.com/blog/?p=604. + iframe = $('<iframe tabindex="-1" title="empty"/>').hide() + + // When Iframe has completely loaded, initialize the history and + // start polling. + .one( 'load', function(){ + iframe_src || history_set( get_fragment() ); + poll(); + }) + + // Load Iframe src if specified, otherwise nothing. + .attr( 'src', iframe_src || 'javascript:0' ) + + // Append Iframe after the end of the body to prevent unnecessary + // initial page scrolling (yes, this works). + .insertAfter( 'body' )[0].contentWindow; + + // Whenever `document.title` changes, update the Iframe's title to + // prettify the back/next history menu entries. Since IE sometimes + // errors with "Unspecified error" the very first time this is set + // (yes, very useful) wrap this with a try/catch block. + doc.onpropertychange = function(){ + try { + if ( event.propertyName === 'title' ) { + iframe.document.title = doc.title; + } + } catch(e) {} + }; + + } + }; + + // Override the "stop" method since an IE6/7 Iframe was created. Even + // if there are no longer any bound event handlers, the polling loop + // is still necessary for back/next to work at all! + self.stop = fn_retval; + + // Get history by looking at the hidden Iframe's location.hash. + history_get = function() { + return get_fragment( iframe.location.href ); + }; + + // Set a new history item by opening and then closing the Iframe + // document, *then* setting its location.hash. If document.domain has + // been set, update that as well. + history_set = function( hash, history_hash ) { + var iframe_doc = iframe.document, + domain = $.fn[ str_hashchange ].domain; + + if ( hash !== history_hash ) { + // Update Iframe with any initial `document.title` that might be set. + iframe_doc.title = doc.title; + + // Opening the Iframe's document after it has been closed is what + // actually adds a history entry. + iframe_doc.open(); + + // Set document.domain for the Iframe document as well, if necessary. + domain && iframe_doc.write( '<script>document.domain="' + domain + '"</script>' ); + + iframe_doc.close(); + + // Update the Iframe's hash, for great justice. + iframe.location.hash = hash; + } + }; + + })(); + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + // ^^^^^^^^^^^^^^^^^^^ REMOVE IF NOT SUPPORTING IE6/7/8 ^^^^^^^^^^^^^^^^^^^ + // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + + return self; + })(); + +})(jQuery,this); diff --git a/hugo/js/jquery/jquery.cookie.js b/hugo/js/jquery/jquery.cookie.js new file mode 100644 index 0000000..61d3bce --- /dev/null +++ b/hugo/js/jquery/jquery.cookie.js @@ -0,0 +1,91 @@ +/*jslint browser: true */ /*global jQuery: true */ + +/** + * jQuery Cookie plugin + * + * Copyright (c) 2010 Klaus Hartl (stilbuero.de) + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + */ + +// TODO JsDoc + +/** + * Create a cookie with the given key and value and other optional parameters. + * + * @example $.cookie('the_cookie', 'the_value'); + * @desc Set the value of a cookie. + * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true }); + * @desc Create a cookie with all available options. + * @example $.cookie('the_cookie', 'the_value'); + * @desc Create a session cookie. + * @example $.cookie('the_cookie', null); + * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain + * used when the cookie was set. + * + * @param String key The key of the cookie. + * @param String value The value of the cookie. + * @param Object options An object literal containing key/value pairs to provide optional cookie attributes. + * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object. + * If a negative value is specified (e.g. a date in the past), the cookie will be deleted. + * If set to null or omitted, the cookie will be a session cookie and will not be retained + * when the the browser exits. + * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie). + * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie). + * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will + * require a secure protocol (like HTTPS). + * @type undefined + * + * @name $.cookie + * @cat Plugins/Cookie + * @author Klaus Hartl/klaus.hartl@stilbuero.de + */ + +/** + * Get the value of a cookie with the given key. + * + * @example $.cookie('the_cookie'); + * @desc Get the value of a cookie. + * + * @param String key The key of the cookie. + * @return The value of the cookie. + * @type String + * + * @name $.cookie + * @cat Plugins/Cookie + * @author Klaus Hartl/klaus.hartl@stilbuero.de + */ +jQuery.cookie = function (key, value, options) { + + // key and at least value given, set cookie... + if (arguments.length > 1 && String(value) !== "[object Object]") { + options = jQuery.extend({}, options); + + if (value === null || value === undefined) { + options.expires = -1; + } + + if (typeof options.expires === 'number') { + var days = options.expires, t = options.expires = new Date(); + t.setDate(t.getDate() + days); + } + + value = String(value); + + return (document.cookie = [ + encodeURIComponent(key), '=', + options.raw ? value : encodeURIComponent(value), + options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE + options.path ? '; path=' + options.path : '', + options.domain ? '; domain=' + options.domain : '', + options.secure ? '; secure' : '' + ].join('')); + } + + // key and possibly options given, get cookie... + options = value || {}; + var result, decode = options.raw ? function (s) { return s; } : decodeURIComponent; + return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null; +}; diff --git a/hugo/js/jquery/jquery.debounce-1.0.5.js b/hugo/js/jquery/jquery.debounce-1.0.5.js new file mode 100644 index 0000000..020128c --- /dev/null +++ b/hugo/js/jquery/jquery.debounce-1.0.5.js @@ -0,0 +1,71 @@ +/** + * Debounce and throttle function's decorator plugin 1.0.5 + * + * Copyright (c) 2009 Filatov Dmitry (alpha@zforms.ru) + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + */ + +(function($) { + +$.extend({ + + debounce : function(fn, timeout, invokeAsap, ctx) { + + if(arguments.length == 3 && typeof invokeAsap != 'boolean') { + ctx = invokeAsap; + invokeAsap = false; + } + + var timer; + + return function() { + + var args = arguments; + ctx = ctx || this; + + invokeAsap && !timer && fn.apply(ctx, args); + + clearTimeout(timer); + + timer = setTimeout(function() { + !invokeAsap && fn.apply(ctx, args); + timer = null; + }, timeout); + + }; + + }, + + throttle : function(fn, timeout, ctx) { + + var timer, args, needInvoke; + + return function() { + + args = arguments; + needInvoke = true; + ctx = ctx || this; + + if(!timer) { + (function() { + if(needInvoke) { + fn.apply(ctx, args); + needInvoke = false; + timer = setTimeout(arguments.callee, timeout); + } + else { + timer = null; + } + })(); + } + + }; + + } + +}); + +})(jQuery);
\ No newline at end of file diff --git a/hugo/js/jquery/jquery.event.drag-2.2.js b/hugo/js/jquery/jquery.event.drag-2.2.js new file mode 100644 index 0000000..1cda0e2 --- /dev/null +++ b/hugo/js/jquery/jquery.event.drag-2.2.js @@ -0,0 +1,402 @@ +/*! + * jquery.event.drag - v 2.2 + * Copyright (c) 2010 Three Dub Media - http://threedubmedia.com + * Open Source MIT License - http://threedubmedia.com/code/license + */ +// Created: 2008-06-04 +// Updated: 2012-05-21 +// REQUIRES: jquery 1.7.x + +;(function( $ ){ + +// add the jquery instance method +$.fn.drag = function( str, arg, opts ){ + // figure out the event type + var type = typeof str == "string" ? str : "", + // figure out the event handler... + fn = $.isFunction( str ) ? str : $.isFunction( arg ) ? arg : null; + // fix the event type + if ( type.indexOf("drag") !== 0 ) + type = "drag"+ type; + // were options passed + opts = ( str == fn ? arg : opts ) || {}; + // trigger or bind event handler + return fn ? this.bind( type, opts, fn ) : this.trigger( type ); +}; + +// local refs (increase compression) +var $event = $.event, +$special = $event.special, +// configure the drag special event +drag = $special.drag = { + + // these are the default settings + defaults: { + which: 1, // mouse button pressed to start drag sequence + distance: 0, // distance dragged before dragstart + not: ':input', // selector to suppress dragging on target elements + handle: null, // selector to match handle target elements + relative: false, // true to use "position", false to use "offset" + drop: true, // false to suppress drop events, true or selector to allow + click: false // false to suppress click events after dragend (no proxy) + }, + + // the key name for stored drag data + datakey: "dragdata", + + // prevent bubbling for better performance + noBubble: true, + + // count bound related events + add: function( obj ){ + // read the interaction data + var data = $.data( this, drag.datakey ), + // read any passed options + opts = obj.data || {}; + // count another realted event + data.related += 1; + // extend data options bound with this event + // don't iterate "opts" in case it is a node + $.each( drag.defaults, function( key, def ){ + if ( opts[ key ] !== undefined ) + data[ key ] = opts[ key ]; + }); + }, + + // forget unbound related events + remove: function(){ + $.data( this, drag.datakey ).related -= 1; + }, + + // configure interaction, capture settings + setup: function(){ + // check for related events + if ( $.data( this, drag.datakey ) ) + return; + // initialize the drag data with copied defaults + var data = $.extend({ related:0 }, drag.defaults ); + // store the interaction data + $.data( this, drag.datakey, data ); + // bind the mousedown event, which starts drag interactions + $event.add( this, "touchstart mousedown", drag.init, data ); + // prevent image dragging in IE... + if ( this.attachEvent ) + this.attachEvent("ondragstart", drag.dontstart ); + }, + + // destroy configured interaction + teardown: function(){ + var data = $.data( this, drag.datakey ) || {}; + // check for related events + if ( data.related ) + return; + // remove the stored data + $.removeData( this, drag.datakey ); + // remove the mousedown event + $event.remove( this, "touchstart mousedown", drag.init ); + // enable text selection + drag.textselect( true ); + // un-prevent image dragging in IE... + if ( this.detachEvent ) + this.detachEvent("ondragstart", drag.dontstart ); + }, + + // initialize the interaction + init: function( event ){ + // sorry, only one touch at a time + if ( drag.touched ) + return; + // the drag/drop interaction data + var dd = event.data, results; + // check the which directive + if ( event.which != 0 && dd.which > 0 && event.which != dd.which ) + return; + // check for suppressed selector + if ( $( event.target ).is( dd.not ) ) + return; + // check for handle selector + if ( dd.handle && !$( event.target ).closest( dd.handle, event.currentTarget ).length ) + return; + + drag.touched = event.type == 'touchstart' ? this : null; + dd.propagates = 1; + dd.mousedown = this; + dd.interactions = [ drag.interaction( this, dd ) ]; + dd.target = event.target; + dd.pageX = event.pageX; + dd.pageY = event.pageY; + dd.dragging = null; + // handle draginit event... + results = drag.hijack( event, "draginit", dd ); + // early cancel + if ( !dd.propagates ) + return; + // flatten the result set + results = drag.flatten( results ); + // insert new interaction elements + if ( results && results.length ){ + dd.interactions = []; + $.each( results, function(){ + dd.interactions.push( drag.interaction( this, dd ) ); + }); + } + // remember how many interactions are propagating + dd.propagates = dd.interactions.length; + // locate and init the drop targets + if ( dd.drop !== false && $special.drop ) + $special.drop.handler( event, dd ); + // disable text selection + drag.textselect( false ); + // bind additional events... + if ( drag.touched ) + $event.add( drag.touched, "touchmove touchend", drag.handler, dd ); + else + $event.add( document, "mousemove mouseup", drag.handler, dd ); + // helps prevent text selection or scrolling + if ( !drag.touched || dd.live ) + return false; + }, + + // returns an interaction object + interaction: function( elem, dd ){ + var offset = $( elem )[ dd.relative ? "position" : "offset" ]() || { top:0, left:0 }; + return { + drag: elem, + callback: new drag.callback(), + droppable: [], + offset: offset + }; + }, + + // handle drag-releatd DOM events + handler: function( event ){ + // read the data before hijacking anything + var dd = event.data; + // handle various events + switch ( event.type ){ + // mousemove, check distance, start dragging + case !dd.dragging && 'touchmove': + event.preventDefault(); + case !dd.dragging && 'mousemove': + // drag tolerance, x² + y² = distance² + if ( Math.pow( event.pageX-dd.pageX, 2 ) + Math.pow( event.pageY-dd.pageY, 2 ) < Math.pow( dd.distance, 2 ) ) + break; // distance tolerance not reached + event.target = dd.target; // force target from "mousedown" event (fix distance issue) + drag.hijack( event, "dragstart", dd ); // trigger "dragstart" + if ( dd.propagates ) // "dragstart" not rejected + dd.dragging = true; // activate interaction + // mousemove, dragging + case 'touchmove': + event.preventDefault(); + case 'mousemove': + if ( dd.dragging ){ + // trigger "drag" + drag.hijack( event, "drag", dd ); + if ( dd.propagates ){ + // manage drop events + if ( dd.drop !== false && $special.drop ) + $special.drop.handler( event, dd ); // "dropstart", "dropend" + break; // "drag" not rejected, stop + } + event.type = "mouseup"; // helps "drop" handler behave + } + // mouseup, stop dragging + case 'touchend': + case 'mouseup': + default: + if ( drag.touched ) + $event.remove( drag.touched, "touchmove touchend", drag.handler ); // remove touch events + else + $event.remove( document, "mousemove mouseup", drag.handler ); // remove page events + if ( dd.dragging ){ + if ( dd.drop !== false && $special.drop ) + $special.drop.handler( event, dd ); // "drop" + drag.hijack( event, "dragend", dd ); // trigger "dragend" + } + drag.textselect( true ); // enable text selection + // if suppressing click events... + if ( dd.click === false && dd.dragging ) + $.data( dd.mousedown, "suppress.click", new Date().getTime() + 5 ); + dd.dragging = drag.touched = false; // deactivate element + break; + } + }, + + // re-use event object for custom events + hijack: function( event, type, dd, x, elem ){ + // not configured + if ( !dd ) + return; + // remember the original event and type + var orig = { event:event.originalEvent, type:event.type }, + // is the event drag related or drog related? + mode = type.indexOf("drop") ? "drag" : "drop", + // iteration vars + result, i = x || 0, ia, $elems, callback, + len = !isNaN( x ) ? x : dd.interactions.length; + // modify the event type + event.type = type; + // remove the original event + event.originalEvent = null; + // initialize the results + dd.results = []; + // handle each interacted element + do if ( ia = dd.interactions[ i ] ){ + // validate the interaction + if ( type !== "dragend" && ia.cancelled ) + continue; + // set the dragdrop properties on the event object + callback = drag.properties( event, dd, ia ); + // prepare for more results + ia.results = []; + // handle each element + $( elem || ia[ mode ] || dd.droppable ).each(function( p, subject ){ + // identify drag or drop targets individually + callback.target = subject; + // force propagtion of the custom event + event.isPropagationStopped = function(){ return false; }; + // handle the event + result = subject ? $event.dispatch.call( subject, event, callback ) : null; + // stop the drag interaction for this element + if ( result === false ){ + if ( mode == "drag" ){ + ia.cancelled = true; + dd.propagates -= 1; + } + if ( type == "drop" ){ + ia[ mode ][p] = null; + } + } + // assign any dropinit elements + else if ( type == "dropinit" ) + ia.droppable.push( drag.element( result ) || subject ); + // accept a returned proxy element + if ( type == "dragstart" ) + ia.proxy = $( drag.element( result ) || ia.drag )[0]; + // remember this result + ia.results.push( result ); + // forget the event result, for recycling + delete event.result; + // break on cancelled handler + if ( type !== "dropinit" ) + return result; + }); + // flatten the results + dd.results[ i ] = drag.flatten( ia.results ); + // accept a set of valid drop targets + if ( type == "dropinit" ) + ia.droppable = drag.flatten( ia.droppable ); + // locate drop targets + if ( type == "dragstart" && !ia.cancelled ) + callback.update(); + } + while ( ++i < len ) + // restore the original event & type + event.type = orig.type; + event.originalEvent = orig.event; + // return all handler results + return drag.flatten( dd.results ); + }, + + // extend the callback object with drag/drop properties... + properties: function( event, dd, ia ){ + var obj = ia.callback; + // elements + obj.drag = ia.drag; + obj.proxy = ia.proxy || ia.drag; + // starting mouse position + obj.startX = dd.pageX; + obj.startY = dd.pageY; + // current distance dragged + obj.deltaX = event.pageX - dd.pageX; + obj.deltaY = event.pageY - dd.pageY; + // original element position + obj.originalX = ia.offset.left; + obj.originalY = ia.offset.top; + // adjusted element position + obj.offsetX = obj.originalX + obj.deltaX; + obj.offsetY = obj.originalY + obj.deltaY; + // assign the drop targets information + obj.drop = drag.flatten( ( ia.drop || [] ).slice() ); + obj.available = drag.flatten( ( ia.droppable || [] ).slice() ); + return obj; + }, + + // determine is the argument is an element or jquery instance + element: function( arg ){ + if ( arg && ( arg.jquery || arg.nodeType == 1 ) ) + return arg; + }, + + // flatten nested jquery objects and arrays into a single dimension array + flatten: function( arr ){ + return $.map( arr, function( member ){ + return member && member.jquery ? $.makeArray( member ) : + member && member.length ? drag.flatten( member ) : member; + }); + }, + + // toggles text selection attributes ON (true) or OFF (false) + textselect: function( bool ){ + $( document )[ bool ? "unbind" : "bind" ]("selectstart", drag.dontstart ) + .css("MozUserSelect", bool ? "" : "none" ); + // .attr("unselectable", bool ? "off" : "on" ) + document.unselectable = bool ? "off" : "on"; + }, + + // suppress "selectstart" and "ondragstart" events + dontstart: function(){ + return false; + }, + + // a callback instance contructor + callback: function(){} + +}; + +// callback methods +drag.callback.prototype = { + update: function(){ + if ( $special.drop && this.available.length ) + $.each( this.available, function( i ){ + $special.drop.locate( this, i ); + }); + } +}; + +// patch $.event.$dispatch to allow suppressing clicks +var $dispatch = $event.dispatch; +$event.dispatch = function( event ){ + if ( $.data( this, "suppress."+ event.type ) - new Date().getTime() > 0 ){ + $.removeData( this, "suppress."+ event.type ); + return; + } + return $dispatch.apply( this, arguments ); +}; + +// event fix hooks for touch events... +var touchHooks = +$event.fixHooks.touchstart = +$event.fixHooks.touchmove = +$event.fixHooks.touchend = +$event.fixHooks.touchcancel = { + props: "clientX clientY pageX pageY screenX screenY".split( " " ), + filter: function( event, orig ) { + if ( orig ){ + var touched = ( orig.touches && orig.touches[0] ) + || ( orig.changedTouches && orig.changedTouches[0] ) + || null; + // iOS webkit: touchstart, touchmove, touchend + if ( touched ) + $.each( touchHooks.props, function( i, prop ){ + event[ prop ] = touched[ prop ]; + }); + } + return event; + } +}; + +// share the same special event configuration with related events... +$special.draginit = $special.dragstart = $special.dragend = drag; + +})( jQuery );
\ No newline at end of file diff --git a/hugo/js/jquery/jquery.fullscreen.js b/hugo/js/jquery/jquery.fullscreen.js new file mode 100644 index 0000000..248e8ff --- /dev/null +++ b/hugo/js/jquery/jquery.fullscreen.js @@ -0,0 +1,60 @@ +// jQuery.FullScreen plugin + +// Triple-licensed: Public Domain, MIT and WTFPL license - share and enjoy! + +(function($) { + function isFullScreen() { + return document[!prefix ? 'fullScreen' : + 'webkit' === prefix ? 'webkitIsFullScreen' : + prefix + 'FullScreen']; + } + function cancelFullScreen() { + return document[prefix ? prefix + 'CancelFullScreen' + : 'cancelFullScreen'](); + } + + var supported = typeof document.cancelFullScreen !== 'undefined' + , prefixes = ['webkit', 'moz', 'o', 'ms', 'khtml'] + , prefix = '' + , noop = function() {} + , i + ; + + if (!supported) { + for (i = 0; prefix = prefixes[i]; i++) { + if (typeof document[prefix + 'CancelFullScreen'] !== 'undefined') { + supported = true; + break; + } + } + } + + if (supported) { + $.fn.requestFullScreen = function() { + return this.each(function() { + return this[prefix ? prefix + 'RequestFullScreen' + : 'requestFullScreen'](); + }); + }; + $.fn.fullScreenChange = function(fn) { + var ar = [prefix + 'fullscreenchange'].concat([].slice.call(arguments, 0)) + , $e = $(this); + return $e.bind.apply($e, ar); + }; + $.FullScreen = + { isFullScreen: isFullScreen + , cancelFullScreen: cancelFullScreen + , prefix: prefix + , supported: supported + }; + } + else { + $.fn.requestFullScreen = $.fn.fullScreenChange = noop; + $.FullScreen = + { isFullScreen: function() { return false; } + , cancelFullScreen: noop + , prefix: prefix + , supported: supported + }; + } +})(jQuery); diff --git a/hugo/js/jquery/jquery.json-2.4.js b/hugo/js/jquery/jquery.json-2.4.js new file mode 100644 index 0000000..75953f4 --- /dev/null +++ b/hugo/js/jquery/jquery.json-2.4.js @@ -0,0 +1,199 @@ +/** + * jQuery JSON plugin 2.4.0 + * + * @author Brantley Harris, 2009-2011 + * @author Timo Tijhof, 2011-2012 + * @source This plugin is heavily influenced by MochiKit's serializeJSON, which is + * copyrighted 2005 by Bob Ippolito. + * @source Brantley Harris wrote this plugin. It is based somewhat on the JSON.org + * website's http://www.json.org/json2.js, which proclaims: + * "NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.", a sentiment that + * I uphold. + * @license MIT License <http://www.opensource.org/licenses/mit-license.php> + */ +(function ($) { + 'use strict'; + + var escape = /["\\\x00-\x1f\x7f-\x9f]/g, + meta = { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '"' : '\\"', + '\\': '\\\\' + }, + hasOwn = Object.prototype.hasOwnProperty; + + /** + * jQuery.toJSON + * Converts the given argument into a JSON representation. + * + * @param o {Mixed} The json-serializable *thing* to be converted + * + * If an object has a toJSON prototype, that will be used to get the representation. + * Non-integer/string keys are skipped in the object, as are keys that point to a + * function. + * + */ + $.toJSON = typeof JSON === 'object' && JSON.stringify ? JSON.stringify : function (o) { + if (o === null) { + return 'null'; + } + + var pairs, k, name, val, + type = $.type(o); + + if (type === 'undefined') { + return undefined; + } + + // Also covers instantiated Number and Boolean objects, + // which are typeof 'object' but thanks to $.type, we + // catch them here. I don't know whether it is right + // or wrong that instantiated primitives are not + // exported to JSON as an {"object":..}. + // We choose this path because that's what the browsers did. + if (type === 'number' || type === 'boolean') { + return String(o); + } + if (type === 'string') { + return $.quoteString(o); + } + if (typeof o.toJSON === 'function') { + return $.toJSON(o.toJSON()); + } + if (type === 'date') { + var month = o.getUTCMonth() + 1, + day = o.getUTCDate(), + year = o.getUTCFullYear(), + hours = o.getUTCHours(), + minutes = o.getUTCMinutes(), + seconds = o.getUTCSeconds(), + milli = o.getUTCMilliseconds(); + + if (month < 10) { + month = '0' + month; + } + if (day < 10) { + day = '0' + day; + } + if (hours < 10) { + hours = '0' + hours; + } + if (minutes < 10) { + minutes = '0' + minutes; + } + if (seconds < 10) { + seconds = '0' + seconds; + } + if (milli < 100) { + milli = '0' + milli; + } + if (milli < 10) { + milli = '0' + milli; + } + return '"' + year + '-' + month + '-' + day + 'T' + + hours + ':' + minutes + ':' + seconds + + '.' + milli + 'Z"'; + } + + pairs = []; + + if ($.isArray(o)) { + for (k = 0; k < o.length; k++) { + pairs.push($.toJSON(o[k]) || 'null'); + } + return '[' + pairs.join(',') + ']'; + } + + // Any other object (plain object, RegExp, ..) + // Need to do typeof instead of $.type, because we also + // want to catch non-plain objects. + if (typeof o === 'object') { + for (k in o) { + // Only include own properties, + // Filter out inherited prototypes + if (hasOwn.call(o, k)) { + // Keys must be numerical or string. Skip others + type = typeof k; + if (type === 'number') { + name = '"' + k + '"'; + } else if (type === 'string') { + name = $.quoteString(k); + } else { + continue; + } + type = typeof o[k]; + + // Invalid values like these return undefined + // from toJSON, however those object members + // shouldn't be included in the JSON string at all. + if (type !== 'function' && type !== 'undefined') { + val = $.toJSON(o[k]); + pairs.push(name + ':' + val); + } + } + } + return '{' + pairs.join(',') + '}'; + } + }; + + /** + * jQuery.evalJSON + * Evaluates a given json string. + * + * @param str {String} + */ + $.evalJSON = typeof JSON === 'object' && JSON.parse ? JSON.parse : function (str) { + /*jshint evil: true */ + return eval('(' + str + ')'); + }; + + /** + * jQuery.secureEvalJSON + * Evals JSON in a way that is *more* secure. + * + * @param str {String} + */ + $.secureEvalJSON = typeof JSON === 'object' && JSON.parse ? JSON.parse : function (str) { + var filtered = + str + .replace(/\\["\\\/bfnrtu]/g, '@') + .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') + .replace(/(?:^|:|,)(?:\s*\[)+/g, ''); + + if (/^[\],:{}\s]*$/.test(filtered)) { + /*jshint evil: true */ + return eval('(' + str + ')'); + } + throw new SyntaxError('Error parsing JSON, source is not valid.'); + }; + + /** + * jQuery.quoteString + * Returns a string-repr of a string, escaping quotes intelligently. + * Mostly a support function for toJSON. + * Examples: + * >>> jQuery.quoteString('apple') + * "apple" + * + * >>> jQuery.quoteString('"Where are we going?", she asked.') + * "\"Where are we going?\", she asked." + */ + $.quoteString = function (str) { + if (str.match(escape)) { + return '"' + str.replace(escape, function (a) { + var c = meta[a]; + if (typeof c === 'string') { + return c; + } + c = a.charCodeAt(); + return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16); + }) + '"'; + } + return '"' + str + '"'; + }; + +}(jQuery)); diff --git a/hugo/js/jquery/jquery.menuResizer-1.0.js b/hugo/js/jquery/jquery.menuResizer-1.0.js new file mode 100644 index 0000000..3a53b1f --- /dev/null +++ b/hugo/js/jquery/jquery.menuResizer-1.0.js @@ -0,0 +1,181 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Handles the resizing of a menu according to the available screen width + * + * Uses themes/original/css/resizable-menu.css.php + * + * To initialise: + * $('#myMenu').menuResizer(function () { + * // This function will be called to find out how much + * // available horizontal space there is for the menu + * return $('body').width() - 5; // Some extra margin for good measure + * }); + * + * To trigger a resize operation: + * $('#myMenu').menuResizer('resize'); // Bind this to $(window).resize() + * + * To restore the menu to a state like before it was initialized: + * $('#myMenu').menuResizer('destroy'); + * + * @package PhpMyAdmin + */ +(function ($) { + function MenuResizer($container, widthCalculator) { + var self = this; + self.$container = $container; + self.widthCalculator = widthCalculator; + // create submenu container + var link = $('<a />', {href: '#', 'class': 'tab nowrap'}) + .text(PMA_messages['strMore']) + .bind('click', false); // same as event.preventDefault() + var img = $container.find('li img'); + if (img.length) { + $(PMA_getImage('b_more.png').toString()).prependTo(link); + } + var $submenu = $('<li />', {'class': 'submenu'}) + .append(link) + .append($('<ul />')) + .mouseenter(function() { + if ($(this).find('ul .tabactive').length == 0) { + $(this) + .addClass('submenuhover') + .find('> a') + .addClass('tabactive'); + } + }) + .mouseleave(function() { + if ($(this).find('ul .tabactive').length == 0) { + $(this) + .removeClass('submenuhover') + .find('> a') + .removeClass('tabactive'); + } + }); + $container.append($submenu); + setTimeout(function () { + self.resize(); + }, 4); + } + MenuResizer.prototype.resize = function () { + var wmax = this.widthCalculator.call(this.$container); + var $submenu = this.$container.find('.submenu:last'); + var submenu_w = $submenu.outerWidth(true); + var $submenu_ul = $submenu.find('ul'); + var $li = this.$container.find('> li'); + var $li2 = $submenu_ul.find('li'); + var more_shown = $li2.length > 0; + // Calculate the total width used by all the shown tabs + var total_len = more_shown ? submenu_w : 0; + var l = $li.length - 1; + for (var i = 0; i < l; i++) { + total_len += $($li[i]).outerWidth(true); + } + // Now hide menu elements that don't fit into the menubar + var hidden = false; // Whether we have hidden any tabs + while (total_len >= wmax && --l >= 0) { // Process the tabs backwards + hidden = true; + var el = $($li[l]); + var el_width = el.outerWidth(true); + el.data('width', el_width); + if (! more_shown) { + total_len -= el_width; + el.prependTo($submenu_ul); + total_len += submenu_w; + more_shown = true; + } else { + total_len -= el_width; + el.prependTo($submenu_ul); + } + } + // If we didn't hide any tabs, then there might be some space to show some + if (! hidden) { + // Show menu elements that do fit into the menubar + for (var i = 0, l = $li2.length; i < l; i++) { + total_len += $($li2[i]).data('width'); + // item fits or (it is the last item + // and it would fit if More got removed) + if (total_len < wmax + || (i == $li2.length - 1 && total_len - submenu_w < wmax) + ) { + $($li2[i]).insertBefore($submenu); + } else { + break; + } + } + } + // Show/hide the "More" tab as needed + if ($submenu_ul.find('li').length > 0) { + $submenu.addClass('shown'); + } else { + $submenu.removeClass('shown'); + } + if (this.$container.find('> li').length == 1) { + // If there is only the "More" tab left, then we need + // to align the submenu to the left edge of the tab + $submenu_ul.removeClass().addClass('only'); + } else { + // Otherwise we align the submenu to the right edge of the tab + $submenu_ul.removeClass().addClass('notonly'); + } + if ($submenu.find('.tabactive').length) { + $submenu + .addClass('active') + .find('> a') + .removeClass('tab') + .addClass('tabactive'); + } else { + $submenu + .removeClass('active') + .find('> a') + .addClass('tab') + .removeClass('tabactive'); + } + }; + MenuResizer.prototype.destroy = function () { + var $submenu = this.$container.find('li.submenu').removeData(); + $submenu.find('li').appendTo(this.$container); + $submenu.remove(); + }; + + /** Public API */ + var methods = { + init: function(widthCalculator) { + return this.each(function () { + var $this = $(this); + if (! $this.data('menuResizer')) { + $this.data( + 'menuResizer', + new MenuResizer($this, widthCalculator) + ); + } + }); + }, + resize: function () { + return this.each(function () { + var self = $(this).data('menuResizer'); + if (self) { + self.resize(); + } + }); + }, + destroy: function () { + return this.each(function () { + var self = $(this).data('menuResizer'); + if (self) { + self.destroy(); + } + }); + } + }; + + /** Extend jQuery */ + $.fn.menuResizer = function(method) { + if (methods[method]) { + return methods[method].call(this); + } else if (typeof method === 'function') { + return methods.init.apply(this, [method]); + } else { + $.error('Method ' + method + ' does not exist on jQuery.menuResizer'); + } + }; +})(jQuery); diff --git a/hugo/js/jquery/jquery.mousewheel.js b/hugo/js/jquery/jquery.mousewheel.js new file mode 100644 index 0000000..38b6095 --- /dev/null +++ b/hugo/js/jquery/jquery.mousewheel.js @@ -0,0 +1,84 @@ +/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net) + * Licensed under the MIT License (LICENSE.txt). + * + * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers. + * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix. + * Thanks to: Seamus Leahy for adding deltaX and deltaY + * + * Version: 3.0.6 + * + * Requires: 1.2.2+ + */ + +(function($) { + +var types = ['DOMMouseScroll', 'mousewheel']; + +if ($.event.fixHooks) { + for ( var i=types.length; i; ) { + $.event.fixHooks[ types[--i] ] = $.event.mouseHooks; + } +} + +$.event.special.mousewheel = { + setup: function() { + if ( this.addEventListener ) { + for ( var i=types.length; i; ) { + this.addEventListener( types[--i], handler, false ); + } + } else { + this.onmousewheel = handler; + } + }, + + teardown: function() { + if ( this.removeEventListener ) { + for ( var i=types.length; i; ) { + this.removeEventListener( types[--i], handler, false ); + } + } else { + this.onmousewheel = null; + } + } +}; + +$.fn.extend({ + mousewheel: function(fn) { + return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel"); + }, + + unmousewheel: function(fn) { + return this.unbind("mousewheel", fn); + } +}); + + +function handler(event) { + var orgEvent = event || window.event, args = [].slice.call( arguments, 1 ), delta = 0, returnValue = true, deltaX = 0, deltaY = 0; + event = $.event.fix(orgEvent); + event.type = "mousewheel"; + + // Old school scrollwheel delta + if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta/120; } + if ( orgEvent.detail ) { delta = -orgEvent.detail/3; } + + // New school multidimensional scroll (touchpads) deltas + deltaY = delta; + + // Gecko + if ( orgEvent.axis !== undefined && orgEvent.axis === orgEvent.HORIZONTAL_AXIS ) { + deltaY = 0; + deltaX = -1*delta; + } + + // Webkit + if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY/120; } + if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = -1*orgEvent.wheelDeltaX/120; } + + // Add event and delta to the front of the arguments + args.unshift(event, delta, deltaX, deltaY); + + return ($.event.dispatch || $.event.handle).apply(this, args); +} + +})(jQuery); diff --git a/hugo/js/jquery/jquery.sortableTable.js b/hugo/js/jquery/jquery.sortableTable.js new file mode 100644 index 0000000..1f4fc91 --- /dev/null +++ b/hugo/js/jquery/jquery.sortableTable.js @@ -0,0 +1,272 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * @fileoverview A jquery plugin that allows drag&drop sorting in tables. + * Coded because JQuery UI sortable doesn't support tables. Also it has no animation + * + * @name Sortable Table JQuery plugin + * + * @requires jQuery + * + */ + +/* Options: + +$('table').sortableTable({ + ignoreRect: { top, left, width, height } - relative coordinates on each element. If the user clicks + in this area, it is not seen as a drag&drop request. Useful for toolbars etc. + events: { + start: callback function when the user starts dragging + drop: callback function after an element has been dropped + } +}) +*/ + +/* Commands: + +$('table').sortableTable('init') - equivalent to $('table').sortableTable() +$('table').sortableTable('refresh') - if the table has been changed, refresh correctly assigns all events again +$('table').sortableTable('destroy') - removes all events from the table + +*/ + +/* Setup: + + Can be applied on any table, there is just one convention. + Each cell (<td>) has to contain one and only one element (preferably div or span) + which is the actually draggable element. +*/ +(function($) { + jQuery.fn.sortableTable = function(method) { + + var methods = { + init : function(options) { + var tb = new sortableTableInstance(this, options); + tb.init(); + $(this).data('sortableTable',tb); + }, + refresh : function( ) { + $(this).data('sortableTable').refresh(); + }, + destroy : function( ) { + $(this).data('sortableTable').destroy(); + } + }; + + if ( methods[method] ) { + return methods[method].apply( this, Array.prototype.slice.call( arguments, 1 )); + } else if ( typeof method === 'object' || ! method ) { + return methods.init.apply( this, arguments ); + } else { + $.error( 'Method ' + method + ' does not exist on jQuery.sortableTable' ); + } + + function sortableTableInstance(table, options) { + var down = false; + var $draggedEl, oldCell, previewMove, id; + + if(!options) options = {}; + + /* Mouse handlers on the child elements */ + var onMouseUp = function(e) { + dropAt(e.pageX, e.pageY); + } + + var onMouseDown = function(e) { + $draggedEl = $(this).children(); + if($draggedEl.length == 0) return; + if(options.ignoreRect && insideRect({x: e.pageX - $draggedEl.offset().left, y: e.pageY - $draggedEl.offset().top}, options.ignoreRect)) return; + + down = true; + oldCell = this; + //move(e.pageX,e.pageY); + + if(options.events && options.events.start) + options.events.start(this); + + return false; + } + + var globalMouseMove = function(e) { + if(down) { + move(e.pageX,e.pageY); + + if(inside($(oldCell), e.pageX, e.pageY)) { + if(previewMove != null) { + moveTo(previewMove); + previewMove = null; + } + } else + $(table).find('td').each(function() { + if(inside($(this), e.pageX, e.pageY)) { + if($(previewMove).attr('class') != $(this).children().first().attr('class')) { + if(previewMove != null) moveTo(previewMove); + previewMove = $(this).children().first(); + if(previewMove.length > 0) + moveTo($(previewMove), { pos: { + top: $(oldCell).offset().top - $(previewMove).parent().offset().top, + left: $(oldCell).offset().left - $(previewMove).parent().offset().left + } }); + } + + return false; + } + }); + } + + return false; + } + + var globalMouseOut = function() { + if(down) { + down = false; + if(previewMove) moveTo(previewMove); + moveTo($draggedEl); + previewMove = null; + } + } + + // Initialize sortable table + this.init = function() { + id = 1; + // Add some required css to each child element in the <td>s + $(table).find('td').children().each(function() { + // Remove any old occurences of our added draggable-num class + $(this).attr('class',$(this).attr('class').replace(/\s*draggable\-\d+/g,'')); + $(this).addClass('draggable-' + (id++)); + }); + + // Mouse events + $(table).find('td').bind('mouseup',onMouseUp); + $(table).find('td').bind('mousedown',onMouseDown); + + $(document).mousemove(globalMouseMove); + $(document).bind('mouseleave', globalMouseOut); + } + + // Call this when the table has been updated + this.refresh = function() { + this.destroy(); + this.init(); + } + + this.destroy = function() { + // Add some required css to each child element in the <td>s + $(table).find('td').children().each(function() { + // Remove any old occurences of our added draggable-num class + $(this).attr('class',$(this).attr('class').replace(/\s*draggable\-\d+/g,'')); + }); + + // Mouse events + $(table).find('td').unbind('mouseup',onMouseUp) + $(table).find('td').unbind('mousedown',onMouseDown); + + $(document).unbind('mousemove',globalMouseMove); + $(document).unbind('mouseleave',globalMouseOut); + } + + function switchElement(drag, dropTo) { + var dragPosDiff = { + left: $(drag).children().first().offset().left - $(dropTo).offset().left, + top: $(drag).children().first().offset().top - $(dropTo).offset().top + }; + + var dropPosDiff = null; + if($(dropTo).children().length > 0) { + dropPosDiff = { + left: $(dropTo).children().first().offset().left - $(drag).offset().left, + top: $(dropTo).children().first().offset().top - $(drag).offset().top + }; + } + + /* I love you append(). It moves the DOM Elements so gracefully <3 */ + // Put the element in the way to old place + $(drag).append($(dropTo).children().first()).children() + .stop(true,true) + .bind('mouseup',onMouseUp); + + if(dropPosDiff) + $(drag).append($(dropTo).children().first()).children() + .css('left',dropPosDiff.left + 'px') + .css('top',dropPosDiff.top + 'px'); + + // Put our dragged element into the space we just freed up + $(dropTo).append($(drag).children().first()).children() + .bind('mouseup',onMouseUp) + .css('left',dragPosDiff.left + 'px') + .css('top',dragPosDiff.top + 'px'); + + moveTo($(dropTo).children().first(), { duration: 100 }); + moveTo($(drag).children().first(), { duration: 100 }); + + if(options.events && options.events.drop) { + // Drop event. The drag child element is moved into the drop element + // and vice versa. So the parameters are switched. + + // Calculate row and column index + colIdx = $(dropTo).prevAll().length; + rowIdx = $(dropTo).parent().prevAll().length; + + options.events.drop(drag,dropTo, { col: colIdx, row: rowIdx }); + } + } + + function move(x,y) { + $draggedEl.offset({ + top: Math.min($(document).height(), Math.max(0, y - $draggedEl.height()/2)), + left: Math.min($(document).width(), Math.max(0, x - $draggedEl.width()/2)) + }); + } + + function inside($el, x,y) { + var off = $el.offset(); + return y >= off.top && x >= off.left && x < off.left + $el.width() && y < off.top + $el.height(); + } + + function insideRect(pos, r) { + return pos.y > r.top && pos.x > r.left && pos.y < r.top + r.height && pos.x < r.left + r.width; + } + + function dropAt(x,y) { + if(!down) return; + down = false; + + var switched = false; + + $(table).find('td').each(function() { + if($(this).children().first().attr('class') != $(oldCell).children().first().attr('class') && inside($(this), x, y)) { + switchElement(oldCell, this); + switched = true; + return; + } + }); + + if(!switched) { + if(previewMove) moveTo(previewMove); + moveTo($draggedEl); + } + + previewMove = null; + } + + function moveTo(elem, opts) { + if(!opts) opts = {}; + if(!opts.pos) opts.pos = { left: 0, top: 0 }; + if(!opts.duration) opts.duration = 200; + + $(elem).css('position','relative'); + $(elem).animate({ top: opts.pos.top, left: opts.pos.left }, { + duration: opts.duration, + complete: function() { + if(opts.pos.left == 0 && opts.pos.top == 0) { + $(elem) + .css('position','') + .css('left','') + .css('top',''); + } + } + }); + } + } + } + +})( jQuery );
\ No newline at end of file diff --git a/hugo/js/jquery/jquery.sprintf.js b/hugo/js/jquery/jquery.sprintf.js new file mode 100644 index 0000000..3d39b76 --- /dev/null +++ b/hugo/js/jquery/jquery.sprintf.js @@ -0,0 +1,68 @@ +/** + * sprintf and vsprintf for jQuery + * somewhat based on http://jan.moesen.nu/code/javascript/sprintf-and-printf-in-javascript/ + * + * Copyright (c) 2008 Sabin Iacob (m0n5t3r) <iacobs@m0n5t3r.info> + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * @license http://www.gnu.org/licenses/gpl.html + * @project jquery.sprintf + */ +(function($){ + var formats = { + 'b': function(val) {return parseInt(val, 10).toString(2);}, + 'c': function(val) {return String.fromCharCode(parseInt(val, 10));}, + 'd': function(val) {return parseInt(val, 10);}, + 'u': function(val) {return Math.abs(val);}, + 'f': function(val, p) { + p = parseInt(p, 10); + val = parseFloat(val); + if(isNaN(p && val)) { + return NaN; + } + return p && val.toFixed(p) || val; + }, + 'o': function(val) {return parseInt(val, 10).toString(8);}, + 's': function(val) {return val;}, + 'x': function(val) {return ('' + parseInt(val, 10).toString(16)).toLowerCase();}, + 'X': function(val) {return ('' + parseInt(val, 10).toString(16)).toUpperCase();} + }; + + var re = /%(?:(\d+)?(?:\.(\d+))?|\(([^)]+)\))([%bcdufosxX])/g; + + var dispatch = function(data){ + if(data.length == 1 && typeof data[0] == 'object') { //python-style printf + data = data[0]; + return function(match, w, p, lbl, fmt, off, str) { + return formats[fmt](data[lbl]); + }; + } else { // regular, somewhat incomplete, printf + var idx = 0; + return function(match, w, p, lbl, fmt, off, str) { + if(fmt == '%') { + return '%'; + } + return formats[fmt](data[idx++], p); + }; + } + }; + + $.extend({ + sprintf: function(format) { + var argv = Array.apply(null, arguments).slice(1); + return format.replace(re, dispatch(argv)); + }, + vsprintf: function(format, data) { + return format.replace(re, dispatch(data)); + } + }); +})(jQuery); + diff --git a/hugo/js/jquery/jquery.svg.js b/hugo/js/jquery/jquery.svg.js new file mode 100644 index 0000000..ec9aa16 --- /dev/null +++ b/hugo/js/jquery/jquery.svg.js @@ -0,0 +1,1339 @@ +/* http://keith-wood.name/svg.html + SVG for jQuery v1.4.3. + Written by Keith Wood (kbwood{at}iinet.com.au) August 2007. + Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and + MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses. + Please attribute the author if you use it. */ + +(function($) { // Hide scope, no $ conflict + +/* SVG manager. + Use the singleton instance of this class, $.svg, + to interact with the SVG functionality. */ +function SVGManager() { + this._settings = []; // Settings to be remembered per SVG object + this._extensions = []; // List of SVG extensions added to SVGWrapper + // for each entry [0] is extension name, [1] is extension class (function) + // the function takes one parameter - the SVGWrapper instance + this.regional = []; // Localisations, indexed by language, '' for default (English) + this.regional[''] = {errorLoadingText: 'Error loading', + notSupportedText: 'This browser does not support SVG'}; + this.local = this.regional['']; // Current localisation + this._uuid = new Date().getTime(); + this._renesis = detectActiveX('RenesisX.RenesisCtrl'); +} + +/* Determine whether a given ActiveX control is available. + @param classId (string) the ID for the ActiveX control + @return (boolean) true if found, false if not */ +function detectActiveX(classId) { + try { + return !!(window.ActiveXObject && new ActiveXObject(classId)); + } + catch (e) { + return false; + } +} + +var PROP_NAME = 'svgwrapper'; + +$.extend(SVGManager.prototype, { + /* Class name added to elements to indicate already configured with SVG. */ + markerClassName: 'hasSVG', + + /* SVG namespace. */ + svgNS: 'http://www.w3.org/2000/svg', + /* XLink namespace. */ + xlinkNS: 'http://www.w3.org/1999/xlink', + + /* SVG wrapper class. */ + _wrapperClass: SVGWrapper, + + /* Camel-case versions of attribute names containing dashes or are reserved words. */ + _attrNames: {class_: 'class', in_: 'in', + alignmentBaseline: 'alignment-baseline', baselineShift: 'baseline-shift', + clipPath: 'clip-path', clipRule: 'clip-rule', + colorInterpolation: 'color-interpolation', + colorInterpolationFilters: 'color-interpolation-filters', + colorRendering: 'color-rendering', dominantBaseline: 'dominant-baseline', + enableBackground: 'enable-background', fillOpacity: 'fill-opacity', + fillRule: 'fill-rule', floodColor: 'flood-color', + floodOpacity: 'flood-opacity', fontFamily: 'font-family', + fontSize: 'font-size', fontSizeAdjust: 'font-size-adjust', + fontStretch: 'font-stretch', fontStyle: 'font-style', + fontVariant: 'font-variant', fontWeight: 'font-weight', + glyphOrientationHorizontal: 'glyph-orientation-horizontal', + glyphOrientationVertical: 'glyph-orientation-vertical', + horizAdvX: 'horiz-adv-x', horizOriginX: 'horiz-origin-x', + imageRendering: 'image-rendering', letterSpacing: 'letter-spacing', + lightingColor: 'lighting-color', markerEnd: 'marker-end', + markerMid: 'marker-mid', markerStart: 'marker-start', + stopColor: 'stop-color', stopOpacity: 'stop-opacity', + strikethroughPosition: 'strikethrough-position', + strikethroughThickness: 'strikethrough-thickness', + strokeDashArray: 'stroke-dasharray', strokeDashOffset: 'stroke-dashoffset', + strokeLineCap: 'stroke-linecap', strokeLineJoin: 'stroke-linejoin', + strokeMiterLimit: 'stroke-miterlimit', strokeOpacity: 'stroke-opacity', + strokeWidth: 'stroke-width', textAnchor: 'text-anchor', + textDecoration: 'text-decoration', textRendering: 'text-rendering', + underlinePosition: 'underline-position', underlineThickness: 'underline-thickness', + vertAdvY: 'vert-adv-y', vertOriginY: 'vert-origin-y', + wordSpacing: 'word-spacing', writingMode: 'writing-mode'}, + + /* Add the SVG object to its container. */ + _attachSVG: function(container, settings) { + var svg = (container.namespaceURI == this.svgNS ? container : null); + var container = (svg ? null : container); + if ($(container || svg).hasClass(this.markerClassName)) { + return; + } + if (typeof settings == 'string') { + settings = {loadURL: settings}; + } + else if (typeof settings == 'function') { + settings = {onLoad: settings}; + } + $(container || svg).addClass(this.markerClassName); + try { + if (!svg) { + svg = document.createElementNS(this.svgNS, 'svg'); + svg.setAttribute('version', '1.1'); + svg.setAttribute('width', container.clientWidth); + svg.setAttribute('height', container.clientHeight); + container.appendChild(svg); + } + this._afterLoad(container, svg, settings || {}); + } + catch (e) { + if ($.browser.msie) { + if (!container.id) { + container.id = 'svg' + (this._uuid++); + } + this._settings[container.id] = settings; + container.innerHTML = '<embed type="image/svg+xml" width="100%" ' + + 'height="100%" src="' + (settings.initPath || '') + 'blank.svg"/>'; + } + else { + container.innerHTML = '<p class="svg_error">' + + this.local.notSupportedText + '</p>'; + } + } + }, + + /* SVG callback after loading - register SVG root. */ + _registerSVG: function() { + for (var i = 0; i < document.embeds.length; i++) { // Check all + var container = document.embeds[i].parentNode; + if (!$(container).hasClass($.svg.markerClassName) || // Not SVG + $.data(container, PROP_NAME)) { // Already done + continue; + } + var svg = null; + try { + svg = document.embeds[i].getSVGDocument(); + } + catch(e) { + setTimeout($.svg._registerSVG, 250); // Renesis takes longer to load + return; + } + svg = (svg ? svg.documentElement : null); + if (svg) { + $.svg._afterLoad(container, svg); + } + } + }, + + /* Post-processing once loaded. */ + _afterLoad: function(container, svg, settings) { + var settings = settings || this._settings[container.id]; + this._settings[container ? container.id : ''] = null; + var wrapper = new this._wrapperClass(svg, container); + $.data(container || svg, PROP_NAME, wrapper); + try { + if (settings.loadURL) { // Load URL + wrapper.load(settings.loadURL, settings); + } + if (settings.settings) { // Additional settings + wrapper.configure(settings.settings); + } + if (settings.onLoad && !settings.loadURL) { // Onload callback + settings.onLoad.apply(container || svg, [wrapper]); + } + } + catch (e) { + alert(e); + } + }, + + /* Return the SVG wrapper created for a given container. + @param container (string) selector for the container or + (element) the container for the SVG object or + jQuery collection - first entry is the container + @return (SVGWrapper) the corresponding SVG wrapper element, or null if not attached */ + _getSVG: function(container) { + container = (typeof container == 'string' ? $(container)[0] : + (container.jquery ? container[0] : container)); + return $.data(container, PROP_NAME); + }, + + /* Remove the SVG functionality from a div. + @param container (element) the container for the SVG object */ + _destroySVG: function(container) { + var $container = $(container); + if (!$container.hasClass(this.markerClassName)) { + return; + } + $container.removeClass(this.markerClassName); + if (container.namespaceURI != this.svgNS) { + $container.empty(); + } + $.removeData(container, PROP_NAME); + }, + + /* Extend the SVGWrapper object with an embedded class. + The constructor function must take a single parameter that is + a reference to the owning SVG root object. This allows the + extension to access the basic SVG functionality. + @param name (string) the name of the SVGWrapper attribute to access the new class + @param extClass (function) the extension class constructor */ + addExtension: function(name, extClass) { + this._extensions.push([name, extClass]); + } +}); + +/* The main SVG interface, which encapsulates the SVG element. + Obtain a reference from $().svg('get') */ +function SVGWrapper(svg, container) { + this._svg = svg; // The SVG root node + this._container = container; // The containing div + for (var i = 0; i < $.svg._extensions.length; i++) { + var extension = $.svg._extensions[i]; + this[extension[0]] = new extension[1](this); + } +} + +$.extend(SVGWrapper.prototype, { + + /* Retrieve the width of the SVG object. */ + _width: function() { + return (this._container ? this._container.clientWidth : this._svg.width); + }, + + /* Retrieve the height of the SVG object. */ + _height: function() { + return (this._container ? this._container.clientHeight : this._svg.height); + }, + + /* Retrieve the root SVG element. + @return the top-level SVG element */ + root: function() { + return this._svg; + }, + + /* Configure the SVG root. + @param settings (object) additional settings for the root + @param clear (boolean) true to remove existing attributes first, + false to add to what is already there (optional) + @return (SVGWrapper) this root */ + configure: function(settings, clear) { + if (clear) { + for (var i = this._svg.attributes.length - 1; i >= 0; i--) { + var attr = this._svg.attributes.item(i); + if (!(attr.nodeName == 'onload' || attr.nodeName == 'version' || + attr.nodeName.substring(0, 5) == 'xmlns')) { + this._svg.attributes.removeNamedItem(attr.nodeName); + } + } + } + for (var attrName in settings) { + this._svg.setAttribute(attrName, settings[attrName]); + } + return this; + }, + + /* Locate a specific element in the SVG document. + @param id (string) the element's identifier + @return (element) the element reference, or null if not found */ + getElementById: function(id) { + return this._svg.ownerDocument.getElementById(id); + }, + + /* Change the attributes for a SVG node. + @param element (SVG element) the node to change + @param settings (object) the new settings + @return (SVGWrapper) this root */ + change: function(element, settings) { + if (element) { + for (var name in settings) { + if (settings[name] == null) { + element.removeAttribute(name); + } + else { + element.setAttribute(name, settings[name]); + } + } + } + return this; + }, + + /* Check for parent being absent and adjust arguments accordingly. */ + _args: function(values, names, optSettings) { + names.splice(0, 0, 'parent'); + names.splice(names.length, 0, 'settings'); + var args = {}; + var offset = 0; + if (values[0] != null && values[0].jquery) { + values[0] = values[0][0]; + } + if (values[0] != null && !(typeof values[0] == 'object' && values[0].nodeName)) { + args['parent'] = null; + offset = 1; + } + for (var i = 0; i < values.length; i++) { + args[names[i + offset]] = values[i]; + } + if (optSettings) { + $.each(optSettings, function(i, value) { + if (typeof args[value] == 'object') { + args.settings = args[value]; + args[value] = null; + } + }); + } + return args; + }, + + /* Add a title. + @param parent (element or jQuery) the parent node for the new title (optional) + @param text (string) the text of the title + @param settings (object) additional settings for the title (optional) + @return (element) the new title node */ + title: function(parent, text, settings) { + var args = this._args(arguments, ['text']); + var node = this._makeNode(args.parent, 'title', args.settings || {}); + node.appendChild(this._svg.ownerDocument.createTextNode(args.text)); + return node; + }, + + /* Add a description. + @param parent (element or jQuery) the parent node for the new description (optional) + @param text (string) the text of the description + @param settings (object) additional settings for the description (optional) + @return (element) the new description node */ + describe: function(parent, text, settings) { + var args = this._args(arguments, ['text']); + var node = this._makeNode(args.parent, 'desc', args.settings || {}); + node.appendChild(this._svg.ownerDocument.createTextNode(args.text)); + return node; + }, + + /* Add a definitions node. + @param parent (element or jQuery) the parent node for the new definitions (optional) + @param id (string) the ID of this definitions (optional) + @param settings (object) additional settings for the definitions (optional) + @return (element) the new definitions node */ + defs: function(parent, id, settings) { + var args = this._args(arguments, ['id'], ['id']); + return this._makeNode(args.parent, 'defs', $.extend( + (args.id ? {id: args.id} : {}), args.settings || {})); + }, + + /* Add a symbol definition. + @param parent (element or jQuery) the parent node for the new symbol (optional) + @param id (string) the ID of this symbol + @param x1 (number) the left coordinate for this symbol + @param y1 (number) the top coordinate for this symbol + @param width (number) the width of this symbol + @param height (number) the height of this symbol + @param settings (object) additional settings for the symbol (optional) + @return (element) the new symbol node */ + symbol: function(parent, id, x1, y1, width, height, settings) { + var args = this._args(arguments, ['id', 'x1', 'y1', 'width', 'height']); + return this._makeNode(args.parent, 'symbol', $.extend({id: args.id, + viewBox: args.x1 + ' ' + args.y1 + ' ' + args.width + ' ' + args.height}, + args.settings || {})); + }, + + /* Add a marker definition. + @param parent (element or jQuery) the parent node for the new marker (optional) + @param id (string) the ID of this marker + @param refX (number) the x-coordinate for the reference point + @param refY (number) the y-coordinate for the reference point + @param mWidth (number) the marker viewport width + @param mHeight (number) the marker viewport height + @param orient (string or int) 'auto' or angle (degrees) (optional) + @param settings (object) additional settings for the marker (optional) + @return (element) the new marker node */ + marker: function(parent, id, refX, refY, mWidth, mHeight, orient, settings) { + var args = this._args(arguments, ['id', 'refX', 'refY', + 'mWidth', 'mHeight', 'orient'], ['orient']); + return this._makeNode(args.parent, 'marker', $.extend( + {id: args.id, refX: args.refX, refY: args.refY, markerWidth: args.mWidth, + markerHeight: args.mHeight, orient: args.orient || 'auto'}, args.settings || {})); + }, + + /* Add a style node. + @param parent (element or jQuery) the parent node for the new node (optional) + @param styles (string) the CSS styles + @param settings (object) additional settings for the node (optional) + @return (element) the new style node */ + style: function(parent, styles, settings) { + var args = this._args(arguments, ['styles']); + var node = this._makeNode(args.parent, 'style', $.extend( + {type: 'text/css'}, args.settings || {})); + node.appendChild(this._svg.ownerDocument.createTextNode(args.styles)); + if ($.browser.opera) { + $('head').append('<style type="text/css">' + args.styles + '</style>'); + } + return node; + }, + + /* Add a script node. + @param parent (element or jQuery) the parent node for the new node (optional) + @param script (string) the JavaScript code + @param type (string) the MIME type for the code (optional, default 'text/javascript') + @param settings (object) additional settings for the node (optional) + @return (element) the new script node */ + script: function(parent, script, type, settings) { + var args = this._args(arguments, ['script', 'type'], ['type']); + var node = this._makeNode(args.parent, 'script', $.extend( + {type: args.type || 'text/javascript'}, args.settings || {})); + node.appendChild(this._svg.ownerDocument.createTextNode(this._escapeXML(args.script))); + if (!$.browser.mozilla) { + $.globalEval(args.script); + } + return node; + }, + + /* Add a linear gradient definition. + Specify all of x1, y1, x2, y2 or none of them. + @param parent (element or jQuery) the parent node for the new gradient (optional) + @param id (string) the ID for this gradient + @param stops (string[][]) the gradient stops, each entry is + [0] is offset (0.0-1.0 or 0%-100%), [1] is colour, + [2] is opacity (optional) + @param x1 (number) the x-coordinate of the gradient start (optional) + @param y1 (number) the y-coordinate of the gradient start (optional) + @param x2 (number) the x-coordinate of the gradient end (optional) + @param y2 (number) the y-coordinate of the gradient end (optional) + @param settings (object) additional settings for the gradient (optional) + @return (element) the new gradient node */ + linearGradient: function(parent, id, stops, x1, y1, x2, y2, settings) { + var args = this._args(arguments, + ['id', 'stops', 'x1', 'y1', 'x2', 'y2'], ['x1']); + var sets = $.extend({id: args.id}, + (args.x1 != null ? {x1: args.x1, y1: args.y1, x2: args.x2, y2: args.y2} : {})); + return this._gradient(args.parent, 'linearGradient', + $.extend(sets, args.settings || {}), args.stops); + }, + + /* Add a radial gradient definition. + Specify all of cx, cy, r, fx, fy or none of them. + @param parent (element or jQuery) the parent node for the new gradient (optional) + @param id (string) the ID for this gradient + @param stops (string[][]) the gradient stops, each entry + [0] is offset, [1] is colour, [2] is opacity (optional) + @param cx (number) the x-coordinate of the largest circle centre (optional) + @param cy (number) the y-coordinate of the largest circle centre (optional) + @param r (number) the radius of the largest circle (optional) + @param fx (number) the x-coordinate of the gradient focus (optional) + @param fy (number) the y-coordinate of the gradient focus (optional) + @param settings (object) additional settings for the gradient (optional) + @return (element) the new gradient node */ + radialGradient: function(parent, id, stops, cx, cy, r, fx, fy, settings) { + var args = this._args(arguments, + ['id', 'stops', 'cx', 'cy', 'r', 'fx', 'fy'], ['cx']); + var sets = $.extend({id: args.id}, (args.cx != null ? + {cx: args.cx, cy: args.cy, r: args.r, fx: args.fx, fy: args.fy} : {})); + return this._gradient(args.parent, 'radialGradient', + $.extend(sets, args.settings || {}), args.stops); + }, + + /* Add a gradient node. */ + _gradient: function(parent, name, settings, stops) { + var node = this._makeNode(parent, name, settings); + for (var i = 0; i < stops.length; i++) { + var stop = stops[i]; + this._makeNode(node, 'stop', $.extend( + {offset: stop[0], stopColor: stop[1]}, + (stop[2] != null ? {stopOpacity: stop[2]} : {}))); + } + return node; + }, + + /* Add a pattern definition. + Specify all of vx, vy, xwidth, vheight or none of them. + @param parent (element or jQuery) the parent node for the new pattern (optional) + @param id (string) the ID for this pattern + @param x (number) the x-coordinate for the left edge of the pattern + @param y (number) the y-coordinate for the top edge of the pattern + @param width (number) the width of the pattern + @param height (number) the height of the pattern + @param vx (number) the minimum x-coordinate for view box (optional) + @param vy (number) the minimum y-coordinate for the view box (optional) + @param vwidth (number) the width of the view box (optional) + @param vheight (number) the height of the view box (optional) + @param settings (object) additional settings for the pattern (optional) + @return (element) the new pattern node */ + pattern: function(parent, id, x, y, width, height, vx, vy, vwidth, vheight, settings) { + var args = this._args(arguments, ['id', 'x', 'y', 'width', 'height', + 'vx', 'vy', 'vwidth', 'vheight'], ['vx']); + var sets = $.extend({id: args.id, x: args.x, y: args.y, + width: args.width, height: args.height}, (args.vx != null ? + {viewBox: args.vx + ' ' + args.vy + ' ' + args.vwidth + ' ' + args.vheight} : {})); + return this._makeNode(args.parent, 'pattern', $.extend(sets, args.settings || {})); + }, + + /* Add a mask definition. + @param parent (element or jQuery) the parent node for the new mask (optional) + @param id (string) the ID for this mask + @param x (number) the x-coordinate for the left edge of the mask + @param y (number) the y-coordinate for the top edge of the mask + @param width (number) the width of the mask + @param height (number) the height of the mask + @param settings (object) additional settings for the mask (optional) + @return (element) the new mask node */ + mask: function(parent, id, x, y, width, height, settings) { + var args = this._args(arguments, ['id', 'x', 'y', 'width', 'height']); + return this._makeNode(args.parent, 'mask', $.extend( + {id: args.id, x: args.x, y: args.y, width: args.width, height: args.height}, + args.settings || {})); + }, + + /* Create a new path object. + @return (SVGPath) a new path object */ + createPath: function() { + return new SVGPath(); + }, + + /* Create a new text object. + @return (SVGText) a new text object */ + createText: function() { + return new SVGText(); + }, + + /* Add an embedded SVG element. + Specify all of vx, vy, vwidth, vheight or none of them. + @param parent (element or jQuery) the parent node for the new node (optional) + @param x (number) the x-coordinate for the left edge of the node + @param y (number) the y-coordinate for the top edge of the node + @param width (number) the width of the node + @param height (number) the height of the node + @param vx (number) the minimum x-coordinate for view box (optional) + @param vy (number) the minimum y-coordinate for the view box (optional) + @param vwidth (number) the width of the view box (optional) + @param vheight (number) the height of the view box (optional) + @param settings (object) additional settings for the node (optional) + @return (element) the new node */ + svg: function(parent, x, y, width, height, vx, vy, vwidth, vheight, settings) { + var args = this._args(arguments, ['x', 'y', 'width', 'height', + 'vx', 'vy', 'vwidth', 'vheight'], ['vx']); + var sets = $.extend({x: args.x, y: args.y, width: args.width, height: args.height}, + (args.vx != null ? {viewBox: args.vx + ' ' + args.vy + ' ' + + args.vwidth + ' ' + args.vheight} : {})); + return this._makeNode(args.parent, 'svg', $.extend(sets, args.settings || {})); + }, + + /* Create a group. + @param parent (element or jQuery) the parent node for the new group (optional) + @param id (string) the ID of this group (optional) + @param settings (object) additional settings for the group (optional) + @return (element) the new group node */ + group: function(parent, id, settings) { + var args = this._args(arguments, ['id'], ['id']); + return this._makeNode(args.parent, 'g', $.extend({id: args.id}, args.settings || {})); + }, + + /* Add a usage reference. + Specify all of x, y, width, height or none of them. + @param parent (element or jQuery) the parent node for the new node (optional) + @param x (number) the x-coordinate for the left edge of the node (optional) + @param y (number) the y-coordinate for the top edge of the node (optional) + @param width (number) the width of the node (optional) + @param height (number) the height of the node (optional) + @param ref (string) the ID of the definition node + @param settings (object) additional settings for the node (optional) + @return (element) the new node */ + use: function(parent, x, y, width, height, ref, settings) { + var args = this._args(arguments, ['x', 'y', 'width', 'height', 'ref']); + if (typeof args.x == 'string') { + args.ref = args.x; + args.settings = args.y; + args.x = args.y = args.width = args.height = null; + } + var node = this._makeNode(args.parent, 'use', $.extend( + {x: args.x, y: args.y, width: args.width, height: args.height}, + args.settings || {})); + node.setAttributeNS($.svg.xlinkNS, 'href', args.ref); + return node; + }, + + /* Add a link, which applies to all child elements. + @param parent (element or jQuery) the parent node for the new link (optional) + @param ref (string) the target URL + @param settings (object) additional settings for the link (optional) + @return (element) the new link node */ + link: function(parent, ref, settings) { + var args = this._args(arguments, ['ref']); + var node = this._makeNode(args.parent, 'a', args.settings); + node.setAttributeNS($.svg.xlinkNS, 'href', args.ref); + return node; + }, + + /* Add an image. + @param parent (element or jQuery) the parent node for the new image (optional) + @param x (number) the x-coordinate for the left edge of the image + @param y (number) the y-coordinate for the top edge of the image + @param width (number) the width of the image + @param height (number) the height of the image + @param ref (string) the path to the image + @param settings (object) additional settings for the image (optional) + @return (element) the new image node */ + image: function(parent, x, y, width, height, ref, settings) { + var args = this._args(arguments, ['x', 'y', 'width', 'height', 'ref']); + var node = this._makeNode(args.parent, 'image', $.extend( + {x: args.x, y: args.y, width: args.width, height: args.height}, + args.settings || {})); + node.setAttributeNS($.svg.xlinkNS, 'href', args.ref); + return node; + }, + + /* Draw a path. + @param parent (element or jQuery) the parent node for the new shape (optional) + @param path (string or SVGPath) the path to draw + @param settings (object) additional settings for the shape (optional) + @return (element) the new shape node */ + path: function(parent, path, settings) { + var args = this._args(arguments, ['path']); + return this._makeNode(args.parent, 'path', $.extend( + {d: (args.path.path ? args.path.path() : args.path)}, args.settings || {})); + }, + + /* Draw a rectangle. + Specify both of rx and ry or neither. + @param parent (element or jQuery) the parent node for the new shape (optional) + @param x (number) the x-coordinate for the left edge of the rectangle + @param y (number) the y-coordinate for the top edge of the rectangle + @param width (number) the width of the rectangle + @param height (number) the height of the rectangle + @param rx (number) the x-radius of the ellipse for the rounded corners (optional) + @param ry (number) the y-radius of the ellipse for the rounded corners (optional) + @param settings (object) additional settings for the shape (optional) + @return (element) the new shape node */ + rect: function(parent, x, y, width, height, rx, ry, settings) { + var args = this._args(arguments, ['x', 'y', 'width', 'height', 'rx', 'ry'], ['rx']); + return this._makeNode(args.parent, 'rect', $.extend( + {x: args.x, y: args.y, width: args.width, height: args.height}, + (args.rx ? {rx: args.rx, ry: args.ry} : {}), args.settings || {})); + }, + + /* Draw a circle. + @param parent (element or jQuery) the parent node for the new shape (optional) + @param cx (number) the x-coordinate for the centre of the circle + @param cy (number) the y-coordinate for the centre of the circle + @param r (number) the radius of the circle + @param settings (object) additional settings for the shape (optional) + @return (element) the new shape node */ + circle: function(parent, cx, cy, r, settings) { + var args = this._args(arguments, ['cx', 'cy', 'r']); + return this._makeNode(args.parent, 'circle', $.extend( + {cx: args.cx, cy: args.cy, r: args.r}, args.settings || {})); + }, + + /* Draw an ellipse. + @param parent (element or jQuery) the parent node for the new shape (optional) + @param cx (number) the x-coordinate for the centre of the ellipse + @param cy (number) the y-coordinate for the centre of the ellipse + @param rx (number) the x-radius of the ellipse + @param ry (number) the y-radius of the ellipse + @param settings (object) additional settings for the shape (optional) + @return (element) the new shape node */ + ellipse: function(parent, cx, cy, rx, ry, settings) { + var args = this._args(arguments, ['cx', 'cy', 'rx', 'ry']); + return this._makeNode(args.parent, 'ellipse', $.extend( + {cx: args.cx, cy: args.cy, rx: args.rx, ry: args.ry}, args.settings || {})); + }, + + /* Draw a line. + @param parent (element or jQuery) the parent node for the new shape (optional) + @param x1 (number) the x-coordinate for the start of the line + @param y1 (number) the y-coordinate for the start of the line + @param x2 (number) the x-coordinate for the end of the line + @param y2 (number) the y-coordinate for the end of the line + @param settings (object) additional settings for the shape (optional) + @return (element) the new shape node */ + line: function(parent, x1, y1, x2, y2, settings) { + var args = this._args(arguments, ['x1', 'y1', 'x2', 'y2']); + return this._makeNode(args.parent, 'line', $.extend( + {x1: args.x1, y1: args.y1, x2: args.x2, y2: args.y2}, args.settings || {})); + }, + + /* Draw a polygonal line. + @param parent (element or jQuery) the parent node for the new shape (optional) + @param points (number[][]) the x-/y-coordinates for the points on the line + @param settings (object) additional settings for the shape (optional) + @return (element) the new shape node */ + polyline: function(parent, points, settings) { + var args = this._args(arguments, ['points']); + return this._poly(args.parent, 'polyline', args.points, args.settings); + }, + + /* Draw a polygonal shape. + @param parent (element or jQuery) the parent node for the new shape (optional) + @param points (number[][]) the x-/y-coordinates for the points on the shape + @param settings (object) additional settings for the shape (optional) + @return (element) the new shape node */ + polygon: function(parent, points, settings) { + var args = this._args(arguments, ['points']); + return this._poly(args.parent, 'polygon', args.points, args.settings); + }, + + /* Draw a polygonal line or shape. */ + _poly: function(parent, name, points, settings) { + var ps = ''; + for (var i = 0; i < points.length; i++) { + ps += points[i].join() + ' '; + } + return this._makeNode(parent, name, $.extend( + {points: $.trim(ps)}, settings || {})); + }, + + /* Draw text. + Specify both of x and y or neither of them. + @param parent (element or jQuery) the parent node for the text (optional) + @param x (number or number[]) the x-coordinate(s) for the text (optional) + @param y (number or number[]) the y-coordinate(s) for the text (optional) + @param value (string) the text content or + (SVGText) text with spans and references + @param settings (object) additional settings for the text (optional) + @return (element) the new text node */ + text: function(parent, x, y, value, settings) { + var args = this._args(arguments, ['x', 'y', 'value']); + if (typeof args.x == 'string' && arguments.length < 4) { + args.value = args.x; + args.settings = args.y; + args.x = args.y = null; + } + return this._text(args.parent, 'text', args.value, $.extend( + {x: (args.x && isArray(args.x) ? args.x.join(' ') : args.x), + y: (args.y && isArray(args.y) ? args.y.join(' ') : args.y)}, + args.settings || {})); + }, + + /* Draw text along a path. + @param parent (element or jQuery) the parent node for the text (optional) + @param path (string) the ID of the path + @param value (string) the text content or + (SVGText) text with spans and references + @param settings (object) additional settings for the text (optional) + @return (element) the new text node */ + textpath: function(parent, path, value, settings) { + var args = this._args(arguments, ['path', 'value']); + var node = this._text(args.parent, 'textPath', args.value, args.settings || {}); + node.setAttributeNS($.svg.xlinkNS, 'href', args.path); + return node; + }, + + /* Draw text. */ + _text: function(parent, name, value, settings) { + var node = this._makeNode(parent, name, settings); + if (typeof value == 'string') { + node.appendChild(node.ownerDocument.createTextNode(value)); + } + else { + for (var i = 0; i < value._parts.length; i++) { + var part = value._parts[i]; + if (part[0] == 'tspan') { + var child = this._makeNode(node, part[0], part[2]); + child.appendChild(node.ownerDocument.createTextNode(part[1])); + node.appendChild(child); + } + else if (part[0] == 'tref') { + var child = this._makeNode(node, part[0], part[2]); + child.setAttributeNS($.svg.xlinkNS, 'href', part[1]); + node.appendChild(child); + } + else if (part[0] == 'textpath') { + var set = $.extend({}, part[2]); + set.href = null; + var child = this._makeNode(node, part[0], set); + child.setAttributeNS($.svg.xlinkNS, 'href', part[2].href); + child.appendChild(node.ownerDocument.createTextNode(part[1])); + node.appendChild(child); + } + else { // straight text + node.appendChild(node.ownerDocument.createTextNode(part[1])); + } + } + } + return node; + }, + + /* Add a custom SVG element. + @param parent (element or jQuery) the parent node for the new element (optional) + @param name (string) the name of the element + @param settings (object) additional settings for the element (optional) + @return (element) the new custom node */ + other: function(parent, name, settings) { + var args = this._args(arguments, ['name']); + return this._makeNode(args.parent, args.name, args.settings || {}); + }, + + /* Create a shape node with the given settings. */ + _makeNode: function(parent, name, settings) { + parent = parent || this._svg; + var node = this._svg.ownerDocument.createElementNS($.svg.svgNS, name); + for (var name in settings) { + var value = settings[name]; + if (value != null && value != null && + (typeof value != 'string' || value != '')) { + node.setAttribute($.svg._attrNames[name] || name, value); + } + } + parent.appendChild(node); + return node; + }, + + /* Add an existing SVG node to the diagram. + @param parent (element or jQuery) the parent node for the new node (optional) + @param node (element) the new node to add or + (string) the jQuery selector for the node or + (jQuery collection) set of nodes to add + @return (SVGWrapper) this wrapper */ + add: function(parent, node) { + var args = this._args((arguments.length == 1 ? [null, parent] : arguments), ['node']); + var svg = this; + args.parent = args.parent || this._svg; + try { + if ($.svg._renesis) { + throw 'Force traversal'; + } + args.parent.appendChild(args.node.cloneNode(true)); + } + catch (e) { + args.node = (args.node.jquery ? args.node : $(args.node)); + args.node.each(function() { + var child = svg._cloneAsSVG(this); + if (child) { + args.parent.appendChild(child); + } + }); + } + return this; + }, + + /* SVG nodes must belong to the SVG namespace, so clone and ensure this is so. */ + _cloneAsSVG: function(node) { + var newNode = null; + if (node.nodeType == 1) { // element + newNode = this._svg.ownerDocument.createElementNS( + $.svg.svgNS, this._checkName(node.nodeName)); + for (var i = 0; i < node.attributes.length; i++) { + var attr = node.attributes.item(i); + if (attr.nodeName != 'xmlns' && attr.nodeValue) { + if (attr.prefix == 'xlink') { + newNode.setAttributeNS($.svg.xlinkNS, attr.localName, attr.nodeValue); + } + else { + newNode.setAttribute(this._checkName(attr.nodeName), attr.nodeValue); + } + } + } + for (var i = 0; i < node.childNodes.length; i++) { + var child = this._cloneAsSVG(node.childNodes[i]); + if (child) { + newNode.appendChild(child); + } + } + } + else if (node.nodeType == 3) { // text + if ($.trim(node.nodeValue)) { + newNode = this._svg.ownerDocument.createTextNode(node.nodeValue); + } + } + else if (node.nodeType == 4) { // CDATA + if ($.trim(node.nodeValue)) { + try { + newNode = this._svg.ownerDocument.createCDATASection(node.nodeValue); + } + catch (e) { + newNode = this._svg.ownerDocument.createTextNode( + node.nodeValue.replace(/&/g, '&'). + replace(/</g, '<').replace(/>/g, '>')); + } + } + } + return newNode; + }, + + /* Node names must be lower case and without SVG namespace prefix. */ + _checkName: function(name) { + name = (name.substring(0, 1) >= 'A' && name.substring(0, 1) <= 'Z' ? + name.toLowerCase() : name); + return (name.substring(0, 4) == 'svg:' ? name.substring(4) : name); + }, + + /* Load an external SVG document. + @param url (string) the location of the SVG document or + the actual SVG content + @param settings (boolean) see addTo below or + (function) see onLoad below or + (object) additional settings for the load with attributes below: + addTo (boolean) true to add to what's already there, + or false to clear the canvas first + changeSize (boolean) true to allow the canvas size to change, + or false to retain the original + onLoad (function) callback after the document has loaded, + 'this' is the container, receives SVG object and + optional error message as a parameter + @return (SVGWrapper) this root */ + load: function(url, settings) { + settings = (typeof settings == 'boolean'? {addTo: settings} : + (typeof settings == 'function'? {onLoad: settings} : settings || {})); + if (!settings.addTo) { + this.clear(false); + } + var size = [this._svg.getAttribute('width'), this._svg.getAttribute('height')]; + var wrapper = this; + // Report a problem with the load + var reportError = function(message) { + message = $.svg.local.errorLoadingText + ': ' + message; + if (settings.onLoad) { + settings.onLoad.apply(wrapper._container || wrapper._svg, [wrapper, message]); + } + else { + wrapper.text(null, 10, 20, message); + } + }; + // Create a DOM from SVG content + var loadXML4IE = function(data) { + var xml = new ActiveXObject('Microsoft.XMLDOM'); + xml.validateOnParse = false; + xml.resolveExternals = false; + xml.async = false; + xml.loadXML(data); + if (xml.parseError.errorCode != 0) { + reportError(xml.parseError.reason); + return null; + } + return xml; + }; + // Load the SVG DOM + var loadSVG = function(data) { + if (!data) { + return; + } + if (data.documentElement.nodeName != 'svg') { + var errors = data.getElementsByTagName('parsererror'); + var messages = (errors.length ? errors[0].getElementsByTagName('div') : []); // Safari + reportError(!errors.length ? '???' : + (messages.length ? messages[0] : errors[0]).firstChild.nodeValue); + return; + } + var attrs = {}; + for (var i = 0; i < data.documentElement.attributes.length; i++) { + var attr = data.documentElement.attributes.item(i); + if (!(attr.nodeName == 'version' || attr.nodeName.substring(0, 5) == 'xmlns')) { + attrs[attr.nodeName] = attr.nodeValue; + } + } + wrapper.configure(attrs, true); + var nodes = data.documentElement.childNodes; + for (var i = 0; i < nodes.length; i++) { + try { + if ($.svg._renesis) { + throw 'Force traversal'; + } + wrapper._svg.appendChild(nodes[i].cloneNode(true)); + if (nodes[i].nodeName == 'script') { + $.globalEval(nodes[i].textContent); + } + } + catch (e) { + wrapper.add(null, nodes[i]); + } + } + if (!settings.changeSize) { + wrapper.configure({width: size[0], height: size[1]}); + } + if (settings.onLoad) { + settings.onLoad.apply(wrapper._container || wrapper._svg, [wrapper]); + } + }; + if (url.match('<svg')) { // Inline SVG + loadSVG($.browser.msie ? loadXML4IE(url) : + new DOMParser().parseFromString(url, 'text/xml')); + } + else { // Remote SVG + $.ajax({url: url, dataType: ($.browser.msie ? 'text' : 'xml'), + success: function(xml) { + loadSVG($.browser.msie ? loadXML4IE(xml) : xml); + }, error: function(http, message, exc) { + reportError(message + (exc ? ' ' + exc.message : '')); + }}); + } + return this; + }, + + /* Delete a specified node. + @param node (element or jQuery) the drawing node to remove + @return (SVGWrapper) this root */ + remove: function(node) { + node = (node.jquery ? node[0] : node); + node.parentNode.removeChild(node); + return this; + }, + + /* Delete everything in the current document. + @param attrsToo (boolean) true to clear any root attributes as well, + false to leave them (optional) + @return (SVGWrapper) this root */ + clear: function(attrsToo) { + if (attrsToo) { + this.configure({}, true); + } + while (this._svg.firstChild) { + this._svg.removeChild(this._svg.firstChild); + } + return this; + }, + + /* Serialise the current diagram into an SVG text document. + @param node (SVG element) the starting node (optional) + @return (string) the SVG as text */ + toSVG: function(node) { + node = node || this._svg; + return (typeof XMLSerializer == 'undefined' ? this._toSVG(node) : + new XMLSerializer().serializeToString(node)); + }, + + /* Serialise one node in the SVG hierarchy. */ + _toSVG: function(node) { + var svgDoc = ''; + if (!node) { + return svgDoc; + } + if (node.nodeType == 3) { // Text + svgDoc = node.nodeValue; + } + else if (node.nodeType == 4) { // CDATA + svgDoc = '<![CDATA[' + node.nodeValue + ']]>'; + } + else { // Element + svgDoc = '<' + node.nodeName; + if (node.attributes) { + for (var i = 0; i < node.attributes.length; i++) { + var attr = node.attributes.item(i); + if (!($.trim(attr.nodeValue) == '' || attr.nodeValue.match(/^\[object/) || + attr.nodeValue.match(/^function/))) { + svgDoc += ' ' + (attr.namespaceURI == $.svg.xlinkNS ? 'xlink:' : '') + + attr.nodeName + '="' + attr.nodeValue + '"'; + } + } + } + if (node.firstChild) { + svgDoc += '>'; + var child = node.firstChild; + while (child) { + svgDoc += this._toSVG(child); + child = child.nextSibling; + } + svgDoc += '</' + node.nodeName + '>'; + } + else { + svgDoc += '/>'; + } + } + return svgDoc; + }, + + /* Escape reserved characters in XML. */ + _escapeXML: function(text) { + text = text.replace(/&/g, '&'); + text = text.replace(/</g, '<'); + text = text.replace(/>/g, '>'); + return text; + } +}); + +/* Helper to generate an SVG path. + Obtain an instance from the SVGWrapper object. + String calls together to generate the path and use its value: + var path = root.createPath(); + root.path(null, path.move(100, 100).line(300, 100).line(200, 300).close(), {fill: 'red'}); + or + root.path(null, path.move(100, 100).line([[300, 100], [200, 300]]).close(), {fill: 'red'}); */ +function SVGPath() { + this._path = ''; +} + +$.extend(SVGPath.prototype, { + /* Prepare to create a new path. + @return (SVGPath) this path */ + reset: function() { + this._path = ''; + return this; + }, + + /* Move the pointer to a position. + @param x (number) x-coordinate to move to or + (number[][]) x-/y-coordinates to move to + @param y (number) y-coordinate to move to (omitted if x is array) + @param relative (boolean) true for coordinates relative to the current point, + false for coordinates being absolute + @return (SVGPath) this path */ + move: function(x, y, relative) { + relative = (isArray(x) ? y : relative); + return this._coords((relative ? 'm' : 'M'), x, y); + }, + + /* Draw a line to a position. + @param x (number) x-coordinate to move to or + (number[][]) x-/y-coordinates to move to + @param y (number) y-coordinate to move to (omitted if x is array) + @param relative (boolean) true for coordinates relative to the current point, + false for coordinates being absolute + @return (SVGPath) this path */ + line: function(x, y, relative) { + relative = (isArray(x) ? y : relative); + return this._coords((relative ? 'l' : 'L'), x, y); + }, + + /* Draw a horizontal line to a position. + @param x (number) x-coordinate to draw to or + (number[]) x-coordinates to draw to + @param relative (boolean) true for coordinates relative to the current point, + false for coordinates being absolute + @return (SVGPath) this path */ + horiz: function(x, relative) { + this._path += (relative ? 'h' : 'H') + (isArray(x) ? x.join(' ') : x); + return this; + }, + + /* Draw a vertical line to a position. + @param y (number) y-coordinate to draw to or + (number[]) y-coordinates to draw to + @param relative (boolean) true for coordinates relative to the current point, + false for coordinates being absolute + @return (SVGPath) this path */ + vert: function(y, relative) { + this._path += (relative ? 'v' : 'V') + (isArray(y) ? y.join(' ') : y); + return this; + }, + + /* Draw a cubic Bézier curve. + @param x1 (number) x-coordinate of beginning control point or + (number[][]) x-/y-coordinates of control and end points to draw to + @param y1 (number) y-coordinate of beginning control point (omitted if x1 is array) + @param x2 (number) x-coordinate of ending control point (omitted if x1 is array) + @param y2 (number) y-coordinate of ending control point (omitted if x1 is array) + @param x (number) x-coordinate of curve end (omitted if x1 is array) + @param y (number) y-coordinate of curve end (omitted if x1 is array) + @param relative (boolean) true for coordinates relative to the current point, + false for coordinates being absolute + @return (SVGPath) this path */ + curveC: function(x1, y1, x2, y2, x, y, relative) { + relative = (isArray(x1) ? y1 : relative); + return this._coords((relative ? 'c' : 'C'), x1, y1, x2, y2, x, y); + }, + + /* Continue a cubic Bézier curve. + Starting control point is the reflection of the previous end control point. + @param x2 (number) x-coordinate of ending control point or + (number[][]) x-/y-coordinates of control and end points to draw to + @param y2 (number) y-coordinate of ending control point (omitted if x2 is array) + @param x (number) x-coordinate of curve end (omitted if x2 is array) + @param y (number) y-coordinate of curve end (omitted if x2 is array) + @param relative (boolean) true for coordinates relative to the current point, + false for coordinates being absolute + @return (SVGPath) this path */ + smoothC: function(x2, y2, x, y, relative) { + relative = (isArray(x2) ? y2 : relative); + return this._coords((relative ? 's' : 'S'), x2, y2, x, y); + }, + + /* Draw a quadratic Bézier curve. + @param x1 (number) x-coordinate of control point or + (number[][]) x-/y-coordinates of control and end points to draw to + @param y1 (number) y-coordinate of control point (omitted if x1 is array) + @param x (number) x-coordinate of curve end (omitted if x1 is array) + @param y (number) y-coordinate of curve end (omitted if x1 is array) + @param relative (boolean) true for coordinates relative to the current point, + false for coordinates being absolute + @return (SVGPath) this path */ + curveQ: function(x1, y1, x, y, relative) { + relative = (isArray(x1) ? y1 : relative); + return this._coords((relative ? 'q' : 'Q'), x1, y1, x, y); + }, + + /* Continue a quadratic Bézier curve. + Control point is the reflection of the previous control point. + @param x (number) x-coordinate of curve end or + (number[][]) x-/y-coordinates of points to draw to + @param y (number) y-coordinate of curve end (omitted if x is array) + @param relative (boolean) true for coordinates relative to the current point, + false for coordinates being absolute + @return (SVGPath) this path */ + smoothQ: function(x, y, relative) { + relative = (isArray(x) ? y : relative); + return this._coords((relative ? 't' : 'T'), x, y); + }, + + /* Generate a path command with (a list of) coordinates. */ + _coords: function(cmd, x1, y1, x2, y2, x3, y3) { + if (isArray(x1)) { + for (var i = 0; i < x1.length; i++) { + var cs = x1[i]; + this._path += (i == 0 ? cmd : ' ') + cs[0] + ',' + cs[1] + + (cs.length < 4 ? '' : ' ' + cs[2] + ',' + cs[3] + + (cs.length < 6 ? '': ' ' + cs[4] + ',' + cs[5])); + } + } + else { + this._path += cmd + x1 + ',' + y1 + + (x2 == null ? '' : ' ' + x2 + ',' + y2 + + (x3 == null ? '' : ' ' + x3 + ',' + y3)); + } + return this; + }, + + /* Draw an arc to a position. + @param rx (number) x-radius of arc or + (number/boolean[][]) x-/y-coordinates and flags for points to draw to + @param ry (number) y-radius of arc (omitted if rx is array) + @param xRotate (number) x-axis rotation (degrees, clockwise) (omitted if rx is array) + @param large (boolean) true to draw the large part of the arc, + false to draw the small part (omitted if rx is array) + @param clockwise (boolean) true to draw the clockwise arc, + false to draw the anti-clockwise arc (omitted if rx is array) + @param x (number) x-coordinate of arc end (omitted if rx is array) + @param y (number) y-coordinate of arc end (omitted if rx is array) + @param relative (boolean) true for coordinates relative to the current point, + false for coordinates being absolute + @return (SVGPath) this path */ + arc: function(rx, ry, xRotate, large, clockwise, x, y, relative) { + relative = (isArray(rx) ? ry : relative); + this._path += (relative ? 'a' : 'A'); + if (isArray(rx)) { + for (var i = 0; i < rx.length; i++) { + var cs = rx[i]; + this._path += (i == 0 ? '' : ' ') + cs[0] + ',' + cs[1] + ' ' + + cs[2] + ' ' + (cs[3] ? '1' : '0') + ',' + + (cs[4] ? '1' : '0') + ' ' + cs[5] + ',' + cs[6]; + } + } + else { + this._path += rx + ',' + ry + ' ' + xRotate + ' ' + + (large ? '1' : '0') + ',' + (clockwise ? '1' : '0') + ' ' + x + ',' + y; + } + return this; + }, + + /* Close the current path. + @return (SVGPath) this path */ + close: function() { + this._path += 'z'; + return this; + }, + + /* Return the string rendering of the specified path. + @return (string) stringified path */ + path: function() { + return this._path; + } +}); + +SVGPath.prototype.moveTo = SVGPath.prototype.move; +SVGPath.prototype.lineTo = SVGPath.prototype.line; +SVGPath.prototype.horizTo = SVGPath.prototype.horiz; +SVGPath.prototype.vertTo = SVGPath.prototype.vert; +SVGPath.prototype.curveCTo = SVGPath.prototype.curveC; +SVGPath.prototype.smoothCTo = SVGPath.prototype.smoothC; +SVGPath.prototype.curveQTo = SVGPath.prototype.curveQ; +SVGPath.prototype.smoothQTo = SVGPath.prototype.smoothQ; +SVGPath.prototype.arcTo = SVGPath.prototype.arc; + +/* Helper to generate an SVG text object. + Obtain an instance from the SVGWrapper object. + String calls together to generate the text and use its value: + var text = root.createText(); + root.text(null, x, y, text.string('This is '). + span('red', {fill: 'red'}).string('!'), {fill: 'blue'}); */ +function SVGText() { + this._parts = []; // The components of the text object +} + +$.extend(SVGText.prototype, { + /* Prepare to create a new text object. + @return (SVGText) this text */ + reset: function() { + this._parts = []; + return this; + }, + + /* Add a straight string value. + @param value (string) the actual text + @return (SVGText) this text object */ + string: function(value) { + this._parts[this._parts.length] = ['text', value]; + return this; + }, + + /* Add a separate text span that has its own settings. + @param value (string) the actual text + @param settings (object) the settings for this text + @return (SVGText) this text object */ + span: function(value, settings) { + this._parts[this._parts.length] = ['tspan', value, settings]; + return this; + }, + + /* Add a reference to a previously defined text string. + @param id (string) the ID of the actual text + @param settings (object) the settings for this text + @return (SVGText) this text object */ + ref: function(id, settings) { + this._parts[this._parts.length] = ['tref', id, settings]; + return this; + }, + + /* Add text drawn along a path. + @param id (string) the ID of the path + @param value (string) the actual text + @param settings (object) the settings for this text + @return (SVGText) this text object */ + path: function(id, value, settings) { + this._parts[this._parts.length] = ['textpath', value, + $.extend({href: id}, settings || {})]; + return this; + } +}); + +/* Attach the SVG functionality to a jQuery selection. + @param command (string) the command to run (optional, default 'attach') + @param options (object) the new settings to use for these SVG instances + @return jQuery (object) for chaining further calls */ +$.fn.svg = function(options) { + var otherArgs = Array.prototype.slice.call(arguments, 1); + if (typeof options == 'string' && options == 'get') { + return $.svg['_' + options + 'SVG'].apply($.svg, [this[0]].concat(otherArgs)); + } + return this.each(function() { + if (typeof options == 'string') { + $.svg['_' + options + 'SVG'].apply($.svg, [this].concat(otherArgs)); + } + else { + $.svg._attachSVG(this, options || {}); + } + }); +}; + +/* Determine whether an object is an array. */ +function isArray(a) { + return (a && a.constructor == Array); +} + +// Singleton primary SVG interface +$.svg = new SVGManager(); + +})(jQuery); diff --git a/hugo/js/jquery/jquery.tablesorter.js b/hugo/js/jquery/jquery.tablesorter.js new file mode 100644 index 0000000..909d947 --- /dev/null +++ b/hugo/js/jquery/jquery.tablesorter.js @@ -0,0 +1,1033 @@ +/* + * + * TableSorter 2.0 - Client-side table sorting with ease! + * Version 2.0.5b + * @requires jQuery v1.2.3 + * + * Copyright (c) 2007 Christian Bach + * Examples and docs at: http://tablesorter.com + * Dual licensed under the MIT and GPL licenses: + * http://www.opensource.org/licenses/mit-license.php + * http://www.gnu.org/licenses/gpl.html + * + */ +/** + * + * @description Create a sortable table with multi-column sorting capabilitys + * + * @example $('table').tablesorter(); + * @desc Create a simple tablesorter interface. + * + * @example $('table').tablesorter({ sortList:[[0,0],[1,0]] }); + * @desc Create a tablesorter interface and sort on the first and secound column column headers. + * + * @example $('table').tablesorter({ headers: { 0: { sorter: false}, 1: {sorter: false} } }); + * + * @desc Create a tablesorter interface and disableing the first and second column headers. + * + * + * @example $('table').tablesorter({ headers: { 0: {sorter:"integer"}, 1: {sorter:"currency"} } }); + * + * @desc Create a tablesorter interface and set a column parser for the first + * and second column. + * + * + * @param Object + * settings An object literal containing key/value pairs to provide + * optional settings. + * + * + * @option String cssHeader (optional) A string of the class name to be appended + * to sortable tr elements in the thead of the table. Default value: + * "header" + * + * @option String cssAsc (optional) A string of the class name to be appended to + * sortable tr elements in the thead on a ascending sort. Default value: + * "headerSortUp" + * + * @option String cssDesc (optional) A string of the class name to be appended + * to sortable tr elements in the thead on a descending sort. Default + * value: "headerSortDown" + * + * @option String sortInitialOrder (optional) A string of the inital sorting + * order can be asc or desc. Default value: "asc" + * + * @option String sortMultisortKey (optional) A string of the multi-column sort + * key. Default value: "shiftKey" + * + * @option String textExtraction (optional) A string of the text-extraction + * method to use. For complex html structures inside td cell set this + * option to "complex", on large tables the complex option can be slow. + * Default value: "simple" + * + * @option Object headers (optional) An array containing the forces sorting + * rules. This option let's you specify a default sorting rule. Default + * value: null + * + * @option Array sortList (optional) An array containing the forces sorting + * rules. This option let's you specify a default sorting rule. Default + * value: null + * + * @option Array sortForce (optional) An array containing forced sorting rules. + * This option let's you specify a default sorting rule, which is + * prepended to user-selected rules. Default value: null + * + * @option Boolean sortLocaleCompare (optional) Boolean flag indicating whatever + * to use String.localeCampare method or not. Default set to true. + * + * + * @option Array sortAppend (optional) An array containing forced sorting rules. + * This option let's you specify a default sorting rule, which is + * appended to user-selected rules. Default value: null + * + * @option Boolean widthFixed (optional) Boolean flag indicating if tablesorter + * should apply fixed widths to the table columns. This is usefull when + * using the pager companion plugin. This options requires the dimension + * jquery plugin. Default value: false + * + * @option Boolean cancelSelection (optional) Boolean flag indicating if + * tablesorter should cancel selection of the table headers text. + * Default value: true + * + * @option Boolean debug (optional) Boolean flag indicating if tablesorter + * should display debuging information usefull for development. + * + * @type jQuery + * + * @name tablesorter + * + * @cat Plugins/Tablesorter + * + * @author Christian Bach/christian.bach@polyester.se + */ + +(function ($) { + $.extend({ + tablesorter: new + function () { + + var parsers = [], + widgets = []; + + this.defaults = { + cssHeader: "header", + cssAsc: "headerSortUp", + cssDesc: "headerSortDown", + cssChildRow: "expand-child", + sortInitialOrder: "asc", + sortMultiSortKey: "shiftKey", + sortForce: null, + sortAppend: null, + sortLocaleCompare: true, + textExtraction: "simple", + parsers: {}, widgets: [], + widgetZebra: { + css: ["even", "odd"] + }, headers: {}, widthFixed: false, + cancelSelection: true, + sortList: [], + headerList: [], + dateFormat: "us", + decimal: '/\.|\,/g', + onRenderHeader: null, + selectorHeaders: 'thead th', + debug: false + }; + + /* debuging utils */ + + function benchmark(s, d) { + log(s + "," + (new Date().getTime() - d.getTime()) + "ms"); + } + + this.benchmark = benchmark; + + function log(s) { + if (typeof console != "undefined" && typeof console.debug != "undefined") { + console.log(s); + } else { + alert(s); + } + } + + /* parsers utils */ + + function buildParserCache(table, $headers) { + + if (table.config.debug) { + var parsersDebug = ""; + } + + if (table.tBodies.length == 0) return; // In the case of empty tables + var rows = table.tBodies[0].rows; + + if (rows[0]) { + + var list = [], + cells = rows[0].cells, + l = cells.length; + + for (var i = 0; i < l; i++) { + + var p = false; + + if ($.metadata && ($($headers[i]).metadata() && $($headers[i]).metadata().sorter)) { + + p = getParserById($($headers[i]).metadata().sorter); + + } else if ((table.config.headers[i] && table.config.headers[i].sorter)) { + + p = getParserById(table.config.headers[i].sorter); + } + if (!p) { + + p = detectParserForColumn(table, rows, -1, i); + } + + if (table.config.debug) { + parsersDebug += "column:" + i + " parser:" + p.id + "\n"; + } + + list.push(p); + } + } + + if (table.config.debug) { + log(parsersDebug); + } + + return list; + }; + + function detectParserForColumn(table, rows, rowIndex, cellIndex) { + var l = parsers.length, + node = false, + nodeValue = false, + keepLooking = true; + while (nodeValue == '' && keepLooking) { + rowIndex++; + if (rows[rowIndex]) { + node = getNodeFromRowAndCellIndex(rows, rowIndex, cellIndex); + nodeValue = trimAndGetNodeText(table.config, node); + if (table.config.debug) { + log('Checking if value was empty on row:' + rowIndex); + } + } else { + keepLooking = false; + } + } + for (var i = 1; i < l; i++) { + if (parsers[i].is(nodeValue, table, node)) { + return parsers[i]; + } + } + // 0 is always the generic parser (text) + return parsers[0]; + } + + function getNodeFromRowAndCellIndex(rows, rowIndex, cellIndex) { + return rows[rowIndex].cells[cellIndex]; + } + + function trimAndGetNodeText(config, node) { + return $.trim(getElementText(config, node)); + } + + function getParserById(name) { + var l = parsers.length; + for (var i = 0; i < l; i++) { + if (parsers[i].id.toLowerCase() == name.toLowerCase()) { + return parsers[i]; + } + } + return false; + } + + /* utils */ + + function buildCache(table) { + + if (table.config.debug) { + var cacheTime = new Date(); + } + + var totalRows = (table.tBodies[0] && table.tBodies[0].rows.length) || 0, + totalCells = (table.tBodies[0].rows[0] && table.tBodies[0].rows[0].cells.length) || 0, + parsers = table.config.parsers, + cache = { + row: [], + normalized: [] + }; + + for (var i = 0; i < totalRows; ++i) { + + /** Add the table data to main data array */ + var c = $(table.tBodies[0].rows[i]), + cols = []; + + // if this is a child row, add it to the last row's children and + // continue to the next row + if (c.hasClass(table.config.cssChildRow)) { + cache.row[cache.row.length - 1] = cache.row[cache.row.length - 1].add(c); + // go to the next for loop + continue; + } + + cache.row.push(c); + + for (var j = 0; j < totalCells; ++j) { + cols.push(parsers[j].format(getElementText(table.config, c[0].cells[j]), table, c[0].cells[j])); + } + + cols.push(cache.normalized.length); // add position for rowCache + cache.normalized.push(cols); + cols = null; + }; + + if (table.config.debug) { + benchmark("Building cache for " + totalRows + " rows:", cacheTime); + } + + return cache; + }; + + function getElementText(config, node) { + + var text = ""; + + if (!node) return ""; + + if (!config.supportsTextContent) config.supportsTextContent = node.textContent || false; + + if (config.textExtraction == "simple") { + if (config.supportsTextContent) { + text = node.textContent; + } else { + if (node.childNodes[0] && node.childNodes[0].hasChildNodes()) { + text = node.childNodes[0].innerHTML; + } else { + text = node.innerHTML; + } + } + } else { + if (typeof(config.textExtraction) == "function") { + text = config.textExtraction(node); + } else { + text = $(node).text(); + } + } + return text; + } + + function appendToTable(table, cache) { + + if (table.config.debug) { + var appendTime = new Date() + } + + var c = cache, + r = c.row, + n = c.normalized, + totalRows = n.length, + checkCell = (n[0].length - 1), + tableBody = $(table.tBodies[0]), + rows = []; + + + for (var i = 0; i < totalRows; i++) { + var pos = n[i][checkCell]; + + rows.push(r[pos]); + + if (!table.config.appender) { + + //var o = ; + var l = r[pos].length; + for (var j = 0; j < l; j++) { + tableBody[0].appendChild(r[pos][j]); + } + + // + } + } + + + + if (table.config.appender) { + + table.config.appender(table, rows); + } + + rows = null; + + if (table.config.debug) { + benchmark("Rebuilt table:", appendTime); + } + + // apply table widgets + applyWidget(table); + + // trigger sortend + setTimeout(function () { + $(table).trigger("sortEnd"); + }, 0); + + }; + + function buildHeaders(table) { + + if (table.config.debug) { + var time = new Date(); + } + + var meta = ($.metadata) ? true : false; + + var header_index = computeTableHeaderCellIndexes(table); + + $tableHeaders = $(table.config.selectorHeaders, table).each(function (index) { + + this.column = header_index[this.parentNode.rowIndex + "-" + this.cellIndex]; + // this.column = index; + this.order = formatSortingOrder(table.config.sortInitialOrder); + + + this.count = this.order; + + if (checkHeaderMetadata(this) || checkHeaderOptions(table, index)) this.sortDisabled = true; + if (checkHeaderOptionsSortingLocked(table, index)) this.order = this.lockedOrder = checkHeaderOptionsSortingLocked(table, index); + + if (!this.sortDisabled) { + var $th = $(this).addClass(table.config.cssHeader); + if (table.config.onRenderHeader) table.config.onRenderHeader.apply($th); + } + + // add cell to headerList + table.config.headerList[index] = this; + }); + + if (table.config.debug) { + benchmark("Built headers:", time); + log($tableHeaders); + } + + return $tableHeaders; + + }; + + // from: + // http://www.javascripttoolbox.com/lib/table/examples.php + // http://www.javascripttoolbox.com/temp/table_cellindex.html + + + function computeTableHeaderCellIndexes(t) { + var matrix = []; + var lookup = {}; + var thead = t.getElementsByTagName('THEAD')[0]; + var trs = thead.getElementsByTagName('TR'); + + for (var i = 0; i < trs.length; i++) { + var cells = trs[i].cells; + for (var j = 0; j < cells.length; j++) { + var c = cells[j]; + + var rowIndex = c.parentNode.rowIndex; + var cellId = rowIndex + "-" + c.cellIndex; + var rowSpan = c.rowSpan || 1; + var colSpan = c.colSpan || 1 + var firstAvailCol; + if (typeof(matrix[rowIndex]) == "undefined") { + matrix[rowIndex] = []; + } + // Find first available column in the first row + for (var k = 0; k < matrix[rowIndex].length + 1; k++) { + if (typeof(matrix[rowIndex][k]) == "undefined") { + firstAvailCol = k; + break; + } + } + lookup[cellId] = firstAvailCol; + for (var k = rowIndex; k < rowIndex + rowSpan; k++) { + if (typeof(matrix[k]) == "undefined") { + matrix[k] = []; + } + var matrixrow = matrix[k]; + for (var l = firstAvailCol; l < firstAvailCol + colSpan; l++) { + matrixrow[l] = "x"; + } + } + } + } + return lookup; + } + + function checkCellColSpan(table, rows, row) { + var arr = [], + r = table.tHead.rows, + c = r[row].cells; + + for (var i = 0; i < c.length; i++) { + var cell = c[i]; + + if (cell.colSpan > 1) { + arr = arr.concat(checkCellColSpan(table, headerArr, row++)); + } else { + if (table.tHead.length == 1 || (cell.rowSpan > 1 || !r[row + 1])) { + arr.push(cell); + } + // headerArr[row] = (i+row); + } + } + return arr; + }; + + function checkHeaderMetadata(cell) { + if (($.metadata) && ($(cell).metadata().sorter === false)) { + return true; + }; + return false; + } + + function checkHeaderOptions(table, i) { + if ((table.config.headers[i]) && (table.config.headers[i].sorter === false)) { + return true; + }; + return false; + } + + function checkHeaderOptionsSortingLocked(table, i) { + if ((table.config.headers[i]) && (table.config.headers[i].lockedOrder)) return table.config.headers[i].lockedOrder; + return false; + } + + function applyWidget(table) { + var c = table.config.widgets; + var l = c.length; + for (var i = 0; i < l; i++) { + + getWidgetById(c[i]).format(table); + } + + } + + function getWidgetById(name) { + var l = widgets.length; + for (var i = 0; i < l; i++) { + if (widgets[i].id.toLowerCase() == name.toLowerCase()) { + return widgets[i]; + } + } + }; + + function formatSortingOrder(v) { + if (typeof(v) != "Number") { + return (v.toLowerCase() == "desc") ? 1 : 0; + } else { + return (v == 1) ? 1 : 0; + } + } + + function isValueInArray(v, a) { + var l = a.length; + for (var i = 0; i < l; i++) { + if (a[i][0] == v) { + return true; + } + } + return false; + } + + function setHeadersCss(table, $headers, list, css) { + // remove all header information + $headers.removeClass(css[0]).removeClass(css[1]); + + var h = []; + $headers.each(function (offset) { + if (!this.sortDisabled) { + h[this.column] = $(this); + } + }); + + var l = list.length; + for (var i = 0; i < l; i++) { + h[list[i][0]].addClass(css[list[i][1]]); + } + } + + function fixColumnWidth(table, $headers) { + var c = table.config; + if (c.widthFixed) { + var colgroup = $('<colgroup>'); + $("tr:first td", table.tBodies[0]).each(function () { + colgroup.append($('<col>').css('width', $(this).width())); + }); + $(table).prepend(colgroup); + }; + } + + function updateHeaderSortCount(table, sortList) { + var c = table.config, + l = sortList.length; + for (var i = 0; i < l; i++) { + var s = sortList[i], + o = c.headerList[s[0]]; + o.count = s[1]; + o.count++; + } + } + + /* sorting methods */ + + function multisort(table, sortList, cache) { + + if (table.config.debug) { + var sortTime = new Date(); + } + + var dynamicExp = "var sortWrapper = function(a,b) {", + l = sortList.length; + + // TODO: inline functions. + for (var i = 0; i < l; i++) { + + var c = sortList[i][0]; + var order = sortList[i][1]; + // var s = (getCachedSortType(table.config.parsers,c) == "text") ? + // ((order == 0) ? "sortText" : "sortTextDesc") : ((order == 0) ? + // "sortNumeric" : "sortNumericDesc"); + // var s = (table.config.parsers[c].type == "text") ? ((order == 0) + // ? makeSortText(c) : makeSortTextDesc(c)) : ((order == 0) ? + // makeSortNumeric(c) : makeSortNumericDesc(c)); + var s = (table.config.parsers[c].type == "text") ? ((order == 0) ? makeSortFunction("text", "asc", c) : makeSortFunction("text", "desc", c)) : ((order == 0) ? makeSortFunction("numeric", "asc", c) : makeSortFunction("numeric", "desc", c)); + var e = "e" + i; + + dynamicExp += "var " + e + " = " + s; // + "(a[" + c + "],b[" + c + // + "]); "; + dynamicExp += "if(" + e + ") { return " + e + "; } "; + dynamicExp += "else { "; + + } + + // if value is the same keep orignal order + var orgOrderCol = cache.normalized[0].length - 1; + dynamicExp += "return a[" + orgOrderCol + "]-b[" + orgOrderCol + "];"; + + for (var i = 0; i < l; i++) { + dynamicExp += "}; "; + } + + dynamicExp += "return 0; "; + dynamicExp += "}; "; + + if (table.config.debug) { + benchmark("Evaling expression:" + dynamicExp, new Date()); + } + + eval(dynamicExp); + + cache.normalized.sort(sortWrapper); + + if (table.config.debug) { + benchmark("Sorting on " + sortList.toString() + " and dir " + order + " time:", sortTime); + } + + return cache; + }; + + function makeSortFunction(type, direction, index) { + var a = "a[" + index + "]", + b = "b[" + index + "]"; + if (type == 'text' && direction == 'asc') { + return "(" + a + " == " + b + " ? 0 : (" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : (" + a + " < " + b + ") ? -1 : 1 )));"; + } else if (type == 'text' && direction == 'desc') { + return "(" + a + " == " + b + " ? 0 : (" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : (" + b + " < " + a + ") ? -1 : 1 )));"; + } else if (type == 'numeric' && direction == 'asc') { + return "(" + a + " === null && " + b + " === null) ? 0 :(" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : " + a + " - " + b + "));"; + } else if (type == 'numeric' && direction == 'desc') { + return "(" + a + " === null && " + b + " === null) ? 0 :(" + a + " === null ? Number.POSITIVE_INFINITY : (" + b + " === null ? Number.NEGATIVE_INFINITY : " + b + " - " + a + "));"; + } + }; + + function makeSortText(i) { + return "((a[" + i + "] < b[" + i + "]) ? -1 : ((a[" + i + "] > b[" + i + "]) ? 1 : 0));"; + }; + + function makeSortTextDesc(i) { + return "((b[" + i + "] < a[" + i + "]) ? -1 : ((b[" + i + "] > a[" + i + "]) ? 1 : 0));"; + }; + + function makeSortNumeric(i) { + return "a[" + i + "]-b[" + i + "];"; + }; + + function makeSortNumericDesc(i) { + return "b[" + i + "]-a[" + i + "];"; + }; + + function sortText(a, b) { + if (table.config.sortLocaleCompare) return a.localeCompare(b); + return ((a < b) ? -1 : ((a > b) ? 1 : 0)); + }; + + function sortTextDesc(a, b) { + if (table.config.sortLocaleCompare) return b.localeCompare(a); + return ((b < a) ? -1 : ((b > a) ? 1 : 0)); + }; + + function sortNumeric(a, b) { + return a - b; + }; + + function sortNumericDesc(a, b) { + return b - a; + }; + + function getCachedSortType(parsers, i) { + return parsers[i].type; + }; /* public methods */ + this.construct = function (settings) { + return this.each(function () { + // if no thead or tbody quit. + if (!this.tHead || !this.tBodies) return; + // declare + var $this, $document, $headers, cache, config, shiftDown = 0, + sortOrder; + // new blank config object + this.config = {}; + // merge and extend. + config = $.extend(this.config, $.tablesorter.defaults, settings); + // store common expression for speed + $this = $(this); + // save the settings where they read + $.data(this, "tablesorter", config); + // build headers + $headers = buildHeaders(this); + // try to auto detect column type, and store in tables config + this.config.parsers = buildParserCache(this, $headers); + // build the cache for the tbody cells + cache = buildCache(this); + // get the css class names, could be done else where. + var sortCSS = [config.cssDesc, config.cssAsc]; + // fixate columns if the users supplies the fixedWidth option + fixColumnWidth(this); + // apply event handling to headers + // this is to big, perhaps break it out? + $headers.click( + + function (e) { + var totalRows = ($this[0].tBodies[0] && $this[0].tBodies[0].rows.length) || 0; + if (!this.sortDisabled && totalRows > 0) { + // Only call sortStart if sorting is + // enabled. + $this.trigger("sortStart"); + // store exp, for speed + var $cell = $(this); + // get current column index + var i = this.column; + // get current column sort order + this.order = this.count++ % 2; + // always sort on the locked order. + if(this.lockedOrder) this.order = this.lockedOrder; + + // user only whants to sort on one + // column + if (!e[config.sortMultiSortKey]) { + // flush the sort list + config.sortList = []; + if (config.sortForce != null) { + var a = config.sortForce; + for (var j = 0; j < a.length; j++) { + if (a[j][0] != i) { + config.sortList.push(a[j]); + } + } + } + // add column to sort list + config.sortList.push([i, this.order]); + // multi column sorting + } else { + // the user has clicked on an all + // ready sortet column. + if (isValueInArray(i, config.sortList)) { + // revers the sorting direction + // for all tables. + for (var j = 0; j < config.sortList.length; j++) { + var s = config.sortList[j], + o = config.headerList[s[0]]; + if (s[0] == i) { + o.count = s[1]; + o.count++; + s[1] = o.count % 2; + } + } + } else { + // add column to sort list array + config.sortList.push([i, this.order]); + } + }; + setTimeout(function () { + // set css for headers + setHeadersCss($this[0], $headers, config.sortList, sortCSS); + appendToTable( + $this[0], multisort( + $this[0], config.sortList, cache) + ); + }, 1); + // stop normal event by returning false + return false; + } + // cancel selection + }).mousedown(function () { + if (config.cancelSelection) { + this.onselectstart = function () { + return false + }; + return false; + } + }); + // apply easy methods that trigger binded events + $this.bind("update", function () { + var me = this; + setTimeout(function () { + // rebuild parsers. + me.config.parsers = buildParserCache( + me, $headers); + // rebuild the cache map + cache = buildCache(me); + }, 1); + }).bind("updateCell", function (e, cell) { + var config = this.config; + // get position from the dom. + var pos = [(cell.parentNode.rowIndex - 1), cell.cellIndex]; + // update cache + cache.normalized[pos[0]][pos[1]] = config.parsers[pos[1]].format( + getElementText(config, cell), cell); + }).bind("sorton", function (e, list) { + $(this).trigger("sortStart"); + config.sortList = list; + // update and store the sortlist + var sortList = config.sortList; + // update header count index + updateHeaderSortCount(this, sortList); + // set css for headers + setHeadersCss(this, $headers, sortList, sortCSS); + // sort the table and append it to the dom + appendToTable(this, multisort(this, sortList, cache)); + }).bind("appendCache", function () { + appendToTable(this, cache); + }).bind("applyWidgetId", function (e, id) { + getWidgetById(id).format(this); + }).bind("applyWidgets", function () { + // apply widgets + applyWidget(this); + }); + if ($.metadata && ($(this).metadata() && $(this).metadata().sortlist)) { + config.sortList = $(this).metadata().sortlist; + } + // if user has supplied a sort list to constructor. + if (config.sortList.length > 0) { + $this.trigger("sorton", [config.sortList]); + } else { + // appendToTable used in sorton event already calls applyWidget + // apply widgets + applyWidget(this); + } + }); + }; + this.addParser = function (parser) { + var l = parsers.length, + a = true; + for (var i = 0; i < l; i++) { + if (parsers[i].id.toLowerCase() == parser.id.toLowerCase()) { + a = false; + } + } + if (a) { + parsers.push(parser); + }; + }; + this.addWidget = function (widget) { + widgets.push(widget); + }; + this.formatFloat = function (s) { + var i = parseFloat(s); + return (isNaN(i)) ? 0 : i; + }; + this.formatInt = function (s) { + var i = parseInt(s); + return (isNaN(i)) ? 0 : i; + }; + this.isDigit = function (s, config) { + // replace all an wanted chars and match. + return /^[-+]?\d*$/.test($.trim(s.replace(/[,.']/g, ''))); + }; + this.clearTableBody = function (table) { + if ($.browser.msie) { + function empty() { + while (this.firstChild) + this.removeChild(this.firstChild); + } + empty.apply(table.tBodies[0]); + } else { + table.tBodies[0].innerHTML = ""; + } + }; + } + }); + + // extend plugin scope + $.fn.extend({ + tablesorter: $.tablesorter.construct + }); + + // make shortcut + var ts = $.tablesorter; + + // add default parsers + ts.addParser({ + id: "text", + is: function (s) { + return true; + }, format: function (s) { + return $.trim(s.toLocaleLowerCase()); + }, type: "text" + }); + + ts.addParser({ + id: "digit", + is: function (s, table) { + var c = table.config; + return $.tablesorter.isDigit(s, c); + }, format: function (s) { + return $.tablesorter.formatFloat(s); + }, type: "numeric" + }); + + ts.addParser({ + id: "currency", + is: function (s) { + return /^[£$€?.]/.test(s); + }, format: function (s) { + return $.tablesorter.formatFloat(s.replace(new RegExp(/[£$€]/g), "")); + }, type: "numeric" + }); + + ts.addParser({ + id: "ipAddress", + is: function (s) { + return /^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s); + }, format: function (s) { + var a = s.split("."), + r = "", + l = a.length; + for (var i = 0; i < l; i++) { + var item = a[i]; + if (item.length == 2) { + r += "0" + item; + } else { + r += item; + } + } + return $.tablesorter.formatFloat(r); + }, type: "numeric" + }); + + ts.addParser({ + id: "url", + is: function (s) { + return /^(https?|ftp|file):\/\/$/.test(s); + }, format: function (s) { + return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//), '')); + }, type: "text" + }); + + ts.addParser({ + id: "isoDate", + is: function (s) { + return /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s); + }, format: function (s) { + return $.tablesorter.formatFloat((s != "") ? new Date(s.replace( + new RegExp(/-/g), "/")).getTime() : "0"); + }, type: "numeric" + }); + + ts.addParser({ + id: "percent", + is: function (s) { + return /\%$/.test($.trim(s)); + }, format: function (s) { + return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g), "")); + }, type: "numeric" + }); + + ts.addParser({ + id: "usLongDate", + is: function (s) { + return s.match(new RegExp(/^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/)); + }, format: function (s) { + return $.tablesorter.formatFloat(new Date(s).getTime()); + }, type: "numeric" + }); + + ts.addParser({ + id: "shortDate", + is: function (s) { + return /\d{1,2}[\/\-]\d{1,2}[\/\-]\d{2,4}/.test(s); + }, format: function (s, table) { + var c = table.config; + s = s.replace(/\-/g, "/"); + if (c.dateFormat == "us") { + // reformat the string in ISO format + s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$1/$2"); + } else if (c.dateFormat == "uk") { + // reformat the string in ISO format + s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{4})/, "$3/$2/$1"); + } else if (c.dateFormat == "dd/mm/yy" || c.dateFormat == "dd-mm-yy") { + s = s.replace(/(\d{1,2})[\/\-](\d{1,2})[\/\-](\d{2})/, "$1/$2/$3"); + } + return $.tablesorter.formatFloat(new Date(s).getTime()); + }, type: "numeric" + }); + ts.addParser({ + id: "time", + is: function (s) { + return /^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s); + }, format: function (s) { + return $.tablesorter.formatFloat(new Date("2000/01/01 " + s).getTime()); + }, type: "numeric" + }); + ts.addParser({ + id: "metadata", + is: function (s) { + return false; + }, format: function (s, table, cell) { + var c = table.config, + p = (!c.parserMetadataName) ? 'sortValue' : c.parserMetadataName; + return $(cell).metadata()[p]; + }, type: "numeric" + }); + // add default widgets + ts.addWidget({ + id: "zebra", + format: function (table) { + if (table.config.debug) { + var time = new Date(); + } + var $tr, row = -1, + odd; + // loop through the visible rows + $("tr:visible", table.tBodies[0]).each(function (i) { + $tr = $(this); + // style children rows the same way the parent + // row was styled + if (!$tr.hasClass(table.config.cssChildRow)) row++; + odd = (row % 2 == 0); + $tr.removeClass( + table.config.widgetZebra.css[odd ? 0 : 1]).addClass( + table.config.widgetZebra.css[odd ? 1 : 0]) + }); + if (table.config.debug) { + $.tablesorter.benchmark("Applying Zebra widget", time); + } + } + }); +})(jQuery);
\ No newline at end of file diff --git a/hugo/js/jquery/src/README b/hugo/js/jquery/src/README new file mode 100644 index 0000000..afd8a97 --- /dev/null +++ b/hugo/js/jquery/src/README @@ -0,0 +1,4 @@ +jQuery and jQuery UI source +=========================== + +This directory contains source code for jQuery and jQuery UI. diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.accordion.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.accordion.js new file mode 100644 index 0000000..78c9575 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.accordion.js @@ -0,0 +1,731 @@ +/*! + * jQuery UI Accordion @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/accordion/ + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +var uid = 0, + hideProps = {}, + showProps = {}; + +hideProps.height = hideProps.paddingTop = hideProps.paddingBottom = + hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide"; +showProps.height = showProps.paddingTop = showProps.paddingBottom = + showProps.borderTopWidth = showProps.borderBottomWidth = "show"; + +$.widget( "ui.accordion", { + version: "@VERSION", + options: { + active: 0, + animate: {}, + collapsible: false, + event: "click", + header: "> li > :first-child,> :not(li):even", + heightStyle: "auto", + icons: { + activeHeader: "ui-icon-triangle-1-s", + header: "ui-icon-triangle-1-e" + }, + + // callbacks + activate: null, + beforeActivate: null + }, + + _create: function() { + var accordionId = this.accordionId = "ui-accordion-" + + (this.element.attr( "id" ) || ++uid), + options = this.options; + + this.prevShow = this.prevHide = $(); + this.element.addClass( "ui-accordion ui-widget ui-helper-reset" ); + + this.headers = this.element.find( options.header ) + .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" ); + this._hoverable( this.headers ); + this._focusable( this.headers ); + + this.headers.next() + .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" ) + .hide(); + + // don't allow collapsible: false and active: false / null + if ( !options.collapsible && (options.active === false || options.active == null) ) { + options.active = 0; + } + // handle negative values + if ( options.active < 0 ) { + options.active += this.headers.length; + } + this.active = this._findActive( options.active ) + .addClass( "ui-accordion-header-active ui-state-active" ) + .toggleClass( "ui-corner-all ui-corner-top" ); + this.active.next() + .addClass( "ui-accordion-content-active" ) + .show(); + + this._createIcons(); + this.refresh(); + + // ARIA + this.element.attr( "role", "tablist" ); + + this.headers + .attr( "role", "tab" ) + .each(function( i ) { + var header = $( this ), + headerId = header.attr( "id" ), + panel = header.next(), + panelId = panel.attr( "id" ); + if ( !headerId ) { + headerId = accordionId + "-header-" + i; + header.attr( "id", headerId ); + } + if ( !panelId ) { + panelId = accordionId + "-panel-" + i; + panel.attr( "id", panelId ); + } + header.attr( "aria-controls", panelId ); + panel.attr( "aria-labelledby", headerId ); + }) + .next() + .attr( "role", "tabpanel" ); + + this.headers + .not( this.active ) + .attr({ + "aria-selected": "false", + tabIndex: -1 + }) + .next() + .attr({ + "aria-expanded": "false", + "aria-hidden": "true" + }) + .hide(); + + // make sure at least one header is in the tab order + if ( !this.active.length ) { + this.headers.eq( 0 ).attr( "tabIndex", 0 ); + } else { + this.active.attr({ + "aria-selected": "true", + tabIndex: 0 + }) + .next() + .attr({ + "aria-expanded": "true", + "aria-hidden": "false" + }); + } + + this._on( this.headers, { keydown: "_keydown" }); + this._on( this.headers.next(), { keydown: "_panelKeyDown" }); + this._setupEvents( options.event ); + }, + + _getCreateEventData: function() { + return { + header: this.active, + content: !this.active.length ? $() : this.active.next() + }; + }, + + _createIcons: function() { + var icons = this.options.icons; + if ( icons ) { + $( "<span>" ) + .addClass( "ui-accordion-header-icon ui-icon " + icons.header ) + .prependTo( this.headers ); + this.active.children( ".ui-accordion-header-icon" ) + .removeClass( icons.header ) + .addClass( icons.activeHeader ); + this.headers.addClass( "ui-accordion-icons" ); + } + }, + + _destroyIcons: function() { + this.headers + .removeClass( "ui-accordion-icons" ) + .children( ".ui-accordion-header-icon" ) + .remove(); + }, + + _destroy: function() { + var contents; + + // clean up main element + this.element + .removeClass( "ui-accordion ui-widget ui-helper-reset" ) + .removeAttr( "role" ); + + // clean up headers + this.headers + .removeClass( "ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" ) + .removeAttr( "role" ) + .removeAttr( "aria-selected" ) + .removeAttr( "aria-controls" ) + .removeAttr( "tabIndex" ) + .each(function() { + if ( /^ui-accordion/.test( this.id ) ) { + this.removeAttribute( "id" ); + } + }); + this._destroyIcons(); + + // clean up content panels + contents = this.headers.next() + .css( "display", "" ) + .removeAttr( "role" ) + .removeAttr( "aria-expanded" ) + .removeAttr( "aria-hidden" ) + .removeAttr( "aria-labelledby" ) + .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" ) + .each(function() { + if ( /^ui-accordion/.test( this.id ) ) { + this.removeAttribute( "id" ); + } + }); + if ( this.options.heightStyle !== "content" ) { + contents.css( "height", "" ); + } + }, + + _setOption: function( key, value ) { + if ( key === "active" ) { + // _activate() will handle invalid values and update this.options + this._activate( value ); + return; + } + + if ( key === "event" ) { + if ( this.options.event ) { + this._off( this.headers, this.options.event ); + } + this._setupEvents( value ); + } + + this._super( key, value ); + + // setting collapsible: false while collapsed; open first panel + if ( key === "collapsible" && !value && this.options.active === false ) { + this._activate( 0 ); + } + + if ( key === "icons" ) { + this._destroyIcons(); + if ( value ) { + this._createIcons(); + } + } + + // #5332 - opacity doesn't cascade to positioned elements in IE + // so we need to add the disabled class to the headers and panels + if ( key === "disabled" ) { + this.headers.add( this.headers.next() ) + .toggleClass( "ui-state-disabled", !!value ); + } + }, + + _keydown: function( event ) { + if ( event.altKey || event.ctrlKey ) { + return; + } + + var keyCode = $.ui.keyCode, + length = this.headers.length, + currentIndex = this.headers.index( event.target ), + toFocus = false; + + switch ( event.keyCode ) { + case keyCode.RIGHT: + case keyCode.DOWN: + toFocus = this.headers[ ( currentIndex + 1 ) % length ]; + break; + case keyCode.LEFT: + case keyCode.UP: + toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; + break; + case keyCode.SPACE: + case keyCode.ENTER: + this._eventHandler( event ); + break; + case keyCode.HOME: + toFocus = this.headers[ 0 ]; + break; + case keyCode.END: + toFocus = this.headers[ length - 1 ]; + break; + } + + if ( toFocus ) { + $( event.target ).attr( "tabIndex", -1 ); + $( toFocus ).attr( "tabIndex", 0 ); + toFocus.focus(); + event.preventDefault(); + } + }, + + _panelKeyDown : function( event ) { + if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { + $( event.currentTarget ).prev().focus(); + } + }, + + refresh: function() { + var maxHeight, overflow, + heightStyle = this.options.heightStyle, + parent = this.element.parent(); + + + if ( heightStyle === "fill" ) { + // IE 6 treats height like minHeight, so we need to turn off overflow + // in order to get a reliable height + // we use the minHeight support test because we assume that only + // browsers that don't support minHeight will treat height as minHeight + if ( !$.support.minHeight ) { + overflow = parent.css( "overflow" ); + parent.css( "overflow", "hidden"); + } + maxHeight = parent.height(); + this.element.siblings( ":visible" ).each(function() { + var elem = $( this ), + position = elem.css( "position" ); + + if ( position === "absolute" || position === "fixed" ) { + return; + } + maxHeight -= elem.outerHeight( true ); + }); + if ( overflow ) { + parent.css( "overflow", overflow ); + } + + this.headers.each(function() { + maxHeight -= $( this ).outerHeight( true ); + }); + + this.headers.next() + .each(function() { + $( this ).height( Math.max( 0, maxHeight - + $( this ).innerHeight() + $( this ).height() ) ); + }) + .css( "overflow", "auto" ); + } else if ( heightStyle === "auto" ) { + maxHeight = 0; + this.headers.next() + .each(function() { + maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); + }) + .height( maxHeight ); + } + }, + + _activate: function( index ) { + var active = this._findActive( index )[ 0 ]; + + // trying to activate the already active panel + if ( active === this.active[ 0 ] ) { + return; + } + + // trying to collapse, simulate a click on the currently active header + active = active || this.active[ 0 ]; + + this._eventHandler({ + target: active, + currentTarget: active, + preventDefault: $.noop + }); + }, + + _findActive: function( selector ) { + return typeof selector === "number" ? this.headers.eq( selector ) : $(); + }, + + _setupEvents: function( event ) { + var events = {}; + if ( !event ) { + return; + } + $.each( event.split(" "), function( index, eventName ) { + events[ eventName ] = "_eventHandler"; + }); + this._on( this.headers, events ); + }, + + _eventHandler: function( event ) { + var options = this.options, + active = this.active, + clicked = $( event.currentTarget ), + clickedIsActive = clicked[ 0 ] === active[ 0 ], + collapsing = clickedIsActive && options.collapsible, + toShow = collapsing ? $() : clicked.next(), + toHide = active.next(), + eventData = { + oldHeader: active, + oldPanel: toHide, + newHeader: collapsing ? $() : clicked, + newPanel: toShow + }; + + event.preventDefault(); + + if ( + // click on active header, but not collapsible + ( clickedIsActive && !options.collapsible ) || + // allow canceling activation + ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { + return; + } + + options.active = collapsing ? false : this.headers.index( clicked ); + + // when the call to ._toggle() comes after the class changes + // it causes a very odd bug in IE 8 (see #6720) + this.active = clickedIsActive ? $() : clicked; + this._toggle( eventData ); + + // switch classes + // corner classes on the previously active header stay after the animation + active.removeClass( "ui-accordion-header-active ui-state-active" ); + if ( options.icons ) { + active.children( ".ui-accordion-header-icon" ) + .removeClass( options.icons.activeHeader ) + .addClass( options.icons.header ); + } + + if ( !clickedIsActive ) { + clicked + .removeClass( "ui-corner-all" ) + .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" ); + if ( options.icons ) { + clicked.children( ".ui-accordion-header-icon" ) + .removeClass( options.icons.header ) + .addClass( options.icons.activeHeader ); + } + + clicked + .next() + .addClass( "ui-accordion-content-active" ); + } + }, + + _toggle: function( data ) { + var toShow = data.newPanel, + toHide = this.prevShow.length ? this.prevShow : data.oldPanel; + + // handle activating a panel during the animation for another activation + this.prevShow.add( this.prevHide ).stop( true, true ); + this.prevShow = toShow; + this.prevHide = toHide; + + if ( this.options.animate ) { + this._animate( toShow, toHide, data ); + } else { + toHide.hide(); + toShow.show(); + this._toggleComplete( data ); + } + + toHide.attr({ + "aria-expanded": "false", + "aria-hidden": "true" + }); + toHide.prev().attr( "aria-selected", "false" ); + // if we're switching panels, remove the old header from the tab order + // if we're opening from collapsed state, remove the previous header from the tab order + // if we're collapsing, then keep the collapsing header in the tab order + if ( toShow.length && toHide.length ) { + toHide.prev().attr( "tabIndex", -1 ); + } else if ( toShow.length ) { + this.headers.filter(function() { + return $( this ).attr( "tabIndex" ) === 0; + }) + .attr( "tabIndex", -1 ); + } + + toShow + .attr({ + "aria-expanded": "true", + "aria-hidden": "false" + }) + .prev() + .attr({ + "aria-selected": "true", + tabIndex: 0 + }); + }, + + _animate: function( toShow, toHide, data ) { + var total, easing, duration, + that = this, + adjust = 0, + down = toShow.length && + ( !toHide.length || ( toShow.index() < toHide.index() ) ), + animate = this.options.animate || {}, + options = down && animate.down || animate, + complete = function() { + that._toggleComplete( data ); + }; + + if ( typeof options === "number" ) { + duration = options; + } + if ( typeof options === "string" ) { + easing = options; + } + // fall back from options to animation in case of partial down settings + easing = easing || options.easing || animate.easing; + duration = duration || options.duration || animate.duration; + + if ( !toHide.length ) { + return toShow.animate( showProps, duration, easing, complete ); + } + if ( !toShow.length ) { + return toHide.animate( hideProps, duration, easing, complete ); + } + + total = toShow.show().outerHeight(); + toHide.animate( hideProps, { + duration: duration, + easing: easing, + step: function( now, fx ) { + fx.now = Math.round( now ); + } + }); + toShow + .hide() + .animate( showProps, { + duration: duration, + easing: easing, + complete: complete, + step: function( now, fx ) { + fx.now = Math.round( now ); + if ( fx.prop !== "height" ) { + adjust += fx.now; + } else if ( that.options.heightStyle !== "content" ) { + fx.now = Math.round( total - toHide.outerHeight() - adjust ); + adjust = 0; + } + } + }); + }, + + _toggleComplete: function( data ) { + var toHide = data.oldPanel; + + toHide + .removeClass( "ui-accordion-content-active" ) + .prev() + .removeClass( "ui-corner-top" ) + .addClass( "ui-corner-all" ); + + // Work around for rendering bug in IE (#5421) + if ( toHide.length ) { + toHide.parent()[0].className = toHide.parent()[0].className; + } + + this._trigger( "activate", null, data ); + } +}); + + + +// DEPRECATED +if ( $.uiBackCompat !== false ) { + // navigation options + (function( $, prototype ) { + $.extend( prototype.options, { + navigation: false, + navigationFilter: function() { + return this.href.toLowerCase() === location.href.toLowerCase(); + } + }); + + var _create = prototype._create; + prototype._create = function() { + if ( this.options.navigation ) { + var that = this, + headers = this.element.find( this.options.header ), + content = headers.next(), + current = headers.add( content ) + .find( "a" ) + .filter( this.options.navigationFilter ) + [ 0 ]; + if ( current ) { + headers.add( content ).each( function( index ) { + if ( $.contains( this, current ) ) { + that.options.active = Math.floor( index / 2 ); + return false; + } + }); + } + } + _create.call( this ); + }; + }( jQuery, jQuery.ui.accordion.prototype ) ); + + // height options + (function( $, prototype ) { + $.extend( prototype.options, { + heightStyle: null, // remove default so we fall back to old values + autoHeight: true, // use heightStyle: "auto" + clearStyle: false, // use heightStyle: "content" + fillSpace: false // use heightStyle: "fill" + }); + + var _create = prototype._create, + _setOption = prototype._setOption; + + $.extend( prototype, { + _create: function() { + this.options.heightStyle = this.options.heightStyle || + this._mergeHeightStyle(); + + _create.call( this ); + }, + + _setOption: function( key ) { + if ( key === "autoHeight" || key === "clearStyle" || key === "fillSpace" ) { + this.options.heightStyle = this._mergeHeightStyle(); + } + _setOption.apply( this, arguments ); + }, + + _mergeHeightStyle: function() { + var options = this.options; + + if ( options.fillSpace ) { + return "fill"; + } + + if ( options.clearStyle ) { + return "content"; + } + + if ( options.autoHeight ) { + return "auto"; + } + } + }); + }( jQuery, jQuery.ui.accordion.prototype ) ); + + // icon options + (function( $, prototype ) { + $.extend( prototype.options.icons, { + activeHeader: null, // remove default so we fall back to old values + headerSelected: "ui-icon-triangle-1-s" + }); + + var _createIcons = prototype._createIcons; + prototype._createIcons = function() { + if ( this.options.icons ) { + this.options.icons.activeHeader = this.options.icons.activeHeader || + this.options.icons.headerSelected; + } + _createIcons.call( this ); + }; + }( jQuery, jQuery.ui.accordion.prototype ) ); + + // expanded active option, activate method + (function( $, prototype ) { + prototype.activate = prototype._activate; + + var _findActive = prototype._findActive; + prototype._findActive = function( index ) { + if ( index === -1 ) { + index = false; + } + if ( index && typeof index !== "number" ) { + index = this.headers.index( this.headers.filter( index ) ); + if ( index === -1 ) { + index = false; + } + } + return _findActive.call( this, index ); + }; + }( jQuery, jQuery.ui.accordion.prototype ) ); + + // resize method + jQuery.ui.accordion.prototype.resize = jQuery.ui.accordion.prototype.refresh; + + // change events + (function( $, prototype ) { + $.extend( prototype.options, { + change: null, + changestart: null + }); + + var _trigger = prototype._trigger; + prototype._trigger = function( type, event, data ) { + var ret = _trigger.apply( this, arguments ); + if ( !ret ) { + return false; + } + + if ( type === "beforeActivate" ) { + ret = _trigger.call( this, "changestart", event, { + oldHeader: data.oldHeader, + oldContent: data.oldPanel, + newHeader: data.newHeader, + newContent: data.newPanel + }); + } else if ( type === "activate" ) { + ret = _trigger.call( this, "change", event, { + oldHeader: data.oldHeader, + oldContent: data.oldPanel, + newHeader: data.newHeader, + newContent: data.newPanel + }); + } + return ret; + }; + }( jQuery, jQuery.ui.accordion.prototype ) ); + + // animated option + // NOTE: this only provides support for "slide", "bounceslide", and easings + // not the full $.ui.accordion.animations API + (function( $, prototype ) { + $.extend( prototype.options, { + animate: null, + animated: "slide" + }); + + var _create = prototype._create; + prototype._create = function() { + var options = this.options; + if ( options.animate === null ) { + if ( !options.animated ) { + options.animate = false; + } else if ( options.animated === "slide" ) { + options.animate = 300; + } else if ( options.animated === "bounceslide" ) { + options.animate = { + duration: 200, + down: { + easing: "easeOutBounce", + duration: 1000 + } + }; + } else { + options.animate = options.animated; + } + } + + _create.call( this ); + }; + }( jQuery, jQuery.ui.accordion.prototype ) ); +} + +})( jQuery ); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.autocomplete.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.autocomplete.js new file mode 100644 index 0000000..2d06483 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.autocomplete.js @@ -0,0 +1,602 @@ +/*! + * jQuery UI Autocomplete @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/autocomplete/ + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.position.js + * jquery.ui.menu.js + */ +(function( $, undefined ) { + +// used to prevent race conditions with remote data sources +var requestIndex = 0; + +$.widget( "ui.autocomplete", { + version: "@VERSION", + defaultElement: "<input>", + options: { + appendTo: "body", + autoFocus: false, + delay: 300, + minLength: 1, + position: { + my: "left top", + at: "left bottom", + collision: "none" + }, + source: null, + + // callbacks + change: null, + close: null, + focus: null, + open: null, + response: null, + search: null, + select: null + }, + + pending: 0, + + _create: function() { + // Some browsers only repeat keydown events, not keypress events, + // so we use the suppressKeyPress flag to determine if we've already + // handled the keydown event. #7269 + // Unfortunately the code for & in keypress is the same as the up arrow, + // so we use the suppressKeyPressRepeat flag to avoid handling keypress + // events when we know the keydown event was used to modify the + // search term. #7799 + var suppressKeyPress, suppressKeyPressRepeat, suppressInput; + + this.isMultiLine = this._isMultiLine(); + this.valueMethod = this.element[ this.element.is( "input,textarea" ) ? "val" : "text" ]; + this.isNewMenu = true; + + this.element + .addClass( "ui-autocomplete-input" ) + .attr( "autocomplete", "off" ); + + this._on( this.element, { + keydown: function( event ) { + if ( this.element.prop( "readOnly" ) ) { + suppressKeyPress = true; + suppressInput = true; + suppressKeyPressRepeat = true; + return; + } + + suppressKeyPress = false; + suppressInput = false; + suppressKeyPressRepeat = false; + var keyCode = $.ui.keyCode; + switch( event.keyCode ) { + case keyCode.PAGE_UP: + suppressKeyPress = true; + this._move( "previousPage", event ); + break; + case keyCode.PAGE_DOWN: + suppressKeyPress = true; + this._move( "nextPage", event ); + break; + case keyCode.UP: + suppressKeyPress = true; + this._keyEvent( "previous", event ); + break; + case keyCode.DOWN: + suppressKeyPress = true; + this._keyEvent( "next", event ); + break; + case keyCode.ENTER: + case keyCode.NUMPAD_ENTER: + // when menu is open and has focus + if ( this.menu.active ) { + // #6055 - Opera still allows the keypress to occur + // which causes forms to submit + suppressKeyPress = true; + event.preventDefault(); + this.menu.select( event ); + } + break; + case keyCode.TAB: + if ( this.menu.active ) { + this.menu.select( event ); + } + break; + case keyCode.ESCAPE: + if ( this.menu.element.is( ":visible" ) ) { + this._value( this.term ); + this.close( event ); + // Different browsers have different default behavior for escape + // Single press can mean undo or clear + // Double press in IE means clear the whole form + event.preventDefault(); + } + break; + default: + suppressKeyPressRepeat = true; + // search timeout should be triggered before the input value is changed + this._searchTimeout( event ); + break; + } + }, + keypress: function( event ) { + if ( suppressKeyPress ) { + suppressKeyPress = false; + event.preventDefault(); + return; + } + if ( suppressKeyPressRepeat ) { + return; + } + + // replicate some key handlers to allow them to repeat in Firefox and Opera + var keyCode = $.ui.keyCode; + switch( event.keyCode ) { + case keyCode.PAGE_UP: + this._move( "previousPage", event ); + break; + case keyCode.PAGE_DOWN: + this._move( "nextPage", event ); + break; + case keyCode.UP: + this._keyEvent( "previous", event ); + break; + case keyCode.DOWN: + this._keyEvent( "next", event ); + break; + } + }, + input: function( event ) { + if ( suppressInput ) { + suppressInput = false; + event.preventDefault(); + return; + } + this._searchTimeout( event ); + }, + focus: function() { + this.selectedItem = null; + this.previous = this._value(); + }, + blur: function( event ) { + if ( this.cancelBlur ) { + delete this.cancelBlur; + return; + } + + clearTimeout( this.searching ); + this.close( event ); + this._change( event ); + } + }); + + this._initSource(); + this.menu = $( "<ul>" ) + .addClass( "ui-autocomplete" ) + .appendTo( this.document.find( this.options.appendTo || "body" )[ 0 ] ) + .menu({ + // custom key handling for now + input: $(), + // disable ARIA support, the live region takes care of that + role: null + }) + .zIndex( this.element.zIndex() + 1 ) + .hide() + .data( "menu" ); + + this._on( this.menu.element, { + mousedown: function( event ) { + // prevent moving focus out of the text field + event.preventDefault(); + + // IE doesn't prevent moving focus even with event.preventDefault() + // so we set a flag to know when we should ignore the blur event + this.cancelBlur = true; + this._delay(function() { + delete this.cancelBlur; + }); + + // clicking on the scrollbar causes focus to shift to the body + // but we can't detect a mouseup or a click immediately afterward + // so we have to track the next mousedown and close the menu if + // the user clicks somewhere outside of the autocomplete + var menuElement = this.menu.element[ 0 ]; + if ( !$( event.target ).closest( ".ui-menu-item" ).length ) { + this._delay(function() { + var that = this; + this.document.one( "mousedown", function( event ) { + if ( event.target !== that.element[ 0 ] && + event.target !== menuElement && + !$.contains( menuElement, event.target ) ) { + that.close(); + } + }); + }); + } + }, + menufocus: function( event, ui ) { + // #7024 - Prevent accidental activation of menu items in Firefox + if ( this.isNewMenu ) { + this.isNewMenu = false; + if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) { + this.menu.blur(); + + this.document.one( "mousemove", function() { + $( event.target ).trigger( event.originalEvent ); + }); + + return; + } + } + + // back compat for _renderItem using item.autocomplete, via #7810 + // TODO remove the fallback, see #8156 + var item = ui.item.data( "ui-autocomplete-item" ) || ui.item.data( "item.autocomplete" ); + if ( false !== this._trigger( "focus", event, { item: item } ) ) { + // use value to match what will end up in the input, if it was a key event + if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) { + this._value( item.value ); + } + } else { + // Normally the input is populated with the item's value as the + // menu is navigated, causing screen readers to notice a change and + // announce the item. Since the focus event was canceled, this doesn't + // happen, so we update the live region so that screen readers can + // still notice the change and announce it. + this.liveRegion.text( item.value ); + } + }, + menuselect: function( event, ui ) { + // back compat for _renderItem using item.autocomplete, via #7810 + // TODO remove the fallback, see #8156 + var item = ui.item.data( "ui-autocomplete-item" ) || ui.item.data( "item.autocomplete" ), + previous = this.previous; + + // only trigger when focus was lost (click on menu) + if ( this.element[0] !== this.document[0].activeElement ) { + this.element.focus(); + this.previous = previous; + // #6109 - IE triggers two focus events and the second + // is asynchronous, so we need to reset the previous + // term synchronously and asynchronously :-( + this._delay(function() { + this.previous = previous; + this.selectedItem = item; + }); + } + + if ( false !== this._trigger( "select", event, { item: item } ) ) { + this._value( item.value ); + } + // reset the term after the select event + // this allows custom select handling to work properly + this.term = this._value(); + + this.close( event ); + this.selectedItem = item; + } + }); + + this.liveRegion = $( "<span>", { + role: "status", + "aria-live": "polite" + }) + .addClass( "ui-helper-hidden-accessible" ) + .insertAfter( this.element ); + + if ( $.fn.bgiframe ) { + this.menu.element.bgiframe(); + } + + // turning off autocomplete prevents the browser from remembering the + // value when navigating through history, so we re-enable autocomplete + // if the page is unloaded before the widget is destroyed. #7790 + this._on( this.window, { + beforeunload: function() { + this.element.removeAttr( "autocomplete" ); + } + }); + }, + + _destroy: function() { + clearTimeout( this.searching ); + this.element + .removeClass( "ui-autocomplete-input" ) + .removeAttr( "autocomplete" ); + this.menu.element.remove(); + this.liveRegion.remove(); + }, + + _setOption: function( key, value ) { + this._super( key, value ); + if ( key === "source" ) { + this._initSource(); + } + if ( key === "appendTo" ) { + this.menu.element.appendTo( this.document.find( value || "body" )[0] ); + } + if ( key === "disabled" && value && this.xhr ) { + this.xhr.abort(); + } + }, + + _isMultiLine: function() { + // Textareas are always multi-line + if ( this.element.is( "textarea" ) ) { + return true; + } + // Inputs are always single-line, even if inside a contentEditable element + // IE also treats inputs as contentEditable + if ( this.element.is( "input" ) ) { + return false; + } + // All other element types are determined by whether or not they're contentEditable + return this.element.prop( "isContentEditable" ); + }, + + _initSource: function() { + var array, url, + that = this; + if ( $.isArray(this.options.source) ) { + array = this.options.source; + this.source = function( request, response ) { + response( $.ui.autocomplete.filter( array, request.term ) ); + }; + } else if ( typeof this.options.source === "string" ) { + url = this.options.source; + this.source = function( request, response ) { + if ( that.xhr ) { + that.xhr.abort(); + } + that.xhr = $.ajax({ + url: url, + data: request, + dataType: "json", + success: function( data ) { + response( data ); + }, + error: function() { + response( [] ); + } + }); + }; + } else { + this.source = this.options.source; + } + }, + + _searchTimeout: function( event ) { + clearTimeout( this.searching ); + this.searching = this._delay(function() { + // only search if the value has changed + if ( this.term !== this._value() ) { + this.selectedItem = null; + this.search( null, event ); + } + }, this.options.delay ); + }, + + search: function( value, event ) { + value = value != null ? value : this._value(); + + // always save the actual value, not the one passed as an argument + this.term = this._value(); + + if ( value.length < this.options.minLength ) { + return this.close( event ); + } + + if ( this._trigger( "search", event ) === false ) { + return; + } + + return this._search( value ); + }, + + _search: function( value ) { + this.pending++; + this.element.addClass( "ui-autocomplete-loading" ); + this.cancelSearch = false; + + this.source( { term: value }, this._response() ); + }, + + _response: function() { + var that = this, + index = ++requestIndex; + + return function( content ) { + if ( index === requestIndex ) { + that.__response( content ); + } + + that.pending--; + if ( !that.pending ) { + that.element.removeClass( "ui-autocomplete-loading" ); + } + }; + }, + + __response: function( content ) { + if ( content ) { + content = this._normalize( content ); + } + this._trigger( "response", null, { content: content } ); + if ( !this.options.disabled && content && content.length && !this.cancelSearch ) { + this._suggest( content ); + this._trigger( "open" ); + } else { + // use ._close() instead of .close() so we don't cancel future searches + this._close(); + } + }, + + close: function( event ) { + this.cancelSearch = true; + this._close( event ); + }, + + _close: function( event ) { + if ( this.menu.element.is( ":visible" ) ) { + this.menu.element.hide(); + this.menu.blur(); + this.isNewMenu = true; + this._trigger( "close", event ); + } + }, + + _change: function( event ) { + if ( this.previous !== this._value() ) { + this._trigger( "change", event, { item: this.selectedItem } ); + } + }, + + _normalize: function( items ) { + // assume all items have the right format when the first item is complete + if ( items.length && items[0].label && items[0].value ) { + return items; + } + return $.map( items, function( item ) { + if ( typeof item === "string" ) { + return { + label: item, + value: item + }; + } + return $.extend({ + label: item.label || item.value, + value: item.value || item.label + }, item ); + }); + }, + + _suggest: function( items ) { + var ul = this.menu.element + .empty() + .zIndex( this.element.zIndex() + 1 ); + this._renderMenu( ul, items ); + this.menu.refresh(); + + // size and position menu + ul.show(); + this._resizeMenu(); + ul.position( $.extend({ + of: this.element + }, this.options.position )); + + if ( this.options.autoFocus ) { + this.menu.next(); + } + }, + + _resizeMenu: function() { + var ul = this.menu.element; + ul.outerWidth( Math.max( + // Firefox wraps long text (possibly a rounding bug) + // so we add 1px to avoid the wrapping (#7513) + ul.width( "" ).outerWidth() + 1, + this.element.outerWidth() + ) ); + }, + + _renderMenu: function( ul, items ) { + var that = this; + $.each( items, function( index, item ) { + that._renderItemData( ul, item ); + }); + }, + + _renderItemData: function( ul, item ) { + return this._renderItem( ul, item ).data( "ui-autocomplete-item", item ); + }, + + _renderItem: function( ul, item ) { + return $( "<li>" ) + .append( $( "<a>" ).text( item.label ) ) + .appendTo( ul ); + }, + + _move: function( direction, event ) { + if ( !this.menu.element.is( ":visible" ) ) { + this.search( null, event ); + return; + } + if ( this.menu.isFirstItem() && /^previous/.test( direction ) || + this.menu.isLastItem() && /^next/.test( direction ) ) { + this._value( this.term ); + this.menu.blur(); + return; + } + this.menu[ direction ]( event ); + }, + + widget: function() { + return this.menu.element; + }, + + _value: function() { + return this.valueMethod.apply( this.element, arguments ); + }, + + _keyEvent: function( keyEvent, event ) { + if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) { + this._move( keyEvent, event ); + + // prevents moving cursor to beginning/end of the text field in some browsers + event.preventDefault(); + } + } +}); + +$.extend( $.ui.autocomplete, { + escapeRegex: function( value ) { + return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"); + }, + filter: function(array, term) { + var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" ); + return $.grep( array, function(value) { + return matcher.test( value.label || value.value || value ); + }); + } +}); + + +// live region extension, adding a `messages` option +// NOTE: This is an experimental API. We are still investigating +// a full solution for string manipulation and internationalization. +$.widget( "ui.autocomplete", $.ui.autocomplete, { + options: { + messages: { + noResults: "No search results.", + results: function( amount ) { + return amount + ( amount > 1 ? " results are" : " result is" ) + + " available, use up and down arrow keys to navigate."; + } + } + }, + + __response: function( content ) { + var message; + this._superApply( arguments ); + if ( this.options.disabled || this.cancelSearch ) { + return; + } + if ( content && content.length ) { + message = this.options.messages.results( content.length ); + } else { + message = this.options.messages.noResults; + } + this.liveRegion.text( message ); + } +}); + + +}( jQuery )); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.button.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.button.js new file mode 100644 index 0000000..673cd3f --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.button.js @@ -0,0 +1,418 @@ +/*! + * jQuery UI Button @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/button/ + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +var lastActive, startXPos, startYPos, clickDragged, + baseClasses = "ui-button ui-widget ui-state-default ui-corner-all", + stateClasses = "ui-state-hover ui-state-active ", + typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only", + formResetHandler = function() { + var buttons = $( this ).find( ":ui-button" ); + setTimeout(function() { + buttons.button( "refresh" ); + }, 1 ); + }, + radioGroup = function( radio ) { + var name = radio.name, + form = radio.form, + radios = $( [] ); + if ( name ) { + if ( form ) { + radios = $( form ).find( "[name='" + name + "']" ); + } else { + radios = $( "[name='" + name + "']", radio.ownerDocument ) + .filter(function() { + return !this.form; + }); + } + } + return radios; + }; + +$.widget( "ui.button", { + version: "@VERSION", + defaultElement: "<button>", + options: { + disabled: null, + text: true, + label: null, + icons: { + primary: null, + secondary: null + } + }, + _create: function() { + this.element.closest( "form" ) + .unbind( "reset" + this.eventNamespace ) + .bind( "reset" + this.eventNamespace, formResetHandler ); + + if ( typeof this.options.disabled !== "boolean" ) { + this.options.disabled = !!this.element.prop( "disabled" ); + } else { + this.element.prop( "disabled", this.options.disabled ); + } + + this._determineButtonType(); + this.hasTitle = !!this.buttonElement.attr( "title" ); + + var that = this, + options = this.options, + toggleButton = this.type === "checkbox" || this.type === "radio", + activeClass = !toggleButton ? "ui-state-active" : "", + focusClass = "ui-state-focus"; + + if ( options.label === null ) { + options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html()); + } + + this._hoverable( this.buttonElement ); + + this.buttonElement + .addClass( baseClasses ) + .attr( "role", "button" ) + .bind( "mouseenter" + this.eventNamespace, function() { + if ( options.disabled ) { + return; + } + if ( this === lastActive ) { + $( this ).addClass( "ui-state-active" ); + } + }) + .bind( "mouseleave" + this.eventNamespace, function() { + if ( options.disabled ) { + return; + } + $( this ).removeClass( activeClass ); + }) + .bind( "click" + this.eventNamespace, function( event ) { + if ( options.disabled ) { + event.preventDefault(); + event.stopImmediatePropagation(); + } + }); + + this.element + .bind( "focus" + this.eventNamespace, function() { + // no need to check disabled, focus won't be triggered anyway + that.buttonElement.addClass( focusClass ); + }) + .bind( "blur" + this.eventNamespace, function() { + that.buttonElement.removeClass( focusClass ); + }); + + if ( toggleButton ) { + this.element.bind( "change" + this.eventNamespace, function() { + if ( clickDragged ) { + return; + } + that.refresh(); + }); + // if mouse moves between mousedown and mouseup (drag) set clickDragged flag + // prevents issue where button state changes but checkbox/radio checked state + // does not in Firefox (see ticket #6970) + this.buttonElement + .bind( "mousedown" + this.eventNamespace, function( event ) { + if ( options.disabled ) { + return; + } + clickDragged = false; + startXPos = event.pageX; + startYPos = event.pageY; + }) + .bind( "mouseup" + this.eventNamespace, function( event ) { + if ( options.disabled ) { + return; + } + if ( startXPos !== event.pageX || startYPos !== event.pageY ) { + clickDragged = true; + } + }); + } + + if ( this.type === "checkbox" ) { + this.buttonElement.bind( "click" + this.eventNamespace, function() { + if ( options.disabled || clickDragged ) { + return false; + } + $( this ).toggleClass( "ui-state-active" ); + that.buttonElement.attr( "aria-pressed", that.element[0].checked ); + }); + } else if ( this.type === "radio" ) { + this.buttonElement.bind( "click" + this.eventNamespace, function() { + if ( options.disabled || clickDragged ) { + return false; + } + $( this ).addClass( "ui-state-active" ); + that.buttonElement.attr( "aria-pressed", "true" ); + + var radio = that.element[ 0 ]; + radioGroup( radio ) + .not( radio ) + .map(function() { + return $( this ).button( "widget" )[ 0 ]; + }) + .removeClass( "ui-state-active" ) + .attr( "aria-pressed", "false" ); + }); + } else { + this.buttonElement + .bind( "mousedown" + this.eventNamespace, function() { + if ( options.disabled ) { + return false; + } + $( this ).addClass( "ui-state-active" ); + lastActive = this; + that.document.one( "mouseup", function() { + lastActive = null; + }); + }) + .bind( "mouseup" + this.eventNamespace, function() { + if ( options.disabled ) { + return false; + } + $( this ).removeClass( "ui-state-active" ); + }) + .bind( "keydown" + this.eventNamespace, function(event) { + if ( options.disabled ) { + return false; + } + if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) { + $( this ).addClass( "ui-state-active" ); + } + }) + .bind( "keyup" + this.eventNamespace, function() { + $( this ).removeClass( "ui-state-active" ); + }); + + if ( this.buttonElement.is("a") ) { + this.buttonElement.keyup(function(event) { + if ( event.keyCode === $.ui.keyCode.SPACE ) { + // TODO pass through original event correctly (just as 2nd argument doesn't work) + $( this ).click(); + } + }); + } + } + + // TODO: pull out $.Widget's handling for the disabled option into + // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can + // be overridden by individual plugins + this._setOption( "disabled", options.disabled ); + this._resetButton(); + }, + + _determineButtonType: function() { + var ancestor, labelSelector, checked; + + if ( this.element.is("[type=checkbox]") ) { + this.type = "checkbox"; + } else if ( this.element.is("[type=radio]") ) { + this.type = "radio"; + } else if ( this.element.is("input") ) { + this.type = "input"; + } else { + this.type = "button"; + } + + if ( this.type === "checkbox" || this.type === "radio" ) { + // we don't search against the document in case the element + // is disconnected from the DOM + ancestor = this.element.parents().last(); + labelSelector = "label[for='" + this.element.attr("id") + "']"; + this.buttonElement = ancestor.find( labelSelector ); + if ( !this.buttonElement.length ) { + ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings(); + this.buttonElement = ancestor.filter( labelSelector ); + if ( !this.buttonElement.length ) { + this.buttonElement = ancestor.find( labelSelector ); + } + } + this.element.addClass( "ui-helper-hidden-accessible" ); + + checked = this.element.is( ":checked" ); + if ( checked ) { + this.buttonElement.addClass( "ui-state-active" ); + } + this.buttonElement.prop( "aria-pressed", checked ); + } else { + this.buttonElement = this.element; + } + }, + + widget: function() { + return this.buttonElement; + }, + + _destroy: function() { + this.element + .removeClass( "ui-helper-hidden-accessible" ); + this.buttonElement + .removeClass( baseClasses + " " + stateClasses + " " + typeClasses ) + .removeAttr( "role" ) + .removeAttr( "aria-pressed" ) + .html( this.buttonElement.find(".ui-button-text").html() ); + + if ( !this.hasTitle ) { + this.buttonElement.removeAttr( "title" ); + } + }, + + _setOption: function( key, value ) { + this._super( key, value ); + if ( key === "disabled" ) { + if ( value ) { + this.element.prop( "disabled", true ); + } else { + this.element.prop( "disabled", false ); + } + return; + } + this._resetButton(); + }, + + refresh: function() { + //See #8237 & #8828 + var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" ); + + if ( isDisabled !== this.options.disabled ) { + this._setOption( "disabled", isDisabled ); + } + if ( this.type === "radio" ) { + radioGroup( this.element[0] ).each(function() { + if ( $( this ).is( ":checked" ) ) { + $( this ).button( "widget" ) + .addClass( "ui-state-active" ) + .attr( "aria-pressed", "true" ); + } else { + $( this ).button( "widget" ) + .removeClass( "ui-state-active" ) + .attr( "aria-pressed", "false" ); + } + }); + } else if ( this.type === "checkbox" ) { + if ( this.element.is( ":checked" ) ) { + this.buttonElement + .addClass( "ui-state-active" ) + .attr( "aria-pressed", "true" ); + } else { + this.buttonElement + .removeClass( "ui-state-active" ) + .attr( "aria-pressed", "false" ); + } + } + }, + + _resetButton: function() { + if ( this.type === "input" ) { + if ( this.options.label ) { + this.element.val( this.options.label ); + } + return; + } + var buttonElement = this.buttonElement.removeClass( typeClasses ), + buttonText = $( "<span></span>", this.document[0] ) + .addClass( "ui-button-text" ) + .html( this.options.label ) + .appendTo( buttonElement.empty() ) + .text(), + icons = this.options.icons, + multipleIcons = icons.primary && icons.secondary, + buttonClasses = []; + + if ( icons.primary || icons.secondary ) { + if ( this.options.text ) { + buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) ); + } + + if ( icons.primary ) { + buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" ); + } + + if ( icons.secondary ) { + buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" ); + } + + if ( !this.options.text ) { + buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" ); + + if ( !this.hasTitle ) { + buttonElement.attr( "title", $.trim( buttonText ) ); + } + } + } else { + buttonClasses.push( "ui-button-text-only" ); + } + buttonElement.addClass( buttonClasses.join( " " ) ); + } +}); + +$.widget( "ui.buttonset", { + version: "@VERSION", + options: { + items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(button)" + }, + + _create: function() { + this.element.addClass( "ui-buttonset" ); + }, + + _init: function() { + this.refresh(); + }, + + _setOption: function( key, value ) { + if ( key === "disabled" ) { + this.buttons.button( "option", key, value ); + } + + this._super( key, value ); + }, + + refresh: function() { + var rtl = this.element.css( "direction" ) === "rtl"; + + this.buttons = this.element.find( this.options.items ) + .filter( ":ui-button" ) + .button( "refresh" ) + .end() + .not( ":ui-button" ) + .button() + .end() + .map(function() { + return $( this ).button( "widget" )[ 0 ]; + }) + .removeClass( "ui-corner-all ui-corner-left ui-corner-right" ) + .filter( ":first" ) + .addClass( rtl ? "ui-corner-right" : "ui-corner-left" ) + .end() + .filter( ":last" ) + .addClass( rtl ? "ui-corner-left" : "ui-corner-right" ) + .end() + .end(); + }, + + _destroy: function() { + this.element.removeClass( "ui-buttonset" ); + this.buttons + .map(function() { + return $( this ).button( "widget" )[ 0 ]; + }) + .removeClass( "ui-corner-left ui-corner-right" ) + .end() + .button( "destroy" ); + } +}); + +}( jQuery ) ); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.core.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.core.js new file mode 100644 index 0000000..d5c38d5 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.core.js @@ -0,0 +1,356 @@ +/*! + * jQuery UI Core @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/category/ui-core/ + */ +(function( $, undefined ) { + +var uuid = 0, + runiqueId = /^ui-id-\d+$/; + +// prevent duplicate loading +// this is only a problem because we proxy existing functions +// and we don't want to double proxy them +$.ui = $.ui || {}; +if ( $.ui.version ) { + return; +} + +$.extend( $.ui, { + version: "@VERSION", + + keyCode: { + BACKSPACE: 8, + COMMA: 188, + DELETE: 46, + DOWN: 40, + END: 35, + ENTER: 13, + ESCAPE: 27, + HOME: 36, + LEFT: 37, + NUMPAD_ADD: 107, + NUMPAD_DECIMAL: 110, + NUMPAD_DIVIDE: 111, + NUMPAD_ENTER: 108, + NUMPAD_MULTIPLY: 106, + NUMPAD_SUBTRACT: 109, + PAGE_DOWN: 34, + PAGE_UP: 33, + PERIOD: 190, + RIGHT: 39, + SPACE: 32, + TAB: 9, + UP: 38 + } +}); + +// plugins +$.fn.extend({ + _focus: $.fn.focus, + focus: function( delay, fn ) { + return typeof delay === "number" ? + this.each(function() { + var elem = this; + setTimeout(function() { + $( elem ).focus(); + if ( fn ) { + fn.call( elem ); + } + }, delay ); + }) : + this._focus.apply( this, arguments ); + }, + + scrollParent: function() { + var scrollParent; + if (($.ui.ie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) { + scrollParent = this.parents().filter(function() { + return (/(relative|absolute|fixed)/).test($.css(this,'position')) && (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x')); + }).eq(0); + } else { + scrollParent = this.parents().filter(function() { + return (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x')); + }).eq(0); + } + + return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent; + }, + + zIndex: function( zIndex ) { + if ( zIndex !== undefined ) { + return this.css( "zIndex", zIndex ); + } + + if ( this.length ) { + var elem = $( this[ 0 ] ), position, value; + while ( elem.length && elem[ 0 ] !== document ) { + // Ignore z-index if position is set to a value where z-index is ignored by the browser + // This makes behavior of this function consistent across browsers + // WebKit always returns auto if the element is positioned + position = elem.css( "position" ); + if ( position === "absolute" || position === "relative" || position === "fixed" ) { + // IE returns 0 when zIndex is not specified + // other browsers return a string + // we ignore the case of nested elements with an explicit value of 0 + // <div style="z-index: -10;"><div style="z-index: 0;"></div></div> + value = parseInt( elem.css( "zIndex" ), 10 ); + if ( !isNaN( value ) && value !== 0 ) { + return value; + } + } + elem = elem.parent(); + } + } + + return 0; + }, + + uniqueId: function() { + return this.each(function() { + if ( !this.id ) { + this.id = "ui-id-" + (++uuid); + } + }); + }, + + removeUniqueId: function() { + return this.each(function() { + if ( runiqueId.test( this.id ) ) { + $( this ).removeAttr( "id" ); + } + }); + } +}); + +// selectors +function focusable( element, isTabIndexNotNaN ) { + var map, mapName, img, + nodeName = element.nodeName.toLowerCase(); + if ( "area" === nodeName ) { + map = element.parentNode; + mapName = map.name; + if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { + return false; + } + img = $( "img[usemap=#" + mapName + "]" )[0]; + return !!img && visible( img ); + } + return ( /input|select|textarea|button|object/.test( nodeName ) ? + !element.disabled : + "a" === nodeName ? + element.href || isTabIndexNotNaN : + isTabIndexNotNaN) && + // the element and all of its ancestors must be visible + visible( element ); +} + +function visible( element ) { + return $.expr.filters.visible( element ) && + !$( element ).parents().andSelf().filter(function() { + return $.css( this, "visibility" ) === "hidden"; + }).length; +} + +$.extend( $.expr[ ":" ], { + data: $.expr.createPseudo ? + $.expr.createPseudo(function( dataName ) { + return function( elem ) { + return !!$.data( elem, dataName ); + }; + }) : + // support: jQuery <1.8 + function( elem, i, match ) { + return !!$.data( elem, match[ 3 ] ); + }, + + focusable: function( element ) { + return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) ); + }, + + tabbable: function( element ) { + var tabIndex = $.attr( element, "tabindex" ), + isTabIndexNaN = isNaN( tabIndex ); + return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN ); + } +}); + +// support +$(function() { + var body = document.body, + div = body.appendChild( div = document.createElement( "div" ) ); + + // access offsetHeight before setting the style to prevent a layout bug + // in IE 9 which causes the element to continue to take up space even + // after it is removed from the DOM (#8026) + div.offsetHeight; + + $.extend( div.style, { + minHeight: "100px", + height: "auto", + padding: 0, + borderWidth: 0 + }); + + $.support.minHeight = div.offsetHeight === 100; + $.support.selectstart = "onselectstart" in div; + + // set display to none to avoid a layout bug in IE + // http://dev.jquery.com/ticket/4014 + body.removeChild( div ).style.display = "none"; +}); + +// support: jQuery <1.8 +if ( !$( "<a>" ).outerWidth( 1 ).jquery ) { + $.each( [ "Width", "Height" ], function( i, name ) { + var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ], + type = name.toLowerCase(), + orig = { + innerWidth: $.fn.innerWidth, + innerHeight: $.fn.innerHeight, + outerWidth: $.fn.outerWidth, + outerHeight: $.fn.outerHeight + }; + + function reduce( elem, size, border, margin ) { + $.each( side, function() { + size -= parseFloat( $.css( elem, "padding" + this ) ) || 0; + if ( border ) { + size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0; + } + if ( margin ) { + size -= parseFloat( $.css( elem, "margin" + this ) ) || 0; + } + }); + return size; + } + + $.fn[ "inner" + name ] = function( size ) { + if ( size === undefined ) { + return orig[ "inner" + name ].call( this ); + } + + return this.each(function() { + $( this ).css( type, reduce( this, size ) + "px" ); + }); + }; + + $.fn[ "outer" + name] = function( size, margin ) { + if ( typeof size !== "number" ) { + return orig[ "outer" + name ].call( this, size ); + } + + return this.each(function() { + $( this).css( type, reduce( this, size, true, margin ) + "px" ); + }); + }; + }); +} + +// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413) +if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) { + $.fn.removeData = (function( removeData ) { + return function( key ) { + if ( arguments.length ) { + return removeData.call( this, $.camelCase( key ) ); + } else { + return removeData.call( this ); + } + }; + })( $.fn.removeData ); +} + + + + + +// deprecated + +(function() { + var uaMatch = /msie ([\w.]+)/.exec( navigator.userAgent.toLowerCase() ) || []; + $.ui.ie = uaMatch.length ? true : false; + $.ui.ie6 = parseFloat( uaMatch[ 1 ], 10 ) === 6; +})(); + +$.fn.extend({ + disableSelection: function() { + return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) + + ".ui-disableSelection", function( event ) { + event.preventDefault(); + }); + }, + + enableSelection: function() { + return this.unbind( ".ui-disableSelection" ); + } +}); + +$.extend( $.ui, { + // $.ui.plugin is deprecated. Use the proxy pattern instead. + plugin: { + add: function( module, option, set ) { + var i, + proto = $.ui[ module ].prototype; + for ( i in set ) { + proto.plugins[ i ] = proto.plugins[ i ] || []; + proto.plugins[ i ].push( [ option, set[ i ] ] ); + } + }, + call: function( instance, name, args ) { + var i, + set = instance.plugins[ name ]; + if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) { + return; + } + + for ( i = 0; i < set.length; i++ ) { + if ( instance.options[ set[ i ][ 0 ] ] ) { + set[ i ][ 1 ].apply( instance.element, args ); + } + } + } + }, + + contains: $.contains, + + // only used by resizable + hasScroll: function( el, a ) { + + //If overflow is hidden, the element might have extra content, but the user wants to hide it + if ( $( el ).css( "overflow" ) === "hidden") { + return false; + } + + var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop", + has = false; + + if ( el[ scroll ] > 0 ) { + return true; + } + + // TODO: determine which cases actually cause this to happen + // if the element doesn't have the scroll set, see if it's possible to + // set the scroll + el[ scroll ] = 1; + has = ( el[ scroll ] > 0 ); + el[ scroll ] = 0; + return has; + }, + + // these are odd functions, fix the API or move into individual plugins + isOverAxis: function( x, reference, size ) { + //Determines when x coordinate is over "b" element axis + return ( x > reference ) && ( x < ( reference + size ) ); + }, + isOver: function( y, x, top, left, height, width ) { + //Determines when x, y coordinates is over "b" element + return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width ); + } +}); + +})( jQuery ); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.datepicker.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.datepicker.js new file mode 100644 index 0000000..7dacbc7 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.datepicker.js @@ -0,0 +1,1846 @@ +/*! + * jQuery UI Datepicker @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/datepicker/ + * + * Depends: + * jquery.ui.core.js + */ +(function( $, undefined ) { + +$.extend($.ui, { datepicker: { version: "@VERSION" } }); + +var PROP_NAME = 'datepicker'; +var dpuuid = new Date().getTime(); +var instActive; + +/* Date picker manager. + Use the singleton instance of this class, $.datepicker, to interact with the date picker. + Settings for (groups of) date pickers are maintained in an instance object, + allowing multiple different settings on the same page. */ + +function Datepicker() { + this.debug = false; // Change this to true to start debugging + this._curInst = null; // The current instance in use + this._keyEvent = false; // If the last event was a key event + this._disabledInputs = []; // List of date picker inputs that have been disabled + this._datepickerShowing = false; // True if the popup picker is showing , false if not + this._inDialog = false; // True if showing within a "dialog", false if not + this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division + this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class + this._appendClass = 'ui-datepicker-append'; // The name of the append marker class + this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class + this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class + this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class + this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class + this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class + this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class + this.regional = []; // Available regional settings, indexed by language code + this.regional[''] = { // Default regional settings + closeText: 'Done', // Display text for close link + prevText: 'Prev', // Display text for previous month link + nextText: 'Next', // Display text for next month link + currentText: 'Today', // Display text for current month link + monthNames: ['January','February','March','April','May','June', + 'July','August','September','October','November','December'], // Names of months for drop-down and formatting + monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting + dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting + dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting + dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday + weekHeader: 'Wk', // Column header for week of the year + dateFormat: 'mm/dd/yy', // See format options on parseDate + firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ... + isRTL: false, // True if right-to-left language, false if left-to-right + showMonthAfterYear: false, // True if the year select precedes month, false for month then year + yearSuffix: '' // Additional text to append to the year in the month headers + }; + this._defaults = { // Global defaults for all the date picker instances + showOn: 'focus', // 'focus' for popup on focus, + // 'button' for trigger button, or 'both' for either + showAnim: 'fadeIn', // Name of jQuery animation for popup + showOptions: {}, // Options for enhanced animations + defaultDate: null, // Used when field is blank: actual date, + // +/-number for offset from today, null for today + appendText: '', // Display text following the input box, e.g. showing the format + buttonText: '...', // Text for trigger button + buttonImage: '', // URL for trigger button image + buttonImageOnly: false, // True if the image appears alone, false if it appears on a button + hideIfNoPrevNext: false, // True to hide next/previous month links + // if not applicable, false to just disable them + navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links + gotoCurrent: false, // True if today link goes back to current selection instead + changeMonth: false, // True if month can be selected directly, false if only prev/next + changeYear: false, // True if year can be selected directly, false if only prev/next + yearRange: 'c-10:c+10', // Range of years to display in drop-down, + // either relative to today's year (-nn:+nn), relative to currently displayed year + // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n) + showOtherMonths: false, // True to show dates in other months, false to leave blank + selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable + showWeek: false, // True to show week of the year, false to not show it + calculateWeek: this.iso8601Week, // How to calculate the week of the year, + // takes a Date and returns the number of the week for it + shortYearCutoff: '+10', // Short year values < this are in the current century, + // > this are in the previous century, + // string value starting with '+' for current year + value + minDate: null, // The earliest selectable date, or null for no limit + maxDate: null, // The latest selectable date, or null for no limit + duration: 'fast', // Duration of display/closure + beforeShowDay: null, // Function that takes a date and returns an array with + // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '', + // [2] = cell title (optional), e.g. $.datepicker.noWeekends + beforeShow: null, // Function that takes an input field and + // returns a set of custom settings for the date picker + onSelect: null, // Define a callback function when a date is selected + onChangeMonthYear: null, // Define a callback function when the month or year is changed + onClose: null, // Define a callback function when the datepicker is closed + numberOfMonths: 1, // Number of months to show at a time + showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0) + stepMonths: 1, // Number of months to step back/forward + stepBigMonths: 12, // Number of months to step back/forward for the big links + altField: '', // Selector for an alternate field to store selected dates into + altFormat: '', // The date format to use for the alternate field + constrainInput: true, // The input is constrained by the current date format + showButtonPanel: false, // True to show button panel, false to not show it + autoSize: false, // True to size the input for the date format, false to leave as is + disabled: false // The initial disabled state + }; + $.extend(this._defaults, this.regional['']); + this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')); +} + +$.extend(Datepicker.prototype, { + /* Class name added to elements to indicate already configured with a date picker. */ + markerClassName: 'hasDatepicker', + + //Keep track of the maximum number of rows displayed (see #7043) + maxRows: 4, + + /* Debug logging (if enabled). */ + log: function () { + if (this.debug) + console.log.apply('', arguments); + }, + + // TODO rename to "widget" when switching to widget factory + _widgetDatepicker: function() { + return this.dpDiv; + }, + + /* Override the default settings for all instances of the date picker. + @param settings object - the new settings to use as defaults (anonymous object) + @return the manager object */ + setDefaults: function(settings) { + extendRemove(this._defaults, settings || {}); + return this; + }, + + /* Attach the date picker to a jQuery selection. + @param target element - the target input field or division or span + @param settings object - the new settings to use for this date picker instance (anonymous) */ + _attachDatepicker: function(target, settings) { + // check for settings on the control itself - in namespace 'date:' + var inlineSettings = null; + for (var attrName in this._defaults) { + var attrValue = target.getAttribute('date:' + attrName); + if (attrValue) { + inlineSettings = inlineSettings || {}; + try { + inlineSettings[attrName] = eval(attrValue); + } catch (err) { + inlineSettings[attrName] = attrValue; + } + } + } + var nodeName = target.nodeName.toLowerCase(); + var inline = (nodeName == 'div' || nodeName == 'span'); + if (!target.id) { + this.uuid += 1; + target.id = 'dp' + this.uuid; + } + var inst = this._newInst($(target), inline); + inst.settings = $.extend({}, settings || {}, inlineSettings || {}); + if (nodeName == 'input') { + this._connectDatepicker(target, inst); + } else if (inline) { + this._inlineDatepicker(target, inst); + } + }, + + /* Create a new instance object. */ + _newInst: function(target, inline) { + var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars + return {id: id, input: target, // associated target + selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection + drawMonth: 0, drawYear: 0, // month being drawn + inline: inline, // is datepicker inline or not + dpDiv: (!inline ? this.dpDiv : // presentation div + bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))}; + }, + + /* Attach the date picker to an input field. */ + _connectDatepicker: function(target, inst) { + var input = $(target); + inst.append = $([]); + inst.trigger = $([]); + if (input.hasClass(this.markerClassName)) + return; + this._attachments(input, inst); + input.addClass(this.markerClassName).keydown(this._doKeyDown). + keypress(this._doKeyPress).keyup(this._doKeyUp). + bind("setData.datepicker", function(event, key, value) { + inst.settings[key] = value; + }).bind("getData.datepicker", function(event, key) { + return this._get(inst, key); + }); + this._autoSize(inst); + $.data(target, PROP_NAME, inst); + //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665) + if( inst.settings.disabled ) { + this._disableDatepicker( target ); + } + }, + + /* Make attachments based on settings. */ + _attachments: function(input, inst) { + var appendText = this._get(inst, 'appendText'); + var isRTL = this._get(inst, 'isRTL'); + if (inst.append) + inst.append.remove(); + if (appendText) { + inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>'); + input[isRTL ? 'before' : 'after'](inst.append); + } + input.unbind('focus', this._showDatepicker); + if (inst.trigger) + inst.trigger.remove(); + var showOn = this._get(inst, 'showOn'); + if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field + input.focus(this._showDatepicker); + if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked + var buttonText = this._get(inst, 'buttonText'); + var buttonImage = this._get(inst, 'buttonImage'); + inst.trigger = $(this._get(inst, 'buttonImageOnly') ? + $('<img/>').addClass(this._triggerClass). + attr({ src: buttonImage, alt: buttonText, title: buttonText }) : + $('<button type="button"></button>').addClass(this._triggerClass). + html(buttonImage == '' ? buttonText : $('<img/>').attr( + { src:buttonImage, alt:buttonText, title:buttonText }))); + input[isRTL ? 'before' : 'after'](inst.trigger); + inst.trigger.click(function() { + if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0]) + $.datepicker._hideDatepicker(); + else if ($.datepicker._datepickerShowing && $.datepicker._lastInput != input[0]) { + $.datepicker._hideDatepicker(); + $.datepicker._showDatepicker(input[0]); + } else + $.datepicker._showDatepicker(input[0]); + return false; + }); + } + }, + + /* Apply the maximum length for the date format. */ + _autoSize: function(inst) { + if (this._get(inst, 'autoSize') && !inst.inline) { + var date = new Date(2009, 12 - 1, 20); // Ensure double digits + var dateFormat = this._get(inst, 'dateFormat'); + if (dateFormat.match(/[DM]/)) { + var findMax = function(names) { + var max = 0; + var maxI = 0; + for (var i = 0; i < names.length; i++) { + if (names[i].length > max) { + max = names[i].length; + maxI = i; + } + } + return maxI; + }; + date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ? + 'monthNames' : 'monthNamesShort')))); + date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ? + 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay()); + } + inst.input.attr('size', this._formatDate(inst, date).length); + } + }, + + /* Attach an inline date picker to a div. */ + _inlineDatepicker: function(target, inst) { + var divSpan = $(target); + if (divSpan.hasClass(this.markerClassName)) + return; + divSpan.addClass(this.markerClassName).append(inst.dpDiv). + bind("setData.datepicker", function(event, key, value){ + inst.settings[key] = value; + }).bind("getData.datepicker", function(event, key){ + return this._get(inst, key); + }); + $.data(target, PROP_NAME, inst); + this._setDate(inst, this._getDefaultDate(inst), true); + this._updateDatepicker(inst); + this._updateAlternate(inst); + //If disabled option is true, disable the datepicker before showing it (see ticket #5665) + if( inst.settings.disabled ) { + this._disableDatepicker( target ); + } + // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements + // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height + inst.dpDiv.css( "display", "block" ); + }, + + /* Pop-up the date picker in a "dialog" box. + @param input element - ignored + @param date string or Date - the initial date to display + @param onSelect function - the function to call when a date is selected + @param settings object - update the dialog date picker instance's settings (anonymous object) + @param pos int[2] - coordinates for the dialog's position within the screen or + event - with x/y coordinates or + leave empty for default (screen centre) + @return the manager object */ + _dialogDatepicker: function(input, date, onSelect, settings, pos) { + var inst = this._dialogInst; // internal instance + if (!inst) { + this.uuid += 1; + var id = 'dp' + this.uuid; + this._dialogInput = $('<input type="text" id="' + id + + '" style="position: absolute; top: -100px; width: 0px;"/>'); + this._dialogInput.keydown(this._doKeyDown); + $('body').append(this._dialogInput); + inst = this._dialogInst = this._newInst(this._dialogInput, false); + inst.settings = {}; + $.data(this._dialogInput[0], PROP_NAME, inst); + } + extendRemove(inst.settings, settings || {}); + date = (date && date.constructor == Date ? this._formatDate(inst, date) : date); + this._dialogInput.val(date); + + this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null); + if (!this._pos) { + var browserWidth = document.documentElement.clientWidth; + var browserHeight = document.documentElement.clientHeight; + var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft; + var scrollY = document.documentElement.scrollTop || document.body.scrollTop; + this._pos = // should use actual width/height below + [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY]; + } + + // move input on screen for focus, but hidden behind dialog + this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px'); + inst.settings.onSelect = onSelect; + this._inDialog = true; + this.dpDiv.addClass(this._dialogClass); + this._showDatepicker(this._dialogInput[0]); + if ($.blockUI) + $.blockUI(this.dpDiv); + $.data(this._dialogInput[0], PROP_NAME, inst); + return this; + }, + + /* Detach a datepicker from its control. + @param target element - the target input field or division or span */ + _destroyDatepicker: function(target) { + var $target = $(target); + var inst = $.data(target, PROP_NAME); + if (!$target.hasClass(this.markerClassName)) { + return; + } + var nodeName = target.nodeName.toLowerCase(); + $.removeData(target, PROP_NAME); + if (nodeName == 'input') { + inst.append.remove(); + inst.trigger.remove(); + $target.removeClass(this.markerClassName). + unbind('focus', this._showDatepicker). + unbind('keydown', this._doKeyDown). + unbind('keypress', this._doKeyPress). + unbind('keyup', this._doKeyUp); + } else if (nodeName == 'div' || nodeName == 'span') + $target.removeClass(this.markerClassName).empty(); + }, + + /* Enable the date picker to a jQuery selection. + @param target element - the target input field or division or span */ + _enableDatepicker: function(target) { + var $target = $(target); + var inst = $.data(target, PROP_NAME); + if (!$target.hasClass(this.markerClassName)) { + return; + } + var nodeName = target.nodeName.toLowerCase(); + if (nodeName == 'input') { + target.disabled = false; + inst.trigger.filter('button'). + each(function() { this.disabled = false; }).end(). + filter('img').css({opacity: '1.0', cursor: ''}); + } + else if (nodeName == 'div' || nodeName == 'span') { + var inline = $target.children('.' + this._inlineClass); + inline.children().removeClass('ui-state-disabled'); + inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). + prop("disabled", false); + } + this._disabledInputs = $.map(this._disabledInputs, + function(value) { return (value == target ? null : value); }); // delete entry + }, + + /* Disable the date picker to a jQuery selection. + @param target element - the target input field or division or span */ + _disableDatepicker: function(target) { + var $target = $(target); + var inst = $.data(target, PROP_NAME); + if (!$target.hasClass(this.markerClassName)) { + return; + } + var nodeName = target.nodeName.toLowerCase(); + if (nodeName == 'input') { + target.disabled = true; + inst.trigger.filter('button'). + each(function() { this.disabled = true; }).end(). + filter('img').css({opacity: '0.5', cursor: 'default'}); + } + else if (nodeName == 'div' || nodeName == 'span') { + var inline = $target.children('.' + this._inlineClass); + inline.children().addClass('ui-state-disabled'); + inline.find("select.ui-datepicker-month, select.ui-datepicker-year"). + prop("disabled", true); + } + this._disabledInputs = $.map(this._disabledInputs, + function(value) { return (value == target ? null : value); }); // delete entry + this._disabledInputs[this._disabledInputs.length] = target; + }, + + /* Is the first field in a jQuery collection disabled as a datepicker? + @param target element - the target input field or division or span + @return boolean - true if disabled, false if enabled */ + _isDisabledDatepicker: function(target) { + if (!target) { + return false; + } + for (var i = 0; i < this._disabledInputs.length; i++) { + if (this._disabledInputs[i] == target) + return true; + } + return false; + }, + + /* Retrieve the instance data for the target control. + @param target element - the target input field or division or span + @return object - the associated instance data + @throws error if a jQuery problem getting data */ + _getInst: function(target) { + try { + return $.data(target, PROP_NAME); + } + catch (err) { + throw 'Missing instance data for this datepicker'; + } + }, + + /* Update or retrieve the settings for a date picker attached to an input field or division. + @param target element - the target input field or division or span + @param name object - the new settings to update or + string - the name of the setting to change or retrieve, + when retrieving also 'all' for all instance settings or + 'defaults' for all global defaults + @param value any - the new value for the setting + (omit if above is an object or to retrieve a value) */ + _optionDatepicker: function(target, name, value) { + var inst = this._getInst(target); + if (arguments.length == 2 && typeof name == 'string') { + return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) : + (inst ? (name == 'all' ? $.extend({}, inst.settings) : + this._get(inst, name)) : null)); + } + var settings = name || {}; + if (typeof name == 'string') { + settings = {}; + settings[name] = value; + } + if (inst) { + if (this._curInst == inst) { + this._hideDatepicker(); + } + var date = this._getDateDatepicker(target, true); + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + extendRemove(inst.settings, settings); + // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided + if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined) + inst.settings.minDate = this._formatDate(inst, minDate); + if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined) + inst.settings.maxDate = this._formatDate(inst, maxDate); + this._attachments($(target), inst); + this._autoSize(inst); + this._setDate(inst, date); + this._updateAlternate(inst); + this._updateDatepicker(inst); + } + }, + + // change method deprecated + _changeDatepicker: function(target, name, value) { + this._optionDatepicker(target, name, value); + }, + + /* Redraw the date picker attached to an input field or division. + @param target element - the target input field or division or span */ + _refreshDatepicker: function(target) { + var inst = this._getInst(target); + if (inst) { + this._updateDatepicker(inst); + } + }, + + /* Set the dates for a jQuery selection. + @param target element - the target input field or division or span + @param date Date - the new date */ + _setDateDatepicker: function(target, date) { + var inst = this._getInst(target); + if (inst) { + this._setDate(inst, date); + this._updateDatepicker(inst); + this._updateAlternate(inst); + } + }, + + /* Get the date(s) for the first entry in a jQuery selection. + @param target element - the target input field or division or span + @param noDefault boolean - true if no default date is to be used + @return Date - the current date */ + _getDateDatepicker: function(target, noDefault) { + var inst = this._getInst(target); + if (inst && !inst.inline) + this._setDateFromField(inst, noDefault); + return (inst ? this._getDate(inst) : null); + }, + + /* Handle keystrokes. */ + _doKeyDown: function(event) { + var inst = $.datepicker._getInst(event.target); + var handled = true; + var isRTL = inst.dpDiv.is('.ui-datepicker-rtl'); + inst._keyEvent = true; + if ($.datepicker._datepickerShowing) + switch (event.keyCode) { + case 9: $.datepicker._hideDatepicker(); + handled = false; + break; // hide on tab out + case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' + + $.datepicker._currentClass + ')', inst.dpDiv); + if (sel[0]) + $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]); + var onSelect = $.datepicker._get(inst, 'onSelect'); + if (onSelect) { + var dateStr = $.datepicker._formatDate(inst); + + // trigger custom callback + onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); + } + else + $.datepicker._hideDatepicker(); + return false; // don't submit the form + break; // select the value on enter + case 27: $.datepicker._hideDatepicker(); + break; // hide on escape + case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ? + -$.datepicker._get(inst, 'stepBigMonths') : + -$.datepicker._get(inst, 'stepMonths')), 'M'); + break; // previous month/year on page up/+ ctrl + case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ? + +$.datepicker._get(inst, 'stepBigMonths') : + +$.datepicker._get(inst, 'stepMonths')), 'M'); + break; // next month/year on page down/+ ctrl + case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target); + handled = event.ctrlKey || event.metaKey; + break; // clear on ctrl or command +end + case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target); + handled = event.ctrlKey || event.metaKey; + break; // current on ctrl or command +home + case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D'); + handled = event.ctrlKey || event.metaKey; + // -1 day on ctrl or command +left + if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? + -$.datepicker._get(inst, 'stepBigMonths') : + -$.datepicker._get(inst, 'stepMonths')), 'M'); + // next month/year on alt +left on Mac + break; + case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D'); + handled = event.ctrlKey || event.metaKey; + break; // -1 week on ctrl or command +up + case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D'); + handled = event.ctrlKey || event.metaKey; + // +1 day on ctrl or command +right + if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ? + +$.datepicker._get(inst, 'stepBigMonths') : + +$.datepicker._get(inst, 'stepMonths')), 'M'); + // next month/year on alt +right + break; + case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D'); + handled = event.ctrlKey || event.metaKey; + break; // +1 week on ctrl or command +down + default: handled = false; + } + else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home + $.datepicker._showDatepicker(this); + else { + handled = false; + } + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } + }, + + /* Filter entered characters - based on date format. */ + _doKeyPress: function(event) { + var inst = $.datepicker._getInst(event.target); + if ($.datepicker._get(inst, 'constrainInput')) { + var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat')); + var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode); + return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1); + } + }, + + /* Synchronise manual entry and field/alternate field. */ + _doKeyUp: function(event) { + var inst = $.datepicker._getInst(event.target); + if (inst.input.val() != inst.lastVal) { + try { + var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'), + (inst.input ? inst.input.val() : null), + $.datepicker._getFormatConfig(inst)); + if (date) { // only if valid + $.datepicker._setDateFromField(inst); + $.datepicker._updateAlternate(inst); + $.datepicker._updateDatepicker(inst); + } + } + catch (err) { + $.datepicker.log(err); + } + } + return true; + }, + + /* Pop-up the date picker for a given input field. + If false returned from beforeShow event handler do not show. + @param input element - the input field attached to the date picker or + event - if triggered by focus */ + _showDatepicker: function(input) { + input = input.target || input; + if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger + input = $('input', input.parentNode)[0]; + if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here + return; + var inst = $.datepicker._getInst(input); + if ($.datepicker._curInst && $.datepicker._curInst != inst) { + $.datepicker._curInst.dpDiv.stop(true, true); + if ( inst && $.datepicker._datepickerShowing ) { + $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] ); + } + } + var beforeShow = $.datepicker._get(inst, 'beforeShow'); + var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {}; + if(beforeShowSettings === false){ + //false + return; + } + extendRemove(inst.settings, beforeShowSettings); + inst.lastVal = null; + $.datepicker._lastInput = input; + $.datepicker._setDateFromField(inst); + if ($.datepicker._inDialog) // hide cursor + input.value = ''; + if (!$.datepicker._pos) { // position below input + $.datepicker._pos = $.datepicker._findPos(input); + $.datepicker._pos[1] += input.offsetHeight; // add the height + } + var isFixed = false; + $(input).parents().each(function() { + isFixed |= $(this).css('position') == 'fixed'; + return !isFixed; + }); + var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]}; + $.datepicker._pos = null; + //to avoid flashes on Firefox + inst.dpDiv.empty(); + // determine sizing offscreen + inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'}); + $.datepicker._updateDatepicker(inst); + // fix width for dynamic number of date pickers + // and adjust position before showing + offset = $.datepicker._checkOffset(inst, offset, isFixed); + inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ? + 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none', + left: offset.left + 'px', top: offset.top + 'px'}); + if (!inst.inline) { + var showAnim = $.datepicker._get(inst, 'showAnim'); + var duration = $.datepicker._get(inst, 'duration'); + var postProcess = function() { + var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only + if( !! cover.length ){ + var borders = $.datepicker._getBorders(inst.dpDiv); + cover.css({left: -borders[0], top: -borders[1], + width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()}); + } + }; + inst.dpDiv.zIndex($(input).zIndex()+1); + $.datepicker._datepickerShowing = true; + + // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed + if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) + inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess); + else + inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess); + if (!showAnim || !duration) + postProcess(); + if (inst.input.is(':visible') && !inst.input.is(':disabled')) + inst.input.focus(); + $.datepicker._curInst = inst; + } + }, + + /* Generate the date picker content. */ + _updateDatepicker: function(inst) { + this.maxRows = 4; //Reset the max number of rows being displayed (see #7043) + var borders = $.datepicker._getBorders(inst.dpDiv); + instActive = inst; // for delegate hover events + inst.dpDiv.empty().append(this._generateHTML(inst)); + this._attachHandlers(inst); + var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only + if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6 + cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()}) + } + inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover(); + var numMonths = this._getNumberOfMonths(inst); + var cols = numMonths[1]; + var width = 17; + inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width(''); + if (cols > 1) + inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em'); + inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') + + 'Class']('ui-datepicker-multi'); + inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') + + 'Class']('ui-datepicker-rtl'); + if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input && + // #6694 - don't focus the input if it's already focused + // this breaks the change event in IE + inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement) + inst.input.focus(); + // deffered render of the years select (to avoid flashes on Firefox) + if( inst.yearshtml ){ + var origyearshtml = inst.yearshtml; + setTimeout(function(){ + //assure that inst.yearshtml didn't change. + if( origyearshtml === inst.yearshtml && inst.yearshtml ){ + inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml); + } + origyearshtml = inst.yearshtml = null; + }, 0); + } + }, + + /* Retrieve the size of left and top borders for an element. + @param elem (jQuery object) the element of interest + @return (number[2]) the left and top borders */ + _getBorders: function(elem) { + var convert = function(value) { + return {thin: 1, medium: 2, thick: 3}[value] || value; + }; + return [parseFloat(convert(elem.css('border-left-width'))), + parseFloat(convert(elem.css('border-top-width')))]; + }, + + /* Check positioning to remain on screen. */ + _checkOffset: function(inst, offset, isFixed) { + var dpWidth = inst.dpDiv.outerWidth(); + var dpHeight = inst.dpDiv.outerHeight(); + var inputWidth = inst.input ? inst.input.outerWidth() : 0; + var inputHeight = inst.input ? inst.input.outerHeight() : 0; + var viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()); + var viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop()); + + offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0); + offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0; + offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0; + + // now check if datepicker is showing outside window viewport - move to a better place if so. + offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? + Math.abs(offset.left + dpWidth - viewWidth) : 0); + offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? + Math.abs(dpHeight + inputHeight) : 0); + + return offset; + }, + + /* Find an object's position on the screen. */ + _findPos: function(obj) { + var inst = this._getInst(obj); + var isRTL = this._get(inst, 'isRTL'); + while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) { + obj = obj[isRTL ? 'previousSibling' : 'nextSibling']; + } + var position = $(obj).offset(); + return [position.left, position.top]; + }, + + /* Hide the date picker from view. + @param input element - the input field attached to the date picker */ + _hideDatepicker: function(input) { + var inst = this._curInst; + if (!inst || (input && inst != $.data(input, PROP_NAME))) + return; + if (this._datepickerShowing) { + var showAnim = this._get(inst, 'showAnim'); + var duration = this._get(inst, 'duration'); + var postProcess = function() { + $.datepicker._tidyDialog(inst); + }; + + // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed + if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) + inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess); + else + inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' : + (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess); + if (!showAnim) + postProcess(); + this._datepickerShowing = false; + var onClose = this._get(inst, 'onClose'); + if (onClose) + onClose.apply((inst.input ? inst.input[0] : null), + [(inst.input ? inst.input.val() : ''), inst]); + this._lastInput = null; + if (this._inDialog) { + this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' }); + if ($.blockUI) { + $.unblockUI(); + $('body').append(this.dpDiv); + } + } + this._inDialog = false; + } + }, + + /* Tidy up after a dialog display. */ + _tidyDialog: function(inst) { + inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar'); + }, + + /* Close date picker if clicked elsewhere. */ + _checkExternalClick: function(event) { + if (!$.datepicker._curInst) + return; + + var $target = $(event.target), + inst = $.datepicker._getInst($target[0]); + + if ( ( ( $target[0].id != $.datepicker._mainDivId && + $target.parents('#' + $.datepicker._mainDivId).length == 0 && + !$target.hasClass($.datepicker.markerClassName) && + !$target.closest("." + $.datepicker._triggerClass).length && + $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) || + ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst != inst ) ) + $.datepicker._hideDatepicker(); + }, + + /* Adjust one of the date sub-fields. */ + _adjustDate: function(id, offset, period) { + var target = $(id); + var inst = this._getInst(target[0]); + if (this._isDisabledDatepicker(target[0])) { + return; + } + this._adjustInstDate(inst, offset + + (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning + period); + this._updateDatepicker(inst); + }, + + /* Action for current link. */ + _gotoToday: function(id) { + var target = $(id); + var inst = this._getInst(target[0]); + if (this._get(inst, 'gotoCurrent') && inst.currentDay) { + inst.selectedDay = inst.currentDay; + inst.drawMonth = inst.selectedMonth = inst.currentMonth; + inst.drawYear = inst.selectedYear = inst.currentYear; + } + else { + var date = new Date(); + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + } + this._notifyChange(inst); + this._adjustDate(target); + }, + + /* Action for selecting a new month/year. */ + _selectMonthYear: function(id, select, period) { + var target = $(id); + var inst = this._getInst(target[0]); + inst['selected' + (period == 'M' ? 'Month' : 'Year')] = + inst['draw' + (period == 'M' ? 'Month' : 'Year')] = + parseInt(select.options[select.selectedIndex].value,10); + this._notifyChange(inst); + this._adjustDate(target); + }, + + /* Action for selecting a day. */ + _selectDay: function(id, month, year, td) { + var target = $(id); + if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) { + return; + } + var inst = this._getInst(target[0]); + inst.selectedDay = inst.currentDay = $('a', td).html(); + inst.selectedMonth = inst.currentMonth = month; + inst.selectedYear = inst.currentYear = year; + this._selectDate(id, this._formatDate(inst, + inst.currentDay, inst.currentMonth, inst.currentYear)); + }, + + /* Erase the input field and hide the date picker. */ + _clearDate: function(id) { + var target = $(id); + var inst = this._getInst(target[0]); + this._selectDate(target, ''); + }, + + /* Update the input field with the selected date. */ + _selectDate: function(id, dateStr) { + var target = $(id); + var inst = this._getInst(target[0]); + dateStr = (dateStr != null ? dateStr : this._formatDate(inst)); + if (inst.input) + inst.input.val(dateStr); + this._updateAlternate(inst); + var onSelect = this._get(inst, 'onSelect'); + if (onSelect) + onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback + else if (inst.input) + inst.input.trigger('change'); // fire the change event + if (inst.inline) + this._updateDatepicker(inst); + else { + this._hideDatepicker(); + this._lastInput = inst.input[0]; + if (typeof(inst.input[0]) != 'object') + inst.input.focus(); // restore focus + this._lastInput = null; + } + }, + + /* Update any alternate field to synchronise with the main field. */ + _updateAlternate: function(inst) { + var altField = this._get(inst, 'altField'); + if (altField) { // update alternate field too + var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat'); + var date = this._getDate(inst); + var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst)); + $(altField).each(function() { $(this).val(dateStr); }); + } + }, + + /* Set as beforeShowDay function to prevent selection of weekends. + @param date Date - the date to customise + @return [boolean, string] - is this date selectable?, what is its CSS class? */ + noWeekends: function(date) { + var day = date.getDay(); + return [(day > 0 && day < 6), '']; + }, + + /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition. + @param date Date - the date to get the week for + @return number - the number of the week within the year that contains this date */ + iso8601Week: function(date) { + var checkDate = new Date(date.getTime()); + // Find Thursday of this week starting on Monday + checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7)); + var time = checkDate.getTime(); + checkDate.setMonth(0); // Compare with Jan 1 + checkDate.setDate(1); + return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1; + }, + + /* Parse a string value into a date object. + See formatDate below for the possible formats. + + @param format string - the expected format of the date + @param value string - the date in the above format + @param settings Object - attributes include: + shortYearCutoff number - the cutoff year for determining the century (optional) + dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) + dayNames string[7] - names of the days from Sunday (optional) + monthNamesShort string[12] - abbreviated names of the months (optional) + monthNames string[12] - names of the months (optional) + @return Date - the extracted date value or null if value is blank */ + parseDate: function (format, value, settings) { + if (format == null || value == null) + throw 'Invalid arguments'; + value = (typeof value == 'object' ? value.toString() : value + ''); + if (value == '') + return null; + var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff; + shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : + new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); + var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; + var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; + var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; + var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; + var year = -1; + var month = -1; + var day = -1; + var doy = -1; + var literal = false; + // Check whether a format character is doubled + var lookAhead = function(match) { + var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); + if (matches) + iFormat++; + return matches; + }; + // Extract a number from the string value + var getNumber = function(match) { + var isDoubled = lookAhead(match); + var size = (match == '@' ? 14 : (match == '!' ? 20 : + (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2)))); + var digits = new RegExp('^\\d{1,' + size + '}'); + var num = value.substring(iValue).match(digits); + if (!num) + throw 'Missing number at position ' + iValue; + iValue += num[0].length; + return parseInt(num[0], 10); + }; + // Extract a name from the string value and convert to an index + var getName = function(match, shortNames, longNames) { + var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) { + return [ [k, v] ]; + }).sort(function (a, b) { + return -(a[1].length - b[1].length); + }); + var index = -1; + $.each(names, function (i, pair) { + var name = pair[1]; + if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) { + index = pair[0]; + iValue += name.length; + return false; + } + }); + if (index != -1) + return index + 1; + else + throw 'Unknown name at position ' + iValue; + }; + // Confirm that a literal character matches the string value + var checkLiteral = function() { + if (value.charAt(iValue) != format.charAt(iFormat)) + throw 'Unexpected literal at position ' + iValue; + iValue++; + }; + var iValue = 0; + for (var iFormat = 0; iFormat < format.length; iFormat++) { + if (literal) + if (format.charAt(iFormat) == "'" && !lookAhead("'")) + literal = false; + else + checkLiteral(); + else + switch (format.charAt(iFormat)) { + case 'd': + day = getNumber('d'); + break; + case 'D': + getName('D', dayNamesShort, dayNames); + break; + case 'o': + doy = getNumber('o'); + break; + case 'm': + month = getNumber('m'); + break; + case 'M': + month = getName('M', monthNamesShort, monthNames); + break; + case 'y': + year = getNumber('y'); + break; + case '@': + var date = new Date(getNumber('@')); + year = date.getFullYear(); + month = date.getMonth() + 1; + day = date.getDate(); + break; + case '!': + var date = new Date((getNumber('!') - this._ticksTo1970) / 10000); + year = date.getFullYear(); + month = date.getMonth() + 1; + day = date.getDate(); + break; + case "'": + if (lookAhead("'")) + checkLiteral(); + else + literal = true; + break; + default: + checkLiteral(); + } + } + if (iValue < value.length){ + var extra = value.substr(iValue); + if (!/^\s+/.test(extra)) { + throw "Extra/unparsed characters found in date: " + extra; + } + } + if (year == -1) + year = new Date().getFullYear(); + else if (year < 100) + year += new Date().getFullYear() - new Date().getFullYear() % 100 + + (year <= shortYearCutoff ? 0 : -100); + if (doy > -1) { + month = 1; + day = doy; + do { + var dim = this._getDaysInMonth(year, month - 1); + if (day <= dim) + break; + month++; + day -= dim; + } while (true); + } + var date = this._daylightSavingAdjust(new Date(year, month - 1, day)); + if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day) + throw 'Invalid date'; // E.g. 31/02/00 + return date; + }, + + /* Standard date formats. */ + ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601) + COOKIE: 'D, dd M yy', + ISO_8601: 'yy-mm-dd', + RFC_822: 'D, d M y', + RFC_850: 'DD, dd-M-y', + RFC_1036: 'D, d M y', + RFC_1123: 'D, d M yy', + RFC_2822: 'D, d M yy', + RSS: 'D, d M y', // RFC 822 + TICKS: '!', + TIMESTAMP: '@', + W3C: 'yy-mm-dd', // ISO 8601 + + _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + + Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000), + + /* Format a date object into a string value. + The format can be combinations of the following: + d - day of month (no leading zero) + dd - day of month (two digit) + o - day of year (no leading zeros) + oo - day of year (three digit) + D - day name short + DD - day name long + m - month of year (no leading zero) + mm - month of year (two digit) + M - month name short + MM - month name long + y - year (two digit) + yy - year (four digit) + @ - Unix timestamp (ms since 01/01/1970) + ! - Windows ticks (100ns since 01/01/0001) + '...' - literal text + '' - single quote + + @param format string - the desired format of the date + @param date Date - the date value to format + @param settings Object - attributes include: + dayNamesShort string[7] - abbreviated names of the days from Sunday (optional) + dayNames string[7] - names of the days from Sunday (optional) + monthNamesShort string[12] - abbreviated names of the months (optional) + monthNames string[12] - names of the months (optional) + @return string - the date in the above format */ + formatDate: function (format, date, settings) { + if (!date) + return ''; + var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort; + var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames; + var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort; + var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames; + // Check whether a format character is doubled + var lookAhead = function(match) { + var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); + if (matches) + iFormat++; + return matches; + }; + // Format a number, with leading zero if necessary + var formatNumber = function(match, value, len) { + var num = '' + value; + if (lookAhead(match)) + while (num.length < len) + num = '0' + num; + return num; + }; + // Format a name, short or long as requested + var formatName = function(match, value, shortNames, longNames) { + return (lookAhead(match) ? longNames[value] : shortNames[value]); + }; + var output = ''; + var literal = false; + if (date) + for (var iFormat = 0; iFormat < format.length; iFormat++) { + if (literal) + if (format.charAt(iFormat) == "'" && !lookAhead("'")) + literal = false; + else + output += format.charAt(iFormat); + else + switch (format.charAt(iFormat)) { + case 'd': + output += formatNumber('d', date.getDate(), 2); + break; + case 'D': + output += formatName('D', date.getDay(), dayNamesShort, dayNames); + break; + case 'o': + output += formatNumber('o', + Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3); + break; + case 'm': + output += formatNumber('m', date.getMonth() + 1, 2); + break; + case 'M': + output += formatName('M', date.getMonth(), monthNamesShort, monthNames); + break; + case 'y': + output += (lookAhead('y') ? date.getFullYear() : + (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100); + break; + case '@': + output += date.getTime(); + break; + case '!': + output += date.getTime() * 10000 + this._ticksTo1970; + break; + case "'": + if (lookAhead("'")) + output += "'"; + else + literal = true; + break; + default: + output += format.charAt(iFormat); + } + } + return output; + }, + + /* Extract all possible characters from the date format. */ + _possibleChars: function (format) { + var chars = ''; + var literal = false; + // Check whether a format character is doubled + var lookAhead = function(match) { + var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match); + if (matches) + iFormat++; + return matches; + }; + for (var iFormat = 0; iFormat < format.length; iFormat++) + if (literal) + if (format.charAt(iFormat) == "'" && !lookAhead("'")) + literal = false; + else + chars += format.charAt(iFormat); + else + switch (format.charAt(iFormat)) { + case 'd': case 'm': case 'y': case '@': + chars += '0123456789'; + break; + case 'D': case 'M': + return null; // Accept anything + case "'": + if (lookAhead("'")) + chars += "'"; + else + literal = true; + break; + default: + chars += format.charAt(iFormat); + } + return chars; + }, + + /* Get a setting value, defaulting if necessary. */ + _get: function(inst, name) { + return inst.settings[name] !== undefined ? + inst.settings[name] : this._defaults[name]; + }, + + /* Parse existing date and initialise date picker. */ + _setDateFromField: function(inst, noDefault) { + if (inst.input.val() == inst.lastVal) { + return; + } + var dateFormat = this._get(inst, 'dateFormat'); + var dates = inst.lastVal = inst.input ? inst.input.val() : null; + var date, defaultDate; + date = defaultDate = this._getDefaultDate(inst); + var settings = this._getFormatConfig(inst); + try { + date = this.parseDate(dateFormat, dates, settings) || defaultDate; + } catch (event) { + this.log(event); + dates = (noDefault ? '' : dates); + } + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + inst.currentDay = (dates ? date.getDate() : 0); + inst.currentMonth = (dates ? date.getMonth() : 0); + inst.currentYear = (dates ? date.getFullYear() : 0); + this._adjustInstDate(inst); + }, + + /* Retrieve the default date shown on opening. */ + _getDefaultDate: function(inst) { + return this._restrictMinMax(inst, + this._determineDate(inst, this._get(inst, 'defaultDate'), new Date())); + }, + + /* A date may be specified as an exact value or a relative one. */ + _determineDate: function(inst, date, defaultDate) { + var offsetNumeric = function(offset) { + var date = new Date(); + date.setDate(date.getDate() + offset); + return date; + }; + var offsetString = function(offset) { + try { + return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'), + offset, $.datepicker._getFormatConfig(inst)); + } + catch (e) { + // Ignore + } + var date = (offset.toLowerCase().match(/^c/) ? + $.datepicker._getDate(inst) : null) || new Date(); + var year = date.getFullYear(); + var month = date.getMonth(); + var day = date.getDate(); + var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g; + var matches = pattern.exec(offset); + while (matches) { + switch (matches[2] || 'd') { + case 'd' : case 'D' : + day += parseInt(matches[1],10); break; + case 'w' : case 'W' : + day += parseInt(matches[1],10) * 7; break; + case 'm' : case 'M' : + month += parseInt(matches[1],10); + day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); + break; + case 'y': case 'Y' : + year += parseInt(matches[1],10); + day = Math.min(day, $.datepicker._getDaysInMonth(year, month)); + break; + } + matches = pattern.exec(offset); + } + return new Date(year, month, day); + }; + var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) : + (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime())))); + newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate); + if (newDate) { + newDate.setHours(0); + newDate.setMinutes(0); + newDate.setSeconds(0); + newDate.setMilliseconds(0); + } + return this._daylightSavingAdjust(newDate); + }, + + /* Handle switch to/from daylight saving. + Hours may be non-zero on daylight saving cut-over: + > 12 when midnight changeover, but then cannot generate + midnight datetime, so jump to 1AM, otherwise reset. + @param date (Date) the date to check + @return (Date) the corrected date */ + _daylightSavingAdjust: function(date) { + if (!date) return null; + date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0); + return date; + }, + + /* Set the date(s) directly. */ + _setDate: function(inst, date, noChange) { + var clear = !date; + var origMonth = inst.selectedMonth; + var origYear = inst.selectedYear; + var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date())); + inst.selectedDay = inst.currentDay = newDate.getDate(); + inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth(); + inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear(); + if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange) + this._notifyChange(inst); + this._adjustInstDate(inst); + if (inst.input) { + inst.input.val(clear ? '' : this._formatDate(inst)); + } + }, + + /* Retrieve the date(s) directly. */ + _getDate: function(inst) { + var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null : + this._daylightSavingAdjust(new Date( + inst.currentYear, inst.currentMonth, inst.currentDay))); + return startDate; + }, + + /* Attach the onxxx handlers. These are declared statically so + * they work with static code transformers like Caja. + */ + _attachHandlers: function(inst) { + var stepMonths = this._get(inst, 'stepMonths'); + var id = '#' + inst.id.replace( /\\\\/g, "\\" ); + inst.dpDiv.find('[data-handler]').map(function () { + var handler = { + prev: function () { + window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, -stepMonths, 'M'); + }, + next: function () { + window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, +stepMonths, 'M'); + }, + hide: function () { + window['DP_jQuery_' + dpuuid].datepicker._hideDatepicker(); + }, + today: function () { + window['DP_jQuery_' + dpuuid].datepicker._gotoToday(id); + }, + selectDay: function () { + window['DP_jQuery_' + dpuuid].datepicker._selectDay(id, +this.getAttribute('data-month'), +this.getAttribute('data-year'), this); + return false; + }, + selectMonth: function () { + window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'M'); + return false; + }, + selectYear: function () { + window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'Y'); + return false; + } + }; + $(this).bind(this.getAttribute('data-event'), handler[this.getAttribute('data-handler')]); + }); + }, + + /* Generate the HTML for the current state of the date picker. */ + _generateHTML: function(inst) { + var today = new Date(); + today = this._daylightSavingAdjust( + new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time + var isRTL = this._get(inst, 'isRTL'); + var showButtonPanel = this._get(inst, 'showButtonPanel'); + var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext'); + var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat'); + var numMonths = this._getNumberOfMonths(inst); + var showCurrentAtPos = this._get(inst, 'showCurrentAtPos'); + var stepMonths = this._get(inst, 'stepMonths'); + var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1); + var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) : + new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + var drawMonth = inst.drawMonth - showCurrentAtPos; + var drawYear = inst.drawYear; + if (drawMonth < 0) { + drawMonth += 12; + drawYear--; + } + if (maxDate) { + var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), + maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate())); + maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw); + while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) { + drawMonth--; + if (drawMonth < 0) { + drawMonth = 11; + drawYear--; + } + } + } + inst.drawMonth = drawMonth; + inst.drawYear = drawYear; + var prevText = this._get(inst, 'prevText'); + prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText, + this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), + this._getFormatConfig(inst))); + var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ? + '<a class="ui-datepicker-prev ui-corner-all" data-handler="prev" data-event="click"' + + ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' : + (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>')); + var nextText = this._get(inst, 'nextText'); + nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText, + this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), + this._getFormatConfig(inst))); + var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ? + '<a class="ui-datepicker-next ui-corner-all" data-handler="next" data-event="click"' + + ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' : + (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>')); + var currentText = this._get(inst, 'currentText'); + var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today); + currentText = (!navigationAsDateFormat ? currentText : + this.formatDate(currentText, gotoDate, this._getFormatConfig(inst))); + var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" data-handler="hide" data-event="click">' + + this._get(inst, 'closeText') + '</button>' : ''); + var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') + + (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" data-handler="today" data-event="click"' + + '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : ''; + var firstDay = parseInt(this._get(inst, 'firstDay'),10); + firstDay = (isNaN(firstDay) ? 0 : firstDay); + var showWeek = this._get(inst, 'showWeek'); + var dayNames = this._get(inst, 'dayNames'); + var dayNamesShort = this._get(inst, 'dayNamesShort'); + var dayNamesMin = this._get(inst, 'dayNamesMin'); + var monthNames = this._get(inst, 'monthNames'); + var monthNamesShort = this._get(inst, 'monthNamesShort'); + var beforeShowDay = this._get(inst, 'beforeShowDay'); + var showOtherMonths = this._get(inst, 'showOtherMonths'); + var selectOtherMonths = this._get(inst, 'selectOtherMonths'); + var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week; + var defaultDate = this._getDefaultDate(inst); + var html = ''; + for (var row = 0; row < numMonths[0]; row++) { + var group = ''; + this.maxRows = 4; + for (var col = 0; col < numMonths[1]; col++) { + var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay)); + var cornerClass = ' ui-corner-all'; + var calender = ''; + if (isMultiMonth) { + calender += '<div class="ui-datepicker-group'; + if (numMonths[1] > 1) + switch (col) { + case 0: calender += ' ui-datepicker-group-first'; + cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break; + case numMonths[1]-1: calender += ' ui-datepicker-group-last'; + cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break; + default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break; + } + calender += '">'; + } + calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' + + (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') + + (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') + + this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, + row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers + '</div><table class="ui-datepicker-calendar"><thead>' + + '<tr>'; + var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : ''); + for (var dow = 0; dow < 7; dow++) { // days of the week + var day = (dow + firstDay) % 7; + thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' + + '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>'; + } + calender += thead + '</tr></thead><tbody>'; + var daysInMonth = this._getDaysInMonth(drawYear, drawMonth); + if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth) + inst.selectedDay = Math.min(inst.selectedDay, daysInMonth); + var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7; + var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate + var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043) + this.maxRows = numRows; + var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays)); + for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows + calender += '<tr>'; + var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' + + this._get(inst, 'calculateWeek')(printDate) + '</td>'); + for (var dow = 0; dow < 7; dow++) { // create date picker days + var daySettings = (beforeShowDay ? + beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']); + var otherMonth = (printDate.getMonth() != drawMonth); + var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] || + (minDate && printDate < minDate) || (maxDate && printDate > maxDate); + tbody += '<td class="' + + ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends + (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months + ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key + (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ? + // or defaultDate is current printedDate and defaultDate is selectedDate + ' ' + this._dayOverClass : '') + // highlight selected day + (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days + (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates + (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day + (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different) + ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title + (unselectable ? '' : ' data-handler="selectDay" data-event="click" data-month="' + printDate.getMonth() + '" data-year="' + printDate.getFullYear() + '"') + '>' + // actions + (otherMonth && !showOtherMonths ? ' ' : // display for other months + (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' + + (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') + + (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day + (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months + '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date + printDate.setDate(printDate.getDate() + 1); + printDate = this._daylightSavingAdjust(printDate); + } + calender += tbody + '</tr>'; + } + drawMonth++; + if (drawMonth > 11) { + drawMonth = 0; + drawYear++; + } + calender += '</tbody></table>' + (isMultiMonth ? '</div>' + + ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : ''); + group += calender; + } + html += group; + } + html += buttonPanel + ($.ui.ie6 && !inst.inline ? + '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : ''); + inst._keyEvent = false; + return html; + }, + + /* Generate the month and year header. */ + _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, + secondary, monthNames, monthNamesShort) { + var changeMonth = this._get(inst, 'changeMonth'); + var changeYear = this._get(inst, 'changeYear'); + var showMonthAfterYear = this._get(inst, 'showMonthAfterYear'); + var html = '<div class="ui-datepicker-title">'; + var monthHtml = ''; + // month selection + if (secondary || !changeMonth) + monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>'; + else { + var inMinYear = (minDate && minDate.getFullYear() == drawYear); + var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear); + monthHtml += '<select class="ui-datepicker-month" data-handler="selectMonth" data-event="change">'; + for (var month = 0; month < 12; month++) { + if ((!inMinYear || month >= minDate.getMonth()) && + (!inMaxYear || month <= maxDate.getMonth())) + monthHtml += '<option value="' + month + '"' + + (month == drawMonth ? ' selected="selected"' : '') + + '>' + monthNamesShort[month] + '</option>'; + } + monthHtml += '</select>'; + } + if (!showMonthAfterYear) + html += monthHtml + (secondary || !(changeMonth && changeYear) ? ' ' : ''); + // year selection + if ( !inst.yearshtml ) { + inst.yearshtml = ''; + if (secondary || !changeYear) + html += '<span class="ui-datepicker-year">' + drawYear + '</span>'; + else { + // determine range of years to display + var years = this._get(inst, 'yearRange').split(':'); + var thisYear = new Date().getFullYear(); + var determineYear = function(value) { + var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) : + (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) : + parseInt(value, 10))); + return (isNaN(year) ? thisYear : year); + }; + var year = determineYear(years[0]); + var endYear = Math.max(year, determineYear(years[1] || '')); + year = (minDate ? Math.max(year, minDate.getFullYear()) : year); + endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear); + inst.yearshtml += '<select class="ui-datepicker-year" data-handler="selectYear" data-event="change">'; + for (; year <= endYear; year++) { + inst.yearshtml += '<option value="' + year + '"' + + (year == drawYear ? ' selected="selected"' : '') + + '>' + year + '</option>'; + } + inst.yearshtml += '</select>'; + + html += inst.yearshtml; + inst.yearshtml = null; + } + } + html += this._get(inst, 'yearSuffix'); + if (showMonthAfterYear) + html += (secondary || !(changeMonth && changeYear) ? ' ' : '') + monthHtml; + html += '</div>'; // Close datepicker_header + return html; + }, + + /* Adjust one of the date sub-fields. */ + _adjustInstDate: function(inst, offset, period) { + var year = inst.drawYear + (period == 'Y' ? offset : 0); + var month = inst.drawMonth + (period == 'M' ? offset : 0); + var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + + (period == 'D' ? offset : 0); + var date = this._restrictMinMax(inst, + this._daylightSavingAdjust(new Date(year, month, day))); + inst.selectedDay = date.getDate(); + inst.drawMonth = inst.selectedMonth = date.getMonth(); + inst.drawYear = inst.selectedYear = date.getFullYear(); + if (period == 'M' || period == 'Y') + this._notifyChange(inst); + }, + + /* Ensure a date is within any min/max bounds. */ + _restrictMinMax: function(inst, date) { + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + var newDate = (minDate && date < minDate ? minDate : date); + newDate = (maxDate && newDate > maxDate ? maxDate : newDate); + return newDate; + }, + + /* Notify change of month/year. */ + _notifyChange: function(inst) { + var onChange = this._get(inst, 'onChangeMonthYear'); + if (onChange) + onChange.apply((inst.input ? inst.input[0] : null), + [inst.selectedYear, inst.selectedMonth + 1, inst]); + }, + + /* Determine the number of months to show. */ + _getNumberOfMonths: function(inst) { + var numMonths = this._get(inst, 'numberOfMonths'); + return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths)); + }, + + /* Determine the current maximum date - ensure no time components are set. */ + _getMinMaxDate: function(inst, minMax) { + return this._determineDate(inst, this._get(inst, minMax + 'Date'), null); + }, + + /* Find the number of days in a given month. */ + _getDaysInMonth: function(year, month) { + return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate(); + }, + + /* Find the day of the week of the first of a month. */ + _getFirstDayOfMonth: function(year, month) { + return new Date(year, month, 1).getDay(); + }, + + /* Determines if we should allow a "next/prev" month display change. */ + _canAdjustMonth: function(inst, offset, curYear, curMonth) { + var numMonths = this._getNumberOfMonths(inst); + var date = this._daylightSavingAdjust(new Date(curYear, + curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1)); + if (offset < 0) + date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth())); + return this._isInRange(inst, date); + }, + + /* Is the given date in the accepted range? */ + _isInRange: function(inst, date) { + var minDate = this._getMinMaxDate(inst, 'min'); + var maxDate = this._getMinMaxDate(inst, 'max'); + return ((!minDate || date.getTime() >= minDate.getTime()) && + (!maxDate || date.getTime() <= maxDate.getTime())); + }, + + /* Provide the configuration settings for formatting/parsing. */ + _getFormatConfig: function(inst) { + var shortYearCutoff = this._get(inst, 'shortYearCutoff'); + shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff : + new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)); + return {shortYearCutoff: shortYearCutoff, + dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'), + monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')}; + }, + + /* Format the given date for display. */ + _formatDate: function(inst, day, month, year) { + if (!day) { + inst.currentDay = inst.selectedDay; + inst.currentMonth = inst.selectedMonth; + inst.currentYear = inst.selectedYear; + } + var date = (day ? (typeof day == 'object' ? day : + this._daylightSavingAdjust(new Date(year, month, day))) : + this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay))); + return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst)); + } +}); + +/* + * Bind hover events for datepicker elements. + * Done via delegate so the binding only occurs once in the lifetime of the parent div. + * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker. + */ +function bindHover(dpDiv) { + var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a'; + return dpDiv.delegate(selector, 'mouseout', function() { + $(this).removeClass('ui-state-hover'); + if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover'); + if (this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover'); + }) + .delegate(selector, 'mouseover', function(){ + if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) { + $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover'); + $(this).addClass('ui-state-hover'); + if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover'); + if (this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover'); + } + }); +} + +/* jQuery extend now ignores nulls! */ +function extendRemove(target, props) { + $.extend(target, props); + for (var name in props) + if (props[name] == null || props[name] == undefined) + target[name] = props[name]; + return target; +}; + +/* Invoke the datepicker functionality. + @param options string - a command, optionally followed by additional parameters or + Object - settings for attaching new datepicker functionality + @return jQuery object */ +$.fn.datepicker = function(options){ + + /* Verify an empty collection wasn't passed - Fixes #6976 */ + if ( !this.length ) { + return this; + } + + /* Initialise the date picker. */ + if (!$.datepicker.initialized) { + $(document).mousedown($.datepicker._checkExternalClick). + find(document.body).append($.datepicker.dpDiv); + $.datepicker.initialized = true; + } + + var otherArgs = Array.prototype.slice.call(arguments, 1); + if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget')) + return $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this[0]].concat(otherArgs)); + if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string') + return $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this[0]].concat(otherArgs)); + return this.each(function() { + typeof options == 'string' ? + $.datepicker['_' + options + 'Datepicker']. + apply($.datepicker, [this].concat(otherArgs)) : + $.datepicker._attachDatepicker(this, options); + }); +}; + +$.datepicker = new Datepicker(); // singleton instance +$.datepicker.initialized = false; +$.datepicker.uuid = new Date().getTime(); +$.datepicker.version = "@VERSION"; + +// Workaround for #4055 +// Add another global to avoid noConflict issues with inline event handlers +window['DP_jQuery_' + dpuuid] = $; + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.dialog.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.dialog.js new file mode 100644 index 0000000..a031eb5 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.dialog.js @@ -0,0 +1,858 @@ +/*! + * jQuery UI Dialog @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/dialog/ + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.button.js + * jquery.ui.draggable.js + * jquery.ui.mouse.js + * jquery.ui.position.js + * jquery.ui.resizable.js + */ +(function( $, undefined ) { + +var uiDialogClasses = "ui-dialog ui-widget ui-widget-content ui-corner-all ", + sizeRelatedOptions = { + buttons: true, + height: true, + maxHeight: true, + maxWidth: true, + minHeight: true, + minWidth: true, + width: true + }, + resizableRelatedOptions = { + maxHeight: true, + maxWidth: true, + minHeight: true, + minWidth: true + }; + +$.widget("ui.dialog", { + version: "@VERSION", + options: { + autoOpen: true, + buttons: {}, + closeOnEscape: true, + closeText: "close", + dialogClass: "", + draggable: true, + hide: null, + height: "auto", + maxHeight: false, + maxWidth: false, + minHeight: 150, + minWidth: 150, + modal: false, + position: { + my: "center", + at: "center", + of: window, + collision: "fit", + // ensure that the titlebar is never outside the document + using: function( pos ) { + var topOffset = $( this ).css( pos ).offset().top; + if ( topOffset < 0 ) { + $( this ).css( "top", pos.top - topOffset ); + } + } + }, + resizable: true, + show: null, + stack: true, + title: "", + width: 300, + zIndex: 1000 + }, + + _create: function() { + this.originalTitle = this.element.attr( "title" ); + // #5742 - .attr() might return a DOMElement + if ( typeof this.originalTitle !== "string" ) { + this.originalTitle = ""; + } + this.oldPosition = { + parent: this.element.parent(), + index: this.element.parent().children().index( this.element ) + }; + this.options.title = this.options.title || this.originalTitle; + var that = this, + options = this.options, + + title = options.title || " ", + uiDialog, + uiDialogTitlebar, + uiDialogTitlebarClose, + uiDialogTitle, + uiDialogButtonPane; + + uiDialog = ( this.uiDialog = $( "<div>" ) ) + .addClass( uiDialogClasses + options.dialogClass ) + .css({ + display: "none", + outline: 0, // TODO: move to stylesheet + zIndex: options.zIndex + }) + // setting tabIndex makes the div focusable + .attr( "tabIndex", -1) + .keydown(function( event ) { + if ( options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && + event.keyCode === $.ui.keyCode.ESCAPE ) { + that.close( event ); + event.preventDefault(); + } + }) + .mousedown(function( event ) { + that.moveToTop( false, event ); + }) + .appendTo( "body" ); + + this.element + .show() + .removeAttr( "title" ) + .addClass( "ui-dialog-content ui-widget-content" ) + .appendTo( uiDialog ); + + uiDialogTitlebar = ( this.uiDialogTitlebar = $( "<div>" ) ) + .addClass( "ui-dialog-titlebar ui-widget-header " + + "ui-corner-all ui-helper-clearfix" ) + .bind( "mousedown", function() { + // Dialog isn't getting focus when dragging (#8063) + uiDialog.focus(); + }) + .prependTo( uiDialog ); + + uiDialogTitlebarClose = $( "<a href='#'></a>" ) + .addClass( "ui-dialog-titlebar-close ui-corner-all" ) + .attr( "role", "button" ) + .click(function( event ) { + event.preventDefault(); + that.close( event ); + }) + .appendTo( uiDialogTitlebar ); + + ( this.uiDialogTitlebarCloseText = $( "<span>" ) ) + .addClass( "ui-icon ui-icon-closethick" ) + .text( options.closeText ) + .appendTo( uiDialogTitlebarClose ); + + uiDialogTitle = $( "<span>" ) + .uniqueId() + .addClass( "ui-dialog-title" ) + .html( title ) + .prependTo( uiDialogTitlebar ); + + uiDialogButtonPane = ( this.uiDialogButtonPane = $( "<div>" ) ) + .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" ); + + ( this.uiButtonSet = $( "<div>" ) ) + .addClass( "ui-dialog-buttonset" ) + .appendTo( uiDialogButtonPane ); + + uiDialog.attr({ + role: "dialog", + "aria-labelledby": uiDialogTitle.attr( "id" ) + }); + + uiDialogTitlebar.find( "*" ).add( uiDialogTitlebar ).disableSelection(); + this._hoverable( uiDialogTitlebarClose ); + this._focusable( uiDialogTitlebarClose ); + + if ( options.draggable && $.fn.draggable ) { + this._makeDraggable(); + } + if ( options.resizable && $.fn.resizable ) { + this._makeResizable(); + } + + this._createButtons( options.buttons ); + this._isOpen = false; + + if ( $.fn.bgiframe ) { + uiDialog.bgiframe(); + } + + // prevent tabbing out of modal dialogs + this._on( uiDialog, { keydown: function( event ) { + if ( !options.modal || event.keyCode !== $.ui.keyCode.TAB ) { + return; + } + + var tabbables = $( ":tabbable", uiDialog ), + first = tabbables.filter( ":first" ), + last = tabbables.filter( ":last" ); + + if ( event.target === last[0] && !event.shiftKey ) { + first.focus( 1 ); + return false; + } else if ( event.target === first[0] && event.shiftKey ) { + last.focus( 1 ); + return false; + } + }}); + }, + + _init: function() { + if ( this.options.autoOpen ) { + this.open(); + } + }, + + _destroy: function() { + var next, + oldPosition = this.oldPosition; + + if ( this.overlay ) { + this.overlay.destroy(); + } + this.uiDialog.hide(); + this.element + .removeClass( "ui-dialog-content ui-widget-content" ) + .hide() + .appendTo( "body" ); + this.uiDialog.remove(); + + if ( this.originalTitle ) { + this.element.attr( "title", this.originalTitle ); + } + + next = oldPosition.parent.children().eq( oldPosition.index ); + // Don't try to place the dialog next to itself (#8613) + if ( next.length && next[ 0 ] !== this.element[ 0 ] ) { + next.before( this.element ); + } else { + oldPosition.parent.append( this.element ); + } + }, + + widget: function() { + return this.uiDialog; + }, + + close: function( event ) { + var that = this, + maxZ, thisZ; + + if ( !this._isOpen ) { + return; + } + + if ( false === this._trigger( "beforeClose", event ) ) { + return; + } + + this._isOpen = false; + + if ( this.overlay ) { + this.overlay.destroy(); + } + + if ( this.options.hide ) { + this._hide( this.uiDialog, this.options.hide, function() { + that._trigger( "close", event ); + }); + } else { + this.uiDialog.hide(); + this._trigger( "close", event ); + } + + $.ui.dialog.overlay.resize(); + + // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) + if ( this.options.modal ) { + maxZ = 0; + $( ".ui-dialog" ).each(function() { + if ( this !== that.uiDialog[0] ) { + thisZ = $( this ).css( "z-index" ); + if ( !isNaN( thisZ ) ) { + maxZ = Math.max( maxZ, thisZ ); + } + } + }); + $.ui.dialog.maxZ = maxZ; + } + + return this; + }, + + isOpen: function() { + return this._isOpen; + }, + + // the force parameter allows us to move modal dialogs to their correct + // position on open + moveToTop: function( force, event ) { + var options = this.options, + saveScroll; + + if ( ( options.modal && !force ) || + ( !options.stack && !options.modal ) ) { + return this._trigger( "focus", event ); + } + + if ( options.zIndex > $.ui.dialog.maxZ ) { + $.ui.dialog.maxZ = options.zIndex; + } + if ( this.overlay ) { + $.ui.dialog.maxZ += 1; + $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ; + this.overlay.$el.css( "z-index", $.ui.dialog.overlay.maxZ ); + } + + // Save and then restore scroll + // Opera 9.5+ resets when parent z-index is changed. + // http://bugs.jqueryui.com/ticket/3193 + saveScroll = { + scrollTop: this.element.scrollTop(), + scrollLeft: this.element.scrollLeft() + }; + $.ui.dialog.maxZ += 1; + this.uiDialog.css( "z-index", $.ui.dialog.maxZ ); + this.element.attr( saveScroll ); + this._trigger( "focus", event ); + + return this; + }, + + open: function() { + if ( this._isOpen ) { + return; + } + + var hasFocus, + options = this.options, + uiDialog = this.uiDialog; + + this._size(); + this._position( options.position ); + uiDialog.show( options.show ); + this.overlay = options.modal ? new $.ui.dialog.overlay( this ) : null; + this.moveToTop( true ); + + // set focus to the first tabbable element in the content area or the first button + // if there are no tabbable elements, set focus on the dialog itself + hasFocus = this.element.find( ":tabbable" ); + if ( !hasFocus.length ) { + hasFocus = this.uiDialogButtonPane.find( ":tabbable" ); + if ( !hasFocus.length ) { + hasFocus = uiDialog; + } + } + hasFocus.eq( 0 ).focus(); + + this._isOpen = true; + this._trigger( "open" ); + + return this; + }, + + _createButtons: function( buttons ) { + var that = this, + hasButtons = false; + + // if we already have a button pane, remove it + this.uiDialogButtonPane.remove(); + this.uiButtonSet.empty(); + + if ( typeof buttons === "object" && buttons !== null ) { + $.each( buttons, function() { + return !(hasButtons = true); + }); + } + if ( hasButtons ) { + $.each( buttons, function( name, props ) { + var button, click; + props = $.isFunction( props ) ? + { click: props, text: name } : + props; + // Default to a non-submitting button + props = $.extend( { type: "button" }, props ); + // Change the context for the click callback to be the main element + click = props.click; + props.click = function() { + click.apply( that.element[0], arguments ); + }; + button = $( "<button></button>", props ) + .appendTo( that.uiButtonSet ); + if ( $.fn.button ) { + button.button(); + } + }); + this.uiDialog.addClass( "ui-dialog-buttons" ); + this.uiDialogButtonPane.appendTo( this.uiDialog ); + } else { + this.uiDialog.removeClass( "ui-dialog-buttons" ); + } + }, + + _makeDraggable: function() { + var that = this, + options = this.options; + + function filteredUi( ui ) { + return { + position: ui.position, + offset: ui.offset + }; + } + + this.uiDialog.draggable({ + cancel: ".ui-dialog-content, .ui-dialog-titlebar-close", + handle: ".ui-dialog-titlebar", + containment: "document", + start: function( event, ui ) { + $( this ) + .addClass( "ui-dialog-dragging" ); + that._trigger( "dragStart", event, filteredUi( ui ) ); + }, + drag: function( event, ui ) { + that._trigger( "drag", event, filteredUi( ui ) ); + }, + stop: function( event, ui ) { + options.position = [ + ui.position.left - that.document.scrollLeft(), + ui.position.top - that.document.scrollTop() + ]; + $( this ) + .removeClass( "ui-dialog-dragging" ); + that._trigger( "dragStop", event, filteredUi( ui ) ); + $.ui.dialog.overlay.resize(); + } + }); + }, + + _makeResizable: function( handles ) { + handles = (handles === undefined ? this.options.resizable : handles); + var that = this, + options = this.options, + // .ui-resizable has position: relative defined in the stylesheet + // but dialogs have to use absolute or fixed positioning + position = this.uiDialog.css( "position" ), + resizeHandles = typeof handles === 'string' ? + handles : + "n,e,s,w,se,sw,ne,nw"; + + function filteredUi( ui ) { + return { + originalPosition: ui.originalPosition, + originalSize: ui.originalSize, + position: ui.position, + size: ui.size + }; + } + + this.uiDialog.resizable({ + cancel: ".ui-dialog-content", + containment: "document", + alsoResize: this.element, + maxWidth: options.maxWidth, + maxHeight: options.maxHeight, + minWidth: options.minWidth, + minHeight: this._minHeight(), + handles: resizeHandles, + start: function( event, ui ) { + $( this ).addClass( "ui-dialog-resizing" ); + that._trigger( "resizeStart", event, filteredUi( ui ) ); + }, + resize: function( event, ui ) { + that._trigger( "resize", event, filteredUi( ui ) ); + }, + stop: function( event, ui ) { + $( this ).removeClass( "ui-dialog-resizing" ); + options.height = $( this ).height(); + options.width = $( this ).width(); + that._trigger( "resizeStop", event, filteredUi( ui ) ); + $.ui.dialog.overlay.resize(); + } + }) + .css( "position", position ) + .find( ".ui-resizable-se" ) + .addClass( "ui-icon ui-icon-grip-diagonal-se" ); + }, + + _minHeight: function() { + var options = this.options; + + if ( options.height === "auto" ) { + return options.minHeight; + } else { + return Math.min( options.minHeight, options.height ); + } + }, + + _position: function( position ) { + var myAt = [], + offset = [ 0, 0 ], + isVisible; + + if ( position ) { + // deep extending converts arrays to objects in jQuery <= 1.3.2 :-( + // if (typeof position == 'string' || $.isArray(position)) { + // myAt = $.isArray(position) ? position : position.split(' '); + + if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) { + myAt = position.split ? position.split( " " ) : [ position[ 0 ], position[ 1 ] ]; + if ( myAt.length === 1 ) { + myAt[ 1 ] = myAt[ 0 ]; + } + + $.each( [ "left", "top" ], function( i, offsetPosition ) { + if ( +myAt[ i ] === myAt[ i ] ) { + offset[ i ] = myAt[ i ]; + myAt[ i ] = offsetPosition; + } + }); + + position = { + my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " + + myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]), + at: myAt.join( " " ) + }; + } + + position = $.extend( {}, $.ui.dialog.prototype.options.position, position ); + } else { + position = $.ui.dialog.prototype.options.position; + } + + // need to show the dialog to get the actual offset in the position plugin + isVisible = this.uiDialog.is( ":visible" ); + if ( !isVisible ) { + this.uiDialog.show(); + } + this.uiDialog.position( position ); + if ( !isVisible ) { + this.uiDialog.hide(); + } + }, + + _setOptions: function( options ) { + var that = this, + resizableOptions = {}, + resize = false; + + $.each( options, function( key, value ) { + that._setOption( key, value ); + + if ( key in sizeRelatedOptions ) { + resize = true; + } + if ( key in resizableRelatedOptions ) { + resizableOptions[ key ] = value; + } + }); + + if ( resize ) { + this._size(); + } + if ( this.uiDialog.is( ":data(resizable)" ) ) { + this.uiDialog.resizable( "option", resizableOptions ); + } + }, + + _setOption: function( key, value ) { + var isDraggable, isResizable, + uiDialog = this.uiDialog; + + switch ( key ) { + case "buttons": + this._createButtons( value ); + break; + case "closeText": + // ensure that we always pass a string + this.uiDialogTitlebarCloseText.text( "" + value ); + break; + case "dialogClass": + uiDialog + .removeClass( this.options.dialogClass ) + .addClass( uiDialogClasses + value ); + break; + case "disabled": + if ( value ) { + uiDialog.addClass( "ui-dialog-disabled" ); + } else { + uiDialog.removeClass( "ui-dialog-disabled" ); + } + break; + case "draggable": + isDraggable = uiDialog.is( ":data(draggable)" ); + if ( isDraggable && !value ) { + uiDialog.draggable( "destroy" ); + } + + if ( !isDraggable && value ) { + this._makeDraggable(); + } + break; + case "position": + this._position( value ); + break; + case "resizable": + // currently resizable, becoming non-resizable + isResizable = uiDialog.is( ":data(resizable)" ); + if ( isResizable && !value ) { + uiDialog.resizable( "destroy" ); + } + + // currently resizable, changing handles + if ( isResizable && typeof value === "string" ) { + uiDialog.resizable( "option", "handles", value ); + } + + // currently non-resizable, becoming resizable + if ( !isResizable && value !== false ) { + this._makeResizable( value ); + } + break; + case "title": + // convert whatever was passed in o a string, for html() to not throw up + $( ".ui-dialog-title", this.uiDialogTitlebar ) + .html( "" + ( value || " " ) ); + break; + } + + this._super( key, value ); + }, + + _size: function() { + /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content + * divs will both have width and height set, so we need to reset them + */ + var nonContentHeight, minContentHeight, autoHeight, + options = this.options, + isVisible = this.uiDialog.is( ":visible" ); + + // reset content sizing + this.element.show().css({ + width: "auto", + minHeight: 0, + height: 0 + }); + + if ( options.minWidth > options.width ) { + options.width = options.minWidth; + } + + // reset wrapper sizing + // determine the height of all the non-content elements + nonContentHeight = this.uiDialog.css({ + height: "auto", + width: options.width + }) + .outerHeight(); + minContentHeight = Math.max( 0, options.minHeight - nonContentHeight ); + + if ( options.height === "auto" ) { + // only needed for IE6 support + if ( $.support.minHeight ) { + this.element.css({ + minHeight: minContentHeight, + height: "auto" + }); + } else { + this.uiDialog.show(); + autoHeight = this.element.css( "height", "auto" ).height(); + if ( !isVisible ) { + this.uiDialog.hide(); + } + this.element.height( Math.max( autoHeight, minContentHeight ) ); + } + } else { + this.element.height( Math.max( options.height - nonContentHeight, 0 ) ); + } + + if (this.uiDialog.is( ":data(resizable)" ) ) { + this.uiDialog.resizable( "option", "minHeight", this._minHeight() ); + } + } +}); + +$.extend($.ui.dialog, { + uuid: 0, + maxZ: 0, + + getTitleId: function($el) { + var id = $el.attr( "id" ); + if ( !id ) { + this.uuid += 1; + id = this.uuid; + } + return "ui-dialog-title-" + id; + }, + + overlay: function( dialog ) { + this.$el = $.ui.dialog.overlay.create( dialog ); + } +}); + +$.extend( $.ui.dialog.overlay, { + instances: [], + // reuse old instances due to IE memory leak with alpha transparency (see #5185) + oldInstances: [], + maxZ: 0, + events: $.map( + "focus,mousedown,mouseup,keydown,keypress,click".split( "," ), + function( event ) { + return event + ".dialog-overlay"; + } + ).join( " " ), + create: function( dialog ) { + if ( this.instances.length === 0 ) { + // prevent use of anchors and inputs + // we use a setTimeout in case the overlay is created from an + // event that we're going to be cancelling (see #2804) + setTimeout(function() { + // handle $(el).dialog().dialog('close') (see #4065) + if ( $.ui.dialog.overlay.instances.length ) { + $( document ).bind( $.ui.dialog.overlay.events, function( event ) { + // stop events if the z-index of the target is < the z-index of the overlay + // we cannot return true when we don't want to cancel the event (#3523) + if ( $( event.target ).zIndex() < $.ui.dialog.overlay.maxZ ) { + return false; + } + }); + } + }, 1 ); + + // handle window resize + $( window ).bind( "resize.dialog-overlay", $.ui.dialog.overlay.resize ); + } + + var $el = ( this.oldInstances.pop() || $( "<div>" ).addClass( "ui-widget-overlay" ) ); + + // allow closing by pressing the escape key + $( document ).bind( "keydown.dialog-overlay", function( event ) { + var instances = $.ui.dialog.overlay.instances; + // only react to the event if we're the top overlay + if ( instances.length !== 0 && instances[ instances.length - 1 ] === $el && + dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && + event.keyCode === $.ui.keyCode.ESCAPE ) { + + dialog.close( event ); + event.preventDefault(); + } + }); + + $el.appendTo( document.body ).css({ + width: this.width(), + height: this.height() + }); + + if ( $.fn.bgiframe ) { + $el.bgiframe(); + } + + this.instances.push( $el ); + return $el; + }, + + destroy: function( $el ) { + var indexOf = $.inArray( $el, this.instances ), + maxZ = 0; + + if ( indexOf !== -1 ) { + this.oldInstances.push( this.instances.splice( indexOf, 1 )[ 0 ] ); + } + + if ( this.instances.length === 0 ) { + $( [ document, window ] ).unbind( ".dialog-overlay" ); + } + + $el.height( 0 ).width( 0 ).remove(); + + // adjust the maxZ to allow other modal dialogs to continue to work (see #4309) + $.each( this.instances, function() { + maxZ = Math.max( maxZ, this.css( "z-index" ) ); + }); + this.maxZ = maxZ; + }, + + height: function() { + var scrollHeight, + offsetHeight; + // handle IE + if ( $.ui.ie ) { + scrollHeight = Math.max( + document.documentElement.scrollHeight, + document.body.scrollHeight + ); + offsetHeight = Math.max( + document.documentElement.offsetHeight, + document.body.offsetHeight + ); + + if ( scrollHeight < offsetHeight ) { + return $( window ).height() + "px"; + } else { + return scrollHeight + "px"; + } + // handle "good" browsers + } else { + return $( document ).height() + "px"; + } + }, + + width: function() { + var scrollWidth, + offsetWidth; + // handle IE + if ( $.ui.ie ) { + scrollWidth = Math.max( + document.documentElement.scrollWidth, + document.body.scrollWidth + ); + offsetWidth = Math.max( + document.documentElement.offsetWidth, + document.body.offsetWidth + ); + + if ( scrollWidth < offsetWidth ) { + return $( window ).width() + "px"; + } else { + return scrollWidth + "px"; + } + // handle "good" browsers + } else { + return $( document ).width() + "px"; + } + }, + + resize: function() { + /* If the dialog is draggable and the user drags it past the + * right edge of the window, the document becomes wider so we + * need to stretch the overlay. If the user then drags the + * dialog back to the left, the document will become narrower, + * so we need to shrink the overlay to the appropriate size. + * This is handled by shrinking the overlay before setting it + * to the full document size. + */ + var $overlays = $( [] ); + $.each( $.ui.dialog.overlay.instances, function() { + $overlays = $overlays.add( this ); + }); + + $overlays.css({ + width: 0, + height: 0 + }).css({ + width: $.ui.dialog.overlay.width(), + height: $.ui.dialog.overlay.height() + }); + } +}); + +$.extend( $.ui.dialog.overlay.prototype, { + destroy: function() { + $.ui.dialog.overlay.destroy( this.$el ); + } +}); + +}( jQuery ) ); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.draggable.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.draggable.js new file mode 100644 index 0000000..aa62752 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.draggable.js @@ -0,0 +1,836 @@ +/*! + * jQuery UI Draggable @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/draggable/ + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +$.widget("ui.draggable", $.ui.mouse, { + version: "@VERSION", + widgetEventPrefix: "drag", + options: { + addClasses: true, + appendTo: "parent", + axis: false, + connectToSortable: false, + containment: false, + cursor: "auto", + cursorAt: false, + grid: false, + handle: false, + helper: "original", + iframeFix: false, + opacity: false, + refreshPositions: false, + revert: false, + revertDuration: 500, + scope: "default", + scroll: true, + scrollSensitivity: 20, + scrollSpeed: 20, + snap: false, + snapMode: "both", + snapTolerance: 20, + stack: false, + zIndex: false + }, + _create: function() { + + if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position"))) + this.element[0].style.position = 'relative'; + + (this.options.addClasses && this.element.addClass("ui-draggable")); + (this.options.disabled && this.element.addClass("ui-draggable-disabled")); + + this._mouseInit(); + + }, + + _destroy: function() { + this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" ); + this._mouseDestroy(); + }, + + _mouseCapture: function(event) { + + var o = this.options; + + // among others, prevent a drag on a resizable-handle + if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle')) + return false; + + //Quit if we're not on a valid handle + this.handle = this._getHandle(event); + if (!this.handle) + return false; + + $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() { + $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>') + .css({ + width: this.offsetWidth+"px", height: this.offsetHeight+"px", + position: "absolute", opacity: "0.001", zIndex: 1000 + }) + .css($(this).offset()) + .appendTo("body"); + }); + + return true; + + }, + + _mouseStart: function(event) { + + var o = this.options; + + //Create and append the visible helper + this.helper = this._createHelper(event); + + this.helper.addClass("ui-draggable-dragging"); + + //Cache the helper size + this._cacheHelperProportions(); + + //If ddmanager is used for droppables, set the global draggable + if($.ui.ddmanager) + $.ui.ddmanager.current = this; + + /* + * - Position generation - + * This block generates everything position related - it's the core of draggables. + */ + + //Cache the margins of the original element + this._cacheMargins(); + + //Store the helper's css position + this.cssPosition = this.helper.css("position"); + this.scrollParent = this.helper.scrollParent(); + + //The element's absolute position on the page minus margins + this.offset = this.positionAbs = this.element.offset(); + this.offset = { + top: this.offset.top - this.margins.top, + left: this.offset.left - this.margins.left + }; + + $.extend(this.offset, { + click: { //Where the click happened, relative to the element + left: event.pageX - this.offset.left, + top: event.pageY - this.offset.top + }, + parent: this._getParentOffset(), + relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper + }); + + //Generate the original position + this.originalPosition = this.position = this._generatePosition(event); + this.originalPageX = event.pageX; + this.originalPageY = event.pageY; + + //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied + (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); + + //Set a containment if given in the options + if(o.containment) + this._setContainment(); + + //Trigger event + callbacks + if(this._trigger("start", event) === false) { + this._clear(); + return false; + } + + //Recache the helper size + this._cacheHelperProportions(); + + //Prepare the droppable offsets + if ($.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + + + this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position + + //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003) + if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event); + + return true; + }, + + _mouseDrag: function(event, noPropagation) { + + //Compute the helpers position + this.position = this._generatePosition(event); + this.positionAbs = this._convertPositionTo("absolute"); + + //Call plugins and callbacks and use the resulting position if something is returned + if (!noPropagation) { + var ui = this._uiHash(); + if(this._trigger('drag', event, ui) === false) { + this._mouseUp({}); + return false; + } + this.position = ui.position; + } + + if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; + if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; + if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); + + return false; + }, + + _mouseStop: function(event) { + + //If we are using droppables, inform the manager about the drop + var dropped = false; + if ($.ui.ddmanager && !this.options.dropBehaviour) + dropped = $.ui.ddmanager.drop(this, event); + + //if a drop comes from outside (a sortable) + if(this.dropped) { + dropped = this.dropped; + this.dropped = false; + } + + //if the original element is no longer in the DOM don't bother to continue (see #8269) + var element = this.element[0], elementInDom = false; + while ( element && (element = element.parentNode) ) { + if (element == document ) { + elementInDom = true; + } + } + if ( !elementInDom && this.options.helper === "original" ) + return false; + + if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) { + var that = this; + $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() { + if(that._trigger("stop", event) !== false) { + that._clear(); + } + }); + } else { + if(this._trigger("stop", event) !== false) { + this._clear(); + } + } + + return false; + }, + + _mouseUp: function(event) { + //Remove frame helpers + $("div.ui-draggable-iframeFix").each(function() { + this.parentNode.removeChild(this); + }); + + //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003) + if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event); + + return $.ui.mouse.prototype._mouseUp.call(this, event); + }, + + cancel: function() { + + if(this.helper.is(".ui-draggable-dragging")) { + this._mouseUp({}); + } else { + this._clear(); + } + + return this; + + }, + + _getHandle: function(event) { + + var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false; + $(this.options.handle, this.element) + .find("*") + .andSelf() + .each(function() { + if(this == event.target) handle = true; + }); + + return handle; + + }, + + _createHelper: function(event) { + + var o = this.options; + var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element); + + if(!helper.parents('body').length) + helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)); + + if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) + helper.css("position", "absolute"); + + return helper; + + }, + + _adjustOffsetFromHelper: function(obj) { + if (typeof obj == 'string') { + obj = obj.split(' '); + } + if ($.isArray(obj)) { + obj = {left: +obj[0], top: +obj[1] || 0}; + } + if ('left' in obj) { + this.offset.click.left = obj.left + this.margins.left; + } + if ('right' in obj) { + this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; + } + if ('top' in obj) { + this.offset.click.top = obj.top + this.margins.top; + } + if ('bottom' in obj) { + this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; + } + }, + + _getParentOffset: function() { + + //Get the offsetParent and cache its position + this.offsetParent = this.helper.offsetParent(); + var po = this.offsetParent.offset(); + + // This is a special case where we need to modify a offset calculated on start, since the following happened: + // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that + // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag + if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) { + po.left += this.scrollParent.scrollLeft(); + po.top += this.scrollParent.scrollTop(); + } + + if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information + || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.ui.ie)) //Ugly IE fix + po = { top: 0, left: 0 }; + + return { + top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), + left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) + }; + + }, + + _getRelativeOffset: function() { + + if(this.cssPosition == "relative") { + var p = this.element.position(); + return { + top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), + left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() + }; + } else { + return { top: 0, left: 0 }; + } + + }, + + _cacheMargins: function() { + this.margins = { + left: (parseInt(this.element.css("marginLeft"),10) || 0), + top: (parseInt(this.element.css("marginTop"),10) || 0), + right: (parseInt(this.element.css("marginRight"),10) || 0), + bottom: (parseInt(this.element.css("marginBottom"),10) || 0) + }; + }, + + _cacheHelperProportions: function() { + this.helperProportions = { + width: this.helper.outerWidth(), + height: this.helper.outerHeight() + }; + }, + + _setContainment: function() { + + var o = this.options; + if(o.containment == 'parent') o.containment = this.helper[0].parentNode; + if(o.containment == 'document' || o.containment == 'window') this.containment = [ + o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left, + o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top, + (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, + (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top + ]; + + if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) { + var c = $(o.containment); + var ce = c[0]; if(!ce) return; + var co = c.offset(); + var over = ($(ce).css("overflow") != 'hidden'); + + this.containment = [ + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0), + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0), + (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right, + (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom + ]; + this.relative_container = c; + + } else if(o.containment.constructor == Array) { + this.containment = o.containment; + } + + }, + + _convertPositionTo: function(d, pos) { + + if(!pos) pos = this.position; + var mod = d == "absolute" ? 1 : -1; + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + return { + top: ( + pos.top // The absolute mouse position + + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) + - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) + ), + left: ( + pos.left // The absolute mouse position + + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) + - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) + ) + }; + + }, + + _generatePosition: function(event) { + + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + var pageX = event.pageX; + var pageY = event.pageY; + + /* + * - Position constraining - + * Constrain the position to a mix of grid, containment. + */ + + if(this.originalPosition) { //If we are not dragging yet, we won't check for options + var containment; + if(this.containment) { + if (this.relative_container){ + var co = this.relative_container.offset(); + containment = [ this.containment[0] + co.left, + this.containment[1] + co.top, + this.containment[2] + co.left, + this.containment[3] + co.top ]; + } + else { + containment = this.containment; + } + + if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left; + if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top; + if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left; + if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top; + } + + if(o.grid) { + //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950) + var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY; + pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; + + var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX; + pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; + } + + } + + return { + top: ( + pageY // The absolute mouse position + - this.offset.click.top // Click offset (relative to the element) + - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.top // The offsetParent's offset without borders (offset + border) + + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) + ), + left: ( + pageX // The absolute mouse position + - this.offset.click.left // Click offset (relative to the element) + - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.left // The offsetParent's offset without borders (offset + border) + + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) + ) + }; + + }, + + _clear: function() { + this.helper.removeClass("ui-draggable-dragging"); + if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove(); + //if($.ui.ddmanager) $.ui.ddmanager.current = null; + this.helper = null; + this.cancelHelperRemoval = false; + }, + + // From now on bulk stuff - mainly helpers + + _trigger: function(type, event, ui) { + ui = ui || this._uiHash(); + $.ui.plugin.call(this, type, [event, ui]); + if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins + return $.Widget.prototype._trigger.call(this, type, event, ui); + }, + + plugins: {}, + + _uiHash: function(event) { + return { + helper: this.helper, + position: this.position, + originalPosition: this.originalPosition, + offset: this.positionAbs + }; + } + +}); + +$.ui.plugin.add("draggable", "connectToSortable", { + start: function(event, ui) { + + var inst = $(this).data("draggable"), o = inst.options, + uiSortable = $.extend({}, ui, { item: inst.element }); + inst.sortables = []; + $(o.connectToSortable).each(function() { + var sortable = $.data(this, 'sortable'); + if (sortable && !sortable.options.disabled) { + inst.sortables.push({ + instance: sortable, + shouldRevert: sortable.options.revert + }); + sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page). + sortable._trigger("activate", event, uiSortable); + } + }); + + }, + stop: function(event, ui) { + + //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper + var inst = $(this).data("draggable"), + uiSortable = $.extend({}, ui, { item: inst.element }); + + $.each(inst.sortables, function() { + if(this.instance.isOver) { + + this.instance.isOver = 0; + + inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance + this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work) + + //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid' + if(this.shouldRevert) this.instance.options.revert = true; + + //Trigger the stop of the sortable + this.instance._mouseStop(event); + + this.instance.options.helper = this.instance.options._helper; + + //If the helper has been the original item, restore properties in the sortable + if(inst.options.helper == 'original') + this.instance.currentItem.css({ top: 'auto', left: 'auto' }); + + } else { + this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance + this.instance._trigger("deactivate", event, uiSortable); + } + + }); + + }, + drag: function(event, ui) { + + var inst = $(this).data("draggable"), that = this; + + var checkPos = function(o) { + var dyClick = this.offset.click.top, dxClick = this.offset.click.left; + var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left; + var itemHeight = o.height, itemWidth = o.width; + var itemTop = o.top, itemLeft = o.left; + + return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth); + }; + + $.each(inst.sortables, function(i) { + + var innermostIntersecting = false; + var thisSortable = this; + //Copy over some variables to allow calling the sortable's native _intersectsWith + this.instance.positionAbs = inst.positionAbs; + this.instance.helperProportions = inst.helperProportions; + this.instance.offset.click = inst.offset.click; + + if(this.instance._intersectsWith(this.instance.containerCache)) { + innermostIntersecting = true; + $.each(inst.sortables, function () { + this.instance.positionAbs = inst.positionAbs; + this.instance.helperProportions = inst.helperProportions; + this.instance.offset.click = inst.offset.click; + if (this != thisSortable + && this.instance._intersectsWith(this.instance.containerCache) + && $.ui.contains(thisSortable.instance.element[0], this.instance.element[0])) + innermostIntersecting = false; + return innermostIntersecting; + }); + } + + + if(innermostIntersecting) { + //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once + if(!this.instance.isOver) { + + this.instance.isOver = 1; + //Now we fake the start of dragging for the sortable instance, + //by cloning the list group item, appending it to the sortable and using it as inst.currentItem + //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one) + this.instance.currentItem = $(that).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true); + this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it + this.instance.options.helper = function() { return ui.helper[0]; }; + + event.target = this.instance.currentItem[0]; + this.instance._mouseCapture(event, true); + this.instance._mouseStart(event, true, true); + + //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes + this.instance.offset.click.top = inst.offset.click.top; + this.instance.offset.click.left = inst.offset.click.left; + this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left; + this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top; + + inst._trigger("toSortable", event); + inst.dropped = this.instance.element; //draggable revert needs that + //hack so receive/update callbacks work (mostly) + inst.currentItem = inst.element; + this.instance.fromOutside = inst; + + } + + //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable + if(this.instance.currentItem) this.instance._mouseDrag(event); + + } else { + + //If it doesn't intersect with the sortable, and it intersected before, + //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval + if(this.instance.isOver) { + + this.instance.isOver = 0; + this.instance.cancelHelperRemoval = true; + + //Prevent reverting on this forced stop + this.instance.options.revert = false; + + // The out event needs to be triggered independently + this.instance._trigger('out', event, this.instance._uiHash(this.instance)); + + this.instance._mouseStop(event, true); + this.instance.options.helper = this.instance.options._helper; + + //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size + this.instance.currentItem.remove(); + if(this.instance.placeholder) this.instance.placeholder.remove(); + + inst._trigger("fromSortable", event); + inst.dropped = false; //draggable revert needs that + } + + }; + + }); + + } +}); + +$.ui.plugin.add("draggable", "cursor", { + start: function(event, ui) { + var t = $('body'), o = $(this).data('draggable').options; + if (t.css("cursor")) o._cursor = t.css("cursor"); + t.css("cursor", o.cursor); + }, + stop: function(event, ui) { + var o = $(this).data('draggable').options; + if (o._cursor) $('body').css("cursor", o._cursor); + } +}); + +$.ui.plugin.add("draggable", "opacity", { + start: function(event, ui) { + var t = $(ui.helper), o = $(this).data('draggable').options; + if(t.css("opacity")) o._opacity = t.css("opacity"); + t.css('opacity', o.opacity); + }, + stop: function(event, ui) { + var o = $(this).data('draggable').options; + if(o._opacity) $(ui.helper).css('opacity', o._opacity); + } +}); + +$.ui.plugin.add("draggable", "scroll", { + start: function(event, ui) { + var i = $(this).data("draggable"); + if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset(); + }, + drag: function(event, ui) { + + var i = $(this).data("draggable"), o = i.options, scrolled = false; + + if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') { + + if(!o.axis || o.axis != 'x') { + if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) + i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed; + else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) + i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed; + } + + if(!o.axis || o.axis != 'y') { + if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) + i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed; + else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) + i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed; + } + + } else { + + if(!o.axis || o.axis != 'x') { + if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); + else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); + } + + if(!o.axis || o.axis != 'y') { + if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); + else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); + } + + } + + if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(i, event); + + } +}); + +$.ui.plugin.add("draggable", "snap", { + start: function(event, ui) { + + var i = $(this).data("draggable"), o = i.options; + i.snapElements = []; + + $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() { + var $t = $(this); var $o = $t.offset(); + if(this != i.element[0]) i.snapElements.push({ + item: this, + width: $t.outerWidth(), height: $t.outerHeight(), + top: $o.top, left: $o.left + }); + }); + + }, + drag: function(event, ui) { + + var inst = $(this).data("draggable"), o = inst.options; + var d = o.snapTolerance; + + var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, + y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height; + + for (var i = inst.snapElements.length - 1; i >= 0; i--){ + + var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width, + t = inst.snapElements[i].top, b = t + inst.snapElements[i].height; + + //Yes, I know, this is insane ;) + if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) { + if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); + inst.snapElements[i].snapping = false; + continue; + } + + if(o.snapMode != 'inner') { + var ts = Math.abs(t - y2) <= d; + var bs = Math.abs(b - y1) <= d; + var ls = Math.abs(l - x2) <= d; + var rs = Math.abs(r - x1) <= d; + if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top; + if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top; + if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left; + if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left; + } + + var first = (ts || bs || ls || rs); + + if(o.snapMode != 'outer') { + var ts = Math.abs(t - y1) <= d; + var bs = Math.abs(b - y2) <= d; + var ls = Math.abs(l - x1) <= d; + var rs = Math.abs(r - x2) <= d; + if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top; + if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top; + if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left; + if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left; + } + + if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) + (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item }))); + inst.snapElements[i].snapping = (ts || bs || ls || rs || first); + + }; + + } +}); + +$.ui.plugin.add("draggable", "stack", { + start: function(event, ui) { + + var o = $(this).data("draggable").options; + + var group = $.makeArray($(o.stack)).sort(function(a,b) { + return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0); + }); + if (!group.length) { return; } + + var min = parseInt(group[0].style.zIndex) || 0; + $(group).each(function(i) { + this.style.zIndex = min + i; + }); + + this[0].style.zIndex = min + group.length; + + } +}); + +$.ui.plugin.add("draggable", "zIndex", { + start: function(event, ui) { + var t = $(ui.helper), o = $(this).data("draggable").options; + if(t.css("zIndex")) o._zIndex = t.css("zIndex"); + t.css('zIndex', o.zIndex); + }, + stop: function(event, ui) { + var o = $(this).data("draggable").options; + if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex); + } +}); + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.droppable.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.droppable.js new file mode 100644 index 0000000..93e74d2 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.droppable.js @@ -0,0 +1,294 @@ +/*! + * jQuery UI Droppable @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/droppable/ + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.mouse.js + * jquery.ui.draggable.js + */ +(function( $, undefined ) { + +$.widget("ui.droppable", { + version: "@VERSION", + widgetEventPrefix: "drop", + options: { + accept: '*', + activeClass: false, + addClasses: true, + greedy: false, + hoverClass: false, + scope: 'default', + tolerance: 'intersect' + }, + _create: function() { + + var o = this.options, accept = o.accept; + this.isover = 0; this.isout = 1; + + this.accept = $.isFunction(accept) ? accept : function(d) { + return d.is(accept); + }; + + //Store the droppable's proportions + this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight }; + + // Add the reference and positions to the manager + $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || []; + $.ui.ddmanager.droppables[o.scope].push(this); + + (o.addClasses && this.element.addClass("ui-droppable")); + + }, + + _destroy: function() { + var drop = $.ui.ddmanager.droppables[this.options.scope]; + for ( var i = 0; i < drop.length; i++ ) + if ( drop[i] == this ) + drop.splice(i, 1); + + this.element.removeClass("ui-droppable ui-droppable-disabled"); + }, + + _setOption: function(key, value) { + + if(key == 'accept') { + this.accept = $.isFunction(value) ? value : function(d) { + return d.is(value); + }; + } + $.Widget.prototype._setOption.apply(this, arguments); + }, + + _activate: function(event) { + var draggable = $.ui.ddmanager.current; + if(this.options.activeClass) this.element.addClass(this.options.activeClass); + (draggable && this._trigger('activate', event, this.ui(draggable))); + }, + + _deactivate: function(event) { + var draggable = $.ui.ddmanager.current; + if(this.options.activeClass) this.element.removeClass(this.options.activeClass); + (draggable && this._trigger('deactivate', event, this.ui(draggable))); + }, + + _over: function(event) { + + var draggable = $.ui.ddmanager.current; + if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element + + if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + if(this.options.hoverClass) this.element.addClass(this.options.hoverClass); + this._trigger('over', event, this.ui(draggable)); + } + + }, + + _out: function(event) { + + var draggable = $.ui.ddmanager.current; + if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element + + if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); + this._trigger('out', event, this.ui(draggable)); + } + + }, + + _drop: function(event,custom) { + + var draggable = custom || $.ui.ddmanager.current; + if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element + + var childrenIntersection = false; + this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() { + var inst = $.data(this, 'droppable'); + if( + inst.options.greedy + && !inst.options.disabled + && inst.options.scope == draggable.options.scope + && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) + && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance) + ) { childrenIntersection = true; return false; } + }); + if(childrenIntersection) return false; + + if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + if(this.options.activeClass) this.element.removeClass(this.options.activeClass); + if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass); + this._trigger('drop', event, this.ui(draggable)); + return this.element; + } + + return false; + + }, + + ui: function(c) { + return { + draggable: (c.currentItem || c.element), + helper: c.helper, + position: c.position, + offset: c.positionAbs + }; + } + +}); + +$.ui.intersect = function(draggable, droppable, toleranceMode) { + + if (!droppable.offset) return false; + + var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width, + y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height; + var l = droppable.offset.left, r = l + droppable.proportions.width, + t = droppable.offset.top, b = t + droppable.proportions.height; + + switch (toleranceMode) { + case 'fit': + return (l <= x1 && x2 <= r + && t <= y1 && y2 <= b); + break; + case 'intersect': + return (l < x1 + (draggable.helperProportions.width / 2) // Right Half + && x2 - (draggable.helperProportions.width / 2) < r // Left Half + && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half + && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half + break; + case 'pointer': + var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left), + draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top), + isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width); + return isOver; + break; + case 'touch': + return ( + (y1 >= t && y1 <= b) || // Top edge touching + (y2 >= t && y2 <= b) || // Bottom edge touching + (y1 < t && y2 > b) // Surrounded vertically + ) && ( + (x1 >= l && x1 <= r) || // Left edge touching + (x2 >= l && x2 <= r) || // Right edge touching + (x1 < l && x2 > r) // Surrounded horizontally + ); + break; + default: + return false; + break; + } + +}; + +/* + This manager tracks offsets of draggables and droppables +*/ +$.ui.ddmanager = { + current: null, + droppables: { 'default': [] }, + prepareOffsets: function(t, event) { + + var m = $.ui.ddmanager.droppables[t.options.scope] || []; + var type = event ? event.type : null; // workaround for #2317 + var list = (t.currentItem || t.element).find(":data(droppable)").andSelf(); + + droppablesLoop: for (var i = 0; i < m.length; i++) { + + if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted + for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item + m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue + + if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables + + m[i].offset = m[i].element.offset(); + m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight }; + + } + + }, + drop: function(draggable, event) { + + var dropped = false; + $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { + + if(!this.options) return; + if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) + dropped = this._drop.call(this, event) || dropped; + + if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) { + this.isout = 1; this.isover = 0; + this._deactivate.call(this, event); + } + + }); + return dropped; + + }, + dragStart: function( draggable, event ) { + //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003) + draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() { + if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); + }); + }, + drag: function(draggable, event) { + + //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse. + if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event); + + //Run through all droppables and check their positions based on specific tolerance options + $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() { + + if(this.options.disabled || this.greedyChild || !this.visible) return; + var intersects = $.ui.intersect(draggable, this, this.options.tolerance); + + var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null); + if(!c) return; + + var parentInstance; + if (this.options.greedy) { + // find droppable parents with same scope + var scope = this.options.scope; + var parent = this.element.parents(':data(droppable)').filter(function () { + return $.data(this, 'droppable').options.scope === scope; + }); + + if (parent.length) { + parentInstance = $.data(parent[0], 'droppable'); + parentInstance.greedyChild = (c == 'isover' ? 1 : 0); + } + } + + // we just moved into a greedy child + if (parentInstance && c == 'isover') { + parentInstance['isover'] = 0; + parentInstance['isout'] = 1; + parentInstance._out.call(parentInstance, event); + } + + this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0; + this[c == "isover" ? "_over" : "_out"].call(this, event); + + // we just moved out of a greedy child + if (parentInstance && c == 'isout') { + parentInstance['isout'] = 0; + parentInstance['isover'] = 1; + parentInstance._over.call(parentInstance, event); + } + }); + + }, + dragStop: function( draggable, event ) { + draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" ); + //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003) + if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event ); + } +}; + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-blind.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-blind.js new file mode 100644 index 0000000..0ee31c0 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-blind.js @@ -0,0 +1,82 @@ +/*! + * jQuery UI Effects Blind @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/blind-effect/ + * + * Depends: + * jquery.ui.effect.js + */ +(function( $, undefined ) { + +var rvertical = /up|down|vertical/, + rpositivemotion = /up|left|vertical|horizontal/; + +$.effects.effect.blind = function( o, done ) { + // Create element + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], + mode = $.effects.setMode( el, o.mode || "hide" ), + direction = o.direction || "up", + vertical = rvertical.test( direction ), + ref = vertical ? "height" : "width", + ref2 = vertical ? "top" : "left", + motion = rpositivemotion.test( direction ), + animation = {}, + show = mode === "show", + wrapper, distance, margin; + + // if already wrapped, the wrapper's properties are my property. #6245 + if ( el.parent().is( ".ui-effects-wrapper" ) ) { + $.effects.save( el.parent(), props ); + } else { + $.effects.save( el, props ); + } + el.show(); + wrapper = $.effects.createWrapper( el ).css({ + overflow: "hidden" + }); + + distance = wrapper[ ref ](); + margin = parseFloat( wrapper.css( ref2 ) ) || 0; + + animation[ ref ] = show ? distance : 0; + if ( !motion ) { + el + .css( vertical ? "bottom" : "right", 0 ) + .css( vertical ? "top" : "left", "auto" ) + .css({ position: "absolute" }); + + animation[ ref2 ] = show ? margin : distance + margin; + } + + // start at 0 if we are showing + if ( show ) { + wrapper.css( ref, 0 ); + if ( ! motion ) { + wrapper.css( ref2, margin + distance ); + } + } + + // Animate + wrapper.animate( animation, { + duration: o.duration, + easing: o.easing, + queue: false, + complete: function() { + if ( mode === "hide" ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); + } + }); + +}; + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-bounce.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-bounce.js new file mode 100644 index 0000000..d36b066 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-bounce.js @@ -0,0 +1,113 @@ +/*! + * jQuery UI Effects Bounce @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/bounce-effect/ + * + * Depends: + * jquery.ui.effect.js + */ +(function( $, undefined ) { + +$.effects.effect.bounce = function( o, done ) { + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], + + // defaults: + mode = $.effects.setMode( el, o.mode || "effect" ), + hide = mode === "hide", + show = mode === "show", + direction = o.direction || "up", + distance = o.distance, + times = o.times || 5, + + // number of internal animations + anims = times * 2 + ( show || hide ? 1 : 0 ), + speed = o.duration / anims, + easing = o.easing, + + // utility: + ref = ( direction === "up" || direction === "down" ) ? "top" : "left", + motion = ( direction === "up" || direction === "left" ), + i, + upAnim, + downAnim, + + // we will need to re-assemble the queue to stack our animations in place + queue = el.queue(), + queuelen = queue.length; + + // Avoid touching opacity to prevent clearType and PNG issues in IE + if ( show || hide ) { + props.push( "opacity" ); + } + + $.effects.save( el, props ); + el.show(); + $.effects.createWrapper( el ); // Create Wrapper + + // default distance for the BIGGEST bounce is the outer Distance / 3 + if ( !distance ) { + distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; + } + + if ( show ) { + downAnim = { opacity: 1 }; + downAnim[ ref ] = 0; + + // if we are showing, force opacity 0 and set the initial position + // then do the "first" animation + el.css( "opacity", 0 ) + .css( ref, motion ? -distance * 2 : distance * 2 ) + .animate( downAnim, speed, easing ); + } + + // start at the smallest distance if we are hiding + if ( hide ) { + distance = distance / Math.pow( 2, times - 1 ); + } + + downAnim = {}; + downAnim[ ref ] = 0; + // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here + for ( i = 0; i < times; i++ ) { + upAnim = {}; + upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; + + el.animate( upAnim, speed, easing ) + .animate( downAnim, speed, easing ); + + distance = hide ? distance * 2 : distance / 2; + } + + // Last Bounce when Hiding + if ( hide ) { + upAnim = { opacity: 0 }; + upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; + + el.animate( upAnim, speed, easing ); + } + + el.queue(function() { + if ( hide ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); + }); + + // inject all the animations we just queued to be first in line (after "inprogress") + if ( queuelen > 1) { + queue.splice.apply( queue, + [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); + } + el.dequeue(); + +}; + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-clip.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-clip.js new file mode 100644 index 0000000..ce4402b --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-clip.js @@ -0,0 +1,67 @@ +/*! + * jQuery UI Effects Clip @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/clip-effect/ + * + * Depends: + * jquery.ui.effect.js + */ +(function( $, undefined ) { + +$.effects.effect.clip = function( o, done ) { + // Create element + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], + mode = $.effects.setMode( el, o.mode || "hide" ), + show = mode === "show", + direction = o.direction || "vertical", + vert = direction === "vertical", + size = vert ? "height" : "width", + position = vert ? "top" : "left", + animation = {}, + wrapper, animate, distance; + + // Save & Show + $.effects.save( el, props ); + el.show(); + + // Create Wrapper + wrapper = $.effects.createWrapper( el ).css({ + overflow: "hidden" + }); + animate = ( el[0].tagName === "IMG" ) ? wrapper : el; + distance = animate[ size ](); + + // Shift + if ( show ) { + animate.css( size, 0 ); + animate.css( position, distance / 2 ); + } + + // Create Animation Object: + animation[ size ] = show ? distance : 0; + animation[ position ] = show ? 0 : distance / 2; + + // Animate + animate.animate( animation, { + queue: false, + duration: o.duration, + easing: o.easing, + complete: function() { + if ( !show ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); + } + }); + +}; + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-drop.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-drop.js new file mode 100644 index 0000000..bd196ec --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-drop.js @@ -0,0 +1,65 @@ +/*! + * jQuery UI Effects Drop @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/drop-effect/ + * + * Depends: + * jquery.ui.effect.js + */ +(function( $, undefined ) { + +$.effects.effect.drop = function( o, done ) { + + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ], + mode = $.effects.setMode( el, o.mode || "hide" ), + show = mode === "show", + direction = o.direction || "left", + ref = ( direction === "up" || direction === "down" ) ? "top" : "left", + motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg", + animation = { + opacity: show ? 1 : 0 + }, + distance; + + // Adjust + $.effects.save( el, props ); + el.show(); + $.effects.createWrapper( el ); + + distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2; + + if ( show ) { + el + .css( "opacity", 0 ) + .css( ref, motion === "pos" ? -distance : distance ); + } + + // Animation + animation[ ref ] = ( show ? + ( motion === "pos" ? "+=" : "-=" ) : + ( motion === "pos" ? "-=" : "+=" ) ) + + distance; + + // Animate + el.animate( animation, { + queue: false, + duration: o.duration, + easing: o.easing, + complete: function() { + if ( mode === "hide" ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); + } + }); +}; + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-explode.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-explode.js new file mode 100644 index 0000000..b31efc8 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-explode.js @@ -0,0 +1,97 @@ +/*! + * jQuery UI Effects Explode @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/explode-effect/ + * + * Depends: + * jquery.ui.effect.js + */ +(function( $, undefined ) { + +$.effects.effect.explode = function( o, done ) { + + var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3, + cells = rows, + el = $( this ), + mode = $.effects.setMode( el, o.mode || "hide" ), + show = mode === "show", + + // show and then visibility:hidden the element before calculating offset + offset = el.show().css( "visibility", "hidden" ).offset(), + + // width and height of a piece + width = Math.ceil( el.outerWidth() / cells ), + height = Math.ceil( el.outerHeight() / rows ), + pieces = [], + + // loop + i, j, left, top, mx, my; + + // children animate complete: + function childComplete() { + pieces.push( this ); + if ( pieces.length === rows * cells ) { + animComplete(); + } + } + + // clone the element for each row and cell. + for( i = 0; i < rows ; i++ ) { // ===> + top = offset.top + i * height; + my = i - ( rows - 1 ) / 2 ; + + for( j = 0; j < cells ; j++ ) { // ||| + left = offset.left + j * width; + mx = j - ( cells - 1 ) / 2 ; + + // Create a clone of the now hidden main element that will be absolute positioned + // within a wrapper div off the -left and -top equal to size of our pieces + el + .clone() + .appendTo( "body" ) + .wrap( "<div></div>" ) + .css({ + position: "absolute", + visibility: "visible", + left: -j * width, + top: -i * height + }) + + // select the wrapper - make it overflow: hidden and absolute positioned based on + // where the original was located +left and +top equal to the size of pieces + .parent() + .addClass( "ui-effects-explode" ) + .css({ + position: "absolute", + overflow: "hidden", + width: width, + height: height, + left: left + ( show ? mx * width : 0 ), + top: top + ( show ? my * height : 0 ), + opacity: show ? 0 : 1 + }).animate({ + left: left + ( show ? 0 : mx * width ), + top: top + ( show ? 0 : my * height ), + opacity: show ? 1 : 0 + }, o.duration || 500, o.easing, childComplete ); + } + } + + function animComplete() { + el.css({ + visibility: "visible" + }); + $( pieces ).remove(); + if ( !show ) { + el.hide(); + } + done(); + } +}; + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-fade.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-fade.js new file mode 100644 index 0000000..00d8232 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-fade.js @@ -0,0 +1,30 @@ +/*! + * jQuery UI Effects Fade @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/fade-effect/ + * + * Depends: + * jquery.ui.effect.js + */ +(function( $, undefined ) { + +$.effects.effect.fade = function( o, done ) { + var el = $( this ), + mode = $.effects.setMode( el, o.mode || "toggle" ); + + el.animate({ + opacity: mode + }, { + queue: false, + duration: o.duration, + easing: o.easing, + complete: done + }); +}; + +})( jQuery ); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-fold.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-fold.js new file mode 100644 index 0000000..893a27e --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-fold.js @@ -0,0 +1,76 @@ +/*! + * jQuery UI Effects Fold @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/fold-effect/ + * + * Depends: + * jquery.ui.effect.js + */ +(function( $, undefined ) { + +$.effects.effect.fold = function( o, done ) { + + // Create element + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], + mode = $.effects.setMode( el, o.mode || "hide" ), + show = mode === "show", + hide = mode === "hide", + size = o.size || 15, + percent = /([0-9]+)%/.exec( size ), + horizFirst = !!o.horizFirst, + widthFirst = show !== horizFirst, + ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ], + duration = o.duration / 2, + wrapper, distance, + animation1 = {}, + animation2 = {}; + + $.effects.save( el, props ); + el.show(); + + // Create Wrapper + wrapper = $.effects.createWrapper( el ).css({ + overflow: "hidden" + }); + distance = widthFirst ? + [ wrapper.width(), wrapper.height() ] : + [ wrapper.height(), wrapper.width() ]; + + if ( percent ) { + size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; + } + if ( show ) { + wrapper.css( horizFirst ? { + height: 0, + width: size + } : { + height: size, + width: 0 + }); + } + + // Animation + animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size; + animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0; + + // Animate + wrapper + .animate( animation1, duration, o.easing ) + .animate( animation2, duration, o.easing, function() { + if ( hide ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); + }); + +}; + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-highlight.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-highlight.js new file mode 100644 index 0000000..99c41de --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-highlight.js @@ -0,0 +1,50 @@ +/*! + * jQuery UI Effects Highlight @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/highlight-effect/ + * + * Depends: + * jquery.ui.effect.js + */ +(function( $, undefined ) { + +$.effects.effect.highlight = function( o, done ) { + var elem = $( this ), + props = [ "backgroundImage", "backgroundColor", "opacity" ], + mode = $.effects.setMode( elem, o.mode || "show" ), + animation = { + backgroundColor: elem.css( "backgroundColor" ) + }; + + if (mode === "hide") { + animation.opacity = 0; + } + + $.effects.save( elem, props ); + + elem + .show() + .css({ + backgroundImage: "none", + backgroundColor: o.color || "#ffff99" + }) + .animate( animation, { + queue: false, + duration: o.duration, + easing: o.easing, + complete: function() { + if ( mode === "hide" ) { + elem.hide(); + } + $.effects.restore( elem, props ); + done(); + } + }); +}; + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-pulsate.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-pulsate.js new file mode 100644 index 0000000..de78894 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-pulsate.js @@ -0,0 +1,63 @@ +/*! + * jQuery UI Effects Pulsate @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/pulsate-effect/ + * + * Depends: + * jquery.ui.effect.js + */ +(function( $, undefined ) { + +$.effects.effect.pulsate = function( o, done ) { + var elem = $( this ), + mode = $.effects.setMode( elem, o.mode || "show" ), + show = mode === "show", + hide = mode === "hide", + showhide = ( show || mode === "hide" ), + + // showing or hiding leaves of the "last" animation + anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), + duration = o.duration / anims, + animateTo = 0, + queue = elem.queue(), + queuelen = queue.length, + i; + + if ( show || !elem.is(":visible")) { + elem.css( "opacity", 0 ).show(); + animateTo = 1; + } + + // anims - 1 opacity "toggles" + for ( i = 1; i < anims; i++ ) { + elem.animate({ + opacity: animateTo + }, duration, o.easing ); + animateTo = 1 - animateTo; + } + + elem.animate({ + opacity: animateTo + }, duration, o.easing); + + elem.queue(function() { + if ( hide ) { + elem.hide(); + } + done(); + }); + + // We just queued up "anims" animations, we need to put them next in the queue + if ( queuelen > 1 ) { + queue.splice.apply( queue, + [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); + } + elem.dequeue(); +}; + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-scale.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-scale.js new file mode 100644 index 0000000..1307e77 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-scale.js @@ -0,0 +1,318 @@ +/*! + * jQuery UI Effects Scale @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/scale-effect/ + * + * Depends: + * jquery.ui.effect.js + */ +(function( $, undefined ) { + +$.effects.effect.puff = function( o, done ) { + var elem = $( this ), + mode = $.effects.setMode( elem, o.mode || "hide" ), + hide = mode === "hide", + percent = parseInt( o.percent, 10 ) || 150, + factor = percent / 100, + original = { + height: elem.height(), + width: elem.width(), + outerHeight: elem.outerHeight(), + outerWidth: elem.outerWidth() + }; + + $.extend( o, { + effect: "scale", + queue: false, + fade: true, + mode: mode, + complete: done, + percent: hide ? percent : 100, + from: hide ? + original : + { + height: original.height * factor, + width: original.width * factor, + outerHeight: original.outerHeight * factor, + outerWidth: original.outerWidth * factor + } + }); + + elem.effect( o ); +}; + +$.effects.effect.scale = function( o, done ) { + + // Create element + var el = $( this ), + options = $.extend( true, {}, o ), + mode = $.effects.setMode( el, o.mode || "effect" ), + percent = parseInt( o.percent, 10 ) || + ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ), + direction = o.direction || "both", + origin = o.origin, + original = { + height: el.height(), + width: el.width(), + outerHeight: el.outerHeight(), + outerWidth: el.outerWidth() + }, + factor = { + y: direction !== "horizontal" ? (percent / 100) : 1, + x: direction !== "vertical" ? (percent / 100) : 1 + }; + + // We are going to pass this effect to the size effect: + options.effect = "size"; + options.queue = false; + options.complete = done; + + // Set default origin and restore for show/hide + if ( mode !== "effect" ) { + options.origin = origin || ["middle","center"]; + options.restore = true; + } + + options.from = o.from || ( mode === "show" ? { + height: 0, + width: 0, + outerHeight: 0, + outerWidth: 0 + } : original ); + options.to = { + height: original.height * factor.y, + width: original.width * factor.x, + outerHeight: original.outerHeight * factor.y, + outerWidth: original.outerWidth * factor.x + }; + + // Fade option to support puff + if ( options.fade ) { + if ( mode === "show" ) { + options.from.opacity = 0; + options.to.opacity = 1; + } + if ( mode === "hide" ) { + options.from.opacity = 1; + options.to.opacity = 0; + } + } + + // Animate + el.effect( options ); + +}; + +$.effects.effect.size = function( o, done ) { + + // Create element + var original, baseline, factor, + el = $( this ), + props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ], + + // Always restore + props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ], + + // Copy for children + props2 = [ "width", "height", "overflow" ], + cProps = [ "fontSize" ], + vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], + hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], + + // Set options + mode = $.effects.setMode( el, o.mode || "effect" ), + restore = o.restore || mode !== "effect", + scale = o.scale || "both", + origin = o.origin || [ "middle", "center" ], + position = el.css( "position" ), + props = restore ? props0 : props1, + zero = { + height: 0, + width: 0, + outerHeight: 0, + outerWidth: 0 + }; + + if ( mode === "show" ) { + el.show(); + } + original = { + height: el.height(), + width: el.width(), + outerHeight: el.outerHeight(), + outerWidth: el.outerWidth() + }; + + if ( o.mode === "toggle" && mode === "show" ) { + el.from = o.to || zero; + el.to = o.from || original; + } else { + el.from = o.from || ( mode === "show" ? zero : original ); + el.to = o.to || ( mode === "hide" ? zero : original ); + } + + // Set scaling factor + factor = { + from: { + y: el.from.height / original.height, + x: el.from.width / original.width + }, + to: { + y: el.to.height / original.height, + x: el.to.width / original.width + } + }; + + // Scale the css box + if ( scale === "box" || scale === "both" ) { + + // Vertical props scaling + if ( factor.from.y !== factor.to.y ) { + props = props.concat( vProps ); + el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from ); + el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to ); + } + + // Horizontal props scaling + if ( factor.from.x !== factor.to.x ) { + props = props.concat( hProps ); + el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from ); + el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to ); + } + } + + // Scale the content + if ( scale === "content" || scale === "both" ) { + + // Vertical props scaling + if ( factor.from.y !== factor.to.y ) { + props = props.concat( cProps ).concat( props2 ); + el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from ); + el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to ); + } + } + + $.effects.save( el, props ); + el.show(); + $.effects.createWrapper( el ); + el.css( "overflow", "hidden" ).css( el.from ); + + // Adjust + if (origin) { // Calculate baseline shifts + baseline = $.effects.getBaseline( origin, original ); + el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y; + el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x; + el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y; + el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x; + } + el.css( el.from ); // set top & left + + // Animate + if ( scale === "content" || scale === "both" ) { // Scale the children + + // Add margins/font-size + vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps); + hProps = hProps.concat([ "marginLeft", "marginRight" ]); + props2 = props0.concat(vProps).concat(hProps); + + el.find( "*[width]" ).each( function(){ + var child = $( this ), + c_original = { + height: child.height(), + width: child.width(), + outerHeight: child.outerHeight(), + outerWidth: child.outerWidth() + }; + if (restore) { + $.effects.save(child, props2); + } + + child.from = { + height: c_original.height * factor.from.y, + width: c_original.width * factor.from.x, + outerHeight: c_original.outerHeight * factor.from.y, + outerWidth: c_original.outerWidth * factor.from.x + }; + child.to = { + height: c_original.height * factor.to.y, + width: c_original.width * factor.to.x, + outerHeight: c_original.height * factor.to.y, + outerWidth: c_original.width * factor.to.x + }; + + // Vertical props scaling + if ( factor.from.y !== factor.to.y ) { + child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from ); + child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to ); + } + + // Horizontal props scaling + if ( factor.from.x !== factor.to.x ) { + child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from ); + child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to ); + } + + // Animate children + child.css( child.from ); + child.animate( child.to, o.duration, o.easing, function() { + + // Restore children + if ( restore ) { + $.effects.restore( child, props2 ); + } + }); + }); + } + + // Animate + el.animate( el.to, { + queue: false, + duration: o.duration, + easing: o.easing, + complete: function() { + if ( el.to.opacity === 0 ) { + el.css( "opacity", el.from.opacity ); + } + if( mode === "hide" ) { + el.hide(); + } + $.effects.restore( el, props ); + if ( !restore ) { + + // we need to calculate our new positioning based on the scaling + if ( position === "static" ) { + el.css({ + position: "relative", + top: el.to.top, + left: el.to.left + }); + } else { + $.each([ "top", "left" ], function( idx, pos ) { + el.css( pos, function( _, str ) { + var val = parseInt( str, 10 ), + toRef = idx ? el.to.left : el.to.top; + + // if original was "auto", recalculate the new value from wrapper + if ( str === "auto" ) { + return toRef + "px"; + } + + return val + toRef + "px"; + }); + }); + } + } + + $.effects.removeWrapper( el ); + done(); + } + }); + +}; + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-shake.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-shake.js new file mode 100644 index 0000000..4c2f981 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-shake.js @@ -0,0 +1,74 @@ +/*! + * jQuery UI Effects Shake @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/shake-effect/ + * + * Depends: + * jquery.ui.effect.js + */ +(function( $, undefined ) { + +$.effects.effect.shake = function( o, done ) { + + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "height", "width" ], + mode = $.effects.setMode( el, o.mode || "effect" ), + direction = o.direction || "left", + distance = o.distance || 20, + times = o.times || 3, + anims = times * 2 + 1, + speed = Math.round(o.duration/anims), + ref = (direction === "up" || direction === "down") ? "top" : "left", + positiveMotion = (direction === "up" || direction === "left"), + animation = {}, + animation1 = {}, + animation2 = {}, + i, + + // we will need to re-assemble the queue to stack our animations in place + queue = el.queue(), + queuelen = queue.length; + + $.effects.save( el, props ); + el.show(); + $.effects.createWrapper( el ); + + // Animation + animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; + animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; + animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; + + // Animate + el.animate( animation, speed, o.easing ); + + // Shakes + for ( i = 1; i < times; i++ ) { + el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing ); + } + el + .animate( animation1, speed, o.easing ) + .animate( animation, speed / 2, o.easing ) + .queue(function() { + if ( mode === "hide" ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); + }); + + // inject all the animations we just queued to be first in line (after "inprogress") + if ( queuelen > 1) { + queue.splice.apply( queue, + [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) ); + } + el.dequeue(); + +}; + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-slide.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-slide.js new file mode 100644 index 0000000..5037256 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-slide.js @@ -0,0 +1,64 @@ +/*! + * jQuery UI Effects Slide @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/slide-effect/ + * + * Depends: + * jquery.ui.effect.js + */ +(function( $, undefined ) { + +$.effects.effect.slide = function( o, done ) { + + // Create element + var el = $( this ), + props = [ "position", "top", "bottom", "left", "right", "width", "height" ], + mode = $.effects.setMode( el, o.mode || "show" ), + show = mode === "show", + direction = o.direction || "left", + ref = (direction === "up" || direction === "down") ? "top" : "left", + positiveMotion = (direction === "up" || direction === "left"), + distance, + animation = {}; + + // Adjust + $.effects.save( el, props ); + el.show(); + distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ); + + $.effects.createWrapper( el ).css({ + overflow: "hidden" + }); + + if ( show ) { + el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance ); + } + + // Animation + animation[ ref ] = ( show ? + ( positiveMotion ? "+=" : "-=") : + ( positiveMotion ? "-=" : "+=")) + + distance; + + // Animate + el.animate( animation, { + queue: false, + duration: o.duration, + easing: o.easing, + complete: function() { + if ( mode === "hide" ) { + el.hide(); + } + $.effects.restore( el, props ); + $.effects.removeWrapper( el ); + done(); + } + }); +}; + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-transfer.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-transfer.js new file mode 100644 index 0000000..0bfffd7 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect-transfer.js @@ -0,0 +1,47 @@ +/*! + * jQuery UI Effects Transfer @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/transfer-effect/ + * + * Depends: + * jquery.ui.effect.js + */ +(function( $, undefined ) { + +$.effects.effect.transfer = function( o, done ) { + var elem = $( this ), + target = $( o.to ), + targetFixed = target.css( "position" ) === "fixed", + body = $("body"), + fixTop = targetFixed ? body.scrollTop() : 0, + fixLeft = targetFixed ? body.scrollLeft() : 0, + endPosition = target.offset(), + animation = { + top: endPosition.top - fixTop , + left: endPosition.left - fixLeft , + height: target.innerHeight(), + width: target.innerWidth() + }, + startPosition = elem.offset(), + transfer = $( '<div class="ui-effects-transfer"></div>' ) + .appendTo( document.body ) + .addClass( o.className ) + .css({ + top: startPosition.top - fixTop , + left: startPosition.left - fixLeft , + height: elem.innerHeight(), + width: elem.innerWidth(), + position: targetFixed ? "fixed" : "absolute" + }) + .animate( animation, o.duration, o.easing, function() { + transfer.remove(); + done(); + }); +}; + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.effect.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect.js new file mode 100644 index 0000000..37ca487 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.effect.js @@ -0,0 +1,1276 @@ +/*! + * jQuery UI Effects @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/category/effects-core/ + */ +;(jQuery.effects || (function($, undefined) { + +var backCompat = $.uiBackCompat !== false, + // prefix used for storing data on .data() + dataSpace = "ui-effects-"; + +$.effects = { + effect: {} +}; + +/*! + * jQuery Color Animations v2.0.0 + * http://jquery.com/ + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * Date: Mon Aug 13 13:41:02 2012 -0500 + */ +(function( jQuery, undefined ) { + + var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor".split(" "), + + // plusequals test for += 100 -= 100 + rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, + // a set of RE's that can match strings and generate color tuples. + stringParsers = [{ + re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, + parse: function( execResult ) { + return [ + execResult[ 1 ], + execResult[ 2 ], + execResult[ 3 ], + execResult[ 4 ] + ]; + } + }, { + re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, + parse: function( execResult ) { + return [ + execResult[ 1 ] * 2.55, + execResult[ 2 ] * 2.55, + execResult[ 3 ] * 2.55, + execResult[ 4 ] + ]; + } + }, { + // this regex ignores A-F because it's compared against an already lowercased string + re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/, + parse: function( execResult ) { + return [ + parseInt( execResult[ 1 ], 16 ), + parseInt( execResult[ 2 ], 16 ), + parseInt( execResult[ 3 ], 16 ) + ]; + } + }, { + // this regex ignores A-F because it's compared against an already lowercased string + re: /#([a-f0-9])([a-f0-9])([a-f0-9])/, + parse: function( execResult ) { + return [ + parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), + parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), + parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ) + ]; + } + }, { + re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/, + space: "hsla", + parse: function( execResult ) { + return [ + execResult[ 1 ], + execResult[ 2 ] / 100, + execResult[ 3 ] / 100, + execResult[ 4 ] + ]; + } + }], + + // jQuery.Color( ) + color = jQuery.Color = function( color, green, blue, alpha ) { + return new jQuery.Color.fn.parse( color, green, blue, alpha ); + }, + spaces = { + rgba: { + props: { + red: { + idx: 0, + type: "byte" + }, + green: { + idx: 1, + type: "byte" + }, + blue: { + idx: 2, + type: "byte" + } + } + }, + + hsla: { + props: { + hue: { + idx: 0, + type: "degrees" + }, + saturation: { + idx: 1, + type: "percent" + }, + lightness: { + idx: 2, + type: "percent" + } + } + } + }, + propTypes = { + "byte": { + floor: true, + max: 255 + }, + "percent": { + max: 1 + }, + "degrees": { + mod: 360, + floor: true + } + }, + support = color.support = {}, + + // element for support tests + supportElem = jQuery( "<p>" )[ 0 ], + + // colors = jQuery.Color.names + colors, + + // local aliases of functions called often + each = jQuery.each; + +// determine rgba support immediately +supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; +support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; + +// define cache name and alpha properties +// for rgba and hsla spaces +each( spaces, function( spaceName, space ) { + space.cache = "_" + spaceName; + space.props.alpha = { + idx: 3, + type: "percent", + def: 1 + }; +}); + +function clamp( value, prop, allowEmpty ) { + var type = propTypes[ prop.type ] || {}; + + if ( value == null ) { + return (allowEmpty || !prop.def) ? null : prop.def; + } + + // ~~ is an short way of doing floor for positive numbers + value = type.floor ? ~~value : parseFloat( value ); + + // IE will pass in empty strings as value for alpha, + // which will hit this case + if ( isNaN( value ) ) { + return prop.def; + } + + if ( type.mod ) { + // we add mod before modding to make sure that negatives values + // get converted properly: -10 -> 350 + return (value + type.mod) % type.mod; + } + + // for now all property types without mod have min and max + return 0 > value ? 0 : type.max < value ? type.max : value; +} + +function stringParse( string ) { + var inst = color(), + rgba = inst._rgba = []; + + string = string.toLowerCase(); + + each( stringParsers, function( i, parser ) { + var parsed, + match = parser.re.exec( string ), + values = match && parser.parse( match ), + spaceName = parser.space || "rgba"; + + if ( values ) { + parsed = inst[ spaceName ]( values ); + + // if this was an rgba parse the assignment might happen twice + // oh well.... + inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; + rgba = inst._rgba = parsed._rgba; + + // exit each( stringParsers ) here because we matched + return false; + } + }); + + // Found a stringParser that handled it + if ( rgba.length ) { + + // if this came from a parsed string, force "transparent" when alpha is 0 + // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) + if ( rgba.join() === "0,0,0,0" ) { + jQuery.extend( rgba, colors.transparent ); + } + return inst; + } + + // named colors + return colors[ string ]; +} + +color.fn = jQuery.extend( color.prototype, { + parse: function( red, green, blue, alpha ) { + if ( red === undefined ) { + this._rgba = [ null, null, null, null ]; + return this; + } + if ( red.jquery || red.nodeType ) { + red = jQuery( red ).css( green ); + green = undefined; + } + + var inst = this, + type = jQuery.type( red ), + rgba = this._rgba = []; + + // more than 1 argument specified - assume ( red, green, blue, alpha ) + if ( green !== undefined ) { + red = [ red, green, blue, alpha ]; + type = "array"; + } + + if ( type === "string" ) { + return this.parse( stringParse( red ) || colors._default ); + } + + if ( type === "array" ) { + each( spaces.rgba.props, function( key, prop ) { + rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); + }); + return this; + } + + if ( type === "object" ) { + if ( red instanceof color ) { + each( spaces, function( spaceName, space ) { + if ( red[ space.cache ] ) { + inst[ space.cache ] = red[ space.cache ].slice(); + } + }); + } else { + each( spaces, function( spaceName, space ) { + var cache = space.cache; + each( space.props, function( key, prop ) { + + // if the cache doesn't exist, and we know how to convert + if ( !inst[ cache ] && space.to ) { + + // if the value was null, we don't need to copy it + // if the key was alpha, we don't need to copy it either + if ( key === "alpha" || red[ key ] == null ) { + return; + } + inst[ cache ] = space.to( inst._rgba ); + } + + // this is the only case where we allow nulls for ALL properties. + // call clamp with alwaysAllowEmpty + inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); + }); + + // everything defined but alpha? + if ( inst[ cache ] && $.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { + // use the default of 1 + inst[ cache ][ 3 ] = 1; + if ( space.from ) { + inst._rgba = space.from( inst[ cache ] ); + } + } + }); + } + return this; + } + }, + is: function( compare ) { + var is = color( compare ), + same = true, + inst = this; + + each( spaces, function( _, space ) { + var localCache, + isCache = is[ space.cache ]; + if (isCache) { + localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; + each( space.props, function( _, prop ) { + if ( isCache[ prop.idx ] != null ) { + same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); + return same; + } + }); + } + return same; + }); + return same; + }, + _space: function() { + var used = [], + inst = this; + each( spaces, function( spaceName, space ) { + if ( inst[ space.cache ] ) { + used.push( spaceName ); + } + }); + return used.pop(); + }, + transition: function( other, distance ) { + var end = color( other ), + spaceName = end._space(), + space = spaces[ spaceName ], + startColor = this.alpha() === 0 ? color( "transparent" ) : this, + start = startColor[ space.cache ] || space.to( startColor._rgba ), + result = start.slice(); + + end = end[ space.cache ]; + each( space.props, function( key, prop ) { + var index = prop.idx, + startValue = start[ index ], + endValue = end[ index ], + type = propTypes[ prop.type ] || {}; + + // if null, don't override start value + if ( endValue === null ) { + return; + } + // if null - use end + if ( startValue === null ) { + result[ index ] = endValue; + } else { + if ( type.mod ) { + if ( endValue - startValue > type.mod / 2 ) { + startValue += type.mod; + } else if ( startValue - endValue > type.mod / 2 ) { + startValue -= type.mod; + } + } + result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); + } + }); + return this[ spaceName ]( result ); + }, + blend: function( opaque ) { + // if we are already opaque - return ourself + if ( this._rgba[ 3 ] === 1 ) { + return this; + } + + var rgb = this._rgba.slice(), + a = rgb.pop(), + blend = color( opaque )._rgba; + + return color( jQuery.map( rgb, function( v, i ) { + return ( 1 - a ) * blend[ i ] + a * v; + })); + }, + toRgbaString: function() { + var prefix = "rgba(", + rgba = jQuery.map( this._rgba, function( v, i ) { + return v == null ? ( i > 2 ? 1 : 0 ) : v; + }); + + if ( rgba[ 3 ] === 1 ) { + rgba.pop(); + prefix = "rgb("; + } + + return prefix + rgba.join() + ")"; + }, + toHslaString: function() { + var prefix = "hsla(", + hsla = jQuery.map( this.hsla(), function( v, i ) { + if ( v == null ) { + v = i > 2 ? 1 : 0; + } + + // catch 1 and 2 + if ( i && i < 3 ) { + v = Math.round( v * 100 ) + "%"; + } + return v; + }); + + if ( hsla[ 3 ] === 1 ) { + hsla.pop(); + prefix = "hsl("; + } + return prefix + hsla.join() + ")"; + }, + toHexString: function( includeAlpha ) { + var rgba = this._rgba.slice(), + alpha = rgba.pop(); + + if ( includeAlpha ) { + rgba.push( ~~( alpha * 255 ) ); + } + + return "#" + jQuery.map( rgba, function( v ) { + + // default to 0 when nulls exist + v = ( v || 0 ).toString( 16 ); + return v.length === 1 ? "0" + v : v; + }).join(""); + }, + toString: function() { + return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); + } +}); +color.fn.parse.prototype = color.fn; + +// hsla conversions adapted from: +// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 + +function hue2rgb( p, q, h ) { + h = ( h + 1 ) % 1; + if ( h * 6 < 1 ) { + return p + (q - p) * h * 6; + } + if ( h * 2 < 1) { + return q; + } + if ( h * 3 < 2 ) { + return p + (q - p) * ((2/3) - h) * 6; + } + return p; +} + +spaces.hsla.to = function ( rgba ) { + if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { + return [ null, null, null, rgba[ 3 ] ]; + } + var r = rgba[ 0 ] / 255, + g = rgba[ 1 ] / 255, + b = rgba[ 2 ] / 255, + a = rgba[ 3 ], + max = Math.max( r, g, b ), + min = Math.min( r, g, b ), + diff = max - min, + add = max + min, + l = add * 0.5, + h, s; + + if ( min === max ) { + h = 0; + } else if ( r === max ) { + h = ( 60 * ( g - b ) / diff ) + 360; + } else if ( g === max ) { + h = ( 60 * ( b - r ) / diff ) + 120; + } else { + h = ( 60 * ( r - g ) / diff ) + 240; + } + + if ( l === 0 || l === 1 ) { + s = l; + } else if ( l <= 0.5 ) { + s = diff / add; + } else { + s = diff / ( 2 - add ); + } + return [ Math.round(h) % 360, s, l, a == null ? 1 : a ]; +}; + +spaces.hsla.from = function ( hsla ) { + if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { + return [ null, null, null, hsla[ 3 ] ]; + } + var h = hsla[ 0 ] / 360, + s = hsla[ 1 ], + l = hsla[ 2 ], + a = hsla[ 3 ], + q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, + p = 2 * l - q; + + return [ + Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), + Math.round( hue2rgb( p, q, h ) * 255 ), + Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), + a + ]; +}; + + +each( spaces, function( spaceName, space ) { + var props = space.props, + cache = space.cache, + to = space.to, + from = space.from; + + // makes rgba() and hsla() + color.fn[ spaceName ] = function( value ) { + + // generate a cache for this space if it doesn't exist + if ( to && !this[ cache ] ) { + this[ cache ] = to( this._rgba ); + } + if ( value === undefined ) { + return this[ cache ].slice(); + } + + var ret, + type = jQuery.type( value ), + arr = ( type === "array" || type === "object" ) ? value : arguments, + local = this[ cache ].slice(); + + each( props, function( key, prop ) { + var val = arr[ type === "object" ? key : prop.idx ]; + if ( val == null ) { + val = local[ prop.idx ]; + } + local[ prop.idx ] = clamp( val, prop ); + }); + + if ( from ) { + ret = color( from( local ) ); + ret[ cache ] = local; + return ret; + } else { + return color( local ); + } + }; + + // makes red() green() blue() alpha() hue() saturation() lightness() + each( props, function( key, prop ) { + // alpha is included in more than one space + if ( color.fn[ key ] ) { + return; + } + color.fn[ key ] = function( value ) { + var vtype = jQuery.type( value ), + fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ), + local = this[ fn ](), + cur = local[ prop.idx ], + match; + + if ( vtype === "undefined" ) { + return cur; + } + + if ( vtype === "function" ) { + value = value.call( this, cur ); + vtype = jQuery.type( value ); + } + if ( value == null && prop.empty ) { + return this; + } + if ( vtype === "string" ) { + match = rplusequals.exec( value ); + if ( match ) { + value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); + } + } + local[ prop.idx ] = value; + return this[ fn ]( local ); + }; + }); +}); + +// add .fx.step functions +each( stepHooks, function( i, hook ) { + jQuery.cssHooks[ hook ] = { + set: function( elem, value ) { + var parsed, curElem, + backgroundColor = ""; + + if ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) { + value = color( parsed || value ); + if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { + curElem = hook === "backgroundColor" ? elem.parentNode : elem; + while ( + (backgroundColor === "" || backgroundColor === "transparent") && + curElem && curElem.style + ) { + try { + backgroundColor = jQuery.css( curElem, "backgroundColor" ); + curElem = curElem.parentNode; + } catch ( e ) { + } + } + + value = value.blend( backgroundColor && backgroundColor !== "transparent" ? + backgroundColor : + "_default" ); + } + + value = value.toRgbaString(); + } + try { + elem.style[ hook ] = value; + } catch( error ) { + // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' + } + } + }; + jQuery.fx.step[ hook ] = function( fx ) { + if ( !fx.colorInit ) { + fx.start = color( fx.elem, hook ); + fx.end = color( fx.end ); + fx.colorInit = true; + } + jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); + }; +}); + +jQuery.cssHooks.borderColor = { + expand: function( value ) { + var expanded = {}; + + each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) { + expanded[ "border" + part + "Color" ] = value; + }); + return expanded; + } +}; + +// Basic color names only. +// Usage of any of the other color names requires adding yourself or including +// jquery.color.svg-names.js. +colors = jQuery.Color.names = { + // 4.1. Basic color keywords + aqua: "#00ffff", + black: "#000000", + blue: "#0000ff", + fuchsia: "#ff00ff", + gray: "#808080", + green: "#008000", + lime: "#00ff00", + maroon: "#800000", + navy: "#000080", + olive: "#808000", + purple: "#800080", + red: "#ff0000", + silver: "#c0c0c0", + teal: "#008080", + white: "#ffffff", + yellow: "#ffff00", + + // 4.2.3. "transparent" color keyword + transparent: [ null, null, null, 0 ], + + _default: "#ffffff" +}; + +})( jQuery ); + + + +/******************************************************************************/ +/****************************** CLASS ANIMATIONS ******************************/ +/******************************************************************************/ +(function() { + +var classAnimationActions = [ "add", "remove", "toggle" ], + shorthandStyles = { + border: 1, + borderBottom: 1, + borderColor: 1, + borderLeft: 1, + borderRight: 1, + borderTop: 1, + borderWidth: 1, + margin: 1, + padding: 1 + }; + +$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) { + $.fx.step[ prop ] = function( fx ) { + if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { + jQuery.style( fx.elem, prop, fx.end ); + fx.setAttr = true; + } + }; +}); + +function getElementStyles() { + var style = this.ownerDocument.defaultView ? + this.ownerDocument.defaultView.getComputedStyle( this, null ) : + this.currentStyle, + newStyle = {}, + key, + len; + + // webkit enumerates style porperties + if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { + len = style.length; + while ( len-- ) { + key = style[ len ]; + if ( typeof style[ key ] === "string" ) { + newStyle[ $.camelCase( key ) ] = style[ key ]; + } + } + } else { + for ( key in style ) { + if ( typeof style[ key ] === "string" ) { + newStyle[ key ] = style[ key ]; + } + } + } + + return newStyle; +} + + +function styleDifference( oldStyle, newStyle ) { + var diff = {}, + name, value; + + for ( name in newStyle ) { + value = newStyle[ name ]; + if ( oldStyle[ name ] !== value ) { + if ( !shorthandStyles[ name ] ) { + if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { + diff[ name ] = value; + } + } + } + } + + return diff; +} + +$.effects.animateClass = function( value, duration, easing, callback ) { + var o = $.speed( duration, easing, callback ); + + return this.queue( function() { + var animated = $( this ), + baseClass = animated.attr( "class" ) || "", + applyClassChange, + allAnimations = o.children ? animated.find( "*" ).andSelf() : animated; + + // map the animated objects to store the original styles. + allAnimations = allAnimations.map(function() { + var el = $( this ); + return { + el: el, + start: getElementStyles.call( this ) + }; + }); + + // apply class change + applyClassChange = function() { + $.each( classAnimationActions, function(i, action) { + if ( value[ action ] ) { + animated[ action + "Class" ]( value[ action ] ); + } + }); + }; + applyClassChange(); + + // map all animated objects again - calculate new styles and diff + allAnimations = allAnimations.map(function() { + this.end = getElementStyles.call( this.el[ 0 ] ); + this.diff = styleDifference( this.start, this.end ); + return this; + }); + + // apply original class + animated.attr( "class", baseClass ); + + // map all animated objects again - this time collecting a promise + allAnimations = allAnimations.map(function() { + var styleInfo = this, + dfd = $.Deferred(), + opts = jQuery.extend({}, o, { + queue: false, + complete: function() { + dfd.resolve( styleInfo ); + } + }); + + this.el.animate( this.diff, opts ); + return dfd.promise(); + }); + + // once all animations have completed: + $.when.apply( $, allAnimations.get() ).done(function() { + + // set the final class + applyClassChange(); + + // for each animated element, + // clear all css properties that were animated + $.each( arguments, function() { + var el = this.el; + $.each( this.diff, function(key) { + el.css( key, '' ); + }); + }); + + // this is guarnteed to be there if you use jQuery.speed() + // it also handles dequeuing the next anim... + o.complete.call( animated[ 0 ] ); + }); + }); +}; + +$.fn.extend({ + _addClass: $.fn.addClass, + addClass: function( classNames, speed, easing, callback ) { + return speed ? + $.effects.animateClass.call( this, + { add: classNames }, speed, easing, callback ) : + this._addClass( classNames ); + }, + + _removeClass: $.fn.removeClass, + removeClass: function( classNames, speed, easing, callback ) { + return speed ? + $.effects.animateClass.call( this, + { remove: classNames }, speed, easing, callback ) : + this._removeClass( classNames ); + }, + + _toggleClass: $.fn.toggleClass, + toggleClass: function( classNames, force, speed, easing, callback ) { + if ( typeof force === "boolean" || force === undefined ) { + if ( !speed ) { + // without speed parameter + return this._toggleClass( classNames, force ); + } else { + return $.effects.animateClass.call( this, + (force ? { add: classNames } : { remove: classNames }), + speed, easing, callback ); + } + } else { + // without force parameter + return $.effects.animateClass.call( this, + { toggle: classNames }, force, speed, easing ); + } + }, + + switchClass: function( remove, add, speed, easing, callback) { + return $.effects.animateClass.call( this, { + add: add, + remove: remove + }, speed, easing, callback ); + } +}); + +})(); + +/******************************************************************************/ +/*********************************** EFFECTS **********************************/ +/******************************************************************************/ + +(function() { + +$.extend( $.effects, { + version: "@VERSION", + + // Saves a set of properties in a data storage + save: function( element, set ) { + for( var i=0; i < set.length; i++ ) { + if ( set[ i ] !== null ) { + element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); + } + } + }, + + // Restores a set of previously saved properties from a data storage + restore: function( element, set ) { + var val, i; + for( i=0; i < set.length; i++ ) { + if ( set[ i ] !== null ) { + val = element.data( dataSpace + set[ i ] ); + // support: jQuery 1.6.2 + // http://bugs.jquery.com/ticket/9917 + // jQuery 1.6.2 incorrectly returns undefined for any falsy value. + // We can't differentiate between "" and 0 here, so we just assume + // empty string since it's likely to be a more common value... + if ( val === undefined ) { + val = ""; + } + element.css( set[ i ], val ); + } + } + }, + + setMode: function( el, mode ) { + if (mode === "toggle") { + mode = el.is( ":hidden" ) ? "show" : "hide"; + } + return mode; + }, + + // Translates a [top,left] array into a baseline value + // this should be a little more flexible in the future to handle a string & hash + getBaseline: function( origin, original ) { + var y, x; + switch ( origin[ 0 ] ) { + case "top": y = 0; break; + case "middle": y = 0.5; break; + case "bottom": y = 1; break; + default: y = origin[ 0 ] / original.height; + } + switch ( origin[ 1 ] ) { + case "left": x = 0; break; + case "center": x = 0.5; break; + case "right": x = 1; break; + default: x = origin[ 1 ] / original.width; + } + return { + x: x, + y: y + }; + }, + + // Wraps the element around a wrapper that copies position properties + createWrapper: function( element ) { + + // if the element is already wrapped, return it + if ( element.parent().is( ".ui-effects-wrapper" )) { + return element.parent(); + } + + // wrap the element + var props = { + width: element.outerWidth(true), + height: element.outerHeight(true), + "float": element.css( "float" ) + }, + wrapper = $( "<div></div>" ) + .addClass( "ui-effects-wrapper" ) + .css({ + fontSize: "100%", + background: "transparent", + border: "none", + margin: 0, + padding: 0 + }), + // Store the size in case width/height are defined in % - Fixes #5245 + size = { + width: element.width(), + height: element.height() + }, + active = document.activeElement; + + // support: Firefox + // Firefox incorrectly exposes anonymous content + // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 + try { + active.id; + } catch( e ) { + active = document.body; + } + + element.wrap( wrapper ); + + // Fixes #7595 - Elements lose focus when wrapped. + if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { + $( active ).focus(); + } + + wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element + + // transfer positioning properties to the wrapper + if ( element.css( "position" ) === "static" ) { + wrapper.css({ position: "relative" }); + element.css({ position: "relative" }); + } else { + $.extend( props, { + position: element.css( "position" ), + zIndex: element.css( "z-index" ) + }); + $.each([ "top", "left", "bottom", "right" ], function(i, pos) { + props[ pos ] = element.css( pos ); + if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { + props[ pos ] = "auto"; + } + }); + element.css({ + position: "relative", + top: 0, + left: 0, + right: "auto", + bottom: "auto" + }); + } + element.css(size); + + return wrapper.css( props ).show(); + }, + + removeWrapper: function( element ) { + var active = document.activeElement; + + if ( element.parent().is( ".ui-effects-wrapper" ) ) { + element.parent().replaceWith( element ); + + // Fixes #7595 - Elements lose focus when wrapped. + if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { + $( active ).focus(); + } + } + + + return element; + }, + + setTransition: function( element, list, factor, value ) { + value = value || {}; + $.each( list, function( i, x ) { + var unit = element.cssUnit( x ); + if ( unit[ 0 ] > 0 ) { + value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; + } + }); + return value; + } +}); + +// return an effect options object for the given parameters: +function _normalizeArguments( effect, options, speed, callback ) { + + // allow passing all options as the first parameter + if ( $.isPlainObject( effect ) ) { + options = effect; + effect = effect.effect; + } + + // convert to an object + effect = { effect: effect }; + + // catch (effect, null, ...) + if ( options == null ) { + options = {}; + } + + // catch (effect, callback) + if ( $.isFunction( options ) ) { + callback = options; + speed = null; + options = {}; + } + + // catch (effect, speed, ?) + if ( typeof options === "number" || $.fx.speeds[ options ] ) { + callback = speed; + speed = options; + options = {}; + } + + // catch (effect, options, callback) + if ( $.isFunction( speed ) ) { + callback = speed; + speed = null; + } + + // add options to effect + if ( options ) { + $.extend( effect, options ); + } + + speed = speed || options.duration; + effect.duration = $.fx.off ? 0 : + typeof speed === "number" ? speed : + speed in $.fx.speeds ? $.fx.speeds[ speed ] : + $.fx.speeds._default; + + effect.complete = callback || options.complete; + + return effect; +} + +function standardSpeed( speed ) { + // valid standard speeds + if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) { + return true; + } + + // invalid strings - treat as "normal" speed + if ( typeof speed === "string" && !$.effects.effect[ speed ] ) { + // TODO: remove in 2.0 (#7115) + if ( backCompat && $.effects[ speed ] ) { + return false; + } + return true; + } + + return false; +} + +$.fn.extend({ + effect: function( /* effect, options, speed, callback */ ) { + var args = _normalizeArguments.apply( this, arguments ), + mode = args.mode, + queue = args.queue, + effectMethod = $.effects.effect[ args.effect ], + + // DEPRECATED: remove in 2.0 (#7115) + oldEffectMethod = !effectMethod && backCompat && $.effects[ args.effect ]; + + if ( $.fx.off || !( effectMethod || oldEffectMethod ) ) { + // delegate to the original method (e.g., .show()) if possible + if ( mode ) { + return this[ mode ]( args.duration, args.complete ); + } else { + return this.each( function() { + if ( args.complete ) { + args.complete.call( this ); + } + }); + } + } + + function run( next ) { + var elem = $( this ), + complete = args.complete, + mode = args.mode; + + function done() { + if ( $.isFunction( complete ) ) { + complete.call( elem[0] ); + } + if ( $.isFunction( next ) ) { + next(); + } + } + + // if the element is hiddden and mode is hide, + // or element is visible and mode is show + if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { + done(); + } else { + effectMethod.call( elem[0], args, done ); + } + } + + // TODO: remove this check in 2.0, effectMethod will always be true + if ( effectMethod ) { + return queue === false ? this.each( run ) : this.queue( queue || "fx", run ); + } else { + // DEPRECATED: remove in 2.0 (#7115) + return oldEffectMethod.call(this, { + options: args, + duration: args.duration, + callback: args.complete, + mode: args.mode + }); + } + }, + + _show: $.fn.show, + show: function( speed ) { + if ( standardSpeed( speed ) ) { + return this._show.apply( this, arguments ); + } else { + var args = _normalizeArguments.apply( this, arguments ); + args.mode = "show"; + return this.effect.call( this, args ); + } + }, + + _hide: $.fn.hide, + hide: function( speed ) { + if ( standardSpeed( speed ) ) { + return this._hide.apply( this, arguments ); + } else { + var args = _normalizeArguments.apply( this, arguments ); + args.mode = "hide"; + return this.effect.call( this, args ); + } + }, + + // jQuery core overloads toggle and creates _toggle + __toggle: $.fn.toggle, + toggle: function( speed ) { + if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) { + return this.__toggle.apply( this, arguments ); + } else { + var args = _normalizeArguments.apply( this, arguments ); + args.mode = "toggle"; + return this.effect.call( this, args ); + } + }, + + // helper functions + cssUnit: function(key) { + var style = this.css( key ), + val = []; + + $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { + if ( style.indexOf( unit ) > 0 ) { + val = [ parseFloat( style ), unit ]; + } + }); + return val; + } +}); + +})(); + +/******************************************************************************/ +/*********************************** EASING ***********************************/ +/******************************************************************************/ + +(function() { + +// based on easing equations from Robert Penner (http://www.robertpenner.com/easing) + +var baseEasings = {}; + +$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { + baseEasings[ name ] = function( p ) { + return Math.pow( p, i + 2 ); + }; +}); + +$.extend( baseEasings, { + Sine: function ( p ) { + return 1 - Math.cos( p * Math.PI / 2 ); + }, + Circ: function ( p ) { + return 1 - Math.sqrt( 1 - p * p ); + }, + Elastic: function( p ) { + return p === 0 || p === 1 ? p : + -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 ); + }, + Back: function( p ) { + return p * p * ( 3 * p - 2 ); + }, + Bounce: function ( p ) { + var pow2, + bounce = 4; + + while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} + return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); + } +}); + +$.each( baseEasings, function( name, easeIn ) { + $.easing[ "easeIn" + name ] = easeIn; + $.easing[ "easeOut" + name ] = function( p ) { + return 1 - easeIn( 1 - p ); + }; + $.easing[ "easeInOut" + name ] = function( p ) { + return p < 0.5 ? + easeIn( p * 2 ) / 2 : + 1 - easeIn( p * -2 + 2 ) / 2; + }; +}); + +})(); + +})(jQuery)); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.menu.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.menu.js new file mode 100644 index 0000000..45c1ec2 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.menu.js @@ -0,0 +1,610 @@ +/*! + * jQuery UI Menu @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/menu/ + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.position.js + */ +(function( $, undefined ) { + +var mouseHandled = false; + +$.widget( "ui.menu", { + version: "@VERSION", + defaultElement: "<ul>", + delay: 300, + options: { + icons: { + submenu: "ui-icon-carat-1-e" + }, + menus: "ul", + position: { + my: "left top", + at: "right top" + }, + role: "menu", + + // callbacks + blur: null, + focus: null, + select: null + }, + + _create: function() { + this.activeMenu = this.element; + this.element + .uniqueId() + .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) + .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length ) + .attr({ + role: this.options.role, + tabIndex: 0 + }) + // need to catch all clicks on disabled menu + // not possible through _on + .bind( "click" + this.eventNamespace, $.proxy(function( event ) { + if ( this.options.disabled ) { + event.preventDefault(); + } + }, this )); + + if ( this.options.disabled ) { + this.element + .addClass( "ui-state-disabled" ) + .attr( "aria-disabled", "true" ); + } + + this._on({ + // Prevent focus from sticking to links inside menu after clicking + // them (focus should always stay on UL during navigation). + "mousedown .ui-menu-item > a": function( event ) { + event.preventDefault(); + }, + "click .ui-state-disabled > a": function( event ) { + event.preventDefault(); + }, + "click .ui-menu-item:has(a)": function( event ) { + var target = $( event.target ).closest( ".ui-menu-item" ); + if ( !mouseHandled && target.not( ".ui-state-disabled" ).length ) { + mouseHandled = true; + + this.select( event ); + // Open submenu on click + if ( target.has( ".ui-menu" ).length ) { + this.expand( event ); + } else if ( !this.element.is( ":focus" ) ) { + // Redirect focus to the menu + this.element.trigger( "focus", [ true ] ); + + // If the active item is on the top level, let it stay active. + // Otherwise, blur the active item since it is no longer visible. + if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) { + clearTimeout( this.timer ); + } + } + } + }, + "mouseenter .ui-menu-item": function( event ) { + var target = $( event.currentTarget ); + // Remove ui-state-active class from siblings of the newly focused menu item + // to avoid a jump caused by adjacent elements both having a class with a border + target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" ); + this.focus( event, target ); + }, + mouseleave: "collapseAll", + "mouseleave .ui-menu": "collapseAll", + focus: function( event, keepActiveItem ) { + // If there's already an active item, keep it active + // If not, activate the first item + var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 ); + + if ( !keepActiveItem ) { + this.focus( event, item ); + } + }, + blur: function( event ) { + this._delay(function() { + if ( !$.contains( this.element[0], this.document[0].activeElement ) ) { + this.collapseAll( event ); + } + }); + }, + keydown: "_keydown" + }); + + this.refresh(); + + // Clicks outside of a menu collapse any open menus + this._on( this.document, { + click: function( event ) { + if ( !$( event.target ).closest( ".ui-menu" ).length ) { + this.collapseAll( event ); + } + + // Reset the mouseHandled flag + mouseHandled = false; + } + }); + }, + + _destroy: function() { + // Destroy (sub)menus + this.element + .removeAttr( "aria-activedescendant" ) + .find( ".ui-menu" ).andSelf() + .removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" ) + .removeAttr( "role" ) + .removeAttr( "tabIndex" ) + .removeAttr( "aria-labelledby" ) + .removeAttr( "aria-expanded" ) + .removeAttr( "aria-hidden" ) + .removeAttr( "aria-disabled" ) + .removeUniqueId() + .show(); + + // Destroy menu items + this.element.find( ".ui-menu-item" ) + .removeClass( "ui-menu-item" ) + .removeAttr( "role" ) + .removeAttr( "aria-disabled" ) + .children( "a" ) + .removeUniqueId() + .removeClass( "ui-corner-all ui-state-hover" ) + .removeAttr( "tabIndex" ) + .removeAttr( "role" ) + .removeAttr( "aria-haspopup" ) + .children().each( function() { + var elem = $( this ); + if ( elem.data( "ui-menu-submenu-carat" ) ) { + elem.remove(); + } + }); + + // Destroy menu dividers + this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" ); + }, + + _keydown: function( event ) { + var match, prev, character, skip, regex, + preventDefault = true; + + function escape( value ) { + return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ); + } + + switch ( event.keyCode ) { + case $.ui.keyCode.PAGE_UP: + this.previousPage( event ); + break; + case $.ui.keyCode.PAGE_DOWN: + this.nextPage( event ); + break; + case $.ui.keyCode.HOME: + this._move( "first", "first", event ); + break; + case $.ui.keyCode.END: + this._move( "last", "last", event ); + break; + case $.ui.keyCode.UP: + this.previous( event ); + break; + case $.ui.keyCode.DOWN: + this.next( event ); + break; + case $.ui.keyCode.LEFT: + this.collapse( event ); + break; + case $.ui.keyCode.RIGHT: + if ( this.active && !this.active.is( ".ui-state-disabled" ) ) { + this.expand( event ); + } + break; + case $.ui.keyCode.ENTER: + case $.ui.keyCode.SPACE: + this._activate( event ); + break; + case $.ui.keyCode.ESCAPE: + this.collapse( event ); + break; + default: + preventDefault = false; + prev = this.previousFilter || ""; + character = String.fromCharCode( event.keyCode ); + skip = false; + + clearTimeout( this.filterTimer ); + + if ( character === prev ) { + skip = true; + } else { + character = prev + character; + } + + regex = new RegExp( "^" + escape( character ), "i" ); + match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { + return regex.test( $( this ).children( "a" ).text() ); + }); + match = skip && match.index( this.active.next() ) !== -1 ? + this.active.nextAll( ".ui-menu-item" ) : + match; + + // If no matches on the current filter, reset to the last character pressed + // to move down the menu to the first item that starts with that character + if ( !match.length ) { + character = String.fromCharCode( event.keyCode ); + regex = new RegExp( "^" + escape( character ), "i" ); + match = this.activeMenu.children( ".ui-menu-item" ).filter(function() { + return regex.test( $( this ).children( "a" ).text() ); + }); + } + + if ( match.length ) { + this.focus( event, match ); + if ( match.length > 1 ) { + this.previousFilter = character; + this.filterTimer = this._delay(function() { + delete this.previousFilter; + }, 1000 ); + } else { + delete this.previousFilter; + } + } else { + delete this.previousFilter; + } + } + + if ( preventDefault ) { + event.preventDefault(); + } + }, + + _activate: function( event ) { + if ( !this.active.is( ".ui-state-disabled" ) ) { + if ( this.active.children( "a[aria-haspopup='true']" ).length ) { + this.expand( event ); + } else { + this.select( event ); + } + } + }, + + refresh: function() { + var menus, + icon = this.options.icons.submenu, + submenus = this.element.find( this.options.menus ); + + // Initialize nested menus + submenus.filter( ":not(.ui-menu)" ) + .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" ) + .hide() + .attr({ + role: this.options.role, + "aria-hidden": "true", + "aria-expanded": "false" + }) + .each(function() { + var menu = $( this ), + item = menu.prev( "a" ), + submenuCarat = $( "<span>" ) + .addClass( "ui-menu-icon ui-icon " + icon ) + .data( "ui-menu-submenu-carat", true ); + + item + .attr( "aria-haspopup", "true" ) + .prepend( submenuCarat ); + menu.attr( "aria-labelledby", item.attr( "id" ) ); + }); + + menus = submenus.add( this.element ); + + // Don't refresh list items that are already adapted + menus.children( ":not(.ui-menu-item):has(a)" ) + .addClass( "ui-menu-item" ) + .attr( "role", "presentation" ) + .children( "a" ) + .uniqueId() + .addClass( "ui-corner-all" ) + .attr({ + tabIndex: -1, + role: this._itemRole() + }); + + // Initialize unlinked menu-items containing spaces and/or dashes only as dividers + menus.children( ":not(.ui-menu-item)" ).each(function() { + var item = $( this ); + // hyphen, em dash, en dash + if ( !/[^\-—–\s]/.test( item.text() ) ) { + item.addClass( "ui-widget-content ui-menu-divider" ); + } + }); + + // Add aria-disabled attribute to any disabled menu item + menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" ); + + // If the active item has been removed, blur the menu + if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { + this.blur(); + } + }, + + _itemRole: function() { + return { + menu: "menuitem", + listbox: "option" + }[ this.options.role ]; + }, + + focus: function( event, item ) { + var nested, focused; + this.blur( event, event && event.type === "focus" ); + + this._scrollIntoView( item ); + + this.active = item.first(); + focused = this.active.children( "a" ).addClass( "ui-state-focus" ); + // Only update aria-activedescendant if there's a role + // otherwise we assume focus is managed elsewhere + if ( this.options.role ) { + this.element.attr( "aria-activedescendant", focused.attr( "id" ) ); + } + + // Highlight active parent menu item, if any + this.active + .parent() + .closest( ".ui-menu-item" ) + .children( "a:first" ) + .addClass( "ui-state-active" ); + + if ( event && event.type === "keydown" ) { + this._close(); + } else { + this.timer = this._delay(function() { + this._close(); + }, this.delay ); + } + + nested = item.children( ".ui-menu" ); + if ( nested.length && ( /^mouse/.test( event.type ) ) ) { + this._startOpening(nested); + } + this.activeMenu = item.parent(); + + this._trigger( "focus", event, { item: item } ); + }, + + _scrollIntoView: function( item ) { + var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight; + if ( this._hasScroll() ) { + borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0; + paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0; + offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop; + scroll = this.activeMenu.scrollTop(); + elementHeight = this.activeMenu.height(); + itemHeight = item.height(); + + if ( offset < 0 ) { + this.activeMenu.scrollTop( scroll + offset ); + } else if ( offset + itemHeight > elementHeight ) { + this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight ); + } + } + }, + + blur: function( event, fromFocus ) { + if ( !fromFocus ) { + clearTimeout( this.timer ); + } + + if ( !this.active ) { + return; + } + + this.active.children( "a" ).removeClass( "ui-state-focus" ); + this.active = null; + + this._trigger( "blur", event, { item: this.active } ); + }, + + _startOpening: function( submenu ) { + clearTimeout( this.timer ); + + // Don't open if already open fixes a Firefox bug that caused a .5 pixel + // shift in the submenu position when mousing over the carat icon + if ( submenu.attr( "aria-hidden" ) !== "true" ) { + return; + } + + this.timer = this._delay(function() { + this._close(); + this._open( submenu ); + }, this.delay ); + }, + + _open: function( submenu ) { + var position = $.extend({ + of: this.active + }, this.options.position ); + + clearTimeout( this.timer ); + this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) ) + .hide() + .attr( "aria-hidden", "true" ); + + submenu + .show() + .removeAttr( "aria-hidden" ) + .attr( "aria-expanded", "true" ) + .position( position ); + }, + + collapseAll: function( event, all ) { + clearTimeout( this.timer ); + this.timer = this._delay(function() { + // If we were passed an event, look for the submenu that contains the event + var currentMenu = all ? this.element : + $( event && event.target ).closest( this.element.find( ".ui-menu" ) ); + + // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway + if ( !currentMenu.length ) { + currentMenu = this.element; + } + + this._close( currentMenu ); + + this.blur( event ); + this.activeMenu = currentMenu; + }, this.delay ); + }, + + // With no arguments, closes the currently active menu - if nothing is active + // it closes all menus. If passed an argument, it will search for menus BELOW + _close: function( startMenu ) { + if ( !startMenu ) { + startMenu = this.active ? this.active.parent() : this.element; + } + + startMenu + .find( ".ui-menu" ) + .hide() + .attr( "aria-hidden", "true" ) + .attr( "aria-expanded", "false" ) + .end() + .find( "a.ui-state-active" ) + .removeClass( "ui-state-active" ); + }, + + collapse: function( event ) { + var newItem = this.active && + this.active.parent().closest( ".ui-menu-item", this.element ); + if ( newItem && newItem.length ) { + this._close(); + this.focus( event, newItem ); + } + }, + + expand: function( event ) { + var newItem = this.active && + this.active + .children( ".ui-menu " ) + .children( ".ui-menu-item" ) + .first(); + + if ( newItem && newItem.length ) { + this._open( newItem.parent() ); + + // Delay so Firefox will not hide activedescendant change in expanding submenu from AT + this._delay(function() { + this.focus( event, newItem ); + }); + } + }, + + next: function( event ) { + this._move( "next", "first", event ); + }, + + previous: function( event ) { + this._move( "prev", "last", event ); + }, + + isFirstItem: function() { + return this.active && !this.active.prevAll( ".ui-menu-item" ).length; + }, + + isLastItem: function() { + return this.active && !this.active.nextAll( ".ui-menu-item" ).length; + }, + + _move: function( direction, filter, event ) { + var next; + if ( this.active ) { + if ( direction === "first" || direction === "last" ) { + next = this.active + [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" ) + .eq( -1 ); + } else { + next = this.active + [ direction + "All" ]( ".ui-menu-item" ) + .eq( 0 ); + } + } + if ( !next || !next.length || !this.active ) { + next = this.activeMenu.children( ".ui-menu-item" )[ filter ](); + } + + this.focus( event, next ); + }, + + nextPage: function( event ) { + var item, base, height; + + if ( !this.active ) { + this.next( event ); + return; + } + if ( this.isLastItem() ) { + return; + } + if ( this._hasScroll() ) { + base = this.active.offset().top; + height = this.element.height(); + this.active.nextAll( ".ui-menu-item" ).each(function() { + item = $( this ); + return item.offset().top - base - height < 0; + }); + + this.focus( event, item ); + } else { + this.focus( event, this.activeMenu.children( ".ui-menu-item" ) + [ !this.active ? "first" : "last" ]() ); + } + }, + + previousPage: function( event ) { + var item, base, height; + if ( !this.active ) { + this.next( event ); + return; + } + if ( this.isFirstItem() ) { + return; + } + if ( this._hasScroll() ) { + base = this.active.offset().top; + height = this.element.height(); + this.active.prevAll( ".ui-menu-item" ).each(function() { + item = $( this ); + return item.offset().top - base + height > 0; + }); + + this.focus( event, item ); + } else { + this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() ); + } + }, + + _hasScroll: function() { + return this.element.outerHeight() < this.element.prop( "scrollHeight" ); + }, + + select: function( event ) { + // TODO: It should never be possible to not have an active item at this + // point, but the tests don't trigger mouseenter before click. + this.active = this.active || $( event.target ).closest( ".ui-menu-item" ); + var ui = { item: this.active }; + if ( !this.active.has( ".ui-menu" ).length ) { + this.collapseAll( event, true ); + } + this._trigger( "select", event, ui ); + } +}); + +}( jQuery )); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.mouse.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.mouse.js new file mode 100644 index 0000000..cdc063f --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.mouse.js @@ -0,0 +1,169 @@ +/*! + * jQuery UI Mouse @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/mouse/ + * + * Depends: + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +var mouseHandled = false; +$( document ).mouseup( function( e ) { + mouseHandled = false; +}); + +$.widget("ui.mouse", { + version: "@VERSION", + options: { + cancel: 'input,textarea,button,select,option', + distance: 1, + delay: 0 + }, + _mouseInit: function() { + var that = this; + + this.element + .bind('mousedown.'+this.widgetName, function(event) { + return that._mouseDown(event); + }) + .bind('click.'+this.widgetName, function(event) { + if (true === $.data(event.target, that.widgetName + '.preventClickEvent')) { + $.removeData(event.target, that.widgetName + '.preventClickEvent'); + event.stopImmediatePropagation(); + return false; + } + }); + + this.started = false; + }, + + // TODO: make sure destroying one instance of mouse doesn't mess with + // other instances of mouse + _mouseDestroy: function() { + this.element.unbind('.'+this.widgetName); + if ( this._mouseMoveDelegate ) { + $(document) + .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate) + .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate); + } + }, + + _mouseDown: function(event) { + // don't let more than one widget handle mouseStart + if( mouseHandled ) { return; } + + // we may have missed mouseup (out of window) + (this._mouseStarted && this._mouseUp(event)); + + this._mouseDownEvent = event; + + var that = this, + btnIsLeft = (event.which === 1), + // event.target.nodeName works around a bug in IE 8 with + // disabled inputs (#7620) + elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false); + if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) { + return true; + } + + this.mouseDelayMet = !this.options.delay; + if (!this.mouseDelayMet) { + this._mouseDelayTimer = setTimeout(function() { + that.mouseDelayMet = true; + }, this.options.delay); + } + + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { + this._mouseStarted = (this._mouseStart(event) !== false); + if (!this._mouseStarted) { + event.preventDefault(); + return true; + } + } + + // Click event may never have fired (Gecko & Opera) + if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) { + $.removeData(event.target, this.widgetName + '.preventClickEvent'); + } + + // these delegates are required to keep context + this._mouseMoveDelegate = function(event) { + return that._mouseMove(event); + }; + this._mouseUpDelegate = function(event) { + return that._mouseUp(event); + }; + $(document) + .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate) + .bind('mouseup.'+this.widgetName, this._mouseUpDelegate); + + event.preventDefault(); + + mouseHandled = true; + return true; + }, + + _mouseMove: function(event) { + // IE mouseup check - mouseup happened when mouse was out of window + if ($.ui.ie && !(document.documentMode >= 9) && !event.button) { + return this._mouseUp(event); + } + + if (this._mouseStarted) { + this._mouseDrag(event); + return event.preventDefault(); + } + + if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) { + this._mouseStarted = + (this._mouseStart(this._mouseDownEvent, event) !== false); + (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event)); + } + + return !this._mouseStarted; + }, + + _mouseUp: function(event) { + $(document) + .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate) + .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate); + + if (this._mouseStarted) { + this._mouseStarted = false; + + if (event.target === this._mouseDownEvent.target) { + $.data(event.target, this.widgetName + '.preventClickEvent', true); + } + + this._mouseStop(event); + } + + return false; + }, + + _mouseDistanceMet: function(event) { + return (Math.max( + Math.abs(this._mouseDownEvent.pageX - event.pageX), + Math.abs(this._mouseDownEvent.pageY - event.pageY) + ) >= this.options.distance + ); + }, + + _mouseDelayMet: function(event) { + return this.mouseDelayMet; + }, + + // These are placeholder methods, to be overriden by extending plugin + _mouseStart: function(event) {}, + _mouseDrag: function(event) {}, + _mouseStop: function(event) {}, + _mouseCapture: function(event) { return true; } +}); + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.position.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.position.js new file mode 100644 index 0000000..5b595a8 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.position.js @@ -0,0 +1,517 @@ +/*! + * jQuery UI Position @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/position/ + */ +(function( $, undefined ) { + +$.ui = $.ui || {}; + +var cachedScrollbarWidth, + max = Math.max, + abs = Math.abs, + round = Math.round, + rhorizontal = /left|center|right/, + rvertical = /top|center|bottom/, + roffset = /[\+\-]\d+%?/, + rposition = /^\w+/, + rpercent = /%$/, + _position = $.fn.position; + +function getOffsets( offsets, width, height ) { + return [ + parseInt( offsets[ 0 ], 10 ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), + parseInt( offsets[ 1 ], 10 ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) + ]; +} +function parseCss( element, property ) { + return parseInt( $.css( element, property ), 10 ) || 0; +} + +$.position = { + scrollbarWidth: function() { + if ( cachedScrollbarWidth !== undefined ) { + return cachedScrollbarWidth; + } + var w1, w2, + div = $( "<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ), + innerDiv = div.children()[0]; + + $( "body" ).append( div ); + w1 = innerDiv.offsetWidth; + div.css( "overflow", "scroll" ); + + w2 = innerDiv.offsetWidth; + + if ( w1 === w2 ) { + w2 = div[0].clientWidth; + } + + div.remove(); + + return (cachedScrollbarWidth = w1 - w2); + }, + getScrollInfo: function( within ) { + var overflowX = within.isWindow ? "" : within.element.css( "overflow-x" ), + overflowY = within.isWindow ? "" : within.element.css( "overflow-y" ), + hasOverflowX = overflowX === "scroll" || + ( overflowX === "auto" && within.width < within.element[0].scrollWidth ), + hasOverflowY = overflowY === "scroll" || + ( overflowY === "auto" && within.height < within.element[0].scrollHeight ); + return { + width: hasOverflowX ? $.position.scrollbarWidth() : 0, + height: hasOverflowY ? $.position.scrollbarWidth() : 0 + }; + }, + getWithinInfo: function( element ) { + var withinElement = $( element || window ), + isWindow = $.isWindow( withinElement[0] ); + return { + element: withinElement, + isWindow: isWindow, + offset: withinElement.offset() || { left: 0, top: 0 }, + scrollLeft: withinElement.scrollLeft(), + scrollTop: withinElement.scrollTop(), + width: isWindow ? withinElement.width() : withinElement.outerWidth(), + height: isWindow ? withinElement.height() : withinElement.outerHeight() + }; + } +}; + +$.fn.position = function( options ) { + if ( !options || !options.of ) { + return _position.apply( this, arguments ); + } + + // make a copy, we don't want to modify arguments + options = $.extend( {}, options ); + + var atOffset, targetWidth, targetHeight, targetOffset, basePosition, + target = $( options.of ), + within = $.position.getWithinInfo( options.within ), + scrollInfo = $.position.getScrollInfo( within ), + targetElem = target[0], + collision = ( options.collision || "flip" ).split( " " ), + offsets = {}; + + if ( targetElem.nodeType === 9 ) { + targetWidth = target.width(); + targetHeight = target.height(); + targetOffset = { top: 0, left: 0 }; + } else if ( $.isWindow( targetElem ) ) { + targetWidth = target.width(); + targetHeight = target.height(); + targetOffset = { top: target.scrollTop(), left: target.scrollLeft() }; + } else if ( targetElem.preventDefault ) { + // force left top to allow flipping + options.at = "left top"; + targetWidth = targetHeight = 0; + targetOffset = { top: targetElem.pageY, left: targetElem.pageX }; + } else { + targetWidth = target.outerWidth(); + targetHeight = target.outerHeight(); + targetOffset = target.offset(); + } + // clone to reuse original targetOffset later + basePosition = $.extend( {}, targetOffset ); + + // force my and at to have valid horizontal and vertical positions + // if a value is missing or invalid, it will be converted to center + $.each( [ "my", "at" ], function() { + var pos = ( options[ this ] || "" ).split( " " ), + horizontalOffset, + verticalOffset; + + if ( pos.length === 1) { + pos = rhorizontal.test( pos[ 0 ] ) ? + pos.concat( [ "center" ] ) : + rvertical.test( pos[ 0 ] ) ? + [ "center" ].concat( pos ) : + [ "center", "center" ]; + } + pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; + pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; + + // calculate offsets + horizontalOffset = roffset.exec( pos[ 0 ] ); + verticalOffset = roffset.exec( pos[ 1 ] ); + offsets[ this ] = [ + horizontalOffset ? horizontalOffset[ 0 ] : 0, + verticalOffset ? verticalOffset[ 0 ] : 0 + ]; + + // reduce to just the positions without the offsets + options[ this ] = [ + rposition.exec( pos[ 0 ] )[ 0 ], + rposition.exec( pos[ 1 ] )[ 0 ] + ]; + }); + + // normalize collision option + if ( collision.length === 1 ) { + collision[ 1 ] = collision[ 0 ]; + } + + if ( options.at[ 0 ] === "right" ) { + basePosition.left += targetWidth; + } else if ( options.at[ 0 ] === "center" ) { + basePosition.left += targetWidth / 2; + } + + if ( options.at[ 1 ] === "bottom" ) { + basePosition.top += targetHeight; + } else if ( options.at[ 1 ] === "center" ) { + basePosition.top += targetHeight / 2; + } + + atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); + basePosition.left += atOffset[ 0 ]; + basePosition.top += atOffset[ 1 ]; + + return this.each(function() { + var collisionPosition, using, + elem = $( this ), + elemWidth = elem.outerWidth(), + elemHeight = elem.outerHeight(), + marginLeft = parseCss( this, "marginLeft" ), + marginTop = parseCss( this, "marginTop" ), + collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width, + collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height, + position = $.extend( {}, basePosition ), + myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); + + if ( options.my[ 0 ] === "right" ) { + position.left -= elemWidth; + } else if ( options.my[ 0 ] === "center" ) { + position.left -= elemWidth / 2; + } + + if ( options.my[ 1 ] === "bottom" ) { + position.top -= elemHeight; + } else if ( options.my[ 1 ] === "center" ) { + position.top -= elemHeight / 2; + } + + position.left += myOffset[ 0 ]; + position.top += myOffset[ 1 ]; + + // if the browser doesn't support fractions, then round for consistent results + if ( !$.support.offsetFractions ) { + position.left = round( position.left ); + position.top = round( position.top ); + } + + collisionPosition = { + marginLeft: marginLeft, + marginTop: marginTop + }; + + $.each( [ "left", "top" ], function( i, dir ) { + if ( $.ui.position[ collision[ i ] ] ) { + $.ui.position[ collision[ i ] ][ dir ]( position, { + targetWidth: targetWidth, + targetHeight: targetHeight, + elemWidth: elemWidth, + elemHeight: elemHeight, + collisionPosition: collisionPosition, + collisionWidth: collisionWidth, + collisionHeight: collisionHeight, + offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], + my: options.my, + at: options.at, + within: within, + elem : elem + }); + } + }); + + if ( $.fn.bgiframe ) { + elem.bgiframe(); + } + + if ( options.using ) { + // adds feedback as second argument to using callback, if present + using = function( props ) { + var left = targetOffset.left - position.left, + right = left + targetWidth - elemWidth, + top = targetOffset.top - position.top, + bottom = top + targetHeight - elemHeight, + feedback = { + target: { + element: target, + left: targetOffset.left, + top: targetOffset.top, + width: targetWidth, + height: targetHeight + }, + element: { + element: elem, + left: position.left, + top: position.top, + width: elemWidth, + height: elemHeight + }, + horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", + vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" + }; + if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { + feedback.horizontal = "center"; + } + if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { + feedback.vertical = "middle"; + } + if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { + feedback.important = "horizontal"; + } else { + feedback.important = "vertical"; + } + options.using.call( this, props, feedback ); + }; + } + + elem.offset( $.extend( position, { using: using } ) ); + }); +}; + +$.ui.position = { + fit: { + left: function( position, data ) { + var within = data.within, + withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, + outerWidth = within.width, + collisionPosLeft = position.left - data.collisionPosition.marginLeft, + overLeft = withinOffset - collisionPosLeft, + overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, + newOverRight; + + // element is wider than within + if ( data.collisionWidth > outerWidth ) { + // element is initially over the left side of within + if ( overLeft > 0 && overRight <= 0 ) { + newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset; + position.left += overLeft - newOverRight; + // element is initially over right side of within + } else if ( overRight > 0 && overLeft <= 0 ) { + position.left = withinOffset; + // element is initially over both left and right sides of within + } else { + if ( overLeft > overRight ) { + position.left = withinOffset + outerWidth - data.collisionWidth; + } else { + position.left = withinOffset; + } + } + // too far left -> align with left edge + } else if ( overLeft > 0 ) { + position.left += overLeft; + // too far right -> align with right edge + } else if ( overRight > 0 ) { + position.left -= overRight; + // adjust based on position and margin + } else { + position.left = max( position.left - collisionPosLeft, position.left ); + } + }, + top: function( position, data ) { + var within = data.within, + withinOffset = within.isWindow ? within.scrollTop : within.offset.top, + outerHeight = data.within.height, + collisionPosTop = position.top - data.collisionPosition.marginTop, + overTop = withinOffset - collisionPosTop, + overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, + newOverBottom; + + // element is taller than within + if ( data.collisionHeight > outerHeight ) { + // element is initially over the top of within + if ( overTop > 0 && overBottom <= 0 ) { + newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset; + position.top += overTop - newOverBottom; + // element is initially over bottom of within + } else if ( overBottom > 0 && overTop <= 0 ) { + position.top = withinOffset; + // element is initially over both top and bottom of within + } else { + if ( overTop > overBottom ) { + position.top = withinOffset + outerHeight - data.collisionHeight; + } else { + position.top = withinOffset; + } + } + // too far up -> align with top + } else if ( overTop > 0 ) { + position.top += overTop; + // too far down -> align with bottom edge + } else if ( overBottom > 0 ) { + position.top -= overBottom; + // adjust based on position and margin + } else { + position.top = max( position.top - collisionPosTop, position.top ); + } + } + }, + flip: { + left: function( position, data ) { + var within = data.within, + withinOffset = within.offset.left + within.scrollLeft, + outerWidth = within.width, + offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, + collisionPosLeft = position.left - data.collisionPosition.marginLeft, + overLeft = collisionPosLeft - offsetLeft, + overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, + myOffset = data.my[ 0 ] === "left" ? + -data.elemWidth : + data.my[ 0 ] === "right" ? + data.elemWidth : + 0, + atOffset = data.at[ 0 ] === "left" ? + data.targetWidth : + data.at[ 0 ] === "right" ? + -data.targetWidth : + 0, + offset = -2 * data.offset[ 0 ], + newOverRight, + newOverLeft; + + if ( overLeft < 0 ) { + newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset; + if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { + position.left += myOffset + atOffset + offset; + } + } + else if ( overRight > 0 ) { + newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft; + if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { + position.left += myOffset + atOffset + offset; + } + } + }, + top: function( position, data ) { + var within = data.within, + withinOffset = within.offset.top + within.scrollTop, + outerHeight = within.height, + offsetTop = within.isWindow ? within.scrollTop : within.offset.top, + collisionPosTop = position.top - data.collisionPosition.marginTop, + overTop = collisionPosTop - offsetTop, + overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, + top = data.my[ 1 ] === "top", + myOffset = top ? + -data.elemHeight : + data.my[ 1 ] === "bottom" ? + data.elemHeight : + 0, + atOffset = data.at[ 1 ] === "top" ? + data.targetHeight : + data.at[ 1 ] === "bottom" ? + -data.targetHeight : + 0, + offset = -2 * data.offset[ 1 ], + newOverTop, + newOverBottom; + if ( overTop < 0 ) { + newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset; + if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) { + position.top += myOffset + atOffset + offset; + } + } + else if ( overBottom > 0 ) { + newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop; + if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) { + position.top += myOffset + atOffset + offset; + } + } + } + }, + flipfit: { + left: function() { + $.ui.position.flip.left.apply( this, arguments ); + $.ui.position.fit.left.apply( this, arguments ); + }, + top: function() { + $.ui.position.flip.top.apply( this, arguments ); + $.ui.position.fit.top.apply( this, arguments ); + } + } +}; + +// fraction support test +(function () { + var testElement, testElementParent, testElementStyle, offsetLeft, i, + body = document.getElementsByTagName( "body" )[ 0 ], + div = document.createElement( "div" ); + + //Create a "fake body" for testing based on method used in jQuery.support + testElement = document.createElement( body ? "div" : "body" ); + testElementStyle = { + visibility: "hidden", + width: 0, + height: 0, + border: 0, + margin: 0, + background: "none" + }; + if ( body ) { + $.extend( testElementStyle, { + position: "absolute", + left: "-1000px", + top: "-1000px" + }); + } + for ( i in testElementStyle ) { + testElement.style[ i ] = testElementStyle[ i ]; + } + testElement.appendChild( div ); + testElementParent = body || document.documentElement; + testElementParent.insertBefore( testElement, testElementParent.firstChild ); + + div.style.cssText = "position: absolute; left: 10.7432222px;"; + + offsetLeft = $( div ).offset().left; + $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11; + + testElement.innerHTML = ""; + testElementParent.removeChild( testElement ); +})(); + +// DEPRECATED +if ( $.uiBackCompat !== false ) { + // offset option + (function( $ ) { + var _position = $.fn.position; + $.fn.position = function( options ) { + if ( !options || !options.offset ) { + return _position.call( this, options ); + } + var offset = options.offset.split( " " ), + at = options.at.split( " " ); + if ( offset.length === 1 ) { + offset[ 1 ] = offset[ 0 ]; + } + if ( /^\d/.test( offset[ 0 ] ) ) { + offset[ 0 ] = "+" + offset[ 0 ]; + } + if ( /^\d/.test( offset[ 1 ] ) ) { + offset[ 1 ] = "+" + offset[ 1 ]; + } + if ( at.length === 1 ) { + if ( /left|center|right/.test( at[ 0 ] ) ) { + at[ 1 ] = "center"; + } else { + at[ 1 ] = at[ 0 ]; + at[ 0 ] = "center"; + } + } + return _position.call( this, $.extend( options, { + at: at[ 0 ] + offset[ 0 ] + " " + at[ 1 ] + offset[ 1 ], + offset: undefined + } ) ); + }; + }( jQuery ) ); +} + +}( jQuery ) ); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.progressbar.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.progressbar.js new file mode 100644 index 0000000..cb561eb --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.progressbar.js @@ -0,0 +1,105 @@ +/*! + * jQuery UI Progressbar @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/progressbar/ + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +$.widget( "ui.progressbar", { + version: "@VERSION", + options: { + value: 0, + max: 100 + }, + + min: 0, + + _create: function() { + this.element + .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) + .attr({ + role: "progressbar", + "aria-valuemin": this.min, + "aria-valuemax": this.options.max, + "aria-valuenow": this._value() + }); + + this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" ) + .appendTo( this.element ); + + this.oldValue = this._value(); + this._refreshValue(); + }, + + _destroy: function() { + this.element + .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" ) + .removeAttr( "role" ) + .removeAttr( "aria-valuemin" ) + .removeAttr( "aria-valuemax" ) + .removeAttr( "aria-valuenow" ); + + this.valueDiv.remove(); + }, + + value: function( newValue ) { + if ( newValue === undefined ) { + return this._value(); + } + + this._setOption( "value", newValue ); + return this; + }, + + _setOption: function( key, value ) { + if ( key === "value" ) { + this.options.value = value; + this._refreshValue(); + if ( this._value() === this.options.max ) { + this._trigger( "complete" ); + } + } + + this._super( key, value ); + }, + + _value: function() { + var val = this.options.value; + // normalize invalid value + if ( typeof val !== "number" ) { + val = 0; + } + return Math.min( this.options.max, Math.max( this.min, val ) ); + }, + + _percentage: function() { + return 100 * this._value() / this.options.max; + }, + + _refreshValue: function() { + var value = this.value(), + percentage = this._percentage(); + + if ( this.oldValue !== value ) { + this.oldValue = value; + this._trigger( "change" ); + } + + this.valueDiv + .toggle( value > this.min ) + .toggleClass( "ui-corner-right", value === this.options.max ) + .width( percentage.toFixed(0) + "%" ); + this.element.attr( "aria-valuenow", value ); + } +}); + +})( jQuery ); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.resizable.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.resizable.js new file mode 100644 index 0000000..fc4868c --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.resizable.js @@ -0,0 +1,801 @@ +/*! + * jQuery UI Resizable @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/resizable/ + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +$.widget("ui.resizable", $.ui.mouse, { + version: "@VERSION", + widgetEventPrefix: "resize", + options: { + alsoResize: false, + animate: false, + animateDuration: "slow", + animateEasing: "swing", + aspectRatio: false, + autoHide: false, + containment: false, + ghost: false, + grid: false, + handles: "e,s,se", + helper: false, + maxHeight: null, + maxWidth: null, + minHeight: 10, + minWidth: 10, + zIndex: 1000 + }, + _create: function() { + + var that = this, o = this.options; + this.element.addClass("ui-resizable"); + + $.extend(this, { + _aspectRatio: !!(o.aspectRatio), + aspectRatio: o.aspectRatio, + originalElement: this.element, + _proportionallyResizeElements: [], + _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null + }); + + //Wrap the element if it cannot hold child nodes + if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) { + + //Create a wrapper element and set the wrapper to the new current internal element + this.element.wrap( + $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({ + position: this.element.css('position'), + width: this.element.outerWidth(), + height: this.element.outerHeight(), + top: this.element.css('top'), + left: this.element.css('left') + }) + ); + + //Overwrite the original this.element + this.element = this.element.parent().data( + "resizable", this.element.data('resizable') + ); + + this.elementIsWrapper = true; + + //Move margins to the wrapper + this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") }); + this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0}); + + //Prevent Safari textarea resize + this.originalResizeStyle = this.originalElement.css('resize'); + this.originalElement.css('resize', 'none'); + + //Push the actual element to our proportionallyResize internal array + this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' })); + + // avoid IE jump (hard set the margin) + this.originalElement.css({ margin: this.originalElement.css('margin') }); + + // fix handlers offset + this._proportionallyResize(); + + } + + this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' }); + if(this.handles.constructor == String) { + + if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw'; + var n = this.handles.split(","); this.handles = {}; + + for(var i = 0; i < n.length; i++) { + + var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle; + var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>'); + + // Apply zIndex to all handles - see #7960 + axis.css({ zIndex: o.zIndex }); + + //TODO : What's going on here? + if ('se' == handle) { + axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se'); + }; + + //Insert into internal handles object and append to element + this.handles[handle] = '.ui-resizable-'+handle; + this.element.append(axis); + } + + } + + this._renderAxis = function(target) { + + target = target || this.element; + + for(var i in this.handles) { + + if(this.handles[i].constructor == String) + this.handles[i] = $(this.handles[i], this.element).show(); + + //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls) + if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) { + + var axis = $(this.handles[i], this.element), padWrapper = 0; + + //Checking the correct pad and border + padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth(); + + //The padding type i have to apply... + var padPos = [ 'padding', + /ne|nw|n/.test(i) ? 'Top' : + /se|sw|s/.test(i) ? 'Bottom' : + /^e$/.test(i) ? 'Right' : 'Left' ].join(""); + + target.css(padPos, padWrapper); + + this._proportionallyResize(); + + } + + //TODO: What's that good for? There's not anything to be executed left + if(!$(this.handles[i]).length) + continue; + + } + }; + + //TODO: make renderAxis a prototype function + this._renderAxis(this.element); + + this._handles = $('.ui-resizable-handle', this.element) + .disableSelection(); + + //Matching axis name + this._handles.mouseover(function() { + if (!that.resizing) { + if (this.className) + var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i); + //Axis, default = se + that.axis = axis && axis[1] ? axis[1] : 'se'; + } + }); + + //If we want to auto hide the elements + if (o.autoHide) { + this._handles.hide(); + $(this.element) + .addClass("ui-resizable-autohide") + .mouseenter(function() { + if (o.disabled) return; + $(this).removeClass("ui-resizable-autohide"); + that._handles.show(); + }) + .mouseleave(function(){ + if (o.disabled) return; + if (!that.resizing) { + $(this).addClass("ui-resizable-autohide"); + that._handles.hide(); + } + }); + } + + //Initialize the mouse interaction + this._mouseInit(); + + }, + + _destroy: function() { + + this._mouseDestroy(); + + var _destroy = function(exp) { + $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing") + .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find('.ui-resizable-handle').remove(); + }; + + //TODO: Unwrap at same DOM position + if (this.elementIsWrapper) { + _destroy(this.element); + var wrapper = this.element; + this.originalElement.css({ + position: wrapper.css('position'), + width: wrapper.outerWidth(), + height: wrapper.outerHeight(), + top: wrapper.css('top'), + left: wrapper.css('left') + }).insertAfter( wrapper ); + wrapper.remove(); + } + + this.originalElement.css('resize', this.originalResizeStyle); + _destroy(this.originalElement); + + return this; + }, + + _mouseCapture: function(event) { + var handle = false; + for (var i in this.handles) { + if ($(this.handles[i])[0] == event.target) { + handle = true; + } + } + + return !this.options.disabled && handle; + }, + + _mouseStart: function(event) { + + var o = this.options, iniPos = this.element.position(), el = this.element; + + this.resizing = true; + this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() }; + + // bugfix for http://dev.jquery.com/ticket/1749 + if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) { + el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left }); + } + + this._renderProxy(); + + var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top')); + + if (o.containment) { + curleft += $(o.containment).scrollLeft() || 0; + curtop += $(o.containment).scrollTop() || 0; + } + + //Store needed variables + this.offset = this.helper.offset(); + this.position = { left: curleft, top: curtop }; + this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; + this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() }; + this.originalPosition = { left: curleft, top: curtop }; + this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() }; + this.originalMousePosition = { left: event.pageX, top: event.pageY }; + + //Aspect Ratio + this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1); + + var cursor = $('.ui-resizable-' + this.axis).css('cursor'); + $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor); + + el.addClass("ui-resizable-resizing"); + this._propagate("start", event); + return true; + }, + + _mouseDrag: function(event) { + + //Increase performance, avoid regex + var el = this.helper, o = this.options, props = {}, + that = this, smp = this.originalMousePosition, a = this.axis; + + var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0; + var trigger = this._change[a]; + if (!trigger) return false; + + // Calculate the attrs that will be change + var data = trigger.apply(this, [event, dx, dy]); + + // Put this in the mouseDrag handler since the user can start pressing shift while resizing + this._updateVirtualBoundaries(event.shiftKey); + if (this._aspectRatio || event.shiftKey) + data = this._updateRatio(data, event); + + data = this._respectSize(data, event); + + // plugins callbacks need to be called first + this._propagate("resize", event); + + el.css({ + top: this.position.top + "px", left: this.position.left + "px", + width: this.size.width + "px", height: this.size.height + "px" + }); + + if (!this._helper && this._proportionallyResizeElements.length) + this._proportionallyResize(); + + this._updateCache(data); + + // calling the user callback at the end + this._trigger('resize', event, this.ui()); + + return false; + }, + + _mouseStop: function(event) { + + this.resizing = false; + var o = this.options, that = this; + + if(this._helper) { + var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), + soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : that.sizeDiff.height, + soffsetw = ista ? 0 : that.sizeDiff.width; + + var s = { width: (that.helper.width() - soffsetw), height: (that.helper.height() - soffseth) }, + left = (parseInt(that.element.css('left'), 10) + (that.position.left - that.originalPosition.left)) || null, + top = (parseInt(that.element.css('top'), 10) + (that.position.top - that.originalPosition.top)) || null; + + if (!o.animate) + this.element.css($.extend(s, { top: top, left: left })); + + that.helper.height(that.size.height); + that.helper.width(that.size.width); + + if (this._helper && !o.animate) this._proportionallyResize(); + } + + $('body').css('cursor', 'auto'); + + this.element.removeClass("ui-resizable-resizing"); + + this._propagate("stop", event); + + if (this._helper) this.helper.remove(); + return false; + + }, + + _updateVirtualBoundaries: function(forceAspectRatio) { + var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b; + + b = { + minWidth: isNumber(o.minWidth) ? o.minWidth : 0, + maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity, + minHeight: isNumber(o.minHeight) ? o.minHeight : 0, + maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity + }; + + if(this._aspectRatio || forceAspectRatio) { + // We want to create an enclosing box whose aspect ration is the requested one + // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension + pMinWidth = b.minHeight * this.aspectRatio; + pMinHeight = b.minWidth / this.aspectRatio; + pMaxWidth = b.maxHeight * this.aspectRatio; + pMaxHeight = b.maxWidth / this.aspectRatio; + + if(pMinWidth > b.minWidth) b.minWidth = pMinWidth; + if(pMinHeight > b.minHeight) b.minHeight = pMinHeight; + if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth; + if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight; + } + this._vBoundaries = b; + }, + + _updateCache: function(data) { + var o = this.options; + this.offset = this.helper.offset(); + if (isNumber(data.left)) this.position.left = data.left; + if (isNumber(data.top)) this.position.top = data.top; + if (isNumber(data.height)) this.size.height = data.height; + if (isNumber(data.width)) this.size.width = data.width; + }, + + _updateRatio: function(data, event) { + + var o = this.options, cpos = this.position, csize = this.size, a = this.axis; + + if (isNumber(data.height)) data.width = (data.height * this.aspectRatio); + else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio); + + if (a == 'sw') { + data.left = cpos.left + (csize.width - data.width); + data.top = null; + } + if (a == 'nw') { + data.top = cpos.top + (csize.height - data.height); + data.left = cpos.left + (csize.width - data.width); + } + + return data; + }, + + _respectSize: function(data, event) { + + var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis, + ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height), + isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height); + + if (isminw) data.width = o.minWidth; + if (isminh) data.height = o.minHeight; + if (ismaxw) data.width = o.maxWidth; + if (ismaxh) data.height = o.maxHeight; + + var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height; + var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a); + + if (isminw && cw) data.left = dw - o.minWidth; + if (ismaxw && cw) data.left = dw - o.maxWidth; + if (isminh && ch) data.top = dh - o.minHeight; + if (ismaxh && ch) data.top = dh - o.maxHeight; + + // fixing jump error on top/left - bug #2330 + var isNotwh = !data.width && !data.height; + if (isNotwh && !data.left && data.top) data.top = null; + else if (isNotwh && !data.top && data.left) data.left = null; + + return data; + }, + + _proportionallyResize: function() { + + var o = this.options; + if (!this._proportionallyResizeElements.length) return; + var element = this.helper || this.element; + + for (var i=0; i < this._proportionallyResizeElements.length; i++) { + + var prel = this._proportionallyResizeElements[i]; + + if (!this.borderDif) { + var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')], + p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')]; + + this.borderDif = $.map(b, function(v, i) { + var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0; + return border + padding; + }); + } + + prel.css({ + height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0, + width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0 + }); + + }; + + }, + + _renderProxy: function() { + + var el = this.element, o = this.options; + this.elementOffset = el.offset(); + + if(this._helper) { + + this.helper = this.helper || $('<div style="overflow:hidden;"></div>'); + + // fix ie6 offset TODO: This seems broken + var ie6offset = ($.ui.ie6 ? 1 : 0), + pxyoffset = ( $.ui.ie6 ? 2 : -1 ); + + this.helper.addClass(this._helper).css({ + width: this.element.outerWidth() + pxyoffset, + height: this.element.outerHeight() + pxyoffset, + position: 'absolute', + left: this.elementOffset.left - ie6offset +'px', + top: this.elementOffset.top - ie6offset +'px', + zIndex: ++o.zIndex //TODO: Don't modify option + }); + + this.helper + .appendTo("body") + .disableSelection(); + + } else { + this.helper = this.element; + } + + }, + + _change: { + e: function(event, dx, dy) { + return { width: this.originalSize.width + dx }; + }, + w: function(event, dx, dy) { + var o = this.options, cs = this.originalSize, sp = this.originalPosition; + return { left: sp.left + dx, width: cs.width - dx }; + }, + n: function(event, dx, dy) { + var o = this.options, cs = this.originalSize, sp = this.originalPosition; + return { top: sp.top + dy, height: cs.height - dy }; + }, + s: function(event, dx, dy) { + return { height: this.originalSize.height + dy }; + }, + se: function(event, dx, dy) { + return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); + }, + sw: function(event, dx, dy) { + return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); + }, + ne: function(event, dx, dy) { + return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy])); + }, + nw: function(event, dx, dy) { + return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy])); + } + }, + + _propagate: function(n, event) { + $.ui.plugin.call(this, n, [event, this.ui()]); + (n != "resize" && this._trigger(n, event, this.ui())); + }, + + plugins: {}, + + ui: function() { + return { + originalElement: this.originalElement, + element: this.element, + helper: this.helper, + position: this.position, + size: this.size, + originalSize: this.originalSize, + originalPosition: this.originalPosition + }; + } + +}); + +/* + * Resizable Extensions + */ + +$.ui.plugin.add("resizable", "alsoResize", { + + start: function (event, ui) { + var that = $(this).data("resizable"), o = that.options; + + var _store = function (exp) { + $(exp).each(function() { + var el = $(this); + el.data("resizable-alsoresize", { + width: parseInt(el.width(), 10), height: parseInt(el.height(), 10), + left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10) + }); + }); + }; + + if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) { + if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); } + else { $.each(o.alsoResize, function (exp) { _store(exp); }); } + }else{ + _store(o.alsoResize); + } + }, + + resize: function (event, ui) { + var that = $(this).data("resizable"), o = that.options, os = that.originalSize, op = that.originalPosition; + + var delta = { + height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0, + top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0 + }, + + _alsoResize = function (exp, c) { + $(exp).each(function() { + var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, + css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left']; + + $.each(css, function (i, prop) { + var sum = (start[prop]||0) + (delta[prop]||0); + if (sum && sum >= 0) + style[prop] = sum || null; + }); + + el.css(style); + }); + }; + + if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) { + $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); }); + }else{ + _alsoResize(o.alsoResize); + } + }, + + stop: function (event, ui) { + $(this).removeData("resizable-alsoresize"); + } +}); + +$.ui.plugin.add("resizable", "animate", { + + stop: function(event, ui) { + var that = $(this).data("resizable"), o = that.options; + + var pr = that._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName), + soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : that.sizeDiff.height, + soffsetw = ista ? 0 : that.sizeDiff.width; + + var style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) }, + left = (parseInt(that.element.css('left'), 10) + (that.position.left - that.originalPosition.left)) || null, + top = (parseInt(that.element.css('top'), 10) + (that.position.top - that.originalPosition.top)) || null; + + that.element.animate( + $.extend(style, top && left ? { top: top, left: left } : {}), { + duration: o.animateDuration, + easing: o.animateEasing, + step: function() { + + var data = { + width: parseInt(that.element.css('width'), 10), + height: parseInt(that.element.css('height'), 10), + top: parseInt(that.element.css('top'), 10), + left: parseInt(that.element.css('left'), 10) + }; + + if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height }); + + // propagating resize, and updating values for each animation step + that._updateCache(data); + that._propagate("resize", event); + + } + } + ); + } + +}); + +$.ui.plugin.add("resizable", "containment", { + + start: function(event, ui) { + var that = $(this).data("resizable"), o = that.options, el = that.element; + var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc; + if (!ce) return; + + that.containerElement = $(ce); + + if (/document/.test(oc) || oc == document) { + that.containerOffset = { left: 0, top: 0 }; + that.containerPosition = { left: 0, top: 0 }; + + that.parentData = { + element: $(document), left: 0, top: 0, + width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight + }; + } + + // i'm a node, so compute top, left, right, bottom + else { + var element = $(ce), p = []; + $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); }); + + that.containerOffset = element.offset(); + that.containerPosition = element.position(); + that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) }; + + var co = that.containerOffset, ch = that.containerSize.height, cw = that.containerSize.width, + width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch); + + that.parentData = { + element: ce, left: co.left, top: co.top, width: width, height: height + }; + } + }, + + resize: function(event, ui) { + var that = $(this).data("resizable"), o = that.options, + ps = that.containerSize, co = that.containerOffset, cs = that.size, cp = that.position, + pRatio = that._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = that.containerElement; + + if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co; + + if (cp.left < (that._helper ? co.left : 0)) { + that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left)); + if (pRatio) that.size.height = that.size.width / that.aspectRatio; + that.position.left = o.helper ? co.left : 0; + } + + if (cp.top < (that._helper ? co.top : 0)) { + that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top); + if (pRatio) that.size.width = that.size.height * that.aspectRatio; + that.position.top = that._helper ? co.top : 0; + } + + that.offset.left = that.parentData.left+that.position.left; + that.offset.top = that.parentData.top+that.position.top; + + var woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width ), + hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height ); + + var isParent = that.containerElement.get(0) == that.element.parent().get(0), + isOffsetRelative = /relative|absolute/.test(that.containerElement.css('position')); + + if(isParent && isOffsetRelative) woset -= that.parentData.left; + + if (woset + that.size.width >= that.parentData.width) { + that.size.width = that.parentData.width - woset; + if (pRatio) that.size.height = that.size.width / that.aspectRatio; + } + + if (hoset + that.size.height >= that.parentData.height) { + that.size.height = that.parentData.height - hoset; + if (pRatio) that.size.width = that.size.height * that.aspectRatio; + } + }, + + stop: function(event, ui){ + var that = $(this).data("resizable"), o = that.options, cp = that.position, + co = that.containerOffset, cop = that.containerPosition, ce = that.containerElement; + + var helper = $(that.helper), ho = helper.offset(), w = helper.outerWidth() - that.sizeDiff.width, h = helper.outerHeight() - that.sizeDiff.height; + + if (that._helper && !o.animate && (/relative/).test(ce.css('position'))) + $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); + + if (that._helper && !o.animate && (/static/).test(ce.css('position'))) + $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h }); + + } +}); + +$.ui.plugin.add("resizable", "ghost", { + + start: function(event, ui) { + + var that = $(this).data("resizable"), o = that.options, cs = that.size; + + that.ghost = that.originalElement.clone(); + that.ghost + .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }) + .addClass('ui-resizable-ghost') + .addClass(typeof o.ghost == 'string' ? o.ghost : ''); + + that.ghost.appendTo(that.helper); + + }, + + resize: function(event, ui){ + var that = $(this).data("resizable"), o = that.options; + if (that.ghost) that.ghost.css({ position: 'relative', height: that.size.height, width: that.size.width }); + }, + + stop: function(event, ui){ + var that = $(this).data("resizable"), o = that.options; + if (that.ghost && that.helper) that.helper.get(0).removeChild(that.ghost.get(0)); + } + +}); + +$.ui.plugin.add("resizable", "grid", { + + resize: function(event, ui) { + var that = $(this).data("resizable"), o = that.options, cs = that.size, os = that.originalSize, op = that.originalPosition, a = that.axis, ratio = o._aspectRatio || event.shiftKey; + o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid; + var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1); + + if (/^(se|s|e)$/.test(a)) { + that.size.width = os.width + ox; + that.size.height = os.height + oy; + } + else if (/^(ne)$/.test(a)) { + that.size.width = os.width + ox; + that.size.height = os.height + oy; + that.position.top = op.top - oy; + } + else if (/^(sw)$/.test(a)) { + that.size.width = os.width + ox; + that.size.height = os.height + oy; + that.position.left = op.left - ox; + } + else { + that.size.width = os.width + ox; + that.size.height = os.height + oy; + that.position.top = op.top - oy; + that.position.left = op.left - ox; + } + } + +}); + +var num = function(v) { + return parseInt(v, 10) || 0; +}; + +var isNumber = function(value) { + return !isNaN(parseInt(value, 10)); +}; + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.selectable.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.selectable.js new file mode 100644 index 0000000..80e32ca --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.selectable.js @@ -0,0 +1,261 @@ +/*! + * jQuery UI Selectable @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/selectable/ + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +$.widget("ui.selectable", $.ui.mouse, { + version: "@VERSION", + options: { + appendTo: 'body', + autoRefresh: true, + distance: 0, + filter: '*', + tolerance: 'touch' + }, + _create: function() { + var that = this; + + this.element.addClass("ui-selectable"); + + this.dragged = false; + + // cache selectee children based on filter + var selectees; + this.refresh = function() { + selectees = $(that.options.filter, that.element[0]); + selectees.addClass("ui-selectee"); + selectees.each(function() { + var $this = $(this); + var pos = $this.offset(); + $.data(this, "selectable-item", { + element: this, + $element: $this, + left: pos.left, + top: pos.top, + right: pos.left + $this.outerWidth(), + bottom: pos.top + $this.outerHeight(), + startselected: false, + selected: $this.hasClass('ui-selected'), + selecting: $this.hasClass('ui-selecting'), + unselecting: $this.hasClass('ui-unselecting') + }); + }); + }; + this.refresh(); + + this.selectees = selectees.addClass("ui-selectee"); + + this._mouseInit(); + + this.helper = $("<div class='ui-selectable-helper'></div>"); + }, + + _destroy: function() { + this.selectees + .removeClass("ui-selectee") + .removeData("selectable-item"); + this.element + .removeClass("ui-selectable ui-selectable-disabled"); + this._mouseDestroy(); + }, + + _mouseStart: function(event) { + var that = this; + + this.opos = [event.pageX, event.pageY]; + + if (this.options.disabled) + return; + + var options = this.options; + + this.selectees = $(options.filter, this.element[0]); + + this._trigger("start", event); + + $(options.appendTo).append(this.helper); + // position helper (lasso) + this.helper.css({ + "left": event.clientX, + "top": event.clientY, + "width": 0, + "height": 0 + }); + + if (options.autoRefresh) { + this.refresh(); + } + + this.selectees.filter('.ui-selected').each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.startselected = true; + if (!event.metaKey && !event.ctrlKey) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + // selectable UNSELECTING callback + that._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + }); + + $(event.target).parents().andSelf().each(function() { + var selectee = $.data(this, "selectable-item"); + if (selectee) { + var doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass('ui-selected'); + selectee.$element + .removeClass(doSelect ? "ui-unselecting" : "ui-selected") + .addClass(doSelect ? "ui-selecting" : "ui-unselecting"); + selectee.unselecting = !doSelect; + selectee.selecting = doSelect; + selectee.selected = doSelect; + // selectable (UN)SELECTING callback + if (doSelect) { + that._trigger("selecting", event, { + selecting: selectee.element + }); + } else { + that._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + return false; + } + }); + + }, + + _mouseDrag: function(event) { + var that = this; + this.dragged = true; + + if (this.options.disabled) + return; + + var options = this.options; + + var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY; + if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; } + if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; } + this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1}); + + this.selectees.each(function() { + var selectee = $.data(this, "selectable-item"); + //prevent helper from being selected if appendTo: selectable + if (!selectee || selectee.element == that.element[0]) + return; + var hit = false; + if (options.tolerance == 'touch') { + hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) ); + } else if (options.tolerance == 'fit') { + hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2); + } + + if (hit) { + // SELECT + if (selectee.selected) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + } + if (selectee.unselecting) { + selectee.$element.removeClass('ui-unselecting'); + selectee.unselecting = false; + } + if (!selectee.selecting) { + selectee.$element.addClass('ui-selecting'); + selectee.selecting = true; + // selectable SELECTING callback + that._trigger("selecting", event, { + selecting: selectee.element + }); + } + } else { + // UNSELECT + if (selectee.selecting) { + if ((event.metaKey || event.ctrlKey) && selectee.startselected) { + selectee.$element.removeClass('ui-selecting'); + selectee.selecting = false; + selectee.$element.addClass('ui-selected'); + selectee.selected = true; + } else { + selectee.$element.removeClass('ui-selecting'); + selectee.selecting = false; + if (selectee.startselected) { + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + } + // selectable UNSELECTING callback + that._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + } + if (selectee.selected) { + if (!event.metaKey && !event.ctrlKey && !selectee.startselected) { + selectee.$element.removeClass('ui-selected'); + selectee.selected = false; + + selectee.$element.addClass('ui-unselecting'); + selectee.unselecting = true; + // selectable UNSELECTING callback + that._trigger("unselecting", event, { + unselecting: selectee.element + }); + } + } + } + }); + + return false; + }, + + _mouseStop: function(event) { + var that = this; + + this.dragged = false; + + var options = this.options; + + $('.ui-unselecting', this.element[0]).each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.$element.removeClass('ui-unselecting'); + selectee.unselecting = false; + selectee.startselected = false; + that._trigger("unselected", event, { + unselected: selectee.element + }); + }); + $('.ui-selecting', this.element[0]).each(function() { + var selectee = $.data(this, "selectable-item"); + selectee.$element.removeClass('ui-selecting').addClass('ui-selected'); + selectee.selecting = false; + selectee.selected = true; + selectee.startselected = true; + that._trigger("selected", event, { + selected: selectee.element + }); + }); + this._trigger("stop", event); + + this.helper.remove(); + + return false; + } + +}); + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.slider.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.slider.js new file mode 100644 index 0000000..18f7113 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.slider.js @@ -0,0 +1,644 @@ +/*! + * jQuery UI Slider @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/slider/ + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +// number of pages in a slider +// (how many times can you page up/down to go through the whole range) +var numPages = 5; + +$.widget( "ui.slider", $.ui.mouse, { + version: "@VERSION", + widgetEventPrefix: "slide", + + options: { + animate: false, + distance: 0, + max: 100, + min: 0, + orientation: "horizontal", + range: false, + step: 1, + value: 0, + values: null + }, + + _create: function() { + var i, handleCount, + o = this.options, + existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ), + handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>", + handles = []; + + this._keySliding = false; + this._mouseSliding = false; + this._animateOff = true; + this._handleIndex = null; + this._detectOrientation(); + this._mouseInit(); + + this.element + .addClass( "ui-slider" + + " ui-slider-" + this.orientation + + " ui-widget" + + " ui-widget-content" + + " ui-corner-all" + + ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) ); + + this.range = $([]); + + if ( o.range ) { + if ( o.range === true ) { + if ( !o.values ) { + o.values = [ this._valueMin(), this._valueMin() ]; + } + if ( o.values.length && o.values.length !== 2 ) { + o.values = [ o.values[0], o.values[0] ]; + } + } + + this.range = $( "<div></div>" ) + .appendTo( this.element ) + .addClass( "ui-slider-range" + + // note: this isn't the most fittingly semantic framework class for this element, + // but worked best visually with a variety of themes + " ui-widget-header" + + ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) ); + } + + handleCount = ( o.values && o.values.length ) || 1; + + for ( i = existingHandles.length; i < handleCount; i++ ) { + handles.push( handle ); + } + + this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) ); + + this.handle = this.handles.eq( 0 ); + + this.handles.add( this.range ).filter( "a" ) + .click(function( event ) { + event.preventDefault(); + }) + .mouseenter(function() { + if ( !o.disabled ) { + $( this ).addClass( "ui-state-hover" ); + } + }) + .mouseleave(function() { + $( this ).removeClass( "ui-state-hover" ); + }) + .focus(function() { + if ( !o.disabled ) { + $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" ); + $( this ).addClass( "ui-state-focus" ); + } else { + $( this ).blur(); + } + }) + .blur(function() { + $( this ).removeClass( "ui-state-focus" ); + }); + + this.handles.each(function( i ) { + $( this ).data( "ui-slider-handle-index", i ); + }); + + this._on( this.handles, { + keydown: function( event ) { + var allowed, curVal, newVal, step, + index = $( event.target ).data( "ui-slider-handle-index" ); + + switch ( event.keyCode ) { + case $.ui.keyCode.HOME: + case $.ui.keyCode.END: + case $.ui.keyCode.PAGE_UP: + case $.ui.keyCode.PAGE_DOWN: + case $.ui.keyCode.UP: + case $.ui.keyCode.RIGHT: + case $.ui.keyCode.DOWN: + case $.ui.keyCode.LEFT: + event.preventDefault(); + if ( !this._keySliding ) { + this._keySliding = true; + $( event.target ).addClass( "ui-state-active" ); + allowed = this._start( event, index ); + if ( allowed === false ) { + return; + } + } + break; + } + + step = this.options.step; + if ( this.options.values && this.options.values.length ) { + curVal = newVal = this.values( index ); + } else { + curVal = newVal = this.value(); + } + + switch ( event.keyCode ) { + case $.ui.keyCode.HOME: + newVal = this._valueMin(); + break; + case $.ui.keyCode.END: + newVal = this._valueMax(); + break; + case $.ui.keyCode.PAGE_UP: + newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) ); + break; + case $.ui.keyCode.PAGE_DOWN: + newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) ); + break; + case $.ui.keyCode.UP: + case $.ui.keyCode.RIGHT: + if ( curVal === this._valueMax() ) { + return; + } + newVal = this._trimAlignValue( curVal + step ); + break; + case $.ui.keyCode.DOWN: + case $.ui.keyCode.LEFT: + if ( curVal === this._valueMin() ) { + return; + } + newVal = this._trimAlignValue( curVal - step ); + break; + } + + this._slide( event, index, newVal ); + }, + keyup: function( event ) { + var index = $( event.target ).data( "ui-slider-handle-index" ); + + if ( this._keySliding ) { + this._keySliding = false; + this._stop( event, index ); + this._change( event, index ); + $( event.target ).removeClass( "ui-state-active" ); + } + } + }); + + this._refreshValue(); + + this._animateOff = false; + }, + + _destroy: function() { + this.handles.remove(); + this.range.remove(); + + this.element + .removeClass( "ui-slider" + + " ui-slider-horizontal" + + " ui-slider-vertical" + + " ui-slider-disabled" + + " ui-widget" + + " ui-widget-content" + + " ui-corner-all" ); + + this._mouseDestroy(); + }, + + _mouseCapture: function( event ) { + var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, + that = this, + o = this.options; + + if ( o.disabled ) { + return false; + } + + this.elementSize = { + width: this.element.outerWidth(), + height: this.element.outerHeight() + }; + this.elementOffset = this.element.offset(); + + position = { x: event.pageX, y: event.pageY }; + normValue = this._normValueFromMouse( position ); + distance = this._valueMax() - this._valueMin() + 1; + this.handles.each(function( i ) { + var thisDistance = Math.abs( normValue - that.values(i) ); + if ( distance > thisDistance ) { + distance = thisDistance; + closestHandle = $( this ); + index = i; + } + }); + + // workaround for bug #3736 (if both handles of a range are at 0, + // the first is always used as the one with least distance, + // and moving it is obviously prevented by preventing negative ranges) + if( o.range === true && this.values(1) === o.min ) { + index += 1; + closestHandle = $( this.handles[index] ); + } + + allowed = this._start( event, index ); + if ( allowed === false ) { + return false; + } + this._mouseSliding = true; + + this._handleIndex = index; + + closestHandle + .addClass( "ui-state-active" ) + .focus(); + + offset = closestHandle.offset(); + mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" ); + this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : { + left: event.pageX - offset.left - ( closestHandle.width() / 2 ), + top: event.pageY - offset.top - + ( closestHandle.height() / 2 ) - + ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) - + ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) + + ( parseInt( closestHandle.css("marginTop"), 10 ) || 0) + }; + + if ( !this.handles.hasClass( "ui-state-hover" ) ) { + this._slide( event, index, normValue ); + } + this._animateOff = true; + return true; + }, + + _mouseStart: function() { + return true; + }, + + _mouseDrag: function( event ) { + var position = { x: event.pageX, y: event.pageY }, + normValue = this._normValueFromMouse( position ); + + this._slide( event, this._handleIndex, normValue ); + + return false; + }, + + _mouseStop: function( event ) { + this.handles.removeClass( "ui-state-active" ); + this._mouseSliding = false; + + this._stop( event, this._handleIndex ); + this._change( event, this._handleIndex ); + + this._handleIndex = null; + this._clickOffset = null; + this._animateOff = false; + + return false; + }, + + _detectOrientation: function() { + this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal"; + }, + + _normValueFromMouse: function( position ) { + var pixelTotal, + pixelMouse, + percentMouse, + valueTotal, + valueMouse; + + if ( this.orientation === "horizontal" ) { + pixelTotal = this.elementSize.width; + pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 ); + } else { + pixelTotal = this.elementSize.height; + pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 ); + } + + percentMouse = ( pixelMouse / pixelTotal ); + if ( percentMouse > 1 ) { + percentMouse = 1; + } + if ( percentMouse < 0 ) { + percentMouse = 0; + } + if ( this.orientation === "vertical" ) { + percentMouse = 1 - percentMouse; + } + + valueTotal = this._valueMax() - this._valueMin(); + valueMouse = this._valueMin() + percentMouse * valueTotal; + + return this._trimAlignValue( valueMouse ); + }, + + _start: function( event, index ) { + var uiHash = { + handle: this.handles[ index ], + value: this.value() + }; + if ( this.options.values && this.options.values.length ) { + uiHash.value = this.values( index ); + uiHash.values = this.values(); + } + return this._trigger( "start", event, uiHash ); + }, + + _slide: function( event, index, newVal ) { + var otherVal, + newValues, + allowed; + + if ( this.options.values && this.options.values.length ) { + otherVal = this.values( index ? 0 : 1 ); + + if ( ( this.options.values.length === 2 && this.options.range === true ) && + ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) ) + ) { + newVal = otherVal; + } + + if ( newVal !== this.values( index ) ) { + newValues = this.values(); + newValues[ index ] = newVal; + // A slide can be canceled by returning false from the slide callback + allowed = this._trigger( "slide", event, { + handle: this.handles[ index ], + value: newVal, + values: newValues + } ); + otherVal = this.values( index ? 0 : 1 ); + if ( allowed !== false ) { + this.values( index, newVal, true ); + } + } + } else { + if ( newVal !== this.value() ) { + // A slide can be canceled by returning false from the slide callback + allowed = this._trigger( "slide", event, { + handle: this.handles[ index ], + value: newVal + } ); + if ( allowed !== false ) { + this.value( newVal ); + } + } + } + }, + + _stop: function( event, index ) { + var uiHash = { + handle: this.handles[ index ], + value: this.value() + }; + if ( this.options.values && this.options.values.length ) { + uiHash.value = this.values( index ); + uiHash.values = this.values(); + } + + this._trigger( "stop", event, uiHash ); + }, + + _change: function( event, index ) { + if ( !this._keySliding && !this._mouseSliding ) { + var uiHash = { + handle: this.handles[ index ], + value: this.value() + }; + if ( this.options.values && this.options.values.length ) { + uiHash.value = this.values( index ); + uiHash.values = this.values(); + } + + this._trigger( "change", event, uiHash ); + } + }, + + value: function( newValue ) { + if ( arguments.length ) { + this.options.value = this._trimAlignValue( newValue ); + this._refreshValue(); + this._change( null, 0 ); + return; + } + + return this._value(); + }, + + values: function( index, newValue ) { + var vals, + newValues, + i; + + if ( arguments.length > 1 ) { + this.options.values[ index ] = this._trimAlignValue( newValue ); + this._refreshValue(); + this._change( null, index ); + return; + } + + if ( arguments.length ) { + if ( $.isArray( arguments[ 0 ] ) ) { + vals = this.options.values; + newValues = arguments[ 0 ]; + for ( i = 0; i < vals.length; i += 1 ) { + vals[ i ] = this._trimAlignValue( newValues[ i ] ); + this._change( null, i ); + } + this._refreshValue(); + } else { + if ( this.options.values && this.options.values.length ) { + return this._values( index ); + } else { + return this.value(); + } + } + } else { + return this._values(); + } + }, + + _setOption: function( key, value ) { + var i, + valsLength = 0; + + if ( $.isArray( this.options.values ) ) { + valsLength = this.options.values.length; + } + + $.Widget.prototype._setOption.apply( this, arguments ); + + switch ( key ) { + case "disabled": + if ( value ) { + this.handles.filter( ".ui-state-focus" ).blur(); + this.handles.removeClass( "ui-state-hover" ); + this.handles.prop( "disabled", true ); + this.element.addClass( "ui-disabled" ); + } else { + this.handles.prop( "disabled", false ); + this.element.removeClass( "ui-disabled" ); + } + break; + case "orientation": + this._detectOrientation(); + this.element + .removeClass( "ui-slider-horizontal ui-slider-vertical" ) + .addClass( "ui-slider-" + this.orientation ); + this._refreshValue(); + break; + case "value": + this._animateOff = true; + this._refreshValue(); + this._change( null, 0 ); + this._animateOff = false; + break; + case "values": + this._animateOff = true; + this._refreshValue(); + for ( i = 0; i < valsLength; i += 1 ) { + this._change( null, i ); + } + this._animateOff = false; + break; + case "min": + case "max": + this._animateOff = true; + this._refreshValue(); + this._animateOff = false; + break; + } + }, + + //internal value getter + // _value() returns value trimmed by min and max, aligned by step + _value: function() { + var val = this.options.value; + val = this._trimAlignValue( val ); + + return val; + }, + + //internal values getter + // _values() returns array of values trimmed by min and max, aligned by step + // _values( index ) returns single value trimmed by min and max, aligned by step + _values: function( index ) { + var val, + vals, + i; + + if ( arguments.length ) { + val = this.options.values[ index ]; + val = this._trimAlignValue( val ); + + return val; + } else { + // .slice() creates a copy of the array + // this copy gets trimmed by min and max and then returned + vals = this.options.values.slice(); + for ( i = 0; i < vals.length; i+= 1) { + vals[ i ] = this._trimAlignValue( vals[ i ] ); + } + + return vals; + } + }, + + // returns the step-aligned value that val is closest to, between (inclusive) min and max + _trimAlignValue: function( val ) { + if ( val <= this._valueMin() ) { + return this._valueMin(); + } + if ( val >= this._valueMax() ) { + return this._valueMax(); + } + var step = ( this.options.step > 0 ) ? this.options.step : 1, + valModStep = (val - this._valueMin()) % step, + alignValue = val - valModStep; + + if ( Math.abs(valModStep) * 2 >= step ) { + alignValue += ( valModStep > 0 ) ? step : ( -step ); + } + + // Since JavaScript has problems with large floats, round + // the final value to 5 digits after the decimal point (see #4124) + return parseFloat( alignValue.toFixed(5) ); + }, + + _valueMin: function() { + return this.options.min; + }, + + _valueMax: function() { + return this.options.max; + }, + + _refreshValue: function() { + var lastValPercent, valPercent, value, valueMin, valueMax, + oRange = this.options.range, + o = this.options, + that = this, + animate = ( !this._animateOff ) ? o.animate : false, + _set = {}; + + if ( this.options.values && this.options.values.length ) { + this.handles.each(function( i ) { + valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100; + _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; + $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); + if ( that.options.range === true ) { + if ( that.orientation === "horizontal" ) { + if ( i === 0 ) { + that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate ); + } + if ( i === 1 ) { + that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + } else { + if ( i === 0 ) { + that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate ); + } + if ( i === 1 ) { + that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + } + } + lastValPercent = valPercent; + }); + } else { + value = this.value(); + valueMin = this._valueMin(); + valueMax = this._valueMax(); + valPercent = ( valueMax !== valueMin ) ? + ( value - valueMin ) / ( valueMax - valueMin ) * 100 : + 0; + _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%"; + this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate ); + + if ( oRange === "min" && this.orientation === "horizontal" ) { + this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate ); + } + if ( oRange === "max" && this.orientation === "horizontal" ) { + this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + if ( oRange === "min" && this.orientation === "vertical" ) { + this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate ); + } + if ( oRange === "max" && this.orientation === "vertical" ) { + this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } ); + } + } + } + +}); + +}(jQuery)); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.sortable.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.sortable.js new file mode 100644 index 0000000..a2132a9 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.sortable.js @@ -0,0 +1,1096 @@ +/*! + * jQuery UI Sortable @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/sortable/ + * + * Depends: + * jquery.ui.core.js + * jquery.ui.mouse.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +$.widget("ui.sortable", $.ui.mouse, { + version: "@VERSION", + widgetEventPrefix: "sort", + ready: false, + options: { + appendTo: "parent", + axis: false, + connectWith: false, + containment: false, + cursor: 'auto', + cursorAt: false, + dropOnEmpty: true, + forcePlaceholderSize: false, + forceHelperSize: false, + grid: false, + handle: false, + helper: "original", + items: '> *', + opacity: false, + placeholder: false, + revert: false, + scroll: true, + scrollSensitivity: 20, + scrollSpeed: 20, + scope: "default", + tolerance: "intersect", + zIndex: 1000 + }, + _create: function() { + + var o = this.options; + this.containerCache = {}; + this.element.addClass("ui-sortable"); + + //Get the items + this.refresh(); + + //Let's determine if the items are being displayed horizontally + this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false; + + //Let's determine the parent's offset + this.offset = this.element.offset(); + + //Initialize mouse events for interaction + this._mouseInit(); + + //We're ready to go + this.ready = true + + }, + + _destroy: function() { + this.element + .removeClass("ui-sortable ui-sortable-disabled"); + this._mouseDestroy(); + + for ( var i = this.items.length - 1; i >= 0; i-- ) + this.items[i].item.removeData(this.widgetName + "-item"); + + return this; + }, + + _setOption: function(key, value){ + if ( key === "disabled" ) { + this.options[ key ] = value; + + this.widget().toggleClass( "ui-sortable-disabled", !!value ); + } else { + // Don't call widget base _setOption for disable as it adds ui-state-disabled class + $.Widget.prototype._setOption.apply(this, arguments); + } + }, + + _mouseCapture: function(event, overrideHandle) { + var that = this; + + if (this.reverting) { + return false; + } + + if(this.options.disabled || this.options.type == 'static') return false; + + //We have to refresh the items data once first + this._refreshItems(event); + + //Find out if the clicked node (or one of its parents) is a actual item in this.items + var currentItem = null, nodes = $(event.target).parents().each(function() { + if($.data(this, that.widgetName + '-item') == that) { + currentItem = $(this); + return false; + } + }); + if($.data(event.target, that.widgetName + '-item') == that) currentItem = $(event.target); + + if(!currentItem) return false; + if(this.options.handle && !overrideHandle) { + var validHandle = false; + + $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; }); + if(!validHandle) return false; + } + + this.currentItem = currentItem; + this._removeCurrentsFromItems(); + return true; + + }, + + _mouseStart: function(event, overrideHandle, noActivation) { + + var o = this.options; + this.currentContainer = this; + + //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture + this.refreshPositions(); + + //Create and append the visible helper + this.helper = this._createHelper(event); + + //Cache the helper size + this._cacheHelperProportions(); + + /* + * - Position generation - + * This block generates everything position related - it's the core of draggables. + */ + + //Cache the margins of the original element + this._cacheMargins(); + + //Get the next scrolling parent + this.scrollParent = this.helper.scrollParent(); + + //The element's absolute position on the page minus margins + this.offset = this.currentItem.offset(); + this.offset = { + top: this.offset.top - this.margins.top, + left: this.offset.left - this.margins.left + }; + + $.extend(this.offset, { + click: { //Where the click happened, relative to the element + left: event.pageX - this.offset.left, + top: event.pageY - this.offset.top + }, + parent: this._getParentOffset(), + relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper + }); + + // Only after we got the offset, we can change the helper's position to absolute + // TODO: Still need to figure out a way to make relative sorting possible + this.helper.css("position", "absolute"); + this.cssPosition = this.helper.css("position"); + + //Generate the original position + this.originalPosition = this._generatePosition(event); + this.originalPageX = event.pageX; + this.originalPageY = event.pageY; + + //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied + (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt)); + + //Cache the former DOM position + this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] }; + + //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way + if(this.helper[0] != this.currentItem[0]) { + this.currentItem.hide(); + } + + //Create the placeholder + this._createPlaceholder(); + + //Set a containment if given in the options + if(o.containment) + this._setContainment(); + + if(o.cursor) { // cursor option + if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor"); + $('body').css("cursor", o.cursor); + } + + if(o.opacity) { // opacity option + if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity"); + this.helper.css("opacity", o.opacity); + } + + if(o.zIndex) { // zIndex option + if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex"); + this.helper.css("zIndex", o.zIndex); + } + + //Prepare scrolling + if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') + this.overflowOffset = this.scrollParent.offset(); + + //Call callbacks + this._trigger("start", event, this._uiHash()); + + //Recache the helper size + if(!this._preserveHelperProportions) + this._cacheHelperProportions(); + + + //Post 'activate' events to possible containers + if(!noActivation) { + for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, this._uiHash(this)); } + } + + //Prepare possible droppables + if($.ui.ddmanager) + $.ui.ddmanager.current = this; + + if ($.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + + this.dragging = true; + + this.helper.addClass("ui-sortable-helper"); + this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position + return true; + + }, + + _mouseDrag: function(event) { + + //Compute the helpers position + this.position = this._generatePosition(event); + this.positionAbs = this._convertPositionTo("absolute"); + + if (!this.lastPositionAbs) { + this.lastPositionAbs = this.positionAbs; + } + + //Do scrolling + if(this.options.scroll) { + var o = this.options, scrolled = false; + if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') { + + if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) + this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed; + else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) + this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed; + + if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) + this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed; + else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) + this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed; + + } else { + + if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed); + else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) + scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed); + + if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed); + else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) + scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed); + + } + + if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) + $.ui.ddmanager.prepareOffsets(this, event); + } + + //Regenerate the absolute position used for position checks + this.positionAbs = this._convertPositionTo("absolute"); + + //Set the helper position + if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px'; + if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px'; + + //Rearrange + for (var i = this.items.length - 1; i >= 0; i--) { + + //Cache variables and intersection, continue if no intersection + var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item); + if (!intersection) continue; + + // Only put the placeholder inside the current Container, skip all + // items form other containers. This works because when moving + // an item from one container to another the + // currentContainer is switched before the placeholder is moved. + // + // Without this moving items in "sub-sortables" can cause the placeholder to jitter + // beetween the outer and inner container. + if (item.instance !== this.currentContainer) continue; + + if (itemElement != this.currentItem[0] //cannot intersect with itself + && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before + && !$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked + && (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true) + //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container + ) { + + this.direction = intersection == 1 ? "down" : "up"; + + if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) { + this._rearrange(event, item); + } else { + break; + } + + this._trigger("change", event, this._uiHash()); + break; + } + } + + //Post events to containers + this._contactContainers(event); + + //Interconnect with droppables + if($.ui.ddmanager) $.ui.ddmanager.drag(this, event); + + //Call callbacks + this._trigger('sort', event, this._uiHash()); + + this.lastPositionAbs = this.positionAbs; + return false; + + }, + + _mouseStop: function(event, noPropagation) { + + if(!event) return; + + //If we are using droppables, inform the manager about the drop + if ($.ui.ddmanager && !this.options.dropBehaviour) + $.ui.ddmanager.drop(this, event); + + if(this.options.revert) { + var that = this; + var cur = this.placeholder.offset(); + + this.reverting = true; + + $(this.helper).animate({ + left: cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft), + top: cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop) + }, parseInt(this.options.revert, 10) || 500, function() { + that._clear(event); + }); + } else { + this._clear(event, noPropagation); + } + + return false; + + }, + + cancel: function() { + + if(this.dragging) { + + this._mouseUp({ target: null }); + + if(this.options.helper == "original") + this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); + else + this.currentItem.show(); + + //Post deactivating events to containers + for (var i = this.containers.length - 1; i >= 0; i--){ + this.containers[i]._trigger("deactivate", null, this._uiHash(this)); + if(this.containers[i].containerCache.over) { + this.containers[i]._trigger("out", null, this._uiHash(this)); + this.containers[i].containerCache.over = 0; + } + } + + } + + if (this.placeholder) { + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! + if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]); + if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove(); + + $.extend(this, { + helper: null, + dragging: false, + reverting: false, + _noFinalSort: null + }); + + if(this.domPosition.prev) { + $(this.domPosition.prev).after(this.currentItem); + } else { + $(this.domPosition.parent).prepend(this.currentItem); + } + } + + return this; + + }, + + serialize: function(o) { + + var items = this._getItemsAsjQuery(o && o.connected); + var str = []; o = o || {}; + + $(items).each(function() { + var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/)); + if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2])); + }); + + if(!str.length && o.key) { + str.push(o.key + '='); + } + + return str.join('&'); + + }, + + toArray: function(o) { + + var items = this._getItemsAsjQuery(o && o.connected); + var ret = []; o = o || {}; + + items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); }); + return ret; + + }, + + /* Be careful with the following core functions */ + _intersectsWith: function(item) { + + var x1 = this.positionAbs.left, + x2 = x1 + this.helperProportions.width, + y1 = this.positionAbs.top, + y2 = y1 + this.helperProportions.height; + + var l = item.left, + r = l + item.width, + t = item.top, + b = t + item.height; + + var dyClick = this.offset.click.top, + dxClick = this.offset.click.left; + + var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r; + + if( this.options.tolerance == "pointer" + || this.options.forcePointerForContainers + || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height']) + ) { + return isOverElement; + } else { + + return (l < x1 + (this.helperProportions.width / 2) // Right Half + && x2 - (this.helperProportions.width / 2) < r // Left Half + && t < y1 + (this.helperProportions.height / 2) // Bottom Half + && y2 - (this.helperProportions.height / 2) < b ); // Top Half + + } + }, + + _intersectsWithPointer: function(item) { + + var isOverElementHeight = (this.options.axis === 'x') || $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), + isOverElementWidth = (this.options.axis === 'y') || $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), + isOverElement = isOverElementHeight && isOverElementWidth, + verticalDirection = this._getDragVerticalDirection(), + horizontalDirection = this._getDragHorizontalDirection(); + + if (!isOverElement) + return false; + + return this.floating ? + ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 ) + : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) ); + + }, + + _intersectsWithSides: function(item) { + + var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height), + isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width), + verticalDirection = this._getDragVerticalDirection(), + horizontalDirection = this._getDragHorizontalDirection(); + + if (this.floating && horizontalDirection) { + return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf)); + } else { + return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf)); + } + + }, + + _getDragVerticalDirection: function() { + var delta = this.positionAbs.top - this.lastPositionAbs.top; + return delta != 0 && (delta > 0 ? "down" : "up"); + }, + + _getDragHorizontalDirection: function() { + var delta = this.positionAbs.left - this.lastPositionAbs.left; + return delta != 0 && (delta > 0 ? "right" : "left"); + }, + + refresh: function(event) { + this._refreshItems(event); + this.refreshPositions(); + return this; + }, + + _connectWith: function() { + var options = this.options; + return options.connectWith.constructor == String + ? [options.connectWith] + : options.connectWith; + }, + + _getItemsAsjQuery: function(connected) { + + var items = []; + var queries = []; + var connectWith = this._connectWith(); + + if(connectWith && connected) { + for (var i = connectWith.length - 1; i >= 0; i--){ + var cur = $(connectWith[i]); + for (var j = cur.length - 1; j >= 0; j--){ + var inst = $.data(cur[j], this.widgetName); + if(inst && inst != this && !inst.options.disabled) { + queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]); + } + }; + }; + } + + queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]); + + for (var i = queries.length - 1; i >= 0; i--){ + queries[i][0].each(function() { + items.push(this); + }); + }; + + return $(items); + + }, + + _removeCurrentsFromItems: function() { + + var list = this.currentItem.find(":data(" + this.widgetName + "-item)"); + + this.items = $.grep(this.items, function (item) { + for (var j=0; j < list.length; j++) { + if(list[j] == item.item[0]) + return false; + }; + return true; + }); + + }, + + _refreshItems: function(event) { + + this.items = []; + this.containers = [this]; + var items = this.items; + var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]]; + var connectWith = this._connectWith(); + + if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down + for (var i = connectWith.length - 1; i >= 0; i--){ + var cur = $(connectWith[i]); + for (var j = cur.length - 1; j >= 0; j--){ + var inst = $.data(cur[j], this.widgetName); + if(inst && inst != this && !inst.options.disabled) { + queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]); + this.containers.push(inst); + } + }; + }; + } + + for (var i = queries.length - 1; i >= 0; i--) { + var targetData = queries[i][1]; + var _queries = queries[i][0]; + + for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) { + var item = $(_queries[j]); + + item.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager) + + items.push({ + item: item, + instance: targetData, + width: 0, height: 0, + left: 0, top: 0 + }); + }; + }; + + }, + + refreshPositions: function(fast) { + + //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change + if(this.offsetParent && this.helper) { + this.offset.parent = this._getParentOffset(); + } + + for (var i = this.items.length - 1; i >= 0; i--){ + var item = this.items[i]; + + //We ignore calculating positions of all connected containers when we're not over them + if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0]) + continue; + + var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item; + + if (!fast) { + item.width = t.outerWidth(); + item.height = t.outerHeight(); + } + + var p = t.offset(); + item.left = p.left; + item.top = p.top; + }; + + if(this.options.custom && this.options.custom.refreshContainers) { + this.options.custom.refreshContainers.call(this); + } else { + for (var i = this.containers.length - 1; i >= 0; i--){ + var p = this.containers[i].element.offset(); + this.containers[i].containerCache.left = p.left; + this.containers[i].containerCache.top = p.top; + this.containers[i].containerCache.width = this.containers[i].element.outerWidth(); + this.containers[i].containerCache.height = this.containers[i].element.outerHeight(); + }; + } + + return this; + }, + + _createPlaceholder: function(that) { + that = that || this; + var o = that.options; + + if(!o.placeholder || o.placeholder.constructor == String) { + var className = o.placeholder; + o.placeholder = { + element: function() { + + var el = $(document.createElement(that.currentItem[0].nodeName)) + .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder") + .removeClass("ui-sortable-helper")[0]; + + if(!className) + el.style.visibility = "hidden"; + + return el; + }, + update: function(container, p) { + + // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that + // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified + if(className && !o.forcePlaceholderSize) return; + + //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item + if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css('paddingTop')||0, 10) - parseInt(that.currentItem.css('paddingBottom')||0, 10)); }; + if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css('paddingLeft')||0, 10) - parseInt(that.currentItem.css('paddingRight')||0, 10)); }; + } + }; + } + + //Create the placeholder + that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem)); + + //Append it after the actual current item + that.currentItem.after(that.placeholder); + + //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317) + o.placeholder.update(that, that.placeholder); + + }, + + _contactContainers: function(event) { + + // get innermost container that intersects with item + var innermostContainer = null, innermostIndex = null; + + + for (var i = this.containers.length - 1; i >= 0; i--){ + + // never consider a container that's located within the item itself + if($.contains(this.currentItem[0], this.containers[i].element[0])) + continue; + + if(this._intersectsWith(this.containers[i].containerCache)) { + + // if we've already found a container and it's more "inner" than this, then continue + if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) + continue; + + innermostContainer = this.containers[i]; + innermostIndex = i; + + } else { + // container doesn't intersect. trigger "out" event if necessary + if(this.containers[i].containerCache.over) { + this.containers[i]._trigger("out", event, this._uiHash(this)); + this.containers[i].containerCache.over = 0; + } + } + + } + + // if no intersecting containers found, return + if(!innermostContainer) return; + + // move the item into the container if it's not there already + if(this.containers.length === 1) { + this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); + this.containers[innermostIndex].containerCache.over = 1; + } else { + + //When entering a new container, we will find the item with the least distance and append our item near it + var dist = 10000; var itemWithLeastDistance = null; + var posProperty = this.containers[innermostIndex].floating ? 'left' : 'top'; + var sizeProperty = this.containers[innermostIndex].floating ? 'width' : 'height'; + var base = this.positionAbs[posProperty] + this.offset.click[posProperty]; + for (var j = this.items.length - 1; j >= 0; j--) { + if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; + if(this.items[j].item[0] == this.currentItem[0]) continue; + var cur = this.items[j].item.offset()[posProperty]; + var nearBottom = false; + if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){ + nearBottom = true; + cur += this.items[j][sizeProperty]; + } + + if(Math.abs(cur - base) < dist) { + dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; + this.direction = nearBottom ? "up": "down"; + } + } + + if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled + return; + + this.currentContainer = this.containers[innermostIndex]; + itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); + this._trigger("change", event, this._uiHash()); + this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); + + //Update the placeholder + this.options.placeholder.update(this.currentContainer, this.placeholder); + + this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); + this.containers[innermostIndex].containerCache.over = 1; + } + + + }, + + _createHelper: function(event) { + + var o = this.options; + var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem); + + if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already + $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]); + + if(helper[0] == this.currentItem[0]) + this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") }; + + if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width()); + if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height()); + + return helper; + + }, + + _adjustOffsetFromHelper: function(obj) { + if (typeof obj == 'string') { + obj = obj.split(' '); + } + if ($.isArray(obj)) { + obj = {left: +obj[0], top: +obj[1] || 0}; + } + if ('left' in obj) { + this.offset.click.left = obj.left + this.margins.left; + } + if ('right' in obj) { + this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left; + } + if ('top' in obj) { + this.offset.click.top = obj.top + this.margins.top; + } + if ('bottom' in obj) { + this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top; + } + }, + + _getParentOffset: function() { + + + //Get the offsetParent and cache its position + this.offsetParent = this.helper.offsetParent(); + var po = this.offsetParent.offset(); + + // This is a special case where we need to modify a offset calculated on start, since the following happened: + // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent + // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that + // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag + if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) { + po.left += this.scrollParent.scrollLeft(); + po.top += this.scrollParent.scrollTop(); + } + + if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information + || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.ui.ie)) //Ugly IE fix + po = { top: 0, left: 0 }; + + return { + top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0), + left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0) + }; + + }, + + _getRelativeOffset: function() { + + if(this.cssPosition == "relative") { + var p = this.currentItem.position(); + return { + top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(), + left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft() + }; + } else { + return { top: 0, left: 0 }; + } + + }, + + _cacheMargins: function() { + this.margins = { + left: (parseInt(this.currentItem.css("marginLeft"),10) || 0), + top: (parseInt(this.currentItem.css("marginTop"),10) || 0) + }; + }, + + _cacheHelperProportions: function() { + this.helperProportions = { + width: this.helper.outerWidth(), + height: this.helper.outerHeight() + }; + }, + + _setContainment: function() { + + var o = this.options; + if(o.containment == 'parent') o.containment = this.helper[0].parentNode; + if(o.containment == 'document' || o.containment == 'window') this.containment = [ + 0 - this.offset.relative.left - this.offset.parent.left, + 0 - this.offset.relative.top - this.offset.parent.top, + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left, + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top + ]; + + if(!(/^(document|window|parent)$/).test(o.containment)) { + var ce = $(o.containment)[0]; + var co = $(o.containment).offset(); + var over = ($(ce).css("overflow") != 'hidden'); + + this.containment = [ + co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left, + co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top, + co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left, + co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top + ]; + } + + }, + + _convertPositionTo: function(d, pos) { + + if(!pos) pos = this.position; + var mod = d == "absolute" ? 1 : -1; + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + return { + top: ( + pos.top // The absolute mouse position + + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border) + - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod) + ), + left: ( + pos.left // The absolute mouse position + + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent + + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border) + - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod) + ) + }; + + }, + + _generatePosition: function(event) { + + var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName); + + // This is another very weird special case that only happens for relative elements: + // 1. If the css position is relative + // 2. and the scroll parent is the document or similar to the offset parent + // we have to refresh the relative offset during the scroll so there are no jumps + if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) { + this.offset.relative = this._getRelativeOffset(); + } + + var pageX = event.pageX; + var pageY = event.pageY; + + /* + * - Position constraining - + * Constrain the position to a mix of grid, containment. + */ + + if(this.originalPosition) { //If we are not dragging yet, we won't check for options + + if(this.containment) { + if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left; + if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top; + if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left; + if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top; + } + + if(o.grid) { + var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1]; + pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top; + + var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0]; + pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left; + } + + } + + return { + top: ( + pageY // The absolute mouse position + - this.offset.click.top // Click offset (relative to the element) + - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.top // The offsetParent's offset without borders (offset + border) + + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) )) + ), + left: ( + pageX // The absolute mouse position + - this.offset.click.left // Click offset (relative to the element) + - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent + - this.offset.parent.left // The offsetParent's offset without borders (offset + border) + + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() )) + ) + }; + + }, + + _rearrange: function(event, i, a, hardRefresh) { + + a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling)); + + //Various things done here to improve the performance: + // 1. we create a setTimeout, that calls refreshPositions + // 2. on the instance, we have a counter variable, that get's higher after every append + // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same + // 4. this lets only the last addition to the timeout stack through + this.counter = this.counter ? ++this.counter : 1; + var counter = this.counter; + + this._delay(function() { + if(counter == this.counter) this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove + }); + + }, + + _clear: function(event, noPropagation) { + + this.reverting = false; + // We delay all events that have to be triggered to after the point where the placeholder has been removed and + // everything else normalized again + var delayedTriggers = []; + + // We first have to update the dom position of the actual currentItem + // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088) + if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem); + this._noFinalSort = null; + + if(this.helper[0] == this.currentItem[0]) { + for(var i in this._storedCSS) { + if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = ''; + } + this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"); + } else { + this.currentItem.show(); + } + + if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); }); + if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed + + // Check if the items Container has Changed and trigger appropriate + // events. + if (this !== this.currentContainer) { + if(!noPropagation) { + delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); }); + delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); + delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer)); + } + } + + + //Post events to containers + for (var i = this.containers.length - 1; i >= 0; i--){ + if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + if(this.containers[i].containerCache.over) { + delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i])); + this.containers[i].containerCache.over = 0; + } + } + + //Do what was originally in plugins + if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor + if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity + if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index + + this.dragging = false; + if(this.cancelHelperRemoval) { + if(!noPropagation) { + this._trigger("beforeStop", event, this._uiHash()); + for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events + this._trigger("stop", event, this._uiHash()); + } + + this.fromOutside = false; + return false; + } + + if(!noPropagation) this._trigger("beforeStop", event, this._uiHash()); + + //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node! + this.placeholder[0].parentNode.removeChild(this.placeholder[0]); + + if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null; + + if(!noPropagation) { + for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events + this._trigger("stop", event, this._uiHash()); + } + + this.fromOutside = false; + return true; + + }, + + _trigger: function() { + if ($.Widget.prototype._trigger.apply(this, arguments) === false) { + this.cancel(); + } + }, + + _uiHash: function(_inst) { + var inst = _inst || this; + return { + helper: inst.helper, + placeholder: inst.placeholder || $([]), + position: inst.position, + originalPosition: inst.originalPosition, + offset: inst.positionAbs, + item: inst.currentItem, + sender: _inst ? _inst.element : null + }; + } + +}); + +})(jQuery); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.spinner.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.spinner.js new file mode 100644 index 0000000..406eefb --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.spinner.js @@ -0,0 +1,478 @@ +/*! + * jQuery UI Spinner @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/spinner/ + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.button.js + */ +(function( $ ) { + +function modifier( fn ) { + return function() { + var previous = this.element.val(); + fn.apply( this, arguments ); + this._refresh(); + if ( previous !== this.element.val() ) { + this._trigger( "change" ); + } + }; +} + +$.widget( "ui.spinner", { + version: "@VERSION", + defaultElement: "<input>", + widgetEventPrefix: "spin", + options: { + culture: null, + icons: { + down: "ui-icon-triangle-1-s", + up: "ui-icon-triangle-1-n" + }, + incremental: true, + max: null, + min: null, + numberFormat: null, + page: 10, + step: 1, + + change: null, + spin: null, + start: null, + stop: null + }, + + _create: function() { + // handle string values that need to be parsed + this._setOption( "max", this.options.max ); + this._setOption( "min", this.options.min ); + this._setOption( "step", this.options.step ); + + // format the value, but don't constrain + this._value( this.element.val(), true ); + + this._draw(); + this._on( this._events ); + this._refresh(); + + // turning off autocomplete prevents the browser from remembering the + // value when navigating through history, so we re-enable autocomplete + // if the page is unloaded before the widget is destroyed. #7790 + this._on( this.window, { + beforeunload: function() { + this.element.removeAttr( "autocomplete" ); + } + }); + }, + + _getCreateOptions: function() { + var options = {}, + element = this.element; + + $.each( [ "min", "max", "step" ], function( i, option ) { + var value = element.attr( option ); + if ( value !== undefined && value.length ) { + options[ option ] = value; + } + }); + + return options; + }, + + _events: { + keydown: function( event ) { + if ( this._start( event ) && this._keydown( event ) ) { + event.preventDefault(); + } + }, + keyup: "_stop", + focus: function() { + this.previous = this.element.val(); + }, + blur: function( event ) { + if ( this.cancelBlur ) { + delete this.cancelBlur; + return; + } + + this._refresh(); + if ( this.previous !== this.element.val() ) { + this._trigger( "change", event ); + } + }, + mousewheel: function( event, delta ) { + if ( !delta ) { + return; + } + if ( !this.spinning && !this._start( event ) ) { + return false; + } + + this._spin( (delta > 0 ? 1 : -1) * this.options.step, event ); + clearTimeout( this.mousewheelTimer ); + this.mousewheelTimer = this._delay(function() { + if ( this.spinning ) { + this._stop( event ); + } + }, 100 ); + event.preventDefault(); + }, + "mousedown .ui-spinner-button": function( event ) { + var previous; + + // We never want the buttons to have focus; whenever the user is + // interacting with the spinner, the focus should be on the input. + // If the input is focused then this.previous is properly set from + // when the input first received focus. If the input is not focused + // then we need to set this.previous based on the value before spinning. + previous = this.element[0] === this.document[0].activeElement ? + this.previous : this.element.val(); + function checkFocus() { + var isActive = this.element[0] === this.document[0].activeElement; + if ( !isActive ) { + this.element.focus(); + this.previous = previous; + // support: IE + // IE sets focus asynchronously, so we need to check if focus + // moved off of the input because the user clicked on the button. + this._delay(function() { + this.previous = previous; + }); + } + } + + // ensure focus is on (or stays on) the text field + event.preventDefault(); + checkFocus.call( this ); + + // support: IE + // IE doesn't prevent moving focus even with event.preventDefault() + // so we set a flag to know when we should ignore the blur event + // and check (again) if focus moved off of the input. + this.cancelBlur = true; + this._delay(function() { + delete this.cancelBlur; + checkFocus.call( this ); + }); + + if ( this._start( event ) === false ) { + return; + } + + this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); + }, + "mouseup .ui-spinner-button": "_stop", + "mouseenter .ui-spinner-button": function( event ) { + // button will add ui-state-active if mouse was down while mouseleave and kept down + if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) { + return; + } + + if ( this._start( event ) === false ) { + return false; + } + this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event ); + }, + // TODO: do we really want to consider this a stop? + // shouldn't we just stop the repeater and wait until mouseup before + // we trigger the stop event? + "mouseleave .ui-spinner-button": "_stop" + }, + + _draw: function() { + var uiSpinner = this.uiSpinner = this.element + .addClass( "ui-spinner-input" ) + .attr( "autocomplete", "off" ) + .wrap( this._uiSpinnerHtml() ) + .parent() + // add buttons + .append( this._buttonHtml() ); + + this.element.attr( "role", "spinbutton" ); + + // button bindings + this.buttons = uiSpinner.find( ".ui-spinner-button" ) + .attr( "tabIndex", -1 ) + .button() + .removeClass( "ui-corner-all" ); + + // IE 6 doesn't understand height: 50% for the buttons + // unless the wrapper has an explicit height + if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) && + uiSpinner.height() > 0 ) { + uiSpinner.height( uiSpinner.height() ); + } + + // disable spinner if element was already disabled + if ( this.options.disabled ) { + this.disable(); + } + }, + + _keydown: function( event ) { + var options = this.options, + keyCode = $.ui.keyCode; + + switch ( event.keyCode ) { + case keyCode.UP: + this._repeat( null, 1, event ); + return true; + case keyCode.DOWN: + this._repeat( null, -1, event ); + return true; + case keyCode.PAGE_UP: + this._repeat( null, options.page, event ); + return true; + case keyCode.PAGE_DOWN: + this._repeat( null, -options.page, event ); + return true; + } + + return false; + }, + + _uiSpinnerHtml: function() { + return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"; + }, + + _buttonHtml: function() { + return "" + + "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" + + "<span class='ui-icon " + this.options.icons.up + "'>▲</span>" + + "</a>" + + "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" + + "<span class='ui-icon " + this.options.icons.down + "'>▼</span>" + + "</a>"; + }, + + _start: function( event ) { + if ( !this.spinning && this._trigger( "start", event ) === false ) { + return false; + } + + if ( !this.counter ) { + this.counter = 1; + } + this.spinning = true; + return true; + }, + + _repeat: function( i, steps, event ) { + i = i || 500; + + clearTimeout( this.timer ); + this.timer = this._delay(function() { + this._repeat( 40, steps, event ); + }, i ); + + this._spin( steps * this.options.step, event ); + }, + + _spin: function( step, event ) { + var value = this.value() || 0; + + if ( !this.counter ) { + this.counter = 1; + } + + value = this._adjustValue( value + step * this._increment( this.counter ) ); + + if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) { + this._value( value ); + this.counter++; + } + }, + + _increment: function( i ) { + var incremental = this.options.incremental; + + if ( incremental ) { + return $.isFunction( incremental ) ? + incremental( i ) : + Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 ); + } + + return 1; + }, + + _precision: function() { + var precision = this._precisionOf( this.options.step ); + if ( this.options.min !== null ) { + precision = Math.max( precision, this._precisionOf( this.options.min ) ); + } + return precision; + }, + + _precisionOf: function( num ) { + var str = num.toString(), + decimal = str.indexOf( "." ); + return decimal === -1 ? 0 : str.length - decimal - 1; + }, + + _adjustValue: function( value ) { + var base, aboveMin, + options = this.options; + + // make sure we're at a valid step + // - find out where we are relative to the base (min or 0) + base = options.min !== null ? options.min : 0; + aboveMin = value - base; + // - round to the nearest step + aboveMin = Math.round(aboveMin / options.step) * options.step; + // - rounding is based on 0, so adjust back to our base + value = base + aboveMin; + + // fix precision from bad JS floating point math + value = parseFloat( value.toFixed( this._precision() ) ); + + // clamp the value + if ( options.max !== null && value > options.max) { + return options.max; + } + if ( options.min !== null && value < options.min ) { + return options.min; + } + + return value; + }, + + _stop: function( event ) { + if ( !this.spinning ) { + return; + } + + clearTimeout( this.timer ); + clearTimeout( this.mousewheelTimer ); + this.counter = 0; + this.spinning = false; + this._trigger( "stop", event ); + }, + + _setOption: function( key, value ) { + if ( key === "culture" || key === "numberFormat" ) { + var prevValue = this._parse( this.element.val() ); + this.options[ key ] = value; + this.element.val( this._format( prevValue ) ); + return; + } + + if ( key === "max" || key === "min" || key === "step" ) { + if ( typeof value === "string" ) { + value = this._parse( value ); + } + } + + this._super( key, value ); + + if ( key === "disabled" ) { + if ( value ) { + this.element.prop( "disabled", true ); + this.buttons.button( "disable" ); + } else { + this.element.prop( "disabled", false ); + this.buttons.button( "enable" ); + } + } + }, + + _setOptions: modifier(function( options ) { + this._super( options ); + this._value( this.element.val() ); + }), + + _parse: function( val ) { + if ( typeof val === "string" && val !== "" ) { + val = window.Globalize && this.options.numberFormat ? + Globalize.parseFloat( val, 10, this.options.culture ) : +val; + } + return val === "" || isNaN( val ) ? null : val; + }, + + _format: function( value ) { + if ( value === "" ) { + return ""; + } + return window.Globalize && this.options.numberFormat ? + Globalize.format( value, this.options.numberFormat, this.options.culture ) : + value; + }, + + _refresh: function() { + this.element.attr({ + "aria-valuemin": this.options.min, + "aria-valuemax": this.options.max, + // TODO: what should we do with values that can't be parsed? + "aria-valuenow": this._parse( this.element.val() ) + }); + }, + + // update the value without triggering change + _value: function( value, allowAny ) { + var parsed; + if ( value !== "" ) { + parsed = this._parse( value ); + if ( parsed !== null ) { + if ( !allowAny ) { + parsed = this._adjustValue( parsed ); + } + value = this._format( parsed ); + } + } + this.element.val( value ); + this._refresh(); + }, + + _destroy: function() { + this.element + .removeClass( "ui-spinner-input" ) + .prop( "disabled", false ) + .removeAttr( "autocomplete" ) + .removeAttr( "role" ) + .removeAttr( "aria-valuemin" ) + .removeAttr( "aria-valuemax" ) + .removeAttr( "aria-valuenow" ); + this.uiSpinner.replaceWith( this.element ); + }, + + stepUp: modifier(function( steps ) { + this._stepUp( steps ); + }), + _stepUp: function( steps ) { + this._spin( (steps || 1) * this.options.step ); + }, + + stepDown: modifier(function( steps ) { + this._stepDown( steps ); + }), + _stepDown: function( steps ) { + this._spin( (steps || 1) * -this.options.step ); + }, + + pageUp: modifier(function( pages ) { + this._stepUp( (pages || 1) * this.options.page ); + }), + + pageDown: modifier(function( pages ) { + this._stepDown( (pages || 1) * this.options.page ); + }), + + value: function( newVal ) { + if ( !arguments.length ) { + return this._parse( this.element.val() ); + } + modifier( this._value ).call( this, newVal ); + }, + + widget: function() { + return this.uiSpinner; + } +}); + +}( jQuery ) ); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.tabs.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.tabs.js new file mode 100644 index 0000000..8e09764 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.tabs.js @@ -0,0 +1,1366 @@ +/*! + * jQuery UI Tabs @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/tabs/ + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +var tabId = 0, + rhash = /#.*$/; + +function getNextTabId() { + return ++tabId; +} + +function isLocal( anchor ) { + return anchor.hash.length > 1 && + anchor.href.replace( rhash, "" ) === + location.href.replace( rhash, "" ) + // support: Safari 5.1 + // Safari 5.1 doesn't encode spaces in window.location + // but it does encode spaces from anchors (#8777) + .replace( /\s/g, "%20" ); +} + +$.widget( "ui.tabs", { + version: "@VERSION", + delay: 300, + options: { + active: null, + collapsible: false, + event: "click", + heightStyle: "content", + hide: null, + show: null, + + // callbacks + activate: null, + beforeActivate: null, + beforeLoad: null, + load: null + }, + + _create: function() { + var that = this, + options = this.options, + active = options.active, + locationHash = location.hash.substring( 1 ); + + this.running = false; + + this.element + .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" ) + .toggleClass( "ui-tabs-collapsible", options.collapsible ) + // Prevent users from focusing disabled tabs via click + .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) { + if ( $( this ).is( ".ui-state-disabled" ) ) { + event.preventDefault(); + } + }) + // support: IE <9 + // Preventing the default action in mousedown doesn't prevent IE + // from focusing the element, so if the anchor gets focused, blur. + // We don't have to worry about focusing the previously focused + // element since clicking on a non-focusable element should focus + // the body anyway. + .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() { + if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) { + this.blur(); + } + }); + + this._processTabs(); + + if ( active === null ) { + // check the fragment identifier in the URL + if ( locationHash ) { + this.tabs.each(function( i, tab ) { + if ( $( tab ).attr( "aria-controls" ) === locationHash ) { + active = i; + return false; + } + }); + } + + // check for a tab marked active via a class + if ( active === null ) { + active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) ); + } + + // no active tab, set to false + if ( active === null || active === -1 ) { + active = this.tabs.length ? 0 : false; + } + } + + // handle numbers: negative, out of range + if ( active !== false ) { + active = this.tabs.index( this.tabs.eq( active ) ); + if ( active === -1 ) { + active = options.collapsible ? false : 0; + } + } + options.active = active; + + // don't allow collapsible: false and active: false + if ( !options.collapsible && options.active === false && this.anchors.length ) { + options.active = 0; + } + + // Take disabling tabs via class attribute from HTML + // into account and update option properly. + if ( $.isArray( options.disabled ) ) { + options.disabled = $.unique( options.disabled.concat( + $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) { + return that.tabs.index( li ); + }) + ) ).sort(); + } + + // check for length avoids error when initializing empty list + if ( this.options.active !== false && this.anchors.length ) { + this.active = this._findActive( this.options.active ); + } else { + this.active = $(); + } + + this._refresh(); + + if ( this.active.length ) { + this.load( options.active ); + } + }, + + _getCreateEventData: function() { + return { + tab: this.active, + panel: !this.active.length ? $() : this._getPanelForTab( this.active ) + }; + }, + + _tabKeydown: function( event ) { + var focusedTab = $( this.document[0].activeElement ).closest( "li" ), + selectedIndex = this.tabs.index( focusedTab ), + goingForward = true; + + if ( this._handlePageNav( event ) ) { + return; + } + + switch ( event.keyCode ) { + case $.ui.keyCode.RIGHT: + case $.ui.keyCode.DOWN: + selectedIndex++; + break; + case $.ui.keyCode.UP: + case $.ui.keyCode.LEFT: + goingForward = false; + selectedIndex--; + break; + case $.ui.keyCode.END: + selectedIndex = this.anchors.length - 1; + break; + case $.ui.keyCode.HOME: + selectedIndex = 0; + break; + case $.ui.keyCode.SPACE: + // Activate only, no collapsing + event.preventDefault(); + clearTimeout( this.activating ); + this._activate( selectedIndex ); + return; + case $.ui.keyCode.ENTER: + // Toggle (cancel delayed activation, allow collapsing) + event.preventDefault(); + clearTimeout( this.activating ); + // Determine if we should collapse or activate + this._activate( selectedIndex === this.options.active ? false : selectedIndex ); + return; + default: + return; + } + + // Focus the appropriate tab, based on which key was pressed + event.preventDefault(); + clearTimeout( this.activating ); + selectedIndex = this._focusNextTab( selectedIndex, goingForward ); + + // Navigating with control key will prevent automatic activation + if ( !event.ctrlKey ) { + // Update aria-selected immediately so that AT think the tab is already selected. + // Otherwise AT may confuse the user by stating that they need to activate the tab, + // but the tab will already be activated by the time the announcement finishes. + focusedTab.attr( "aria-selected", "false" ); + this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" ); + + this.activating = this._delay(function() { + this.option( "active", selectedIndex ); + }, this.delay ); + } + }, + + _panelKeydown: function( event ) { + if ( this._handlePageNav( event ) ) { + return; + } + + // Ctrl+up moves focus to the current tab + if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) { + event.preventDefault(); + this.active.focus(); + } + }, + + // Alt+page up/down moves focus to the previous/next tab (and activates) + _handlePageNav: function( event ) { + if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) { + this._activate( this._focusNextTab( this.options.active - 1, false ) ); + return true; + } + if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) { + this._activate( this._focusNextTab( this.options.active + 1, true ) ); + return true; + } + }, + + _findNextTab: function( index, goingForward ) { + var lastTabIndex = this.tabs.length - 1; + + function constrain() { + if ( index > lastTabIndex ) { + index = 0; + } + if ( index < 0 ) { + index = lastTabIndex; + } + return index; + } + + while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) { + index = goingForward ? index + 1 : index - 1; + } + + return index; + }, + + _focusNextTab: function( index, goingForward ) { + index = this._findNextTab( index, goingForward ); + this.tabs.eq( index ).focus(); + return index; + }, + + _setOption: function( key, value ) { + if ( key === "active" ) { + // _activate() will handle invalid values and update this.options + this._activate( value ); + return; + } + + if ( key === "disabled" ) { + // don't use the widget factory's disabled handling + this._setupDisabled( value ); + return; + } + + this._super( key, value); + + if ( key === "collapsible" ) { + this.element.toggleClass( "ui-tabs-collapsible", value ); + // Setting collapsible: false while collapsed; open first panel + if ( !value && this.options.active === false ) { + this._activate( 0 ); + } + } + + if ( key === "event" ) { + this._setupEvents( value ); + } + + if ( key === "heightStyle" ) { + this._setupHeightStyle( value ); + } + }, + + _tabId: function( tab ) { + return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId(); + }, + + _sanitizeSelector: function( hash ) { + return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : ""; + }, + + refresh: function() { + var options = this.options, + lis = this.tablist.children( ":has(a[href])" ); + + // get disabled tabs from class attribute from HTML + // this will get converted to a boolean if needed in _refresh() + options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) { + return lis.index( tab ); + }); + + this._processTabs(); + + // was collapsed or no tabs + if ( options.active === false || !this.anchors.length ) { + options.active = false; + this.active = $(); + // was active, but active tab is gone + } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) { + // all remaining tabs are disabled + if ( this.tabs.length === options.disabled.length ) { + options.active = false; + this.active = $(); + // activate previous tab + } else { + this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) ); + } + // was active, active tab still exists + } else { + // make sure active index is correct + options.active = this.tabs.index( this.active ); + } + + this._refresh(); + }, + + _refresh: function() { + this._setupDisabled( this.options.disabled ); + this._setupEvents( this.options.event ); + this._setupHeightStyle( this.options.heightStyle ); + + this.tabs.not( this.active ).attr({ + "aria-selected": "false", + tabIndex: -1 + }); + this.panels.not( this._getPanelForTab( this.active ) ) + .hide() + .attr({ + "aria-expanded": "false", + "aria-hidden": "true" + }); + + // Make sure one tab is in the tab order + if ( !this.active.length ) { + this.tabs.eq( 0 ).attr( "tabIndex", 0 ); + } else { + this.active + .addClass( "ui-tabs-active ui-state-active" ) + .attr({ + "aria-selected": "true", + tabIndex: 0 + }); + this._getPanelForTab( this.active ) + .show() + .attr({ + "aria-expanded": "true", + "aria-hidden": "false" + }); + } + }, + + _processTabs: function() { + var that = this; + + this.tablist = this._getList() + .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) + .attr( "role", "tablist" ); + + this.tabs = this.tablist.find( "> li:has(a[href])" ) + .addClass( "ui-state-default ui-corner-top" ) + .attr({ + role: "tab", + tabIndex: -1 + }); + + this.anchors = this.tabs.map(function() { + return $( "a", this )[ 0 ]; + }) + .addClass( "ui-tabs-anchor" ) + .attr({ + role: "presentation", + tabIndex: -1 + }); + + this.panels = $(); + + this.anchors.each(function( i, anchor ) { + var selector, panel, panelId, + anchorId = $( anchor ).uniqueId().attr( "id" ), + tab = $( anchor ).closest( "li" ), + originalAriaControls = tab.attr( "aria-controls" ); + + // inline tab + if ( isLocal( anchor ) ) { + selector = anchor.hash; + panel = that.element.find( that._sanitizeSelector( selector ) ); + // remote tab + } else { + panelId = that._tabId( tab ); + selector = "#" + panelId; + panel = that.element.find( selector ); + if ( !panel.length ) { + panel = that._createPanel( panelId ); + panel.insertAfter( that.panels[ i - 1 ] || that.tablist ); + } + panel.attr( "aria-live", "polite" ); + } + + if ( panel.length) { + that.panels = that.panels.add( panel ); + } + if ( originalAriaControls ) { + tab.data( "ui-tabs-aria-controls", originalAriaControls ); + } + tab.attr({ + "aria-controls": selector.substring( 1 ), + "aria-labelledby": anchorId + }); + panel.attr( "aria-labelledby", anchorId ); + }); + + this.panels + .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) + .attr( "role", "tabpanel" ); + }, + + // allow overriding how to find the list for rare usage scenarios (#7715) + _getList: function() { + return this.element.find( "ol,ul" ).eq( 0 ); + }, + + _createPanel: function( id ) { + return $( "<div>" ) + .attr( "id", id ) + .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) + .data( "ui-tabs-destroy", true ); + }, + + _setupDisabled: function( disabled ) { + if ( $.isArray( disabled ) ) { + if ( !disabled.length ) { + disabled = false; + } else if ( disabled.length === this.anchors.length ) { + disabled = true; + } + } + + // disable tabs + for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) { + if ( disabled === true || $.inArray( i, disabled ) !== -1 ) { + $( li ) + .addClass( "ui-state-disabled" ) + .attr( "aria-disabled", "true" ); + } else { + $( li ) + .removeClass( "ui-state-disabled" ) + .removeAttr( "aria-disabled" ); + } + } + + this.options.disabled = disabled; + }, + + _setupEvents: function( event ) { + var events = { + click: function( event ) { + event.preventDefault(); + } + }; + if ( event ) { + $.each( event.split(" "), function( index, eventName ) { + events[ eventName ] = "_eventHandler"; + }); + } + + this._off( this.anchors.add( this.tabs ).add( this.panels ) ); + this._on( this.anchors, events ); + this._on( this.tabs, { keydown: "_tabKeydown" } ); + this._on( this.panels, { keydown: "_panelKeydown" } ); + + this._focusable( this.tabs ); + this._hoverable( this.tabs ); + }, + + _setupHeightStyle: function( heightStyle ) { + var maxHeight, overflow, + parent = this.element.parent(); + + if ( heightStyle === "fill" ) { + // IE 6 treats height like minHeight, so we need to turn off overflow + // in order to get a reliable height + // we use the minHeight support test because we assume that only + // browsers that don't support minHeight will treat height as minHeight + if ( !$.support.minHeight ) { + overflow = parent.css( "overflow" ); + parent.css( "overflow", "hidden"); + } + maxHeight = parent.height(); + this.element.siblings( ":visible" ).each(function() { + var elem = $( this ), + position = elem.css( "position" ); + + if ( position === "absolute" || position === "fixed" ) { + return; + } + maxHeight -= elem.outerHeight( true ); + }); + if ( overflow ) { + parent.css( "overflow", overflow ); + } + + this.element.children().not( this.panels ).each(function() { + maxHeight -= $( this ).outerHeight( true ); + }); + + this.panels.each(function() { + $( this ).height( Math.max( 0, maxHeight - + $( this ).innerHeight() + $( this ).height() ) ); + }) + .css( "overflow", "auto" ); + } else if ( heightStyle === "auto" ) { + maxHeight = 0; + this.panels.each(function() { + maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() ); + }).height( maxHeight ); + } + }, + + _eventHandler: function( event ) { + var options = this.options, + active = this.active, + anchor = $( event.currentTarget ), + tab = anchor.closest( "li" ), + clickedIsActive = tab[ 0 ] === active[ 0 ], + collapsing = clickedIsActive && options.collapsible, + toShow = collapsing ? $() : this._getPanelForTab( tab ), + toHide = !active.length ? $() : this._getPanelForTab( active ), + eventData = { + oldTab: active, + oldPanel: toHide, + newTab: collapsing ? $() : tab, + newPanel: toShow + }; + + event.preventDefault(); + + if ( tab.hasClass( "ui-state-disabled" ) || + // tab is already loading + tab.hasClass( "ui-tabs-loading" ) || + // can't switch durning an animation + this.running || + // click on active header, but not collapsible + ( clickedIsActive && !options.collapsible ) || + // allow canceling activation + ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { + return; + } + + options.active = collapsing ? false : this.tabs.index( tab ); + + this.active = clickedIsActive ? $() : tab; + if ( this.xhr ) { + this.xhr.abort(); + } + + if ( !toHide.length && !toShow.length ) { + $.error( "jQuery UI Tabs: Mismatching fragment identifier." ); + } + + if ( toShow.length ) { + this.load( this.tabs.index( tab ), event ); + } + this._toggle( event, eventData ); + }, + + // handles show/hide for selecting tabs + _toggle: function( event, eventData ) { + var that = this, + toShow = eventData.newPanel, + toHide = eventData.oldPanel; + + this.running = true; + + function complete() { + that.running = false; + that._trigger( "activate", event, eventData ); + } + + function show() { + eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); + + if ( toShow.length && that.options.show ) { + that._show( toShow, that.options.show, complete ); + } else { + toShow.show(); + complete(); + } + } + + // start out by hiding, then showing, then completing + if ( toHide.length && this.options.hide ) { + this._hide( toHide, this.options.hide, function() { + eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + show(); + }); + } else { + eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + toHide.hide(); + show(); + } + + toHide.attr({ + "aria-expanded": "false", + "aria-hidden": "true" + }); + eventData.oldTab.attr( "aria-selected", "false" ); + // If we're switching tabs, remove the old tab from the tab order. + // If we're opening from collapsed state, remove the previous tab from the tab order. + // If we're collapsing, then keep the collapsing tab in the tab order. + if ( toShow.length && toHide.length ) { + eventData.oldTab.attr( "tabIndex", -1 ); + } else if ( toShow.length ) { + this.tabs.filter(function() { + return $( this ).attr( "tabIndex" ) === 0; + }) + .attr( "tabIndex", -1 ); + } + + toShow.attr({ + "aria-expanded": "true", + "aria-hidden": "false" + }); + eventData.newTab.attr({ + "aria-selected": "true", + tabIndex: 0 + }); + }, + + _activate: function( index ) { + var anchor, + active = this._findActive( index ); + + // trying to activate the already active panel + if ( active[ 0 ] === this.active[ 0 ] ) { + return; + } + + // trying to collapse, simulate a click on the current active header + if ( !active.length ) { + active = this.active; + } + + anchor = active.find( ".ui-tabs-anchor" )[ 0 ]; + this._eventHandler({ + target: anchor, + currentTarget: anchor, + preventDefault: $.noop + }); + }, + + _findActive: function( index ) { + return index === false ? $() : this.tabs.eq( index ); + }, + + _getIndex: function( index ) { + // meta-function to give users option to provide a href string instead of a numerical index. + if ( typeof index === "string" ) { + index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) ); + } + + return index; + }, + + _destroy: function() { + if ( this.xhr ) { + this.xhr.abort(); + } + + this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" ); + + this.tablist + .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" ) + .removeAttr( "role" ); + + this.anchors + .removeClass( "ui-tabs-anchor" ) + .removeAttr( "role" ) + .removeAttr( "tabIndex" ) + .removeData( "href.tabs" ) + .removeData( "load.tabs" ) + .removeUniqueId(); + + this.tabs.add( this.panels ).each(function() { + if ( $.data( this, "ui-tabs-destroy" ) ) { + $( this ).remove(); + } else { + $( this ) + .removeClass( "ui-state-default ui-state-active ui-state-disabled " + + "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" ) + .removeAttr( "tabIndex" ) + .removeAttr( "aria-live" ) + .removeAttr( "aria-busy" ) + .removeAttr( "aria-selected" ) + .removeAttr( "aria-labelledby" ) + .removeAttr( "aria-hidden" ) + .removeAttr( "aria-expanded" ) + .removeAttr( "role" ); + } + }); + + this.tabs.each(function() { + var li = $( this ), + prev = li.data( "ui-tabs-aria-controls" ); + if ( prev ) { + li.attr( "aria-controls", prev ); + } else { + li.removeAttr( "aria-controls" ); + } + }); + + this.panels.show(); + + if ( this.options.heightStyle !== "content" ) { + this.panels.css( "height", "" ); + } + }, + + enable: function( index ) { + var disabled = this.options.disabled; + if ( disabled === false ) { + return; + } + + if ( index === undefined ) { + disabled = false; + } else { + index = this._getIndex( index ); + if ( $.isArray( disabled ) ) { + disabled = $.map( disabled, function( num ) { + return num !== index ? num : null; + }); + } else { + disabled = $.map( this.tabs, function( li, num ) { + return num !== index ? num : null; + }); + } + } + this._setupDisabled( disabled ); + }, + + disable: function( index ) { + var disabled = this.options.disabled; + if ( disabled === true ) { + return; + } + + if ( index === undefined ) { + disabled = true; + } else { + index = this._getIndex( index ); + if ( $.inArray( index, disabled ) !== -1 ) { + return; + } + if ( $.isArray( disabled ) ) { + disabled = $.merge( [ index ], disabled ).sort(); + } else { + disabled = [ index ]; + } + } + this._setupDisabled( disabled ); + }, + + load: function( index, event ) { + index = this._getIndex( index ); + var that = this, + tab = this.tabs.eq( index ), + anchor = tab.find( ".ui-tabs-anchor" ), + panel = this._getPanelForTab( tab ), + eventData = { + tab: tab, + panel: panel + }; + + // not remote + if ( isLocal( anchor[ 0 ] ) ) { + return; + } + + this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) ); + + // support: jQuery <1.8 + // jQuery <1.8 returns false if the request is canceled in beforeSend, + // but as of 1.8, $.ajax() always returns a jqXHR object. + if ( this.xhr && this.xhr.statusText !== "canceled" ) { + tab.addClass( "ui-tabs-loading" ); + panel.attr( "aria-busy", "true" ); + + this.xhr + .success(function( response ) { + // support: jQuery <1.8 + // http://bugs.jquery.com/ticket/11778 + setTimeout(function() { + panel.html( response ); + that._trigger( "load", event, eventData ); + }, 1 ); + }) + .complete(function( jqXHR, status ) { + // support: jQuery <1.8 + // http://bugs.jquery.com/ticket/11778 + setTimeout(function() { + if ( status === "abort" ) { + that.panels.stop( false, true ); + } + + tab.removeClass( "ui-tabs-loading" ); + panel.removeAttr( "aria-busy" ); + + if ( jqXHR === that.xhr ) { + delete that.xhr; + } + }, 1 ); + }); + } + }, + + // TODO: Remove this function in 1.10 when ajaxOptions is removed + _ajaxSettings: function( anchor, event, eventData ) { + var that = this; + return { + url: anchor.attr( "href" ), + beforeSend: function( jqXHR, settings ) { + return that._trigger( "beforeLoad", event, + $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) ); + } + }; + }, + + _getPanelForTab: function( tab ) { + var id = $( tab ).attr( "aria-controls" ); + return this.element.find( this._sanitizeSelector( "#" + id ) ); + } +}); + +// DEPRECATED +if ( $.uiBackCompat !== false ) { + + // helper method for a lot of the back compat extensions + $.ui.tabs.prototype._ui = function( tab, panel ) { + return { + tab: tab, + panel: panel, + index: this.anchors.index( tab ) + }; + }; + + // url method + $.widget( "ui.tabs", $.ui.tabs, { + url: function( index, url ) { + this.anchors.eq( index ).attr( "href", url ); + } + }); + + // TODO: Remove _ajaxSettings() method when removing this extension + // ajaxOptions and cache options + $.widget( "ui.tabs", $.ui.tabs, { + options: { + ajaxOptions: null, + cache: false + }, + + _create: function() { + this._super(); + + var that = this; + + this._on({ tabsbeforeload: function( event, ui ) { + // tab is already cached + if ( $.data( ui.tab[ 0 ], "cache.tabs" ) ) { + event.preventDefault(); + return; + } + + ui.jqXHR.success(function() { + if ( that.options.cache ) { + $.data( ui.tab[ 0 ], "cache.tabs", true ); + } + }); + }}); + }, + + _ajaxSettings: function( anchor, event, ui ) { + var ajaxOptions = this.options.ajaxOptions; + return $.extend( {}, ajaxOptions, { + error: function( xhr, status ) { + try { + // Passing index avoid a race condition when this method is + // called after the user has selected another tab. + // Pass the anchor that initiated this request allows + // loadError to manipulate the tab content panel via $(a.hash) + ajaxOptions.error( + xhr, status, ui.tab.closest( "li" ).index(), ui.tab[ 0 ] ); + } + catch ( error ) {} + } + }, this._superApply( arguments ) ); + }, + + _setOption: function( key, value ) { + // reset cache if switching from cached to not cached + if ( key === "cache" && value === false ) { + this.anchors.removeData( "cache.tabs" ); + } + this._super( key, value ); + }, + + _destroy: function() { + this.anchors.removeData( "cache.tabs" ); + this._super(); + }, + + url: function( index ){ + this.anchors.eq( index ).removeData( "cache.tabs" ); + this._superApply( arguments ); + } + }); + + // abort method + $.widget( "ui.tabs", $.ui.tabs, { + abort: function() { + if ( this.xhr ) { + this.xhr.abort(); + } + } + }); + + // spinner + $.widget( "ui.tabs", $.ui.tabs, { + options: { + spinner: "<em>Loading…</em>" + }, + _create: function() { + this._super(); + this._on({ + tabsbeforeload: function( event, ui ) { + // Don't react to nested tabs or tabs that don't use a spinner + if ( event.target !== this.element[ 0 ] || + !this.options.spinner ) { + return; + } + + var span = ui.tab.find( "span" ), + html = span.html(); + span.html( this.options.spinner ); + ui.jqXHR.complete(function() { + span.html( html ); + }); + } + }); + } + }); + + // enable/disable events + $.widget( "ui.tabs", $.ui.tabs, { + options: { + enable: null, + disable: null + }, + + enable: function( index ) { + var options = this.options, + trigger; + + if ( index && options.disabled === true || + ( $.isArray( options.disabled ) && $.inArray( index, options.disabled ) !== -1 ) ) { + trigger = true; + } + + this._superApply( arguments ); + + if ( trigger ) { + this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + } + }, + + disable: function( index ) { + var options = this.options, + trigger; + + if ( index && options.disabled === false || + ( $.isArray( options.disabled ) && $.inArray( index, options.disabled ) === -1 ) ) { + trigger = true; + } + + this._superApply( arguments ); + + if ( trigger ) { + this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + } + } + }); + + // add/remove methods and events + $.widget( "ui.tabs", $.ui.tabs, { + options: { + add: null, + remove: null, + tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>" + }, + + add: function( url, label, index ) { + if ( index === undefined ) { + index = this.anchors.length; + } + + var doInsertAfter, panel, + options = this.options, + li = $( options.tabTemplate + .replace( /#\{href\}/g, url ) + .replace( /#\{label\}/g, label ) ), + id = !url.indexOf( "#" ) ? + url.replace( "#", "" ) : + this._tabId( li ); + + li.addClass( "ui-state-default ui-corner-top" ).data( "ui-tabs-destroy", true ); + li.attr( "aria-controls", id ); + + doInsertAfter = index >= this.tabs.length; + + // try to find an existing element before creating a new one + panel = this.element.find( "#" + id ); + if ( !panel.length ) { + panel = this._createPanel( id ); + if ( doInsertAfter ) { + if ( index > 0 ) { + panel.insertAfter( this.panels.eq( -1 ) ); + } else { + panel.appendTo( this.element ); + } + } else { + panel.insertBefore( this.panels[ index ] ); + } + } + panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ).hide(); + + if ( doInsertAfter ) { + li.appendTo( this.tablist ); + } else { + li.insertBefore( this.tabs[ index ] ); + } + + options.disabled = $.map( options.disabled, function( n ) { + return n >= index ? ++n : n; + }); + + this.refresh(); + if ( this.tabs.length === 1 && options.active === false ) { + this.option( "active", 0 ); + } + + this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) ); + return this; + }, + + remove: function( index ) { + index = this._getIndex( index ); + var options = this.options, + tab = this.tabs.eq( index ).remove(), + panel = this._getPanelForTab( tab ).remove(); + + // If selected tab was removed focus tab to the right or + // in case the last tab was removed the tab to the left. + // We check for more than 2 tabs, because if there are only 2, + // then when we remove this tab, there will only be one tab left + // so we don't need to detect which tab to activate. + if ( tab.hasClass( "ui-tabs-active" ) && this.anchors.length > 2 ) { + this._activate( index + ( index + 1 < this.anchors.length ? 1 : -1 ) ); + } + + options.disabled = $.map( + $.grep( options.disabled, function( n ) { + return n !== index; + }), + function( n ) { + return n >= index ? --n : n; + }); + + this.refresh(); + + this._trigger( "remove", null, this._ui( tab.find( "a" )[ 0 ], panel[ 0 ] ) ); + return this; + } + }); + + // length method + $.widget( "ui.tabs", $.ui.tabs, { + length: function() { + return this.anchors.length; + } + }); + + // panel ids (idPrefix option + title attribute) + $.widget( "ui.tabs", $.ui.tabs, { + options: { + idPrefix: "ui-tabs-" + }, + + _tabId: function( tab ) { + var a = tab.is( "li" ) ? tab.find( "a[href]" ) : tab; + a = a[0]; + return $( a ).closest( "li" ).attr( "aria-controls" ) || + a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF\-]/g, "" ) || + this.options.idPrefix + getNextTabId(); + } + }); + + // _createPanel method + $.widget( "ui.tabs", $.ui.tabs, { + options: { + panelTemplate: "<div></div>" + }, + + _createPanel: function( id ) { + return $( this.options.panelTemplate ) + .attr( "id", id ) + .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ) + .data( "ui-tabs-destroy", true ); + } + }); + + // selected option + $.widget( "ui.tabs", $.ui.tabs, { + _create: function() { + var options = this.options; + if ( options.active === null && options.selected !== undefined ) { + options.active = options.selected === -1 ? false : options.selected; + } + this._super(); + options.selected = options.active; + if ( options.selected === false ) { + options.selected = -1; + } + }, + + _setOption: function( key, value ) { + if ( key !== "selected" ) { + return this._super( key, value ); + } + + var options = this.options; + this._super( "active", value === -1 ? false : value ); + options.selected = options.active; + if ( options.selected === false ) { + options.selected = -1; + } + }, + + _eventHandler: function() { + this._superApply( arguments ); + this.options.selected = this.options.active; + if ( this.options.selected === false ) { + this.options.selected = -1; + } + } + }); + + // show and select event + $.widget( "ui.tabs", $.ui.tabs, { + options: { + show: null, + select: null + }, + _create: function() { + this._super(); + if ( this.options.active !== false ) { + this._trigger( "show", null, this._ui( + this.active.find( ".ui-tabs-anchor" )[ 0 ], + this._getPanelForTab( this.active )[ 0 ] ) ); + } + }, + _trigger: function( type, event, data ) { + var tab, panel, + ret = this._superApply( arguments ); + + if ( !ret ) { + return false; + } + + if ( type === "beforeActivate" ) { + tab = data.newTab.length ? data.newTab : data.oldTab; + panel = data.newPanel.length ? data.newPanel : data.oldPanel; + ret = this._super( "select", event, { + tab: tab.find( ".ui-tabs-anchor" )[ 0], + panel: panel[ 0 ], + index: tab.closest( "li" ).index() + }); + } else if ( type === "activate" && data.newTab.length ) { + ret = this._super( "show", event, { + tab: data.newTab.find( ".ui-tabs-anchor" )[ 0 ], + panel: data.newPanel[ 0 ], + index: data.newTab.closest( "li" ).index() + }); + } + return ret; + } + }); + + // select method + $.widget( "ui.tabs", $.ui.tabs, { + select: function( index ) { + index = this._getIndex( index ); + if ( index === -1 ) { + if ( this.options.collapsible && this.options.selected !== -1 ) { + index = this.options.selected; + } else { + return; + } + } + this.anchors.eq( index ).trigger( this.options.event + this.eventNamespace ); + } + }); + + // cookie option + (function() { + + var listId = 0; + + $.widget( "ui.tabs", $.ui.tabs, { + options: { + cookie: null // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true } + }, + _create: function() { + var options = this.options, + active; + if ( options.active == null && options.cookie ) { + active = parseInt( this._cookie(), 10 ); + if ( active === -1 ) { + active = false; + } + options.active = active; + } + this._super(); + }, + _cookie: function( active ) { + var cookie = [ this.cookie || + ( this.cookie = this.options.cookie.name || "ui-tabs-" + (++listId) ) ]; + if ( arguments.length ) { + cookie.push( active === false ? -1 : active ); + cookie.push( this.options.cookie ); + } + return $.cookie.apply( null, cookie ); + }, + _refresh: function() { + this._super(); + if ( this.options.cookie ) { + this._cookie( this.options.active, this.options.cookie ); + } + }, + _eventHandler: function() { + this._superApply( arguments ); + if ( this.options.cookie ) { + this._cookie( this.options.active, this.options.cookie ); + } + }, + _destroy: function() { + this._super(); + if ( this.options.cookie ) { + this._cookie( null, this.options.cookie ); + } + } + }); + + })(); + + // load event + $.widget( "ui.tabs", $.ui.tabs, { + _trigger: function( type, event, data ) { + var _data = $.extend( {}, data ); + if ( type === "load" ) { + _data.panel = _data.panel[ 0 ]; + _data.tab = _data.tab.find( ".ui-tabs-anchor" )[ 0 ]; + } + return this._super( type, event, _data ); + } + }); + + // fx option + // The new animation options (show, hide) conflict with the old show callback. + // The old fx option wins over show/hide anyway (always favor back-compat). + // If a user wants to use the new animation API, they must give up the old API. + $.widget( "ui.tabs", $.ui.tabs, { + options: { + fx: null // e.g. { height: "toggle", opacity: "toggle", duration: 200 } + }, + + _getFx: function() { + var hide, show, + fx = this.options.fx; + + if ( fx ) { + if ( $.isArray( fx ) ) { + hide = fx[ 0 ]; + show = fx[ 1 ]; + } else { + hide = show = fx; + } + } + + return fx ? { show: show, hide: hide } : null; + }, + + _toggle: function( event, eventData ) { + var that = this, + toShow = eventData.newPanel, + toHide = eventData.oldPanel, + fx = this._getFx(); + + if ( !fx ) { + return this._super( event, eventData ); + } + + that.running = true; + + function complete() { + that.running = false; + that._trigger( "activate", event, eventData ); + } + + function show() { + eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" ); + + if ( toShow.length && fx.show ) { + toShow + .animate( fx.show, fx.show.duration, function() { + complete(); + }); + } else { + toShow.show(); + complete(); + } + } + + // start out by hiding, then showing, then completing + if ( toHide.length && fx.hide ) { + toHide.animate( fx.hide, fx.hide.duration, function() { + eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + show(); + }); + } else { + eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" ); + toHide.hide(); + show(); + } + } + }); +} + +})( jQuery ); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.tooltip.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.tooltip.js new file mode 100644 index 0000000..629dc08 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.tooltip.js @@ -0,0 +1,398 @@ +/*! + * jQuery UI Tooltip @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/tooltip/ + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + * jquery.ui.position.js + */ +(function( $ ) { + +var increments = 0; + +function addDescribedBy( elem, id ) { + var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ); + describedby.push( id ); + elem + .data( "ui-tooltip-id", id ) + .attr( "aria-describedby", $.trim( describedby.join( " " ) ) ); +} + +function removeDescribedBy( elem ) { + var id = elem.data( "ui-tooltip-id" ), + describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ), + index = $.inArray( id, describedby ); + if ( index !== -1 ) { + describedby.splice( index, 1 ); + } + + elem.removeData( "ui-tooltip-id" ); + describedby = $.trim( describedby.join( " " ) ); + if ( describedby ) { + elem.attr( "aria-describedby", describedby ); + } else { + elem.removeAttr( "aria-describedby" ); + } +} + +$.widget( "ui.tooltip", { + version: "@VERSION", + options: { + content: function() { + return $( this ).attr( "title" ); + }, + hide: true, + // Disabled elements have inconsistent behavior across browsers (#8661) + items: "[title]:not([disabled])", + position: { + my: "left top+15", + at: "left bottom", + collision: "flipfit flip" + }, + show: true, + tooltipClass: null, + track: false, + + // callbacks + close: null, + open: null + }, + + _create: function() { + this._on({ + mouseover: "open", + focusin: "open" + }); + + // IDs of generated tooltips, needed for destroy + this.tooltips = {}; + // IDs of parent tooltips where we removed the title attribute + this.parents = {}; + + if ( this.options.disabled ) { + this._disable(); + } + }, + + _setOption: function( key, value ) { + var that = this; + + if ( key === "disabled" ) { + this[ value ? "_disable" : "_enable" ](); + this.options[ key ] = value; + // disable element style changes + return; + } + + this._super( key, value ); + + if ( key === "content" ) { + $.each( this.tooltips, function( id, element ) { + that._updateContent( element ); + }); + } + }, + + _disable: function() { + var that = this; + + // close open tooltips + $.each( this.tooltips, function( id, element ) { + var event = $.Event( "blur" ); + event.target = event.currentTarget = element[0]; + that.close( event, true ); + }); + + // remove title attributes to prevent native tooltips + this.element.find( this.options.items ).andSelf().each(function() { + var element = $( this ); + if ( element.is( "[title]" ) ) { + element + .data( "ui-tooltip-title", element.attr( "title" ) ) + .attr( "title", "" ); + } + }); + }, + + _enable: function() { + // restore title attributes + this.element.find( this.options.items ).andSelf().each(function() { + var element = $( this ); + if ( element.data( "ui-tooltip-title" ) ) { + element.attr( "title", element.data( "ui-tooltip-title" ) ); + } + }); + }, + + open: function( event ) { + var that = this, + target = $( event ? event.target : this.element ) + // we need closest here due to mouseover bubbling, + // but always pointing at the same event target + .closest( this.options.items ); + + // No element to show a tooltip for or the tooltip is already open + if ( !target.length || target.data( "ui-tooltip-id" ) ) { + return; + } + + if ( target.attr( "title" ) ) { + target.data( "ui-tooltip-title", target.attr( "title" ) ); + } + + target.data( "ui-tooltip-open", true ); + + // kill parent tooltips, custom or native, for hover + if ( event && event.type === "mouseover" ) { + target.parents().each(function() { + var parent = $( this ), + blurEvent; + if ( parent.data( "ui-tooltip-open" ) ) { + blurEvent = $.Event( "blur" ); + blurEvent.target = blurEvent.currentTarget = this; + that.close( blurEvent, true ); + } + if ( parent.attr( "title" ) ) { + parent.uniqueId(); + that.parents[ this.id ] = { + element: this, + title: parent.attr( "title" ) + }; + parent.attr( "title", "" ); + } + }); + } + + this._updateContent( target, event ); + }, + + _updateContent: function( target, event ) { + var content, + contentOption = this.options.content, + that = this, + eventType = event ? event.type : null; + + if ( typeof contentOption === "string" ) { + return this._open( event, target, contentOption ); + } + + content = contentOption.call( target[0], function( response ) { + // ignore async response if tooltip was closed already + if ( !target.data( "ui-tooltip-open" ) ) { + return; + } + // IE may instantly serve a cached response for ajax requests + // delay this call to _open so the other call to _open runs first + that._delay(function() { + // jQuery creates a special event for focusin when it doesn't + // exist natively. To improve performance, the native event + // object is reused and the type is changed. Therefore, we can't + // rely on the type being correct after the event finished + // bubbling, so we set it back to the previous value. (#8740) + if ( event ) { + event.type = eventType; + } + this._open( event, target, response ); + }); + }); + if ( content ) { + this._open( event, target, content ); + } + }, + + _open: function( event, target, content ) { + var tooltip, events, delayedShow, + positionOption = $.extend( {}, this.options.position ); + + if ( !content ) { + return; + } + + // Content can be updated multiple times. If the tooltip already + // exists, then just update the content and bail. + tooltip = this._find( target ); + if ( tooltip.length ) { + tooltip.find( ".ui-tooltip-content" ).html( content ); + return; + } + + // if we have a title, clear it to prevent the native tooltip + // we have to check first to avoid defining a title if none exists + // (we don't want to cause an element to start matching [title]) + // + // We use removeAttr only for key events, to allow IE to export the correct + // accessible attributes. For mouse events, set to empty string to avoid + // native tooltip showing up (happens only when removing inside mouseover). + if ( target.is( "[title]" ) ) { + if ( event && event.type === "mouseover" ) { + target.attr( "title", "" ); + } else { + target.removeAttr( "title" ); + } + } + + tooltip = this._tooltip( target ); + addDescribedBy( target, tooltip.attr( "id" ) ); + tooltip.find( ".ui-tooltip-content" ).html( content ); + + function position( event ) { + positionOption.of = event; + if ( tooltip.is( ":hidden" ) ) { + return; + } + tooltip.position( positionOption ); + } + if ( this.options.track && event && /^mouse/.test( event.type ) ) { + this._on( this.document, { + mousemove: position + }); + // trigger once to override element-relative positioning + position( event ); + } else { + tooltip.position( $.extend({ + of: target + }, this.options.position ) ); + } + + tooltip.hide(); + + this._show( tooltip, this.options.show ); + // Handle tracking tooltips that are shown with a delay (#8644). As soon + // as the tooltip is visible, position the tooltip using the most recent + // event. + if ( this.options.show && this.options.show.delay ) { + delayedShow = setInterval(function() { + if ( tooltip.is( ":visible" ) ) { + position( positionOption.of ); + clearInterval( delayedShow ); + } + }, $.fx.interval ); + } + + this._trigger( "open", event, { tooltip: tooltip } ); + + events = { + keyup: function( event ) { + if ( event.keyCode === $.ui.keyCode.ESCAPE ) { + var fakeEvent = $.Event(event); + fakeEvent.currentTarget = target[0]; + this.close( fakeEvent, true ); + } + }, + remove: function() { + this._removeTooltip( tooltip ); + } + }; + if ( !event || event.type === "mouseover" ) { + events.mouseleave = "close"; + } + if ( !event || event.type === "focusin" ) { + events.focusout = "close"; + } + this._on( true, target, events ); + }, + + close: function( event ) { + var that = this, + target = $( event ? event.currentTarget : this.element ), + tooltip = this._find( target ); + + // disabling closes the tooltip, so we need to track when we're closing + // to avoid an infinite loop in case the tooltip becomes disabled on close + if ( this.closing ) { + return; + } + + // only set title if we had one before (see comment in _open()) + if ( target.data( "ui-tooltip-title" ) ) { + target.attr( "title", target.data( "ui-tooltip-title" ) ); + } + + removeDescribedBy( target ); + + tooltip.stop( true ); + this._hide( tooltip, this.options.hide, function() { + that._removeTooltip( $( this ) ); + }); + + target.removeData( "ui-tooltip-open" ); + this._off( target, "mouseleave focusout keyup" ); + // Remove 'remove' binding only on delegated targets + if ( target[0] !== this.element[0] ) { + this._off( target, "remove" ); + } + this._off( this.document, "mousemove" ); + + if ( event && event.type === "mouseleave" ) { + $.each( this.parents, function( id, parent ) { + $( parent.element ).attr( "title", parent.title ); + delete that.parents[ id ]; + }); + } + + this.closing = true; + this._trigger( "close", event, { tooltip: tooltip } ); + this.closing = false; + }, + + _tooltip: function( element ) { + var id = "ui-tooltip-" + increments++, + tooltip = $( "<div>" ) + .attr({ + id: id, + role: "tooltip" + }) + .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " + + ( this.options.tooltipClass || "" ) ); + $( "<div>" ) + .addClass( "ui-tooltip-content" ) + .appendTo( tooltip ); + tooltip.appendTo( this.document[0].body ); + if ( $.fn.bgiframe ) { + tooltip.bgiframe(); + } + this.tooltips[ id ] = element; + return tooltip; + }, + + _find: function( target ) { + var id = target.data( "ui-tooltip-id" ); + return id ? $( "#" + id ) : $(); + }, + + _removeTooltip: function( tooltip ) { + tooltip.remove(); + delete this.tooltips[ tooltip.attr( "id" ) ]; + }, + + _destroy: function() { + var that = this; + + // close open tooltips + $.each( this.tooltips, function( id, element ) { + // Delegate to close method to handle common cleanup + var event = $.Event( "blur" ); + event.target = event.currentTarget = element[0]; + that.close( event, true ); + + // Remove immediately; destroying an open tooltip doesn't use the + // hide animation + $( "#" + id ).remove(); + + // Restore the title + if ( element.data( "ui-tooltip-title" ) ) { + element.attr( "title", element.data( "ui-tooltip-title" ) ); + element.removeData( "ui-tooltip-title" ); + } + }); + } +}); + +}( jQuery ) ); diff --git a/hugo/js/jquery/src/jquery-ui/jquery.ui.widget.js b/hugo/js/jquery/src/jquery-ui/jquery.ui.widget.js new file mode 100644 index 0000000..2533448 --- /dev/null +++ b/hugo/js/jquery/src/jquery-ui/jquery.ui.widget.js @@ -0,0 +1,528 @@ +/*! + * jQuery UI Widget @VERSION + * http://jqueryui.com + * + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/jQuery.widget/ + */ +(function( $, undefined ) { + +var uuid = 0, + slice = Array.prototype.slice, + _cleanData = $.cleanData; +$.cleanData = function( elems ) { + for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) { + try { + $( elem ).triggerHandler( "remove" ); + // http://bugs.jquery.com/ticket/8235 + } catch( e ) {} + } + _cleanData( elems ); +}; + +$.widget = function( name, base, prototype ) { + var fullName, existingConstructor, constructor, basePrototype, + namespace = name.split( "." )[ 0 ]; + + name = name.split( "." )[ 1 ]; + fullName = namespace + "-" + name; + + if ( !prototype ) { + prototype = base; + base = $.Widget; + } + + // create selector for plugin + $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) { + return !!$.data( elem, fullName ); + }; + + $[ namespace ] = $[ namespace ] || {}; + existingConstructor = $[ namespace ][ name ]; + constructor = $[ namespace ][ name ] = function( options, element ) { + // allow instantiation without "new" keyword + if ( !this._createWidget ) { + return new constructor( options, element ); + } + + // allow instantiation without initializing for simple inheritance + // must use "new" keyword (the code above always passes args) + if ( arguments.length ) { + this._createWidget( options, element ); + } + }; + // extend with the existing constructor to carry over any static properties + $.extend( constructor, existingConstructor, { + version: prototype.version, + // copy the object used to create the prototype in case we need to + // redefine the widget later + _proto: $.extend( {}, prototype ), + // track widgets that inherit from this widget in case this widget is + // redefined after a widget inherits from it + _childConstructors: [] + }); + + basePrototype = new base(); + // we need to make the options hash a property directly on the new instance + // otherwise we'll modify the options hash on the prototype that we're + // inheriting from + basePrototype.options = $.widget.extend( {}, basePrototype.options ); + $.each( prototype, function( prop, value ) { + if ( $.isFunction( value ) ) { + prototype[ prop ] = (function() { + var _super = function() { + return base.prototype[ prop ].apply( this, arguments ); + }, + _superApply = function( args ) { + return base.prototype[ prop ].apply( this, args ); + }; + return function() { + var __super = this._super, + __superApply = this._superApply, + returnValue; + + this._super = _super; + this._superApply = _superApply; + + returnValue = value.apply( this, arguments ); + + this._super = __super; + this._superApply = __superApply; + + return returnValue; + }; + })(); + } + }); + constructor.prototype = $.widget.extend( basePrototype, { + // TODO: remove support for widgetEventPrefix + // always use the name + a colon as the prefix, e.g., draggable:start + // don't prefix for widgets that aren't DOM-based + widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name + }, prototype, { + constructor: constructor, + namespace: namespace, + widgetName: name, + // TODO remove widgetBaseClass, see #8155 + widgetBaseClass: fullName, + widgetFullName: fullName + }); + + // If this widget is being redefined then we need to find all widgets that + // are inheriting from it and redefine all of them so that they inherit from + // the new version of this widget. We're essentially trying to replace one + // level in the prototype chain. + if ( existingConstructor ) { + $.each( existingConstructor._childConstructors, function( i, child ) { + var childPrototype = child.prototype; + + // redefine the child widget using the same prototype that was + // originally used, but inherit from the new version of the base + $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto ); + }); + // remove the list of existing child constructors from the old constructor + // so the old child constructors can be garbage collected + delete existingConstructor._childConstructors; + } else { + base._childConstructors.push( constructor ); + } + + $.widget.bridge( name, constructor ); +}; + +$.widget.extend = function( target ) { + var input = slice.call( arguments, 1 ), + inputIndex = 0, + inputLength = input.length, + key, + value; + for ( ; inputIndex < inputLength; inputIndex++ ) { + for ( key in input[ inputIndex ] ) { + value = input[ inputIndex ][ key ]; + if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) { + // Clone objects + if ( $.isPlainObject( value ) ) { + target[ key ] = $.isPlainObject( target[ key ] ) ? + $.widget.extend( {}, target[ key ], value ) : + // Don't extend strings, arrays, etc. with objects + $.widget.extend( {}, value ); + // Copy everything else by reference + } else { + target[ key ] = value; + } + } + } + } + return target; +}; + +$.widget.bridge = function( name, object ) { + var fullName = object.prototype.widgetFullName || name; + $.fn[ name ] = function( options ) { + var isMethodCall = typeof options === "string", + args = slice.call( arguments, 1 ), + returnValue = this; + + // allow multiple hashes to be passed on init + options = !isMethodCall && args.length ? + $.widget.extend.apply( null, [ options ].concat(args) ) : + options; + + if ( isMethodCall ) { + this.each(function() { + var methodValue, + instance = $.data( this, fullName ); + if ( !instance ) { + return $.error( "cannot call methods on " + name + " prior to initialization; " + + "attempted to call method '" + options + "'" ); + } + if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) { + return $.error( "no such method '" + options + "' for " + name + " widget instance" ); + } + methodValue = instance[ options ].apply( instance, args ); + if ( methodValue !== instance && methodValue !== undefined ) { + returnValue = methodValue && methodValue.jquery ? + returnValue.pushStack( methodValue.get() ) : + methodValue; + return false; + } + }); + } else { + this.each(function() { + var instance = $.data( this, fullName ); + if ( instance ) { + instance.option( options || {} )._init(); + } else { + $.data( this, fullName, new object( options, this ) ); + } + }); + } + + return returnValue; + }; +}; + +$.Widget = function( /* options, element */ ) {}; +$.Widget._childConstructors = []; + +$.Widget.prototype = { + widgetName: "widget", + widgetEventPrefix: "", + defaultElement: "<div>", + options: { + disabled: false, + + // callbacks + create: null + }, + _createWidget: function( options, element ) { + element = $( element || this.defaultElement || this )[ 0 ]; + this.element = $( element ); + this.uuid = uuid++; + this.eventNamespace = "." + this.widgetName + this.uuid; + this.options = $.widget.extend( {}, + this.options, + this._getCreateOptions(), + options ); + + this.bindings = $(); + this.hoverable = $(); + this.focusable = $(); + + if ( element !== this ) { + // 1.9 BC for #7810 + // TODO remove dual storage + $.data( element, this.widgetName, this ); + $.data( element, this.widgetFullName, this ); + this._on( true, this.element, { + remove: function( event ) { + if ( event.target === element ) { + this.destroy(); + } + } + }); + this.document = $( element.style ? + // element within the document + element.ownerDocument : + // element is window or document + element.document || element ); + this.window = $( this.document[0].defaultView || this.document[0].parentWindow ); + } + + this._create(); + this._trigger( "create", null, this._getCreateEventData() ); + this._init(); + }, + _getCreateOptions: $.noop, + _getCreateEventData: $.noop, + _create: $.noop, + _init: $.noop, + + destroy: function() { + this._destroy(); + // we can probably remove the unbind calls in 2.0 + // all event bindings should go through this._on() + this.element + .unbind( this.eventNamespace ) + // 1.9 BC for #7810 + // TODO remove dual storage + .removeData( this.widgetName ) + .removeData( this.widgetFullName ) + // support: jquery <1.6.3 + // http://bugs.jquery.com/ticket/9413 + .removeData( $.camelCase( this.widgetFullName ) ); + this.widget() + .unbind( this.eventNamespace ) + .removeAttr( "aria-disabled" ) + .removeClass( + this.widgetFullName + "-disabled " + + "ui-state-disabled" ); + + // clean up events and states + this.bindings.unbind( this.eventNamespace ); + this.hoverable.removeClass( "ui-state-hover" ); + this.focusable.removeClass( "ui-state-focus" ); + }, + _destroy: $.noop, + + widget: function() { + return this.element; + }, + + option: function( key, value ) { + var options = key, + parts, + curOption, + i; + + if ( arguments.length === 0 ) { + // don't return a reference to the internal hash + return $.widget.extend( {}, this.options ); + } + + if ( typeof key === "string" ) { + // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } + options = {}; + parts = key.split( "." ); + key = parts.shift(); + if ( parts.length ) { + curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); + for ( i = 0; i < parts.length - 1; i++ ) { + curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; + curOption = curOption[ parts[ i ] ]; + } + key = parts.pop(); + if ( value === undefined ) { + return curOption[ key ] === undefined ? null : curOption[ key ]; + } + curOption[ key ] = value; + } else { + if ( value === undefined ) { + return this.options[ key ] === undefined ? null : this.options[ key ]; + } + options[ key ] = value; + } + } + + this._setOptions( options ); + + return this; + }, + _setOptions: function( options ) { + var key; + + for ( key in options ) { + this._setOption( key, options[ key ] ); + } + + return this; + }, + _setOption: function( key, value ) { + this.options[ key ] = value; + + if ( key === "disabled" ) { + this.widget() + .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value ) + .attr( "aria-disabled", value ); + this.hoverable.removeClass( "ui-state-hover" ); + this.focusable.removeClass( "ui-state-focus" ); + } + + return this; + }, + + enable: function() { + return this._setOption( "disabled", false ); + }, + disable: function() { + return this._setOption( "disabled", true ); + }, + + _on: function( suppressDisabledCheck, element, handlers ) { + var delegateElement, + instance = this; + + // no suppressDisabledCheck flag, shuffle arguments + if ( typeof suppressDisabledCheck !== "boolean" ) { + handlers = element; + element = suppressDisabledCheck; + suppressDisabledCheck = false; + } + + // no element argument, shuffle and use this.element + if ( !handlers ) { + handlers = element; + element = this.element; + delegateElement = this.widget(); + } else { + // accept selectors, DOM elements + element = delegateElement = $( element ); + this.bindings = this.bindings.add( element ); + } + + $.each( handlers, function( event, handler ) { + function handlerProxy() { + // allow widgets to customize the disabled handling + // - disabled as an array instead of boolean + // - disabled class as method for disabling individual parts + if ( !suppressDisabledCheck && + ( instance.options.disabled === true || + $( this ).hasClass( "ui-state-disabled" ) ) ) { + return; + } + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + + // copy the guid so direct unbinding works + if ( typeof handler !== "string" ) { + handlerProxy.guid = handler.guid = + handler.guid || handlerProxy.guid || $.guid++; + } + + var match = event.match( /^(\w+)\s*(.*)$/ ), + eventName = match[1] + instance.eventNamespace, + selector = match[2]; + if ( selector ) { + delegateElement.delegate( selector, eventName, handlerProxy ); + } else { + element.bind( eventName, handlerProxy ); + } + }); + }, + + _off: function( element, eventName ) { + eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace; + element.unbind( eventName ).undelegate( eventName ); + }, + + _delay: function( handler, delay ) { + function handlerProxy() { + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + var instance = this; + return setTimeout( handlerProxy, delay || 0 ); + }, + + _hoverable: function( element ) { + this.hoverable = this.hoverable.add( element ); + this._on( element, { + mouseenter: function( event ) { + $( event.currentTarget ).addClass( "ui-state-hover" ); + }, + mouseleave: function( event ) { + $( event.currentTarget ).removeClass( "ui-state-hover" ); + } + }); + }, + + _focusable: function( element ) { + this.focusable = this.focusable.add( element ); + this._on( element, { + focusin: function( event ) { + $( event.currentTarget ).addClass( "ui-state-focus" ); + }, + focusout: function( event ) { + $( event.currentTarget ).removeClass( "ui-state-focus" ); + } + }); + }, + + _trigger: function( type, event, data ) { + var prop, orig, + callback = this.options[ type ]; + + data = data || {}; + event = $.Event( event ); + event.type = ( type === this.widgetEventPrefix ? + type : + this.widgetEventPrefix + type ).toLowerCase(); + // the original event may come from any element + // so we need to reset the target on the new event + event.target = this.element[ 0 ]; + + // copy original event properties over to the new event + orig = event.originalEvent; + if ( orig ) { + for ( prop in orig ) { + if ( !( prop in event ) ) { + event[ prop ] = orig[ prop ]; + } + } + } + + this.element.trigger( event, data ); + return !( $.isFunction( callback ) && + callback.apply( this.element[0], [ event ].concat( data ) ) === false || + event.isDefaultPrevented() ); + } +}; + +$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { + $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { + if ( typeof options === "string" ) { + options = { effect: options }; + } + var hasOptions, + effectName = !options ? + method : + options === true || typeof options === "number" ? + defaultEffect : + options.effect || defaultEffect; + options = options || {}; + if ( typeof options === "number" ) { + options = { duration: options }; + } + hasOptions = !$.isEmptyObject( options ); + options.complete = callback; + if ( options.delay ) { + element.delay( options.delay ); + } + if ( hasOptions && $.effects && ( $.effects.effect[ effectName ] || $.uiBackCompat !== false && $.effects[ effectName ] ) ) { + element[ method ]( options ); + } else if ( effectName !== method && element[ effectName ] ) { + element[ effectName ]( options.duration, options.easing, callback ); + } else { + element.queue(function( next ) { + $( this )[ method ](); + if ( callback ) { + callback.call( element[ 0 ] ); + } + next(); + }); + } + }; +}); + +// DEPRECATED +if ( $.uiBackCompat !== false ) { + $.Widget.prototype._getCreateOptions = function() { + return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ]; + }; +} + +})( jQuery ); diff --git a/hugo/js/jquery/src/jquery/ajax.js b/hugo/js/jquery/src/jquery/ajax.js new file mode 100644 index 0000000..8facc17 --- /dev/null +++ b/hugo/js/jquery/src/jquery/ajax.js @@ -0,0 +1,855 @@ +var + // Document location + ajaxLocParts, + ajaxLocation, + + ajax_nonce = jQuery.now(), + + ajax_rquery = /\?/, + rhash = /#.*$/, + rts = /([?&])_=[^&]*/, + rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, + // #7653, #8125, #8152: local protocol detection + rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, + rnoContent = /^(?:GET|HEAD)$/, + rprotocol = /^\/\//, + rurl = /^([\w.+-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/, + + // Keep a copy of the old load method + _load = jQuery.fn.load, + + /* Prefilters + * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) + * 2) These are called: + * - BEFORE asking for a transport + * - AFTER param serialization (s.data is a string if s.processData is true) + * 3) key is the dataType + * 4) the catchall symbol "*" can be used + * 5) execution will start with transport dataType and THEN continue down to "*" if needed + */ + prefilters = {}, + + /* Transports bindings + * 1) key is the dataType + * 2) the catchall symbol "*" can be used + * 3) selection will start with transport dataType and THEN go to "*" if needed + */ + transports = {}, + + // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + allTypes = "*/".concat("*"); + +// #8138, IE may throw an exception when accessing +// a field from window.location if document.domain has been set +try { + ajaxLocation = location.href; +} catch( e ) { + // Use the href attribute of an A element + // since IE will modify it given document.location + ajaxLocation = document.createElement( "a" ); + ajaxLocation.href = ""; + ajaxLocation = ajaxLocation.href; +} + +// Segment location into parts +ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || []; + +// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport +function addToPrefiltersOrTransports( structure ) { + + // dataTypeExpression is optional and defaults to "*" + return function( dataTypeExpression, func ) { + + if ( typeof dataTypeExpression !== "string" ) { + func = dataTypeExpression; + dataTypeExpression = "*"; + } + + var dataType, + i = 0, + dataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || []; + + if ( jQuery.isFunction( func ) ) { + // For each dataType in the dataTypeExpression + while ( (dataType = dataTypes[i++]) ) { + // Prepend if requested + if ( dataType[0] === "+" ) { + dataType = dataType.slice( 1 ) || "*"; + (structure[ dataType ] = structure[ dataType ] || []).unshift( func ); + + // Otherwise append + } else { + (structure[ dataType ] = structure[ dataType ] || []).push( func ); + } + } + } + }; +} + +// Base inspection function for prefilters and transports +function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) { + + var inspected = {}, + seekingTransport = ( structure === transports ); + + function inspect( dataType ) { + var selected; + inspected[ dataType ] = true; + jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) { + var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR ); + if( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) { + options.dataTypes.unshift( dataTypeOrTransport ); + inspect( dataTypeOrTransport ); + return false; + } else if ( seekingTransport ) { + return !( selected = dataTypeOrTransport ); + } + }); + return selected; + } + + return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" ); +} + +// A special extend for ajax options +// that takes "flat" options (not to be deep extended) +// Fixes #9887 +function ajaxExtend( target, src ) { + var key, deep, + flatOptions = jQuery.ajaxSettings.flatOptions || {}; + + for ( key in src ) { + if ( src[ key ] !== undefined ) { + ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ]; + } + } + if ( deep ) { + jQuery.extend( true, target, deep ); + } + + return target; +} + +jQuery.fn.load = function( url, params, callback ) { + if ( typeof url !== "string" && _load ) { + return _load.apply( this, arguments ); + } + + var selector, type, response, + self = this, + off = url.indexOf(" "); + + if ( off >= 0 ) { + selector = url.slice( off ); + url = url.slice( 0, off ); + } + + // If it's a function + if ( jQuery.isFunction( params ) ) { + + // We assume that it's the callback + callback = params; + params = undefined; + + // Otherwise, build a param string + } else if ( params && typeof params === "object" ) { + type = "POST"; + } + + // If we have elements to modify, make the request + if ( self.length > 0 ) { + jQuery.ajax({ + url: url, + + // if "type" variable is undefined, then "GET" method will be used + type: type, + dataType: "html", + data: params + }).done(function( responseText ) { + + // Save response for use in complete callback + response = arguments; + + self.html( selector ? + + // If a selector was specified, locate the right elements in a dummy div + // Exclude scripts to avoid IE 'Permission Denied' errors + jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) : + + // Otherwise use the full result + responseText ); + + }).complete( callback && function( jqXHR, status ) { + self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] ); + }); + } + + return this; +}; + +// Attach a bunch of functions for handling common AJAX events +jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){ + jQuery.fn[ type ] = function( fn ){ + return this.on( type, fn ); + }; +}); + +jQuery.extend({ + + // Counter for holding the number of active queries + active: 0, + + // Last-Modified header cache for next request + lastModified: {}, + etag: {}, + + ajaxSettings: { + url: ajaxLocation, + type: "GET", + isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ), + global: true, + processData: true, + async: true, + contentType: "application/x-www-form-urlencoded; charset=UTF-8", + /* + timeout: 0, + data: null, + dataType: null, + username: null, + password: null, + cache: null, + throws: false, + traditional: false, + headers: {}, + */ + + accepts: { + "*": allTypes, + text: "text/plain", + html: "text/html", + xml: "application/xml, text/xml", + json: "application/json, text/javascript" + }, + + contents: { + xml: /xml/, + html: /html/, + json: /json/ + }, + + responseFields: { + xml: "responseXML", + text: "responseText", + json: "responseJSON" + }, + + // Data converters + // Keys separate source (or catchall "*") and destination types with a single space + converters: { + + // Convert anything to text + "* text": String, + + // Text to html (true = no transformation) + "text html": true, + + // Evaluate text as a json expression + "text json": jQuery.parseJSON, + + // Parse text as xml + "text xml": jQuery.parseXML + }, + + // For options that shouldn't be deep extended: + // you can add your own custom options here if + // and when you create one that shouldn't be + // deep extended (see ajaxExtend) + flatOptions: { + url: true, + context: true + } + }, + + // Creates a full fledged settings object into target + // with both ajaxSettings and settings fields. + // If target is omitted, writes into ajaxSettings. + ajaxSetup: function( target, settings ) { + return settings ? + + // Building a settings object + ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) : + + // Extending ajaxSettings + ajaxExtend( jQuery.ajaxSettings, target ); + }, + + ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), + ajaxTransport: addToPrefiltersOrTransports( transports ), + + // Main method + ajax: function( url, options ) { + + // If url is an object, simulate pre-1.5 signature + if ( typeof url === "object" ) { + options = url; + url = undefined; + } + + // Force options to be an object + options = options || {}; + + var transport, + // URL without anti-cache param + cacheURL, + // Response headers + responseHeadersString, + responseHeaders, + // timeout handle + timeoutTimer, + // Cross-domain detection vars + parts, + // To know if global events are to be dispatched + fireGlobals, + // Loop variable + i, + // Create the final options object + s = jQuery.ajaxSetup( {}, options ), + // Callbacks context + callbackContext = s.context || s, + // Context for global events is callbackContext if it is a DOM node or jQuery collection + globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ? + jQuery( callbackContext ) : + jQuery.event, + // Deferreds + deferred = jQuery.Deferred(), + completeDeferred = jQuery.Callbacks("once memory"), + // Status-dependent callbacks + statusCode = s.statusCode || {}, + // Headers (they are sent all at once) + requestHeaders = {}, + requestHeadersNames = {}, + // The jqXHR state + state = 0, + // Default abort message + strAbort = "canceled", + // Fake xhr + jqXHR = { + readyState: 0, + + // Builds headers hashtable if needed + getResponseHeader: function( key ) { + var match; + if ( state === 2 ) { + if ( !responseHeaders ) { + responseHeaders = {}; + while ( (match = rheaders.exec( responseHeadersString )) ) { + responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; + } + } + match = responseHeaders[ key.toLowerCase() ]; + } + return match == null ? null : match; + }, + + // Raw string + getAllResponseHeaders: function() { + return state === 2 ? responseHeadersString : null; + }, + + // Caches the header + setRequestHeader: function( name, value ) { + var lname = name.toLowerCase(); + if ( !state ) { + name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; + requestHeaders[ name ] = value; + } + return this; + }, + + // Overrides response content-type header + overrideMimeType: function( type ) { + if ( !state ) { + s.mimeType = type; + } + return this; + }, + + // Status-dependent callbacks + statusCode: function( map ) { + var code; + if ( map ) { + if ( state < 2 ) { + for ( code in map ) { + // Lazy-add the new callback in a way that preserves old ones + statusCode[ code ] = [ statusCode[ code ], map[ code ] ]; + } + } else { + // Execute the appropriate callbacks + jqXHR.always( map[ jqXHR.status ] ); + } + } + return this; + }, + + // Cancel the request + abort: function( statusText ) { + var finalText = statusText || strAbort; + if ( transport ) { + transport.abort( finalText ); + } + done( 0, finalText ); + return this; + } + }; + + // Attach deferreds + deferred.promise( jqXHR ).complete = completeDeferred.add; + jqXHR.success = jqXHR.done; + jqXHR.error = jqXHR.fail; + + // Remove hash character (#7531: and string promotion) + // Add protocol if not provided (prefilters might expect it) + // Handle falsy url in the settings object (#10093: consistency with old signature) + // We also use the url parameter if available + s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ) + .replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); + + // Alias method option to type as per ticket #12004 + s.type = options.method || options.type || s.method || s.type; + + // Extract dataTypes list + s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""]; + + // A cross-domain request is in order when we have a protocol:host:port mismatch + if ( s.crossDomain == null ) { + parts = rurl.exec( s.url.toLowerCase() ); + s.crossDomain = !!( parts && + ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] || + ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !== + ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) ) + ); + } + + // Convert data if not already a string + if ( s.data && s.processData && typeof s.data !== "string" ) { + s.data = jQuery.param( s.data, s.traditional ); + } + + // Apply prefilters + inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); + + // If request was aborted inside a prefilter, stop there + if ( state === 2 ) { + return jqXHR; + } + + // We can fire global events as of now if asked to + fireGlobals = s.global; + + // Watch for a new set of requests + if ( fireGlobals && jQuery.active++ === 0 ) { + jQuery.event.trigger("ajaxStart"); + } + + // Uppercase the type + s.type = s.type.toUpperCase(); + + // Determine if request has content + s.hasContent = !rnoContent.test( s.type ); + + // Save the URL in case we're toying with the If-Modified-Since + // and/or If-None-Match header later on + cacheURL = s.url; + + // More options handling for requests with no content + if ( !s.hasContent ) { + + // If data is available, append data to url + if ( s.data ) { + cacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data ); + // #9682: remove data so that it's not used in an eventual retry + delete s.data; + } + + // Add anti-cache in url if needed + if ( s.cache === false ) { + s.url = rts.test( cacheURL ) ? + + // If there is already a '_' parameter, set its value + cacheURL.replace( rts, "$1_=" + ajax_nonce++ ) : + + // Otherwise add one to the end + cacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++; + } + } + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + if ( jQuery.lastModified[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] ); + } + if ( jQuery.etag[ cacheURL ] ) { + jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] ); + } + } + + // Set the correct header, if data is being sent + if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { + jqXHR.setRequestHeader( "Content-Type", s.contentType ); + } + + // Set the Accepts header for the server, depending on the dataType + jqXHR.setRequestHeader( + "Accept", + s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? + s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : + s.accepts[ "*" ] + ); + + // Check for headers option + for ( i in s.headers ) { + jqXHR.setRequestHeader( i, s.headers[ i ] ); + } + + // Allow custom headers/mimetypes and early abort + if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { + // Abort if not done already and return + return jqXHR.abort(); + } + + // aborting is no longer a cancellation + strAbort = "abort"; + + // Install callbacks on deferreds + for ( i in { success: 1, error: 1, complete: 1 } ) { + jqXHR[ i ]( s[ i ] ); + } + + // Get transport + transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); + + // If no transport, we auto-abort + if ( !transport ) { + done( -1, "No Transport" ); + } else { + jqXHR.readyState = 1; + + // Send global event + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); + } + // Timeout + if ( s.async && s.timeout > 0 ) { + timeoutTimer = setTimeout(function() { + jqXHR.abort("timeout"); + }, s.timeout ); + } + + try { + state = 1; + transport.send( requestHeaders, done ); + } catch ( e ) { + // Propagate exception as error if not done + if ( state < 2 ) { + done( -1, e ); + // Simply rethrow otherwise + } else { + throw e; + } + } + } + + // Callback for when everything is done + function done( status, nativeStatusText, responses, headers ) { + var isSuccess, success, error, response, modified, + statusText = nativeStatusText; + + // Called once + if ( state === 2 ) { + return; + } + + // State is "done" now + state = 2; + + // Clear timeout if it exists + if ( timeoutTimer ) { + clearTimeout( timeoutTimer ); + } + + // Dereference transport for early garbage collection + // (no matter how long the jqXHR object will be used) + transport = undefined; + + // Cache response headers + responseHeadersString = headers || ""; + + // Set readyState + jqXHR.readyState = status > 0 ? 4 : 0; + + // Determine if successful + isSuccess = status >= 200 && status < 300 || status === 304; + + // Get response data + if ( responses ) { + response = ajaxHandleResponses( s, jqXHR, responses ); + } + + // Convert no matter what (that way responseXXX fields are always set) + response = ajaxConvert( s, response, jqXHR, isSuccess ); + + // If successful, handle type chaining + if ( isSuccess ) { + + // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. + if ( s.ifModified ) { + modified = jqXHR.getResponseHeader("Last-Modified"); + if ( modified ) { + jQuery.lastModified[ cacheURL ] = modified; + } + modified = jqXHR.getResponseHeader("etag"); + if ( modified ) { + jQuery.etag[ cacheURL ] = modified; + } + } + + // if no content + if ( status === 204 || s.type === "HEAD" ) { + statusText = "nocontent"; + + // if not modified + } else if ( status === 304 ) { + statusText = "notmodified"; + + // If we have data, let's convert it + } else { + statusText = response.state; + success = response.data; + error = response.error; + isSuccess = !error; + } + } else { + // We extract error from statusText + // then normalize statusText and status for non-aborts + error = statusText; + if ( status || !statusText ) { + statusText = "error"; + if ( status < 0 ) { + status = 0; + } + } + } + + // Set data for the fake xhr object + jqXHR.status = status; + jqXHR.statusText = ( nativeStatusText || statusText ) + ""; + + // Success/Error + if ( isSuccess ) { + deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); + } else { + deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); + } + + // Status-dependent callbacks + jqXHR.statusCode( statusCode ); + statusCode = undefined; + + if ( fireGlobals ) { + globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError", + [ jqXHR, s, isSuccess ? success : error ] ); + } + + // Complete + completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); + + if ( fireGlobals ) { + globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); + // Handle the global AJAX counter + if ( !( --jQuery.active ) ) { + jQuery.event.trigger("ajaxStop"); + } + } + } + + return jqXHR; + }, + + getJSON: function( url, data, callback ) { + return jQuery.get( url, data, callback, "json" ); + }, + + getScript: function( url, callback ) { + return jQuery.get( url, undefined, callback, "script" ); + } +}); + +jQuery.each( [ "get", "post" ], function( i, method ) { + jQuery[ method ] = function( url, data, callback, type ) { + // shift arguments if data argument was omitted + if ( jQuery.isFunction( data ) ) { + type = type || callback; + callback = data; + data = undefined; + } + + return jQuery.ajax({ + url: url, + type: method, + dataType: type, + data: data, + success: callback + }); + }; +}); + +/* Handles responses to an ajax request: + * - finds the right dataType (mediates between content-type and expected dataType) + * - returns the corresponding response + */ +function ajaxHandleResponses( s, jqXHR, responses ) { + + var ct, type, finalDataType, firstDataType, + contents = s.contents, + dataTypes = s.dataTypes; + + // Remove auto dataType and get content-type in the process + while( dataTypes[ 0 ] === "*" ) { + dataTypes.shift(); + if ( ct === undefined ) { + ct = s.mimeType || jqXHR.getResponseHeader("Content-Type"); + } + } + + // Check if we're dealing with a known content-type + if ( ct ) { + for ( type in contents ) { + if ( contents[ type ] && contents[ type ].test( ct ) ) { + dataTypes.unshift( type ); + break; + } + } + } + + // Check to see if we have a response for the expected dataType + if ( dataTypes[ 0 ] in responses ) { + finalDataType = dataTypes[ 0 ]; + } else { + // Try convertible dataTypes + for ( type in responses ) { + if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) { + finalDataType = type; + break; + } + if ( !firstDataType ) { + firstDataType = type; + } + } + // Or just use first one + finalDataType = finalDataType || firstDataType; + } + + // If we found a dataType + // We add the dataType to the list if needed + // and return the corresponding response + if ( finalDataType ) { + if ( finalDataType !== dataTypes[ 0 ] ) { + dataTypes.unshift( finalDataType ); + } + return responses[ finalDataType ]; + } +} + +/* Chain conversions given the request and the original response + * Also sets the responseXXX fields on the jqXHR instance + */ +function ajaxConvert( s, response, jqXHR, isSuccess ) { + var conv2, current, conv, tmp, prev, + converters = {}, + // Work with a copy of dataTypes in case we need to modify it for conversion + dataTypes = s.dataTypes.slice(); + + // Create converters map with lowercased keys + if ( dataTypes[ 1 ] ) { + for ( conv in s.converters ) { + converters[ conv.toLowerCase() ] = s.converters[ conv ]; + } + } + + current = dataTypes.shift(); + + // Convert to each sequential dataType + while ( current ) { + + if ( s.responseFields[ current ] ) { + jqXHR[ s.responseFields[ current ] ] = response; + } + + // Apply the dataFilter if provided + if ( !prev && isSuccess && s.dataFilter ) { + response = s.dataFilter( response, s.dataType ); + } + + prev = current; + current = dataTypes.shift(); + + if ( current ) { + + // There's only work to do if current dataType is non-auto + if ( current === "*" ) { + + current = prev; + + // Convert response if prev dataType is non-auto and differs from current + } else if ( prev !== "*" && prev !== current ) { + + // Seek a direct converter + conv = converters[ prev + " " + current ] || converters[ "* " + current ]; + + // If none found, seek a pair + if ( !conv ) { + for ( conv2 in converters ) { + + // If conv2 outputs current + tmp = conv2.split( " " ); + if ( tmp[ 1 ] === current ) { + + // If prev can be converted to accepted input + conv = converters[ prev + " " + tmp[ 0 ] ] || + converters[ "* " + tmp[ 0 ] ]; + if ( conv ) { + // Condense equivalence converters + if ( conv === true ) { + conv = converters[ conv2 ]; + + // Otherwise, insert the intermediate dataType + } else if ( converters[ conv2 ] !== true ) { + current = tmp[ 0 ]; + dataTypes.unshift( tmp[ 1 ] ); + } + break; + } + } + } + } + + // Apply converter (if not an equivalence) + if ( conv !== true ) { + + // Unless errors are allowed to bubble, catch and return them + if ( conv && s[ "throws" ] ) { + response = conv( response ); + } else { + try { + response = conv( response ); + } catch ( e ) { + return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current }; + } + } + } + } + } + } + + return { state: "success", data: response }; +} diff --git a/hugo/js/jquery/src/jquery/ajax/jsonp.js b/hugo/js/jquery/src/jquery/ajax/jsonp.js new file mode 100644 index 0000000..b8803df --- /dev/null +++ b/hugo/js/jquery/src/jquery/ajax/jsonp.js @@ -0,0 +1,80 @@ +var oldCallbacks = [], + rjsonp = /(=)\?(?=&|$)|\?\?/; + +// Default jsonp settings +jQuery.ajaxSetup({ + jsonp: "callback", + jsonpCallback: function() { + var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) ); + this[ callback ] = true; + return callback; + } +}); + +// Detect, normalize options and install callbacks for jsonp requests +jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { + + var callbackName, overwritten, responseContainer, + jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? + "url" : + typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data" + ); + + // Handle iff the expected data type is "jsonp" or we have a parameter to set + if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { + + // Get callback name, remembering preexisting value associated with it + callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? + s.jsonpCallback() : + s.jsonpCallback; + + // Insert callback into url or form data + if ( jsonProp ) { + s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); + } else if ( s.jsonp !== false ) { + s.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; + } + + // Use data converter to retrieve json after script execution + s.converters["script json"] = function() { + if ( !responseContainer ) { + jQuery.error( callbackName + " was not called" ); + } + return responseContainer[ 0 ]; + }; + + // force json dataType + s.dataTypes[ 0 ] = "json"; + + // Install callback + overwritten = window[ callbackName ]; + window[ callbackName ] = function() { + responseContainer = arguments; + }; + + // Clean-up function (fires after converters) + jqXHR.always(function() { + // Restore preexisting value + window[ callbackName ] = overwritten; + + // Save back as free + if ( s[ callbackName ] ) { + // make sure that re-using the options doesn't screw things around + s.jsonpCallback = originalSettings.jsonpCallback; + + // save the callback name for future use + oldCallbacks.push( callbackName ); + } + + // Call if it was a function and we have a response + if ( responseContainer && jQuery.isFunction( overwritten ) ) { + overwritten( responseContainer[ 0 ] ); + } + + responseContainer = overwritten = undefined; + }); + + // Delegate to script + return "script"; + } +}); diff --git a/hugo/js/jquery/src/jquery/ajax/script.js b/hugo/js/jquery/src/jquery/ajax/script.js new file mode 100644 index 0000000..fe0562a --- /dev/null +++ b/hugo/js/jquery/src/jquery/ajax/script.js @@ -0,0 +1,57 @@ +// Install script dataType +jQuery.ajaxSetup({ + accepts: { + script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" + }, + contents: { + script: /(?:java|ecma)script/ + }, + converters: { + "text script": function( text ) { + jQuery.globalEval( text ); + return text; + } + } +}); + +// Handle cache's special case and crossDomain +jQuery.ajaxPrefilter( "script", function( s ) { + if ( s.cache === undefined ) { + s.cache = false; + } + if ( s.crossDomain ) { + s.type = "GET"; + } +}); + +// Bind script tag hack transport +jQuery.ajaxTransport( "script", function( s ) { + // This transport only deals with cross domain requests + if ( s.crossDomain ) { + var script, callback; + return { + send: function( _, complete ) { + script = jQuery("<script>").prop({ + async: true, + charset: s.scriptCharset, + src: s.url + }).on( + "load error", + callback = function( evt ) { + script.remove(); + callback = null; + if ( evt ) { + complete( evt.type === "error" ? 404 : 200, evt.type ); + } + } + ); + document.head.appendChild( script[ 0 ] ); + }, + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +}); diff --git a/hugo/js/jquery/src/jquery/ajax/xhr.js b/hugo/js/jquery/src/jquery/ajax/xhr.js new file mode 100644 index 0000000..3a9c9e9 --- /dev/null +++ b/hugo/js/jquery/src/jquery/ajax/xhr.js @@ -0,0 +1,111 @@ +jQuery.ajaxSettings.xhr = function() { + try { + return new XMLHttpRequest(); + } catch( e ) {} +}; + +var xhrSupported = jQuery.ajaxSettings.xhr(), + xhrSuccessStatus = { + // file protocol always yields status code 0, assume 200 + 0: 200, + // Support: IE9 + // #1450: sometimes IE returns 1223 when it should be 204 + 1223: 204 + }, + // Support: IE9 + // We need to keep track of outbound xhr and abort them manually + // because IE is not smart enough to do it all by itself + xhrId = 0, + xhrCallbacks = {}; + +if ( window.ActiveXObject ) { + jQuery( window ).on( "unload", function() { + for( var key in xhrCallbacks ) { + xhrCallbacks[ key ](); + } + xhrCallbacks = undefined; + }); +} + +jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); +jQuery.support.ajax = xhrSupported = !!xhrSupported; + +jQuery.ajaxTransport(function( options ) { + var callback; + // Cross domain only allowed if supported through XMLHttpRequest + if ( jQuery.support.cors || xhrSupported && !options.crossDomain ) { + return { + send: function( headers, complete ) { + var i, id, + xhr = options.xhr(); + xhr.open( options.type, options.url, options.async, options.username, options.password ); + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; + } + } + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers["X-Requested-With"] ) { + headers["X-Requested-With"] = "XMLHttpRequest"; + } + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + delete xhrCallbacks[ id ]; + callback = xhr.onload = xhr.onerror = null; + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + complete( + // file protocol always yields status 0, assume 404 + xhr.status || 404, + xhr.statusText + ); + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + // Support: IE9 + // #11426: When requesting binary data, IE9 will throw an exception + // on any attempt to access responseText + typeof xhr.responseText === "string" ? { + text: xhr.responseText + } : undefined, + xhr.getAllResponseHeaders() + ); + } + } + }; + }; + // Listen to events + xhr.onload = callback(); + xhr.onerror = callback("error"); + // Create the abort callback + callback = xhrCallbacks[( id = xhrId++ )] = callback("abort"); + // Do send the request + // This may raise an exception which is actually + // handled in jQuery.ajax (so no try/catch here) + xhr.send( options.hasContent && options.data || null ); + }, + abort: function() { + if ( callback ) { + callback(); + } + } + }; + } +}); diff --git a/hugo/js/jquery/src/jquery/attributes.js b/hugo/js/jquery/src/jquery/attributes.js new file mode 100644 index 0000000..4da2db6 --- /dev/null +++ b/hugo/js/jquery/src/jquery/attributes.js @@ -0,0 +1,502 @@ +var nodeHook, boolHook, + rclass = /[\t\r\n\f]/g, + rreturn = /\r/g, + rfocusable = /^(?:input|select|textarea|button)$/i; + +jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + return this.each(function() { + delete this[ jQuery.propFix[ name ] || name ]; + }); + }, + + addClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call( this, j, this.className ) ); + }); + } + + if ( proceed ) { + // The disjunction here is for better compressibility (see removeClass) + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + " " + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + elem.className = jQuery.trim( cur ); + + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = arguments.length === 0 || typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call( this, j, this.className ) ); + }); + } + if ( proceed ) { + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + "" + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + elem.className = value ? jQuery.trim( cur ) : ""; + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value; + + if ( typeof stateVal === "boolean" && type === "string" ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + classNames = value.match( core_rnotwhite ) || []; + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space separated list + if ( self.hasClass( className ) ) { + self.removeClass( className ); + } else { + self.addClass( className ); + } + } + + // Toggle whole class name + } else if ( type === core_strundefined || type === "boolean" ) { + if ( this.className ) { + // store className if set + data_priv.set( this, "__className__", this.className ); + } + + // If the element has a class name or if we're passed "false", + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + this.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var hooks, ret, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var val; + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, jQuery( this ).val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } +}); + +jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, option, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one" || index < 0, + values = one ? null : [], + max = one ? index + 1 : options.length, + i = index < 0 ? + max : + one ? index : 0; + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // IE6-9 doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + // Don't return options that are disabled or in a disabled optgroup + ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && + ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var optionSet, option, + options = elem.options, + values = jQuery.makeArray( value ), + i = options.length; + + while ( i-- ) { + option = options[ i ]; + if ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) { + optionSet = true; + } + } + + // force browsers to behave consistently when non-matching value is set + if ( !optionSet ) { + elem.selectedIndex = -1; + } + return values; + } + } + }, + + attr: function( elem, name, value ) { + var hooks, ret, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === core_strundefined ) { + return jQuery.prop( elem, name, value ); + } + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || + ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + + } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, value + "" ); + return value; + } + + } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + ret = jQuery.find.attr( elem, name ); + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var name, propName, + i = 0, + attrNames = value && value.match( core_rnotwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( (name = attrNames[i++]) ) { + propName = jQuery.propFix[ name ] || name; + + // Boolean attributes get special treatment (#10870) + if ( jQuery.expr.match.bool.test( name ) ) { + // Set corresponding property to false + elem[ propName ] = false; + } + + elem.removeAttribute( name ); + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to default in case type is set after value during creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + propFix: { + "for": "htmlFor", + "class": "className" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ? + ret : + ( elem[ name ] = value ); + + } else { + return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ? + ret : + elem[ name ]; + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + return elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ? + elem.tabIndex : + -1; + } + } + } +}); + +// Hooks for boolean attributes +boolHook = { + set: function( elem, value, name ) { + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else { + elem.setAttribute( name, name ); + } + return name; + } +}; +jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) { + var getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr; + + jQuery.expr.attrHandle[ name ] = function( elem, name, isXML ) { + var fn = jQuery.expr.attrHandle[ name ], + ret = isXML ? + undefined : + /* jshint eqeqeq: false */ + // Temporarily disable this handler to check existence + (jQuery.expr.attrHandle[ name ] = undefined) != + getter( elem, name, isXML ) ? + + name.toLowerCase() : + null; + + // Restore handler + jQuery.expr.attrHandle[ name ] = fn; + + return ret; + }; +}); + +// Support: IE9+ +// Selectedness for an option in an optgroup can be inaccurate +if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = { + get: function( elem ) { + var parent = elem.parentNode; + if ( parent && parent.parentNode ) { + parent.parentNode.selectedIndex; + } + return null; + } + }; +} + +jQuery.each([ + "tabIndex", + "readOnly", + "maxLength", + "cellSpacing", + "cellPadding", + "rowSpan", + "colSpan", + "useMap", + "frameBorder", + "contentEditable" +], function() { + jQuery.propFix[ this.toLowerCase() ] = this; +}); + +// Radios and checkboxes getter/setter +jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }; + if ( !jQuery.support.checkOn ) { + jQuery.valHooks[ this ].get = function( elem ) { + // Support: Webkit + // "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + }; + } +}); diff --git a/hugo/js/jquery/src/jquery/callbacks.js b/hugo/js/jquery/src/jquery/callbacks.js new file mode 100644 index 0000000..84c8346 --- /dev/null +++ b/hugo/js/jquery/src/jquery/callbacks.js @@ -0,0 +1,197 @@ +// String to Object options format cache +var optionsCache = {}; + +// Convert String-formatted options into Object-formatted ones and store in cache +function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; +} + +/* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ +jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // Flag to know if list is currently firing + firing, + // First callback to fire (used internally by add and fireWith) + firingStart, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + firingLength = 0; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + if ( list && ( !fired || stack ) ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; +}; diff --git a/hugo/js/jquery/src/jquery/core.js b/hugo/js/jquery/src/jquery/core.js new file mode 100644 index 0000000..55a0c25 --- /dev/null +++ b/hugo/js/jquery/src/jquery/core.js @@ -0,0 +1,846 @@ +var + // A central reference to the root jQuery(document) + rootjQuery, + + // The deferred used on DOM ready + readyList, + + // Support: IE9 + // For `typeof xmlNode.method` instead of `xmlNode.method !== undefined` + core_strundefined = typeof undefined, + + // Use the correct document accordingly with window argument (sandbox) + location = window.location, + document = window.document, + docElem = document.documentElement, + + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + + // Map over the $ in case of overwrite + _$ = window.$, + + // [[Class]] -> type pairs + class2type = {}, + + // List of deleted data cache ids, so we can reuse them + core_deletedIds = [], + + core_version = "@VERSION", + + // Save a reference to some core methods + core_concat = core_deletedIds.concat, + core_push = core_deletedIds.push, + core_slice = core_deletedIds.slice, + core_indexOf = core_deletedIds.indexOf, + core_toString = class2type.toString, + core_hasOwn = class2type.hasOwnProperty, + core_trim = core_version.trim, + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + + // Used for matching numbers + core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, + + // Used for splitting on whitespace + core_rnotwhite = /\S+/g, + + // A simple way to check for HTML strings + // Prioritize #id over <tag> to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/, + + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + + // The ready event handler and self cleanup method + completed = function() { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + jQuery.ready(); + }; + +jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: core_version, + + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return core_slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + + // Return a 'clean' array + this.toArray() : + + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; + }, + + slice: function() { + return this.pushStack( core_slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: core_push, + sort: [].sort, + splice: [].splice +}; + +// Give the init function the jQuery prototype for later instantiation +jQuery.fn.init.prototype = jQuery.fn; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend({ + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ), + + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger("ready").off("ready"); + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray, + + isWindow: function( obj ) { + return obj != null && obj === obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + if ( obj == null ) { + return String( obj ); + } + // Support: Safari <= 5.1 (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ core_toString.call(obj) ] || "object" : + typeof obj; + }, + + isPlainObject: function( obj ) { + // Not plain objects: + // - Any object or value whose internal [[Class]] property is not "[object Object]" + // - DOM nodes + // - window + if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + // Support: Firefox <20 + // The try/catch suppresses exceptions thrown when attempting to access + // the "constructor" property of certain host objects, ie. |window.location| + // https://bugzilla.mozilla.org/show_bug.cgi?id=814622 + try { + if ( obj.constructor && + !core_hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) { + return false; + } + } catch ( e ) { + return false; + } + + // If the function hasn't returned already, we're confident that + // |obj| is a plain object, created by {} or constructed with new Object + return true; + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + // data: string of html + // context (optional): If specified, the fragment will be created in this context, defaults to document + // keepScripts (optional): If true, will include scripts passed in the html string + parseHTML: function( data, context, keepScripts ) { + if ( !data || typeof data !== "string" ) { + return null; + } + if ( typeof context === "boolean" ) { + keepScripts = context; + context = false; + } + context = context || document; + + var parsed = rsingleTag.exec( data ), + scripts = !keepScripts && []; + + // Single tag + if ( parsed ) { + return [ context.createElement( parsed[1] ) ]; + } + + parsed = jQuery.buildFragment( [ data ], context, scripts ); + + if ( scripts && scripts.length ) { + jQuery( scripts ).remove(); + } + + return jQuery.merge( [], parsed.childNodes ); + }, + + parseJSON: JSON.parse, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE9 + try { + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } catch ( e ) { + xml = undefined; + } + + if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + globalEval: function( code ) { + var script, + indirect = eval; + + code = jQuery.trim( code ); + + if ( code ) { + // If the code includes a valid, prologue position + // strict mode pragma, execute code by injecting a + // script tag into the document. + if ( code.indexOf("use strict") === 1 ) { + script = document.createElement("script"); + script.text = code; + document.head.appendChild( script ).parentNode.removeChild( script ); + } else { + // Otherwise, avoid the DOM node creation, insertion + // and removal by using an indirect global eval + indirect( code ); + } + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + trim: function( text ) { + return text == null ? "" : core_trim.call( text ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + core_push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : core_indexOf.call( arr, elem, i ); + }, + + merge: function( first, second ) { + var l = second.length, + i = first.length, + j = 0; + + if ( typeof l === "number" ) { + for ( ; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var retVal, + ret = [], + i = 0, + length = elems.length; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return core_concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var tmp, args, proxy; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = core_slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + // Multifunctional method to get and set values of a collection + // The value/s can optionally be executed if it's a function + access: function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; + }, + + now: Date.now, + + // A method for quickly swapping in/out CSS properties to get correct calculations. + // Note: this method belongs to the css module but it's needed here for the support module. + // If support gets modularized, this method should be moved back to the css module. + swap: function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; + } +}); + +jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + } else { + + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + } + } + return readyList.promise( obj ); +}; + +// Populate the class2type map +jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +}); + +function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || type !== "function" && + ( length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj ); +} + +// All jQuery objects should point back to these +rootjQuery = jQuery(document); diff --git a/hugo/js/jquery/src/jquery/css.js b/hugo/js/jquery/src/jquery/css.js new file mode 100644 index 0000000..34b4d12 --- /dev/null +++ b/hugo/js/jquery/src/jquery/css.js @@ -0,0 +1,563 @@ +var curCSS, iframe, + // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" + // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rmargin = /^margin/, + rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), + rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), + rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ), + elemdisplay = { BODY: "block" }, + + cssShow = { position: "absolute", visibility: "hidden", display: "block" }, + cssNormalTransform = { + letterSpacing: 0, + fontWeight: 400 + }, + + cssExpand = [ "Top", "Right", "Bottom", "Left" ], + cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; + +// return a css property mapped to a potentially vendor prefixed property +function vendorPropName( style, name ) { + + // shortcut for names that are not vendor prefixed + if ( name in style ) { + return name; + } + + // check for vendor prefixed names + var capName = name.charAt(0).toUpperCase() + name.slice(1), + origName = name, + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in style ) { + return name; + } + } + + return origName; +} + +function isHidden( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); +} + +// NOTE: we've included the "window" in window.getComputedStyle +// because jsdom on node.js will break without it. +function getStyles( elem ) { + return window.getComputedStyle( elem, null ); +} + +function showHide( elements, show ) { + var display, elem, hidden, + values = [], + index = 0, + length = elements.length; + + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + values[ index ] = data_priv.get( elem, "olddisplay" ); + display = elem.style.display; + if ( show ) { + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !values[ index ] && display === "none" ) { + elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( elem.style.display === "" && isHidden( elem ) ) { + values[ index ] = data_priv.access( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); + } + } else { + + if ( !values[ index ] ) { + hidden = isHidden( elem ); + + if ( display && display !== "none" || !hidden ) { + data_priv.set( elem, "olddisplay", hidden ? display : jQuery.css(elem, "display") ); + } + } + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( index = 0; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + if ( !show || elem.style.display === "none" || elem.style.display === "" ) { + elem.style.display = show ? values[ index ] || "" : "none"; + } + } + + return elements; +} + +jQuery.fn.extend({ + css: function( name, value ) { + return jQuery.access( this, function( elem, name, value ) { + var styles, len, + map = {}, + i = 0; + + if ( jQuery.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + }, + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + if ( typeof state === "boolean" ) { + return state ? this.show() : this.hide(); + } + + return this.each(function() { + if ( isHidden( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + }); + } +}); + +jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Don't automatically add "px" to these possibly-unitless properties + cssNumber: { + "columnCount": true, + "fillOpacity": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "order": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": "cssFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = jQuery.camelCase( name ), + style = elem.style; + + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && (ret = rrelNum.exec( value )) ) { + value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); + // Fixes bug #9237 + type = "number"; + } + + // Make sure that NaN and null values aren't set. See: #7116 + if ( value == null || type === "number" && isNaN( value ) ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // Fixes #8908, it can be done more correctly by specifying setters in cssHooks, + // but it would mean to define eight (for every problematic property) identical functions + if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { + style[ name ] = value; + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var val, num, hooks, + origName = jQuery.camelCase( name ); + + // Make sure that we're working with the right name + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + //convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Return, converting to number if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; + } + return val; + } +}); + +curCSS = function( elem, name, _computed ) { + var width, minWidth, maxWidth, + computed = _computed || getStyles( elem ), + + // Support: IE9 + // getPropertyValue is only needed for .css('filter') in IE9, see #12537 + ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, + style = elem.style; + + if ( computed ) { + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // Support: Safari 5.1 + // A tribute to the "awesome hack by Dean Edwards" + // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels + // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values + if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret; +}; + + +function setPositiveNumber( elem, value, subtract ) { + var matches = rnumsplit.exec( value ); + return matches ? + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : + value; +} + +function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { + var i = extra === ( isBorderBox ? "border" : "content" ) ? + // If we already have the right measurement, avoid augmentation + 4 : + // Otherwise initialize for horizontal or vertical properties + name === "width" ? 1 : 0, + + val = 0; + + for ( ; i < 4; i += 2 ) { + // both box models exclude margin, so add it if we want it + if ( extra === "margin" ) { + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); + } + + if ( isBorderBox ) { + // border-box includes padding, so remove it if we want content + if ( extra === "content" ) { + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // at this point, extra isn't border nor margin, so remove border + if ( extra !== "margin" ) { + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } else { + // at this point, extra isn't content, so add padding + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // at this point, extra isn't content nor padding, so add border + if ( extra !== "padding" ) { + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + return val; +} + +function getWidthOrHeight( elem, name, extra ) { + + // Start with offset property, which is equivalent to the border-box value + var valueIsBorderBox = true, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight, + styles = getStyles( elem ), + isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // some non-html elements return undefined for offsetWidth, so check for null/undefined + // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 + // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 + if ( val <= 0 || val == null ) { + // Fall back to computed then uncomputed css if necessary + val = curCSS( elem, name, styles ); + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + } + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test(val) ) { + return val; + } + + // we need the check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + } + + // use the active box-sizing model to add/subtract irrelevant styles + return ( val + + augmentWidthOrHeight( + elem, + name, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles + ) + ) + "px"; +} + +// Try to determine the default display value of an element +function css_defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + // Use the already-created iframe if possible + iframe = ( iframe || + jQuery("<iframe frameborder='0' width='0' height='0'/>") + .css( "cssText", "display:block !important" ) + ).appendTo( doc.documentElement ); + + // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse + doc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document; + doc.write("<!doctype html><html><body>"); + doc.close(); + + display = actualDisplay( nodeName, doc ); + iframe.detach(); + } + + // Store the correct default display + elemdisplay[ nodeName ] = display; + } + + return display; +} + +// Called ONLY from within css_defaultDisplay +function actualDisplay( name, doc ) { + var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ), + display = jQuery.css( elem[0], "display" ); + elem.remove(); + return display; +} + +jQuery.each([ "height", "width" ], function( i, name ) { + jQuery.cssHooks[ name ] = { + get: function( elem, computed, extra ) { + if ( computed ) { + // certain elements can have dimension info if we invisibly show them + // however, it must have a current display style that would benefit from this + return elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ? + jQuery.swap( elem, cssShow, function() { + return getWidthOrHeight( elem, name, extra ); + }) : + getWidthOrHeight( elem, name, extra ); + } + }, + + set: function( elem, value, extra ) { + var styles = extra && getStyles( elem ); + return setPositiveNumber( elem, value, extra ? + augmentWidthOrHeight( + elem, + name, + extra, + jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + styles + ) : 0 + ); + } + }; +}); + +// These hooks cannot be added until DOM ready because the support test +// for it is not run until after DOM ready +jQuery(function() { + // Support: Android 2.3 + if ( !jQuery.support.reliableMarginRight ) { + jQuery.cssHooks.marginRight = { + get: function( elem, computed ) { + if ( computed ) { + // Support: Android 2.3 + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + // Work around by temporarily setting element display to inline-block + return jQuery.swap( elem, { "display": "inline-block" }, + curCSS, [ elem, "marginRight" ] ); + } + } + }; + } + + // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 + // getComputedStyle returns percent when specified for top/left/bottom/right + // rather than make the css module depend on the offset module, we just check for it here + if ( !jQuery.support.pixelPosition && jQuery.fn.position ) { + jQuery.each( [ "top", "left" ], function( i, prop ) { + jQuery.cssHooks[ prop ] = { + get: function( elem, computed ) { + if ( computed ) { + computed = curCSS( elem, prop ); + // if curCSS returns percentage, fallback to offset + return rnumnonpx.test( computed ) ? + jQuery( elem ).position()[ prop ] + "px" : + computed; + } + } + }; + }); + } + +}); + +if ( jQuery.expr && jQuery.expr.filters ) { + jQuery.expr.filters.hidden = function( elem ) { + // Support: Opera <= 12.12 + // Opera reports offsetWidths and offsetHeights less than zero on some elements + return elem.offsetWidth <= 0 && elem.offsetHeight <= 0; + }; + + jQuery.expr.filters.visible = function( elem ) { + return !jQuery.expr.filters.hidden( elem ); + }; +} + +// These hooks are used by animate to expand properties +jQuery.each({ + margin: "", + padding: "", + border: "Width" +}, function( prefix, suffix ) { + jQuery.cssHooks[ prefix + suffix ] = { + expand: function( value ) { + var i = 0, + expanded = {}, + + // assumes a single number if not a string + parts = typeof value === "string" ? value.split(" ") : [ value ]; + + for ( ; i < 4; i++ ) { + expanded[ prefix + cssExpand[ i ] + suffix ] = + parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; + } + + return expanded; + } + }; + + if ( !rmargin.test( prefix ) ) { + jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; + } +}); diff --git a/hugo/js/jquery/src/jquery/data.js b/hugo/js/jquery/src/jquery/data.js new file mode 100644 index 0000000..96afe6f --- /dev/null +++ b/hugo/js/jquery/src/jquery/data.js @@ -0,0 +1,356 @@ +/* + Implementation Summary + + 1. Enforce API surface and semantic compatibility with 1.9.x branch + 2. Improve the module's maintainability by reducing the storage + paths to a single mechanism. + 3. Use the same single mechanism to support "private" and "user" data. + 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData) + 5. Avoid exposing implementation details on user objects (eg. expando properties) + 6. Provide a clear path for implementation upgrade to WeakMap in 2014 +*/ +var data_user, data_priv, + rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, + rmultiDash = /([A-Z])/g; + +function Data() { + // Support: Android < 4, + // Old WebKit does not have Object.preventExtensions/freeze method, + // return new empty object instead with no [[set]] accessor + Object.defineProperty( this.cache = {}, 0, { + get: function() { + return {}; + } + }); + + this.expando = jQuery.expando + Math.random(); +} + +Data.uid = 1; + +Data.accepts = function( owner ) { + // Accepts only: + // - Node + // - Node.ELEMENT_NODE + // - Node.DOCUMENT_NODE + // - Object + // - Any + return owner.nodeType ? + owner.nodeType === 1 || owner.nodeType === 9 : true; +}; + +Data.prototype = { + key: function( owner ) { + // We can accept data for non-element nodes in modern browsers, + // but we should not, see #8335. + // Always return the key for a frozen object. + if ( !Data.accepts( owner ) ) { + return 0; + } + + var descriptor = {}, + // Check if the owner object already has a cache key + unlock = owner[ this.expando ]; + + // If not, create one + if ( !unlock ) { + unlock = Data.uid++; + + // Secure it in a non-enumerable, non-writable property + try { + descriptor[ this.expando ] = { value: unlock }; + Object.defineProperties( owner, descriptor ); + + // Support: Android < 4 + // Fallback to a less secure definition + } catch ( e ) { + descriptor[ this.expando ] = unlock; + jQuery.extend( owner, descriptor ); + } + } + + // Ensure the cache object + if ( !this.cache[ unlock ] ) { + this.cache[ unlock ] = {}; + } + + return unlock; + }, + set: function( owner, data, value ) { + var prop, + // There may be an unlock assigned to this node, + // if there is no entry for this "owner", create one inline + // and set the unlock as though an owner entry had always existed + unlock = this.key( owner ), + cache = this.cache[ unlock ]; + + // Handle: [ owner, key, value ] args + if ( typeof data === "string" ) { + cache[ data ] = value; + + // Handle: [ owner, { properties } ] args + } else { + // Fresh assignments by object are shallow copied + if ( jQuery.isEmptyObject( cache ) ) { + jQuery.extend( this.cache[ unlock ], data ); + // Otherwise, copy the properties one-by-one to the cache object + } else { + for ( prop in data ) { + cache[ prop ] = data[ prop ]; + } + } + } + return cache; + }, + get: function( owner, key ) { + // Either a valid cache is found, or will be created. + // New caches will be created and the unlock returned, + // allowing direct access to the newly created + // empty data object. A valid owner object must be provided. + var cache = this.cache[ this.key( owner ) ]; + + return key === undefined ? + cache : cache[ key ]; + }, + access: function( owner, key, value ) { + var stored; + // In cases where either: + // + // 1. No key was specified + // 2. A string key was specified, but no value provided + // + // Take the "read" path and allow the get method to determine + // which value to return, respectively either: + // + // 1. The entire cache object + // 2. The data stored at the key + // + if ( key === undefined || + ((key && typeof key === "string") && value === undefined) ) { + + stored = this.get( owner, key ); + + return stored !== undefined ? + stored : this.get( owner, jQuery.camelCase(key) ); + } + + // [*]When the key is not a string, or both a key and value + // are specified, set or extend (existing objects) with either: + // + // 1. An object of properties + // 2. A key and value + // + this.set( owner, key, value ); + + // Since the "set" path can have two possible entry points + // return the expected data based on which path was taken[*] + return value !== undefined ? value : key; + }, + remove: function( owner, key ) { + var i, name, camel, + unlock = this.key( owner ), + cache = this.cache[ unlock ]; + + if ( key === undefined ) { + this.cache[ unlock ] = {}; + + } else { + // Support array or space separated string of keys + if ( jQuery.isArray( key ) ) { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = key.concat( key.map( jQuery.camelCase ) ); + } else { + camel = jQuery.camelCase( key ); + // Try the string as a key before any manipulation + if ( key in cache ) { + name = [ key, camel ]; + } else { + // If a key with the spaces exists, use it. + // Otherwise, create an array by matching non-whitespace + name = camel; + name = name in cache ? + [ name ] : ( name.match( core_rnotwhite ) || [] ); + } + } + + i = name.length; + while ( i-- ) { + delete cache[ name[ i ] ]; + } + } + }, + hasData: function( owner ) { + return !jQuery.isEmptyObject( + this.cache[ owner[ this.expando ] ] || {} + ); + }, + discard: function( owner ) { + if ( owner[ this.expando ] ) { + delete this.cache[ owner[ this.expando ] ]; + } + } +}; + +// These may be used throughout the jQuery core codebase +data_user = new Data(); +data_priv = new Data(); + + +jQuery.extend({ + acceptData: Data.accepts, + + hasData: function( elem ) { + return data_user.hasData( elem ) || data_priv.hasData( elem ); + }, + + data: function( elem, name, data ) { + return data_user.access( elem, name, data ); + }, + + removeData: function( elem, name ) { + data_user.remove( elem, name ); + }, + + // TODO: Now that all calls to _data and _removeData have been replaced + // with direct calls to data_priv methods, these can be deprecated. + _data: function( elem, name, data ) { + return data_priv.access( elem, name, data ); + }, + + _removeData: function( elem, name ) { + data_priv.remove( elem, name ); + } +}); + +jQuery.fn.extend({ + data: function( key, value ) { + var attrs, name, + elem = this[ 0 ], + i = 0, + data = null; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = data_user.get( elem ); + + if ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) { + attrs = elem.attributes; + for ( ; i < attrs.length; i++ ) { + name = attrs[ i ].name; + + if ( name.indexOf( "data-" ) === 0 ) { + name = jQuery.camelCase( name.slice(5) ); + dataAttr( elem, name, data[ name ] ); + } + } + data_priv.set( elem, "hasDataAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + data_user.set( this, key ); + }); + } + + return jQuery.access( this, function( value ) { + var data, + camelKey = jQuery.camelCase( key ); + + // The calling jQuery object (element matches) is not empty + // (and therefore has an element appears at this[ 0 ]) and the + // `value` parameter was not undefined. An empty jQuery object + // will result in `undefined` for elem = this[ 0 ] which will + // throw an exception if an attempt to read a data cache is made. + if ( elem && value === undefined ) { + // Attempt to get data from the cache + // with the key as-is + data = data_user.get( elem, key ); + if ( data !== undefined ) { + return data; + } + + // Attempt to get data from the cache + // with the key camelized + data = data_user.get( elem, camelKey ); + if ( data !== undefined ) { + return data; + } + + // Attempt to "discover" the data in + // HTML5 custom data-* attrs + data = dataAttr( elem, camelKey, undefined ); + if ( data !== undefined ) { + return data; + } + + // We tried really hard, but the data doesn't exist. + return; + } + + // Set the data... + this.each(function() { + // First, attempt to store a copy or reference of any + // data that might've been store with a camelCased key. + var data = data_user.get( this, camelKey ); + + // For HTML5 data-* attribute interop, we have to + // store property names with dashes in a camelCase form. + // This might not apply to all properties...* + data_user.set( this, camelKey, value ); + + // *... In the case of properties that might _actually_ + // have dashes, we need to also store a copy of that + // unchanged property. + if ( key.indexOf("-") !== -1 && data !== undefined ) { + data_user.set( this, key, value ); + } + }); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each(function() { + data_user.remove( this, key ); + }); + } +}); + +function dataAttr( elem, key, data ) { + var name; + + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + +data + "" === data ? +data : + rbrace.test( data ) ? JSON.parse( data ) : + data; + } catch( e ) {} + + // Make sure we set the data so it isn't changed later + data_user.set( elem, key, data ); + } else { + data = undefined; + } + } + return data; +} diff --git a/hugo/js/jquery/src/jquery/deferred.js b/hugo/js/jquery/src/jquery/deferred.js new file mode 100644 index 0000000..0efc05d --- /dev/null +++ b/hugo/js/jquery/src/jquery/deferred.js @@ -0,0 +1,141 @@ +jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var action = tuple[ 0 ], + fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ ) { + var i = 0, + resolveValues = core_slice.call( arguments ), + length = resolveValues.length, + + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; + if( values === progressValues ) { + deferred.notifyWith( contexts, values ); + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } +}); diff --git a/hugo/js/jquery/src/jquery/deprecated.js b/hugo/js/jquery/src/jquery/deprecated.js new file mode 100644 index 0000000..40f8dd6 --- /dev/null +++ b/hugo/js/jquery/src/jquery/deprecated.js @@ -0,0 +1,11 @@ +// Limit scope pollution from any deprecated API +// (function() { + +// The number of elements contained in the matched element set +jQuery.fn.size = function() { + return this.length; +}; + +jQuery.fn.andSelf = jQuery.fn.addBack; + +// })(); diff --git a/hugo/js/jquery/src/jquery/dimensions.js b/hugo/js/jquery/src/jquery/dimensions.js new file mode 100644 index 0000000..ae59fb0 --- /dev/null +++ b/hugo/js/jquery/src/jquery/dimensions.js @@ -0,0 +1,41 @@ +// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods +jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { + jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) { + // margin is only for outerHeight, outerWidth + jQuery.fn[ funcName ] = function( margin, value ) { + var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ), + extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" ); + + return jQuery.access( this, function( elem, type, value ) { + var doc; + + if ( jQuery.isWindow( elem ) ) { + // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there + // isn't a whole lot we can do. See pull request at this URL for discussion: + // https://github.com/jquery/jquery/pull/764 + return elem.document.documentElement[ "client" + name ]; + } + + // Get document width or height + if ( elem.nodeType === 9 ) { + doc = elem.documentElement; + + // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], + // whichever is greatest + return Math.max( + elem.body[ "scroll" + name ], doc[ "scroll" + name ], + elem.body[ "offset" + name ], doc[ "offset" + name ], + doc[ "client" + name ] + ); + } + + return value === undefined ? + // Get width or height on the element, requesting but not forcing parseFloat + jQuery.css( elem, type, extra ) : + + // Set width or height on the element + jQuery.style( elem, type, value, extra ); + }, type, chainable ? margin : undefined, chainable, null ); + }; + }); +}); diff --git a/hugo/js/jquery/src/jquery/effects.js b/hugo/js/jquery/src/jquery/effects.js new file mode 100644 index 0000000..b0a9083 --- /dev/null +++ b/hugo/js/jquery/src/jquery/effects.js @@ -0,0 +1,730 @@ +var fxNow, timerId, + rfxtypes = /^(?:toggle|show|hide)$/, + rfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ), + rrun = /queueHooks$/, + animationPrefilters = [ defaultPrefilter ], + tweeners = { + "*": [function( prop, value ) { + var tween = this.createTween( prop, value ), + target = tween.cur(), + parts = rfxnum.exec( value ), + unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), + + // Starting value computation is required for potential unit mismatches + start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) && + rfxnum.exec( jQuery.css( tween.elem, prop ) ), + scale = 1, + maxIterations = 20; + + if ( start && start[ 3 ] !== unit ) { + // Trust units reported by jQuery.css + unit = unit || start[ 3 ]; + + // Make sure we update the tween properties later on + parts = parts || []; + + // Iteratively approximate from a nonzero starting point + start = +target || 1; + + do { + // If previous iteration zeroed out, double until we get *something* + // Use a string for doubling factor so we don't accidentally see scale as unchanged below + scale = scale || ".5"; + + // Adjust and apply + start = start / scale; + jQuery.style( tween.elem, prop, start + unit ); + + // Update scale, tolerating zero or NaN from tween.cur() + // And breaking the loop if scale is unchanged or perfect, or if we've just had enough + } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations ); + } + + // Update tween properties + if ( parts ) { + start = tween.start = +start || +target || 0; + tween.unit = unit; + // If a +=/-= token was provided, we're doing a relative animation + tween.end = parts[ 1 ] ? + start + ( parts[ 1 ] + 1 ) * parts[ 2 ] : + +parts[ 2 ]; + } + + return tween; + }] + }; + +// Animations created synchronously will run synchronously +function createFxNow() { + setTimeout(function() { + fxNow = undefined; + }); + return ( fxNow = jQuery.now() ); +} + +function createTween( value, prop, animation ) { + var tween, + collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ), + index = 0, + length = collection.length; + for ( ; index < length; index++ ) { + if ( (tween = collection[ index ].call( animation, prop, value )) ) { + + // we're done with this property + return tween; + } + } +} + +function Animation( elem, properties, options ) { + var result, + stopped, + index = 0, + length = animationPrefilters.length, + deferred = jQuery.Deferred().always( function() { + // don't match elem in the :animated selector + delete tick.elem; + }), + tick = function() { + if ( stopped ) { + return false; + } + var currentTime = fxNow || createFxNow(), + remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), + // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497) + temp = remaining / animation.duration || 0, + percent = 1 - temp, + index = 0, + length = animation.tweens.length; + + for ( ; index < length ; index++ ) { + animation.tweens[ index ].run( percent ); + } + + deferred.notifyWith( elem, [ animation, percent, remaining ]); + + if ( percent < 1 && length ) { + return remaining; + } else { + deferred.resolveWith( elem, [ animation ] ); + return false; + } + }, + animation = deferred.promise({ + elem: elem, + props: jQuery.extend( {}, properties ), + opts: jQuery.extend( true, { specialEasing: {} }, options ), + originalProperties: properties, + originalOptions: options, + startTime: fxNow || createFxNow(), + duration: options.duration, + tweens: [], + createTween: function( prop, end ) { + var tween = jQuery.Tween( elem, animation.opts, prop, end, + animation.opts.specialEasing[ prop ] || animation.opts.easing ); + animation.tweens.push( tween ); + return tween; + }, + stop: function( gotoEnd ) { + var index = 0, + // if we are going to the end, we want to run all the tweens + // otherwise we skip this part + length = gotoEnd ? animation.tweens.length : 0; + if ( stopped ) { + return this; + } + stopped = true; + for ( ; index < length ; index++ ) { + animation.tweens[ index ].run( 1 ); + } + + // resolve when we played the last frame + // otherwise, reject + if ( gotoEnd ) { + deferred.resolveWith( elem, [ animation, gotoEnd ] ); + } else { + deferred.rejectWith( elem, [ animation, gotoEnd ] ); + } + return this; + } + }), + props = animation.props; + + propFilter( props, animation.opts.specialEasing ); + + for ( ; index < length ; index++ ) { + result = animationPrefilters[ index ].call( animation, elem, props, animation.opts ); + if ( result ) { + return result; + } + } + + jQuery.map( props, createTween, animation ); + + if ( jQuery.isFunction( animation.opts.start ) ) { + animation.opts.start.call( elem, animation ); + } + + jQuery.fx.timer( + jQuery.extend( tick, { + elem: elem, + anim: animation, + queue: animation.opts.queue + }) + ); + + // attach callbacks from options + return animation.progress( animation.opts.progress ) + .done( animation.opts.done, animation.opts.complete ) + .fail( animation.opts.fail ) + .always( animation.opts.always ); +} + +function propFilter( props, specialEasing ) { + var index, name, easing, value, hooks; + + // camelCase, specialEasing and expand cssHook pass + for ( index in props ) { + name = jQuery.camelCase( index ); + easing = specialEasing[ name ]; + value = props[ index ]; + if ( jQuery.isArray( value ) ) { + easing = value[ 1 ]; + value = props[ index ] = value[ 0 ]; + } + + if ( index !== name ) { + props[ name ] = value; + delete props[ index ]; + } + + hooks = jQuery.cssHooks[ name ]; + if ( hooks && "expand" in hooks ) { + value = hooks.expand( value ); + delete props[ name ]; + + // not quite $.extend, this wont overwrite keys already present. + // also - reusing 'index' from above because we have the correct "name" + for ( index in value ) { + if ( !( index in props ) ) { + props[ index ] = value[ index ]; + specialEasing[ index ] = easing; + } + } + } else { + specialEasing[ name ] = easing; + } + } +} + +jQuery.Animation = jQuery.extend( Animation, { + + tweener: function( props, callback ) { + if ( jQuery.isFunction( props ) ) { + callback = props; + props = [ "*" ]; + } else { + props = props.split(" "); + } + + var prop, + index = 0, + length = props.length; + + for ( ; index < length ; index++ ) { + prop = props[ index ]; + tweeners[ prop ] = tweeners[ prop ] || []; + tweeners[ prop ].unshift( callback ); + } + }, + + prefilter: function( callback, prepend ) { + if ( prepend ) { + animationPrefilters.unshift( callback ); + } else { + animationPrefilters.push( callback ); + } + } +}); + +function defaultPrefilter( elem, props, opts ) { + /* jshint validthis: true */ + var prop, value, toggle, tween, hooks, oldfire, + anim = this, + orig = {}, + style = elem.style, + hidden = elem.nodeType && isHidden( elem ), + dataShow = data_priv.get( elem, "fxshow" ); + + // handle queue: false promises + if ( !opts.queue ) { + hooks = jQuery._queueHooks( elem, "fx" ); + if ( hooks.unqueued == null ) { + hooks.unqueued = 0; + oldfire = hooks.empty.fire; + hooks.empty.fire = function() { + if ( !hooks.unqueued ) { + oldfire(); + } + }; + } + hooks.unqueued++; + + anim.always(function() { + // doing this makes sure that the complete handler will be called + // before this completes + anim.always(function() { + hooks.unqueued--; + if ( !jQuery.queue( elem, "fx" ).length ) { + hooks.empty.fire(); + } + }); + }); + } + + // height/width overflow pass + if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) { + // Make sure that nothing sneaks out + // Record all 3 overflow attributes because IE9-10 do not + // change the overflow attribute when overflowX and + // overflowY are set to the same value + opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; + + // Set display property to inline-block for height/width + // animations on inline elements that are having width/height animated + if ( jQuery.css( elem, "display" ) === "inline" && + jQuery.css( elem, "float" ) === "none" ) { + + style.display = "inline-block"; + } + } + + if ( opts.overflow ) { + style.overflow = "hidden"; + anim.always(function() { + style.overflow = opts.overflow[ 0 ]; + style.overflowX = opts.overflow[ 1 ]; + style.overflowY = opts.overflow[ 2 ]; + }); + } + + + // show/hide pass + for ( prop in props ) { + value = props[ prop ]; + if ( rfxtypes.exec( value ) ) { + delete props[ prop ]; + toggle = toggle || value === "toggle"; + if ( value === ( hidden ? "hide" : "show" ) ) { + + // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden + if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) { + hidden = true; + } else { + continue; + } + } + orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop ); + } + } + + if ( !jQuery.isEmptyObject( orig ) ) { + if ( dataShow ) { + if ( "hidden" in dataShow ) { + hidden = dataShow.hidden; + } + } else { + dataShow = data_priv.access( elem, "fxshow", {} ); + } + + // store state if its toggle - enables .stop().toggle() to "reverse" + if ( toggle ) { + dataShow.hidden = !hidden; + } + if ( hidden ) { + jQuery( elem ).show(); + } else { + anim.done(function() { + jQuery( elem ).hide(); + }); + } + anim.done(function() { + var prop; + + data_priv.remove( elem, "fxshow" ); + for ( prop in orig ) { + jQuery.style( elem, prop, orig[ prop ] ); + } + }); + for ( prop in orig ) { + tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim ); + + if ( !( prop in dataShow ) ) { + dataShow[ prop ] = tween.start; + if ( hidden ) { + tween.end = tween.start; + tween.start = prop === "width" || prop === "height" ? 1 : 0; + } + } + } + } +} + +function Tween( elem, options, prop, end, easing ) { + return new Tween.prototype.init( elem, options, prop, end, easing ); +} +jQuery.Tween = Tween; + +Tween.prototype = { + constructor: Tween, + init: function( elem, options, prop, end, easing, unit ) { + this.elem = elem; + this.prop = prop; + this.easing = easing || "swing"; + this.options = options; + this.start = this.now = this.cur(); + this.end = end; + this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); + }, + cur: function() { + var hooks = Tween.propHooks[ this.prop ]; + + return hooks && hooks.get ? + hooks.get( this ) : + Tween.propHooks._default.get( this ); + }, + run: function( percent ) { + var eased, + hooks = Tween.propHooks[ this.prop ]; + + if ( this.options.duration ) { + this.pos = eased = jQuery.easing[ this.easing ]( + percent, this.options.duration * percent, 0, 1, this.options.duration + ); + } else { + this.pos = eased = percent; + } + this.now = ( this.end - this.start ) * eased + this.start; + + if ( this.options.step ) { + this.options.step.call( this.elem, this.now, this ); + } + + if ( hooks && hooks.set ) { + hooks.set( this ); + } else { + Tween.propHooks._default.set( this ); + } + return this; + } +}; + +Tween.prototype.init.prototype = Tween.prototype; + +Tween.propHooks = { + _default: { + get: function( tween ) { + var result; + + if ( tween.elem[ tween.prop ] != null && + (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) { + return tween.elem[ tween.prop ]; + } + + // passing an empty string as a 3rd parameter to .css will automatically + // attempt a parseFloat and fallback to a string if the parse fails + // so, simple values such as "10px" are parsed to Float. + // complex values such as "rotate(1rad)" are returned as is. + result = jQuery.css( tween.elem, tween.prop, "" ); + // Empty strings, null, undefined and "auto" are converted to 0. + return !result || result === "auto" ? 0 : result; + }, + set: function( tween ) { + // use step hook for back compat - use cssHook if its there - use .style if its + // available and use plain properties where available + if ( jQuery.fx.step[ tween.prop ] ) { + jQuery.fx.step[ tween.prop ]( tween ); + } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) { + jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); + } else { + tween.elem[ tween.prop ] = tween.now; + } + } + } +}; + +// Support: IE9 +// Panic based approach to setting things on disconnected nodes + +Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { + set: function( tween ) { + if ( tween.elem.nodeType && tween.elem.parentNode ) { + tween.elem[ tween.prop ] = tween.now; + } + } +}; + +jQuery.each([ "toggle", "show", "hide" ], function( i, name ) { + var cssFn = jQuery.fn[ name ]; + jQuery.fn[ name ] = function( speed, easing, callback ) { + return speed == null || typeof speed === "boolean" ? + cssFn.apply( this, arguments ) : + this.animate( genFx( name, true ), speed, easing, callback ); + }; +}); + +jQuery.fn.extend({ + fadeTo: function( speed, to, easing, callback ) { + + // show any hidden elements after setting opacity to 0 + return this.filter( isHidden ).css( "opacity", 0 ).show() + + // animate to the value specified + .end().animate({ opacity: to }, speed, easing, callback ); + }, + animate: function( prop, speed, easing, callback ) { + var empty = jQuery.isEmptyObject( prop ), + optall = jQuery.speed( speed, easing, callback ), + doAnimation = function() { + // Operate on a copy of prop so per-property easing won't be lost + var anim = Animation( this, jQuery.extend( {}, prop ), optall ); + + // Empty animations, or finishing resolves immediately + if ( empty || data_priv.get( this, "finish" ) ) { + anim.stop( true ); + } + }; + doAnimation.finish = doAnimation; + + return empty || optall.queue === false ? + this.each( doAnimation ) : + this.queue( optall.queue, doAnimation ); + }, + stop: function( type, clearQueue, gotoEnd ) { + var stopQueue = function( hooks ) { + var stop = hooks.stop; + delete hooks.stop; + stop( gotoEnd ); + }; + + if ( typeof type !== "string" ) { + gotoEnd = clearQueue; + clearQueue = type; + type = undefined; + } + if ( clearQueue && type !== false ) { + this.queue( type || "fx", [] ); + } + + return this.each(function() { + var dequeue = true, + index = type != null && type + "queueHooks", + timers = jQuery.timers, + data = data_priv.get( this ); + + if ( index ) { + if ( data[ index ] && data[ index ].stop ) { + stopQueue( data[ index ] ); + } + } else { + for ( index in data ) { + if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { + stopQueue( data[ index ] ); + } + } + } + + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) { + timers[ index ].anim.stop( gotoEnd ); + dequeue = false; + timers.splice( index, 1 ); + } + } + + // start the next in the queue if the last step wasn't forced + // timers currently will call their complete callbacks, which will dequeue + // but only if they were gotoEnd + if ( dequeue || !gotoEnd ) { + jQuery.dequeue( this, type ); + } + }); + }, + finish: function( type ) { + if ( type !== false ) { + type = type || "fx"; + } + return this.each(function() { + var index, + data = data_priv.get( this ), + queue = data[ type + "queue" ], + hooks = data[ type + "queueHooks" ], + timers = jQuery.timers, + length = queue ? queue.length : 0; + + // enable finishing flag on private data + data.finish = true; + + // empty the queue first + jQuery.queue( this, type, [] ); + + if ( hooks && hooks.stop ) { + hooks.stop.call( this, true ); + } + + // look for any active animations, and finish them + for ( index = timers.length; index--; ) { + if ( timers[ index ].elem === this && timers[ index ].queue === type ) { + timers[ index ].anim.stop( true ); + timers.splice( index, 1 ); + } + } + + // look for any animations in the old queue and finish them + for ( index = 0; index < length; index++ ) { + if ( queue[ index ] && queue[ index ].finish ) { + queue[ index ].finish.call( this ); + } + } + + // turn off finishing flag + delete data.finish; + }); + } +}); + +// Generate parameters to create a standard animation +function genFx( type, includeWidth ) { + var which, + attrs = { height: type }, + i = 0; + + // if we include width, step value is 1 to do all cssExpand values, + // if we don't include width, step value is 2 to skip over Left and Right + includeWidth = includeWidth? 1 : 0; + for( ; i < 4 ; i += 2 - includeWidth ) { + which = cssExpand[ i ]; + attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; + } + + if ( includeWidth ) { + attrs.opacity = attrs.width = type; + } + + return attrs; +} + +// Generate shortcuts for custom animations +jQuery.each({ + slideDown: genFx("show"), + slideUp: genFx("hide"), + slideToggle: genFx("toggle"), + fadeIn: { opacity: "show" }, + fadeOut: { opacity: "hide" }, + fadeToggle: { opacity: "toggle" } +}, function( name, props ) { + jQuery.fn[ name ] = function( speed, easing, callback ) { + return this.animate( props, speed, easing, callback ); + }; +}); + +jQuery.speed = function( speed, easing, fn ) { + var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { + complete: fn || !fn && easing || + jQuery.isFunction( speed ) && speed, + duration: speed, + easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing + }; + + opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : + opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default; + + // normalize opt.queue - true/undefined/null -> "fx" + if ( opt.queue == null || opt.queue === true ) { + opt.queue = "fx"; + } + + // Queueing + opt.old = opt.complete; + + opt.complete = function() { + if ( jQuery.isFunction( opt.old ) ) { + opt.old.call( this ); + } + + if ( opt.queue ) { + jQuery.dequeue( this, opt.queue ); + } + }; + + return opt; +}; + +jQuery.easing = { + linear: function( p ) { + return p; + }, + swing: function( p ) { + return 0.5 - Math.cos( p*Math.PI ) / 2; + } +}; + +jQuery.timers = []; +jQuery.fx = Tween.prototype.init; +jQuery.fx.tick = function() { + var timer, + timers = jQuery.timers, + i = 0; + + fxNow = jQuery.now(); + + for ( ; i < timers.length; i++ ) { + timer = timers[ i ]; + // Checks the timer has not already been removed + if ( !timer() && timers[ i ] === timer ) { + timers.splice( i--, 1 ); + } + } + + if ( !timers.length ) { + jQuery.fx.stop(); + } + fxNow = undefined; +}; + +jQuery.fx.timer = function( timer ) { + if ( timer() && jQuery.timers.push( timer ) ) { + jQuery.fx.start(); + } +}; + +jQuery.fx.interval = 13; + +jQuery.fx.start = function() { + if ( !timerId ) { + timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval ); + } +}; + +jQuery.fx.stop = function() { + clearInterval( timerId ); + timerId = null; +}; + +jQuery.fx.speeds = { + slow: 600, + fast: 200, + // Default speed + _default: 400 +}; + +// Back Compat <1.8 extension point +jQuery.fx.step = {}; + +if ( jQuery.expr && jQuery.expr.filters ) { + jQuery.expr.filters.animated = function( elem ) { + return jQuery.grep(jQuery.timers, function( fn ) { + return elem === fn.elem; + }).length; + }; +} diff --git a/hugo/js/jquery/src/jquery/event-alias.js b/hugo/js/jquery/src/jquery/event-alias.js new file mode 100644 index 0000000..b1a15e8 --- /dev/null +++ b/hugo/js/jquery/src/jquery/event-alias.js @@ -0,0 +1,32 @@ +jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + + "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { + + // Handle event binding + jQuery.fn[ name ] = function( data, fn ) { + return arguments.length > 0 ? + this.on( name, null, data, fn ) : + this.trigger( name ); + }; +}); + +jQuery.fn.extend({ + hover: function( fnOver, fnOut ) { + return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + }, + + bind: function( types, data, fn ) { + return this.on( types, null, data, fn ); + }, + unbind: function( types, fn ) { + return this.off( types, null, fn ); + }, + + delegate: function( selector, types, data, fn ) { + return this.on( types, selector, data, fn ); + }, + undelegate: function( selector, types, fn ) { + // ( namespace ) or ( selector, types [, fn] ) + return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); + } +}); diff --git a/hugo/js/jquery/src/jquery/event.js b/hugo/js/jquery/src/jquery/event.js new file mode 100644 index 0000000..9262d1d --- /dev/null +++ b/hugo/js/jquery/src/jquery/event.js @@ -0,0 +1,829 @@ +var rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + +function returnTrue() { + return true; +} + +function returnFalse() { + return false; +} + +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + +/* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ +jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + + var handleObjIn, eventHandle, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = data_priv.get( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // There *must* be a type, no attaching namespace-only handlers + if ( !type ) { + continue; + } + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + + var j, origCount, tmp, + events, t, handleObj, + special, handlers, type, namespaces, origType, + elemData = data_priv.hasData( elem ) && data_priv.get( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + data_priv.remove( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + + var i, cur, tmp, bubbleType, ontype, handle, special, + eventPath = [ elem || document ], + type = core_hasOwn.call( event, "type" ) ? event.type : event, + namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true) + event.isTrigger = onlyHandlers ? 2 : 3; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) && + jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + elem[ type ](); + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, j, ret, matched, handleObj, + handlerQueue = [], + args = core_slice.call( arguments ), + handlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var i, matches, sel, handleObj, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG <use> instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + for ( ; cur !== this; cur = cur.parentNode || this ) { + + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.disabled !== true || event.type !== "click" ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ elem: cur, handlers: matches }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) }); + } + + return handlerQueue; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), + + fixHooks: {}, + + keyHooks: { + props: "char charCode key keyCode".split(" "), + filter: function( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var eventDoc, doc, body, + button = original.button; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: Cordova 2.5 (WebKit) (#13255) + // All events should have a target; Cordova deviceready doesn't + if ( !event.target ) { + event.target = document; + } + + // Support: Safari 6.0+, Chrome < 28 + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + return fixHook.filter? fixHook.filter( event, originalEvent ) : event; + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== safeActiveElement() && this.focus ) { + this.focus(); + return false; + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === safeActiveElement() && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) { + this.click(); + return false; + } + }, + + // For cross-browser consistency, don't fire native .click() on links + _default: function( event ) { + return jQuery.nodeName( event.target, "a" ); + } + }, + + beforeunload: { + postDispatch: function( event ) { + + // Support: Firefox 20+ + // Firefox doesn't alert if the returnValue field is not set. + if ( event.result !== undefined ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true, + originalEvent: {} + } + ); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } +}; + +jQuery.removeEvent = function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } +}; + +jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; +}; + +// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding +// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html +jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + + if ( e && e.preventDefault ) { + e.preventDefault(); + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + + if ( e && e.stopPropagation ) { + e.stopPropagation(); + } + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + } +}; + +// Create mouseenter/leave events using mouseover/out and event-time checks +// Support: Chrome 15+ +jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" +}, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; +}); + +// Create "bubbling" focus and blur events +// Support: Firefox, Chrome, Safari +if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); +} + +jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ one ) { + var origFn, type; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } +}); diff --git a/hugo/js/jquery/src/jquery/intro.js b/hugo/js/jquery/src/jquery/intro.js new file mode 100644 index 0000000..1d1640a --- /dev/null +++ b/hugo/js/jquery/src/jquery/intro.js @@ -0,0 +1,54 @@ +/*! + * jQuery JavaScript Library v@VERSION + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: @DATE + */ + +(function ( window, factory ) { + + if ( typeof module === "object" && typeof module.exports === "object" ) { + // Expose a jQuery-making factory as module.exports in loaders that implement the Node + // module pattern (including browserify). + // This accentuates the need for a real window in the environment + // e.g. var jQuery = require("jquery")(window); + module.exports = function( w ) { + w = w || window; + if ( !w.document ) { + throw new Error("jQuery requires a window with a document"); + } + return factory( w ); + }; + } else { + // Execute the factory to produce jQuery + var jQuery = factory( window ); + + // Register as a named AMD module, since jQuery can be concatenated with other + // files that may use define, but not via a proper concatenation script that + // understands anonymous AMD modules. A named AMD is safest and most robust + // way to register. Lowercase jquery is used because AMD module names are + // derived from file names, and jQuery is normally delivered in a lowercase + // file name. Do this after creating the global so that if an AMD module wants + // to call noConflict to hide this version of jQuery, it will work. + if ( typeof define === "function" && define.amd ) { + define( "jquery", [], function() { + return jQuery; + }); + } + } + +// Pass this, window may not be defined yet +}(this, function ( window ) { + +// Can't do this because several apps including ASP.NET trace +// the stack via arguments.caller.callee and Firefox dies if +// you try to trace through "use strict" call chains. (#13335) +// Support: Firefox 18+ +//"use strict"; diff --git a/hugo/js/jquery/src/jquery/manipulation.js b/hugo/js/jquery/src/jquery/manipulation.js new file mode 100644 index 0000000..19494ae --- /dev/null +++ b/hugo/js/jquery/src/jquery/manipulation.js @@ -0,0 +1,577 @@ +var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rhtml = /<|&#?\w+;/, + rnoInnerhtml = /<(?:script|style|link)/i, + manipulation_rcheckableType = /^(?:checkbox|radio)$/i, + // checked="checked" or checked + rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, + rscriptType = /^$|\/(?:java|ecma)script/i, + rscriptTypeMasked = /^true\/(.*)/, + rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g, + + // We have to close these tags to support XHTML (#13200) + wrapMap = { + + // Support: IE 9 + option: [ 1, "<select multiple='multiple'>", "</select>" ], + + thead: [ 1, "<table>", "</table>" ], + col: [ 2, "<table><colgroup>", "</colgroup></table>" ], + tr: [ 2, "<table><tbody>", "</tbody></table>" ], + td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ], + + _default: [ 0, "", "" ] + }; + +// Support: IE 9 +wrapMap.optgroup = wrapMap.option; + +wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; +wrapMap.th = wrapMap.td; + +jQuery.fn.extend({ + text: function( value ) { + return jQuery.access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[ 0 ] && this[ 0 ].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + append: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip( arguments, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + var target = manipulationTarget( this, elem ); + target.insertBefore( elem, target.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + var elem, + elems = selector ? jQuery.filter( selector, this ) : this, + i = 0; + + for ( ; (elem = elems[i]) != null; i++ ) { + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + if ( elem.nodeType === 1 ) { + + // Prevent memory leaks + jQuery.cleanData( getAll( elem, false ) ); + + // Remove any remaining nodes + elem.textContent = ""; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return jQuery.access( this, function( value ) { + var elem = this[ 0 ] || {}, + i = 0, + l = this.length; + + if ( value === undefined && elem.nodeType === 1 ) { + return elem.innerHTML; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1></$2>" ); + + try { + for ( ; i < l; i++ ) { + elem = this[ i ] || {}; + + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch( e ) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function() { + var + // Snapshot the DOM in case .domManip sweeps something relevant into its fragment + args = jQuery.map( this, function( elem ) { + return [ elem.nextSibling, elem.parentNode ]; + }), + i = 0; + + // Make the changes, replacing each context element with the new content + this.domManip( arguments, function( elem ) { + var next = args[ i++ ], + parent = args[ i++ ]; + + if ( parent ) { + // Don't use the snapshot next if it has moved (#13810) + if ( next && next.parentNode !== parent ) { + next = this.nextSibling; + } + jQuery( this ).remove(); + parent.insertBefore( elem, next ); + } + // Allow new content to include elements from the context set + }, true ); + + // Force removal if there was no new content (e.g., from empty arguments) + return i ? this : this.remove(); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, callback, allowIntersection ) { + + // Flatten any nested arrays + args = core_concat.apply( [], args ); + + var fragment, first, scripts, hasScripts, node, doc, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[ 0 ], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[ 0 ] = value.call( this, index, self.html() ); + } + self.domManip( args, callback, allowIntersection ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + // Support: QtWebKit + // jQuery.merge because core_push.apply(_, arraylike) throws + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( this[ i ], node, i ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Hope ajax is available... + jQuery._evalUrl( node.src ); + } else { + jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) ); + } + } + } + } + } + } + + return this; + } +}); + +jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" +}, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1, + i = 0; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone( true ); + jQuery( insert[ i ] )[ original ]( elems ); + + // Support: QtWebKit + // .get() because core_push.apply(_, arraylike) throws + core_push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; +}); + +jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var i, l, srcElements, destElements, + clone = elem.cloneNode( true ), + inPage = jQuery.contains( elem.ownerDocument, elem ); + + // Support: IE >= 9 + // Fix Cloning issues + if ( !jQuery.support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && !jQuery.isXMLDoc( elem ) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + fixInput( srcElements[ i ], destElements[ i ] ); + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0, l = srcElements.length; i < l; i++ ) { + cloneCopyEvent( srcElements[ i ], destElements[ i ] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var elem, tmp, tag, wrap, contains, j, + i = 0, + l = elems.length, + fragment = context.createDocumentFragment(), + nodes = []; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + // Support: QtWebKit + // jQuery.merge because core_push.apply(_, arraylike) throws + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || fragment.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || ["", ""] )[ 1 ].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + tmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[ 2 ]; + + // Descend through wrappers to the right content + j = wrap[ 0 ]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Support: QtWebKit + // jQuery.merge because core_push.apply(_, arraylike) throws + jQuery.merge( nodes, tmp.childNodes ); + + // Remember the top-level container + tmp = fragment.firstChild; + + // Fixes #12346 + // Support: Webkit, IE + tmp.textContent = ""; + } + } + } + + // Remove wrapper from fragment + fragment.textContent = ""; + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== -1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( fragment.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + return fragment; + }, + + cleanData: function( elems ) { + var data, elem, events, type, key, j, + special = jQuery.event.special, + i = 0; + + for ( ; (elem = elems[ i ]) !== undefined; i++ ) { + if ( Data.accepts( elem ) ) { + key = elem[ data_priv.expando ]; + + if ( key && (data = data_priv.cache[ key ]) ) { + events = Object.keys( data.events || {} ); + if ( events.length ) { + for ( j = 0; (type = events[j]) !== undefined; j++ ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + if ( data_priv.cache[ key ] ) { + // Discard any remaining `private` data + delete data_priv.cache[ key ]; + } + } + } + // Discard any remaining `user` data + delete data_user.cache[ elem[ data_user.expando ] ]; + } + }, + + _evalUrl: function( url ) { + return jQuery.ajax({ + url: url, + type: "GET", + dataType: "script", + async: false, + global: false, + "throws": true + }); + } +}); + +// Support: 1.x compatibility +// Manipulating tables requires a tbody +function manipulationTarget( elem, content ) { + return jQuery.nodeName( elem, "table" ) && + jQuery.nodeName( content.nodeType === 1 ? content : content.firstChild, "tr" ) ? + + elem.getElementsByTagName("tbody")[0] || + elem.appendChild( elem.ownerDocument.createElement("tbody") ) : + elem; +} + +// Replace/restore the type attribute of script elements for safe DOM manipulation +function disableScript( elem ) { + elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type; + return elem; +} +function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + + if ( match ) { + elem.type = match[ 1 ]; + } else { + elem.removeAttribute("type"); + } + + return elem; +} + +// Mark scripts as having already been evaluated +function setGlobalEval( elems, refElements ) { + var l = elems.length, + i = 0; + + for ( ; i < l; i++ ) { + data_priv.set( + elems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" ) + ); + } +} + +function cloneCopyEvent( src, dest ) { + var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events; + + if ( dest.nodeType !== 1 ) { + return; + } + + // 1. Copy private data: events, handlers, etc. + if ( data_priv.hasData( src ) ) { + pdataOld = data_priv.access( src ); + pdataCur = data_priv.set( dest, pdataOld ); + events = pdataOld.events; + + if ( events ) { + delete pdataCur.handle; + pdataCur.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + } + + // 2. Copy user data + if ( data_user.hasData( src ) ) { + udataOld = data_user.access( src ); + udataCur = jQuery.extend( {}, udataOld ); + + data_user.set( dest, udataCur ); + } +} + + +function getAll( context, tag ) { + var ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) : + context.querySelectorAll ? context.querySelectorAll( tag || "*" ) : + []; + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], ret ) : + ret; +} + +// Support: IE >= 9 +function fixInput( src, dest ) { + var nodeName = dest.nodeName.toLowerCase(); + + // Fails to persist the checked state of a cloned checkbox or radio button. + if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { + dest.checked = src.checked; + + // Fails to return the selected option to the default selected state when cloning options + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } +} diff --git a/hugo/js/jquery/src/jquery/offset.js b/hugo/js/jquery/src/jquery/offset.js new file mode 100644 index 0000000..b616a49 --- /dev/null +++ b/hugo/js/jquery/src/jquery/offset.js @@ -0,0 +1,167 @@ +jQuery.fn.offset = function( options ) { + if ( arguments.length ) { + return options === undefined ? + this : + this.each(function( i ) { + jQuery.offset.setOffset( this, options, i ); + }); + } + + var docElem, win, + elem = this[ 0 ], + box = { top: 0, left: 0 }, + doc = elem && elem.ownerDocument; + + if ( !doc ) { + return; + } + + docElem = doc.documentElement; + + // Make sure it's not a disconnected DOM node + if ( !jQuery.contains( docElem, elem ) ) { + return box; + } + + // If we don't have gBCR, just use 0,0 rather than error + // BlackBerry 5, iOS 3 (original iPhone) + if ( typeof elem.getBoundingClientRect !== core_strundefined ) { + box = elem.getBoundingClientRect(); + } + win = getWindow( doc ); + return { + top: box.top + win.pageYOffset - docElem.clientTop, + left: box.left + win.pageXOffset - docElem.clientLeft + }; +}; + +jQuery.offset = { + + setOffset: function( elem, options, i ) { + var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition, + position = jQuery.css( elem, "position" ), + curElem = jQuery( elem ), + props = {}; + + // Set position first, in-case top/left are set even on static elem + if ( position === "static" ) { + elem.style.position = "relative"; + } + + curOffset = curElem.offset(); + curCSSTop = jQuery.css( elem, "top" ); + curCSSLeft = jQuery.css( elem, "left" ); + calculatePosition = ( position === "absolute" || position === "fixed" ) && ( curCSSTop + curCSSLeft ).indexOf("auto") > -1; + + // Need to be able to calculate position if either top or left is auto and position is either absolute or fixed + if ( calculatePosition ) { + curPosition = curElem.position(); + curTop = curPosition.top; + curLeft = curPosition.left; + + } else { + curTop = parseFloat( curCSSTop ) || 0; + curLeft = parseFloat( curCSSLeft ) || 0; + } + + if ( jQuery.isFunction( options ) ) { + options = options.call( elem, i, curOffset ); + } + + if ( options.top != null ) { + props.top = ( options.top - curOffset.top ) + curTop; + } + if ( options.left != null ) { + props.left = ( options.left - curOffset.left ) + curLeft; + } + + if ( "using" in options ) { + options.using.call( elem, props ); + + } else { + curElem.css( props ); + } + } +}; + + +jQuery.fn.extend({ + + position: function() { + if ( !this[ 0 ] ) { + return; + } + + var offsetParent, offset, + elem = this[ 0 ], + parentOffset = { top: 0, left: 0 }; + + // Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it's only offset parent + if ( jQuery.css( elem, "position" ) === "fixed" ) { + // We assume that getBoundingClientRect is available when computed position is fixed + offset = elem.getBoundingClientRect(); + + } else { + // Get *real* offsetParent + offsetParent = this.offsetParent(); + + // Get correct offsets + offset = this.offset(); + if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) { + parentOffset = offsetParent.offset(); + } + + // Add offsetParent borders + parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ); + parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true ); + } + + // Subtract parent offsets and element margins + return { + top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ), + left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true ) + }; + }, + + offsetParent: function() { + return this.map(function() { + var offsetParent = this.offsetParent || docElem; + + while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) { + offsetParent = offsetParent.offsetParent; + } + + return offsetParent || docElem; + }); + } +}); + + +// Create scrollLeft and scrollTop methods +jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) { + var top = "pageYOffset" === prop; + + jQuery.fn[ method ] = function( val ) { + return jQuery.access( this, function( elem, method, val ) { + var win = getWindow( elem ); + + if ( val === undefined ) { + return win ? win[ prop ] : elem[ method ]; + } + + if ( win ) { + win.scrollTo( + !top ? val : window.pageXOffset, + top ? val : window.pageYOffset + ); + + } else { + elem[ method ] = val; + } + }, method, val, arguments.length, null ); + }; +}); + +function getWindow( elem ) { + return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView; +} diff --git a/hugo/js/jquery/src/jquery/outro.js b/hugo/js/jquery/src/jquery/outro.js new file mode 100644 index 0000000..20cec43 --- /dev/null +++ b/hugo/js/jquery/src/jquery/outro.js @@ -0,0 +1,6 @@ +// Expose jQuery and $ identifiers, even in +// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557) +// and CommonJS for browser emulators (#13566) +return (window.jQuery = window.$ = jQuery); + +})); diff --git a/hugo/js/jquery/src/jquery/queue.js b/hugo/js/jquery/src/jquery/queue.js new file mode 100644 index 0000000..1297bc1 --- /dev/null +++ b/hugo/js/jquery/src/jquery/queue.js @@ -0,0 +1,145 @@ +jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = data_priv.get( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray( data ) ) { + queue = data_priv.access( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return data_priv.get( elem, key ) || data_priv.access( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + data_priv.remove( elem, [ type + "queue", key ] ); + }) + }); + } +}); + +jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while( i-- ) { + tmp = data_priv.get( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } +}); diff --git a/hugo/js/jquery/src/jquery/selector-native.js b/hugo/js/jquery/src/jquery/selector-native.js new file mode 100644 index 0000000..58a0cec --- /dev/null +++ b/hugo/js/jquery/src/jquery/selector-native.js @@ -0,0 +1,164 @@ +/* + * Optional (non-Sizzle) selector module for custom builds. + * + * Note that this DOES NOT SUPPORT many documented jQuery + * features in exchange for its smaller size: + * + * Attribute not equal selector + * Positional selectors (:first; :eq(n); :odd; etc.) + * Type selectors (:input; :checkbox; :button; etc.) + * State-based selectors (:animated; :visible; :hidden; etc.) + * :has(selector) + * :not(complex selector) + * custom selectors via Sizzle extensions + * Leading combinators (e.g., $collection.find("> *")) + * Reliable functionality on XML fragments + * Requiring all parts of a selector to match elements under context + * (e.g., $div.find("div > *") now matches children of $div) + * Matching against non-elements + * Reliable sorting of disconnected nodes + * querySelectorAll bug fixes (e.g., unreliable :focus on WebKit) + * + * If any of these are unacceptable tradeoffs, either use Sizzle or + * customize this stub for the project's specific needs. + */ + +var selector_hasDuplicate, + matches = docElem.webkitMatchesSelector || + docElem.mozMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector, + selector_sortOrder = function( a, b ) { + // Flag for duplicate removal + if ( a === b ) { + selector_hasDuplicate = true; + return 0; + } + + var compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b ); + + if ( compare ) { + // Disconnected nodes + if ( compare & 1 ) { + + // Choose the first element that is related to our document + if ( a === document || jQuery.contains(document, a) ) { + return -1; + } + if ( b === document || jQuery.contains(document, b) ) { + return 1; + } + + // Maintain original order + return 0; + } + + return compare & 4 ? -1 : 1; + } + + // Not directly comparable, sort on existence of method + return a.compareDocumentPosition ? -1 : 1; + }; + +jQuery.extend({ + find: function( selector, context, results, seed ) { + var elem, nodeType, + i = 0; + + results = results || []; + context = context || document; + + // Same basic safeguard as Sizzle + if ( !selector || typeof selector !== "string" ) { + return results; + } + + // Early return if context is not an element or document + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( seed ) { + while ( (elem = seed[i++]) ) { + if ( jQuery.find.matchesSelector(elem, selector) ) { + results.push( elem ); + } + } + } else { + jQuery.merge( results, context.querySelectorAll(selector) ); + } + + return results; + }, + unique: function( results ) { + var elem, + duplicates = [], + i = 0, + j = 0; + + selector_hasDuplicate = false; + results.sort( selector_sortOrder ); + + if ( selector_hasDuplicate ) { + while ( (elem = results[i++]) ) { + if ( elem === results[ i ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + return results; + }, + text: function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + while ( (node = elem[i++]) ) { + // Do not traverse comment nodes + ret += jQuery.text( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + return elem.textContent; + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; + }, + contains: function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && adown.contains(bup) ); + }, + isXMLDoc: function( elem ) { + return (elem.ownerDocument || elem).documentElement.nodeName !== "HTML"; + }, + expr: { + attrHandle: {}, + match: { + bool: /^(?:checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped)$/i, + needsContext: /^[\x20\t\r\n\f]*[>+~]/ + } + } +}); + +jQuery.extend( jQuery.find, { + matches: function( expr, elements ) { + return jQuery.find( expr, null, null, elements ); + }, + matchesSelector: function( elem, expr ) { + return matches.call( elem, expr ); + }, + attr: function( elem, name ) { + return elem.getAttribute( name ); + } +}); diff --git a/hugo/js/jquery/src/jquery/serialize.js b/hugo/js/jquery/src/jquery/serialize.js new file mode 100644 index 0000000..65dee40 --- /dev/null +++ b/hugo/js/jquery/src/jquery/serialize.js @@ -0,0 +1,99 @@ +var r20 = /%20/g, + rbracket = /\[\]$/, + rCRLF = /\r?\n/g, + rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, + rsubmittable = /^(?:input|select|textarea|keygen)/i; + +jQuery.fn.extend({ + serialize: function() { + return jQuery.param( this.serializeArray() ); + }, + serializeArray: function() { + return this.map(function(){ + // Can add propHook for "elements" to filter or add form elements + var elements = jQuery.prop( this, "elements" ); + return elements ? jQuery.makeArray( elements ) : this; + }) + .filter(function(){ + var type = this.type; + // Use .is(":disabled") so that fieldset[disabled] works + return this.name && !jQuery( this ).is( ":disabled" ) && + rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) && + ( this.checked || !manipulation_rcheckableType.test( type ) ); + }) + .map(function( i, elem ){ + var val = jQuery( this ).val(); + + return val == null ? + null : + jQuery.isArray( val ) ? + jQuery.map( val, function( val ){ + return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + }) : + { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; + }).get(); + } +}); + +//Serialize an array of form elements or a set of +//key/values into a query string +jQuery.param = function( a, traditional ) { + var prefix, + s = [], + add = function( key, value ) { + // If value is a function, invoke it and return its value + value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value ); + s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); + }; + + // Set traditional to true for jQuery <= 1.3.2 behavior. + if ( traditional === undefined ) { + traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional; + } + + // If an array was passed in, assume that it is an array of form elements. + if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { + // Serialize the form elements + jQuery.each( a, function() { + add( this.name, this.value ); + }); + + } else { + // If traditional, encode the "old" way (the way 1.3.2 or older + // did it), otherwise encode params recursively. + for ( prefix in a ) { + buildParams( prefix, a[ prefix ], traditional, add ); + } + } + + // Return the resulting serialization + return s.join( "&" ).replace( r20, "+" ); +}; + +function buildParams( prefix, obj, traditional, add ) { + var name; + + if ( jQuery.isArray( obj ) ) { + // Serialize array item. + jQuery.each( obj, function( i, v ) { + if ( traditional || rbracket.test( prefix ) ) { + // Treat each array item as a scalar. + add( prefix, v ); + + } else { + // Item is non-scalar (array or object), encode its numeric index. + buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add ); + } + }); + + } else if ( !traditional && jQuery.type( obj ) === "object" ) { + // Serialize object item. + for ( name in obj ) { + buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); + } + + } else { + // Serialize scalar item. + add( prefix, obj ); + } +} diff --git a/hugo/js/jquery/src/jquery/sizzle-jquery.js b/hugo/js/jquery/src/jquery/sizzle-jquery.js new file mode 100644 index 0000000..fa31965 --- /dev/null +++ b/hugo/js/jquery/src/jquery/sizzle-jquery.js @@ -0,0 +1,7 @@ +jQuery.find = Sizzle; +jQuery.expr = Sizzle.selectors; +jQuery.expr[":"] = jQuery.expr.pseudos; +jQuery.unique = Sizzle.uniqueSort; +jQuery.text = Sizzle.getText; +jQuery.isXMLDoc = Sizzle.isXML; +jQuery.contains = Sizzle.contains; diff --git a/hugo/js/jquery/src/jquery/support.js b/hugo/js/jquery/src/jquery/support.js new file mode 100644 index 0000000..e46588d --- /dev/null +++ b/hugo/js/jquery/src/jquery/support.js @@ -0,0 +1,113 @@ +jQuery.support = (function( support ) { + var input = document.createElement("input"), + fragment = document.createDocumentFragment(), + div = document.createElement("div"), + select = document.createElement("select"), + opt = select.appendChild( document.createElement("option") ); + + // Finish early in limited environments + if ( !input.type ) { + return support; + } + + input.type = "checkbox"; + + // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3 + // Check the default checkbox/radio value ("" on old WebKit; "on" elsewhere) + support.checkOn = input.value !== ""; + + // Must access the parent to make an option select properly + // Support: IE9, IE10 + support.optSelected = opt.selected; + + // Will be defined later + support.reliableMarginRight = true; + support.boxSizingReliable = true; + support.pixelPosition = false; + + // Make sure checked status is properly cloned + // Support: IE9, IE10 + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Check if an input maintains its value after becoming a radio + // Support: IE9, IE10 + input = document.createElement("input"); + input.value = "t"; + input.type = "radio"; + support.radioValue = input.value === "t"; + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "checked", "t" ); + input.setAttribute( "name", "t" ); + + fragment.appendChild( input ); + + // Support: Safari 5.1, Android 4.x, Android 2.3 + // old WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: Firefox, Chrome, Safari + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP) + support.focusinBubbles = "onfocusin" in window; + + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, marginDiv, + // Support: Firefox, Android 2.3 (Prefixed box-sizing versions). + divReset = "padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box", + body = document.getElementsByTagName("body")[ 0 ]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + container = document.createElement("div"); + container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px"; + + // Check box-sizing and margin behavior. + body.appendChild( container ).appendChild( div ); + div.innerHTML = ""; + // Support: Firefox, Android 2.3 (Prefixed box-sizing versions). + div.style.cssText = "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%"; + + // Workaround failing boxSizing test due to offsetWidth returning wrong value + // with some non-1 values of body zoom, ticket #13543 + jQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() { + support.boxSizing = div.offsetWidth === 4; + }); + + // Use window.getComputedStyle because jsdom on node.js will break without it. + if ( window.getComputedStyle ) { + support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; + support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; + + // Support: Android 2.3 + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. (#3333) + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + marginDiv = div.appendChild( document.createElement("div") ); + marginDiv.style.cssText = div.style.cssText = divReset; + marginDiv.style.marginRight = marginDiv.style.width = "0"; + div.style.width = "1px"; + + support.reliableMarginRight = + !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); + } + + body.removeChild( container ); + }); + + return support; +})( {} ); + diff --git a/hugo/js/jquery/src/jquery/traversing.js b/hugo/js/jquery/src/jquery/traversing.js new file mode 100644 index 0000000..8e305c2 --- /dev/null +++ b/hugo/js/jquery/src/jquery/traversing.js @@ -0,0 +1,283 @@ +var isSimple = /^.[^:#\[\.,]*$/, + rparentsprev = /^(?:parents|prev(?:Until|All))/, + rneedsContext = jQuery.expr.match.needsContext, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + +jQuery.fn.extend({ + find: function( selector ) { + var i, + ret = [], + self = this, + len = self.length; + + if ( typeof selector !== "string" ) { + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, self[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = this.selector ? this.selector + " " + selector : selector; + return ret; + }, + + has: function( target ) { + var targets = jQuery( target, this ), + l = targets.length; + + return this.filter(function() { + var i = 0; + for ( ; i < l; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector || [], true) ); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector || [], false) ); + }, + + is: function( selector ) { + return !!winnow( + this, + + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + typeof selector === "string" && rneedsContext.test( selector ) ? + jQuery( selector ) : + selector || [], + false + ).length; + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + matched = [], + pos = ( rneedsContext.test( selectors ) || typeof selectors !== "string" ) ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) { + // Always skip document fragments + if ( cur.nodeType < 11 && (pos ? + pos.index(cur) > -1 : + + // Don't pass non-elements to Sizzle + cur.nodeType === 1 && + jQuery.find.matchesSelector(cur, selectors)) ) { + + cur = matched.push( cur ); + break; + } + } + } + + return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1; + } + + // index in selector + if ( typeof elem === "string" ) { + return core_indexOf.call( jQuery( elem ), this[ 0 ] ); + } + + // Locate the position of the desired element + return core_indexOf.call( this, + + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[ 0 ] : elem + ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( jQuery.unique(all) ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } +}); + +function sibling( cur, dir ) { + while ( (cur = cur[dir]) && cur.nodeType !== 1 ) {} + + return cur; +} + +jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return elem.contentDocument || jQuery.merge( [], elem.childNodes ); + } +}, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var matched = jQuery.map( this, fn, until ); + + if ( name.slice( -5 ) !== "Until" ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + matched = jQuery.filter( selector, matched ); + } + + if ( this.length > 1 ) { + // Remove duplicates + if ( !guaranteedUnique[ name ] ) { + jQuery.unique( matched ); + } + + // Reverse order for parents* and prev-derivatives + if ( rparentsprev.test( name ) ) { + matched.reverse(); + } + } + + return this.pushStack( matched ); + }; +}); + +jQuery.extend({ + filter: function( expr, elems, not ) { + var elem = elems[ 0 ]; + + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 && elem.nodeType === 1 ? + jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] : + jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) { + return elem.nodeType === 1; + })); + }, + + dir: function( elem, dir, until ) { + var matched = [], + truncate = until !== undefined; + + while ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) { + if ( elem.nodeType === 1 ) { + if ( truncate && jQuery( elem ).is( until ) ) { + break; + } + matched.push( elem ); + } + } + return matched; + }, + + sibling: function( n, elem ) { + var matched = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + matched.push( n ); + } + } + + return matched; + } +}); + +// Implement the identical functionality for filter and not +function winnow( elements, qualifier, not ) { + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep( elements, function( elem, i ) { + /* jshint -W018 */ + return !!qualifier.call( elem, i, elem ) !== not; + }); + + } + + if ( qualifier.nodeType ) { + return jQuery.grep( elements, function( elem ) { + return ( elem === qualifier ) !== not; + }); + + } + + if ( typeof qualifier === "string" ) { + if ( isSimple.test( qualifier ) ) { + return jQuery.filter( qualifier, elements, not ); + } + + qualifier = jQuery.filter( qualifier, elements ); + } + + return jQuery.grep( elements, function( elem ) { + return ( core_indexOf.call( qualifier, elem ) >= 0 ) !== not; + }); +} diff --git a/hugo/js/jquery/src/jquery/wrap.js b/hugo/js/jquery/src/jquery/wrap.js new file mode 100644 index 0000000..5968adb --- /dev/null +++ b/hugo/js/jquery/src/jquery/wrap.js @@ -0,0 +1,69 @@ +jQuery.fn.extend({ + wrapAll: function( html ) { + var wrap; + + if ( jQuery.isFunction( html ) ) { + return this.each(function( i ) { + jQuery( this ).wrapAll( html.call(this, i) ); + }); + } + + if ( this[ 0 ] ) { + + // The elements to wrap the target around + wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true ); + + if ( this[ 0 ].parentNode ) { + wrap.insertBefore( this[ 0 ] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstElementChild ) { + elem = elem.firstElementChild; + } + + return elem; + }).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function( i ) { + jQuery( this ).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each(function( i ) { + jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + } +}); diff --git a/hugo/js/keyhandler.js b/hugo/js/keyhandler.js new file mode 100644 index 0000000..3876fa5 --- /dev/null +++ b/hugo/js/keyhandler.js @@ -0,0 +1,103 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Allows moving around inputs/select by Ctrl+arrows + * + * @param object event data + */ + +AJAX.registerTeardown('keyhandler.js', function() { + $('#table_columns').die('keydown keyup'); + $('table.insertRowTable').die('keydown keyup'); +}); + +AJAX.registerOnload('keyhandler.js', function() { + $('#table_columns').live('keydown keyup', function(event) { + onKeyDownArrowsHandler(event.originalEvent); + }); + $('table.insertRowTable').live('keydown keyup', function(event) { + onKeyDownArrowsHandler(event.originalEvent); + }); +}); + +function onKeyDownArrowsHandler(e) +{ + e = e||window.event; + var o = (e.srcElement||e.target); + if (!o) { + return; + } + if (o.tagName != "TEXTAREA" && o.tagName != "INPUT" && o.tagName != "SELECT") { + return; + }console.log(e); + if (navigator.userAgent.toLowerCase().indexOf('applewebkit/') != -1) { + if (e.ctrlKey || e.shiftKey || !e.altKey) { + return; + } + } else { + if (!e.ctrlKey || e.shiftKey || e.altKey) { + return; + } + } + if (!o.id) { + return; + } + + var pos = o.id.split("_"); + if (pos[0] != "field" || typeof pos[2] == "undefined") { + return; + } + + var x = pos[2], y = pos[1]; + + var nO = null; + + switch(e.keyCode) { + case 38: + // up + y--; + break; + case 40: + // down + y++; + break; + case 37: + // left + x--; + break; + case 39: + // right + x++; + break; + default: + return; + } + + var is_firefox = navigator.userAgent.toLowerCase().indexOf("firefox/") > -1; + + // restore selected index, bug #3799 + if (is_firefox && e.type == "keyup") { + o.selectedIndex = window["selectedIndex_" + o.id]; + } + + var id = "field_" + y + "_" + x; + nO = document.getElementById(id); + if (! nO) { + id = "field_" + y + "_" + x + "_0"; + nO = document.getElementById(id); + } + + // skip non existent fields + if (! nO) { + return; + } + if (e.type == "keydown") { + nO.focus(); + if (is_firefox) { + window["selectedIndex_" + nO.id] = nO.selectedIndex; + } + } + if (nO.tagName != 'SELECT') { + nO.select(); + } + e.returnValue = false; +} diff --git a/hugo/js/makegrid.js b/hugo/js/makegrid.js new file mode 100644 index 0000000..c623788 --- /dev/null +++ b/hugo/js/makegrid.js @@ -0,0 +1,1832 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Create advanced table (resize, reorder, and show/hide columns; and also grid editing). + * This function is designed mainly for table DOM generated from browsing a table in the database. + * For using this function in other table DOM, you may need to: + * - add "draggable" class in the table header <th>, in order to make it resizable, sortable or hidable + * - have at least one non-"draggable" header in the table DOM for placing column visibility drop-down arrow + * - pass the value "false" for the parameter "enableGridEdit" + * - adjust other parameter value, to select which features that will be enabled + * + * @param t the table DOM element + * @param enableResize Optional, if false, column resizing feature will be disabled + * @param enableReorder Optional, if false, column reordering feature will be disabled + * @param enableVisib Optional, if false, show/hide column feature will be disabled + * @param enableGridEdit Optional, if false, grid editing feature will be disabled + */ +function PMA_makegrid(t, enableResize, enableReorder, enableVisib, enableGridEdit) { + var g = { + /*********** + * Constant + ***********/ + minColWidth: 15, + + + /*********** + * Variables, assigned with default value, changed later + ***********/ + actionSpan: 5, // number of colspan in Actions header in a table + tableCreateTime: null, // table creation time, used for saving column order and visibility to server, only available in "Browse tab" + + // Column reordering variables + colOrder: [], // array of column order + + // Column visibility variables + colVisib: [], // array of column visibility + showAllColText: '', // string, text for "show all" button under column visibility list + visibleHeadersCount: 0, // number of visible data headers + + // Table hint variables + reorderHint: '', // string, hint for column reordering + sortHint: '', // string, hint for column sorting + markHint: '', // string, hint for column marking + copyHint: '', // string, hint for copy column name + showReorderHint: false, + showSortHint: false, + showMarkHint: false, + + // Grid editing + isCellEditActive: false, // true if current focus is in edit cell + isEditCellTextEditable: false, // true if current edit cell is editable in the text input box (not textarea) + currentEditCell: null, // reference to <td> that currently being edited + cellEditHint: '', // hint shown when doing grid edit + gotoLinkText: '', // "Go to link" text + wasEditedCellNull: false, // true if last value of the edited cell was NULL + maxTruncatedLen: 0, // number of characters that can be displayed in a cell + saveCellsAtOnce: false, // $cfg[saveCellsAtOnce] + isCellEdited: false, // true if at least one cell has been edited + saveCellWarning: '', // string, warning text when user want to leave a page with unsaved edited data + lastXHR : null, // last XHR object used in AJAX request + isSaving: false, // true when currently saving edited data, used to handle double posting caused by pressing ENTER in grid edit text box in Chrome browser + alertNonUnique: '', // string, alert shown when saving edited nonunique table + + // Common hidden inputs + token: null, + server: null, + db: null, + table: null, + + + /************ + * Functions + ************/ + + /** + * Start to resize column. Called when clicking on column separator. + * + * @param e event + * @param obj dragged div object + */ + dragStartRsz: function(e, obj) { + var n = $(g.cRsz).find('div').index(obj); // get the index of separator (i.e., column index) + $(obj).addClass('colborder_active'); + g.colRsz = { + x0: e.pageX, + n: n, + obj: obj, + objLeft: $(obj).position().left, + objWidth: $(g.t).find('th.draggable:visible:eq(' + n + ') span').outerWidth() + }; + $(document.body).css('cursor', 'col-resize').noSelect(); + if (g.isCellEditActive) { + g.hideEditCell(); + } + }, + + /** + * Start to reorder column. Called when clicking on table header. + * + * @param e event + * @param obj table header object + */ + dragStartReorder: function(e, obj) { + // prepare the cCpy (column copy) and cPointer (column pointer) from the dragged column + $(g.cCpy).text($(obj).text()); + var objPos = $(obj).position(); + $(g.cCpy).css({ + top: objPos.top + 20, + left: objPos.left, + height: $(obj).height(), + width: $(obj).width() + }); + $(g.cPointer).css({ + top: objPos.top + }); + + // get the column index, zero-based + var n = g.getHeaderIdx(obj); + + g.colReorder = { + x0: e.pageX, + y0: e.pageY, + n: n, + newn: n, + obj: obj, + objTop: objPos.top, + objLeft: objPos.left + }; + + $(document.body).css('cursor', 'move').noSelect(); + if (g.isCellEditActive) { + g.hideEditCell(); + } + }, + + /** + * Handle mousemove event when dragging. + * + * @param e event + */ + dragMove: function(e) { + if (g.colRsz) { + var dx = e.pageX - g.colRsz.x0; + if (g.colRsz.objWidth + dx > g.minColWidth) { + $(g.colRsz.obj).css('left', g.colRsz.objLeft + dx + 'px'); + } + } else if (g.colReorder) { + // dragged column animation + var dx = e.pageX - g.colReorder.x0; + $(g.cCpy) + .css('left', g.colReorder.objLeft + dx) + .show(); + + // pointer animation + var hoveredCol = g.getHoveredCol(e); + if (hoveredCol) { + var newn = g.getHeaderIdx(hoveredCol); + g.colReorder.newn = newn; + if (newn != g.colReorder.n) { + // show the column pointer in the right place + var colPos = $(hoveredCol).position(); + var newleft = newn < g.colReorder.n ? + colPos.left : + colPos.left + $(hoveredCol).outerWidth(); + $(g.cPointer) + .css({ + left: newleft, + visibility: 'visible' + }); + } else { + // no movement to other column, hide the column pointer + $(g.cPointer).css('visibility', 'hidden'); + } + } + } + }, + + /** + * Stop the dragging action. + * + * @param e event + */ + dragEnd: function(e) { + if (g.colRsz) { + var dx = e.pageX - g.colRsz.x0; + var nw = g.colRsz.objWidth + dx; + if (nw < g.minColWidth) { + nw = g.minColWidth; + } + var n = g.colRsz.n; + // do the resizing + g.resize(n, nw); + + g.reposRsz(); + g.reposDrop(); + g.colRsz = false; + $(g.cRsz).find('div').removeClass('colborder_active'); + } else if (g.colReorder) { + // shift columns + if (g.colReorder.newn != g.colReorder.n) { + g.shiftCol(g.colReorder.n, g.colReorder.newn); + // assign new position + var objPos = $(g.colReorder.obj).position(); + g.colReorder.objTop = objPos.top; + g.colReorder.objLeft = objPos.left; + g.colReorder.n = g.colReorder.newn; + // send request to server to remember the column order + if (g.tableCreateTime) { + g.sendColPrefs(); + } + g.refreshRestoreButton(); + } + + // animate new column position + $(g.cCpy).stop(true, true) + .animate({ + top: g.colReorder.objTop, + left: g.colReorder.objLeft + }, 'fast') + .fadeOut(); + $(g.cPointer).css('visibility', 'hidden'); + + g.colReorder = false; + } + $(document.body).css('cursor', 'inherit').noSelect(false); + }, + + /** + * Resize column n to new width "nw" + * + * @param n zero-based column index + * @param nw new width of the column in pixel + */ + resize: function(n, nw) { + $(g.t).find('tr').each(function() { + $(this).find('th.draggable:visible:eq(' + n + ') span,' + + 'td:visible:eq(' + (g.actionSpan + n) + ') span') + .css('width', nw); + }); + }, + + /** + * Reposition column resize bars. + */ + reposRsz: function() { + $(g.cRsz).find('div').hide(); + var $firstRowCols = $(g.t).find('tr:first th.draggable:visible'); + var $resizeHandles = $(g.cRsz).find('div').removeClass('condition'); + $('table.pma_table').find('thead th:first').removeClass('before-condition'); + for (var n = 0, l = $firstRowCols.length; n < l; n++) { + var $col = $($firstRowCols[n]); + $($resizeHandles[n]).css('left', $col.position().left + $col.outerWidth(true)) + .show(); + if ($col.hasClass('condition')) { + $($resizeHandles[n]).addClass('condition'); + if (n > 0) { + $($resizeHandles[n-1]).addClass('condition'); + } + } + } + if ($($resizeHandles[0]).hasClass('condition')) { + $('table.pma_table').find('thead th:first').addClass('before-condition'); + } + $(g.cRsz).css('height', $(g.t).height()); + }, + + /** + * Shift column from index oldn to newn. + * + * @param oldn old zero-based column index + * @param newn new zero-based column index + */ + shiftCol: function(oldn, newn) { + $(g.t).find('tr').each(function() { + if (newn < oldn) { + $(this).find('th.draggable:eq(' + newn + '),' + + 'td:eq(' + (g.actionSpan + newn) + ')') + .before($(this).find('th.draggable:eq(' + oldn + '),' + + 'td:eq(' + (g.actionSpan + oldn) + ')')); + } else { + $(this).find('th.draggable:eq(' + newn + '),' + + 'td:eq(' + (g.actionSpan + newn) + ')') + .after($(this).find('th.draggable:eq(' + oldn + '),' + + 'td:eq(' + (g.actionSpan + oldn) + ')')); + } + }); + // reposition the column resize bars + g.reposRsz(); + + // adjust the column visibility list + if (newn < oldn) { + $(g.cList).find('.lDiv div:eq(' + newn + ')') + .before($(g.cList).find('.lDiv div:eq(' + oldn + ')')); + } else { + $(g.cList).find('.lDiv div:eq(' + newn + ')') + .after($(g.cList).find('.lDiv div:eq(' + oldn + ')')); + } + // adjust the colOrder + var tmp = g.colOrder[oldn]; + g.colOrder.splice(oldn, 1); + g.colOrder.splice(newn, 0, tmp); + // adjust the colVisib + if (g.colVisib.length > 0) { + tmp = g.colVisib[oldn]; + g.colVisib.splice(oldn, 1); + g.colVisib.splice(newn, 0, tmp); + } + }, + + /** + * Find currently hovered table column's header (excluding actions column). + * + * @param e event + * @return the hovered column's th object or undefined if no hovered column found. + */ + getHoveredCol: function(e) { + var hoveredCol; + $headers = $(g.t).find('th.draggable:visible'); + $headers.each(function() { + var left = $(this).offset().left; + var right = left + $(this).outerWidth(); + if (left <= e.pageX && e.pageX <= right) { + hoveredCol = this; + } + }); + return hoveredCol; + }, + + /** + * Get a zero-based index from a <th class="draggable"> tag in a table. + * + * @param obj table header <th> object + * @return zero-based index of the specified table header in the set of table headers (visible or not) + */ + getHeaderIdx: function(obj) { + return $(obj).parents('tr').find('th.draggable').index(obj); + }, + + /** + * Reposition the columns back to normal order. + */ + restoreColOrder: function() { + // use insertion sort, since we already have shiftCol function + for (var i = 1; i < g.colOrder.length; i++) { + var x = g.colOrder[i]; + var j = i - 1; + while (j >= 0 && x < g.colOrder[j]) { + j--; + } + if (j != i - 1) { + g.shiftCol(i, j + 1); + } + } + if (g.tableCreateTime) { + // send request to server to remember the column order + g.sendColPrefs(); + } + g.refreshRestoreButton(); + }, + + /** + * Send column preferences (column order and visibility) to the server. + */ + sendColPrefs: function() { + if ($(g.t).is('.ajax')) { // only send preferences if ajax class + var post_params = { + ajax_request: true, + db: g.db, + table: g.table, + token: g.token, + server: g.server, + set_col_prefs: true, + table_create_time: g.tableCreateTime + }; + if (g.colOrder.length > 0) { + $.extend(post_params, {col_order: g.colOrder.toString()}); + } + if (g.colVisib.length > 0) { + $.extend(post_params, {col_visib: g.colVisib.toString()}); + } + $.post('sql.php', post_params, function(data) { + if (data.success != true) { + var $temp_div = $(document.createElement('div')); + $temp_div.html(data.error); + $temp_div.addClass("error"); + PMA_ajaxShowMessage($temp_div, false); + } + }); + } + }, + + /** + * Refresh restore button state. + * Make restore button disabled if the table is similar with initial state. + */ + refreshRestoreButton: function() { + // check if table state is as initial state + var isInitial = true; + for (var i = 0; i < g.colOrder.length; i++) { + if (g.colOrder[i] != i) { + isInitial = false; + break; + } + } + // check if only one visible column left + var isOneColumn = g.visibleHeadersCount == 1; + // enable or disable restore button + if (isInitial || isOneColumn) { + $('div.restore_column').hide(); + } else { + $('div.restore_column').show(); + } + }, + + /** + * Update current hint using the boolean values (showReorderHint, showSortHint, etc.). + * + */ + updateHint: function() { + var text = ''; + if (!g.colRsz && !g.colReorder) { // if not resizing or dragging + if (g.visibleHeadersCount > 1) { + g.showReorderHint = true; + } + if ($(t).find('th.marker').length > 0) { + g.showMarkHint = true; + } + + if (g.showReorderHint && g.reorderHint) { + text += g.reorderHint; + } + if (g.showSortHint && g.sortHint) { + text += text.length > 0 ? '<br />' : ''; + text += g.sortHint; + } + if (g.showMarkHint && g.markHint && + !g.showSortHint // we do not show mark hint, when sort hint is shown + ) { + text += text.length > 0 ? '<br />' : ''; + text += g.markHint; + text += text.length > 0 ? '<br />' : ''; + text += g.copyHint; + } + } + return text; + }, + + /** + * Toggle column's visibility. + * After calling this function and it returns true, afterToggleCol() must be called. + * + * @return boolean True if the column is toggled successfully. + */ + toggleCol: function(n) { + if (g.colVisib[n]) { + // can hide if more than one column is visible + if (g.visibleHeadersCount > 1) { + $(g.t).find('tr').each(function() { + $(this).find('th.draggable:eq(' + n + '),' + + 'td:eq(' + (g.actionSpan + n) + ')') + .hide(); + }); + g.colVisib[n] = 0; + $(g.cList).find('.lDiv div:eq(' + n + ') input').prop('checked', false); + } else { + // cannot hide, force the checkbox to stay checked + $(g.cList).find('.lDiv div:eq(' + n + ') input').prop('checked', true); + return false; + } + } else { // column n is not visible + $(g.t).find('tr').each(function() { + $(this).find('th.draggable:eq(' + n + '),' + + 'td:eq(' + (g.actionSpan + n) + ')') + .show(); + }); + g.colVisib[n] = 1; + $(g.cList).find('.lDiv div:eq(' + n + ') input').prop('checked', true); + } + return true; + }, + + /** + * This must be called if toggleCol() returns is true. + * + * This function is separated from toggleCol because, sometimes, we want to toggle + * some columns together at one time and do just one adjustment after it, e.g. in showAllColumns(). + */ + afterToggleCol: function() { + // some adjustments after hiding column + g.reposRsz(); + g.reposDrop(); + g.sendColPrefs(); + + // check visible first row headers count + g.visibleHeadersCount = $(g.t).find('tr:first th.draggable:visible').length; + g.refreshRestoreButton(); + }, + + /** + * Show columns' visibility list. + * + * @param obj The drop down arrow of column visibility list + */ + showColList: function(obj) { + // only show when not resizing or reordering + if (!g.colRsz && !g.colReorder) { + var pos = $(obj).position(); + // check if the list position is too right + if (pos.left + $(g.cList).outerWidth(true) > $(document).width()) { + pos.left = $(document).width() - $(g.cList).outerWidth(true); + } + $(g.cList).css({ + left: pos.left, + top: pos.top + $(obj).outerHeight(true) + }) + .show(); + $(obj).addClass('coldrop-hover'); + } + }, + + /** + * Hide columns' visibility list. + */ + hideColList: function() { + $(g.cList).hide(); + $(g.cDrop).find('.coldrop-hover').removeClass('coldrop-hover'); + }, + + /** + * Reposition the column visibility drop-down arrow. + */ + reposDrop: function() { + var $th = $(t).find('th:not(.draggable)'); + for (var i = 0; i < $th.length; i++) { + var $cd = $(g.cDrop).find('div:eq(' + i + ')'); // column drop-down arrow + var pos = $($th[i]).position(); + $cd.css({ + left: pos.left + $($th[i]).width() - $cd.width(), + top: pos.top + }); + } + }, + + /** + * Show all hidden columns. + */ + showAllColumns: function() { + for (var i = 0; i < g.colVisib.length; i++) { + if (!g.colVisib[i]) { + g.toggleCol(i); + } + } + g.afterToggleCol(); + }, + + /** + * Show edit cell, if it can be shown + * + * @param cell <td> element to be edited + */ + showEditCell: function(cell) { + if ($(cell).is('.grid_edit') && + !g.colRsz && !g.colReorder) + { + if (!g.isCellEditActive) { + var $cell = $(cell); + // remove all edit area and hide it + $(g.cEdit).find('.edit_area').empty().hide(); + // reposition the cEdit element + $(g.cEdit).css({ + top: $cell.position().top, + left: $cell.position().left + }) + .show() + .find('.edit_box') + .css({ + width: $cell.outerWidth(), + height: $cell.outerHeight() + }); + // fill the cell edit with text from <td> + var value = PMA_getCellValue(cell); + $(g.cEdit).find('.edit_box').val(value); + + g.currentEditCell = cell; + $(g.cEdit).find('.edit_box').focus(); + $(g.cEdit).find('*').removeProp('disabled'); + } + } + }, + + /** + * Remove edit cell and the edit area, if it is shown. + * + * @param force Optional, force to hide edit cell without saving edited field. + * @param data Optional, data from the POST AJAX request to save the edited field + * or just specify "true", if we want to replace the edited field with the new value. + * @param field Optional, the edited <td>. If not specified, the function will + * use currently edited <td> from g.currentEditCell. + */ + hideEditCell: function(force, data, field) { + if (g.isCellEditActive && !force) { + // cell is being edited, save or post the edited data + g.saveOrPostEditedCell(); + return; + } + + // cancel any previous request + if (g.lastXHR != null) { + g.lastXHR.abort(); + g.lastXHR = null; + } + + if (data) { + if (g.currentEditCell) { // save value of currently edited cell + // replace current edited field with the new value + var $this_field = $(g.currentEditCell); + var is_null = $this_field.data('value') == null; + if (is_null) { + $this_field.find('span').html('NULL'); + $this_field.addClass('null'); + } else { + $this_field.removeClass('null'); + var new_html = data.isNeedToRecheck + ? data.truncatableFieldValue + : $this_field.data('value'); + if ($this_field.is('.truncated')) { + if (new_html.length > g.maxTruncatedLen) { + new_html = new_html.substring(0, g.maxTruncatedLen) + '...'; + } + } + $this_field.find('span').text(new_html); + } + } + if (data.transformations != undefined) { + $.each(data.transformations, function(cell_index, value) { + var $this_field = $(g.t).find('.to_be_saved:eq(' + cell_index + ')'); + $this_field.find('span').html(value); + }); + } + if (data.relations != undefined) { + $.each(data.relations, function(cell_index, value) { + var $this_field = $(g.t).find('.to_be_saved:eq(' + cell_index + ')'); + $this_field.find('span').html(value); + }); + } + + // refresh the grid + g.reposRsz(); + g.reposDrop(); + } + + // hide the cell editing area + $(g.cEdit).hide(); + $(g.cEdit).find('.edit_box').blur(); + g.isCellEditActive = false; + g.currentEditCell = null; + // destroy datepicker in edit area, if exist + var $dp = $(g.cEdit).find('.hasDatepicker'); + if ($dp.length > 0) { + $dp.datepicker('destroy'); + // change the cursor in edit box back to normal + // (the cursor become a hand pointer when we add datepicker) + $(g.cEdit).find('.edit_box').css('cursor', 'inherit'); + } + }, + + /** + * Show drop-down edit area when edit cell is focused. + */ + showEditArea: function() { + if (!g.isCellEditActive) { // make sure the edit area has not been shown + g.isCellEditActive = true; + g.isEditCellTextEditable = false; + /** + * @var $td current edited cell + */ + var $td = $(g.currentEditCell); + /** + * @var $editArea the editing area + */ + var $editArea = $(g.cEdit).find('.edit_area'); + /** + * @var where_clause WHERE clause for the edited cell + */ + var where_clause = $td.parent('tr').find('.where_clause').val(); + /** + * @var field_name String containing the name of this field. + * @see getFieldName() + */ + var field_name = getFieldName($td); + /** + * @var relation_curr_value String current value of the field (for fields that are foreign keyed). + */ + var relation_curr_value = $td.text(); + /** + * @var relation_key_or_display_column String relational key if in 'Relational display column' mode, + * relational display column if in 'Relational key' mode (for fields that are foreign keyed). + */ + var relation_key_or_display_column = $td.find('a').attr('title'); + /** + * @var curr_value String current value of the field (for fields that are of type enum or set). + */ + var curr_value = $td.find('span').text(); + + // empty all edit area, then rebuild it based on $td classes + $editArea.empty(); + + // add show data row link if the data resulted by 'browse distinct values' in table structure + if ($td.find('input').hasClass('data_browse_link')) { + var showDataRowLink = document.createElement('div'); + showDataRowLink.className = 'goto_link'; + $(showDataRowLink).append("<a href='" + $td.find('.data_browse_link').val() + "'>" + g.showDataRowLinkText + "</a>"); + $editArea.append(showDataRowLink); + } + + // add goto link, if this cell contains a link + if ($td.find('a').length > 0) { + var gotoLink = document.createElement('div'); + gotoLink.className = 'goto_link'; + $(gotoLink).append(g.gotoLinkText + ': ') + .append($td.find('a').clone().click( + function (event) { + event.preventDefault(); + window.open(this.href); + })); + $editArea.append(gotoLink); + } + + g.wasEditedCellNull = false; + if ($td.is(':not(.not_null)')) { + // append a null checkbox + $editArea.append('<div class="null_div">Null :<input type="checkbox"></div>'); + var $checkbox = $editArea.find('.null_div input'); + // check if current <td> is NULL + if ($td.is('.null')) { + $checkbox.prop('checked', true); + g.wasEditedCellNull = true; + } + + // if the select/editor is changed un-check the 'checkbox_null_<field_name>_<row_index>'. + if ($td.is('.enum, .set')) { + $editArea.find('select').live('change', function(e) { + $checkbox.prop('checked', false); + }); + } else if ($td.is('.relation')) { + $editArea.find('select').live('change', function(e) { + $checkbox.prop('checked', false); + }); + $editArea.find('.browse_foreign').live('click', function(e) { + $checkbox.prop('checked', false); + }); + } else { + $(g.cEdit).find('.edit_box').live('keypress change', function(e) { + $checkbox.prop('checked', false); + }); + // Capture ctrl+v (on IE and Chrome) + $(g.cEdit).find('.edit_box').live('keydown', function(e) { + if (e.ctrlKey && e.which == 86) { + $checkbox.prop('checked', false); + } + }); + $editArea.find('textarea').live('keydown', function(e) { + $checkbox.prop('checked', false); + }); + } + + // if null checkbox is clicked empty the corresponding select/editor. + $checkbox.click(function(e) { + if ($td.is('.enum')) { + $editArea.find('select').val(''); + } else if ($td.is('.set')) { + $editArea.find('select').find('option').each(function() { + var $option = $(this); + $option.prop('selected', false); + }); + } else if ($td.is('.relation')) { + // if the dropdown is there to select the foreign value + if ($editArea.find('select').length > 0) { + $editArea.find('select').val(''); + } + } else { + $editArea.find('textarea').val(''); + } + $(g.cEdit).find('.edit_box').val(''); + }); + } + + if ($td.is('.relation')) { + //handle relations + $editArea.addClass('edit_area_loading'); + + // initialize the original data + $td.data('original_data', null); + + /** + * @var post_params Object containing parameters for the POST request + */ + var post_params = { + 'ajax_request' : true, + 'get_relational_values' : true, + 'server' : g.server, + 'db' : g.db, + 'table' : g.table, + 'column' : field_name, + 'token' : g.token, + 'curr_value' : relation_curr_value, + 'relation_key_or_display_column' : relation_key_or_display_column + }; + + g.lastXHR = $.post('sql.php', post_params, function(data) { + g.lastXHR = null; + $editArea.removeClass('edit_area_loading'); + if ($(data.dropdown).is('select')) { + // save original_data + var value = $(data.dropdown).val(); + $td.data('original_data', value); + // update the text input field, in case where the "Relational display column" is checked + $(g.cEdit).find('.edit_box').val(value); + } + + $editArea.append(data.dropdown); + $editArea.append('<div class="cell_edit_hint">' + g.cellEditHint + '</div>'); + + // for 'Browse foreign values' options, + // hide the value next to 'Browse foreign values' link + $editArea.find('span.curr_value').hide(); + // handle update for new values selected from new window + $editArea.find('span.curr_value').change(function() { + $(g.cEdit).find('.edit_box').val($(this).text()); + }); + }); // end $.post() + + $editArea.show(); + $editArea.find('select').live('change', function(e) { + $(g.cEdit).find('.edit_box').val($(this).val()); + }); + g.isEditCellTextEditable = true; + } + else if ($td.is('.enum')) { + //handle enum fields + $editArea.addClass('edit_area_loading'); + + /** + * @var post_params Object containing parameters for the POST request + */ + var post_params = { + 'ajax_request' : true, + 'get_enum_values' : true, + 'server' : g.server, + 'db' : g.db, + 'table' : g.table, + 'column' : field_name, + 'token' : g.token, + 'curr_value' : curr_value + }; + g.lastXHR = $.post('sql.php', post_params, function(data) { + g.lastXHR = null; + $editArea.removeClass('edit_area_loading'); + $editArea.append(data.dropdown); + $editArea.append('<div class="cell_edit_hint">' + g.cellEditHint + '</div>'); + }); // end $.post() + + $editArea.show(); + $editArea.find('select').live('change', function(e) { + $(g.cEdit).find('.edit_box').val($(this).val()); + }); + } + else if ($td.is('.set')) { + //handle set fields + $editArea.addClass('edit_area_loading'); + + /** + * @var post_params Object containing parameters for the POST request + */ + var post_params = { + 'ajax_request' : true, + 'get_set_values' : true, + 'server' : g.server, + 'db' : g.db, + 'table' : g.table, + 'column' : field_name, + 'token' : g.token, + 'curr_value' : curr_value + }; + + g.lastXHR = $.post('sql.php', post_params, function(data) { + g.lastXHR = null; + $editArea.removeClass('edit_area_loading'); + $editArea.append(data.select); + $editArea.append('<div class="cell_edit_hint">' + g.cellEditHint + '</div>'); + }); // end $.post() + + $editArea.show(); + $editArea.find('select').live('change', function(e) { + $(g.cEdit).find('.edit_box').val($(this).val()); + }); + } + else if ($td.is('.truncated, .transformed')) { + if ($td.is('.to_be_saved')) { // cell has been edited + var value = $td.data('value'); + $(g.cEdit).find('.edit_box').val(value); + $editArea.append('<textarea></textarea>'); + $editArea.find('textarea') + .val(value) + .live('keyup', function(e) { + $(g.cEdit).find('.edit_box').val($(this).val()); + }); + $(g.cEdit).find('.edit_box').live('keyup', function(e) { + $editArea.find('textarea').val($(this).val()); + }); + $editArea.append('<div class="cell_edit_hint">' + g.cellEditHint + '</div>'); + } else { + //handle truncated/transformed values values + $editArea.addClass('edit_area_loading'); + + // initialize the original data + $td.data('original_data', null); + + /** + * @var sql_query String containing the SQL query used to retrieve value of truncated/transformed data + */ + var sql_query = 'SELECT `' + field_name + '` FROM `' + g.table + '` WHERE ' + PMA_urldecode(where_clause); + + // Make the Ajax call and get the data, wrap it and insert it + g.lastXHR = $.post('sql.php', { + 'token' : g.token, + 'server' : g.server, + 'db' : g.db, + 'ajax_request' : true, + 'sql_query' : sql_query, + 'grid_edit' : true + }, function(data) { + g.lastXHR = null; + $editArea.removeClass('edit_area_loading'); + if (data.success == true) { + if ($td.is('.truncated')) { + // get the truncated data length + g.maxTruncatedLen = $(g.currentEditCell).text().length - 3; + } + + $td.data('original_data', data.value); + $(g.cEdit).find('.edit_box').val(data.value); + $editArea.append('<textarea></textarea>'); + $editArea.find('textarea') + .val(data.value) + .live('keyup', function(e) { + $(g.cEdit).find('.edit_box').val($(this).val()); + }); + $(g.cEdit).find('.edit_box').live('keyup', function(e) { + $editArea.find('textarea').val($(this).val()); + }); + $editArea.append('<div class="cell_edit_hint">' + g.cellEditHint + '</div>'); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.post() + $editArea.show(); + } + g.isEditCellTextEditable = true; + } else if ($td.is('.datefield, .datetimefield, .timestampfield')) { + var $input_field = $(g.cEdit).find('.edit_box'); + + // remember current datetime value in $input_field, if it is not null + var is_null = $td.is('.null'); + var current_datetime_value = !is_null ? $input_field.val() : ''; + + var showTimeOption = true; + if ($td.is('.datefield')) { + showTimeOption = false; + } + PMA_addDatepicker($editArea, { + altField: $input_field, + showTimepicker: showTimeOption, + onSelect: function(dateText, inst) { + // remove null checkbox if it exists + $(g.cEdit).find('.null_div input[type=checkbox]').prop('checked', false); + } + }); + + // cancel any click on the datepicker element + $editArea.find('> *').click(function(e) { + e.stopPropagation(); + }); + + // force to restore modified $input_field value after adding datepicker + // (after adding a datepicker, the input field doesn't display the time anymore, only the date) + if (is_null + || current_datetime_value == '0000-00-00' + || current_datetime_value == '0000-00-00 00:00:00' + ) { + $input_field.val(current_datetime_value); + } else { + $editArea.datetimepicker('setDate', current_datetime_value); + } + $editArea.append('<div class="cell_edit_hint">' + g.cellEditHint + '</div>'); + + // remove {cursor: 'pointer'} added inside + // jquery-ui-timepicker-addon.js + $input_field.css('cursor', ''); + // make the cell editable, so one can can bypass the timepicker + // and enter date/time value manually + g.isEditCellTextEditable = true; + } else { + g.isEditCellTextEditable = true; + // only append edit area hint if there is a null checkbox + if ($editArea.children().length > 0) { + $editArea.append('<div class="cell_edit_hint">' + g.cellEditHint + '</div>'); + } + } + if ($editArea.children().length > 0) { + $editArea.show(); + } + } + }, + + /** + * Post the content of edited cell. + */ + postEditedCell: function() { + if (g.isSaving) { + return; + } + g.isSaving = true; + + /** + * @var relation_fields Array containing the name/value pairs of relational fields + */ + var relation_fields = {}; + /** + * @var relational_display string 'K' if relational key, 'D' if relational display column + */ + var relational_display = $("#relational_display_K").prop('checked') ? 'K' : 'D'; + /** + * @var transform_fields Array containing the name/value pairs for transformed fields + */ + var transform_fields = {}; + /** + * @var transformation_fields Boolean, if there are any transformed fields in the edited cells + */ + var transformation_fields = false; + /** + * @var full_sql_query String containing the complete SQL query to update this table + */ + var full_sql_query = ''; + /** + * @var rel_fields_list String, url encoded representation of {@link relations_fields} + */ + var rel_fields_list = ''; + /** + * @var transform_fields_list String, url encoded representation of {@link transform_fields} + */ + var transform_fields_list = ''; + /** + * @var where_clause Array containing where clause for updated fields + */ + var full_where_clause = []; + /** + * @var is_unique Boolean, whether the rows in this table is unique or not + */ + var is_unique = $('td.edit_row_anchor').is('.nonunique') ? 0 : 1; + /** + * multi edit variables + */ + var me_fields_name = []; + var me_fields = []; + var me_fields_null = []; + + // alert user if edited table is not unique + if (!is_unique) { + alert(g.alertNonUnique); + } + + // loop each edited row + $('td.to_be_saved').parents('tr').each(function() { + var $tr = $(this); + var where_clause = $tr.find('.where_clause').val(); + full_where_clause.push(PMA_urldecode(where_clause)); + var condition_array = jQuery.parseJSON($tr.find('.condition_array').val()); + + /** + * multi edit variables, for current row + * @TODO array indices are still not correct, they should be md5 of field's name + */ + var fields_name = []; + var fields = []; + var fields_null = []; + + // loop each edited cell in a row + $tr.find('.to_be_saved').each(function() { + /** + * @var $this_field Object referring to the td that is being edited + */ + var $this_field = $(this); + + /** + * @var field_name String containing the name of this field. + * @see getFieldName() + */ + var field_name = getFieldName($this_field); + + /** + * @var this_field_params Array temporary storage for the name/value of current field + */ + var this_field_params = {}; + + if ($this_field.is('.transformed')) { + transformation_fields = true; + } + this_field_params[field_name] = $this_field.data('value'); + + /** + * @var is_null String capturing whether 'checkbox_null_<field_name>_<row_index>' is checked. + */ + var is_null = this_field_params[field_name] === null; + + fields_name.push(field_name); + + if (is_null) { + fields_null.push('on'); + fields.push(''); + } else { + fields_null.push(''); + fields.push($this_field.data('value')); + + var cell_index = $this_field.index('.to_be_saved'); + if ($this_field.is(":not(.relation, .enum, .set, .bit)")) { + if ($this_field.is('.transformed')) { + transform_fields[cell_index] = {}; + $.extend(transform_fields[cell_index], this_field_params); + } + } else if ($this_field.is('.relation')) { + relation_fields[cell_index] = {}; + $.extend(relation_fields[cell_index], this_field_params); + } + } + // check if edited field appears in WHERE clause + if (where_clause.indexOf(PMA_urlencode(field_name)) > -1) { + var field_str = '`' + g.table + '`.' + '`' + field_name + '`'; + for (var field in condition_array) { + if (field.indexOf(field_str) > -1) { + condition_array[field] = is_null ? 'IS NULL' : "= '" + this_field_params[field_name].replace(/'/g,"''") + "'"; + break; + } + } + } + + }); // end of loop for every edited cells in a row + + // save new_clause + var new_clause = ''; + for (var field in condition_array) { + new_clause += field + ' ' + condition_array[field] + ' AND '; + } + new_clause = new_clause.substring(0, new_clause.length - 5); // remove the last AND + new_clause = PMA_urlencode(new_clause); + $tr.data('new_clause', new_clause); + // save condition_array + $tr.find('.condition_array').val(JSON.stringify(condition_array)); + + me_fields_name.push(fields_name); + me_fields.push(fields); + me_fields_null.push(fields_null); + + }); // end of loop for every edited rows + + rel_fields_list = $.param(relation_fields); + transform_fields_list = $.param(transform_fields); + + // Make the Ajax post after setting all parameters + /** + * @var post_params Object containing parameters for the POST request + */ + var post_params = {'ajax_request' : true, + 'sql_query' : full_sql_query, + 'token' : g.token, + 'server' : g.server, + 'db' : g.db, + 'table' : g.table, + 'clause_is_unique' : is_unique, + 'where_clause' : full_where_clause, + 'fields[multi_edit]' : me_fields, + 'fields_name[multi_edit]' : me_fields_name, + 'fields_null[multi_edit]' : me_fields_null, + 'rel_fields_list' : rel_fields_list, + 'do_transformations' : transformation_fields, + 'transform_fields_list' : transform_fields_list, + 'relational_display' : relational_display, + 'goto' : 'sql.php', + 'submit_type' : 'save' + }; + + if (!g.saveCellsAtOnce) { + $(g.cEdit).find('*').prop('disabled', true); + $(g.cEdit).find('.edit_box').addClass('edit_box_posting'); + } else { + $('div.save_edited').addClass('saving_edited_data') + .find('input').prop('disabled', true); // disable the save button + } + + $.ajax({ + type: 'POST', + url: 'tbl_replace.php', + data: post_params, + success: + function(data) { + g.isSaving = false; + if (!g.saveCellsAtOnce) { + $(g.cEdit).find('*').removeProp('disabled'); + $(g.cEdit).find('.edit_box').removeClass('edit_box_posting'); + } else { + $('div.save_edited').removeClass('saving_edited_data') + .find('input').removeProp('disabled'); // enable the save button back + } + if (data.success == true) { + PMA_ajaxShowMessage(data.message); + + // update where_clause related data in each edited row + $('td.to_be_saved').parents('tr').each(function() { + var new_clause = $(this).data('new_clause'); + var $where_clause = $(this).find('.where_clause'); + var old_clause = $where_clause.val(); + var decoded_old_clause = PMA_urldecode(old_clause); + var decoded_new_clause = PMA_urldecode(new_clause); + + $where_clause.val(new_clause); + // update Edit, Copy, and Delete links also + $(this).find('a').each(function() { + $(this).attr('href', $(this).attr('href').replace(old_clause, new_clause)); + // update delete confirmation in Delete link + if ($(this).attr('href').indexOf('DELETE') > -1) { + $(this).removeAttr('onclick') + .unbind('click') + .bind('click', function() { + return confirmLink(this, 'DELETE FROM `' + g.db + '`.`' + g.table + '` WHERE ' + + decoded_new_clause + (is_unique ? '' : ' LIMIT 1')); + }); + } + }); + // update the multi edit checkboxes + $(this).find('input[type=checkbox]').each(function() { + var $checkbox = $(this); + var checkbox_name = $checkbox.attr('name'); + var checkbox_value = $checkbox.val(); + + $checkbox.attr('name', checkbox_name.replace(old_clause, new_clause)); + $checkbox.val(checkbox_value.replace(decoded_old_clause, decoded_new_clause)); + }); + }); + // update the display of executed SQL query command + $('#result_query').remove(); + if (typeof data.sql_query != 'undefined') { + // display feedback + $('#sqlqueryresults').prepend(data.sql_query); + } + // hide and/or update the successfully saved cells + g.hideEditCell(true, data); + + // remove the "Save edited cells" button + $('div.save_edited').hide(); + // update saved fields + $(g.t).find('.to_be_saved') + .removeClass('to_be_saved') + .data('value', null) + .data('original_data', null); + + g.isCellEdited = false; + } else { + PMA_ajaxShowMessage(data.error, false); + } + } + }); // end $.ajax() + }, + + /** + * Save edited cell, so it can be posted later. + */ + saveEditedCell: function() { + /** + * @var $this_field Object referring to the td that is being edited + */ + var $this_field = $(g.currentEditCell); + var $test_element = ''; // to test the presence of a element + + var need_to_post = false; + + /** + * @var field_name String containing the name of this field. + * @see getFieldName() + */ + var field_name = getFieldName($this_field); + + /** + * @var this_field_params Array temporary storage for the name/value of current field + */ + var this_field_params = {}; + + /** + * @var is_null String capturing whether 'checkbox_null_<field_name>_<row_index>' is checked. + */ + var is_null = $(g.cEdit).find('input:checkbox').is(':checked'); + var value; + + if ($(g.cEdit).find('.edit_area').is('.edit_area_loading')) { + // the edit area is still loading (retrieving cell data), no need to post + need_to_post = false; + } else if (is_null) { + if (!g.wasEditedCellNull) { + this_field_params[field_name] = null; + need_to_post = true; + } + } else { + if ($this_field.is('.bit')) { + this_field_params[field_name] = '0b' + $(g.cEdit).find('.edit_box').val(); + } else if ($this_field.is('.set')) { + $test_element = $(g.cEdit).find('select'); + this_field_params[field_name] = $test_element.map(function(){ + return $(this).val(); + }).get().join(","); + } else if ($this_field.is('.relation, .enum')) { + // for relation and enumeration, take the results from edit box value, + // because selected value from drop-down, new window or multiple + // selection list will always be updated to the edit box + this_field_params[field_name] = $(g.cEdit).find('.edit_box').val(); + } else { + this_field_params[field_name] = $(g.cEdit).find('.edit_box').val(); + } + if (g.wasEditedCellNull || this_field_params[field_name] != PMA_getCellValue(g.currentEditCell)) { + need_to_post = true; + } + } + + if (need_to_post) { + $(g.currentEditCell).addClass('to_be_saved') + .data('value', this_field_params[field_name]); + if (g.saveCellsAtOnce) { + $('div.save_edited').show(); + } + g.isCellEdited = true; + } + + return need_to_post; + }, + + /** + * Save or post currently edited cell, depending on the "saveCellsAtOnce" configuration. + */ + saveOrPostEditedCell: function() { + var saved = g.saveEditedCell(); + if (!g.saveCellsAtOnce) { + if (saved) { + g.postEditedCell(); + } else { + g.hideEditCell(true); + } + } else { + if (saved) { + g.hideEditCell(true, true); + } else { + g.hideEditCell(true); + } + } + }, + + /** + * Initialize column resize feature. + */ + initColResize: function() { + // create column resizer div + g.cRsz = document.createElement('div'); + g.cRsz.className = 'cRsz'; + + // get data columns in the first row of the table + var $firstRowCols = $(g.t).find('tr:first th.draggable'); + + // create column borders + $firstRowCols.each(function() { + var cb = document.createElement('div'); // column border + $(cb).addClass('colborder') + .mousedown(function(e) { + g.dragStartRsz(e, this); + }); + $(g.cRsz).append(cb); + }); + g.reposRsz(); + + // attach to global div + $(g.gDiv).prepend(g.cRsz); + }, + + /** + * Initialize column reordering feature. + */ + initColReorder: function() { + g.cCpy = document.createElement('div'); // column copy, to store copy of dragged column header + g.cPointer = document.createElement('div'); // column pointer, used when reordering column + + // adjust g.cCpy + g.cCpy.className = 'cCpy'; + $(g.cCpy).hide(); + + // adjust g.cPointer + g.cPointer.className = 'cPointer'; + $(g.cPointer).css('visibility', 'hidden'); // set visibility to hidden instead of calling hide() to force browsers to cache the image in cPointer class + + // assign column reordering hint + g.reorderHint = PMA_messages['strColOrderHint']; + + // get data columns in the first row of the table + var $firstRowCols = $(g.t).find('tr:first th.draggable'); + + // initialize column order + $col_order = $('#col_order'); // check if column order is passed from PHP + if ($col_order.length > 0) { + g.colOrder = $col_order.val().split(','); + for (var i = 0; i < g.colOrder.length; i++) { + g.colOrder[i] = parseInt(g.colOrder[i]); + } + } else { + g.colOrder = []; + for (var i = 0; i < $firstRowCols.length; i++) { + g.colOrder.push(i); + } + } + + // register events + $(t).find('th.draggable') + .mousedown(function(e) { + if (g.visibleHeadersCount > 1) { + g.dragStartReorder(e, this); + } + }) + .mouseenter(function(e) { + if (g.visibleHeadersCount > 1) { + $(this).css('cursor', 'move'); + } else { + $(this).css('cursor', 'inherit'); + } + }) + .mouseleave(function(e) { + g.showReorderHint = false; + $(this).tooltip("option", { + content: g.updateHint() + }) ; + }) + .dblclick(function(e) { + e.preventDefault(); + $("<div/>") + .prop("title", PMA_messages["strColNameCopyTitle"]) + .addClass("modal-copy") + .text(PMA_messages["strColNameCopyText"]) + .append( + $("<input/>") + .prop("readonly", true) + .val($(this).data("column")) + ) + .dialog({ + resizable: false, + modal: true + }) + .find("input").focus().select(); + }); + // restore column order when the restore button is clicked + $('div.restore_column').click(function() { + g.restoreColOrder(); + }); + + // attach to global div + $(g.gDiv).append(g.cPointer); + $(g.gDiv).append(g.cCpy); + + // prevent default "dragstart" event when dragging a link + $(t).find('th a').bind('dragstart', function() { + return false; + }); + + // refresh the restore column button state + g.refreshRestoreButton(); + }, + + /** + * Initialize column visibility feature. + */ + initColVisib: function() { + g.cDrop = document.createElement('div'); // column drop-down arrows + g.cList = document.createElement('div'); // column visibility list + + // adjust g.cDrop + g.cDrop.className = 'cDrop'; + + // adjust g.cList + g.cList.className = 'cList'; + $(g.cList).hide(); + + // assign column visibility related hints + g.showAllColText = PMA_messages['strShowAllCol']; + + // get data columns in the first row of the table + var $firstRowCols = $(g.t).find('tr:first th.draggable'); + + // initialize column visibility + var $col_visib = $('#col_visib'); // check if column visibility is passed from PHP + if ($col_visib.length > 0) { + g.colVisib = $col_visib.val().split(','); + for (var i = 0; i < g.colVisib.length; i++) { + g.colVisib[i] = parseInt(g.colVisib[i]); + } + } else { + g.colVisib = []; + for (var i = 0; i < $firstRowCols.length; i++) { + g.colVisib.push(1); + } + } + + // make sure we have more than one column + if ($firstRowCols.length > 1) { + var $colVisibTh = $(g.t).find('th:not(.draggable)'); + PMA_tooltip( + $colVisibTh, + 'th', + PMA_messages['strColVisibHint'] + ); + + // create column visibility drop-down arrow(s) + $colVisibTh.each(function() { + var $th = $(this); + var cd = document.createElement('div'); // column drop-down arrow + var pos = $th.position(); + $(cd).addClass('coldrop') + .click(function() { + if (g.cList.style.display == 'none') { + g.showColList(this); + } else { + g.hideColList(); + } + }); + $(g.cDrop).append(cd); + }); + + // add column visibility control + g.cList.innerHTML = '<div class="lDiv"></div>'; + var $listDiv = $(g.cList).find('div'); + for (var i = 0; i < $firstRowCols.length; i++) { + var currHeader = $firstRowCols[i]; + var listElmt = document.createElement('div'); + $(listElmt).text($(currHeader).text()) + .prepend('<input type="checkbox" ' + (g.colVisib[i] ? 'checked="checked" ' : '') + '/>'); + $listDiv.append(listElmt); + // add event on click + $(listElmt).click(function() { + if ( g.toggleCol($(this).index()) ) { + g.afterToggleCol(); + } + }); + } + // add "show all column" button + var showAll = document.createElement('div'); + $(showAll).addClass('showAllColBtn') + .text(g.showAllColText); + $(g.cList).append(showAll); + $(showAll).click(function() { + g.showAllColumns(); + }); + // prepend "show all column" button at top if the list is too long + if ($firstRowCols.length > 10) { + var clone = showAll.cloneNode(true); + $(g.cList).prepend(clone); + $(clone).click(function() { + g.showAllColumns(); + }); + } + } + + // hide column visibility list if we move outside the list + $(t).find('td, th.draggable').mouseenter(function() { + g.hideColList(); + }); + + // attach to global div + $(g.gDiv).append(g.cDrop); + $(g.gDiv).append(g.cList); + + // some adjustment + g.reposDrop(); + }, + + /** + * Initialize grid editing feature. + */ + initGridEdit: function() { + + function startGridEditing(e, cell) { + if (g.isCellEditActive) { + g.saveOrPostEditedCell(); + } else { + g.showEditCell(cell); + } + e.stopPropagation(); + } + + // create cell edit wrapper element + g.cEdit = document.createElement('div'); + + // adjust g.cEdit + g.cEdit.className = 'cEdit'; + $(g.cEdit).html('<textarea class="edit_box" rows="1" ></textarea><div class="edit_area" />'); + $(g.cEdit).hide(); + + // assign cell editing hint + g.cellEditHint = PMA_messages['strCellEditHint']; + g.saveCellWarning = PMA_messages['strSaveCellWarning']; + g.alertNonUnique = PMA_messages['strAlertNonUnique']; + g.gotoLinkText = PMA_messages['strGoToLink']; + g.showDataRowLinkText = PMA_messages['strShowDataRowLink']; + + // initialize cell editing configuration + g.saveCellsAtOnce = $('#save_cells_at_once').val(); + + // register events + $(t).find('td.data.click1') + .click(function(e) { + startGridEditing(e, this); + // prevent default action when clicking on "link" in a table + if ($(e.target).is('.grid_edit a')) { + e.preventDefault(); + } + }); + + $(t).find('td.data.click2') + .click(function(e) { + $cell = $(this); + // In the case of relational link, We want single click on the link + // to goto the link and double click to start grid-editing. + var $link = $(e.target); + if ($link.is('.grid_edit.relation a')) { + e.preventDefault(); + // get the click count and increase + var clicks = $cell.data('clicks'); + clicks = (clicks == null) ? 1 : clicks + 1; + + if (clicks == 1) { + // if there are no previous clicks, + // start the single click timer + timer = setTimeout(function() { + // temporarily remove ajax class so the page loader will not handle it, + // submit and then add it back + $link.removeClass('ajax'); + AJAX.requestHandler.call($link[0]); + $link.addClass('ajax'); + $cell.data('clicks', 0); + }, 700); + $cell.data('clicks', clicks); + $cell.data('timer', timer); + } else { + // this is a double click, cancel the single click timer + // and make the click count 0 + clearTimeout($cell.data('timer')); + $cell.data('clicks', 0); + // start grid-editing + startGridEditing(e, this); + } + } + }) + .dblclick(function(e) { + if ($(e.target).is('.grid_edit a')) { + e.preventDefault(); + } else { + startGridEditing(e, this); + } + }); + + $(g.cEdit).find('.edit_box').focus(function(e) { + g.showEditArea(); + }); + $(g.cEdit).find('.edit_box, select').live('keydown', function(e) { + if (e.which == 13) { + // post on pressing "Enter" + e.preventDefault(); + g.saveOrPostEditedCell(); + } + }); + $(g.cEdit).keydown(function(e) { + if (!g.isEditCellTextEditable) { + // prevent text editing + e.preventDefault(); + } + }); + $('html').click(function(e) { + // hide edit cell if the click is not from g.cEdit + if ($(e.target).parents().index(g.cEdit) == -1) { + g.hideEditCell(); + } + }).keydown(function(e) { + if (e.which == 27 && g.isCellEditActive) { + + // cancel on pressing "Esc" + g.hideEditCell(true); + } + }); + $('div.save_edited').click(function() { + g.hideEditCell(); + g.postEditedCell(); + }); + $(window).bind('beforeunload', function(e) { + if (g.isCellEdited) { + return g.saveCellWarning; + } + }); + + // attach to global div + $(g.gDiv).append(g.cEdit); + + // add hint for grid editing feature when hovering "Edit" link in each table row + if (PMA_messages['strGridEditFeatureHint'] != undefined) { + PMA_tooltip( + $(g.t).find('.edit_row_anchor a'), + 'a', + PMA_messages['strGridEditFeatureHint'] + ); + } + } + }; + + /****************** + * Initialize grid + ******************/ + + // wrap all data cells, except actions cell, with span + $(t).find('th, td:not(:has(span))') + .wrapInner('<span />'); + + // create grid elements + g.gDiv = document.createElement('div'); // create global div + + // initialize the table variable + g.t = t; + + // get data columns in the first row of the table + var $firstRowCols = $(t).find('tr:first th.draggable'); + + // initialize visible headers count + g.visibleHeadersCount = $firstRowCols.filter(':visible').length; + + // assign first column (actions) span + if (! $(t).find('tr:first th:first').hasClass('draggable')) { // action header exist + g.actionSpan = $(t).find('tr:first th:first').prop('colspan'); + } else { + g.actionSpan = 0; + } + + // assign table create time + // #table_create_time will only available if we are in "Browse" tab + g.tableCreateTime = $('#table_create_time').val(); + + // assign the hints + g.sortHint = PMA_messages['strSortHint']; + g.markHint = PMA_messages['strColMarkHint']; + g.copyHint = PMA_messages['strColNameCopyHint']; + + // assign common hidden inputs + var $common_hidden_inputs = $('div.common_hidden_inputs'); + g.token = $common_hidden_inputs.find('input[name=token]').val(); + g.server = $common_hidden_inputs.find('input[name=server]').val(); + g.db = $common_hidden_inputs.find('input[name=db]').val(); + g.table = $common_hidden_inputs.find('input[name=table]').val(); + + // add table class + $(t).addClass('pma_table'); + + // add relative position to global div so that resize handlers are correctly positioned + $(g.gDiv).css('position', 'relative'); + + // link the global div + $(t).before(g.gDiv); + $(g.gDiv).append(t); + + // FEATURES + enableResize = enableResize == undefined ? true : enableResize; + enableReorder = enableReorder == undefined ? true : enableReorder; + enableVisib = enableVisib == undefined ? true : enableVisib; + enableGridEdit = enableGridEdit == undefined ? true : enableGridEdit; + if (enableResize) { + g.initColResize(); + } + if (enableReorder && + $('table.navigation').length > 0) // disable reordering for result from EXPLAIN or SHOW syntax, which do not have a table navigation panel + { + g.initColReorder(); + } + if (enableVisib) { + g.initColVisib(); + } + if (enableGridEdit && + $(t).is('.ajax')) // make sure we have the ajax class + { + g.initGridEdit(); + } + + // create tooltip for each <th> with draggable class + PMA_tooltip( + $(t).find("th.draggable"), + 'th', + g.updateHint() + ); + + // register events for hint tooltip (anchors inside draggable th) + $(t).find('th.draggable a') + .mouseenter(function(e) { + g.showSortHint = true; + $(t).find("th.draggable").tooltip("option", { + content: g.updateHint() + }); + }) + .mouseleave(function(e) { + g.showSortHint = false; + $(t).find("th.draggable").tooltip("option", { + content: g.updateHint() + }); + }); + + // register events for dragging-related feature + if (enableResize || enableReorder) { + $(document).mousemove(function(e) { + g.dragMove(e); + }); + $(document).mouseup(function(e) { + g.dragEnd(e); + }); + } + + // some adjustment + $(t).removeClass('data'); + $(g.gDiv).addClass('data'); +} diff --git a/hugo/js/messages.php b/hugo/js/messages.php new file mode 100644 index 0000000..cc3fe5b --- /dev/null +++ b/hugo/js/messages.php @@ -0,0 +1,531 @@ +<?php +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Exporting of translated messages from PHP to Javascript + * + * @package PhpMyAdmin + */ + +chdir('..'); + +// Send correct type: +header('Content-Type: text/javascript; charset=UTF-8'); + +// Cache output in client - the nocache query parameter makes sure that this +// file is reloaded when config changes +header('Expires: ' . gmdate('D, d M Y H:i:s', time() + 3600) . ' GMT'); + +// Avoid loading the full common.inc.php because this would add many +// non-js-compatible stuff like DOCTYPE +define('PMA_MINIMUM_COMMON', true); +require_once './libraries/common.inc.php'; +// Close session early as we won't write anything there +session_write_close(); +// But this one is needed for PMA_escapeJsString() +require_once './libraries/js_escape.lib.php'; + +$js_messages['strNoDropDatabases'] = $cfg['AllowUserDropDatabase'] ? '' : __('"DROP DATABASE" statements are disabled.'); + +/* For confirmations */ +$js_messages['strDoYouReally'] = __('Do you really want to execute "%s"?'); +$js_messages['strDropDatabaseStrongWarning'] = __('You are about to DESTROY a complete database!'); +$js_messages['strDropTableStrongWarning'] = __('You are about to DESTROY a complete table!'); +$js_messages['strTruncateTableStrongWarning'] = __('You are about to TRUNCATE a complete table!'); +$js_messages['strDeleteTrackingData'] = __('Delete tracking data for this table'); +$js_messages['strDeletingTrackingData'] = __('Deleting tracking data'); +$js_messages['strDroppingPrimaryKeyIndex'] = __('Dropping Primary Key/Index'); +$js_messages['strOperationTakesLongTime'] = __('This operation could take a long time. Proceed anyway?'); + +/* For indexes */ +$js_messages['strFormEmpty'] = __('Missing value in the form!'); +$js_messages['strNotNumber'] = __('This is not a number!'); +$js_messages['strAddIndex'] = __('Add Index'); +$js_messages['strEditIndex'] = __('Edit Index'); +$js_messages['strAddToIndex'] = __('Add %s column(s) to index'); + +/* Charts */ +/* l10n: Default label for the y-Axis of Charts */ +$js_messages['strYValues'] = __('Y Values'); + +/* For server_privileges.js */ +$js_messages['strHostEmpty'] = __('The host name is empty!'); +$js_messages['strUserEmpty'] = __('The user name is empty!'); +$js_messages['strPasswordEmpty'] = __('The password is empty!'); +$js_messages['strPasswordNotSame'] = __('The passwords aren\'t the same!'); +$js_messages['strAddUser'] = __('Add user'); +$js_messages['strReloadingPrivileges'] = __('Reloading Privileges'); +$js_messages['strRemovingSelectedUsers'] = __('Removing Selected Users'); +$js_messages['strClose'] = __('Close'); + +/* for server_status.js */ +$js_messages['strEdit'] = __('Edit'); +$js_messages['strLiveTrafficChart'] = __('Live traffic chart'); +$js_messages['strLiveConnChart'] = __('Live conn./process chart'); +$js_messages['strLiveQueryChart'] = __('Live query chart'); + +$js_messages['strStaticData'] = __('Static data'); +/* l10n: Total number of queries */ +$js_messages['strTotal'] = __('Total'); +/* l10n: Other, small valued, queries */ +$js_messages['strOther'] = __('Other'); +/* l10n: Thousands separator */ +$js_messages['strThousandsSeparator'] = __(','); +/* l10n: Decimal separator */ +$js_messages['strDecimalSeparator'] = __('.'); + +$js_messages['strChartConnectionsTitle'] = __('Connections / Processes'); + +/* server status monitor */ +$js_messages['strIncompatibleMonitorConfig'] = __('Local monitor configuration incompatible'); +$js_messages['strIncompatibleMonitorConfigDescription'] = __('The chart arrangement configuration in your browsers local storage is not compatible anymore to the newer version of the monitor dialog. It is very likely that your current configuration will not work anymore. Please reset your configuration to default in the <i>Settings</i> menu.'); + +$js_messages['strQueryCacheEfficiency'] = __('Query cache efficiency'); +$js_messages['strQueryCacheUsage'] = __('Query cache usage'); +$js_messages['strQueryCacheUsed'] = __('Query cache used'); + +$js_messages['strSystemCPUUsage'] = __('System CPU Usage'); +$js_messages['strSystemMemory'] = __('System memory'); +$js_messages['strSystemSwap'] = __('System swap'); + +$js_messages['strAverageLoad'] = __('Average load'); +$js_messages['strTotalMemory'] = __('Total memory'); +$js_messages['strCachedMemory'] = __('Cached memory'); +$js_messages['strBufferedMemory'] = __('Buffered memory'); +$js_messages['strFreeMemory'] = __('Free memory'); +$js_messages['strUsedMemory'] = __('Used memory'); + +$js_messages['strTotalSwap'] = __('Total Swap'); +$js_messages['strCachedSwap'] = __('Cached Swap'); +$js_messages['strUsedSwap'] = __('Used Swap'); +$js_messages['strFreeSwap'] = __('Free Swap'); + +$js_messages['strBytesSent'] = __('Bytes sent'); +$js_messages['strBytesReceived'] = __('Bytes received'); +$js_messages['strConnections'] = __('Connections'); +$js_messages['strProcesses'] = __('Processes'); + +/* summary row */ +$js_messages['strB'] = __('B'); +$js_messages['strKiB'] = __('KiB'); +$js_messages['strMiB'] = __('MiB'); +$js_messages['strGiB'] = __('GiB'); +$js_messages['strTiB'] = __('TiB'); +$js_messages['strPiB'] = __('PiB'); +$js_messages['strEiB'] = __('EiB'); +$js_messages['strTables'] = __('%d table(s)'); + +/* l10n: Questions is the name of a MySQL Status variable */ +$js_messages['strQuestions'] = __('Questions'); +$js_messages['strTraffic'] = __('Traffic'); +$js_messages['strSettings'] = __('Settings'); +$js_messages['strRemoveChart'] = __('Remove chart'); +$js_messages['strEditChart'] = __('Edit title and labels'); +$js_messages['strAddChart'] = __('Add chart to grid'); +$js_messages['strClose'] = __('Close'); +$js_messages['strAddOneSeriesWarning'] = __('Please add at least one variable to the series'); +$js_messages['strNone'] = __('None'); +$js_messages['strResumeMonitor'] = __('Resume monitor'); +$js_messages['strPauseMonitor'] = __('Pause monitor'); +/* Monitor: Instructions Dialog */ +$js_messages['strBothLogOn'] = __('general_log and slow_query_log are enabled.'); +$js_messages['strGenLogOn'] = __('general_log is enabled.'); +$js_messages['strSlowLogOn'] = __('slow_query_log is enabled.'); +$js_messages['strBothLogOff'] = __('slow_query_log and general_log are disabled.'); +$js_messages['strLogOutNotTable'] = __('log_output is not set to TABLE.'); +$js_messages['strLogOutIsTable'] = __('log_output is set to TABLE.'); +$js_messages['strSmallerLongQueryTimeAdvice'] = __('slow_query_log is enabled, but the server logs only queries that take longer than %d seconds. It is advisable to set this long_query_time 0-2 seconds, depending on your system.'); +$js_messages['strLongQueryTimeSet'] = __('long_query_time is set to %d second(s).'); +$js_messages['strSettingsAppliedGlobal'] = __('Following settings will be applied globally and reset to default on server restart:'); +/* l10n: %s is FILE or TABLE */ +$js_messages['strSetLogOutput'] = __('Set log_output to %s'); +/* l10n: Enable in this context means setting a status variable to ON */ +$js_messages['strEnableVar'] = __('Enable %s'); +/* l10n: Disable in this context means setting a status variable to OFF */ +$js_messages['strDisableVar'] = __('Disable %s'); +/* l10n: %d seconds */ +$js_messages['setSetLongQueryTime'] = __('Set long_query_time to %ds'); +$js_messages['strNoSuperUser'] = __('You can\'t change these variables. Please log in as root or contact your database administrator.'); +$js_messages['strChangeSettings'] = __('Change settings'); +$js_messages['strCurrentSettings'] = __('Current settings'); + +$js_messages['strChartTitle'] = __('Chart Title'); +/* l10n: As in differential values */ +$js_messages['strDifferential'] = __('Differential'); +$js_messages['strDividedBy'] = __('Divided by %s'); +$js_messages['strUnit'] = __('Unit'); + +$js_messages['strFromSlowLog'] = __('From slow log'); +$js_messages['strFromGeneralLog'] = __('From general log'); +$js_messages['strServerLogError'] = __('The database name is not known for this query in the server\'s logs.'); +$js_messages['strAnalysingLogsTitle'] = __('Analysing logs'); +$js_messages['strAnalysingLogs'] = __('Analysing & loading logs. This may take a while.'); +$js_messages['strCancelRequest'] = __('Cancel request'); +$js_messages['strCountColumnExplanation'] = __('This column shows the amount of identical queries that are grouped together. However only the SQL query itself has been used as a grouping criteria, so the other attributes of queries, such as start time, may differ.'); +$js_messages['strMoreCountColumnExplanation'] = __('Since grouping of INSERTs queries has been selected, INSERT queries into the same table are also being grouped together, disregarding of the inserted data.'); +$js_messages['strLogDataLoaded'] = __('Log data loaded. Queries executed in this time span:'); + +$js_messages['strJumpToTable'] = __('Jump to Log table'); +$js_messages['strNoDataFoundTitle'] = __('No data found'); +$js_messages['strNoDataFound'] = __('Log analysed, but no data found in this time span.'); + +$js_messages['strAnalyzing'] = __('Analyzing…'); +$js_messages['strExplainOutput'] = __('Explain output'); +$js_messages['strStatus'] = __('Status'); +$js_messages['strTime'] = __('Time'); +$js_messages['strTotalTime'] = __('Total time:'); +$js_messages['strProfilingResults'] = __('Profiling results'); +$js_messages['strTable'] = _pgettext('Display format', 'Table'); +$js_messages['strChart'] = __('Chart'); +$js_messages['strChartEdit'] = __('Edit chart'); +$js_messages['strSeries'] = __('Series'); + +/* l10n: A collection of available filters */ +$js_messages['strFiltersForLogTable'] = __('Log table filter options'); +/* l10n: Filter as in "Start Filtering" */ +$js_messages['strFilter'] = __('Filter'); +$js_messages['strFilterByWordRegexp'] = __('Filter queries by word/regexp:'); +$js_messages['strIgnoreWhereAndGroup'] = __('Group queries, ignoring variable data in WHERE clauses'); +$js_messages['strSumRows'] = __('Sum of grouped rows:'); +$js_messages['strTotal'] = __('Total:'); + +$js_messages['strLoadingLogs'] = __('Loading logs'); +$js_messages['strRefreshFailed'] = __('Monitor refresh failed'); +$js_messages['strInvalidResponseExplanation'] = __('While requesting new chart data the server returned an invalid response. This is most likely because your session expired. Reloading the page and reentering your credentials should help.'); +$js_messages['strReloadPage'] = __('Reload page'); + +$js_messages['strAffectedRows'] = __('Affected rows:'); + +$js_messages['strFailedParsingConfig'] = __('Failed parsing config file. It doesn\'t seem to be valid JSON code.'); +$js_messages['strFailedBuildingGrid'] = __('Failed building chart grid with imported config. Resetting to default config…'); +$js_messages['strImport'] = __('Import'); +$js_messages['strImportDialogTitle'] = __('Import monitor configuration'); +$js_messages['strImportDialogMessage'] = __('Please select the file you want to import'); + +$js_messages['strAnalyzeQuery'] = __('Analyse Query'); + +/* Server status advisor */ + +$js_messages['strAdvisorSystem'] = __('Advisor system'); +$js_messages['strPerformanceIssues'] = __('Possible performance issues'); +$js_messages['strIssuse'] = __('Issue'); +$js_messages['strRecommendation'] = __('Recommendation'); +$js_messages['strRuleDetails'] = __('Rule details'); +$js_messages['strJustification'] = __('Justification'); +$js_messages['strFormula'] = __('Used variable / formula'); +$js_messages['strTest'] = __('Test'); + + +/* For inline query editing */ +$js_messages['strGo'] = __('Go'); +$js_messages['strCancel'] = __('Cancel'); + +/* For Ajax Notifications */ +$js_messages['strLoading'] = __('Loading'); +$js_messages['strProcessingRequest'] = __('Processing Request'); +$js_messages['strErrorProcessingRequest'] = __('Error in Processing Request'); +$js_messages['strErrorCode'] = __('Error code: %s'); +$js_messages['strErrorText'] = __('Error text: %s'); +$js_messages['strNoDatabasesSelected'] = __('No databases selected.'); +$js_messages['strDroppingColumn'] = __('Dropping Column'); +$js_messages['strAddingPrimaryKey'] = __('Adding Primary Key'); +$js_messages['strOK'] = __('OK'); +$js_messages['strDismiss'] = __('Click to dismiss this notification'); + +/* For db_operations.js */ +$js_messages['strRenamingDatabases'] = __('Renaming Databases'); +$js_messages['strReloadDatabase'] = __('Reload Database'); +$js_messages['strCopyingDatabase'] = __('Copying Database'); +$js_messages['strChangingCharset'] = __('Changing Charset'); +$js_messages['strTableMustHaveAtleastOneColumn'] = __('Table must have at least one column'); +$js_messages['strYes'] = __('Yes'); +$js_messages['strNo'] = __('No'); + +/* For db_stucture.js */ +$js_messages['strInsertTable'] = __('Insert Table'); +$js_messages['strHideIndexes'] = __('Hide indexes'); +$js_messages['strShowIndexes'] = __('Show indexes'); +$js_messages['strForeignKeyCheck'] = __('Foreign key check:'); +$js_messages['strForeignKeyCheckEnabled'] = __('(Enabled)'); +$js_messages['strForeignKeyCheckDisabled'] = __('(Disabled)'); + +/* For db_search.js */ +$js_messages['strSearching'] = __('Searching'); +$js_messages['strHideSearchResults'] = __('Hide search results'); +$js_messages['strShowSearchResults'] = __('Show search results'); +$js_messages['strBrowsing'] = __('Browsing'); +$js_messages['strDeleting'] = __('Deleting'); + +/* For db_routines.js */ +$js_messages['MissingReturn'] = __('The definition of a stored function must contain a RETURN statement!'); + +/* For ENUM/SET editor*/ +$js_messages['enum_editor'] = __('ENUM/SET editor'); +$js_messages['enum_columnVals'] =__('Values for column %s'); +$js_messages['enum_newColumnVals'] = __('Values for a new column'); +$js_messages['enum_hint'] =__('Enter each value in a separate field'); +$js_messages['enum_addValue'] =__('Add %d value(s)'); + +/* For import.js */ +$js_messages['strImportCSV'] = __('Note: If the file contains multiple tables, they will be combined into one'); + +/* For sql.js */ +$js_messages['strHideQueryBox'] = __('Hide query box'); +$js_messages['strShowQueryBox'] = __('Show query box'); +$js_messages['strEdit'] = __('Edit'); +$js_messages['strNoRowSelected'] = __('No rows selected'); +$js_messages['strChangeTbl'] = __('Change'); +$js_messages['strQueryExecutionTime'] = __('Query execution time'); +$js_messages['strNotValidRowNumber'] = __('%d is not valid row number.'); + +/* For server_variables.js */ +$js_messages['strSave'] = __('Save'); + +/* For tbl_select.js */ +$js_messages['strHideSearchCriteria'] = __('Hide search criteria'); +$js_messages['strShowSearchCriteria'] = __('Show search criteria'); + +/* For tbl_zoom_plot_jqplot.js */ +$js_messages['strZoomSearch'] = __('Zoom Search'); +$js_messages['strDisplayHelp'] = '<ul><li>' + . __('Each point represents a data row.') + . '</li><li>' + . __('Hovering over a point will show its label.') + . '</li><li>' + . __('To zoom in, select a section of the plot with the mouse.') + . '</li><li>' + . __('Click reset zoom button to come back to original state.') + . '</li><li>' + . __('Click a data point to view and possibly edit the data row.') + . '</li><li>' + . __('The plot can be resized by dragging it along the bottom right corner.') + . '</li></ul>'; +$js_messages['strInputNull'] = '<strong>' . __('Select two columns') . '</strong>'; +$js_messages['strSameInputs'] = '<strong>' . __('Select two different columns') . '</strong>'; +$js_messages['strQueryResults'] = __('Query results'); +$js_messages['strDataPointContent'] = __('Data point content'); + +/* For tbl_change.js */ +$js_messages['strIgnore'] = __('Ignore'); +$js_messages['strCopy'] = __('Copy'); +$js_messages['strX'] = __('X'); +$js_messages['strY'] = __('Y'); +$js_messages['strPoint'] = __('Point'); +$js_messages['strPointN'] = __('Point %d'); +$js_messages['strLineString'] = __('Linestring'); +$js_messages['strPolygon'] = __('Polygon'); +$js_messages['strGeometry'] = __('Geometry'); +$js_messages['strInnerRing'] = __('Inner Ring'); +$js_messages['strOuterRing'] = __('Outer Ring'); +$js_messages['strAddPoint'] = __('Add a point'); +$js_messages['strAddInnerRing'] = __('Add an inner ring'); +$js_messages['strAddPolygon'] = __('Add a polygon'); + +/* For tbl_structure.js */ +$js_messages['strAddColumns'] = __('Add columns'); + +/* Designer (js/pmd/move.js) */ +$js_messages['strSelectReferencedKey'] = __('Select referenced key'); +$js_messages['strSelectForeignKey'] = __('Select Foreign Key'); +$js_messages['strPleaseSelectPrimaryOrUniqueKey'] = __('Please select the primary key or a unique key'); +$js_messages['strChangeDisplay'] = __('Choose column to display'); +$js_messages['strLeavingDesigner'] = __('You haven\'t saved the changes in the layout. They will be lost if you don\'t save them. Do you want to continue?'); + +/* Visual query builder (js/pmd/move.js) */ +$js_messages['strAddOption'] = __('Add an option for column '); +$js_messages['strObjectsCreated'] = __('%d object(s) created'); + +/* For makegrid.js (column reordering, show/hide column, grid editing) */ +$js_messages['strCellEditHint'] = __('Press escape to cancel editing'); +$js_messages['strSaveCellWarning'] = __('You have edited some data and they have not been saved. Are you sure you want to leave this page before saving the data?'); +$js_messages['strColOrderHint'] = __('Drag to reorder'); +$js_messages['strSortHint'] = __('Click to sort'); +$js_messages['strColMarkHint'] = __('Click to mark/unmark'); +$js_messages['strColNameCopyHint'] = __('Double-click to copy column name'); +$js_messages['strColVisibHint'] = __('Click the drop-down arrow<br />to toggle column\'s visibility'); +$js_messages['strShowAllCol'] = __('Show all'); +$js_messages['strAlertNonUnique'] = __('This table does not contain a unique column. Features related to the grid edit, checkbox, Edit, Copy and Delete links may not work after saving.'); + +// this approach does not work when the parameter is changed via user prefs +switch ($GLOBALS['cfg']['GridEditing']) { +case 'double-click': + $js_messages['strGridEditFeatureHint'] = __('You can also edit most values<br />by double-clicking directly on them.'); + break; +case 'click': + $js_messages['strGridEditFeatureHint'] = __('You can also edit most values<br />by clicking directly on them.'); + break; +default: + break; +} +$js_messages['strGoToLink'] = __('Go to link'); +$js_messages['strColNameCopyTitle'] = __('Copy column name'); +$js_messages['strColNameCopyText'] = __('Right-click the column name to copy it to your clipboard.'); +$js_messages['strShowDataRowLink'] = __('Show data row(s)'); + +/* password generation */ +$js_messages['strGeneratePassword'] = __('Generate password'); +$js_messages['strGenerate'] = __('Generate'); +$js_messages['strChangePassword'] = __('Change Password'); + +/* navigation tabs */ +$js_messages['strMore'] = __('More'); + +/* navigation panel */ +$js_messages['strShowPanel'] = __('Show Panel'); +$js_messages['strHidePanel'] = __('Hide Panel'); + +/* microhistory */ +$js_messages['strInvalidPage'] = __('The requested page was not found in the history, it may have expired.'); + +/* update */ +$js_messages['strNewerVersion'] = __('A newer version of phpMyAdmin is available and you should consider upgrading. The newest version is %s, released on %s.'); +/* l10n: Latest available phpMyAdmin version */ +$js_messages['strLatestAvailable'] = __(', latest stable version:'); +$js_messages['strUpToDate'] = __('up to date'); + + +echo "var PMA_messages = new Array();\n"; +foreach ($js_messages as $name => $js_message) { + PMA_printJsValue("PMA_messages['" . $name . "']", $js_message); +} + +/* Calendar */ +echo "var themeCalendarImage = '" . $GLOBALS['pmaThemeImage'] . 'b_calendar.png' . "';\n"; + +/* Image path */ +echo "var pmaThemeImage = '" . $GLOBALS['pmaThemeImage'] . "';\n"; + +/* Version */ +echo "var pmaversion = '" . PMA_VERSION . "';\n"; + +echo "if ($.datepicker) {\n"; +/* l10n: Display text for calendar close link */ +PMA_printJsValue("$.datepicker.regional['']['closeText']", __('Done')); +/* l10n: Display text for previous month link in calendar */ +PMA_printJsValue( + "$.datepicker.regional['']['prevText']", + _pgettext('Previous month', 'Prev') +); +/* l10n: Display text for next month link in calendar */ +PMA_printJsValue( + "$.datepicker.regional['']['nextText']", + _pgettext('Next month', 'Next') +); +/* l10n: Display text for current month link in calendar */ +PMA_printJsValue("$.datepicker.regional['']['currentText']", __('Today')); +PMA_printJsValue( + "$.datepicker.regional['']['monthNames']", + array( + __('January'), + __('February'), + __('March'), + __('April'), + __('May'), + __('June'), + __('July'), + __('August'), + __('September'), + __('October'), + __('November'), + __('December') + ) +); +PMA_printJsValue( + "$.datepicker.regional['']['monthNamesShort']", + array( +/* l10n: Short month name */ + __('Jan'), +/* l10n: Short month name */ + __('Feb'), +/* l10n: Short month name */ + __('Mar'), +/* l10n: Short month name */ + __('Apr'), +/* l10n: Short month name */ + _pgettext('Short month name', 'May'), +/* l10n: Short month name */ + __('Jun'), +/* l10n: Short month name */ + __('Jul'), +/* l10n: Short month name */ + __('Aug'), +/* l10n: Short month name */ + __('Sep'), +/* l10n: Short month name */ + __('Oct'), +/* l10n: Short month name */ + __('Nov'), +/* l10n: Short month name */ + __('Dec') + ) +); +PMA_printJsValue( + "$.datepicker.regional['']['dayNames']", + array( + __('Sunday'), + __('Monday'), + __('Tuesday'), + __('Wednesday'), + __('Thursday'), + __('Friday'), + __('Saturday') + ) +); +PMA_printJsValue( + "$.datepicker.regional['']['dayNamesShort']", + array( +/* l10n: Short week day name */ + __('Sun'), +/* l10n: Short week day name */ + __('Mon'), +/* l10n: Short week day name */ + __('Tue'), +/* l10n: Short week day name */ + __('Wed'), +/* l10n: Short week day name */ + __('Thu'), +/* l10n: Short week day name */ + __('Fri'), +/* l10n: Short week day name */ + __('Sat') + ) +); +PMA_printJsValue( + "$.datepicker.regional['']['dayNamesMin']", + array( +/* l10n: Minimal week day name */ + __('Su'), +/* l10n: Minimal week day name */ + __('Mo'), +/* l10n: Minimal week day name */ + __('Tu'), +/* l10n: Minimal week day name */ + __('We'), +/* l10n: Minimal week day name */ + __('Th'), +/* l10n: Minimal week day name */ + __('Fr'), +/* l10n: Minimal week day name */ + __('Sa') + ) +); +/* l10n: Column header for week of the year in calendar */ +PMA_printJsValue("$.datepicker.regional['']['weekHeader']", __('Wk')); + +/* l10n: Month-year order for calendar, use either "calendar-month-year" or "calendar-year-month". */ +PMA_printJsValue("$.datepicker.regional['']['showMonthAfterYear']", (__('calendar-month-year') == 'calendar-year-month')); +/* l10n: Year suffix for calendar, "none" is empty. */ +$year_suffix = _pgettext('Year suffix', 'none'); +PMA_printJsValue("$.datepicker.regional['']['yearSuffix']", ($year_suffix == 'none' ? '' : $year_suffix)); +?> +$.extend($.datepicker._defaults, $.datepicker.regional['']); +} /* if ($.datepicker) */ + +<?php +echo "if ($.timepicker) {\n"; +PMA_printJsValue("$.timepicker.regional['']['timeText']", __('Time')); +PMA_printJsValue("$.timepicker.regional['']['hourText']", __('Hour')); +PMA_printJsValue("$.timepicker.regional['']['minuteText']", __('Minute')); +PMA_printJsValue("$.timepicker.regional['']['secondText']", __('Second')); +?> +$.extend($.timepicker._defaults, $.timepicker.regional['']); +} /* if ($.timepicker) */ diff --git a/hugo/js/navigation.js b/hugo/js/navigation.js new file mode 100644 index 0000000..4806f43 --- /dev/null +++ b/hugo/js/navigation.js @@ -0,0 +1,1079 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * function used in or for navigation panel + * + * @package phpMyAdmin-Navigation + */ + +/** + * Executed on page load + */ +$(function() { + if (! $('#pma_navigation').length) { + // Don't bother running any code if the navigation is not even on the page + return; + } + + // Do not let the page reload on submitting the fast filter + $(document).on('submit', '.fast_filter', function(event) { + event.preventDefault(); + }); + + // Fire up the resize handlers + new ResizeHandler(); + + /** + * opens/closes (hides/shows) tree elements + * loads data via ajax + */ + $('#pma_navigation_tree a.expander').live('click', function(event) { + event.preventDefault(); + event.stopImmediatePropagation(); + var $icon = $(this).find('img'); + if ($icon.is('.ic_b_plus')) { + expandTreeNode($(this)); + } else { + collapseTreeNode($(this)); + } + }); + + /** + * Register event handler for click on the reload + * navigation icon at the top of the panel + */ + $('#pma_navigation_reload').live('click', function (event) { + event.preventDefault(); + $('#pma_navigation .throbber') + .first() + .css('visibility', 'visible'); + PMA_reloadNavigation(); + }); + + /** + * Bind all "fast filter" events + */ + $('#pma_navigation_tree li.fast_filter span') + .live('click', PMA_fastFilter.events.clear); + $('#pma_navigation_tree li.fast_filter input.searchClause') + .live('focus', PMA_fastFilter.events.focus) + .live('blur', PMA_fastFilter.events.blur) + .live('keyup', PMA_fastFilter.events.keyup); + + /** + * Ajax handler for pagination + */ + $('#pma_navigation_tree div.pageselector a.ajax').live('click', function (event) { + event.preventDefault(); + PMA_navigationTreePagination($(this)); + }); + + /** + * Node highlighting + */ + $('#pma_navigation_tree.highlight li:not(.fast_filter)').live( + 'mouseover', + function () { + if ($('li:visible', this).length == 0) { + $(this).addClass('activePointer'); + } + } + ); + $('#pma_navigation_tree.highlight li:not(.fast_filter)').live( + 'mouseout', + function () { + $(this).removeClass('activePointer'); + } + ); + + /** + * Jump to recent table + */ + $('#recentTable').live('change', function() { + if (this.value != '') { + var arr = jQuery.parseJSON(this.value); + var $form = $(this).closest('form'); + $form.find('input[name=db]').val(arr['db']); + $form.find('input[name=table]').val(arr['table']); + $form.submit(); + } + }); + + /** Create a Routine, Trigger or Event */ + $('li.new_procedure a.ajax, li.new_function a.ajax').live('click', function (event) { + event.preventDefault(); + var dialog = new RTE.object('routine'); + dialog.editorDialog(1, $(this)) + }); + $('li.new_trigger a.ajax').live('click', function (event) { + event.preventDefault(); + var dialog = new RTE.object('trigger'); + dialog.editorDialog(1, $(this)) + }); + $('li.new_event a.ajax').live('click', function (event) { + event.preventDefault(); + var dialog = new RTE.object('event'); + dialog.editorDialog(1, $(this)) + }); + + /** Edit Routines, Triggers and Events */ + $('li.procedure > a.ajax, li.function > a.ajax').live('click', function (event) { + event.preventDefault(); + var dialog = new RTE.object('routine'); + dialog.editorDialog(0, $(this)) + }); + $('li.trigger > a.ajax').live('click', function (event) { + event.preventDefault(); + var dialog = new RTE.object('trigger'); + dialog.editorDialog(0, $(this)) + }); + $('li.event > a.ajax').live('click', function (event) { + event.preventDefault(); + var dialog = new RTE.object('event'); + dialog.editorDialog(0, $(this)) + }); + + /** Export Routines, Triggers and Events */ + $('li.procedure a.ajax img, li.function a.ajax img, li.trigger a.ajax img, li.event a.ajax img').live('click', function (event) { + event.preventDefault(); + var dialog = new RTE.object(); + dialog.exportDialog($(this).parent()) + }); + + /** New index */ + $('li.new_index a.ajax').live('click', function (event) { + event.preventDefault(); + var url = $(this).attr('href').substr( + $(this).attr('href').indexOf('?') + 1 + ) + '&ajax_request=true'; + var title = PMA_messages['strAddIndex']; + indexEditorDialog(url, title); + }); + + /** Edit index */ + $('li.index a.ajax').live('click', function (event) { + event.preventDefault(); + var url = $(this).attr('href').substr( + $(this).attr('href').indexOf('?') + 1 + ) + '&ajax_request=true'; + var title = PMA_messages['strEditIndex']; + indexEditorDialog(url, title); + }); + + /** New view */ + $('li.new_view a.ajax').live('click', function (event) { + event.preventDefault(); + PMA_createViewDialog($(this)); + }); + + PMA_showCurrentNavigation(); +}); + +/** + * Expands a node in navigation tree. + * + * @param $expandElem expander + * @param callback callback function + * + * @returns void + */ +function expandTreeNode($expandElem, callback) +{ + var $children = $expandElem.closest('li').children('div.list_container'); + var $icon = $expandElem.find('img'); + if ($expandElem.hasClass('loaded')) { + if ($icon.is('.ic_b_plus')) { + $icon.removeClass('ic_b_plus').addClass('ic_b_minus'); + $children.show('fast'); + } + if (callback && typeof callback == 'function') { + callback.call(); + } + } else { + var $throbber = $('#pma_navigation .throbber') + .first() + .clone() + .css('visibility', 'visible') + .click(false); + $icon.hide(); + $throbber.insertBefore($icon); + + loadChildNodes($expandElem, function(data) { + if (data.success === true) { + var $destination = $expandElem.closest('li'); + $icon.removeClass('ic_b_plus').addClass('ic_b_minus'); + $destination + .children('div.list_container') + .show('fast'); + if ($destination.find('ul > li').length == 1) { + $destination.find('ul > li') + .find('a.expander.container') + .click(); + } + if (callback && typeof callback == 'function') { + callback.call(); + } + } else { + PMA_ajaxShowMessage(data.error, false); + } + $icon.show(); + $throbber.remove(); + }); + } + $expandElem.blur(); +} + +/** + * Auto-scrolls the newly chosen database + * + * @param object $element The element to set to view + * @param object $container The container srollable element + * + */ +function scrollToView($element, $container) { + var elementOffset = $element.offset(), + containerOffset = $container.offset(); + if(elementOffset != undefined && containerOffset != undefined) { + var pushToOffset = elementOffset.top - containerOffset.top + $container.scrollTop(); + $('#pma_navigation_tree_content').stop().animate({ + scrollTop: pushToOffset + }); + } +} + +/** + * Collapses a node in navigation tree. + * + * @param $expandElem expander + * + * @returns void + */ +function collapseTreeNode($expandElem) { + var $children = $expandElem.closest('li').children('div.list_container'); + var $icon = $expandElem.find('img'); + if ($expandElem.hasClass('loaded')) { + if ($icon.is('.ic_b_minus')) { + $icon.removeClass('ic_b_minus').addClass('ic_b_plus'); + $children.hide('fast'); + } + } + $expandElem.blur(); +} + +/** + * Loads child items of a node and executes a given callback + * + * @param $expandElem expander + * @param callback callback function + * + * @returns void + */ +function loadChildNodes($expandElem, callback) { + var $destination = $expandElem.closest('li'); + + var searchClause = PMA_fastFilter.getSearchClause(); + var searchClause2 = PMA_fastFilter.getSearchClause2($expandElem); + + var params = { + aPath: $expandElem.find('span.aPath').text(), + vPath: $expandElem.find('span.vPath').text(), + pos: $expandElem.find('span.pos').text(), + pos2_name: $expandElem.find('span.pos2_name').text(), + pos2_value: $expandElem.find('span.pos2_value').text(), + searchClause: searchClause, + searchClause2: searchClause2 + }; + + var url = $('#pma_navigation').find('a.navigation_url').attr('href'); + $.get(url, params, function (data) { + if (data.success === true) { + $expandElem.addClass('loaded'); + $destination.find('div.list_container').remove(); // FIXME: Hack, there shouldn't be a list container there + $destination.append(data.message); + if (callback && typeof callback == 'function') { + callback(data); + } + } + }); +} + +/** + * Expand the navigation and highlight the current database or table/view + * + * @returns void + */ +function PMA_showCurrentNavigation() +{ + var db = PMA_commonParams.get('db'); + var table = PMA_commonParams.get('table'); + $('#pma_navigation_tree') + .find('li.selected') + .removeClass('selected'); + if (db && table) { // if we are at the table/view level + // open the database in the tree + var $dbItem = highlightLoadedItem( + $('#pma_navigation_tree > div'), db, 'database', false, false + ); + if ($dbItem) { + // open the table in the tree and select it + var $expander = $dbItem.children('div:first').children('a.expander'); + // if not loaded or loaded but collapsed + if (! $expander.hasClass('loaded') + || $expander.find('img').is('.ic_b_plus') + ) { + expandTreeNode($expander, function() { + loadAndHighlightTableOrView($dbItem, table); + }); + } else { + loadAndHighlightTableOrView($dbItem, table); + } + } + } else if (db) { // if we are at the database level + // open in the tree and select the database + highlightLoadedItem( + $('#pma_navigation_tree > div'), db, 'database', true, true + ); + } + + function highlightLoadedItem($container, name, clazz, doSelect, doOpen) { + var ret = false; + $container.children('ul').children('li').each(function() { + var $li = $(this); + // this is a navigation group, recurse + if ($li.is('.navGroup')) { + var $container = $li.children('div.list_container'); + var $childRet = highlightLoadedItem( + $container, name, clazz, doSelect, doOpen + ); + if ($childRet) { + ret = $childRet; + return false; + } + } else { // this is a real navigation item + // name and class matches + if ($li.is('.' + clazz) && $li.children('a').text() == name) { + if (doSelect) { + $li.addClass('selected'); + if (! doOpen) { // if the node will be opened no point scrolling now + scrollToView($li, $('#pma_navigation_tree_content')); + } + } + if (doOpen) { + var $expander = $li.find('div:first').children('a.expander'); + if ($expander.length > 0) { + expandTreeNode($expander, function() { + scrollToView($li, $('#pma_navigation_tree_content')); + }); + } + } + // taverse up and expand and parent navigation groups + $li.parents('.navGroup').each(function() { + $cont = $(this).children('div.list_container'); + if (! $cont.is(':visible')) { + $(this) + .children('div:first') + .children('a.expander') + .click(); + } + }); + ret = $li; + return false; + } + } + }); + return ret; + } + + function loadAndHighlightTableOrView($dbItem, table) { + var $container = $dbItem.children('div.list_container'); + var $tableContainer = $container + .children('ul') + .children('li.tableContainer'); + var $viewContainer = $container + .children('ul') + .children('li.viewContainer'); + + if ($tableContainer.length > 0) { + var $expander = $tableContainer + .children('div:first') + .children('a.expander'); + + if (! $expander.hasClass('loaded') ) { + loadChildNodes($expander, function(data) { + highlightTableOrView($tableContainer, $viewContainer, table); + }); + } else { + highlightTableOrView($tableContainer, $viewContainer, table); + } + } else if ($viewContainer.length > 0) { + highlightView($viewContainer, table); + } else { + // no containers, highlight the item + highlightLoadedItem($container, table, 'table', true, false); + } + } + + function highlightTableOrView($tableContainer, $viewContainer, table) + { + if (isItemInContainer($tableContainer, table, 'table')) { + var $expander = $tableContainer + .children('div:first') + .children('a.expander'); + if ($expander.find('img').is('.ic_b_plus')) { + expandTreeNode($expander); + } + highlightLoadedItem( + $tableContainer.children('div.list_container'), + table, 'table', true, false + ); + } else if ($viewContainer.length > 0) { + highlightView($viewContainer, table); + } + } + + function isItemInContainer($container, name, clazz) + { + $items = $container.find('li.' + clazz); + var found = false; + $items.each(function() { + if ($(this).children('a').text() == name) { + found = true; + return false; + } + }); + return found; + } + + function highlightView($viewContainer, view) { + var $expander = $viewContainer + .children('div:first') + .children('a.expander'); + if (! $expander.hasClass('loaded') + || $expander.find('img').is('.ic_b_plus') + ) { + expandTreeNode($expander, function() { + highlightLoadedItem( + $viewContainer.children('div.list_container'), + view, 'view', true, false + ); + }); + } else { + highlightLoadedItem( + $viewContainer.children('div.list_container'), + view, 'view', true, false + ); + } + } +} + +/** + * Reloads the whole navigation tree while preserving its state + * + * @param function the callback function + * @return void + */ +function PMA_reloadNavigation(callback) { + var params = { + reload: true, + pos: $('#pma_navigation_tree').find('a.expander:first > span.pos').text() + }; + // Traverse the navigation tree backwards to generate all the actual + // and virtual paths, as well as the positions in the pagination at + // various levels, if necessary. + var count = 0; + $('#pma_navigation_tree').find('a.expander:visible').each(function () { + if ($(this).find('img').is('.ic_b_minus') + && $(this).closest('li').find('div.list_container .ic_b_minus').length == 0 + ) { + params['n' + count + '_aPath'] = $(this).find('span.aPath').text(); + params['n' + count + '_vPath'] = $(this).find('span.vPath').text(); + + var pos2_name = $(this).find('span.pos2_name').text(); + if (! pos2_name) { + pos2_name = $(this) + .parent() + .parent() + .find('span.pos2_name:last') + .text(); + } + var pos2_value = $(this).find('span.pos2_value').text(); + if (! pos2_value) { + pos2_value = $(this) + .parent() + .parent() + .find('span.pos2_value:last') + .text(); + } + + params['n' + count + '_pos2_name'] = pos2_name; + params['n' + count + '_pos2_value'] = pos2_value; + + params['n' + count + '_pos3_name'] = $(this).find('span.pos3_name').text(); + params['n' + count + '_pos3_value'] = $(this).find('span.pos3_value').text(); + count++; + } + }); + var url = $('#pma_navigation').find('a.navigation_url').attr('href'); + $.post(url, params, function (data) { + // Hide throbber if it's visible + $('#pma_navigation .throbber') + .first() + .css('visibility', 'hidden'); + if (data.success) { + $('#pma_navigation_tree').html(data.message).children('div').show(); + PMA_showCurrentNavigation(); + // Fire the callback, if any + if (typeof callback === 'function') { + callback.call(); + } + } else { + PMA_ajaxShowMessage(data.error); + } + }); +} + +/** + * Handles any requests to change the page in a branch of a tree + * + * This can be called from link click or select change event handlers + * + * @param object $this A jQuery object that points to the element that + * initiated the action of changing the page + * + * @return void + */ +function PMA_navigationTreePagination($this) +{ + var $msgbox = PMA_ajaxShowMessage(); + var isDbSelector = $this.closest('div.pageselector').is('.dbselector'); + if ($this[0].tagName == 'A') { + var url = $this.attr('href'); + var params = 'ajax_request=true'; + } else { // tagName == 'SELECT' + var url = 'navigation.php'; + var params = $this.closest("form").serialize() + '&ajax_request=true'; + } + var searchClause = PMA_fastFilter.getSearchClause(); + if (searchClause) { + params += '&searchClause=' + encodeURIComponent(searchClause); + } + if (isDbSelector) { + params += '&full=true'; + } else { + var searchClause2 = PMA_fastFilter.getSearchClause2($this); + if (searchClause2) { + params += '&searchClause2=' + encodeURIComponent(searchClause2); + } + } + $.post(url, params, function (data) { + PMA_ajaxRemoveMessage($msgbox); + if (data.success) { + if (isDbSelector) { + var val = PMA_fastFilter.getSearchClause(); + $('#pma_navigation_tree') + .html(data.message) + .children('div') + .show(); + if (val) { + $('#pma_navigation_tree') + .find('li.fast_filter input.searchClause') + .val(val); + } + } else { + var $parent = $this.closest('div.list_container').parent(); + var val = PMA_fastFilter.getSearchClause2($this); + $this.closest('div.list_container').html( + $(data.message).children().show() + ); + if (val) { + $parent.find('li.fast_filter input.searchClause').val(val); + } + $parent.find('span.pos2_value:first').text( + $parent.find('span.pos2_value:last').text() + ); + $parent.find('span.pos3_value:first').text( + $parent.find('span.pos3_value:last').text() + ); + } + } else { + PMA_ajaxShowMessage(data.error); + } + }); +} + +/** + * @var ResizeHandler Custom object that manages the resizing of the navigation + * + * XXX: Must only be ever instanciated once + * XXX: Inside event handlers the 'this' object is accessed as 'event.data.resize_handler' + */ +var ResizeHandler = function () { + /** + * Whether the user has initiated a resize operation + */ + this.active = false; + /** + * @var int panel_width Used by the collapser to know where to go + * back to when uncollapsing the panel + */ + this.panel_width = 0; + /** + * @var string left Used to provide support for RTL languages + */ + this.left = $('html').attr('dir') == 'ltr' ? 'left' : 'right'; + /** + * Adjusts the width of the navigation panel to the specified value + * + * @param int pos Navigation width in pixels + * + * @return void + */ + this.setWidth = function (pos) { + var $resizer = $('#pma_navigation_resizer'); + var resizer_width = $resizer.width(); + var $collapser = $('#pma_navigation_collapser'); + $('#pma_navigation').width(pos); + $('body').css('margin-' + this.left, pos + 'px'); + $("#floating_menubar") + .css('margin-' + this.left, (pos + resizer_width) + 'px'); + $resizer.css(this.left, pos + 'px'); + if (pos === 0) { + $collapser + .css(this.left, pos + resizer_width) + .html(this.getSymbol(pos)) + .prop('title', PMA_messages['strShowPanel']); + } else { + $collapser + .css(this.left, pos) + .html(this.getSymbol(pos)) + .prop('title', PMA_messages['strHidePanel']); + } + setTimeout(function (){ + $(window).trigger('resize'); + }, 4); + }; + /** + * Returns the horizontal position of the mouse, + * relative to the outer side of the navigation panel + * + * @param int pos Navigation width in pixels + * + * @return void + */ + this.getPos = function (event) { + var pos = event.pageX; + var windowWidth = $(window).width(); + if (this.left != 'left') { + pos = windowWidth - event.pageX; + } + if (pos < 0) { + pos = 0; + } else if (pos + 100 >= windowWidth) { + pos = windowWidth - 100; + } else { + this.panel_width = 0; + } + return pos; + }; + /** + * Returns the HTML code for the arrow symbol used in the collapser + * + * @param int width The width of the panel + * + * @return string + */ + this.getSymbol = function (width) { + if (this.left == 'left') { + if (width == 0) { + return '→'; + } else { + return '←'; + } + } else { + if (width == 0) { + return '←'; + } else { + return '→'; + } + } + }; + /** + * Event handler for initiating a resize of the panel + * + * @param object e Event data (contains a reference to resizeHandler) + * + * @return void + */ + this.mousedown = function (event) { + event.preventDefault(); + event.data.resize_handler.active = true; + $('body').css('cursor', 'col-resize'); + }; + /** + * Event handler for terminating a resize of the panel + * + * @param object e Event data (contains a reference to resizeHandler) + * + * @return void + */ + this.mouseup = function (event) { + if (event.data.resize_handler.active) { + event.data.resize_handler.active = false; + $('body').css('cursor', ''); + $.cookie('pma_navi_width', event.data.resize_handler.getPos(event)); + $('#topmenu').menuResizer('resize'); + } + }; + /** + * Event handler for updating the panel during a resize operation + * + * @param object e Event data (contains a reference to resizeHandler) + * + * @return void + */ + this.mousemove = function (event) { + if (event.data && event.data.resize_handler && event.data.resize_handler.active) { + event.preventDefault(); + var pos = event.data.resize_handler.getPos(event); + event.data.resize_handler.setWidth(pos); + } + }; + /** + * Event handler for collapsing the panel + * + * @param object e Event data (contains a reference to resizeHandler) + * + * @return void + */ + this.collapse = function (event) { + event.preventDefault(); + event.data.active = false; + var panel_width = event.data.resize_handler.panel_width; + var width = $('#pma_navigation').width(); + if (width === 0 && panel_width === 0) { + panel_width = 240; + } + event.data.resize_handler.setWidth(panel_width); + event.data.resize_handler.panel_width = width; + }; + /** + * Even thandler for resizing the navigation tree height on window resize + * + * @return void + */ + this.treeResize = function (event) { + var $nav = $("#pma_navigation"), + $nav_tree = $("#pma_navigation_tree"), + $nav_header = $("#pma_navigation_header"), + $nav_tree_content = $("#pma_navigation_tree_content"); + $nav_tree.height($nav.height() - $nav_header.height()); + $nav_tree_content.height($nav_tree.height() - $nav_tree_content.position().top); + }; + /* Initialisation section begins here */ + if ($.cookie('pma_navi_width')) { + // If we have a cookie, set the width of the panel to its value + var pos = Math.abs(parseInt($.cookie('pma_navi_width'), 10) || 0); + this.setWidth(pos); + $('#topmenu').menuResizer('resize'); + } + // Register the events for the resizer and the collapser + $('#pma_navigation_resizer') + .live('mousedown', {'resize_handler':this}, this.mousedown); + $(document) + .bind('mouseup', {'resize_handler':this}, this.mouseup) + .bind('mousemove', {'resize_handler':this}, $.throttle(this.mousemove, 4)); + var $collapser = $('#pma_navigation_collapser'); + $collapser.live('click', {'resize_handler':this}, this.collapse); + // Add the correct arrow symbol to the collapser + $collapser.html(this.getSymbol($('#pma_navigation').width())); + // Fix navigation tree height + $(window).on('resize', this.treeResize); + // need to call this now and then, browser might decide + // to show/hide horizontal scrollbars depending on page content width + setInterval(this.treeResize, 2000); +}; // End of ResizeHandler + +/** + * @var object PMA_fastFilter Handles the functionality that allows filtering + * of the items in a branch of the navigation tree + */ +var PMA_fastFilter = { + /** + * Construct for the asynchronous fast filter functionality + * + * @param object $this A jQuery object pointing to the list container + * which is the nearest parent of the fast filter + * @param string searchClause The query string for the filter + * + * @return new PMA_fastFilter.filter object + */ + filter: function ($this, searchClause) { + /** + * @var object $this A jQuery object pointing to the list container + * which is the nearest parent of the fast filter + */ + this.$this = $this; + /** + * @var bool searchClause The query string for the filter + */ + this.searchClause = searchClause; + /** + * @var object $clone A clone of the original contents + * of the navigation branch before + * the fast filter was applied + */ + this.$clone = $this.clone(); + /** + * @var bool swapped Whether the user clicked on the "N other results" link + */ + this.swapped = false; + /** + * @var object xhr A reference to the ajax request that is currently running + */ + this.xhr = null; + /** + * @var int timeout Used to delay the request for asynchronous search + */ + this.timeout = null; + + var $filterInput = $this.find('li.fast_filter input.searchClause'); + if ( $filterInput.length != 0 + && $filterInput.val() != '' + && $filterInput.val() != $filterInput[0].defaultValue + ) { + this.request(); + } + }, + /** + * Gets the query string from the database fast filter form + * + * @return string + */ + getSearchClause: function () { + var retval = ''; + var $input = $('#pma_navigation_tree') + .find('li.fast_filter.db_fast_filter input.searchClause'); + if ($input.length && $input.val() != $input[0].defaultValue) { + retval = $input.val(); + } + return retval; + }, + /** + * Gets the query string from a second level item's fast filter form + * The retrieval is done by trasversing the navigation tree backwards + * + * @return string + */ + getSearchClause2: function ($this) { + var $filterContainer = $this.closest('div.list_container'); + var $filterInput = $([]); + while (1) { + if ($filterContainer.find('li.fast_filter:not(.db_fast_filter) input.searchClause').length != 0) { + $filterInput = $filterContainer.find('li.fast_filter:not(.db_fast_filter) input.searchClause'); + break; + } else if (! $filterContainer.is('div.list_container')) { + break; + } + $filterContainer = $filterContainer + .parent() + .closest('div.list_container'); + } + var searchClause2 = ''; + if ($filterInput.length != 0 + && $filterInput.first().val() != $filterInput[0].defaultValue + ) { + searchClause2 = $filterInput.val(); + } + return searchClause2; + }, + /** + * @var hash events A list of functions that are bound to DOM events + * at the top of this file + */ + events: { + focus: function (event) { + var $obj = $(this).closest('div.list_container'); + if (! $obj.data('fastFilter')) { + $obj.data( + 'fastFilter', + new PMA_fastFilter.filter($obj, $(this).val()) + ); + } + if ($(this).val() == this.defaultValue) { + $(this).val(''); + } else { + $(this).select(); + } + }, + blur: function (event) { + if ($(this).val() == '') { + $(this).val(this.defaultValue); + } + var $obj = $(this).closest('div.list_container'); + if ($(this).val() == this.defaultValue && $obj.data('fastFilter')) { + $obj.data('fastFilter').restore(); + } + }, + keyup: function (event) { + var $obj = $(this).closest('div.list_container'); + var str = ''; + if ($(this).val() != this.defaultValue && $(this).val() != '') { + $obj.find('div.pageselector').hide(); + str = $(this).val().toLowerCase(); + } + $obj.find('li > a').not('.container').each(function () { + if ($(this).text().toLowerCase().indexOf(str) != -1) { + $(this).parent().show().removeClass('hidden'); + } else { + $(this).parent().hide().addClass('hidden'); + } + }); + var container_filter = function ($curr, str) { + $curr.children('li').children('a.container').each(function () { + var $group = $(this).parent().children('ul'); + if ($group.children('li').children('a.container').length > 0) { + container_filter($group); // recursive + } + $group.parent().show().removeClass('hidden'); + if ($group.children().not('.hidden').length == 0) { + $group.parent().hide().addClass('hidden'); + } + }); + }; + container_filter($obj, str); + if ($(this).val() != this.defaultValue && $(this).val() != '') { + if (! $obj.data('fastFilter')) { + $obj.data( + 'fastFilter', + new PMA_fastFilter.filter($obj, $(this).val()) + ); + } else { + $obj.data('fastFilter').update($(this).val()); + } + } else if ($obj.data('fastFilter')) { + $obj.data('fastFilter').restore(true); + } + }, + clear: function (event) { + event.stopPropagation(); + // Clear the input and apply the fast filter with empty input + var filter = $(this).closest('div.list_container').data('fastFilter'); + if (filter) { + filter.restore(); + } + var value = $(this).prev()[0].defaultValue; + $(this).prev().val(value).trigger('keyup'); + } + } +}; +/** + * Handles a change in the search clause + * + * @param string searchClause The query string for the filter + * + * @return void + */ +PMA_fastFilter.filter.prototype.update = function (searchClause) +{ + if (this.searchClause != searchClause) { + this.searchClause = searchClause; + this.$this.find('.moreResults').remove(); + this.request(); + } +}; +/** + * After a delay of 250mS, initiates a request to retrieve search results + * Multiple calls to this function will always abort the previous request + * + * @return void + */ +PMA_fastFilter.filter.prototype.request = function () +{ + var self = this; + clearTimeout(self.timeout); + if (self.$this.find('li.fast_filter').find('img.throbber').length == 0) { + self.$this.find('li.fast_filter').append( + $('<div class="throbber"></div>').append( + $('#pma_navigation_content') + .find('img.throbber') + .clone() + .css('visibility', 'visible') + ) + ); + } + self.timeout = setTimeout(function () { + if (self.xhr) { + self.xhr.abort(); + } + var url = $('#pma_navigation').find('a.navigation_url').attr('href'); + var results = self.$this.find('li:not(.hidden):not(.fast_filter):not(.navGroup)').not('[class^=new]').length; + var params = self.$this.find('> ul > li > form.fast_filter').first().serialize() + "&results=" + results; + if (self.$this.find('> ul > li > form.fast_filter:first input[name=searchClause]').length == 0) { + var $input = $('#pma_navigation_tree').find('li.fast_filter.db_fast_filter input.searchClause'); + if ($input.length && $input.val() != $input[0].defaultValue) { + params += '&searchClause=' + encodeURIComponent($input.val()); + } + } + self.xhr = $.ajax({ + url: url, + type: 'post', + dataType: 'json', + data: params, + complete: function (jqXHR) { + var data = $.parseJSON(jqXHR.responseText); + self.$this.find('li.fast_filter').find('div.throbber').remove(); + if (data && data.results) { + var $listItem = $('<li />', {'class':'moreResults'}) + .appendTo(self.$this.find('li.fast_filter')); + var $link = $('<a />', {href:'#'}) + .text(data.results) + .appendTo($listItem) + .click(function (event) { + event.preventDefault(); + self.swap.apply(self, [data.message]); + }); + } + } + }); + }, 250); +}; +/** + * Replaces the contents of the navigation branch with the search results + * + * @param string list The search results + * + * @return void + */ +PMA_fastFilter.filter.prototype.swap = function (list) +{ + this.swapped = true; + this.$this + .html($(list).html()) + .children() + .show() + .end() + .find('li.fast_filter input.searchClause') + .val(this.searchClause); + this.$this.data('fastFilter', this); +}; +/** + * Restores the navigation to the original state after the fast filter is cleared + * + * @param bool focus Whether to also focus the input box of the fast filter + * + * @return void + */ +PMA_fastFilter.filter.prototype.restore = function (focus) +{ + if (this.swapped) { + this.swapped = false; + this.$this.html(this.$clone.html()).children().show(); + this.$this.data('fastFilter', this); + if (focus) { + this.$this.find('li.fast_filter input.searchClause').focus(); + } + } + this.searchClause = ''; + this.$this.find('.moreResults').remove(); + this.$this.find('div.pageselector').show(); + this.$this.find('div.throbber').remove(); +}; diff --git a/hugo/js/openlayers/OpenLayers.js b/hugo/js/openlayers/OpenLayers.js new file mode 100644 index 0000000..b9efb11 --- /dev/null +++ b/hugo/js/openlayers/OpenLayers.js @@ -0,0 +1,2681 @@ +/* + + OpenLayers.js -- OpenLayers Map Viewer Library + + Copyright 2005-2010 OpenLayers Contributors, released under the Clear BSD + license. Please see http://svn.openlayers.org/trunk/openlayers/license.txt + for the full text of the license. + + Includes compressed code under the following licenses: + + (For uncompressed versions of the code used please see the + OpenLayers SVN repository: <http://openlayers.org/>) + +*/ + +/* Contains portions of Prototype.js: + * + * Prototype JavaScript framework, version 1.4.0 + * (c) 2005 Sam Stephenson <sam@conio.net> + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://prototype.conio.net/ + * + *--------------------------------------------------------------------------*/ + +/** +* +* Contains portions of Rico <http://openrico.org/> +* +* 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. +* +**/ + +/** + * Contains XMLHttpRequest.js <http://code.google.com/p/xmlhttprequest/> + * 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 + */ + +/** + * Contains portions of Gears <http://code.google.com/apis/gears/> + * + * Copyright 2007, Google Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * 3. Neither the name of Google Inc. nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + * Sets up google.gears.*, which is *the only* supported way to access Gears. + * + * Circumvent this file at your own risk! + * + * In the future, Gears may automatically define google.gears.* without this + * file. Gears may use these objects to transparently fix bugs and compatibility + * issues. Applications that use the code below will continue to work seamlessly + * when that happens. + */ +var OpenLayers={singleFile:true};(function(){var singleFile=(typeof OpenLayers=="object"&&OpenLayers.singleFile);var scriptLocation="js/openlayers/";window.OpenLayers={_scriptName:(!singleFile)?"lib/OpenLayers.js":"OpenLayers.js",_getScriptLocation:function(){if(scriptLocation!=undefined){return scriptLocation;} +scriptLocation="";var isOL=new RegExp("(^|(.*?\\/))("+OpenLayers._scriptName+")(\\?|$)");var scripts=document.getElementsByTagName('script');for(var i=0,len=scripts.length;i<len;i++){var src=scripts[i].getAttribute('src');if(src){var match=src.match(isOL);if(match){scriptLocation=match[1];break;}}} +return scriptLocation;}};if(!singleFile){var jsfiles=new Array("OpenLayers/Util.js","OpenLayers/BaseTypes.js","OpenLayers/BaseTypes/Class.js","OpenLayers/BaseTypes/Bounds.js","OpenLayers/BaseTypes/Element.js","OpenLayers/BaseTypes/LonLat.js","OpenLayers/BaseTypes/Pixel.js","OpenLayers/BaseTypes/Size.js","OpenLayers/Console.js","OpenLayers/Tween.js","Rico/Corner.js","Rico/Color.js","OpenLayers/Ajax.js","OpenLayers/Events.js","OpenLayers/Request.js","OpenLayers/Request/XMLHttpRequest.js","OpenLayers/Projection.js","OpenLayers/Map.js","OpenLayers/Layer.js","OpenLayers/Icon.js","OpenLayers/Marker.js","OpenLayers/Marker/Box.js","OpenLayers/Popup.js","OpenLayers/Tile.js","OpenLayers/Tile/Image.js","OpenLayers/Tile/Image/IFrame.js","OpenLayers/Tile/WFS.js","OpenLayers/Layer/Image.js","OpenLayers/Layer/SphericalMercator.js","OpenLayers/Layer/EventPane.js","OpenLayers/Layer/FixedZoomLevels.js","OpenLayers/Layer/Google.js","OpenLayers/Layer/Google/v3.js","OpenLayers/Layer/VirtualEarth.js","OpenLayers/Layer/Yahoo.js","OpenLayers/Layer/HTTPRequest.js","OpenLayers/Layer/Grid.js","OpenLayers/Layer/MapGuide.js","OpenLayers/Layer/MapServer.js","OpenLayers/Layer/MapServer/Untiled.js","OpenLayers/Layer/KaMap.js","OpenLayers/Layer/KaMapCache.js","OpenLayers/Layer/MultiMap.js","OpenLayers/Layer/Markers.js","OpenLayers/Layer/Text.js","OpenLayers/Layer/WorldWind.js","OpenLayers/Layer/ArcGIS93Rest.js","OpenLayers/Layer/WMS.js","OpenLayers/Layer/WMS/Untiled.js","OpenLayers/Layer/WMS/Post.js","OpenLayers/Layer/WMTS.js","OpenLayers/Layer/ArcIMS.js","OpenLayers/Layer/GeoRSS.js","OpenLayers/Layer/Boxes.js","OpenLayers/Layer/XYZ.js","OpenLayers/Layer/TMS.js","OpenLayers/Layer/TileCache.js","OpenLayers/Layer/Zoomify.js","OpenLayers/Popup/Anchored.js","OpenLayers/Popup/AnchoredBubble.js","OpenLayers/Popup/Framed.js","OpenLayers/Popup/FramedCloud.js","OpenLayers/Feature.js","OpenLayers/Feature/Vector.js","OpenLayers/Feature/WFS.js","OpenLayers/Handler.js","OpenLayers/Handler/Click.js","OpenLayers/Handler/Hover.js","OpenLayers/Handler/Point.js","OpenLayers/Handler/Path.js","OpenLayers/Handler/Polygon.js","OpenLayers/Handler/Feature.js","OpenLayers/Handler/Drag.js","OpenLayers/Handler/RegularPolygon.js","OpenLayers/Handler/Box.js","OpenLayers/Handler/MouseWheel.js","OpenLayers/Handler/Keyboard.js","OpenLayers/Control.js","OpenLayers/Control/Attribution.js","OpenLayers/Control/Button.js","OpenLayers/Control/ZoomBox.js","OpenLayers/Control/ZoomToMaxExtent.js","OpenLayers/Control/DragPan.js","OpenLayers/Control/Navigation.js","OpenLayers/Control/MouseDefaults.js","OpenLayers/Control/MousePosition.js","OpenLayers/Control/OverviewMap.js","OpenLayers/Control/KeyboardDefaults.js","OpenLayers/Control/PanZoom.js","OpenLayers/Control/PanZoomBar.js","OpenLayers/Control/ArgParser.js","OpenLayers/Control/Permalink.js","OpenLayers/Control/Scale.js","OpenLayers/Control/ScaleLine.js","OpenLayers/Control/Snapping.js","OpenLayers/Control/Split.js","OpenLayers/Control/LayerSwitcher.js","OpenLayers/Control/DrawFeature.js","OpenLayers/Control/DragFeature.js","OpenLayers/Control/ModifyFeature.js","OpenLayers/Control/Panel.js","OpenLayers/Control/SelectFeature.js","OpenLayers/Control/NavigationHistory.js","OpenLayers/Control/Measure.js","OpenLayers/Control/WMSGetFeatureInfo.js","OpenLayers/Control/WMTSGetFeatureInfo.js","OpenLayers/Control/Graticule.js","OpenLayers/Control/TransformFeature.js","OpenLayers/Control/SLDSelect.js","OpenLayers/Geometry.js","OpenLayers/Geometry/Rectangle.js","OpenLayers/Geometry/Collection.js","OpenLayers/Geometry/Point.js","OpenLayers/Geometry/MultiPoint.js","OpenLayers/Geometry/Curve.js","OpenLayers/Geometry/LineString.js","OpenLayers/Geometry/LinearRing.js","OpenLayers/Geometry/Polygon.js","OpenLayers/Geometry/MultiLineString.js","OpenLayers/Geometry/MultiPolygon.js","OpenLayers/Geometry/Surface.js","OpenLayers/Renderer.js","OpenLayers/Renderer/Elements.js","OpenLayers/Renderer/SVG.js","OpenLayers/Renderer/Canvas.js","OpenLayers/Renderer/VML.js","OpenLayers/Layer/Vector.js","OpenLayers/Layer/Vector/RootContainer.js","OpenLayers/Strategy.js","OpenLayers/Strategy/Filter.js","OpenLayers/Strategy/Fixed.js","OpenLayers/Strategy/Cluster.js","OpenLayers/Strategy/Paging.js","OpenLayers/Strategy/BBOX.js","OpenLayers/Strategy/Save.js","OpenLayers/Strategy/Refresh.js","OpenLayers/Filter.js","OpenLayers/Filter/FeatureId.js","OpenLayers/Filter/Logical.js","OpenLayers/Filter/Comparison.js","OpenLayers/Filter/Spatial.js","OpenLayers/Protocol.js","OpenLayers/Protocol/HTTP.js","OpenLayers/Protocol/SQL.js","OpenLayers/Protocol/SQL/Gears.js","OpenLayers/Protocol/WFS.js","OpenLayers/Protocol/WFS/v1.js","OpenLayers/Protocol/WFS/v1_0_0.js","OpenLayers/Protocol/WFS/v1_1_0.js","OpenLayers/Protocol/SOS.js","OpenLayers/Protocol/SOS/v1_0_0.js","OpenLayers/Layer/PointTrack.js","OpenLayers/Layer/GML.js","OpenLayers/Style.js","OpenLayers/Style2.js","OpenLayers/StyleMap.js","OpenLayers/Rule.js","OpenLayers/Format.js","OpenLayers/Format/XML.js","OpenLayers/Format/Context.js","OpenLayers/Format/ArcXML.js","OpenLayers/Format/ArcXML/Features.js","OpenLayers/Format/GML.js","OpenLayers/Format/GML/Base.js","OpenLayers/Format/GML/v2.js","OpenLayers/Format/GML/v3.js","OpenLayers/Format/Atom.js","OpenLayers/Format/KML.js","OpenLayers/Format/GeoRSS.js","OpenLayers/Format/WFS.js","OpenLayers/Format/WFSCapabilities.js","OpenLayers/Format/WFSCapabilities/v1.js","OpenLayers/Format/WFSCapabilities/v1_0_0.js","OpenLayers/Format/WFSCapabilities/v1_1_0.js","OpenLayers/Format/WFSDescribeFeatureType.js","OpenLayers/Format/WMSDescribeLayer.js","OpenLayers/Format/WMSDescribeLayer/v1_1.js","OpenLayers/Format/WKT.js","OpenLayers/Format/OSM.js","OpenLayers/Format/GPX.js","OpenLayers/Format/Filter.js","OpenLayers/Format/Filter/v1.js","OpenLayers/Format/Filter/v1_0_0.js","OpenLayers/Format/Filter/v1_1_0.js","OpenLayers/Format/SLD.js","OpenLayers/Format/SLD/v1.js","OpenLayers/Format/SLD/v1_0_0.js","OpenLayers/Format/OWSCommon/v1.js","OpenLayers/Format/OWSCommon/v1_0_0.js","OpenLayers/Format/OWSCommon/v1_1_0.js","OpenLayers/Format/CSWGetDomain.js","OpenLayers/Format/CSWGetDomain/v2_0_2.js","OpenLayers/Format/CSWGetRecords.js","OpenLayers/Format/CSWGetRecords/v2_0_2.js","OpenLayers/Format/WFST.js","OpenLayers/Format/WFST/v1.js","OpenLayers/Format/WFST/v1_0_0.js","OpenLayers/Format/WFST/v1_1_0.js","OpenLayers/Format/Text.js","OpenLayers/Format/JSON.js","OpenLayers/Format/GeoJSON.js","OpenLayers/Format/WMC.js","OpenLayers/Format/WMC/v1.js","OpenLayers/Format/WMC/v1_0_0.js","OpenLayers/Format/WMC/v1_1_0.js","OpenLayers/Format/WMSCapabilities.js","OpenLayers/Format/WMSCapabilities/v1.js","OpenLayers/Format/WMSCapabilities/v1_1.js","OpenLayers/Format/WMSCapabilities/v1_1_0.js","OpenLayers/Format/WMSCapabilities/v1_1_1.js","OpenLayers/Format/WMSCapabilities/v1_3.js","OpenLayers/Format/WMSCapabilities/v1_3_0.js","OpenLayers/Format/WMSGetFeatureInfo.js","OpenLayers/Format/SOSCapabilities.js","OpenLayers/Format/SOSCapabilities/v1_0_0.js","OpenLayers/Format/SOSGetObservation.js","OpenLayers/Format/SOSGetFeatureOfInterest.js","OpenLayers/Format/OWSContext.js","OpenLayers/Format/OWSContext/v0_3_1.js","OpenLayers/Format/WMTSCapabilities.js","OpenLayers/Format/WMTSCapabilities/v1_0_0.js","OpenLayers/Layer/WFS.js","OpenLayers/Control/GetFeature.js","OpenLayers/Control/MouseToolbar.js","OpenLayers/Control/NavToolbar.js","OpenLayers/Control/PanPanel.js","OpenLayers/Control/Pan.js","OpenLayers/Control/ZoomIn.js","OpenLayers/Control/ZoomOut.js","OpenLayers/Control/ZoomPanel.js","OpenLayers/Control/EditingToolbar.js","OpenLayers/Symbolizer.js","OpenLayers/Symbolizer/Point.js","OpenLayers/Symbolizer/Line.js","OpenLayers/Symbolizer/Polygon.js","OpenLayers/Symbolizer/Text.js","OpenLayers/Symbolizer/Raster.js","OpenLayers/Lang.js","OpenLayers/Lang/en.js");var agent=navigator.userAgent;var docWrite=(agent.match("MSIE")||agent.match("Safari"));if(docWrite){var allScriptTags=new Array(jsfiles.length);} +var host=OpenLayers._getScriptLocation()+"lib/";for(var i=0,len=jsfiles.length;i<len;i++){if(docWrite){allScriptTags[i]="<script src='"+host+jsfiles[i]+"'></script>";}else{var s=document.createElement("script");s.src=host+jsfiles[i];var h=document.getElementsByTagName("head").length?document.getElementsByTagName("head")[0]:document.body;h.appendChild(s);}} +if(docWrite){document.write(allScriptTags.join(""));}}})();OpenLayers.VERSION_NUMBER="OpenLayers 2.10 -- $Revision: 10721 $";OpenLayers.String={startsWith:function(str,sub){return(str.indexOf(sub)==0);},contains:function(str,sub){return(str.indexOf(sub)!=-1);},trim:function(str){return str.replace(/^\s\s*/,'').replace(/\s\s*$/,'');},camelize:function(str){var oStringList=str.split('-');var camelizedString=oStringList[0];for(var i=1,len=oStringList.length;i<len;i++){var s=oStringList[i];camelizedString+=s.charAt(0).toUpperCase()+s.substring(1);} +return camelizedString;},format:function(template,context,args){if(!context){context=window;} +var replacer=function(str,match){var replacement;var subs=match.split(/\.+/);for(var i=0;i<subs.length;i++){if(i==0){replacement=context;} +replacement=replacement[subs[i]];} +if(typeof replacement=="function"){replacement=args?replacement.apply(null,args):replacement();} +if(typeof replacement=='undefined'){return'undefined';}else{return replacement;}};return template.replace(OpenLayers.String.tokenRegEx,replacer);},tokenRegEx:/\$\{([\w.]+?)\}/g,numberRegEx:/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/,isNumeric:function(value){return OpenLayers.String.numberRegEx.test(value);},numericIf:function(value){return OpenLayers.String.isNumeric(value)?parseFloat(value):value;}};if(!String.prototype.startsWith){String.prototype.startsWith=function(sStart){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.String.startsWith'}));return OpenLayers.String.startsWith(this,sStart);};} +if(!String.prototype.contains){String.prototype.contains=function(str){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.String.contains'}));return OpenLayers.String.contains(this,str);};} +if(!String.prototype.trim){String.prototype.trim=function(){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.String.trim'}));return OpenLayers.String.trim(this);};} +if(!String.prototype.camelize){String.prototype.camelize=function(){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.String.camelize'}));return OpenLayers.String.camelize(this);};} +OpenLayers.Number={decimalSeparator:".",thousandsSeparator:",",limitSigDigs:function(num,sig){var fig=0;if(sig>0){fig=parseFloat(num.toPrecision(sig));} +return fig;},format:function(num,dec,tsep,dsep){dec=(typeof dec!="undefined")?dec:0;tsep=(typeof tsep!="undefined")?tsep:OpenLayers.Number.thousandsSeparator;dsep=(typeof dsep!="undefined")?dsep:OpenLayers.Number.decimalSeparator;if(dec!=null){num=parseFloat(num.toFixed(dec));} +var parts=num.toString().split(".");if(parts.length==1&&dec==null){dec=0;} +var integer=parts[0];if(tsep){var thousands=/(-?[0-9]+)([0-9]{3})/;while(thousands.test(integer)){integer=integer.replace(thousands,"$1"+tsep+"$2");}} +var str;if(dec==0){str=integer;}else{var rem=parts.length>1?parts[1]:"0";if(dec!=null){rem=rem+new Array(dec-rem.length+1).join("0");} +str=integer+dsep+rem;} +return str;}};if(!Number.prototype.limitSigDigs){Number.prototype.limitSigDigs=function(sig){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.Number.limitSigDigs'}));return OpenLayers.Number.limitSigDigs(this,sig);};} +OpenLayers.Function={bind:function(func,object){var args=Array.prototype.slice.apply(arguments,[2]);return function(){var newArgs=args.concat(Array.prototype.slice.apply(arguments,[0]));return func.apply(object,newArgs);};},bindAsEventListener:function(func,object){return function(event){return func.call(object,event||window.event);};},False:function(){return false;},True:function(){return true;}};if(!Function.prototype.bind){Function.prototype.bind=function(){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.Function.bind'}));Array.prototype.unshift.apply(arguments,[this]);return OpenLayers.Function.bind.apply(null,arguments);};} +if(!Function.prototype.bindAsEventListener){Function.prototype.bindAsEventListener=function(object){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.Function.bindAsEventListener'}));return OpenLayers.Function.bindAsEventListener(this,object);};} +OpenLayers.Array={filter:function(array,callback,caller){var selected=[];if(Array.prototype.filter){selected=array.filter(callback,caller);}else{var len=array.length;if(typeof callback!="function"){throw new TypeError();} +for(var i=0;i<len;i++){if(i in array){var val=array[i];if(callback.call(caller,val,i,array)){selected.push(val);}}}} +return selected;}};OpenLayers.Date={toISOString:(function(){if("toISOString"in Date.prototype){return function(date){return date.toISOString();}}else{function pad(num,len){var str=num+"";while(str.length<len){str="0"+str;} +return str;} +return function(date){var str;if(isNaN(date.getTime())){str="Invalid Date";}else{str=date.getUTCFullYear()+"-"+ +pad(date.getUTCMonth()+1,2)+"-"+ +pad(date.getUTCDate(),2)+"T"+ +pad(date.getUTCHours(),2)+":"+ +pad(date.getUTCMinutes(),2)+":"+ +pad(date.getUTCSeconds(),2)+"."+ +pad(date.getUTCMilliseconds(),3)+"Z";} +return str;}}})(),parse:function(str){var date;var elapsed=Date.parse(str);if(!isNaN(elapsed)){date=new Date(elapsed);}else{var match=str.match(/^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:T(\d{1,2}):(\d{2}):(\d{2}(?:\.\d+)?)(Z|(?:[+-]\d{1,2}(?::(\d{2}))?)))?$/);var date;if(match&&(match[1]||match[7])){var year=parseInt(match[1],10)||0;var month=(parseInt(match[2],10)-1)||0;var day=parseInt(match[3],10)||1;date=new Date(Date.UTC(year,month,day));var type=match[7];if(type){var hours=parseInt(match[4],10);var minutes=parseInt(match[5],10);var secFrac=parseFloat(match[6]);var seconds=secFrac|0;var milliseconds=Math.round(1000*(secFrac-seconds));date.setUTCHours(hours,minutes,seconds,milliseconds);if(type!=="Z"){var hoursOffset=parseInt(type,10);var minutesOffset=parseInt(match[8])||0;var offset=-1000*(60*(hoursOffset*60)+minutesOffset*60);date=new Date(date.getTime()+offset);}}}else{date=new Date("invalid");}} +return date;}};OpenLayers.Class=function(){var Class=function(){if(arguments&&arguments[0]!=OpenLayers.Class.isPrototype){this.initialize.apply(this,arguments);}};var extended={};var parent,initialize,Type;for(var i=0,len=arguments.length;i<len;++i){Type=arguments[i];if(typeof Type=="function"){if(i==0&&len>1){initialize=Type.prototype.initialize;Type.prototype.initialize=function(){};extended=new Type();if(initialize===undefined){delete Type.prototype.initialize;}else{Type.prototype.initialize=initialize;}} +parent=Type.prototype;}else{parent=Type;} +OpenLayers.Util.extend(extended,parent);} +Class.prototype=extended;return Class;};OpenLayers.Class.isPrototype=function(){};OpenLayers.Class.create=function(){return function(){if(arguments&&arguments[0]!=OpenLayers.Class.isPrototype){this.initialize.apply(this,arguments);}};};OpenLayers.Class.inherit=function(){var superClass=arguments[0];var proto=new superClass(OpenLayers.Class.isPrototype);for(var i=1,len=arguments.length;i<len;i++){if(typeof arguments[i]=="function"){var mixin=arguments[i];arguments[i]=new mixin(OpenLayers.Class.isPrototype);} +OpenLayers.Util.extend(proto,arguments[i]);} +return proto;};OpenLayers.Util={};OpenLayers.Util.getElement=function(){var elements=[];for(var i=0,len=arguments.length;i<len;i++){var element=arguments[i];if(typeof element=='string'){element=document.getElementById(element);} +if(arguments.length==1){return element;} +elements.push(element);} +return elements;};OpenLayers.Util.isElement=function(o){return!!(o&&o.nodeType===1);};if(typeof window.$==="undefined"){window.$=OpenLayers.Util.getElement;} +OpenLayers.Util.extend=function(destination,source){destination=destination||{};if(source){for(var property in source){var value=source[property];if(value!==undefined){destination[property]=value;}} +var sourceIsEvt=typeof window.Event=="function"&&source instanceof window.Event;if(!sourceIsEvt&&source.hasOwnProperty&&source.hasOwnProperty('toString')){destination.toString=source.toString;}} +return destination;};OpenLayers.Util.removeItem=function(array,item){for(var i=array.length-1;i>=0;i--){if(array[i]==item){array.splice(i,1);}} +return array;};OpenLayers.Util.clearArray=function(array){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'array = []'}));array.length=0;};OpenLayers.Util.indexOf=function(array,obj){if(typeof array.indexOf=="function"){return array.indexOf(obj);}else{for(var i=0,len=array.length;i<len;i++){if(array[i]==obj){return i;}} +return-1;}};OpenLayers.Util.modifyDOMElement=function(element,id,px,sz,position,border,overflow,opacity){if(id){element.id=id;} +if(px){element.style.left=px.x+"px";element.style.top=px.y+"px";} +if(sz){element.style.width=sz.w+"px";element.style.height=sz.h+"px";} +if(position){element.style.position=position;} +if(border){element.style.border=border;} +if(overflow){element.style.overflow=overflow;} +if(parseFloat(opacity)>=0.0&&parseFloat(opacity)<1.0){element.style.filter='alpha(opacity='+(opacity*100)+')';element.style.opacity=opacity;}else if(parseFloat(opacity)==1.0){element.style.filter='';element.style.opacity='';}};OpenLayers.Util.createDiv=function(id,px,sz,imgURL,position,border,overflow,opacity){var dom=document.createElement('div');if(imgURL){dom.style.backgroundImage='url('+imgURL+')';} +if(!id){id=OpenLayers.Util.createUniqueID("OpenLayersDiv");} +if(!position){position="absolute";} +OpenLayers.Util.modifyDOMElement(dom,id,px,sz,position,border,overflow,opacity);return dom;};OpenLayers.Util.createImage=function(id,px,sz,imgURL,position,border,opacity,delayDisplay){var image=document.createElement("img");if(!id){id=OpenLayers.Util.createUniqueID("OpenLayersDiv");} +if(!position){position="relative";} +OpenLayers.Util.modifyDOMElement(image,id,px,sz,position,border,null,opacity);if(delayDisplay){image.style.display="none";OpenLayers.Event.observe(image,"load",OpenLayers.Function.bind(OpenLayers.Util.onImageLoad,image));OpenLayers.Event.observe(image,"error",OpenLayers.Function.bind(OpenLayers.Util.onImageLoadError,image));} +image.style.alt=id;image.galleryImg="no";if(imgURL){image.src=imgURL;} +return image;};OpenLayers.Util.setOpacity=function(element,opacity){OpenLayers.Util.modifyDOMElement(element,null,null,null,null,null,null,opacity);};OpenLayers.Util.onImageLoad=function(){if(!this.viewRequestID||(this.map&&this.viewRequestID==this.map.viewRequestID)){this.style.display="";} +OpenLayers.Element.removeClass(this,"olImageLoadError");};OpenLayers.IMAGE_RELOAD_ATTEMPTS=0;OpenLayers.Util.onImageLoadError=function(){this._attempts=(this._attempts)?(this._attempts+1):1;if(this._attempts<=OpenLayers.IMAGE_RELOAD_ATTEMPTS){var urls=this.urls;if(urls&&urls instanceof Array&&urls.length>1){var src=this.src.toString();var current_url,k;for(k=0;current_url=urls[k];k++){if(src.indexOf(current_url)!=-1){break;}} +var guess=Math.floor(urls.length*Math.random());var new_url=urls[guess];k=0;while(new_url==current_url&&k++<4){guess=Math.floor(urls.length*Math.random());new_url=urls[guess];} +this.src=src.replace(current_url,new_url);}else{this.src=this.src;}}else{OpenLayers.Element.addClass(this,"olImageLoadError");} +this.style.display="";};OpenLayers.Util.alphaHackNeeded=null;OpenLayers.Util.alphaHack=function(){if(OpenLayers.Util.alphaHackNeeded==null){var arVersion=navigator.appVersion.split("MSIE");var version=parseFloat(arVersion[1]);var filter=false;try{filter=!!(document.body.filters);}catch(e){} +OpenLayers.Util.alphaHackNeeded=(filter&&(version>=5.5)&&(version<7));} +return OpenLayers.Util.alphaHackNeeded;};OpenLayers.Util.modifyAlphaImageDiv=function(div,id,px,sz,imgURL,position,border,sizing,opacity){OpenLayers.Util.modifyDOMElement(div,id,px,sz,position,null,null,opacity);var img=div.childNodes[0];if(imgURL){img.src=imgURL;} +OpenLayers.Util.modifyDOMElement(img,div.id+"_innerImage",null,sz,"relative",border);if(OpenLayers.Util.alphaHack()){if(div.style.display!="none"){div.style.display="inline-block";} +if(sizing==null){sizing="scale";} +div.style.filter="progid:DXImageTransform.Microsoft"+".AlphaImageLoader(src='"+img.src+"', "+"sizingMethod='"+sizing+"')";if(parseFloat(div.style.opacity)>=0.0&&parseFloat(div.style.opacity)<1.0){div.style.filter+=" alpha(opacity="+div.style.opacity*100+")";} +img.style.filter="alpha(opacity=0)";}};OpenLayers.Util.createAlphaImageDiv=function(id,px,sz,imgURL,position,border,sizing,opacity,delayDisplay){var div=OpenLayers.Util.createDiv();var img=OpenLayers.Util.createImage(null,null,null,null,null,null,null,false);div.appendChild(img);if(delayDisplay){img.style.display="none";OpenLayers.Event.observe(img,"load",OpenLayers.Function.bind(OpenLayers.Util.onImageLoad,div));OpenLayers.Event.observe(img,"error",OpenLayers.Function.bind(OpenLayers.Util.onImageLoadError,div));} +OpenLayers.Util.modifyAlphaImageDiv(div,id,px,sz,imgURL,position,border,sizing,opacity);return div;};OpenLayers.Util.upperCaseObject=function(object){var uObject={};for(var key in object){uObject[key.toUpperCase()]=object[key];} +return uObject;};OpenLayers.Util.applyDefaults=function(to,from){to=to||{};var fromIsEvt=typeof window.Event=="function"&&from instanceof window.Event;for(var key in from){if(to[key]===undefined||(!fromIsEvt&&from.hasOwnProperty&&from.hasOwnProperty(key)&&!to.hasOwnProperty(key))){to[key]=from[key];}} +if(!fromIsEvt&&from&&from.hasOwnProperty&&from.hasOwnProperty('toString')&&!to.hasOwnProperty('toString')){to.toString=from.toString;} +return to;};OpenLayers.Util.getParameterString=function(params){var paramsArray=[];for(var key in params){var value=params[key];if((value!=null)&&(typeof value!='function')){var encodedValue;if(typeof value=='object'&&value.constructor==Array){var encodedItemArray=[];var item;for(var itemIndex=0,len=value.length;itemIndex<len;itemIndex++){item=value[itemIndex];encodedItemArray.push(encodeURIComponent((item===null||item===undefined)?"":item));} +encodedValue=encodedItemArray.join(",");} +else{encodedValue=encodeURIComponent(value);} +paramsArray.push(encodeURIComponent(key)+"="+encodedValue);}} +return paramsArray.join("&");};OpenLayers.Util.urlAppend=function(url,paramStr){var newUrl=url;if(paramStr){var parts=(url+" ").split(/[?&]/);newUrl+=(parts.pop()===" "?paramStr:parts.length?"&"+paramStr:"?"+paramStr);} +return newUrl;};OpenLayers.ImgPath='';OpenLayers.Util.getImagesLocation=function(){return OpenLayers.ImgPath||(OpenLayers._getScriptLocation()+"img/");};OpenLayers.Util.Try=function(){var returnValue=null;for(var i=0,len=arguments.length;i<len;i++){var lambda=arguments[i];try{returnValue=lambda();break;}catch(e){}} +return returnValue;};OpenLayers.Util.getNodes=function(p,tagName){var nodes=OpenLayers.Util.Try(function(){return OpenLayers.Util._getNodes(p.documentElement.childNodes,tagName);},function(){return OpenLayers.Util._getNodes(p.childNodes,tagName);});return nodes;};OpenLayers.Util._getNodes=function(nodes,tagName){var retArray=[];for(var i=0,len=nodes.length;i<len;i++){if(nodes[i].nodeName==tagName){retArray.push(nodes[i]);}} +return retArray;};OpenLayers.Util.getTagText=function(parent,item,index){var result=OpenLayers.Util.getNodes(parent,item);if(result&&(result.length>0)) +{if(!index){index=0;} +if(result[index].childNodes.length>1){return result.childNodes[1].nodeValue;} +else if(result[index].childNodes.length==1){return result[index].firstChild.nodeValue;}}else{return"";}};OpenLayers.Util.getXmlNodeValue=function(node){var val=null;OpenLayers.Util.Try(function(){val=node.text;if(!val){val=node.textContent;} +if(!val){val=node.firstChild.nodeValue;}},function(){val=node.textContent;});return val;};OpenLayers.Util.mouseLeft=function(evt,div){var target=(evt.relatedTarget)?evt.relatedTarget:evt.toElement;while(target!=div&&target!=null){target=target.parentNode;} +return(target!=div);};OpenLayers.Util.DEFAULT_PRECISION=14;OpenLayers.Util.toFloat=function(number,precision){if(precision==null){precision=OpenLayers.Util.DEFAULT_PRECISION;} +var number;if(precision==0){number=parseFloat(number);}else{number=parseFloat(parseFloat(number).toPrecision(precision));} +return number;};OpenLayers.Util.rad=function(x){return x*Math.PI/180;};OpenLayers.Util.deg=function(x){return x*180/Math.PI;};OpenLayers.Util.VincentyConstants={a:6378137,b:6356752.3142,f:1/298.257223563};OpenLayers.Util.distVincenty=function(p1,p2){var ct=OpenLayers.Util.VincentyConstants;var a=ct.a,b=ct.b,f=ct.f;var L=OpenLayers.Util.rad(p2.lon-p1.lon);var U1=Math.atan((1-f)*Math.tan(OpenLayers.Util.rad(p1.lat)));var U2=Math.atan((1-f)*Math.tan(OpenLayers.Util.rad(p2.lat)));var sinU1=Math.sin(U1),cosU1=Math.cos(U1);var sinU2=Math.sin(U2),cosU2=Math.cos(U2);var lambda=L,lambdaP=2*Math.PI;var iterLimit=20;while(Math.abs(lambda-lambdaP)>1e-12&&--iterLimit>0){var sinLambda=Math.sin(lambda),cosLambda=Math.cos(lambda);var sinSigma=Math.sqrt((cosU2*sinLambda)*(cosU2*sinLambda)+ +(cosU1*sinU2-sinU1*cosU2*cosLambda)*(cosU1*sinU2-sinU1*cosU2*cosLambda));if(sinSigma==0){return 0;} +var cosSigma=sinU1*sinU2+cosU1*cosU2*cosLambda;var sigma=Math.atan2(sinSigma,cosSigma);var alpha=Math.asin(cosU1*cosU2*sinLambda/sinSigma);var cosSqAlpha=Math.cos(alpha)*Math.cos(alpha);var cos2SigmaM=cosSigma-2*sinU1*sinU2/cosSqAlpha;var C=f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));lambdaP=lambda;lambda=L+(1-C)*f*Math.sin(alpha)*(sigma+C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));} +if(iterLimit==0){return NaN;} +var uSq=cosSqAlpha*(a*a-b*b)/(b*b);var A=1+uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));var B=uSq/1024*(256+uSq*(-128+uSq*(74-47*uSq)));var deltaSigma=B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)- +B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));var s=b*A*(sigma-deltaSigma);var d=s.toFixed(3)/1000;return d;};OpenLayers.Util.destinationVincenty=function(lonlat,brng,dist){var u=OpenLayers.Util;var ct=u.VincentyConstants;var a=ct.a,b=ct.b,f=ct.f;var lon1=lonlat.lon;var lat1=lonlat.lat;var s=dist;var alpha1=u.rad(brng);var sinAlpha1=Math.sin(alpha1);var cosAlpha1=Math.cos(alpha1);var tanU1=(1-f)*Math.tan(u.rad(lat1));var cosU1=1/Math.sqrt((1+tanU1*tanU1)),sinU1=tanU1*cosU1;var sigma1=Math.atan2(tanU1,cosAlpha1);var sinAlpha=cosU1*sinAlpha1;var cosSqAlpha=1-sinAlpha*sinAlpha;var uSq=cosSqAlpha*(a*a-b*b)/(b*b);var A=1+uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));var B=uSq/1024*(256+uSq*(-128+uSq*(74-47*uSq)));var sigma=s/(b*A),sigmaP=2*Math.PI;while(Math.abs(sigma-sigmaP)>1e-12){var cos2SigmaM=Math.cos(2*sigma1+sigma);var sinSigma=Math.sin(sigma);var cosSigma=Math.cos(sigma);var deltaSigma=B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)- +B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));sigmaP=sigma;sigma=s/(b*A)+deltaSigma;} +var tmp=sinU1*sinSigma-cosU1*cosSigma*cosAlpha1;var lat2=Math.atan2(sinU1*cosSigma+cosU1*sinSigma*cosAlpha1,(1-f)*Math.sqrt(sinAlpha*sinAlpha+tmp*tmp));var lambda=Math.atan2(sinSigma*sinAlpha1,cosU1*cosSigma-sinU1*sinSigma*cosAlpha1);var C=f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));var L=lambda-(1-C)*f*sinAlpha*(sigma+C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));var revAz=Math.atan2(sinAlpha,-tmp);return new OpenLayers.LonLat(lon1+u.deg(L),u.deg(lat2));};OpenLayers.Util.getParameters=function(url){url=url||window.location.href;var paramsString="";if(OpenLayers.String.contains(url,'?')){var start=url.indexOf('?')+1;var end=OpenLayers.String.contains(url,"#")?url.indexOf('#'):url.length;paramsString=url.substring(start,end);} +var parameters={};var pairs=paramsString.split(/[&;]/);for(var i=0,len=pairs.length;i<len;++i){var keyValue=pairs[i].split('=');if(keyValue[0]){var key=decodeURIComponent(keyValue[0]);var value=keyValue[1]||'';value=decodeURIComponent(value.replace(/\+/g," ")).split(",");if(value.length==1){value=value[0];} +parameters[key]=value;}} +return parameters;};OpenLayers.Util.getArgs=function(url){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.Util.getParameters'}));return OpenLayers.Util.getParameters(url);};OpenLayers.Util.lastSeqID=0;OpenLayers.Util.createUniqueID=function(prefix){if(prefix==null){prefix="id_";} +OpenLayers.Util.lastSeqID+=1;return prefix+OpenLayers.Util.lastSeqID;};OpenLayers.INCHES_PER_UNIT={'inches':1.0,'ft':12.0,'mi':63360.0,'m':39.3701,'km':39370.1,'dd':4374754,'yd':36};OpenLayers.INCHES_PER_UNIT["in"]=OpenLayers.INCHES_PER_UNIT.inches;OpenLayers.INCHES_PER_UNIT["degrees"]=OpenLayers.INCHES_PER_UNIT.dd;OpenLayers.INCHES_PER_UNIT["nmi"]=1852*OpenLayers.INCHES_PER_UNIT.m;OpenLayers.METERS_PER_INCH=0.02540005080010160020;OpenLayers.Util.extend(OpenLayers.INCHES_PER_UNIT,{"Inch":OpenLayers.INCHES_PER_UNIT.inches,"Meter":1.0/OpenLayers.METERS_PER_INCH,"Foot":0.30480060960121920243/OpenLayers.METERS_PER_INCH,"IFoot":0.30480000000000000000/OpenLayers.METERS_PER_INCH,"ClarkeFoot":0.3047972651151/OpenLayers.METERS_PER_INCH,"SearsFoot":0.30479947153867624624/OpenLayers.METERS_PER_INCH,"GoldCoastFoot":0.30479971018150881758/OpenLayers.METERS_PER_INCH,"IInch":0.02540000000000000000/OpenLayers.METERS_PER_INCH,"MicroInch":0.00002540000000000000/OpenLayers.METERS_PER_INCH,"Mil":0.00000002540000000000/OpenLayers.METERS_PER_INCH,"Centimeter":0.01000000000000000000/OpenLayers.METERS_PER_INCH,"Kilometer":1000.00000000000000000000/OpenLayers.METERS_PER_INCH,"Yard":0.91440182880365760731/OpenLayers.METERS_PER_INCH,"SearsYard":0.914398414616029/OpenLayers.METERS_PER_INCH,"IndianYard":0.91439853074444079983/OpenLayers.METERS_PER_INCH,"IndianYd37":0.91439523/OpenLayers.METERS_PER_INCH,"IndianYd62":0.9143988/OpenLayers.METERS_PER_INCH,"IndianYd75":0.9143985/OpenLayers.METERS_PER_INCH,"IndianFoot":0.30479951/OpenLayers.METERS_PER_INCH,"IndianFt37":0.30479841/OpenLayers.METERS_PER_INCH,"IndianFt62":0.3047996/OpenLayers.METERS_PER_INCH,"IndianFt75":0.3047995/OpenLayers.METERS_PER_INCH,"Mile":1609.34721869443738887477/OpenLayers.METERS_PER_INCH,"IYard":0.91440000000000000000/OpenLayers.METERS_PER_INCH,"IMile":1609.34400000000000000000/OpenLayers.METERS_PER_INCH,"NautM":1852.00000000000000000000/OpenLayers.METERS_PER_INCH,"Lat-66":110943.316488932731/OpenLayers.METERS_PER_INCH,"Lat-83":110946.25736872234125/OpenLayers.METERS_PER_INCH,"Decimeter":0.10000000000000000000/OpenLayers.METERS_PER_INCH,"Millimeter":0.00100000000000000000/OpenLayers.METERS_PER_INCH,"Dekameter":10.00000000000000000000/OpenLayers.METERS_PER_INCH,"Decameter":10.00000000000000000000/OpenLayers.METERS_PER_INCH,"Hectometer":100.00000000000000000000/OpenLayers.METERS_PER_INCH,"GermanMeter":1.0000135965/OpenLayers.METERS_PER_INCH,"CaGrid":0.999738/OpenLayers.METERS_PER_INCH,"ClarkeChain":20.1166194976/OpenLayers.METERS_PER_INCH,"GunterChain":20.11684023368047/OpenLayers.METERS_PER_INCH,"BenoitChain":20.116782494375872/OpenLayers.METERS_PER_INCH,"SearsChain":20.11676512155/OpenLayers.METERS_PER_INCH,"ClarkeLink":0.201166194976/OpenLayers.METERS_PER_INCH,"GunterLink":0.2011684023368047/OpenLayers.METERS_PER_INCH,"BenoitLink":0.20116782494375872/OpenLayers.METERS_PER_INCH,"SearsLink":0.2011676512155/OpenLayers.METERS_PER_INCH,"Rod":5.02921005842012/OpenLayers.METERS_PER_INCH,"IntnlChain":20.1168/OpenLayers.METERS_PER_INCH,"IntnlLink":0.201168/OpenLayers.METERS_PER_INCH,"Perch":5.02921005842012/OpenLayers.METERS_PER_INCH,"Pole":5.02921005842012/OpenLayers.METERS_PER_INCH,"Furlong":201.1684023368046/OpenLayers.METERS_PER_INCH,"Rood":3.778266898/OpenLayers.METERS_PER_INCH,"CapeFoot":0.3047972615/OpenLayers.METERS_PER_INCH,"Brealey":375.00000000000000000000/OpenLayers.METERS_PER_INCH,"ModAmFt":0.304812252984505969011938/OpenLayers.METERS_PER_INCH,"Fathom":1.8288/OpenLayers.METERS_PER_INCH,"NautM-UK":1853.184/OpenLayers.METERS_PER_INCH,"50kilometers":50000.0/OpenLayers.METERS_PER_INCH,"150kilometers":150000.0/OpenLayers.METERS_PER_INCH});OpenLayers.Util.extend(OpenLayers.INCHES_PER_UNIT,{"mm":OpenLayers.INCHES_PER_UNIT["Meter"]/1000.0,"cm":OpenLayers.INCHES_PER_UNIT["Meter"]/100.0,"dm":OpenLayers.INCHES_PER_UNIT["Meter"]*100.0,"km":OpenLayers.INCHES_PER_UNIT["Meter"]*1000.0,"kmi":OpenLayers.INCHES_PER_UNIT["nmi"],"fath":OpenLayers.INCHES_PER_UNIT["Fathom"],"ch":OpenLayers.INCHES_PER_UNIT["IntnlChain"],"link":OpenLayers.INCHES_PER_UNIT["IntnlLink"],"us-in":OpenLayers.INCHES_PER_UNIT["inches"],"us-ft":OpenLayers.INCHES_PER_UNIT["Foot"],"us-yd":OpenLayers.INCHES_PER_UNIT["Yard"],"us-ch":OpenLayers.INCHES_PER_UNIT["GunterChain"],"us-mi":OpenLayers.INCHES_PER_UNIT["Mile"],"ind-yd":OpenLayers.INCHES_PER_UNIT["IndianYd37"],"ind-ft":OpenLayers.INCHES_PER_UNIT["IndianFt37"],"ind-ch":20.11669506/OpenLayers.METERS_PER_INCH});OpenLayers.DOTS_PER_INCH=72;OpenLayers.Util.normalizeScale=function(scale){var normScale=(scale>1.0)?(1.0/scale):scale;return normScale;};OpenLayers.Util.getResolutionFromScale=function(scale,units){var resolution;if(scale){if(units==null){units="degrees";} +var normScale=OpenLayers.Util.normalizeScale(scale);resolution=1/(normScale*OpenLayers.INCHES_PER_UNIT[units]*OpenLayers.DOTS_PER_INCH);} +return resolution;};OpenLayers.Util.getScaleFromResolution=function(resolution,units){if(units==null){units="degrees";} +var scale=resolution*OpenLayers.INCHES_PER_UNIT[units]*OpenLayers.DOTS_PER_INCH;return scale;};OpenLayers.Util.safeStopPropagation=function(evt){OpenLayers.Event.stop(evt,true);};OpenLayers.Util.pagePosition=function(forElement){var valueT=0,valueL=0;var element=forElement;var child=forElement;while(element){if(element==document.body){if(OpenLayers.Element.getStyle(child,'position')=='absolute'){break;}} +valueT+=element.offsetTop||0;valueL+=element.offsetLeft||0;child=element;try{element=element.offsetParent;}catch(e){OpenLayers.Console.error(OpenLayers.i18n("pagePositionFailed",{'elemId':element.id}));break;}} +element=forElement;while(element){valueT-=element.scrollTop||0;valueL-=element.scrollLeft||0;element=element.parentNode;} +return[valueL,valueT];};OpenLayers.Util.isEquivalentUrl=function(url1,url2,options){options=options||{};OpenLayers.Util.applyDefaults(options,{ignoreCase:true,ignorePort80:true,ignoreHash:true});var urlObj1=OpenLayers.Util.createUrlObject(url1,options);var urlObj2=OpenLayers.Util.createUrlObject(url2,options);for(var key in urlObj1){if(key!=="args"){if(urlObj1[key]!=urlObj2[key]){return false;}}} +for(var key in urlObj1.args){if(urlObj1.args[key]!=urlObj2.args[key]){return false;} +delete urlObj2.args[key];} +for(var key in urlObj2.args){return false;} +return true;};OpenLayers.Util.createUrlObject=function(url,options){options=options||{};if(!(/^\w+:\/\//).test(url)){var loc=window.location;var port=loc.port?":"+loc.port:"";var fullUrl=loc.protocol+"//"+loc.host.split(":").shift()+port;if(url.indexOf("/")===0){url=fullUrl+url;}else{var parts=loc.pathname.split("/");parts.pop();url=fullUrl+parts.join("/")+"/"+url;}} +if(options.ignoreCase){url=url.toLowerCase();} +var a=document.createElement('a');a.href=url;var urlObject={};urlObject.host=a.host.split(":").shift();urlObject.protocol=a.protocol;if(options.ignorePort80){urlObject.port=(a.port=="80"||a.port=="0")?"":a.port;}else{urlObject.port=(a.port==""||a.port=="0")?"80":a.port;} +urlObject.hash=(options.ignoreHash||a.hash==="#")?"":a.hash;var queryString=a.search;if(!queryString){var qMark=url.indexOf("?");queryString=(qMark!=-1)?url.substr(qMark):"";} +urlObject.args=OpenLayers.Util.getParameters(queryString);urlObject.pathname=(a.pathname.charAt(0)=="/")?a.pathname:"/"+a.pathname;return urlObject;};OpenLayers.Util.removeTail=function(url){var head=null;var qMark=url.indexOf("?");var hashMark=url.indexOf("#");if(qMark==-1){head=(hashMark!=-1)?url.substr(0,hashMark):url;}else{head=(hashMark!=-1)?url.substr(0,Math.min(qMark,hashMark)):url.substr(0,qMark);} +return head;};OpenLayers.Util.getBrowserName=function(){var browserName="";var ua=navigator.userAgent.toLowerCase();if(ua.indexOf("opera")!=-1){browserName="opera";}else if(ua.indexOf("msie")!=-1){browserName="msie";}else if(ua.indexOf("safari")!=-1){browserName="safari";}else if(ua.indexOf("mozilla")!=-1){if(ua.indexOf("firefox")!=-1){browserName="firefox";}else{browserName="mozilla";}} +return browserName;};OpenLayers.Util.getRenderedDimensions=function(contentHTML,size,options){var w,h;var container=document.createElement("div");container.style.visibility="hidden";var containerElement=(options&&options.containerElement)?options.containerElement:document.body;if(size){if(size.w){w=size.w;container.style.width=w+"px";}else if(size.h){h=size.h;container.style.height=h+"px";}} +if(options&&options.displayClass){container.className=options.displayClass;} +var content=document.createElement("div");content.innerHTML=contentHTML;content.style.overflow="visible";if(content.childNodes){for(var i=0,l=content.childNodes.length;i<l;i++){if(!content.childNodes[i].style)continue;content.childNodes[i].style.overflow="visible";}} +container.appendChild(content);containerElement.appendChild(container);var parentHasPositionAbsolute=false;var parent=container.parentNode;while(parent&&parent.tagName.toLowerCase()!="body"){var parentPosition=OpenLayers.Element.getStyle(parent,"position");if(parentPosition=="absolute"){parentHasPositionAbsolute=true;break;}else if(parentPosition&&parentPosition!="static"){break;} +parent=parent.parentNode;} +if(!parentHasPositionAbsolute){container.style.position="absolute";} +if(!w){w=parseInt(content.scrollWidth);container.style.width=w+"px";} +if(!h){h=parseInt(content.scrollHeight);} +container.removeChild(content);containerElement.removeChild(container);return new OpenLayers.Size(w,h);};OpenLayers.Util.getScrollbarWidth=function(){var scrollbarWidth=OpenLayers.Util._scrollbarWidth;if(scrollbarWidth==null){var scr=null;var inn=null;var wNoScroll=0;var wScroll=0;scr=document.createElement('div');scr.style.position='absolute';scr.style.top='-1000px';scr.style.left='-1000px';scr.style.width='100px';scr.style.height='50px';scr.style.overflow='hidden';inn=document.createElement('div');inn.style.width='100%';inn.style.height='200px';scr.appendChild(inn);document.body.appendChild(scr);wNoScroll=inn.offsetWidth;scr.style.overflow='scroll';wScroll=inn.offsetWidth;document.body.removeChild(document.body.lastChild);OpenLayers.Util._scrollbarWidth=(wNoScroll-wScroll);scrollbarWidth=OpenLayers.Util._scrollbarWidth;} +return scrollbarWidth;};OpenLayers.Util.getFormattedLonLat=function(coordinate,axis,dmsOption){if(!dmsOption){dmsOption='dms';} +var abscoordinate=Math.abs(coordinate) +var coordinatedegrees=Math.floor(abscoordinate);var coordinateminutes=(abscoordinate-coordinatedegrees)/(1/60);var tempcoordinateminutes=coordinateminutes;coordinateminutes=Math.floor(coordinateminutes);var coordinateseconds=(tempcoordinateminutes-coordinateminutes)/(1/60);coordinateseconds=Math.round(coordinateseconds*10);coordinateseconds/=10;if(coordinatedegrees<10){coordinatedegrees="0"+coordinatedegrees;} +var str=coordinatedegrees+"\u00B0";if(dmsOption.indexOf('dm')>=0){if(coordinateminutes<10){coordinateminutes="0"+coordinateminutes;} +str+=coordinateminutes+"'";if(dmsOption.indexOf('dms')>=0){if(coordinateseconds<10){coordinateseconds="0"+coordinateseconds;} +str+=coordinateseconds+'"';}} +if(axis=="lon"){str+=coordinate<0?OpenLayers.i18n("W"):OpenLayers.i18n("E");}else{str+=coordinate<0?OpenLayers.i18n("S"):OpenLayers.i18n("N");} +return str;};OpenLayers.Rico=new Object();OpenLayers.Rico.Corner={round:function(e,options){e=OpenLayers.Util.getElement(e);this._setOptions(options);var color=this.options.color;if(this.options.color=="fromElement"){color=this._background(e);} +var bgColor=this.options.bgColor;if(this.options.bgColor=="fromParent"){bgColor=this._background(e.offsetParent);} +this._roundCornersImpl(e,color,bgColor);},changeColor:function(theDiv,newColor){theDiv.style.backgroundColor=newColor;var spanElements=theDiv.parentNode.getElementsByTagName("span");for(var currIdx=0;currIdx<spanElements.length;currIdx++){spanElements[currIdx].style.backgroundColor=newColor;}},changeOpacity:function(theDiv,newOpacity){var mozillaOpacity=newOpacity;var ieOpacity='alpha(opacity='+newOpacity*100+')';theDiv.style.opacity=mozillaOpacity;theDiv.style.filter=ieOpacity;var spanElements=theDiv.parentNode.getElementsByTagName("span");for(var currIdx=0;currIdx<spanElements.length;currIdx++){spanElements[currIdx].style.opacity=mozillaOpacity;spanElements[currIdx].style.filter=ieOpacity;}},reRound:function(theDiv,options){var topRico=theDiv.parentNode.childNodes[0];var bottomRico=theDiv.parentNode.childNodes[2];theDiv.parentNode.removeChild(topRico);theDiv.parentNode.removeChild(bottomRico);this.round(theDiv.parentNode,options);},_roundCornersImpl:function(e,color,bgColor){if(this.options.border){this._renderBorder(e,bgColor);} +if(this._isTopRounded()){this._roundTopCorners(e,color,bgColor);} +if(this._isBottomRounded()){this._roundBottomCorners(e,color,bgColor);}},_renderBorder:function(el,bgColor){var borderValue="1px solid "+this._borderColor(bgColor);var borderL="border-left: "+borderValue;var borderR="border-right: "+borderValue;var style="style='"+borderL+";"+borderR+"'";el.innerHTML="<div "+style+">"+el.innerHTML+"</div>";},_roundTopCorners:function(el,color,bgColor){var corner=this._createCorner(bgColor);for(var i=0;i<this.options.numSlices;i++){corner.appendChild(this._createCornerSlice(color,bgColor,i,"top"));} +el.style.paddingTop=0;el.insertBefore(corner,el.firstChild);},_roundBottomCorners:function(el,color,bgColor){var corner=this._createCorner(bgColor);for(var i=(this.options.numSlices-1);i>=0;i--){corner.appendChild(this._createCornerSlice(color,bgColor,i,"bottom"));} +el.style.paddingBottom=0;el.appendChild(corner);},_createCorner:function(bgColor){var corner=document.createElement("div");corner.style.backgroundColor=(this._isTransparent()?"transparent":bgColor);return corner;},_createCornerSlice:function(color,bgColor,n,position){var slice=document.createElement("span");var inStyle=slice.style;inStyle.backgroundColor=color;inStyle.display="block";inStyle.height="1px";inStyle.overflow="hidden";inStyle.fontSize="1px";var borderColor=this._borderColor(color,bgColor);if(this.options.border&&n==0){inStyle.borderTopStyle="solid";inStyle.borderTopWidth="1px";inStyle.borderLeftWidth="0px";inStyle.borderRightWidth="0px";inStyle.borderBottomWidth="0px";inStyle.height="0px";inStyle.borderColor=borderColor;} +else if(borderColor){inStyle.borderColor=borderColor;inStyle.borderStyle="solid";inStyle.borderWidth="0px 1px";} +if(!this.options.compact&&(n==(this.options.numSlices-1))){inStyle.height="2px";} +this._setMargin(slice,n,position);this._setBorder(slice,n,position);return slice;},_setOptions:function(options){this.options={corners:"all",color:"fromElement",bgColor:"fromParent",blend:true,border:false,compact:false};OpenLayers.Util.extend(this.options,options||{});this.options.numSlices=this.options.compact?2:4;if(this._isTransparent()){this.options.blend=false;}},_whichSideTop:function(){if(this._hasString(this.options.corners,"all","top")){return"";} +if(this.options.corners.indexOf("tl")>=0&&this.options.corners.indexOf("tr")>=0){return"";} +if(this.options.corners.indexOf("tl")>=0){return"left";}else if(this.options.corners.indexOf("tr")>=0){return"right";} +return"";},_whichSideBottom:function(){if(this._hasString(this.options.corners,"all","bottom")){return"";} +if(this.options.corners.indexOf("bl")>=0&&this.options.corners.indexOf("br")>=0){return"";} +if(this.options.corners.indexOf("bl")>=0){return"left";}else if(this.options.corners.indexOf("br")>=0){return"right";} +return"";},_borderColor:function(color,bgColor){if(color=="transparent"){return bgColor;}else if(this.options.border){return this.options.border;}else if(this.options.blend){return this._blend(bgColor,color);}else{return"";}},_setMargin:function(el,n,corners){var marginSize=this._marginSize(n);var whichSide=corners=="top"?this._whichSideTop():this._whichSideBottom();if(whichSide=="left"){el.style.marginLeft=marginSize+"px";el.style.marginRight="0px";} +else if(whichSide=="right"){el.style.marginRight=marginSize+"px";el.style.marginLeft="0px";} +else{el.style.marginLeft=marginSize+"px";el.style.marginRight=marginSize+"px";}},_setBorder:function(el,n,corners){var borderSize=this._borderSize(n);var whichSide=corners=="top"?this._whichSideTop():this._whichSideBottom();if(whichSide=="left"){el.style.borderLeftWidth=borderSize+"px";el.style.borderRightWidth="0px";} +else if(whichSide=="right"){el.style.borderRightWidth=borderSize+"px";el.style.borderLeftWidth="0px";} +else{el.style.borderLeftWidth=borderSize+"px";el.style.borderRightWidth=borderSize+"px";} +if(this.options.border!=false){el.style.borderLeftWidth=borderSize+"px";el.style.borderRightWidth=borderSize+"px";}},_marginSize:function(n){if(this._isTransparent()){return 0;} +var marginSizes=[5,3,2,1];var blendedMarginSizes=[3,2,1,0];var compactMarginSizes=[2,1];var smBlendedMarginSizes=[1,0];if(this.options.compact&&this.options.blend){return smBlendedMarginSizes[n];}else if(this.options.compact){return compactMarginSizes[n];}else if(this.options.blend){return blendedMarginSizes[n];}else{return marginSizes[n];}},_borderSize:function(n){var transparentBorderSizes=[5,3,2,1];var blendedBorderSizes=[2,1,1,1];var compactBorderSizes=[1,0];var actualBorderSizes=[0,2,0,0];if(this.options.compact&&(this.options.blend||this._isTransparent())){return 1;}else if(this.options.compact){return compactBorderSizes[n];}else if(this.options.blend){return blendedBorderSizes[n];}else if(this.options.border){return actualBorderSizes[n];}else if(this._isTransparent()){return transparentBorderSizes[n];} +return 0;},_hasString:function(str){for(var i=1;i<arguments.length;i++)if(str.indexOf(arguments[i])>=0){return true;}return false;},_blend:function(c1,c2){var cc1=OpenLayers.Rico.Color.createFromHex(c1);cc1.blend(OpenLayers.Rico.Color.createFromHex(c2));return cc1;},_background:function(el){try{return OpenLayers.Rico.Color.createColorFromBackground(el).asHex();}catch(err){return"#ffffff";}},_isTransparent:function(){return this.options.color=="transparent";},_isTopRounded:function(){return this._hasString(this.options.corners,"all","top","tl","tr");},_isBottomRounded:function(){return this._hasString(this.options.corners,"all","bottom","bl","br");},_hasSingleTextChild:function(el){return el.childNodes.length==1&&el.childNodes[0].nodeType==3;}};(function(){if(window.google&&google.gears){return;} +var factory=null;if(typeof GearsFactory!='undefined'){factory=new GearsFactory();}else{try{factory=new ActiveXObject('Gears.Factory');if(factory.getBuildInfo().indexOf('ie_mobile')!=-1){factory.privateSetGlobalObject(this);}}catch(e){if((typeof navigator.mimeTypes!='undefined')&&navigator.mimeTypes["application/x-googlegears"]){factory=document.createElement("object");factory.style.display="none";factory.width=0;factory.height=0;factory.type="application/x-googlegears";document.documentElement.appendChild(factory);}}} +if(!factory){return;} +if(!window.google){google={};} +if(!google.gears){google.gears={factory:factory};}})();OpenLayers.Element={visible:function(element){return OpenLayers.Util.getElement(element).style.display!='none';},toggle:function(){for(var i=0,len=arguments.length;i<len;i++){var element=OpenLayers.Util.getElement(arguments[i]);var display=OpenLayers.Element.visible(element)?'hide':'show';OpenLayers.Element[display](element);}},hide:function(){for(var i=0,len=arguments.length;i<len;i++){var element=OpenLayers.Util.getElement(arguments[i]);if(element){element.style.display='none';}}},show:function(){for(var i=0,len=arguments.length;i<len;i++){var element=OpenLayers.Util.getElement(arguments[i]);if(element){element.style.display='';}}},remove:function(element){element=OpenLayers.Util.getElement(element);element.parentNode.removeChild(element);},getHeight:function(element){element=OpenLayers.Util.getElement(element);return element.offsetHeight;},getDimensions:function(element){element=OpenLayers.Util.getElement(element);if(OpenLayers.Element.getStyle(element,'display')!='none'){return{width:element.offsetWidth,height:element.offsetHeight};} +var els=element.style;var originalVisibility=els.visibility;var originalPosition=els.position;var originalDisplay=els.display;els.visibility='hidden';els.position='absolute';els.display='';var originalWidth=element.clientWidth;var originalHeight=element.clientHeight;els.display=originalDisplay;els.position=originalPosition;els.visibility=originalVisibility;return{width:originalWidth,height:originalHeight};},hasClass:function(element,name){var names=element.className;return(!!names&&new RegExp("(^|\\s)"+name+"(\\s|$)").test(names));},addClass:function(element,name){if(!OpenLayers.Element.hasClass(element,name)){element.className+=(element.className?" ":"")+name;} +return element;},removeClass:function(element,name){var names=element.className;if(names){element.className=OpenLayers.String.trim(names.replace(new RegExp("(^|\\s+)"+name+"(\\s+|$)")," "));} +return element;},toggleClass:function(element,name){if(OpenLayers.Element.hasClass(element,name)){OpenLayers.Element.removeClass(element,name);}else{OpenLayers.Element.addClass(element,name);} +return element;},getStyle:function(element,style){element=OpenLayers.Util.getElement(element);var value=null;if(element&&element.style){value=element.style[OpenLayers.String.camelize(style)];if(!value){if(document.defaultView&&document.defaultView.getComputedStyle){var css=document.defaultView.getComputedStyle(element,null);value=css?css.getPropertyValue(style):null;}else if(element.currentStyle){value=element.currentStyle[OpenLayers.String.camelize(style)];}} +var positions=['left','top','right','bottom'];if(window.opera&&(OpenLayers.Util.indexOf(positions,style)!=-1)&&(OpenLayers.Element.getStyle(element,'position')=='static')){value='auto';}} +return value=='auto'?null:value;}};OpenLayers.Size=OpenLayers.Class({w:0.0,h:0.0,initialize:function(w,h){this.w=parseFloat(w);this.h=parseFloat(h);},toString:function(){return("w="+this.w+",h="+this.h);},clone:function(){return new OpenLayers.Size(this.w,this.h);},equals:function(sz){var equals=false;if(sz!=null){equals=((this.w==sz.w&&this.h==sz.h)||(isNaN(this.w)&&isNaN(this.h)&&isNaN(sz.w)&&isNaN(sz.h)));} +return equals;},CLASS_NAME:"OpenLayers.Size"});OpenLayers.Console={log:function(){},debug:function(){},info:function(){},warn:function(){},error:function(){},userError:function(error){alert(error);},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(){var scripts=document.getElementsByTagName("script");for(var i=0,len=scripts.length;i<len;++i){if(scripts[i].src.indexOf("firebug.js")!=-1){if(console){OpenLayers.Util.extend(OpenLayers.Console,console);break;}}}})();OpenLayers.Icon=OpenLayers.Class({url:null,size:null,offset:null,calculateOffset:null,imageDiv:null,px:null,initialize:function(url,size,offset,calculateOffset){this.url=url;this.size=(size)?size:new OpenLayers.Size(20,20);this.offset=offset?offset:new OpenLayers.Pixel(-(this.size.w/2),-(this.size.h/2));this.calculateOffset=calculateOffset;var id=OpenLayers.Util.createUniqueID("OL_Icon_");this.imageDiv=OpenLayers.Util.createAlphaImageDiv(id);},destroy:function(){this.erase();OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild);this.imageDiv.innerHTML="";this.imageDiv=null;},clone:function(){return new OpenLayers.Icon(this.url,this.size,this.offset,this.calculateOffset);},setSize:function(size){if(size!=null){this.size=size;} +this.draw();},setUrl:function(url){if(url!=null){this.url=url;} +this.draw();},draw:function(px){OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,null,null,this.size,this.url,"absolute");this.moveTo(px);return this.imageDiv;},erase:function(){if(this.imageDiv!=null&&this.imageDiv.parentNode!=null){OpenLayers.Element.remove(this.imageDiv);}},setOpacity:function(opacity){OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,null,null,null,null,null,null,null,opacity);},moveTo:function(px){if(px!=null){this.px=px;} +if(this.imageDiv!=null){if(this.px==null){this.display(false);}else{if(this.calculateOffset){this.offset=this.calculateOffset(this.size);} +var offsetPx=this.px.offset(this.offset);OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,null,offsetPx);}}},display:function(display){this.imageDiv.style.display=(display)?"":"none";},isDrawn:function(){var isDrawn=(this.imageDiv&&this.imageDiv.parentNode&&(this.imageDiv.parentNode.nodeType!=11));return isDrawn;},CLASS_NAME:"OpenLayers.Icon"});OpenLayers.Popup=OpenLayers.Class({events:null,id:"",lonlat:null,div:null,contentSize:null,size:null,contentHTML:null,backgroundColor:"",opacity:"",border:"",contentDiv:null,groupDiv:null,closeDiv:null,autoSize:false,minSize:null,maxSize:null,displayClass:"olPopup",contentDisplayClass:"olPopupContent",padding:0,disableFirefoxOverflowHack:false,fixPadding:function(){if(typeof this.padding=="number"){this.padding=new OpenLayers.Bounds(this.padding,this.padding,this.padding,this.padding);}},panMapIfOutOfView:false,keepInMap:false,closeOnMove:false,map:null,initialize:function(id,lonlat,contentSize,contentHTML,closeBox,closeBoxCallback){if(id==null){id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");} +this.id=id;this.lonlat=lonlat;this.contentSize=(contentSize!=null)?contentSize:new OpenLayers.Size(OpenLayers.Popup.WIDTH,OpenLayers.Popup.HEIGHT);if(contentHTML!=null){this.contentHTML=contentHTML;} +this.backgroundColor=OpenLayers.Popup.COLOR;this.opacity=OpenLayers.Popup.OPACITY;this.border=OpenLayers.Popup.BORDER;this.div=OpenLayers.Util.createDiv(this.id,null,null,null,null,null,"hidden");this.div.className=this.displayClass;var groupDivId=this.id+"_GroupDiv";this.groupDiv=OpenLayers.Util.createDiv(groupDivId,null,null,null,"relative",null,"hidden");var id=this.div.id+"_contentDiv";this.contentDiv=OpenLayers.Util.createDiv(id,null,this.contentSize.clone(),null,"relative");this.contentDiv.className=this.contentDisplayClass;this.groupDiv.appendChild(this.contentDiv);this.div.appendChild(this.groupDiv);if(closeBox){this.addCloseBox(closeBoxCallback);} +this.registerEvents();},destroy:function(){this.id=null;this.lonlat=null;this.size=null;this.contentHTML=null;this.backgroundColor=null;this.opacity=null;this.border=null;if(this.closeOnMove&&this.map){this.map.events.unregister("movestart",this,this.hide);} +this.events.destroy();this.events=null;if(this.closeDiv){OpenLayers.Event.stopObservingElement(this.closeDiv);this.groupDiv.removeChild(this.closeDiv);} +this.closeDiv=null;this.div.removeChild(this.groupDiv);this.groupDiv=null;if(this.map!=null){this.map.removePopup(this);} +this.map=null;this.div=null;this.autoSize=null;this.minSize=null;this.maxSize=null;this.padding=null;this.panMapIfOutOfView=null;},draw:function(px){if(px==null){if((this.lonlat!=null)&&(this.map!=null)){px=this.map.getLayerPxFromLonLat(this.lonlat);}} +if(this.closeOnMove){this.map.events.register("movestart",this,this.hide);} +if(!this.disableFirefoxOverflowHack&&OpenLayers.Util.getBrowserName()=='firefox'){this.map.events.register("movestart",this,function(){var style=document.defaultView.getComputedStyle(this.contentDiv,null);var currentOverflow=style.getPropertyValue("overflow");if(currentOverflow!="hidden"){this.contentDiv._oldOverflow=currentOverflow;this.contentDiv.style.overflow="hidden";}});this.map.events.register("moveend",this,function(){var oldOverflow=this.contentDiv._oldOverflow;if(oldOverflow){this.contentDiv.style.overflow=oldOverflow;this.contentDiv._oldOverflow=null;}});} +this.moveTo(px);if(!this.autoSize&&!this.size){this.setSize(this.contentSize);} +this.setBackgroundColor();this.setOpacity();this.setBorder();this.setContentHTML();if(this.panMapIfOutOfView){this.panIntoView();} +return this.div;},updatePosition:function(){if((this.lonlat)&&(this.map)){var px=this.map.getLayerPxFromLonLat(this.lonlat);if(px){this.moveTo(px);}}},moveTo:function(px){if((px!=null)&&(this.div!=null)){this.div.style.left=px.x+"px";this.div.style.top=px.y+"px";}},visible:function(){return OpenLayers.Element.visible(this.div);},toggle:function(){if(this.visible()){this.hide();}else{this.show();}},show:function(){OpenLayers.Element.show(this.div);if(this.panMapIfOutOfView){this.panIntoView();}},hide:function(){OpenLayers.Element.hide(this.div);},setSize:function(contentSize){this.size=contentSize.clone();var contentDivPadding=this.getContentDivPadding();var wPadding=contentDivPadding.left+contentDivPadding.right;var hPadding=contentDivPadding.top+contentDivPadding.bottom;this.fixPadding();wPadding+=this.padding.left+this.padding.right;hPadding+=this.padding.top+this.padding.bottom;if(this.closeDiv){var closeDivWidth=parseInt(this.closeDiv.style.width);wPadding+=closeDivWidth+contentDivPadding.right;} +this.size.w+=wPadding;this.size.h+=hPadding;if(OpenLayers.Util.getBrowserName()=="msie"){this.contentSize.w+=contentDivPadding.left+contentDivPadding.right;this.contentSize.h+=contentDivPadding.bottom+contentDivPadding.top;} +if(this.div!=null){this.div.style.width=this.size.w+"px";this.div.style.height=this.size.h+"px";} +if(this.contentDiv!=null){this.contentDiv.style.width=contentSize.w+"px";this.contentDiv.style.height=contentSize.h+"px";}},updateSize:function(){var preparedHTML="<div class='"+this.contentDisplayClass+"'>"+ +this.contentDiv.innerHTML+"</div>";var containerElement=(this.map)?this.map.layerContainerDiv:document.body;var realSize=OpenLayers.Util.getRenderedDimensions(preparedHTML,null,{displayClass:this.displayClass,containerElement:containerElement});var safeSize=this.getSafeContentSize(realSize);var newSize=null;if(safeSize.equals(realSize)){newSize=realSize;}else{var fixedSize=new OpenLayers.Size();fixedSize.w=(safeSize.w<realSize.w)?safeSize.w:null;fixedSize.h=(safeSize.h<realSize.h)?safeSize.h:null;if(fixedSize.w&&fixedSize.h){newSize=safeSize;}else{var clippedSize=OpenLayers.Util.getRenderedDimensions(preparedHTML,fixedSize,{displayClass:this.contentDisplayClass,containerElement:containerElement});var currentOverflow=OpenLayers.Element.getStyle(this.contentDiv,"overflow");if((currentOverflow!="hidden")&&(clippedSize.equals(safeSize))){var scrollBar=OpenLayers.Util.getScrollbarWidth();if(fixedSize.w){clippedSize.h+=scrollBar;}else{clippedSize.w+=scrollBar;}} +newSize=this.getSafeContentSize(clippedSize);}} +this.setSize(newSize);},setBackgroundColor:function(color){if(color!=undefined){this.backgroundColor=color;} +if(this.div!=null){this.div.style.backgroundColor=this.backgroundColor;}},setOpacity:function(opacity){if(opacity!=undefined){this.opacity=opacity;} +if(this.div!=null){this.div.style.opacity=this.opacity;this.div.style.filter='alpha(opacity='+this.opacity*100+')';}},setBorder:function(border){if(border!=undefined){this.border=border;} +if(this.div!=null){this.div.style.border=this.border;}},setContentHTML:function(contentHTML){if(contentHTML!=null){this.contentHTML=contentHTML;} +if((this.contentDiv!=null)&&(this.contentHTML!=null)&&(this.contentHTML!=this.contentDiv.innerHTML)){this.contentDiv.innerHTML=this.contentHTML;if(this.autoSize){this.registerImageListeners();this.updateSize();}}},registerImageListeners:function(){var onImgLoad=function(){this.popup.updateSize();if(this.popup.visible()&&this.popup.panMapIfOutOfView){this.popup.panIntoView();} +OpenLayers.Event.stopObserving(this.img,"load",this.img._onImageLoad);};var images=this.contentDiv.getElementsByTagName("img");for(var i=0,len=images.length;i<len;i++){var img=images[i];if(img.width==0||img.height==0){var context={'popup':this,'img':img};img._onImgLoad=OpenLayers.Function.bind(onImgLoad,context);OpenLayers.Event.observe(img,'load',img._onImgLoad);}}},getSafeContentSize:function(size){var safeContentSize=size.clone();var contentDivPadding=this.getContentDivPadding();var wPadding=contentDivPadding.left+contentDivPadding.right;var hPadding=contentDivPadding.top+contentDivPadding.bottom;this.fixPadding();wPadding+=this.padding.left+this.padding.right;hPadding+=this.padding.top+this.padding.bottom;if(this.closeDiv){var closeDivWidth=parseInt(this.closeDiv.style.width);wPadding+=closeDivWidth+contentDivPadding.right;} +if(this.minSize){safeContentSize.w=Math.max(safeContentSize.w,(this.minSize.w-wPadding));safeContentSize.h=Math.max(safeContentSize.h,(this.minSize.h-hPadding));} +if(this.maxSize){safeContentSize.w=Math.min(safeContentSize.w,(this.maxSize.w-wPadding));safeContentSize.h=Math.min(safeContentSize.h,(this.maxSize.h-hPadding));} +if(this.map&&this.map.size){var extraX=0,extraY=0;if(this.keepInMap&&!this.panMapIfOutOfView){var px=this.map.getPixelFromLonLat(this.lonlat);switch(this.relativePosition){case"tr":extraX=px.x;extraY=this.map.size.h-px.y;break;case"tl":extraX=this.map.size.w-px.x;extraY=this.map.size.h-px.y;break;case"bl":extraX=this.map.size.w-px.x;extraY=px.y;break;case"br":extraX=px.x;extraY=px.y;break;default:extraX=px.x;extraY=this.map.size.h-px.y;break;}} +var maxY=this.map.size.h- +this.map.paddingForPopups.top- +this.map.paddingForPopups.bottom- +hPadding-extraY;var maxX=this.map.size.w- +this.map.paddingForPopups.left- +this.map.paddingForPopups.right- +wPadding-extraX;safeContentSize.w=Math.min(safeContentSize.w,maxX);safeContentSize.h=Math.min(safeContentSize.h,maxY);} +return safeContentSize;},getContentDivPadding:function(){var contentDivPadding=this._contentDivPadding;if(!contentDivPadding){if(this.div.parentNode==null){this.div.style.display="none";document.body.appendChild(this.div);} +contentDivPadding=new OpenLayers.Bounds(OpenLayers.Element.getStyle(this.contentDiv,"padding-left"),OpenLayers.Element.getStyle(this.contentDiv,"padding-bottom"),OpenLayers.Element.getStyle(this.contentDiv,"padding-right"),OpenLayers.Element.getStyle(this.contentDiv,"padding-top"));this._contentDivPadding=contentDivPadding;if(this.div.parentNode==document.body){document.body.removeChild(this.div);this.div.style.display="";}} +return contentDivPadding;},addCloseBox:function(callback){this.closeDiv=OpenLayers.Util.createDiv(this.id+"_close",null,new OpenLayers.Size(17,17));this.closeDiv.className="olPopupCloseBox";var contentDivPadding=this.getContentDivPadding();this.closeDiv.style.right=contentDivPadding.right+"px";this.closeDiv.style.top=contentDivPadding.top+"px";this.groupDiv.appendChild(this.closeDiv);var closePopup=callback||function(e){this.hide();OpenLayers.Event.stop(e);};OpenLayers.Event.observe(this.closeDiv,"click",OpenLayers.Function.bindAsEventListener(closePopup,this));},panIntoView:function(){var mapSize=this.map.getSize();var origTL=this.map.getViewPortPxFromLayerPx(new OpenLayers.Pixel(parseInt(this.div.style.left),parseInt(this.div.style.top)));var newTL=origTL.clone();if(origTL.x<this.map.paddingForPopups.left){newTL.x=this.map.paddingForPopups.left;}else +if((origTL.x+this.size.w)>(mapSize.w-this.map.paddingForPopups.right)){newTL.x=mapSize.w-this.map.paddingForPopups.right-this.size.w;} +if(origTL.y<this.map.paddingForPopups.top){newTL.y=this.map.paddingForPopups.top;}else +if((origTL.y+this.size.h)>(mapSize.h-this.map.paddingForPopups.bottom)){newTL.y=mapSize.h-this.map.paddingForPopups.bottom-this.size.h;} +var dx=origTL.x-newTL.x;var dy=origTL.y-newTL.y;this.map.pan(dx,dy);},registerEvents:function(){this.events=new OpenLayers.Events(this,this.div,null,true);this.events.on({"mousedown":this.onmousedown,"mousemove":this.onmousemove,"mouseup":this.onmouseup,"click":this.onclick,"mouseout":this.onmouseout,"dblclick":this.ondblclick,scope:this});},onmousedown:function(evt){this.mousedown=true;OpenLayers.Event.stop(evt,true);},onmousemove:function(evt){if(this.mousedown){OpenLayers.Event.stop(evt,true);}},onmouseup:function(evt){if(this.mousedown){this.mousedown=false;OpenLayers.Event.stop(evt,true);}},onclick:function(evt){OpenLayers.Event.stop(evt,true);},onmouseout:function(evt){this.mousedown=false;},ondblclick:function(evt){OpenLayers.Event.stop(evt,true);},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.Protocol=OpenLayers.Class({format:null,options:null,autoDestroy:true,defaultFilter:null,initialize:function(options){options=options||{};OpenLayers.Util.extend(this,options);this.options=options;},mergeWithDefaultFilter:function(filter){var merged;if(filter&&this.defaultFilter){merged=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND,filters:[this.defaultFilter,filter]});}else{merged=filter||this.defaultFilter||undefined;} +return merged;},destroy:function(){this.options=null;this.format=null;},read:function(options){options=options||{};options.filter=this.mergeWithDefaultFilter(options.filter);},create:function(){},update:function(){},"delete":function(){},commit:function(){},abort:function(response){},createCallback:function(method,response,options){return OpenLayers.Function.bind(function(){method.apply(this,[response,options]);},this);},CLASS_NAME:"OpenLayers.Protocol"});OpenLayers.Protocol.Response=OpenLayers.Class({code:null,requestType:null,last:true,features:null,reqFeatures:null,priv:null,initialize:function(options){OpenLayers.Util.extend(this,options);},success:function(){return this.code>0;},CLASS_NAME:"OpenLayers.Protocol.Response"});OpenLayers.Protocol.Response.SUCCESS=1;OpenLayers.Protocol.Response.FAILURE=0;OpenLayers.Renderer=OpenLayers.Class({container:null,root:null,extent:null,locked:false,size:null,resolution:null,map:null,initialize:function(containerID,options){this.container=OpenLayers.Util.getElement(containerID);},destroy:function(){this.container=null;this.extent=null;this.size=null;this.resolution=null;this.map=null;},supported:function(){return false;},setExtent:function(extent,resolutionChanged){this.extent=extent.clone();if(resolutionChanged){this.resolution=null;}},setSize:function(size){this.size=size.clone();this.resolution=null;},getResolution:function(){this.resolution=this.resolution||this.map.getResolution();return this.resolution;},drawFeature:function(feature,style){if(style==null){style=feature.style;} +if(feature.geometry){var bounds=feature.geometry.getBounds();if(bounds){if(!bounds.intersectsBounds(this.extent)){style={display:"none"};} +var rendered=this.drawGeometry(feature.geometry,style,feature.id);if(style.display!="none"&&style.label&&rendered!==false){var location=feature.geometry.getCentroid();if(style.labelXOffset||style.labelYOffset){xOffset=isNaN(style.labelXOffset)?0:style.labelXOffset;yOffset=isNaN(style.labelYOffset)?0:style.labelYOffset;var res=this.getResolution();location.move(xOffset*res,yOffset*res);} +this.drawText(feature.id,style,location);}else{this.removeText(feature.id);} +return rendered;}}},drawGeometry:function(geometry,style,featureId){},drawText:function(featureId,style,location){},removeText:function(featureId){},clear:function(){},getFeatureIdFromEvent:function(evt){},eraseFeatures:function(features){if(!(features instanceof Array)){features=[features];} +for(var i=0,len=features.length;i<len;++i){var feature=features[i];this.eraseGeometry(feature.geometry,feature.id);this.removeText(feature.id);}},eraseGeometry:function(geometry,featureId){},moveRoot:function(renderer){},getRenderLayerId:function(){return this.container.id;},applyDefaultSymbolizer:function(symbolizer){var result=OpenLayers.Util.extend({},OpenLayers.Renderer.defaultSymbolizer);if(symbolizer.stroke===false){delete result.strokeWidth;delete result.strokeColor;} +if(symbolizer.fill===false){delete result.fillColor;} +OpenLayers.Util.extend(result,symbolizer);return result;},CLASS_NAME:"OpenLayers.Renderer"});OpenLayers.Renderer.defaultSymbolizer={fillColor:"#000000",strokeColor:"#000000",strokeWidth:2,fillOpacity:1,strokeOpacity:1,pointRadius:0};OpenLayers.Strategy=OpenLayers.Class({layer:null,options:null,active:null,autoActivate:true,autoDestroy:true,initialize:function(options){OpenLayers.Util.extend(this,options);this.options=options;this.active=false;},destroy:function(){this.deactivate();this.layer=null;this.options=null;},setLayer:function(layer){this.layer=layer;},activate:function(){if(!this.active){this.active=true;return true;} +return false;},deactivate:function(){if(this.active){this.active=false;return true;} +return false;},CLASS_NAME:"OpenLayers.Strategy"});OpenLayers.Symbolizer=OpenLayers.Class({zIndex:0,initialize:function(config){OpenLayers.Util.extend(this,config);},clone:function(){var Type=eval(this.CLASS_NAME);return new Type(OpenLayers.Util.extend({},this));},CLASS_NAME:"OpenLayers.Symbolizer"});OpenLayers.Rico.Color=OpenLayers.Class({initialize:function(red,green,blue){this.rgb={r:red,g:green,b:blue};},setRed:function(r){this.rgb.r=r;},setGreen:function(g){this.rgb.g=g;},setBlue:function(b){this.rgb.b=b;},setHue:function(h){var hsb=this.asHSB();hsb.h=h;this.rgb=OpenLayers.Rico.Color.HSBtoRGB(hsb.h,hsb.s,hsb.b);},setSaturation:function(s){var hsb=this.asHSB();hsb.s=s;this.rgb=OpenLayers.Rico.Color.HSBtoRGB(hsb.h,hsb.s,hsb.b);},setBrightness:function(b){var hsb=this.asHSB();hsb.b=b;this.rgb=OpenLayers.Rico.Color.HSBtoRGB(hsb.h,hsb.s,hsb.b);},darken:function(percent){var hsb=this.asHSB();this.rgb=OpenLayers.Rico.Color.HSBtoRGB(hsb.h,hsb.s,Math.max(hsb.b-percent,0));},brighten:function(percent){var hsb=this.asHSB();this.rgb=OpenLayers.Rico.Color.HSBtoRGB(hsb.h,hsb.s,Math.min(hsb.b+percent,1));},blend:function(other){this.rgb.r=Math.floor((this.rgb.r+other.rgb.r)/2);this.rgb.g=Math.floor((this.rgb.g+other.rgb.g)/2);this.rgb.b=Math.floor((this.rgb.b+other.rgb.b)/2);},isBright:function(){var hsb=this.asHSB();return this.asHSB().b>0.5;},isDark:function(){return!this.isBright();},asRGB:function(){return"rgb("+this.rgb.r+","+this.rgb.g+","+this.rgb.b+")";},asHex:function(){return"#"+this.rgb.r.toColorPart()+this.rgb.g.toColorPart()+this.rgb.b.toColorPart();},asHSB:function(){return OpenLayers.Rico.Color.RGBtoHSB(this.rgb.r,this.rgb.g,this.rgb.b);},toString:function(){return this.asHex();}});OpenLayers.Rico.Color.createFromHex=function(hexCode){if(hexCode.length==4){var shortHexCode=hexCode;var hexCode='#';for(var i=1;i<4;i++){hexCode+=(shortHexCode.charAt(i)+ +shortHexCode.charAt(i));}} +if(hexCode.indexOf('#')==0){hexCode=hexCode.substring(1);} +var red=hexCode.substring(0,2);var green=hexCode.substring(2,4);var blue=hexCode.substring(4,6);return new OpenLayers.Rico.Color(parseInt(red,16),parseInt(green,16),parseInt(blue,16));};OpenLayers.Rico.Color.createColorFromBackground=function(elem){var actualColor=RicoUtil.getElementsComputedStyle(OpenLayers.Util.getElement(elem),"backgroundColor","background-color");if(actualColor=="transparent"&&elem.parentNode){return OpenLayers.Rico.Color.createColorFromBackground(elem.parentNode);} +if(actualColor==null){return new OpenLayers.Rico.Color(255,255,255);} +if(actualColor.indexOf("rgb(")==0){var colors=actualColor.substring(4,actualColor.length-1);var colorArray=colors.split(",");return new OpenLayers.Rico.Color(parseInt(colorArray[0]),parseInt(colorArray[1]),parseInt(colorArray[2]));} +else if(actualColor.indexOf("#")==0){return OpenLayers.Rico.Color.createFromHex(actualColor);} +else{return new OpenLayers.Rico.Color(255,255,255);}};OpenLayers.Rico.Color.HSBtoRGB=function(hue,saturation,brightness){var red=0;var green=0;var blue=0;if(saturation==0){red=parseInt(brightness*255.0+0.5);green=red;blue=red;} +else{var h=(hue-Math.floor(hue))*6.0;var f=h-Math.floor(h);var p=brightness*(1.0-saturation);var q=brightness*(1.0-saturation*f);var t=brightness*(1.0-(saturation*(1.0-f)));switch(parseInt(h)){case 0:red=(brightness*255.0+0.5);green=(t*255.0+0.5);blue=(p*255.0+0.5);break;case 1:red=(q*255.0+0.5);green=(brightness*255.0+0.5);blue=(p*255.0+0.5);break;case 2:red=(p*255.0+0.5);green=(brightness*255.0+0.5);blue=(t*255.0+0.5);break;case 3:red=(p*255.0+0.5);green=(q*255.0+0.5);blue=(brightness*255.0+0.5);break;case 4:red=(t*255.0+0.5);green=(p*255.0+0.5);blue=(brightness*255.0+0.5);break;case 5:red=(brightness*255.0+0.5);green=(p*255.0+0.5);blue=(q*255.0+0.5);break;}} +return{r:parseInt(red),g:parseInt(green),b:parseInt(blue)};};OpenLayers.Rico.Color.RGBtoHSB=function(r,g,b){var hue;var saturation;var brightness;var cmax=(r>g)?r:g;if(b>cmax){cmax=b;} +var cmin=(r<g)?r:g;if(b<cmin){cmin=b;} +brightness=cmax/255.0;if(cmax!=0){saturation=(cmax-cmin)/cmax;}else{saturation=0;} +if(saturation==0){hue=0;}else{var redc=(cmax-r)/(cmax-cmin);var greenc=(cmax-g)/(cmax-cmin);var bluec=(cmax-b)/(cmax-cmin);if(r==cmax){hue=bluec-greenc;}else if(g==cmax){hue=2.0+redc-bluec;}else{hue=4.0+greenc-redc;} +hue=hue/6.0;if(hue<0){hue=hue+1.0;}} +return{h:hue,s:saturation,b:brightness};};OpenLayers.Bounds=OpenLayers.Class({left:null,bottom:null,right:null,top:null,centerLonLat:null,initialize:function(left,bottom,right,top){if(left!=null){this.left=OpenLayers.Util.toFloat(left);} +if(bottom!=null){this.bottom=OpenLayers.Util.toFloat(bottom);} +if(right!=null){this.right=OpenLayers.Util.toFloat(right);} +if(top!=null){this.top=OpenLayers.Util.toFloat(top);}},clone:function(){return new OpenLayers.Bounds(this.left,this.bottom,this.right,this.top);},equals:function(bounds){var equals=false;if(bounds!=null){equals=((this.left==bounds.left)&&(this.right==bounds.right)&&(this.top==bounds.top)&&(this.bottom==bounds.bottom));} +return equals;},toString:function(){return("left-bottom=("+this.left+","+this.bottom+")" ++" right-top=("+this.right+","+this.top+")");},toArray:function(reverseAxisOrder){if(reverseAxisOrder===true){return[this.bottom,this.left,this.top,this.right];}else{return[this.left,this.bottom,this.right,this.top];}},toBBOX:function(decimal,reverseAxisOrder){if(decimal==null){decimal=6;} +var mult=Math.pow(10,decimal);var xmin=Math.round(this.left*mult)/mult;var ymin=Math.round(this.bottom*mult)/mult;var xmax=Math.round(this.right*mult)/mult;var ymax=Math.round(this.top*mult)/mult;if(reverseAxisOrder===true){return ymin+","+xmin+","+ymax+","+xmax;}else{return xmin+","+ymin+","+xmax+","+ymax;}},toGeometry:function(){return new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing([new OpenLayers.Geometry.Point(this.left,this.bottom),new OpenLayers.Geometry.Point(this.right,this.bottom),new OpenLayers.Geometry.Point(this.right,this.top),new OpenLayers.Geometry.Point(this.left,this.top)])]);},getWidth:function(){return(this.right-this.left);},getHeight:function(){return(this.top-this.bottom);},getSize:function(){return new OpenLayers.Size(this.getWidth(),this.getHeight());},getCenterPixel:function(){return new OpenLayers.Pixel((this.left+this.right)/2,(this.bottom+this.top)/2);},getCenterLonLat:function(){if(!this.centerLonLat){this.centerLonLat=new OpenLayers.LonLat((this.left+this.right)/2,(this.bottom+this.top)/2);} +return this.centerLonLat;},scale:function(ratio,origin){if(origin==null){origin=this.getCenterLonLat();} +var origx,origy;if(origin.CLASS_NAME=="OpenLayers.LonLat"){origx=origin.lon;origy=origin.lat;}else{origx=origin.x;origy=origin.y;} +var left=(this.left-origx)*ratio+origx;var bottom=(this.bottom-origy)*ratio+origy;var right=(this.right-origx)*ratio+origx;var top=(this.top-origy)*ratio+origy;return new OpenLayers.Bounds(left,bottom,right,top);},add:function(x,y){if((x==null)||(y==null)){var msg=OpenLayers.i18n("boundsAddError");OpenLayers.Console.error(msg);return null;} +return new OpenLayers.Bounds(this.left+x,this.bottom+y,this.right+x,this.top+y);},extend:function(object){var bounds=null;if(object){switch(object.CLASS_NAME){case"OpenLayers.LonLat":bounds=new OpenLayers.Bounds(object.lon,object.lat,object.lon,object.lat);break;case"OpenLayers.Geometry.Point":bounds=new OpenLayers.Bounds(object.x,object.y,object.x,object.y);break;case"OpenLayers.Bounds":bounds=object;break;} +if(bounds){this.centerLonLat=null;if((this.left==null)||(bounds.left<this.left)){this.left=bounds.left;} +if((this.bottom==null)||(bounds.bottom<this.bottom)){this.bottom=bounds.bottom;} +if((this.right==null)||(bounds.right>this.right)){this.right=bounds.right;} +if((this.top==null)||(bounds.top>this.top)){this.top=bounds.top;}}}},containsLonLat:function(ll,inclusive){return this.contains(ll.lon,ll.lat,inclusive);},containsPixel:function(px,inclusive){return this.contains(px.x,px.y,inclusive);},contains:function(x,y,inclusive){if(inclusive==null){inclusive=true;} +if(x==null||y==null){return false;} +x=OpenLayers.Util.toFloat(x);y=OpenLayers.Util.toFloat(y);var contains=false;if(inclusive){contains=((x>=this.left)&&(x<=this.right)&&(y>=this.bottom)&&(y<=this.top));}else{contains=((x>this.left)&&(x<this.right)&&(y>this.bottom)&&(y<this.top));} +return contains;},intersectsBounds:function(bounds,inclusive){if(inclusive==null){inclusive=true;} +var intersects=false;var mightTouch=(this.left==bounds.right||this.right==bounds.left||this.top==bounds.bottom||this.bottom==bounds.top);if(inclusive||!mightTouch){var inBottom=(((bounds.bottom>=this.bottom)&&(bounds.bottom<=this.top))||((this.bottom>=bounds.bottom)&&(this.bottom<=bounds.top)));var inTop=(((bounds.top>=this.bottom)&&(bounds.top<=this.top))||((this.top>bounds.bottom)&&(this.top<bounds.top)));var inLeft=(((bounds.left>=this.left)&&(bounds.left<=this.right))||((this.left>=bounds.left)&&(this.left<=bounds.right)));var inRight=(((bounds.right>=this.left)&&(bounds.right<=this.right))||((this.right>=bounds.left)&&(this.right<=bounds.right)));intersects=((inBottom||inTop)&&(inLeft||inRight));} +return intersects;},containsBounds:function(bounds,partial,inclusive){if(partial==null){partial=false;} +if(inclusive==null){inclusive=true;} +var bottomLeft=this.contains(bounds.left,bounds.bottom,inclusive);var bottomRight=this.contains(bounds.right,bounds.bottom,inclusive);var topLeft=this.contains(bounds.left,bounds.top,inclusive);var topRight=this.contains(bounds.right,bounds.top,inclusive);return(partial)?(bottomLeft||bottomRight||topLeft||topRight):(bottomLeft&&bottomRight&&topLeft&&topRight);},determineQuadrant:function(lonlat){var quadrant="";var center=this.getCenterLonLat();quadrant+=(lonlat.lat<center.lat)?"b":"t";quadrant+=(lonlat.lon<center.lon)?"l":"r";return quadrant;},transform:function(source,dest){this.centerLonLat=null;var ll=OpenLayers.Projection.transform({'x':this.left,'y':this.bottom},source,dest);var lr=OpenLayers.Projection.transform({'x':this.right,'y':this.bottom},source,dest);var ul=OpenLayers.Projection.transform({'x':this.left,'y':this.top},source,dest);var ur=OpenLayers.Projection.transform({'x':this.right,'y':this.top},source,dest);this.left=Math.min(ll.x,ul.x);this.bottom=Math.min(ll.y,lr.y);this.right=Math.max(lr.x,ur.x);this.top=Math.max(ul.y,ur.y);return this;},wrapDateLine:function(maxExtent,options){options=options||{};var leftTolerance=options.leftTolerance||0;var rightTolerance=options.rightTolerance||0;var newBounds=this.clone();if(maxExtent){while(newBounds.left<maxExtent.left&&(newBounds.right-rightTolerance)<=maxExtent.left){newBounds=newBounds.add(maxExtent.getWidth(),0);} +while((newBounds.left+leftTolerance)>=maxExtent.right&&newBounds.right>maxExtent.right){newBounds=newBounds.add(-maxExtent.getWidth(),0);}} +return newBounds;},CLASS_NAME:"OpenLayers.Bounds"});OpenLayers.Bounds.fromString=function(str){var bounds=str.split(",");return OpenLayers.Bounds.fromArray(bounds);};OpenLayers.Bounds.fromArray=function(bbox){return new OpenLayers.Bounds(parseFloat(bbox[0]),parseFloat(bbox[1]),parseFloat(bbox[2]),parseFloat(bbox[3]));};OpenLayers.Bounds.fromSize=function(size){return new OpenLayers.Bounds(0,size.h,size.w,0);};OpenLayers.Bounds.oppositeQuadrant=function(quadrant){var opp="";opp+=(quadrant.charAt(0)=='t')?'b':'t';opp+=(quadrant.charAt(1)=='l')?'r':'l';return opp;};OpenLayers.LonLat=OpenLayers.Class({lon:0.0,lat:0.0,initialize:function(lon,lat){this.lon=OpenLayers.Util.toFloat(lon);this.lat=OpenLayers.Util.toFloat(lat);},toString:function(){return("lon="+this.lon+",lat="+this.lat);},toShortString:function(){return(this.lon+", "+this.lat);},clone:function(){return new OpenLayers.LonLat(this.lon,this.lat);},add:function(lon,lat){if((lon==null)||(lat==null)){var msg=OpenLayers.i18n("lonlatAddError");OpenLayers.Console.error(msg);return null;} +return new OpenLayers.LonLat(this.lon+OpenLayers.Util.toFloat(lon),this.lat+OpenLayers.Util.toFloat(lat));},equals:function(ll){var equals=false;if(ll!=null){equals=((this.lon==ll.lon&&this.lat==ll.lat)||(isNaN(this.lon)&&isNaN(this.lat)&&isNaN(ll.lon)&&isNaN(ll.lat)));} +return equals;},transform:function(source,dest){var point=OpenLayers.Projection.transform({'x':this.lon,'y':this.lat},source,dest);this.lon=point.x;this.lat=point.y;return this;},wrapDateLine:function(maxExtent){var newLonLat=this.clone();if(maxExtent){while(newLonLat.lon<maxExtent.left){newLonLat.lon+=maxExtent.getWidth();} +while(newLonLat.lon>maxExtent.right){newLonLat.lon-=maxExtent.getWidth();}} +return newLonLat;},CLASS_NAME:"OpenLayers.LonLat"});OpenLayers.LonLat.fromString=function(str){var pair=str.split(",");return new OpenLayers.LonLat(pair[0],pair[1]);};OpenLayers.Pixel=OpenLayers.Class({x:0.0,y:0.0,initialize:function(x,y){this.x=parseFloat(x);this.y=parseFloat(y);},toString:function(){return("x="+this.x+",y="+this.y);},clone:function(){return new OpenLayers.Pixel(this.x,this.y);},equals:function(px){var equals=false;if(px!=null){equals=((this.x==px.x&&this.y==px.y)||(isNaN(this.x)&&isNaN(this.y)&&isNaN(px.x)&&isNaN(px.y)));} +return equals;},add:function(x,y){if((x==null)||(y==null)){var msg=OpenLayers.i18n("pixelAddError");OpenLayers.Console.error(msg);return null;} +return new OpenLayers.Pixel(this.x+x,this.y+y);},offset:function(px){var newPx=this.clone();if(px){newPx=this.add(px.x,px.y);} +return newPx;},CLASS_NAME:"OpenLayers.Pixel"});OpenLayers.Control=OpenLayers.Class({id:null,map:null,div:null,type:null,allowSelection:false,displayClass:"",title:"",autoActivate:false,active:null,handler:null,eventListeners:null,events:null,EVENT_TYPES:["activate","deactivate"],initialize:function(options){this.displayClass=this.CLASS_NAME.replace("OpenLayers.","ol").replace(/\./g,"");OpenLayers.Util.extend(this,options);this.events=new OpenLayers.Events(this,null,this.EVENT_TYPES);if(this.eventListeners instanceof Object){this.events.on(this.eventListeners);} +if(this.id==null){this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");}},destroy:function(){if(this.events){if(this.eventListeners){this.events.un(this.eventListeners);} +this.events.destroy();this.events=null;} +this.eventListeners=null;if(this.handler){this.handler.destroy();this.handler=null;} +if(this.handlers){for(var key in this.handlers){if(this.handlers.hasOwnProperty(key)&&typeof this.handlers[key].destroy=="function"){this.handlers[key].destroy();}} +this.handlers=null;} +if(this.map){this.map.removeControl(this);this.map=null;}},setMap:function(map){this.map=map;if(this.handler){this.handler.setMap(map);}},draw:function(px){if(this.div==null){this.div=OpenLayers.Util.createDiv(this.id);this.div.className=this.displayClass;if(!this.allowSelection){this.div.className+=" olControlNoSelect";this.div.setAttribute("unselectable","on",0);this.div.onselectstart=OpenLayers.Function.False;} +if(this.title!=""){this.div.title=this.title;}} +if(px!=null){this.position=px.clone();} +this.moveTo(this.position);return this.div;},moveTo:function(px){if((px!=null)&&(this.div!=null)){this.div.style.left=px.x+"px";this.div.style.top=px.y+"px";}},activate:function(){if(this.active){return false;} +if(this.handler){this.handler.activate();} +this.active=true;if(this.map){OpenLayers.Element.addClass(this.map.viewPortDiv,this.displayClass.replace(/ /g,"")+"Active");} +this.events.triggerEvent("activate");return true;},deactivate:function(){if(this.active){if(this.handler){this.handler.deactivate();} +this.active=false;if(this.map){OpenLayers.Element.removeClass(this.map.viewPortDiv,this.displayClass.replace(/ /g,"")+"Active");} +this.events.triggerEvent("deactivate");return true;} +return false;},CLASS_NAME:"OpenLayers.Control"});OpenLayers.Control.TYPE_BUTTON=1;OpenLayers.Control.TYPE_TOGGLE=2;OpenLayers.Control.TYPE_TOOL=3;OpenLayers.Lang={code:null,defaultCode:"en",getCode:function(){if(!OpenLayers.Lang.code){OpenLayers.Lang.setCode();} +return OpenLayers.Lang.code;},setCode:function(code){var lang;if(!code){code=(OpenLayers.Util.getBrowserName()=="msie")?navigator.userLanguage:navigator.language;} +var parts=code.split('-');parts[0]=parts[0].toLowerCase();if(typeof OpenLayers.Lang[parts[0]]=="object"){lang=parts[0];} +if(parts[1]){var testLang=parts[0]+'-'+parts[1].toUpperCase();if(typeof OpenLayers.Lang[testLang]=="object"){lang=testLang;}} +if(!lang){OpenLayers.Console.warn('Failed to find OpenLayers.Lang.'+parts.join("-")+' dictionary, falling back to default language');lang=OpenLayers.Lang.defaultCode;} +OpenLayers.Lang.code=lang;},translate:function(key,context){var dictionary=OpenLayers.Lang[OpenLayers.Lang.getCode()];var message=dictionary[key];if(!message){message=key;} +if(context){message=OpenLayers.String.format(message,context);} +return message;}};OpenLayers.i18n=OpenLayers.Lang.translate;OpenLayers.Popup.Anchored=OpenLayers.Class(OpenLayers.Popup,{relativePosition:null,keepInMap:true,anchor:null,initialize:function(id,lonlat,contentSize,contentHTML,anchor,closeBox,closeBoxCallback){var newArguments=[id,lonlat,contentSize,contentHTML,closeBox,closeBoxCallback];OpenLayers.Popup.prototype.initialize.apply(this,newArguments);this.anchor=(anchor!=null)?anchor:{size:new OpenLayers.Size(0,0),offset:new OpenLayers.Pixel(0,0)};},destroy:function(){this.anchor=null;this.relativePosition=null;OpenLayers.Popup.prototype.destroy.apply(this,arguments);},show:function(){this.updatePosition();OpenLayers.Popup.prototype.show.apply(this,arguments);},moveTo:function(px){var oldRelativePosition=this.relativePosition;this.relativePosition=this.calculateRelativePosition(px);var newPx=this.calculateNewPx(px);var newArguments=new Array(newPx);OpenLayers.Popup.prototype.moveTo.apply(this,newArguments);if(this.relativePosition!=oldRelativePosition){this.updateRelativePosition();}},setSize:function(contentSize){OpenLayers.Popup.prototype.setSize.apply(this,arguments);if((this.lonlat)&&(this.map)){var px=this.map.getLayerPxFromLonLat(this.lonlat);this.moveTo(px);}},calculateRelativePosition:function(px){var lonlat=this.map.getLonLatFromLayerPx(px);var extent=this.map.getExtent();var quadrant=extent.determineQuadrant(lonlat);return OpenLayers.Bounds.oppositeQuadrant(quadrant);},updateRelativePosition:function(){},calculateNewPx:function(px){var newPx=px.offset(this.anchor.offset);var size=this.size||this.contentSize;var top=(this.relativePosition.charAt(0)=='t');newPx.y+=(top)?-(size.h+this.anchor.size.h):this.anchor.size.h;var left=(this.relativePosition.charAt(1)=='l');newPx.x+=(left)?-(size.w+this.anchor.size.w):this.anchor.size.w;return newPx;},CLASS_NAME:"OpenLayers.Popup.Anchored"});OpenLayers.Protocol.SOS=function(options){options=OpenLayers.Util.applyDefaults(options,OpenLayers.Protocol.SOS.DEFAULTS);var cls=OpenLayers.Protocol.SOS["v"+options.version.replace(/\./g,"_")];if(!cls){throw"Unsupported SOS version: "+options.version;} +return new cls(options);};OpenLayers.Protocol.SOS.DEFAULTS={"version":"1.0.0"};OpenLayers.Protocol.SQL=OpenLayers.Class(OpenLayers.Protocol,{databaseName:'ol',tableName:"ol_vector_features",postReadFiltering:true,initialize:function(options){OpenLayers.Protocol.prototype.initialize.apply(this,[options]);},destroy:function(){OpenLayers.Protocol.prototype.destroy.apply(this);},supported:function(){return false;},evaluateFilter:function(feature,filter){return filter&&this.postReadFiltering?filter.evaluate(feature):true;},CLASS_NAME:"OpenLayers.Protocol.SQL"});OpenLayers.Protocol.WFS=function(options){options=OpenLayers.Util.applyDefaults(options,OpenLayers.Protocol.WFS.DEFAULTS);var cls=OpenLayers.Protocol.WFS["v"+options.version.replace(/\./g,"_")];if(!cls){throw"Unsupported WFS version: "+options.version;} +return new cls(options);};OpenLayers.Protocol.WFS.fromWMSLayer=function(layer,options){var typeName,featurePrefix;var param=layer.params["LAYERS"];var parts=(param instanceof Array?param[0]:param).split(":");if(parts.length>1){featurePrefix=parts[0];} +typeName=parts.pop();var protocolOptions={url:layer.url,featureType:typeName,featurePrefix:featurePrefix,srsName:layer.projection&&layer.projection.getCode()||layer.map&&layer.map.getProjectionObject().getCode(),version:"1.1.0"};return new OpenLayers.Protocol.WFS(OpenLayers.Util.applyDefaults(options,protocolOptions));};OpenLayers.Protocol.WFS.DEFAULTS={"version":"1.0.0"};OpenLayers.Renderer.Canvas=OpenLayers.Class(OpenLayers.Renderer,{canvas:null,features:null,initialize:function(containerID){OpenLayers.Renderer.prototype.initialize.apply(this,arguments);this.root=document.createElement("canvas");this.container.appendChild(this.root);this.canvas=this.root.getContext("2d");this.features={};},eraseGeometry:function(geometry,featureId){this.eraseFeatures(this.features[featureId][0]);},supported:function(){var canvas=document.createElement("canvas");return!!canvas.getContext;},setExtent:function(extent){this.extent=extent.clone();this.resolution=null;this.redraw();},setSize:function(size){this.size=size.clone();this.root.style.width=size.w+"px";this.root.style.height=size.h+"px";this.root.width=size.w;this.root.height=size.h;this.resolution=null;},drawFeature:function(feature,style){style=style||feature.style;style=this.applyDefaultSymbolizer(style);this.features[feature.id]=[feature,style];this.redraw();},drawGeometry:function(geometry,style){var className=geometry.CLASS_NAME;if((className=="OpenLayers.Geometry.Collection")||(className=="OpenLayers.Geometry.MultiPoint")||(className=="OpenLayers.Geometry.MultiLineString")||(className=="OpenLayers.Geometry.MultiPolygon")){for(var i=0;i<geometry.components.length;i++){this.drawGeometry(geometry.components[i],style);} +return;} +switch(geometry.CLASS_NAME){case"OpenLayers.Geometry.Point":this.drawPoint(geometry,style);break;case"OpenLayers.Geometry.LineString":this.drawLineString(geometry,style);break;case"OpenLayers.Geometry.LinearRing":this.drawLinearRing(geometry,style);break;case"OpenLayers.Geometry.Polygon":this.drawPolygon(geometry,style);break;default:break;}},drawExternalGraphic:function(pt,style){var img=new Image();if(style.graphicTitle){img.title=style.graphicTitle;} +var width=style.graphicWidth||style.graphicHeight;var height=style.graphicHeight||style.graphicWidth;width=width?width:style.pointRadius*2;height=height?height:style.pointRadius*2;var xOffset=(style.graphicXOffset!=undefined)?style.graphicXOffset:-(0.5*width);var yOffset=(style.graphicYOffset!=undefined)?style.graphicYOffset:-(0.5*height);var context={img:img,x:(pt[0]+xOffset),y:(pt[1]+yOffset),width:width,height:height,opacity:style.graphicOpacity||style.fillOpacity,canvas:this.canvas};img.onload=OpenLayers.Function.bind(function(){this.canvas.globalAlpha=this.opacity;this.canvas.drawImage(this.img,this.x,this.y,this.width,this.height);},context);img.src=style.externalGraphic;},setCanvasStyle:function(type,style){if(type=="fill"){this.canvas.globalAlpha=style['fillOpacity'];this.canvas.fillStyle=style['fillColor'];}else if(type=="stroke"){this.canvas.globalAlpha=style['strokeOpacity'];this.canvas.strokeStyle=style['strokeColor'];this.canvas.lineWidth=style['strokeWidth'];}else{this.canvas.globalAlpha=0;this.canvas.lineWidth=1;}},drawPoint:function(geometry,style){if(style.graphic!==false){var pt=this.getLocalXY(geometry);if(style.externalGraphic){this.drawExternalGraphic(pt,style);}else{if(style.fill!==false){this.setCanvasStyle("fill",style);this.canvas.beginPath();this.canvas.arc(pt[0],pt[1],style.pointRadius,0,Math.PI*2,true);this.canvas.fill();} +if(style.stroke!==false){this.setCanvasStyle("stroke",style);this.canvas.beginPath();this.canvas.arc(pt[0],pt[1],style.pointRadius,0,Math.PI*2,true);this.canvas.stroke();this.setCanvasStyle("reset");}}}},drawLineString:function(geometry,style){if(style.stroke!==false){this.setCanvasStyle("stroke",style);this.canvas.beginPath();var start=this.getLocalXY(geometry.components[0]);this.canvas.moveTo(start[0],start[1]);for(var i=1;i<geometry.components.length;i++){var pt=this.getLocalXY(geometry.components[i]);this.canvas.lineTo(pt[0],pt[1]);} +this.canvas.stroke();} +this.setCanvasStyle("reset");},drawLinearRing:function(geometry,style){if(style.fill!==false){this.setCanvasStyle("fill",style);this.canvas.beginPath();var start=this.getLocalXY(geometry.components[0]);this.canvas.moveTo(start[0],start[1]);for(var i=1;i<geometry.components.length-1;i++){var pt=this.getLocalXY(geometry.components[i]);this.canvas.lineTo(pt[0],pt[1]);} +this.canvas.fill();} +if(style.stroke!==false){this.setCanvasStyle("stroke",style);this.canvas.beginPath();var start=this.getLocalXY(geometry.components[0]);this.canvas.moveTo(start[0],start[1]);for(var i=1;i<geometry.components.length;i++){var pt=this.getLocalXY(geometry.components[i]);this.canvas.lineTo(pt[0],pt[1]);} +this.canvas.stroke();} +this.setCanvasStyle("reset");},drawPolygon:function(geometry,style){this.drawLinearRing(geometry.components[0],style);for(var i=1;i<geometry.components.length;i++){this.drawLinearRing(geometry.components[i],{fillOpacity:0,strokeWidth:0,strokeOpacity:0,strokeColor:'#000000',fillColor:'#000000'});}},drawText:function(location,style){style=OpenLayers.Util.extend({fontColor:"#000000",labelAlign:"cm"},style);var pt=this.getLocalXY(location);this.setCanvasStyle("reset");this.canvas.fillStyle=style.fontColor;this.canvas.globalAlpha=style.fontOpacity||1.0;var fontStyle=style.fontWeight+" "+style.fontSize+" "+style.fontFamily;if(this.canvas.fillText){var labelAlign=OpenLayers.Renderer.Canvas.LABEL_ALIGN[style.labelAlign[0]]||"center";this.canvas.font=fontStyle;this.canvas.textAlign=labelAlign;this.canvas.fillText(style.label,pt[0],pt[1]);}else if(this.canvas.mozDrawText){this.canvas.mozTextStyle=fontStyle;var len=this.canvas.mozMeasureText(style.label);switch(style.labelAlign[0]){case"l":break;case"r":pt[0]-=len;break;case"c":default:pt[0]-=len/2;} +this.canvas.translate(pt[0],pt[1]);this.canvas.mozDrawText(style.label);this.canvas.translate(-1*pt[0],-1*pt[1]);} +this.setCanvasStyle("reset");},getLocalXY:function(point){var resolution=this.getResolution();var extent=this.extent;var x=(point.x/resolution+(-extent.left/resolution));var y=((extent.top/resolution)-point.y/resolution);return[x,y];},clear:function(){this.canvas.clearRect(0,0,this.root.width,this.root.height);this.features={};},getFeatureIdFromEvent:function(evt){var loc=this.map.getLonLatFromPixel(evt.xy);var resolution=this.getResolution();var bounds=new OpenLayers.Bounds(loc.lon-resolution*5,loc.lat-resolution*5,loc.lon+resolution*5,loc.lat+resolution*5);var geom=bounds.toGeometry();for(var feat in this.features){if(!this.features.hasOwnProperty(feat)){continue;} +if(this.features[feat][0].geometry.intersects(geom)){return feat;}} +return null;},eraseFeatures:function(features){if(!(features instanceof Array)){features=[features];} +for(var i=0;i<features.length;++i){delete this.features[features[i].id];} +this.redraw();},redraw:function(){if(!this.locked){this.canvas.clearRect(0,0,this.root.width,this.root.height);var labelMap=[];var feature,style;for(var id in this.features){if(!this.features.hasOwnProperty(id)){continue;} +feature=this.features[id][0];style=this.features[id][1];if(!feature.geometry){continue;} +this.drawGeometry(feature.geometry,style);if(style.label){labelMap.push([feature,style]);}} +var item;for(var i=0,len=labelMap.length;i<len;++i){item=labelMap[i];this.drawText(item[0].geometry.getCentroid(),item[1]);}}},CLASS_NAME:"OpenLayers.Renderer.Canvas"});OpenLayers.Renderer.Canvas.LABEL_ALIGN={"l":"left","r":"right"};OpenLayers.ElementsIndexer=OpenLayers.Class({maxZIndex:null,order:null,indices:null,compare:null,initialize:function(yOrdering){this.compare=yOrdering?OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_Y_ORDER:OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_DRAWING_ORDER;this.order=[];this.indices={};this.maxZIndex=0;},insert:function(newNode){if(this.exists(newNode)){this.remove(newNode);} +var nodeId=newNode.id;this.determineZIndex(newNode);var leftIndex=-1;var rightIndex=this.order.length;var middle;while(rightIndex-leftIndex>1){middle=parseInt((leftIndex+rightIndex)/2);var placement=this.compare(this,newNode,OpenLayers.Util.getElement(this.order[middle]));if(placement>0){leftIndex=middle;}else{rightIndex=middle;}} +this.order.splice(rightIndex,0,nodeId);this.indices[nodeId]=this.getZIndex(newNode);return this.getNextElement(rightIndex);},remove:function(node){var nodeId=node.id;var arrayIndex=OpenLayers.Util.indexOf(this.order,nodeId);if(arrayIndex>=0){this.order.splice(arrayIndex,1);delete this.indices[nodeId];if(this.order.length>0){var lastId=this.order[this.order.length-1];this.maxZIndex=this.indices[lastId];}else{this.maxZIndex=0;}}},clear:function(){this.order=[];this.indices={};this.maxZIndex=0;},exists:function(node){return(this.indices[node.id]!=null);},getZIndex:function(node){return node._style.graphicZIndex;},determineZIndex:function(node){var zIndex=node._style.graphicZIndex;if(zIndex==null){zIndex=this.maxZIndex;node._style.graphicZIndex=zIndex;}else if(zIndex>this.maxZIndex){this.maxZIndex=zIndex;}},getNextElement:function(index){var nextIndex=index+1;if(nextIndex<this.order.length){var nextElement=OpenLayers.Util.getElement(this.order[nextIndex]);if(nextElement==undefined){nextElement=this.getNextElement(nextIndex);} +return nextElement;}else{return null;}},CLASS_NAME:"OpenLayers.ElementsIndexer"});OpenLayers.ElementsIndexer.IndexingMethods={Z_ORDER:function(indexer,newNode,nextNode){var newZIndex=indexer.getZIndex(newNode);var returnVal=0;if(nextNode){var nextZIndex=indexer.getZIndex(nextNode);returnVal=newZIndex-nextZIndex;} +return returnVal;},Z_ORDER_DRAWING_ORDER:function(indexer,newNode,nextNode){var returnVal=OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(indexer,newNode,nextNode);if(nextNode&&returnVal==0){returnVal=1;} +return returnVal;},Z_ORDER_Y_ORDER:function(indexer,newNode,nextNode){var returnVal=OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(indexer,newNode,nextNode);if(nextNode&&returnVal===0){var result=nextNode._boundsBottom-newNode._boundsBottom;returnVal=(result===0)?1:result;} +return returnVal;}};OpenLayers.Renderer.Elements=OpenLayers.Class(OpenLayers.Renderer,{rendererRoot:null,root:null,vectorRoot:null,textRoot:null,xmlns:null,indexer:null,BACKGROUND_ID_SUFFIX:"_background",LABEL_ID_SUFFIX:"_label",initialize:function(containerID,options){OpenLayers.Renderer.prototype.initialize.apply(this,arguments);this.rendererRoot=this.createRenderRoot();this.root=this.createRoot("_root");this.vectorRoot=this.createRoot("_vroot");this.textRoot=this.createRoot("_troot");this.root.appendChild(this.vectorRoot);this.root.appendChild(this.textRoot);this.rendererRoot.appendChild(this.root);this.container.appendChild(this.rendererRoot);if(options&&(options.zIndexing||options.yOrdering)){this.indexer=new OpenLayers.ElementsIndexer(options.yOrdering);}},destroy:function(){this.clear();this.rendererRoot=null;this.root=null;this.xmlns=null;OpenLayers.Renderer.prototype.destroy.apply(this,arguments);},clear:function(){var child;var root=this.vectorRoot;if(root){while(child=root.firstChild){root.removeChild(child);}} +root=this.textRoot;if(root){while(child=root.firstChild){root.removeChild(child);}} +if(this.indexer){this.indexer.clear();}},getNodeType:function(geometry,style){},drawGeometry:function(geometry,style,featureId){var className=geometry.CLASS_NAME;var rendered=true;if((className=="OpenLayers.Geometry.Collection")||(className=="OpenLayers.Geometry.MultiPoint")||(className=="OpenLayers.Geometry.MultiLineString")||(className=="OpenLayers.Geometry.MultiPolygon")){for(var i=0,len=geometry.components.length;i<len;i++){rendered=this.drawGeometry(geometry.components[i],style,featureId)&&rendered;} +return rendered;};rendered=false;if(style.display!="none"){if(style.backgroundGraphic){this.redrawBackgroundNode(geometry.id,geometry,style,featureId);} +rendered=this.redrawNode(geometry.id,geometry,style,featureId);} +if(rendered==false){var node=document.getElementById(geometry.id);if(node){if(node._style.backgroundGraphic){node.parentNode.removeChild(document.getElementById(geometry.id+this.BACKGROUND_ID_SUFFIX));} +node.parentNode.removeChild(node);}} +return rendered;},redrawNode:function(id,geometry,style,featureId){style=this.applyDefaultSymbolizer(style);var node=this.nodeFactory(id,this.getNodeType(geometry,style));node._featureId=featureId;node._boundsBottom=geometry.getBounds().bottom;node._geometryClass=geometry.CLASS_NAME;node._style=style;var drawResult=this.drawGeometryNode(node,geometry,style);if(drawResult===false){return false;} +node=drawResult.node;if(this.indexer){var insert=this.indexer.insert(node);if(insert){this.vectorRoot.insertBefore(node,insert);}else{this.vectorRoot.appendChild(node);}}else{if(node.parentNode!==this.vectorRoot){this.vectorRoot.appendChild(node);}} +this.postDraw(node);return drawResult.complete;},redrawBackgroundNode:function(id,geometry,style,featureId){var backgroundStyle=OpenLayers.Util.extend({},style);backgroundStyle.externalGraphic=backgroundStyle.backgroundGraphic;backgroundStyle.graphicXOffset=backgroundStyle.backgroundXOffset;backgroundStyle.graphicYOffset=backgroundStyle.backgroundYOffset;backgroundStyle.graphicZIndex=backgroundStyle.backgroundGraphicZIndex;backgroundStyle.graphicWidth=backgroundStyle.backgroundWidth||backgroundStyle.graphicWidth;backgroundStyle.graphicHeight=backgroundStyle.backgroundHeight||backgroundStyle.graphicHeight;backgroundStyle.backgroundGraphic=null;backgroundStyle.backgroundXOffset=null;backgroundStyle.backgroundYOffset=null;backgroundStyle.backgroundGraphicZIndex=null;return this.redrawNode(id+this.BACKGROUND_ID_SUFFIX,geometry,backgroundStyle,null);},drawGeometryNode:function(node,geometry,style){style=style||node._style;var options={'isFilled':style.fill===undefined?true:style.fill,'isStroked':style.stroke===undefined?!!style.strokeWidth:style.stroke};var drawn;switch(geometry.CLASS_NAME){case"OpenLayers.Geometry.Point":if(style.graphic===false){options.isFilled=false;options.isStroked=false;} +drawn=this.drawPoint(node,geometry);break;case"OpenLayers.Geometry.LineString":options.isFilled=false;drawn=this.drawLineString(node,geometry);break;case"OpenLayers.Geometry.LinearRing":drawn=this.drawLinearRing(node,geometry);break;case"OpenLayers.Geometry.Polygon":drawn=this.drawPolygon(node,geometry);break;case"OpenLayers.Geometry.Surface":drawn=this.drawSurface(node,geometry);break;case"OpenLayers.Geometry.Rectangle":drawn=this.drawRectangle(node,geometry);break;default:break;} +node._options=options;if(drawn!=false){return{node:this.setStyle(node,style,options,geometry),complete:drawn};}else{return false;}},postDraw:function(node){},drawPoint:function(node,geometry){},drawLineString:function(node,geometry){},drawLinearRing:function(node,geometry){},drawPolygon:function(node,geometry){},drawRectangle:function(node,geometry){},drawCircle:function(node,geometry){},drawSurface:function(node,geometry){},removeText:function(featureId){var label=document.getElementById(featureId+this.LABEL_ID_SUFFIX);if(label){this.textRoot.removeChild(label);}},getFeatureIdFromEvent:function(evt){var target=evt.target;var useElement=target&&target.correspondingUseElement;var node=useElement?useElement:(target||evt.srcElement);var featureId=node._featureId;return featureId;},eraseGeometry:function(geometry,featureId){if((geometry.CLASS_NAME=="OpenLayers.Geometry.MultiPoint")||(geometry.CLASS_NAME=="OpenLayers.Geometry.MultiLineString")||(geometry.CLASS_NAME=="OpenLayers.Geometry.MultiPolygon")||(geometry.CLASS_NAME=="OpenLayers.Geometry.Collection")){for(var i=0,len=geometry.components.length;i<len;i++){this.eraseGeometry(geometry.components[i],featureId);}}else{var element=OpenLayers.Util.getElement(geometry.id);if(element&&element.parentNode){if(element.geometry){element.geometry.destroy();element.geometry=null;} +element.parentNode.removeChild(element);if(this.indexer){this.indexer.remove(element);} +if(element._style.backgroundGraphic){var backgroundId=geometry.id+this.BACKGROUND_ID_SUFFIX;var bElem=OpenLayers.Util.getElement(backgroundId);if(bElem&&bElem.parentNode){bElem.parentNode.removeChild(bElem);}}}}},nodeFactory:function(id,type){var node=OpenLayers.Util.getElement(id);if(node){if(!this.nodeTypeCompare(node,type)){node.parentNode.removeChild(node);node=this.nodeFactory(id,type);}}else{node=this.createNode(type,id);} +return node;},nodeTypeCompare:function(node,type){},createNode:function(type,id){},moveRoot:function(renderer){var root=this.root;if(renderer.root.parentNode==this.rendererRoot){root=renderer.root;} +root.parentNode.removeChild(root);renderer.rendererRoot.appendChild(root);},getRenderLayerId:function(){return this.root.parentNode.parentNode.id;},isComplexSymbol:function(graphicName){return(graphicName!="circle")&&!!graphicName;},CLASS_NAME:"OpenLayers.Renderer.Elements"});OpenLayers.Renderer.symbol={"star":[350,75,379,161,469,161,397,215,423,301,350,250,277,301,303,215,231,161,321,161,350,75],"cross":[4,0,6,0,6,4,10,4,10,6,6,6,6,10,4,10,4,6,0,6,0,4,4,4,4,0],"x":[0,0,25,0,50,35,75,0,100,0,65,50,100,100,75,100,50,65,25,100,0,100,35,50,0,0],"square":[0,0,0,1,1,1,1,0,0,0],"triangle":[0,10,10,10,5,0,0,10]};OpenLayers.Strategy.Cluster=OpenLayers.Class(OpenLayers.Strategy,{distance:20,threshold:null,features:null,clusters:null,clustering:false,resolution:null,initialize:function(options){OpenLayers.Strategy.prototype.initialize.apply(this,[options]);},activate:function(){var activated=OpenLayers.Strategy.prototype.activate.call(this);if(activated){this.layer.events.on({"beforefeaturesadded":this.cacheFeatures,"moveend":this.cluster,scope:this});} +return activated;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.clearCache();this.layer.events.un({"beforefeaturesadded":this.cacheFeatures,"moveend":this.cluster,scope:this});} +return deactivated;},cacheFeatures:function(event){var propagate=true;if(!this.clustering){this.clearCache();this.features=event.features;this.cluster();propagate=false;} +return propagate;},clearCache:function(){this.features=null;},cluster:function(event){if((!event||event.zoomChanged)&&this.features){var resolution=this.layer.map.getResolution();if(resolution!=this.resolution||!this.clustersExist()){this.resolution=resolution;var clusters=[];var feature,clustered,cluster;for(var i=0;i<this.features.length;++i){feature=this.features[i];if(feature.geometry){clustered=false;for(var j=clusters.length-1;j>=0;--j){cluster=clusters[j];if(this.shouldCluster(cluster,feature)){this.addToCluster(cluster,feature);clustered=true;break;}} +if(!clustered){clusters.push(this.createCluster(this.features[i]));}}} +this.layer.removeAllFeatures();if(clusters.length>0){if(this.threshold>1){var clone=clusters.slice();clusters=[];var candidate;for(var i=0,len=clone.length;i<len;++i){candidate=clone[i];if(candidate.attributes.count<this.threshold){Array.prototype.push.apply(clusters,candidate.cluster);}else{clusters.push(candidate);}}} +this.clustering=true;this.layer.addFeatures(clusters);this.clustering=false;} +this.clusters=clusters;}}},clustersExist:function(){var exist=false;if(this.clusters&&this.clusters.length>0&&this.clusters.length==this.layer.features.length){exist=true;for(var i=0;i<this.clusters.length;++i){if(this.clusters[i]!=this.layer.features[i]){exist=false;break;}}} +return exist;},shouldCluster:function(cluster,feature){var cc=cluster.geometry.getBounds().getCenterLonLat();var fc=feature.geometry.getBounds().getCenterLonLat();var distance=(Math.sqrt(Math.pow((cc.lon-fc.lon),2)+Math.pow((cc.lat-fc.lat),2))/this.resolution);return(distance<=this.distance);},addToCluster:function(cluster,feature){cluster.cluster.push(feature);cluster.attributes.count+=1;},createCluster:function(feature){var center=feature.geometry.getBounds().getCenterLonLat();var cluster=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(center.lon,center.lat),{count:1});cluster.cluster=[feature];return cluster;},CLASS_NAME:"OpenLayers.Strategy.Cluster"});OpenLayers.Strategy.Fixed=OpenLayers.Class(OpenLayers.Strategy,{preload:false,initialize:function(options){OpenLayers.Strategy.prototype.initialize.apply(this,[options]);},destroy:function(){OpenLayers.Strategy.prototype.destroy.apply(this,arguments);},activate:function(){if(OpenLayers.Strategy.prototype.activate.apply(this,arguments)){this.layer.events.on({"refresh":this.load,scope:this});if(this.layer.visibility==true||this.preload){this.load();}else{this.layer.events.on({"visibilitychanged":this.load,scope:this});} +return true;} +return false;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.layer.events.un({"refresh":this.load,"visibilitychanged":this.load,scope:this});} +return deactivated;},load:function(options){this.layer.events.triggerEvent("loadstart");this.layer.protocol.read(OpenLayers.Util.applyDefaults({callback:this.merge,filter:this.layer.filter,scope:this},options));this.layer.events.un({"visibilitychanged":this.load,scope:this});},merge:function(resp){this.layer.destroyFeatures();var features=resp.features;if(features&&features.length>0){var remote=this.layer.projection;var local=this.layer.map.getProjectionObject();if(!local.equals(remote)){var geom;for(var i=0,len=features.length;i<len;++i){geom=features[i].geometry;if(geom){geom.transform(remote,local);}}} +this.layer.addFeatures(features);} +this.layer.events.triggerEvent("loadend");},CLASS_NAME:"OpenLayers.Strategy.Fixed"});OpenLayers.Strategy.Paging=OpenLayers.Class(OpenLayers.Strategy,{features:null,length:10,num:null,paging:false,initialize:function(options){OpenLayers.Strategy.prototype.initialize.apply(this,[options]);},activate:function(){var activated=OpenLayers.Strategy.prototype.activate.call(this);if(activated){this.layer.events.on({"beforefeaturesadded":this.cacheFeatures,scope:this});} +return activated;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.clearCache();this.layer.events.un({"beforefeaturesadded":this.cacheFeatures,scope:this});} +return deactivated;},cacheFeatures:function(event){if(!this.paging){this.clearCache();this.features=event.features;this.pageNext(event);}},clearCache:function(){if(this.features){for(var i=0;i<this.features.length;++i){this.features[i].destroy();}} +this.features=null;this.num=null;},pageCount:function(){var numFeatures=this.features?this.features.length:0;return Math.ceil(numFeatures/this.length);},pageNum:function(){return this.num;},pageLength:function(newLength){if(newLength&&newLength>0){this.length=newLength;} +return this.length;},pageNext:function(event){var changed=false;if(this.features){if(this.num===null){this.num=-1;} +var start=(this.num+1)*this.length;changed=this.page(start,event);} +return changed;},pagePrevious:function(){var changed=false;if(this.features){if(this.num===null){this.num=this.pageCount();} +var start=(this.num-1)*this.length;changed=this.page(start);} +return changed;},page:function(start,event){var changed=false;if(this.features){if(start>=0&&start<this.features.length){var num=Math.floor(start/this.length);if(num!=this.num){this.paging=true;var features=this.features.slice(start,start+this.length);this.layer.removeFeatures(this.layer.features);this.num=num;if(event&&event.features){event.features=features;}else{this.layer.addFeatures(features);} +this.paging=false;changed=true;}}} +return changed;},CLASS_NAME:"OpenLayers.Strategy.Paging"});OpenLayers.Strategy.Refresh=OpenLayers.Class(OpenLayers.Strategy,{force:false,interval:0,timer:null,initialize:function(options){OpenLayers.Strategy.prototype.initialize.apply(this,[options]);},activate:function(){var activated=OpenLayers.Strategy.prototype.activate.call(this);if(activated){if(this.layer.visibility===true){this.start();} +this.layer.events.on({"visibilitychanged":this.reset,scope:this});} +return activated;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.stop();} +return deactivated;},reset:function(){if(this.layer.visibility===true){this.start();}else{this.stop();}},start:function(){if(this.interval&&typeof this.interval==="number"&&this.interval>0){this.timer=window.setInterval(OpenLayers.Function.bind(this.refresh,this),this.interval);}},refresh:function(){if(this.layer&&this.layer.refresh&&typeof this.layer.refresh=="function"){this.layer.refresh({force:this.force});}},stop:function(){if(this.timer!==null){window.clearInterval(this.timer);this.timer=null;}},CLASS_NAME:"OpenLayers.Strategy.Refresh"});OpenLayers.Strategy.Save=OpenLayers.Class(OpenLayers.Strategy,{EVENT_TYPES:["start","success","fail"],events:null,auto:false,timer:null,initialize:function(options){OpenLayers.Strategy.prototype.initialize.apply(this,[options]);this.events=new OpenLayers.Events(this,null,this.EVENT_TYPES);},activate:function(){var activated=OpenLayers.Strategy.prototype.activate.call(this);if(activated){if(this.auto){if(typeof this.auto==="number"){this.timer=window.setInterval(OpenLayers.Function.bind(this.save,this),this.auto*1000);}else{this.layer.events.on({"featureadded":this.triggerSave,"afterfeaturemodified":this.triggerSave,scope:this});}}} +return activated;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){if(this.auto){if(typeof this.auto==="number"){window.clearInterval(this.timer);}else{this.layer.events.un({"featureadded":this.triggerSave,"afterfeaturemodified":this.triggerSave,scope:this});}}} +return deactivated;},triggerSave:function(event){var feature=event.feature;if(feature.state===OpenLayers.State.INSERT||feature.state===OpenLayers.State.UPDATE||feature.state===OpenLayers.State.DELETE){this.save([event.feature]);}},save:function(features){if(!features){features=this.layer.features;} +this.events.triggerEvent("start",{features:features});var remote=this.layer.projection;var local=this.layer.map.getProjectionObject();if(!local.equals(remote)){var len=features.length;var clones=new Array(len);var orig,clone;for(var i=0;i<len;++i){orig=features[i];clone=orig.clone();clone.fid=orig.fid;clone.state=orig.state;if(orig.url){clone.url=orig.url;} +clone._original=orig;clone.geometry.transform(local,remote);clones[i]=clone;} +features=clones;} +this.layer.protocol.commit(features,{callback:this.onCommit,scope:this});},onCommit:function(response){var evt={"response":response};if(response.success()){var features=response.reqFeatures;var state,feature;var destroys=[];var insertIds=response.insertIds||[];var j=0;for(var i=0,len=features.length;i<len;++i){feature=features[i];feature=feature._original||feature;state=feature.state;if(state){if(state==OpenLayers.State.DELETE){destroys.push(feature);}else if(state==OpenLayers.State.INSERT){feature.fid=insertIds[j];++j;} +feature.state=null;}} +if(destroys.length>0){this.layer.destroyFeatures(destroys);} +this.events.triggerEvent("success",evt);}else{this.events.triggerEvent("fail",evt);}},CLASS_NAME:"OpenLayers.Strategy.Save"});OpenLayers.Symbolizer.Line=OpenLayers.Class(OpenLayers.Symbolizer,{strokeColor:null,strokeOpacity:null,strokeWidth:null,strokeLinecap:null,strokeDashstyle:null,initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Line"});OpenLayers.Symbolizer.Point=OpenLayers.Class(OpenLayers.Symbolizer,{strokeColor:null,strokeOpacity:null,strokeWidth:null,strokeLinecap:null,strokeDashstyle:null,fillColor:null,fillOpacity:null,pointRadius:null,externalGraphic:null,graphicWidth:null,graphicHeight:null,graphicOpacity:null,graphicXOffset:null,graphicYOffset:null,rotation:null,graphicName:null,initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Point"});OpenLayers.Symbolizer.Polygon=OpenLayers.Class(OpenLayers.Symbolizer,{strokeColor:null,strokeOpacity:null,strokeWidth:null,strokeLinecap:null,strokeDashstyle:null,fillColor:null,fillOpacity:null,initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Polygon"});OpenLayers.Symbolizer.Raster=OpenLayers.Class(OpenLayers.Symbolizer,{initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Raster"});OpenLayers.Symbolizer.Text=OpenLayers.Class(OpenLayers.Symbolizer,{label:null,fontFamily:null,fontSize:null,fontWeight:null,fontStyle:null,initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Text"});OpenLayers.Tween=OpenLayers.Class({INTERVAL:10,easing:null,begin:null,finish:null,duration:null,callbacks:null,time:null,interval:null,playing:false,initialize:function(easing){this.easing=(easing)?easing:OpenLayers.Easing.Expo.easeOut;},start:function(begin,finish,duration,options){this.playing=true;this.begin=begin;this.finish=finish;this.duration=duration;this.callbacks=options.callbacks;this.time=0;if(this.interval){window.clearInterval(this.interval);this.interval=null;} +if(this.callbacks&&this.callbacks.start){this.callbacks.start.call(this,this.begin);} +this.interval=window.setInterval(OpenLayers.Function.bind(this.play,this),this.INTERVAL);},stop:function(){if(!this.playing){return;} +if(this.callbacks&&this.callbacks.done){this.callbacks.done.call(this,this.finish);} +window.clearInterval(this.interval);this.interval=null;this.playing=false;},play:function(){var value={};for(var i in this.begin){var b=this.begin[i];var f=this.finish[i];if(b==null||f==null||isNaN(b)||isNaN(f)){OpenLayers.Console.error('invalid value for Tween');} +var c=f-b;value[i]=this.easing.apply(this,[this.time,b,c,this.duration]);} +this.time++;if(this.callbacks&&this.callbacks.eachStep){this.callbacks.eachStep.call(this,value);} +if(this.time>this.duration){this.stop();}},CLASS_NAME:"OpenLayers.Tween"});OpenLayers.Easing={CLASS_NAME:"OpenLayers.Easing"};OpenLayers.Easing.Linear={easeIn:function(t,b,c,d){return c*t/d+b;},easeOut:function(t,b,c,d){return c*t/d+b;},easeInOut:function(t,b,c,d){return c*t/d+b;},CLASS_NAME:"OpenLayers.Easing.Linear"};OpenLayers.Easing.Expo={easeIn:function(t,b,c,d){return(t==0)?b:c*Math.pow(2,10*(t/d-1))+b;},easeOut:function(t,b,c,d){return(t==d)?b+c:c*(-Math.pow(2,-10*t/d)+1)+b;},easeInOut:function(t,b,c,d){if(t==0)return b;if(t==d)return b+c;if((t/=d/2)<1)return c/2*Math.pow(2,10*(t-1))+b;return c/2*(-Math.pow(2,-10*--t)+2)+b;},CLASS_NAME:"OpenLayers.Easing.Expo"};OpenLayers.Easing.Quad={easeIn:function(t,b,c,d){return c*(t/=d)*t+b;},easeOut:function(t,b,c,d){return-c*(t/=d)*(t-2)+b;},easeInOut:function(t,b,c,d){if((t/=d/2)<1)return c/2*t*t+b;return-c/2*((--t)*(t-2)-1)+b;},CLASS_NAME:"OpenLayers.Easing.Quad"};OpenLayers.Control.ArgParser=OpenLayers.Class(OpenLayers.Control,{center:null,zoom:null,layers:null,displayProjection:null,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,arguments);},setMap:function(map){OpenLayers.Control.prototype.setMap.apply(this,arguments);for(var i=0,len=this.map.controls.length;i<len;i++){var control=this.map.controls[i];if((control!=this)&&(control.CLASS_NAME=="OpenLayers.Control.ArgParser")){if(control.displayProjection!=this.displayProjection){this.displayProjection=control.displayProjection;} +break;}} +if(i==this.map.controls.length){var args=OpenLayers.Util.getParameters();if(args.layers){this.layers=args.layers;this.map.events.register('addlayer',this,this.configureLayers);this.configureLayers();} +if(args.lat&&args.lon){this.center=new OpenLayers.LonLat(parseFloat(args.lon),parseFloat(args.lat));if(args.zoom){this.zoom=parseInt(args.zoom);} +this.map.events.register('changebaselayer',this,this.setCenter);this.setCenter();}}},setCenter:function(){if(this.map.baseLayer){this.map.events.unregister('changebaselayer',this,this.setCenter);if(this.displayProjection){this.center.transform(this.displayProjection,this.map.getProjectionObject());} +this.map.setCenter(this.center,this.zoom);}},configureLayers:function(){if(this.layers.length==this.map.layers.length){this.map.events.unregister('addlayer',this,this.configureLayers);for(var i=0,len=this.layers.length;i<len;i++){var layer=this.map.layers[i];var c=this.layers.charAt(i);if(c=="B"){this.map.setBaseLayer(layer);}else if((c=="T")||(c=="F")){layer.setVisibility(c=="T");}}}},CLASS_NAME:"OpenLayers.Control.ArgParser"});OpenLayers.Control.Attribution=OpenLayers.Class(OpenLayers.Control,{separator:", ",initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,arguments);},destroy:function(){this.map.events.un({"removelayer":this.updateAttribution,"addlayer":this.updateAttribution,"changelayer":this.updateAttribution,"changebaselayer":this.updateAttribution,scope:this});OpenLayers.Control.prototype.destroy.apply(this,arguments);},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);this.map.events.on({'changebaselayer':this.updateAttribution,'changelayer':this.updateAttribution,'addlayer':this.updateAttribution,'removelayer':this.updateAttribution,scope:this});this.updateAttribution();return this.div;},updateAttribution:function(){var attributions=[];if(this.map&&this.map.layers){for(var i=0,len=this.map.layers.length;i<len;i++){var layer=this.map.layers[i];if(layer.attribution&&layer.getVisibility()){if(OpenLayers.Util.indexOf(attributions,layer.attribution)===-1){attributions.push(layer.attribution);}}} +this.div.innerHTML=attributions.join(this.separator);}},CLASS_NAME:"OpenLayers.Control.Attribution"});OpenLayers.Control.Button=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_BUTTON,trigger:function(){},CLASS_NAME:"OpenLayers.Control.Button"});OpenLayers.Control.Graticule=OpenLayers.Class(OpenLayers.Control,{autoActivate:true,intervals:[45,30,20,10,5,2,1,0.5,0.2,0.1,0.05,0.01,0.005,0.002,0.001],displayInLayerSwitcher:true,visible:true,numPoints:50,targetSize:200,layerName:null,labelled:true,labelFormat:'dm',lineSymbolizer:{strokeColor:"#333",strokeWidth:1,strokeOpacity:0.5},labelSymbolizer:{},gratLayer:null,initialize:function(options){options=options||{};options.layerName=options.layerName||OpenLayers.i18n("graticule");OpenLayers.Control.prototype.initialize.apply(this,[options]);this.labelSymbolizer.stroke=false;this.labelSymbolizer.fill=false;this.labelSymbolizer.label="${label}";this.labelSymbolizer.labelAlign="${labelAlign}";this.labelSymbolizer.labelXOffset="${xOffset}";this.labelSymbolizer.labelYOffset="${yOffset}";},destroy:function(){this.deactivate();OpenLayers.Control.prototype.destroy.apply(this,arguments);if(this.gratLayer){this.gratLayer.destroy();this.gratLayer=null;}},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!this.gratLayer){var gratStyle=new OpenLayers.Style({},{rules:[new OpenLayers.Rule({'symbolizer':{"Point":this.labelSymbolizer,"Line":this.lineSymbolizer}})]});this.gratLayer=new OpenLayers.Layer.Vector(this.layerName,{styleMap:new OpenLayers.StyleMap({'default':gratStyle}),visibility:this.visible,displayInLayerSwitcher:this.displayInLayerSwitcher});} +return this.div;},activate:function(){if(OpenLayers.Control.prototype.activate.apply(this,arguments)){this.map.addLayer(this.gratLayer);this.map.events.register('moveend',this,this.update);this.update();return true;}else{return false;}},deactivate:function(){if(OpenLayers.Control.prototype.deactivate.apply(this,arguments)){this.map.events.unregister('moveend',this,this.update);this.map.removeLayer(this.gratLayer);return true;}else{return false;}},update:function(){var mapBounds=this.map.getExtent();if(!mapBounds){return;} +this.gratLayer.destroyFeatures();var llProj=new OpenLayers.Projection("EPSG:4326");var mapProj=this.map.getProjectionObject();var mapRes=this.map.getResolution();if(mapProj.proj&&mapProj.proj.projName=="longlat"){this.numPoints=1;} +var mapCenter=this.map.getCenter();var mapCenterLL=new OpenLayers.Pixel(mapCenter.lon,mapCenter.lat);OpenLayers.Projection.transform(mapCenterLL,mapProj,llProj);var testSq=this.targetSize*mapRes;testSq*=testSq;var llInterval;for(var i=0;i<this.intervals.length;++i){llInterval=this.intervals[i];var delta=llInterval/2;var p1=mapCenterLL.offset(new OpenLayers.Pixel(-delta,-delta));var p2=mapCenterLL.offset(new OpenLayers.Pixel(delta,delta));OpenLayers.Projection.transform(p1,llProj,mapProj);OpenLayers.Projection.transform(p2,llProj,mapProj);var distSq=(p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y);if(distSq<=testSq){break;}} +mapCenterLL.x=Math.floor(mapCenterLL.x/llInterval)*llInterval;mapCenterLL.y=Math.floor(mapCenterLL.y/llInterval)*llInterval;var iter=0;var centerLonPoints=[mapCenterLL.clone()];var newPoint=mapCenterLL.clone();var mapXY;do{newPoint=newPoint.offset(new OpenLayers.Pixel(0,llInterval));mapXY=OpenLayers.Projection.transform(newPoint.clone(),llProj,mapProj);centerLonPoints.unshift(newPoint);}while(mapBounds.containsPixel(mapXY)&&++iter<1000);newPoint=mapCenterLL.clone();do{newPoint=newPoint.offset(new OpenLayers.Pixel(0,-llInterval));mapXY=OpenLayers.Projection.transform(newPoint.clone(),llProj,mapProj);centerLonPoints.push(newPoint);}while(mapBounds.containsPixel(mapXY)&&++iter<1000);iter=0;var centerLatPoints=[mapCenterLL.clone()];newPoint=mapCenterLL.clone();do{newPoint=newPoint.offset(new OpenLayers.Pixel(-llInterval,0));mapXY=OpenLayers.Projection.transform(newPoint.clone(),llProj,mapProj);centerLatPoints.unshift(newPoint);}while(mapBounds.containsPixel(mapXY)&&++iter<1000);newPoint=mapCenterLL.clone();do{newPoint=newPoint.offset(new OpenLayers.Pixel(llInterval,0));mapXY=OpenLayers.Projection.transform(newPoint.clone(),llProj,mapProj);centerLatPoints.push(newPoint);}while(mapBounds.containsPixel(mapXY)&&++iter<1000);var lines=[];for(var i=0;i<centerLatPoints.length;++i){var lon=centerLatPoints[i].x;var pointList=[];var labelPoint=null;var latEnd=Math.min(centerLonPoints[0].y,90);var latStart=Math.max(centerLonPoints[centerLonPoints.length-1].y,-90);var latDelta=(latEnd-latStart)/this.numPoints;var lat=latStart;for(var j=0;j<=this.numPoints;++j){var gridPoint=new OpenLayers.Geometry.Point(lon,lat);gridPoint.transform(llProj,mapProj);pointList.push(gridPoint);lat+=latDelta;if(gridPoint.y>=mapBounds.bottom&&!labelPoint){labelPoint=gridPoint;}} +if(this.labelled){var labelPos=new OpenLayers.Geometry.Point(labelPoint.x,mapBounds.bottom);var labelAttrs={value:lon,label:this.labelled?OpenLayers.Util.getFormattedLonLat(lon,"lon",this.labelFormat):"",labelAlign:"cb",xOffset:0,yOffset:2};this.gratLayer.addFeatures(new OpenLayers.Feature.Vector(labelPos,labelAttrs));} +var geom=new OpenLayers.Geometry.LineString(pointList);lines.push(new OpenLayers.Feature.Vector(geom));} +for(var j=0;j<centerLonPoints.length;++j){lat=centerLonPoints[j].y;if(lat<-90||lat>90){continue;} +var pointList=[];var lonStart=centerLatPoints[0].x;var lonEnd=centerLatPoints[centerLatPoints.length-1].x;var lonDelta=(lonEnd-lonStart)/this.numPoints;var lon=lonStart;var labelPoint=null;for(var i=0;i<=this.numPoints;++i){var gridPoint=new OpenLayers.Geometry.Point(lon,lat);gridPoint.transform(llProj,mapProj);pointList.push(gridPoint);lon+=lonDelta;if(gridPoint.x<mapBounds.right){labelPoint=gridPoint;}} +if(this.labelled){var labelPos=new OpenLayers.Geometry.Point(mapBounds.right,labelPoint.y);var labelAttrs={value:lat,label:this.labelled?OpenLayers.Util.getFormattedLonLat(lat,"lat",this.labelFormat):"",labelAlign:"rb",xOffset:-2,yOffset:2};this.gratLayer.addFeatures(new OpenLayers.Feature.Vector(labelPos,labelAttrs));} +var geom=new OpenLayers.Geometry.LineString(pointList);lines.push(new OpenLayers.Feature.Vector(geom));} +this.gratLayer.addFeatures(lines);},CLASS_NAME:"OpenLayers.Control.Graticule"});OpenLayers.Control.LayerSwitcher=OpenLayers.Class(OpenLayers.Control,{roundedCorner:true,roundedCornerColor:"darkblue",layerStates:null,layersDiv:null,baseLayersDiv:null,baseLayers:null,dataLbl:null,dataLayersDiv:null,dataLayers:null,minimizeDiv:null,maximizeDiv:null,ascending:true,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,arguments);this.layerStates=[];},destroy:function(){OpenLayers.Event.stopObservingElement(this.div);OpenLayers.Event.stopObservingElement(this.minimizeDiv);OpenLayers.Event.stopObservingElement(this.maximizeDiv);this.clearLayersArray("base");this.clearLayersArray("data");this.map.events.un({"addlayer":this.redraw,"changelayer":this.redraw,"removelayer":this.redraw,"changebaselayer":this.redraw,scope:this});OpenLayers.Control.prototype.destroy.apply(this,arguments);},setMap:function(map){OpenLayers.Control.prototype.setMap.apply(this,arguments);this.map.events.on({"addlayer":this.redraw,"changelayer":this.redraw,"removelayer":this.redraw,"changebaselayer":this.redraw,scope:this});},draw:function(){OpenLayers.Control.prototype.draw.apply(this);this.loadContents();if(!this.outsideViewport){this.minimizeControl();} +this.redraw();return this.div;},clearLayersArray:function(layersType){var layers=this[layersType+"Layers"];if(layers){for(var i=0,len=layers.length;i<len;i++){var layer=layers[i];OpenLayers.Event.stopObservingElement(layer.inputElem);OpenLayers.Event.stopObservingElement(layer.labelSpan);}} +this[layersType+"LayersDiv"].innerHTML="";this[layersType+"Layers"]=[];},checkRedraw:function(){var redraw=false;if(!this.layerStates.length||(this.map.layers.length!=this.layerStates.length)){redraw=true;}else{for(var i=0,len=this.layerStates.length;i<len;i++){var layerState=this.layerStates[i];var layer=this.map.layers[i];if((layerState.name!=layer.name)||(layerState.inRange!=layer.inRange)||(layerState.id!=layer.id)||(layerState.visibility!=layer.visibility)){redraw=true;break;}}} +return redraw;},redraw:function(){if(!this.checkRedraw()){return this.div;} +this.clearLayersArray("base");this.clearLayersArray("data");var containsOverlays=false;var containsBaseLayers=false;var len=this.map.layers.length;this.layerStates=new Array(len);for(var i=0;i<len;i++){var layer=this.map.layers[i];this.layerStates[i]={'name':layer.name,'visibility':layer.visibility,'inRange':layer.inRange,'id':layer.id};} +var layers=this.map.layers.slice();if(!this.ascending){layers.reverse();} +for(var i=0,len=layers.length;i<len;i++){var layer=layers[i];var baseLayer=layer.isBaseLayer;if(layer.displayInLayerSwitcher){if(baseLayer){containsBaseLayers=true;}else{containsOverlays=true;} +var checked=(baseLayer)?(layer==this.map.baseLayer):layer.getVisibility();var inputElem=document.createElement("input");inputElem.id=this.id+"_input_"+layer.name;inputElem.name=(baseLayer)?this.id+"_baseLayers":layer.name;inputElem.type=(baseLayer)?"radio":"checkbox";inputElem.value=layer.name;inputElem.checked=checked;inputElem.defaultChecked=checked;if(!baseLayer&&!layer.inRange){inputElem.disabled=true;} +var context={'inputElem':inputElem,'layer':layer,'layerSwitcher':this};OpenLayers.Event.observe(inputElem,"mouseup",OpenLayers.Function.bindAsEventListener(this.onInputClick,context));var labelSpan=document.createElement("span");OpenLayers.Element.addClass(labelSpan,"labelSpan") +if(!baseLayer&&!layer.inRange){labelSpan.style.color="gray";} +labelSpan.innerHTML=layer.name;labelSpan.style.verticalAlign=(baseLayer)?"bottom":"baseline";OpenLayers.Event.observe(labelSpan,"click",OpenLayers.Function.bindAsEventListener(this.onInputClick,context));var br=document.createElement("br");var groupArray=(baseLayer)?this.baseLayers:this.dataLayers;groupArray.push({'layer':layer,'inputElem':inputElem,'labelSpan':labelSpan});var groupDiv=(baseLayer)?this.baseLayersDiv:this.dataLayersDiv;groupDiv.appendChild(inputElem);groupDiv.appendChild(labelSpan);groupDiv.appendChild(br);}} +this.dataLbl.style.display=(containsOverlays)?"":"none";this.baseLbl.style.display=(containsBaseLayers)?"":"none";return this.div;},onInputClick:function(e){if(!this.inputElem.disabled){if(this.inputElem.type=="radio"){this.inputElem.checked=true;this.layer.map.setBaseLayer(this.layer);}else{this.inputElem.checked=!this.inputElem.checked;this.layerSwitcher.updateMap();}} +OpenLayers.Event.stop(e);},onLayerClick:function(e){this.updateMap();},updateMap:function(){for(var i=0,len=this.baseLayers.length;i<len;i++){var layerEntry=this.baseLayers[i];if(layerEntry.inputElem.checked){this.map.setBaseLayer(layerEntry.layer,false);}} +for(var i=0,len=this.dataLayers.length;i<len;i++){var layerEntry=this.dataLayers[i];layerEntry.layer.setVisibility(layerEntry.inputElem.checked);}},maximizeControl:function(e){this.div.style.width="";this.div.style.height="";this.showControls(false);if(e!=null){OpenLayers.Event.stop(e);}},minimizeControl:function(e){this.div.style.width="0px";this.div.style.height="0px";this.showControls(true);if(e!=null){OpenLayers.Event.stop(e);}},showControls:function(minimize){this.maximizeDiv.style.display=minimize?"":"none";this.minimizeDiv.style.display=minimize?"none":"";this.layersDiv.style.display=minimize?"none":"";},loadContents:function(){OpenLayers.Event.observe(this.div,"mouseup",OpenLayers.Function.bindAsEventListener(this.mouseUp,this));OpenLayers.Event.observe(this.div,"click",this.ignoreEvent);OpenLayers.Event.observe(this.div,"mousedown",OpenLayers.Function.bindAsEventListener(this.mouseDown,this));OpenLayers.Event.observe(this.div,"dblclick",this.ignoreEvent);this.layersDiv=document.createElement("div");this.layersDiv.id=this.id+"_layersDiv";OpenLayers.Element.addClass(this.layersDiv,"layersDiv");this.baseLbl=document.createElement("div");this.baseLbl.innerHTML=OpenLayers.i18n("baseLayer");OpenLayers.Element.addClass(this.baseLbl,"baseLbl");this.baseLayersDiv=document.createElement("div");OpenLayers.Element.addClass(this.baseLayersDiv,"baseLayersDiv");this.dataLbl=document.createElement("div");this.dataLbl.innerHTML=OpenLayers.i18n("overlays");OpenLayers.Element.addClass(this.dataLbl,"dataLbl");this.dataLayersDiv=document.createElement("div");OpenLayers.Element.addClass(this.dataLayersDiv,"dataLayersDiv");if(this.ascending){this.layersDiv.appendChild(this.baseLbl);this.layersDiv.appendChild(this.baseLayersDiv);this.layersDiv.appendChild(this.dataLbl);this.layersDiv.appendChild(this.dataLayersDiv);}else{this.layersDiv.appendChild(this.dataLbl);this.layersDiv.appendChild(this.dataLayersDiv);this.layersDiv.appendChild(this.baseLbl);this.layersDiv.appendChild(this.baseLayersDiv);} +this.div.appendChild(this.layersDiv);if(this.roundedCorner){OpenLayers.Rico.Corner.round(this.div,{corners:"tl bl",bgColor:"transparent",color:this.roundedCornerColor,blend:false});OpenLayers.Rico.Corner.changeOpacity(this.layersDiv,0.75);} +var imgLocation=OpenLayers.Util.getImagesLocation();var sz=new OpenLayers.Size(18,18);var img=imgLocation+'layer-switcher-maximize.png';this.maximizeDiv=OpenLayers.Util.createAlphaImageDiv("OpenLayers_Control_MaximizeDiv",null,sz,img,"absolute");OpenLayers.Element.addClass(this.maximizeDiv,"maximizeDiv");this.maximizeDiv.style.display="none";OpenLayers.Event.observe(this.maximizeDiv,"click",OpenLayers.Function.bindAsEventListener(this.maximizeControl,this));this.div.appendChild(this.maximizeDiv);var img=imgLocation+'layer-switcher-minimize.png';var sz=new OpenLayers.Size(18,18);this.minimizeDiv=OpenLayers.Util.createAlphaImageDiv("OpenLayers_Control_MinimizeDiv",null,sz,img,"absolute");OpenLayers.Element.addClass(this.minimizeDiv,"minimizeDiv");this.minimizeDiv.style.display="none";OpenLayers.Event.observe(this.minimizeDiv,"click",OpenLayers.Function.bindAsEventListener(this.minimizeControl,this));this.div.appendChild(this.minimizeDiv);},ignoreEvent:function(evt){OpenLayers.Event.stop(evt);},mouseDown:function(evt){this.isMouseDown=true;this.ignoreEvent(evt);},mouseUp:function(evt){if(this.isMouseDown){this.isMouseDown=false;this.ignoreEvent(evt);}},CLASS_NAME:"OpenLayers.Control.LayerSwitcher"});OpenLayers.Control.MouseDefaults=OpenLayers.Class(OpenLayers.Control,{performedDrag:false,wheelObserver:null,initialize:function(){OpenLayers.Control.prototype.initialize.apply(this,arguments);},destroy:function(){if(this.handler){this.handler.destroy();} +this.handler=null;this.map.events.un({"click":this.defaultClick,"dblclick":this.defaultDblClick,"mousedown":this.defaultMouseDown,"mouseup":this.defaultMouseUp,"mousemove":this.defaultMouseMove,"mouseout":this.defaultMouseOut,scope:this});OpenLayers.Event.stopObserving(window,"DOMMouseScroll",this.wheelObserver);OpenLayers.Event.stopObserving(window,"mousewheel",this.wheelObserver);OpenLayers.Event.stopObserving(document,"mousewheel",this.wheelObserver);this.wheelObserver=null;OpenLayers.Control.prototype.destroy.apply(this,arguments);},draw:function(){this.map.events.on({"click":this.defaultClick,"dblclick":this.defaultDblClick,"mousedown":this.defaultMouseDown,"mouseup":this.defaultMouseUp,"mousemove":this.defaultMouseMove,"mouseout":this.defaultMouseOut,scope:this});this.registerWheelEvents();},registerWheelEvents:function(){this.wheelObserver=OpenLayers.Function.bindAsEventListener(this.onWheelEvent,this);OpenLayers.Event.observe(window,"DOMMouseScroll",this.wheelObserver);OpenLayers.Event.observe(window,"mousewheel",this.wheelObserver);OpenLayers.Event.observe(document,"mousewheel",this.wheelObserver);},defaultClick:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;} +var notAfterDrag=!this.performedDrag;this.performedDrag=false;return notAfterDrag;},defaultDblClick:function(evt){var newCenter=this.map.getLonLatFromViewPortPx(evt.xy);this.map.setCenter(newCenter,this.map.zoom+1);OpenLayers.Event.stop(evt);return false;},defaultMouseDown:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;} +this.mouseDragStart=evt.xy.clone();this.performedDrag=false;if(evt.shiftKey){this.map.div.style.cursor="crosshair";this.zoomBox=OpenLayers.Util.createDiv('zoomBox',this.mouseDragStart,null,null,"absolute","2px solid red");this.zoomBox.style.backgroundColor="white";this.zoomBox.style.filter="alpha(opacity=50)";this.zoomBox.style.opacity="0.50";this.zoomBox.style.fontSize="1px";this.zoomBox.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.viewPortDiv.appendChild(this.zoomBox);} +document.onselectstart=OpenLayers.Function.False;OpenLayers.Event.stop(evt);},defaultMouseMove:function(evt){this.mousePosition=evt.xy.clone();if(this.mouseDragStart!=null){if(this.zoomBox){var deltaX=Math.abs(this.mouseDragStart.x-evt.xy.x);var deltaY=Math.abs(this.mouseDragStart.y-evt.xy.y);this.zoomBox.style.width=Math.max(1,deltaX)+"px";this.zoomBox.style.height=Math.max(1,deltaY)+"px";if(evt.xy.x<this.mouseDragStart.x){this.zoomBox.style.left=evt.xy.x+"px";} +if(evt.xy.y<this.mouseDragStart.y){this.zoomBox.style.top=evt.xy.y+"px";}}else{var deltaX=this.mouseDragStart.x-evt.xy.x;var deltaY=this.mouseDragStart.y-evt.xy.y;var size=this.map.getSize();var newXY=new OpenLayers.Pixel(size.w/2+deltaX,size.h/2+deltaY);var newCenter=this.map.getLonLatFromViewPortPx(newXY);this.map.setCenter(newCenter,null,true);this.mouseDragStart=evt.xy.clone();this.map.div.style.cursor="move";} +this.performedDrag=true;}},defaultMouseUp:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;} +if(this.zoomBox){this.zoomBoxEnd(evt);}else{if(this.performedDrag){this.map.setCenter(this.map.center);}} +document.onselectstart=null;this.mouseDragStart=null;this.map.div.style.cursor="";},defaultMouseOut:function(evt){if(this.mouseDragStart!=null&&OpenLayers.Util.mouseLeft(evt,this.map.div)){if(this.zoomBox){this.removeZoomBox();} +this.mouseDragStart=null;}},defaultWheelUp:function(evt){if(this.map.getZoom()<=this.map.getNumZoomLevels()){this.map.setCenter(this.map.getLonLatFromPixel(evt.xy),this.map.getZoom()+1);}},defaultWheelDown:function(evt){if(this.map.getZoom()>0){this.map.setCenter(this.map.getLonLatFromPixel(evt.xy),this.map.getZoom()-1);}},zoomBoxEnd:function(evt){if(this.mouseDragStart!=null){if(Math.abs(this.mouseDragStart.x-evt.xy.x)>5||Math.abs(this.mouseDragStart.y-evt.xy.y)>5){var start=this.map.getLonLatFromViewPortPx(this.mouseDragStart);var end=this.map.getLonLatFromViewPortPx(evt.xy);var top=Math.max(start.lat,end.lat);var bottom=Math.min(start.lat,end.lat);var left=Math.min(start.lon,end.lon);var right=Math.max(start.lon,end.lon);var bounds=new OpenLayers.Bounds(left,bottom,right,top);this.map.zoomToExtent(bounds);}else{var end=this.map.getLonLatFromViewPortPx(evt.xy);this.map.setCenter(new OpenLayers.LonLat((end.lon),(end.lat)),this.map.getZoom()+1);} +this.removeZoomBox();}},removeZoomBox:function(){this.map.viewPortDiv.removeChild(this.zoomBox);this.zoomBox=null;},onWheelEvent:function(e){var inMap=false;var elem=OpenLayers.Event.element(e);while(elem!=null){if(this.map&&elem==this.map.div){inMap=true;break;} +elem=elem.parentNode;} +if(inMap){var delta=0;if(!e){e=window.event;} +if(e.wheelDelta){delta=e.wheelDelta/120;if(window.opera&&window.opera.version()<9.2){delta=-delta;}}else if(e.detail){delta=-e.detail/3;} +if(delta){e.xy=this.mousePosition;if(delta<0){this.defaultWheelDown(e);}else{this.defaultWheelUp(e);}} +OpenLayers.Event.stop(e);}},CLASS_NAME:"OpenLayers.Control.MouseDefaults"});OpenLayers.Control.MousePosition=OpenLayers.Class(OpenLayers.Control,{autoActivate:true,element:null,prefix:'',separator:', ',suffix:'',numDigits:5,granularity:10,emptyString:null,lastXy:null,displayProjection:null,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,arguments);},destroy:function(){this.deactivate();OpenLayers.Control.prototype.destroy.apply(this,arguments);},activate:function(){if(OpenLayers.Control.prototype.activate.apply(this,arguments)){this.map.events.register('mousemove',this,this.redraw);this.map.events.register('mouseout',this,this.reset);this.redraw();return true;}else{return false;}},deactivate:function(){if(OpenLayers.Control.prototype.deactivate.apply(this,arguments)){this.map.events.unregister('mousemove',this,this.redraw);this.map.events.unregister('mouseout',this,this.reset);this.element.innerHTML="";return true;}else{return false;}},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!this.element){this.div.left="";this.div.top="";this.element=this.div;} +return this.div;},redraw:function(evt){var lonLat;if(evt==null){this.reset();return;}else{if(this.lastXy==null||Math.abs(evt.xy.x-this.lastXy.x)>this.granularity||Math.abs(evt.xy.y-this.lastXy.y)>this.granularity) +{this.lastXy=evt.xy;return;} +lonLat=this.map.getLonLatFromPixel(evt.xy);if(!lonLat){return;} +if(this.displayProjection){lonLat.transform(this.map.getProjectionObject(),this.displayProjection);} +this.lastXy=evt.xy;} +var newHtml=this.formatOutput(lonLat);if(newHtml!=this.element.innerHTML){this.element.innerHTML=newHtml;}},reset:function(evt){if(this.emptyString!=null){this.element.innerHTML=this.emptyString;}},formatOutput:function(lonLat){var digits=parseInt(this.numDigits);var newHtml=this.prefix+ +lonLat.lon.toFixed(digits)+ +this.separator+ +lonLat.lat.toFixed(digits)+ +this.suffix;return newHtml;},CLASS_NAME:"OpenLayers.Control.MousePosition"});OpenLayers.Control.Pan=OpenLayers.Class(OpenLayers.Control,{slideFactor:50,direction:null,type:OpenLayers.Control.TYPE_BUTTON,initialize:function(direction,options){this.direction=direction;this.CLASS_NAME+=this.direction;OpenLayers.Control.prototype.initialize.apply(this,[options]);},trigger:function(){switch(this.direction){case OpenLayers.Control.Pan.NORTH:this.map.pan(0,-this.slideFactor);break;case OpenLayers.Control.Pan.SOUTH:this.map.pan(0,this.slideFactor);break;case OpenLayers.Control.Pan.WEST:this.map.pan(-this.slideFactor,0);break;case OpenLayers.Control.Pan.EAST:this.map.pan(this.slideFactor,0);break;}},CLASS_NAME:"OpenLayers.Control.Pan"});OpenLayers.Control.Pan.NORTH="North";OpenLayers.Control.Pan.SOUTH="South";OpenLayers.Control.Pan.EAST="East";OpenLayers.Control.Pan.WEST="West";OpenLayers.Control.PanZoom=OpenLayers.Class(OpenLayers.Control,{slideFactor:50,slideRatio:null,buttons:null,position:null,initialize:function(options){this.position=new OpenLayers.Pixel(OpenLayers.Control.PanZoom.X,OpenLayers.Control.PanZoom.Y);OpenLayers.Control.prototype.initialize.apply(this,arguments);},destroy:function(){OpenLayers.Control.prototype.destroy.apply(this,arguments);this.removeButtons();this.buttons=null;this.position=null;},draw:function(px){OpenLayers.Control.prototype.draw.apply(this,arguments);px=this.position;this.buttons=[];var sz=new OpenLayers.Size(18,18);var centered=new OpenLayers.Pixel(px.x+sz.w/2,px.y);this._addButton("panup","north-mini.png",centered,sz);px.y=centered.y+sz.h;this._addButton("panleft","west-mini.png",px,sz);this._addButton("panright","east-mini.png",px.add(sz.w,0),sz);this._addButton("pandown","south-mini.png",centered.add(0,sz.h*2),sz);this._addButton("zoomin","zoom-plus-mini.png",centered.add(0,sz.h*3+5),sz);this._addButton("zoomworld","zoom-world-mini.png",centered.add(0,sz.h*4+5),sz);this._addButton("zoomout","zoom-minus-mini.png",centered.add(0,sz.h*5+5),sz);return this.div;},_addButton:function(id,img,xy,sz){var imgLocation=OpenLayers.Util.getImagesLocation()+img;var btn=OpenLayers.Util.createAlphaImageDiv(this.id+"_"+id,xy,sz,imgLocation,"absolute");this.div.appendChild(btn);OpenLayers.Event.observe(btn,"mousedown",OpenLayers.Function.bindAsEventListener(this.buttonDown,btn));OpenLayers.Event.observe(btn,"dblclick",OpenLayers.Function.bindAsEventListener(this.doubleClick,btn));OpenLayers.Event.observe(btn,"click",OpenLayers.Function.bindAsEventListener(this.doubleClick,btn));btn.action=id;btn.map=this.map;if(!this.slideRatio){var slideFactorPixels=this.slideFactor;var getSlideFactor=function(){return slideFactorPixels;};}else{var slideRatio=this.slideRatio;var getSlideFactor=function(dim){return this.map.getSize()[dim]*slideRatio;};} +btn.getSlideFactor=getSlideFactor;this.buttons.push(btn);return btn;},_removeButton:function(btn){OpenLayers.Event.stopObservingElement(btn);btn.map=null;btn.getSlideFactor=null;this.div.removeChild(btn);OpenLayers.Util.removeItem(this.buttons,btn);},removeButtons:function(){for(var i=this.buttons.length-1;i>=0;--i){this._removeButton(this.buttons[i]);}},doubleClick:function(evt){OpenLayers.Event.stop(evt);return false;},buttonDown:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;} +switch(this.action){case"panup":this.map.pan(0,-this.getSlideFactor("h"));break;case"pandown":this.map.pan(0,this.getSlideFactor("h"));break;case"panleft":this.map.pan(-this.getSlideFactor("w"),0);break;case"panright":this.map.pan(this.getSlideFactor("w"),0);break;case"zoomin":this.map.zoomIn();break;case"zoomout":this.map.zoomOut();break;case"zoomworld":this.map.zoomToMaxExtent();break;} +OpenLayers.Event.stop(evt);},CLASS_NAME:"OpenLayers.Control.PanZoom"});OpenLayers.Control.PanZoom.X=4;OpenLayers.Control.PanZoom.Y=4;OpenLayers.Control.Panel=OpenLayers.Class(OpenLayers.Control,{controls:null,autoActivate:true,defaultControl:null,saveState:false,activeState:null,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,[options]);this.controls=[];this.activeState={};},destroy:function(){OpenLayers.Control.prototype.destroy.apply(this,arguments);for(var i=this.controls.length-1;i>=0;i--){if(this.controls[i].events){this.controls[i].events.un({"activate":this.redraw,"deactivate":this.redraw,scope:this});} +OpenLayers.Event.stopObservingElement(this.controls[i].panel_div);this.controls[i].panel_div=null;} +this.activeState=null;},activate:function(){if(OpenLayers.Control.prototype.activate.apply(this,arguments)){var control;for(var i=0,len=this.controls.length;i<len;i++){control=this.controls[i];if(control===this.defaultControl||(this.saveState&&this.activeState[control.id])){control.activate();}} +if(this.saveState===true){this.defaultControl=null;} +this.redraw();return true;}else{return false;}},deactivate:function(){if(OpenLayers.Control.prototype.deactivate.apply(this,arguments)){var control;for(var i=0,len=this.controls.length;i<len;i++){control=this.controls[i];this.activeState[control.id]=control.deactivate();} +return true;}else{return false;}},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);this.addControlsToMap(this.controls);return this.div;},redraw:function(){if(this.div.children.length>0){for(var l=this.div.children.length,i=l-1;i>=0;i--){this.div.removeChild(this.div.children[i]);}} +this.div.innerHTML="";if(this.active){for(var i=0,len=this.controls.length;i<len;i++){var element=this.controls[i].panel_div;if(this.controls[i].active){element.className=this.controls[i].displayClass+"ItemActive";}else{element.className=this.controls[i].displayClass+"ItemInactive";} +this.div.appendChild(element);}}},activateControl:function(control){if(!this.active){return false;} +if(control.type==OpenLayers.Control.TYPE_BUTTON){control.trigger();this.redraw();return;} +if(control.type==OpenLayers.Control.TYPE_TOGGLE){if(control.active){control.deactivate();}else{control.activate();} +this.redraw();return;} +var c;for(var i=0,len=this.controls.length;i<len;i++){c=this.controls[i];if(c!=control&&(c.type===OpenLayers.Control.TYPE_TOOL||c.type==null)){c.deactivate();}} +control.activate();},addControls:function(controls){if(!(controls instanceof Array)){controls=[controls];} +this.controls=this.controls.concat(controls);for(var i=0,len=controls.length;i<len;i++){var element=document.createElement("div");controls[i].panel_div=element;if(controls[i].title!=""){controls[i].panel_div.title=controls[i].title;} +OpenLayers.Event.observe(controls[i].panel_div,"click",OpenLayers.Function.bind(this.onClick,this,controls[i]));OpenLayers.Event.observe(controls[i].panel_div,"dblclick",OpenLayers.Function.bind(this.onDoubleClick,this,controls[i]));OpenLayers.Event.observe(controls[i].panel_div,"mousedown",OpenLayers.Function.bindAsEventListener(OpenLayers.Event.stop));} +if(this.map){this.addControlsToMap(controls);this.redraw();}},addControlsToMap:function(controls){var control;for(var i=0,len=controls.length;i<len;i++){control=controls[i];if(control.autoActivate===true){control.autoActivate=false;this.map.addControl(control);control.autoActivate=true;}else{this.map.addControl(control);control.deactivate();} +control.events.on({"activate":this.redraw,"deactivate":this.redraw,scope:this});}},onClick:function(ctrl,evt){OpenLayers.Event.stop(evt?evt:window.event);this.activateControl(ctrl);},onDoubleClick:function(ctrl,evt){OpenLayers.Event.stop(evt?evt:window.event);},getControlsBy:function(property,match){var test=(typeof match.test=="function");var found=OpenLayers.Array.filter(this.controls,function(item){return item[property]==match||(test&&match.test(item[property]));});return found;},getControlsByName:function(match){return this.getControlsBy("name",match);},getControlsByClass:function(match){return this.getControlsBy("CLASS_NAME",match);},CLASS_NAME:"OpenLayers.Control.Panel"});OpenLayers.Control.Scale=OpenLayers.Class(OpenLayers.Control,{element:null,geodesic:false,initialize:function(element,options){OpenLayers.Control.prototype.initialize.apply(this,[options]);this.element=OpenLayers.Util.getElement(element);},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!this.element){this.element=document.createElement("div");this.div.appendChild(this.element);} +this.map.events.register('moveend',this,this.updateScale);this.updateScale();return this.div;},updateScale:function(){var scale;if(this.geodesic===true){var units=this.map.getUnits();if(!units){return;} +var inches=OpenLayers.INCHES_PER_UNIT;scale=(this.map.getGeodesicPixelSize().w||0.000001)*inches["km"]*OpenLayers.DOTS_PER_INCH;}else{scale=this.map.getScale();} +if(!scale){return;} +if(scale>=9500&&scale<=950000){scale=Math.round(scale/1000)+"K";}else if(scale>=950000){scale=Math.round(scale/1000000)+"M";}else{scale=Math.round(scale);} +this.element.innerHTML=OpenLayers.i18n("scale",{'scaleDenom':scale});},CLASS_NAME:"OpenLayers.Control.Scale"});OpenLayers.Control.ScaleLine=OpenLayers.Class(OpenLayers.Control,{maxWidth:100,topOutUnits:"km",topInUnits:"m",bottomOutUnits:"mi",bottomInUnits:"ft",eTop:null,eBottom:null,geodesic:false,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,[options]);},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!this.eTop){this.eTop=document.createElement("div");this.eTop.className=this.displayClass+"Top";var theLen=this.topInUnits.length;this.div.appendChild(this.eTop);if((this.topOutUnits=="")||(this.topInUnits=="")){this.eTop.style.visibility="hidden";}else{this.eTop.style.visibility="visible";} +this.eBottom=document.createElement("div");this.eBottom.className=this.displayClass+"Bottom";this.div.appendChild(this.eBottom);if((this.bottomOutUnits=="")||(this.bottomInUnits=="")){this.eBottom.style.visibility="hidden";}else{this.eBottom.style.visibility="visible";}} +this.map.events.register('moveend',this,this.update);this.update();return this.div;},getBarLen:function(maxLen){var digits=parseInt(Math.log(maxLen)/Math.log(10));var pow10=Math.pow(10,digits);var firstChar=parseInt(maxLen/pow10);var barLen;if(firstChar>5){barLen=5;}else if(firstChar>2){barLen=2;}else{barLen=1;} +return barLen*pow10;},update:function(){var res=this.map.getResolution();if(!res){return;} +var curMapUnits=this.map.getUnits();var inches=OpenLayers.INCHES_PER_UNIT;var maxSizeData=this.maxWidth*res*inches[curMapUnits];var geodesicRatio=1;if(this.geodesic===true){var maxSizeGeodesic=(this.map.getGeodesicPixelSize().w||0.000001)*this.maxWidth;var maxSizeKilometers=maxSizeData/inches["km"];geodesicRatio=maxSizeGeodesic/maxSizeKilometers;maxSizeData*=geodesicRatio;} +var topUnits;var bottomUnits;if(maxSizeData>100000){topUnits=this.topOutUnits;bottomUnits=this.bottomOutUnits;}else{topUnits=this.topInUnits;bottomUnits=this.bottomInUnits;} +var topMax=maxSizeData/inches[topUnits];var bottomMax=maxSizeData/inches[bottomUnits];var topRounded=this.getBarLen(topMax);var bottomRounded=this.getBarLen(bottomMax);topMax=topRounded/inches[curMapUnits]*inches[topUnits];bottomMax=bottomRounded/inches[curMapUnits]*inches[bottomUnits];var topPx=topMax/res/geodesicRatio;var bottomPx=bottomMax/res/geodesicRatio;if(this.eBottom.style.visibility=="visible"){this.eBottom.style.width=Math.round(bottomPx)+"px";this.eBottom.innerHTML=bottomRounded+" "+bottomUnits;} +if(this.eTop.style.visibility=="visible"){this.eTop.style.width=Math.round(topPx)+"px";this.eTop.innerHTML=topRounded+" "+topUnits;}},CLASS_NAME:"OpenLayers.Control.ScaleLine"});OpenLayers.Control.ZoomIn=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_BUTTON,trigger:function(){this.map.zoomIn();},CLASS_NAME:"OpenLayers.Control.ZoomIn"});OpenLayers.Control.ZoomOut=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_BUTTON,trigger:function(){this.map.zoomOut();},CLASS_NAME:"OpenLayers.Control.ZoomOut"});OpenLayers.Control.ZoomToMaxExtent=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_BUTTON,trigger:function(){if(this.map){this.map.zoomToMaxExtent();}},CLASS_NAME:"OpenLayers.Control.ZoomToMaxExtent"});OpenLayers.Event={observers:false,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(event){return event.target||event.srcElement;},isLeftClick:function(event){return(((event.which)&&(event.which==1))||((event.button)&&(event.button==1)));},isRightClick:function(event){return(((event.which)&&(event.which==3))||((event.button)&&(event.button==2)));},stop:function(event,allowDefault){if(!allowDefault){if(event.preventDefault){event.preventDefault();}else{event.returnValue=false;}} +if(event.stopPropagation){event.stopPropagation();}else{event.cancelBubble=true;}},findElement:function(event,tagName){var element=OpenLayers.Event.element(event);while(element.parentNode&&(!element.tagName||(element.tagName.toUpperCase()!=tagName.toUpperCase()))){element=element.parentNode;} +return element;},observe:function(elementParam,name,observer,useCapture){var element=OpenLayers.Util.getElement(elementParam);useCapture=useCapture||false;if(name=='keypress'&&(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||element.attachEvent)){name='keydown';} +if(!this.observers){this.observers={};} +if(!element._eventCacheID){var idPrefix="eventCacheID_";if(element.id){idPrefix=element.id+"_"+idPrefix;} +element._eventCacheID=OpenLayers.Util.createUniqueID(idPrefix);} +var cacheID=element._eventCacheID;if(!this.observers[cacheID]){this.observers[cacheID]=[];} +this.observers[cacheID].push({'element':element,'name':name,'observer':observer,'useCapture':useCapture});if(element.addEventListener){element.addEventListener(name,observer,useCapture);}else if(element.attachEvent){element.attachEvent('on'+name,observer);}},stopObservingElement:function(elementParam){var element=OpenLayers.Util.getElement(elementParam);var cacheID=element._eventCacheID;this._removeElementObservers(OpenLayers.Event.observers[cacheID]);},_removeElementObservers:function(elementObservers){if(elementObservers){for(var i=elementObservers.length-1;i>=0;i--){var entry=elementObservers[i];var args=new Array(entry.element,entry.name,entry.observer,entry.useCapture);var removed=OpenLayers.Event.stopObserving.apply(this,args);}}},stopObserving:function(elementParam,name,observer,useCapture){useCapture=useCapture||false;var element=OpenLayers.Util.getElement(elementParam);var cacheID=element._eventCacheID;if(name=='keypress'){if(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||element.detachEvent){name='keydown';}} +var foundEntry=false;var elementObservers=OpenLayers.Event.observers[cacheID];if(elementObservers){var i=0;while(!foundEntry&&i<elementObservers.length){var cacheEntry=elementObservers[i];if((cacheEntry.name==name)&&(cacheEntry.observer==observer)&&(cacheEntry.useCapture==useCapture)){elementObservers.splice(i,1);if(elementObservers.length==0){delete OpenLayers.Event.observers[cacheID];} +foundEntry=true;break;} +i++;}} +if(foundEntry){if(element.removeEventListener){element.removeEventListener(name,observer,useCapture);}else if(element&&element.detachEvent){element.detachEvent('on'+name,observer);}} +return foundEntry;},unloadCache:function(){if(OpenLayers.Event&&OpenLayers.Event.observers){for(var cacheID in OpenLayers.Event.observers){var elementObservers=OpenLayers.Event.observers[cacheID];OpenLayers.Event._removeElementObservers.apply(this,[elementObservers]);} +OpenLayers.Event.observers=false;}},CLASS_NAME:"OpenLayers.Event"};OpenLayers.Event.observe(window,'unload',OpenLayers.Event.unloadCache,false);if(window.Event){OpenLayers.Util.applyDefaults(window.Event,OpenLayers.Event);}else{var Event=OpenLayers.Event;} +OpenLayers.Events=OpenLayers.Class({BROWSER_EVENTS:["mouseover","mouseout","mousedown","mouseup","mousemove","click","dblclick","rightclick","dblrightclick","resize","focus","blur"],listeners:null,object:null,element:null,eventTypes:null,eventHandler:null,fallThrough:null,includeXY:false,clearMouseListener:null,initialize:function(object,element,eventTypes,fallThrough,options){OpenLayers.Util.extend(this,options);this.object=object;this.fallThrough=fallThrough;this.listeners={};this.eventHandler=OpenLayers.Function.bindAsEventListener(this.handleBrowserEvent,this);this.clearMouseListener=OpenLayers.Function.bind(this.clearMouseCache,this);this.eventTypes=[];if(eventTypes!=null){for(var i=0,len=eventTypes.length;i<len;i++){this.addEventType(eventTypes[i]);}} +if(element!=null){this.attachToElement(element);}},destroy:function(){if(this.element){OpenLayers.Event.stopObservingElement(this.element);if(this.element.hasScrollEvent){OpenLayers.Event.stopObserving(window,"scroll",this.clearMouseListener);}} +this.element=null;this.listeners=null;this.object=null;this.eventTypes=null;this.fallThrough=null;this.eventHandler=null;},addEventType:function(eventName){if(!this.listeners[eventName]){this.eventTypes.push(eventName);this.listeners[eventName]=[];}},attachToElement:function(element){if(this.element){OpenLayers.Event.stopObservingElement(this.element);} +this.element=element;for(var i=0,len=this.BROWSER_EVENTS.length;i<len;i++){var eventType=this.BROWSER_EVENTS[i];this.addEventType(eventType);OpenLayers.Event.observe(element,eventType,this.eventHandler);} +OpenLayers.Event.observe(element,"dragstart",OpenLayers.Event.stop);},on:function(object){for(var type in object){if(type!="scope"){this.register(type,object.scope,object[type]);}}},register:function(type,obj,func){if((func!=null)&&(OpenLayers.Util.indexOf(this.eventTypes,type)!=-1)){if(obj==null){obj=this.object;} +var listeners=this.listeners[type];listeners.push({obj:obj,func:func});}},registerPriority:function(type,obj,func){if(func!=null){if(obj==null){obj=this.object;} +var listeners=this.listeners[type];if(listeners!=null){listeners.unshift({obj:obj,func:func});}}},un:function(object){for(var type in object){if(type!="scope"){this.unregister(type,object.scope,object[type]);}}},unregister:function(type,obj,func){if(obj==null){obj=this.object;} +var listeners=this.listeners[type];if(listeners!=null){for(var i=0,len=listeners.length;i<len;i++){if(listeners[i].obj==obj&&listeners[i].func==func){listeners.splice(i,1);break;}}}},remove:function(type){if(this.listeners[type]!=null){this.listeners[type]=[];}},triggerEvent:function(type,evt){var listeners=this.listeners[type];if(!listeners||listeners.length==0){return;} +if(evt==null){evt={};} +evt.object=this.object;evt.element=this.element;if(!evt.type){evt.type=type;} +var listeners=listeners.slice(),continueChain;for(var i=0,len=listeners.length;i<len;i++){var callback=listeners[i];continueChain=callback.func.apply(callback.obj,[evt]);if((continueChain!=undefined)&&(continueChain==false)){break;}} +if(!this.fallThrough){OpenLayers.Event.stop(evt,true);} +return continueChain;},handleBrowserEvent:function(evt){if(this.includeXY){evt.xy=this.getMousePosition(evt);} +this.triggerEvent(evt.type,evt);},clearMouseCache:function(){this.element.scrolls=null;this.element.lefttop=null;this.element.offsets=null;},getMousePosition:function(evt){if(!this.includeXY){this.clearMouseCache();}else if(!this.element.hasScrollEvent){OpenLayers.Event.observe(window,"scroll",this.clearMouseListener);this.element.hasScrollEvent=true;} +if(!this.element.scrolls){this.element.scrolls=[(document.documentElement.scrollLeft||document.body.scrollLeft),(document.documentElement.scrollTop||document.body.scrollTop)];} +if(!this.element.lefttop){this.element.lefttop=[(document.documentElement.clientLeft||0),(document.documentElement.clientTop||0)];} +if(!this.element.offsets){this.element.offsets=OpenLayers.Util.pagePosition(this.element);this.element.offsets[0]+=this.element.scrolls[0];this.element.offsets[1]+=this.element.scrolls[1];} +return new OpenLayers.Pixel((evt.clientX+this.element.scrolls[0])-this.element.offsets[0] +-this.element.lefttop[0],(evt.clientY+this.element.scrolls[1])-this.element.offsets[1] +-this.element.lefttop[1]);},CLASS_NAME:"OpenLayers.Events"});OpenLayers.Format=OpenLayers.Class({options:null,externalProjection:null,internalProjection:null,data:null,keepData:false,initialize:function(options){OpenLayers.Util.extend(this,options);this.options=options;},destroy:function(){},read:function(data){OpenLayers.Console.userError(OpenLayers.i18n("readNotImplemented"));},write:function(object){OpenLayers.Console.userError(OpenLayers.i18n("writeNotImplemented"));},CLASS_NAME:"OpenLayers.Format"});OpenLayers.Lang["ar"]=OpenLayers.Util.applyDefaults({'permalink':"وصلة دائمة",'baseLayer':"الطبقة الاساسية",'readNotImplemented':"القراءة غير Ù…ØÙ‚قة.",'writeNotImplemented':"الكتابة غير Ù…ØÙ‚قة",'errorLoadingGML':"خطأ عند تØÙ…يل المل٠جي ام ال ${url}",'scale':"النسبة = 1 : ${scaleDenom}",'W':"غ",'E':"شر",'N':"شم",'S':"ج"});OpenLayers.Lang["be-tarask"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Ðеапрацаваны вынік запыту ${statusText}",'permalink':"Ð¡Ñ‚Ð°Ð»Ð°Ñ ÑпаÑылка",'overlays':"Слаі",'baseLayer':"Базавы Ñлой",'sameProjection':"ÐглÑÐ´Ð½Ð°Ñ Ð¼Ð°Ð¿Ð° працуе толькі калі Ñна мае тую ж праекцыю, што Ñ– аÑÐ½Ð¾ÑžÐ½Ð°Ñ Ð¼Ð°Ð¿Ð°",'readNotImplemented':"ФункцыÑнальнаÑьць Ñ‡Ñ‹Ñ‚Ð°Ð½ÑŒÐ½Ñ Ð½Ñ ÑтворанаÑ.",'writeNotImplemented':"ФункцыÑнальнаÑьць запіÑу Ð½Ñ ÑтворанаÑ.",'noFID':"Ðемагчыма абнавіць магчымаÑьць, Ð´Ð»Ñ Ñкога не Ñ–Ñнуе FID.",'errorLoadingGML':"Памылка загрузкі файла GML ${url}",'browserNotSupported':"Ваш браўзÑÑ€ не падтрымлівае вÑктарную графіку. У цÑперашні момант падтрымліваюцца: ${renderers}",'componentShouldBe':"addFeatures : кампанÑнт павінен быць ${geomType}",'getFeatureError':"getFeatureFromEvent выкліканы Ð´Ð»Ñ ÑÐ»Ð¾Ñ Ð±Ñз Ñ€ÑндÑру. Звычайна гÑта азначае, што Ð’Ñ‹ зьнішчылі Ñлой, але пакінулі зьвÑзаны зь ім апрацоўшчык.",'minZoomLevelError':"УлаÑьціваÑьць minZoomLevel прызначана толькі Ð´Ð»Ñ Ð²Ñ‹ÐºÐ°Ñ€Ñ‹ÑÑ‚Ð°Ð½ÑŒÐ½Ñ Ñа ÑлаÑмі вытворнымі ад FixedZoomLevels. Тое, што гÑты wfs-Ñлой правÑраецца на minZoomLevel — Ñ€Ñха прошлага. Ðле мы Ð½Ñ Ð¼Ð¾Ð¶Ð°Ð¼ выдаліць гÑтую магчымаÑьць, таму што ад Ñе залежаць Ð½ÐµÐºÐ°Ñ‚Ð¾Ñ€Ñ‹Ñ Ð·Ð°ÑÐ½Ð°Ð²Ð°Ð½Ñ‹Ñ Ð½Ð° OL даÑтаÑаваньні. Тым Ð½Ñ Ð¼ÐµÐ½Ñˆ, праверка minZoomLevel будзе Ð²Ñ‹Ð´Ð°Ð»ÐµÐ½Ð°Ñ Ñž вÑÑ€ÑÑ–Ñ– 3.0. Калі лаÑка, выкарыÑтоўваеце замеÑÑ‚ Ñе ÑžÑтаноўкі мінімальнага/макÑымальнага памераў, Ñк апіÑана тут: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS-транзакцыÑ: ПОСЬПЕХ ${response}",'commitFailed':"WFS-транзакцыÑ: ПÐМЫЛКР${response}",'googleWarning':"Ðе атрымалаÑÑ Ð·Ð°Ð³Ñ€ÑƒÐ·Ñ–Ñ†ÑŒ Ñлой Google. \x3cbr\x3e\x3cbr\x3eКаб пазбавіцца гÑтага паведамленьнÑ, выберыце новы базавы Ñлой у ÑьпіÑе Ñž верхнім правым куце.\x3cbr\x3e\x3cbr\x3e ХутчÑй за ÑžÑÑ‘, прычына Ñž тым, што Ñкрыпт бібліÑÑ‚Ñкі Google Maps Ð½Ñ Ð±Ñ‹Ñž ÑƒÐºÐ»ÑŽÑ‡Ð°Ð½Ñ‹Ñ Ð°Ð»ÑŒÐ±Ð¾ не ўтрымлівае Ñлушны API-ключ Ð´Ð»Ñ Ð’Ð°ÑˆÐ°Ð³Ð° Ñайта.\x3cbr\x3e\x3cbr\x3eРаÑпрацоўшчыкам: Ð”Ð»Ñ Ñ‚Ð°Ð³Ð¾, каб даведацца Ñк зрабіць так, каб уÑÑ‘ працавала, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eнаціÑьніце тут\x3c/a\x3e",'getLayerWarning':"Ðемагчыма загрузіць Ñлой ${layerType}.\x3cbr\x3e\x3cbr\x3eКаб пазбавіцца гÑтага паведамленьнÑ, выберыце новы базавы Ñлой у ÑьпіÑе Ñž верхнім правым куце.\x3cbr\x3e\x3cbr\x3eХутчÑй за ÑžÑÑ‘, прычына Ñž тым, што Ñкрыпт бібліÑÑ‚Ñкі ${layerLib} Ð½Ñ Ð±Ñ‹Ñž Ñлушна ўключаны.\x3cbr\x3e\x3cbr\x3eРаÑпрацоўшчыкам: Ð”Ð»Ñ Ñ‚Ð°Ð³Ð¾, каб даведацца Ñк зрабіць так, каб уÑÑ‘ працавала, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eнаціÑьніце тут\x3c/a\x3e",'scale':"Маштаб = 1 : ${scaleDenom}",'W':"З",'E':"У",'N':"Пн",'S':"Пд",'layerAlreadyAdded':"Ð’Ñ‹ паÑпрабавалі дадаць Ñлой ${layerName} на мапу, але ён ужо дададзены",'reprojectDeprecated':"Ð’Ñ‹ выкарыÑтоўваеце ÑžÑтаноўку \'reproject\' Ð´Ð»Ñ ÑÐ»Ð¾Ñ ${layerName}. ГÑÑ‚Ð°Ñ ÑžÑтаноўка зьÑўлÑецца ÑаÑтарÑлай: Ñна выкарыÑтоўвалаÑÑ Ð´Ð»Ñ Ð¿Ð°Ð´Ñ‚Ñ€Ñ‹Ð¼ÐºÑ– паказу зьвеÑтак на камÑрцыйных базавых мапах, але гÑта Ñ„ÑƒÐ½ÐºÑ†Ñ‹Ñ Ñ†Ñпер Ñ€ÑÐ°Ð»Ñ–Ð·Ð°Ð²Ð°Ð½Ð°Ñ Ñž убудаванай падтрымцы ÑÑ„Ñрычнай праекцыі МÑркатара. Ð”Ð°Ð´Ð°Ñ‚ÐºÐ¾Ð²Ð°Ñ Ñ–Ð½Ñ„Ð°Ñ€Ð¼Ð°Ñ†Ñ‹Ñ Ñ‘Ñьць на http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"ГÑты мÑтад ÑаÑтарÑлы Ñ– будзе выдалены Ñž вÑÑ€ÑÑ–Ñ– 3.0. Калі лаÑка, замеÑÑ‚ Ñго выкарыÑтоўвайце ${newMethod}.",'boundsAddError':"Вам неабходна падаць абодва значÑньні x Ñ– y Ð´Ð»Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ‹Ñ– ÑкладаньнÑ.",'lonlatAddError':"Вам неабходна падаць абодва значÑньні lon Ñ– lat Ð´Ð»Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ‹Ñ– ÑкладаньнÑ.",'pixelAddError':"Вам неабходна падаць абодва значÑньні x Ñ– y Ð´Ð»Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ‹Ñ– ÑкладаньнÑ.",'unsupportedGeometryType':"Тып геамÑтрыі не падтрымліваецца: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition failed: верагодна ÑлемÑнт з ідÑнтыфікатарам ${elemId} займае нÑÑлушнае меÑца.",'filterEvaluateNotImplemented':"evaluate не Ñ€Ñалізаваны Ð´Ð»Ñ Ð³Ñтага тыпу фільтру."});OpenLayers.Lang["bg"]=OpenLayers.Util.applyDefaults({'permalink':"ПоÑтоÑнна препратка",'baseLayer':"ОÑновен Ñлой",'errorLoadingGML':"Грешка при зареждане на GML файл ${url}",'scale':"Мащаб = 1 : ${scaleDenom}",'layerAlreadyAdded':"Опитахте да добавите Ñлой ${layerName} в картата, но той вече е добавен",'methodDeprecated':"Този метод е оÑтарÑл и ще бъде премахват в 3.0. ВмеÑто него използвайте ${newMethod}."});OpenLayers.Lang["br"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Distro evel reked anveret ${statusText}",'permalink':"Peurliamm",'overlays':"Gwiskadoù",'baseLayer':"Gwiskad diazez",'sameProjection':"Ne\'z ar gartenn lec\'hiañ en-dro nemet pa vez heñvel ar banndres anezhi ha hini ar gartenn bennañ",'readNotImplemented':"N\'eo ket emplementet al lenn.",'writeNotImplemented':"N\'eo ket emplementet ar skrivañ.",'noFID':"N\'haller ket hizivaat un elfenn ma n\'eus ket a niverenn-anaout (FID) eviti.",'errorLoadingGML':"Fazi e-ser kargañ ar restr GML ${url}",'browserNotSupported':"N\'eo ket skoret an daskor vektorel gant ho merdeer. Setu aze an daskorerioù skoret evit ar poent :\n${renderers}",'componentShouldBe':"addFeatures : bez\' e tlefe ar parzh besañ eus ar seurt ${geomType}",'getFeatureError':"Galvet eo bet getFeatureFromEvent called war ur gwiskad hep daskorer. Kement-se a dalvez ez eus bet freuzet ur gwiskad hag hoc\'h eus miret un embreger bennak stag outañ.",'minZoomLevelError':"Ne zleer implijout ar perzh minZoomLevel nemet evit gwiskadoù FixedZoomLevels-descendent. Ar fed ma wiria ar gwiskad WHS-se hag-eñ ez eus eus minZoomLevel zo un aspadenn gozh. Koulskoude n\'omp ket evit e ziverkañ kuit da derriñ arloadoù diazezet war OL a c\'hallfe bezañ stag outañ. Setu perak eo dispredet -- Lamet kuit e vo ar gwiriañ minZoomLevel a-is er stumm 3.0. Ober gant an arventennoù bihanañ/brasañ evel deskrivet amañ e plas : http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Treuzgread WFS : MAT EO ${response}",'commitFailed':"Treuzgread WFS Transaction: C\'HWITET ${response}",'googleWarning':"N\'eus ket bet gallet kargañ ar gwiskad Google ent reizh.\x3cbr\x3e\x3cbr\x3eEvit en em zizober eus ar c\'hemenn-mañ, dibabit ur BaseLayer nevez en diuzer gwiskadoù er c\'horn dehoù el laez.\x3cbr\x3e\x3cbr\x3eSur a-walc\'h eo peogwir n\'eo ket bet ensoc\'het levraoueg Google Maps pe neuze ne glot ket an alc\'hwez API gant ho lec\'hienn.\x3cbr\x3e\x3cbr\x3eDiorroerien : Evit reizhañ an dra-se, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclick here\x3c/a\x3e",'getLayerWarning':"N\'haller ket kargañ ar gwiskad ${layerType} ent reizh.\x3cbr\x3e\x3cbr\x3eEvit en em zizober eus ar c\'hemenn-mañ, dibabit ur BaseLayer nevez en diuzer gwiskadoù er c\'horn dehoù el laez.\x3cbr\x3e\x3cbr\x3eSur a-walc\'h eo peogwir n\'eo ket bet ensoc\'het mat al levraoueg ${layerLib}.\x3cbr\x3e\x3cbr\x3eDiorroerien : Evit gouzout penaos reizhañ an dra-se, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclick here\x3c/a\x3e",'scale':"Skeul = 1 : ${scaleDenom}",'W':"K",'E':"R",'N':"N",'S':"S",'layerAlreadyAdded':"Klasket hoc\'h eus ouzhpennañ ar gwiskad : ${layerName} d\'ar gartenn, met ouzhpennet e oa bet c\'hoazh",'reprojectDeprecated':"Emaoc\'h oc\'h implijout an dibarzh \'reproject\' war ar gwiskad ${layerName}. Dispredet eo an dibarzh-mañ : bet eo hag e talveze da ziskwel roadennoù war-c\'horre kartennoù diazez kenwerzhel, un dra hag a c\'haller ober bremañ gant an arc\'hwel dre skor banndres boullek Mercator. Muioc\'h a ditouroù a c\'haller da gaout war http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Dispredet eo an daore-se ha tennet e vo kuit eus ar stumm 3.0. Grit gant ${newMethod} e plas.",'boundsAddError':"Rekis eo tremen an div dalvoudenn x ha y d\'an arc\'hwel add.",'lonlatAddError':"Rekis eo tremen an div dalvoudenn hedred ha ledred d\'an arc\'hwel add.",'pixelAddError':"Rekis eo tremen an div dalvoudenn x ha y d\'an arc\'hwel add.",'unsupportedGeometryType':"Seurt mentoniezh anskoret : ${geomType}",'pagePositionFailed':"C\'hwitet eo OpenLayers.Util.pagePosition : marteze emañ lec\'hiet fall an elfenn id ${elemId}.",'filterEvaluateNotImplemented':"N\'eo ket bet emplementet ar priziañ evit seurt siloù c\'hoazh."});OpenLayers.Lang["el"]=OpenLayers.Util.applyDefaults({'scale':"Κλίμακα ~ 1 : ${scaleDenom}"});OpenLayers.Lang.en={'unhandledRequest':"Unhandled request return ${statusText}",'permalink':"Permalink",'overlays':"Overlays",'baseLayer':"Base Layer",'sameProjection':"The overview map only works when it is in the same projection as the main map",'readNotImplemented':"Read not implemented.",'writeNotImplemented':"Write not implemented.",'noFID':"Can't update a feature for which there is no FID.",'errorLoadingGML':"Error in loading GML file ${url}",'browserNotSupported':"Your browser does not support vector rendering. Currently supported renderers are:\n${renderers}",'componentShouldBe':"addFeatures : component should be an ${geomType}",'getFeatureError':"getFeatureFromEvent called on layer with no renderer. This usually means you "+"destroyed a layer, but not some handler which is associated with it.",'minZoomLevelError':"The minZoomLevel property is only intended for use "+"with the FixedZoomLevels-descendent layers. That this "+"wfs layer checks for minZoomLevel is a relic of the"+"past. We cannot, however, remove it without possibly "+"breaking OL based applications that may depend on it."+" Therefore we are deprecating it -- the minZoomLevel "+"check below will be removed at 3.0. Please instead "+"use min/max resolution setting as described here: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS Transaction: SUCCESS ${response}",'commitFailed':"WFS Transaction: FAILED ${response}",'googleWarning':"The Google Layer was unable to load correctly.<br><br>"+"To get rid of this message, select a new BaseLayer "+"in the layer switcher in the upper-right corner.<br><br>"+"Most likely, this is because the Google Maps library "+"script was either not included, or does not contain the "+"correct API key for your site.<br><br>"+"Developers: For help getting this working correctly, "+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>click here</a>",'getLayerWarning':"The ${layerType} Layer was unable to load correctly.<br><br>"+"To get rid of this message, select a new BaseLayer "+"in the layer switcher in the upper-right corner.<br><br>"+"Most likely, this is because the ${layerLib} library "+"script was not correctly included.<br><br>"+"Developers: For help getting this working correctly, "+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>click here</a>",'scale':"Scale = 1 : ${scaleDenom}",'W':'W','E':'E','N':'N','S':'S','graticule':'Graticule','layerAlreadyAdded':"You tried to add the layer: ${layerName} to the map, but it has already been added",'reprojectDeprecated':"You are using the 'reproject' option "+"on the ${layerName} layer. This option is deprecated: "+"its use was designed to support displaying data over commercial "+"basemaps, but that functionality should now be achieved by using "+"Spherical Mercator support. More information is available from "+"http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"This method has been deprecated and will be removed in 3.0. "+"Please use ${newMethod} instead.",'boundsAddError':"You must pass both x and y values to the add function.",'lonlatAddError':"You must pass both lon and lat values to the add function.",'pixelAddError':"You must pass both x and y values to the add function.",'unsupportedGeometryType':"Unsupported geometry type: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition failed: element with id ${elemId} may be misplaced.",'filterEvaluateNotImplemented':"evaluate is not implemented for this filter type.",'end':''};OpenLayers.Lang["fi"]=OpenLayers.Util.applyDefaults({'permalink':"Ikilinkki",'overlays':"Kerrokset",'baseLayer':"Peruskerros",'sameProjection':"Yleiskuvakarttaa voi käyttää vain, kun sillä on sama projektio kuin pääkartalla.",'W':"L",'E':"I",'N':"P",'S':"E"});OpenLayers.Lang["fur"]=OpenLayers.Util.applyDefaults({'permalink':"Leam Permanent",'overlays':"Livei parsore",'baseLayer':"Livel di base",'browserNotSupported':"Il to sgarfadôr nol supuarte la renderizazion vetoriâl. Al moment a son supuartâts:\n${renderers}",'scale':"Scjale = 1 : ${scaleDenom}",'W':"O",'E':"E",'N':"N",'S':"S"});OpenLayers.Lang["gl"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Solicitude non xerada; a resposta foi: ${statusText}",'permalink':"Ligazón permanente",'overlays':"Capas superpostas",'baseLayer':"Capa base",'sameProjection':"A vista xeral do mapa só funciona cando está na mesma proxección có mapa principal",'readNotImplemented':"Lectura non implementada.",'writeNotImplemented':"Escritura non implementada.",'noFID':"Non se pode actualizar a funcionalidade para a que non hai FID.",'errorLoadingGML':"Erro ao cargar o ficheiro GML ${url}",'browserNotSupported':"O seu navegador non soporta a renderización de vectores. Os renderizadores soportados actualmente son:\n${renderers}",'componentShouldBe':"addFeatures: o compoñente debera ser de tipo ${geomType}",'getFeatureError':"getFeatureFromEvent ten sido chamado a unha capa sen renderizador. Isto normalmente significa que destruÃu unha capa, mais non o executador que está asociado con ela.",'minZoomLevelError':"A propiedade minZoomLevel é só para uso conxuntamente coas capas FixedZoomLevels-descendent. O feito de que esa capa wfs verifique o minZoomLevel é unha reliquia do pasado. Non podemos, con todo, eliminala sen a posibilidade de non romper as aplicacións baseadas en OL que poidan depender dela. Por iso a estamos deixando obsoleta (a comprobación minZoomLevel de embaixo será eliminada na versión 3.0). Por favor, no canto diso use o axuste de resolución mÃn/máx tal e como está descrito aquÃ: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transacción WFS: ÉXITO ${response}",'commitFailed':"Transacción WFS: FALLIDA ${response}",'googleWarning':"A capa do Google non puido cargarse correctamente.\x3cbr\x3e\x3cbr\x3ePara evitar esta mensaxe, escolla unha nova capa base no seleccionador de capas na marxe superior dereita.\x3cbr\x3e\x3cbr\x3eProbablemente, isto acontece porque a escritura da librarÃa do Google Maps ou ben non foi incluÃda ou ben non contén a clave API correcta para o seu sitio.\x3cbr\x3e\x3cbr\x3eDesenvolvedores: para axudar a facer funcionar isto correctamente, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3epremede aquÃ\x3c/a\x3e",'getLayerWarning':"A capa ${layerType} foi incapaz de cargarse correctamente.\x3cbr\x3e\x3cbr\x3ePara evitar esta mensaxe, escolla unha nova capa base no seleccionador de capas na marxe superior dereita.\x3cbr\x3e\x3cbr\x3eProbablemente, isto acontece porque a escritura da librarÃa ${layerLib} non foi ben incluÃda.\x3cbr\x3e\x3cbr\x3eDesenvolvedores: para axudar a facer funcionar isto correctamente, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3epremede aquÃ\x3c/a\x3e",'scale':"Escala = 1 : ${scaleDenom}",'W':"O",'E':"L",'N':"N",'S':"S",'layerAlreadyAdded':"Intentou engadir a capa: ${layerName} ao mapa, pero xa fora engadida",'reprojectDeprecated':"Está usando a opción \"reproject\" na capa ${layerName}. Esta opción está obsoleta: o seu uso foi deseñado para a visualización de datos sobre mapas base comerciais, pero esta funcionalidade debera agora ser obtida utilizando a proxección Spherical Mercator. Hai dispoñible máis información en http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Este método está obsoleto e será eliminado na versión 3.0. Por favor, no canto deste use ${newMethod}.",'boundsAddError':"Debe achegar os valores x e y á función add.",'lonlatAddError':"Debe achegar tanto o valor lon coma o lat á función add.",'pixelAddError':"Debe achegar os valores x e y á función add.",'unsupportedGeometryType':"Tipo xeométrico non soportado: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition fallou: o elemento con id ${elemId} pode non estar na súa posición.",'filterEvaluateNotImplemented':"avaliar non está implementado para este tipo de filtro."});OpenLayers.Lang["gsw"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nit behandleti Aafrogsruckmäldig ${statusText}",'permalink':"Permalink",'overlays':"Iberlagerige",'baseLayer':"Grundcharte",'sameProjection':"D Ibersichts-Charte funktioniert nume, wänn si di glych Projäktion brucht wie d Hauptcharte",'readNotImplemented':"Läse nit implementiert.",'writeNotImplemented':"Schrybe nit implementiert.",'noFID':"E Feature, wu s kei FID derfir git, cha nit aktualisiert wäre.",'errorLoadingGML':"Fähler bim Lade vu dr GML-Datei ${url}",'browserNotSupported':"Dyy Browser unterstitzt kei Vektordarstellig. Aktuäll unterstitzti Renderer:\n${renderers}",'componentShouldBe':"addFeatures : Komponänt sott dr Typ ${geomType} syy",'getFeatureError':"getFeatureFromEvent isch uf eme Layer ohni Renderer ufgruefe wore. Des heisst normalerwys, ass Du e Layer kaputt gmacht hesch, aber nit dr Handler, wu derzue ghert.",'minZoomLevelError':"D minZoomLevel-Eigeschaft isch nume dänk fir d Layer, wu vu dr FixedZoomLevels abstamme. Ass dää wfs-Layer minZoomLevel prieft, scih e Relikt us dr Vergangeheit. Mir chenne s aber nit ändere ohni OL_basierti Aawändige villicht kaputt gehn, wu dervu abhänge. Us däm Grund het die Funktion d Eigeschaft \'deprecated\' iberchuu. D minZoomLevel-Priefig unte wird in dr Version 3.0 usegnuu. Bitte verwänd statt däm e min/max-Uflesig wie s do bschriben isch: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS-Transaktion: ERFOLGRYCH ${response}",'commitFailed':"WFS-Transaktion: FÄHLGSCHLAA ${response}",'googleWarning':"Dr Google-Layer het nit korräkt chenne glade wäre.\x3cbr\x3e\x3cbr\x3eGo die Mäldig nimi z kriege, wehl e andere Hintergrundlayer us em LayerSwitcher im rächte obere Ecke.\x3cbr\x3e\x3cbr\x3eDää Fähler git s seli hyfig, wel s Skript vu dr Google-Maps-Bibliothek nit yybunde woren isch oder wel s kei giltige API-Schlissel fir Dyy URL din het.\x3cbr\x3e\x3cbr\x3eEntwickler: Fir Hilf zum korräkte Yybinde vum Google-Layer \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3edoo drucke\x3c/a\x3e",'getLayerWarning':"Dr ${layerType}-Layer het nit korräkt chenne glade wäre.\x3cbr\x3e\x3cbr\x3eGo die Mäldig nimi z kriege, wehl e andere Hintergrundlayer us em LayerSwitcher im rächte obere Ecke.\x3cbr\x3e\x3cbr\x3eDää Fähler git s seli hyfig, wel s Skript vu dr \'${layerLib}\'-Bibliothek nit yybunde woren isch oder wel s kei giltige API-Schlissel fir Dyy URL din het.\x3cbr\x3e\x3cbr\x3eEntwickler: Fir Hilf zum korräkte Yybinde vu Layer \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3edoo drucke\x3c/a\x3e",'scale':"Maßstab = 1 : ${scaleDenom}",'W':"W",'E':"O",'N':"N",'S':"S",'layerAlreadyAdded':"Du hesch versuecht dää Layer in d Charte yyzfiege: ${layerName}, aber är isch schoi yygfiegt",'reprojectDeprecated':"Du bruchsch d \'reproject\'-Option bim ${layerName}-Layer. Die Option isch nimi giltig: si isch aagleit wore go Date iber kommerziälli Grundcharte lege, aber des sott mer jetz mache mit dr Unterstitzig vu Spherical Mercator. Meh Informatione git s uf http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Die Methode isch veraltet un wird us dr Version 3.0 usegnuu. Bitte verwäbnd statt däm ${newMethod}.",'boundsAddError':"Du muesch e x-Wärt un e y-Wärt yygee bi dr Zuefieg-Funktion",'lonlatAddError':"Du meusch e Lengi- un e Breiti-Grad yygee bi dr Zuefieg-Funktion.",'pixelAddError':"Du muesch x- un y-Wärt aagee bi dr Zuefieg-Funktion.",'unsupportedGeometryType':"Nit unterstitze Geometrii-Typ: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition fählgschlaa: Elemänt mit ID ${elemId} isch villicht falsch gsetzt.",'filterEvaluateNotImplemented':"evaluiere isch nit implemäntiert in däm Filtertyp."});OpenLayers.Lang["hr"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nepodržani zahtjev ${statusText}",'permalink':"Permalink",'overlays':"Overlays",'baseLayer':"Osnovna karta",'sameProjection':"Pregledna karta radi jedino kao je u istoj projekciji kao i glava karta",'readNotImplemented':"ÄŒitanje nije implementirano.",'writeNotImplemented':"Pisanje nije implementirano.",'noFID':"Ne mogu ažurirati znaÄajku za koju ne postoji FID.",'errorLoadingGML':"GreÅ¡ka u uÄitavanju GML datoteke ${url}",'browserNotSupported':"VaÅ¡ preglednik ne podržava vektorsko renderiranje. Trenutno podržani rendereri su: ${renderers}",'componentShouldBe':"addFeatures : komponenta bi trebala biti ${geomType}",'getFeatureError':"getFeatureFromEvent je pozvao Layer bez renderera. Ovo obiÄno znaÄi da ste uniÅ¡tiili Layer, a ne neki Handler koji je povezan s njim.",'commitSuccess':"WFS Transakcija: USPJEÅ NA ${response}",'commitFailed':"WFS Transakcija: NEUSPJEÅ NA ${response}",'scale':"Mjerilo = 1 : ${scaleDenom}",'layerAlreadyAdded':"PokuÅ¡ali ste dodati layer: ${layerName} na kartu, ali je već dodan",'methodDeprecated':"Ova metoda nije odobrena i biti će maknuta u 3.0. Koristite ${newMethod}.",'boundsAddError':"Morate dati obje vrijednosti , x i y da bi dodali funkciju.",'lonlatAddError':"Morate dati obje vrijednosti , (lon i lat) da bi dodali funkciju.",'pixelAddError':"Morate dati obje vrijednosti , x i y da bi dodali funkciju.",'unsupportedGeometryType':"Nepodržani tip geometrije: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition nije uspjelo: element sa id ${elemId} može biti krivo smjeÅ¡ten."});OpenLayers.Lang["hsb"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"WotmoÅ‚wa njewobdźěłaneho napraÅ¡owanja ${statusText}",'permalink':"Trajny wotkaz",'overlays':"NaworÅ¡towanja",'baseLayer':"ZakÅ‚adna runina",'sameProjection':"PÅ™ehladowa karta jenož funguje, hdyž je w samsnej projekciji kaž hÅ‚owna karta",'readNotImplemented':"ÄŒitanje njeimplementowane.",'writeNotImplemented':"Pisanje njeimplementowane.",'noFID':"Funkcija, za kotruž FID njeje, njeda so aktualizować.",'errorLoadingGML':"Zmylk pÅ™i zaÄitowanju dataje ${url}",'browserNotSupported':"Twój wobhladowak wektorowe rysowanje njepodpÄ›ruje. Tuchwilu podpÄ›rowane rysowaki su:\n${renderers}",'componentShouldBe':"addFeatures: komponenta měła ${geomType} być",'getFeatureError':"getFeatureFromEvent bu na woršće bjez rysowak zawoÅ‚any. To zwjetÅ¡a woznamjenja, zo sy worÅ¡tu zniÄiÅ‚, ale nic wobdźěłak, kotryž je z njej zwjazany.",'minZoomLevelError':"Kajkosć minZoomLevel je jenož za wužiwanje z worÅ¡tami myslena, kotrež wot FixedZoomLevels pochadźeja. Zo tuta worÅ¡ta wfs za minZoomLevel pÅ™epruwuje, je relikt zaÅ„dźenosće. Njemóžemy wÅ¡ak ju wotstronić, bjeztoho zo aplikacije, kotrež na OpenLayers bazÄ›ruja a snano tutu kajkosć wužiwaja, hižo njefunguja. Tohodla smy ju jako zestarjenu woznamjenili -- pÅ™epruwowanje za minZoomLevel budu so we wersiji 3.0 wotstronjeć. ProÅ¡u wužij mÄ›sto toho nastajenje min/max, kaž je tu wopisane: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS-Transakcija: WUSPĚŠNA ${response}",'commitFailed':"WFS-Transakcija: NJEPORADŹENA ${response}",'googleWarning':"WorÅ¡ta Google njemóžeÅ¡e so korektnje zaÄitać.\x3cbr\x3e\x3cbr\x3eZo by tutu zdźělenku wotbyÅ‚, wubjer nowy BaseLayer z wubÄ›ra worÅ¡tow horjeka naprawo.\x3cbr\x3e\x3cbr\x3eNajskerje so to stawa, dokelž skript biblioteki Google Maps pak njebu zapÅ™ijaty pak njewobsahuje korektny kluÄ API za twoje sydÅ‚o.\x3cbr\x3e\x3cbr\x3eWuwiwarjo: Za pomoc ke korektnemu fungowanju worÅ¡tow\n\x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3etu kliknyć\x3c/a\x3e",'getLayerWarning':"WorÅ¡ta ${layerType} njemóžeÅ¡e so korektnje zaÄitać.\x3cbr\x3e\x3cbr\x3eZo by tutu zdźělenku wotbyÅ‚, wubjer nowy BaseLayer z wubÄ›ra worÅ¡tow horjeka naprawo.\x3cbr\x3e\x3cbr\x3eNajskerje so to stawa, dokelž skript biblioteki ${layerLib} njebu korektnje zapÅ™ijaty.\x3cbr\x3e\x3cbr\x3eWuwiwarjo: Za pomoc ke korektnemu fungowanju worÅ¡tow\n\x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3etu kliknyć\x3c/a\x3e",'scale':"MÄ›ritko = 1 : ${scaleDenom}",'W':"Z",'E':"W",'N':"S",'S':"J",'layerAlreadyAdded':"Sy spytaÅ‚ runinu ${layerName} karće dodać, ale je so hižo dodaÅ‚a",'reprojectDeprecated':"WužiwaÅ¡ opciju \"reproject\" wořšty ${layerName}. Tuta opcija je zestarjena: jeje wužiwanje bÄ› myslene, zo by zwobraznjenje datow nad komercielnymi bazowymi kartami podpÄ›raÅ‚o, ale funkcionalnosć měła so nÄ›tko z pomocu Sperical Mercator docpěć. DalÅ¡e informacije steja na http://trac.openlayers.org/wiki/SphericalMercator k dispoziciji.",'methodDeprecated':"Tuta metoda je so njeschwaliÅ‚a a budźe so w 3.0 wotstronjeć. ProÅ¡u wužij ${newMethod} mÄ›sto toho.",'boundsAddError':"DyrbiÅ¡ hódnotu x kaž tež y funkciji \"add\" pÅ™epodać.",'lonlatAddError':"DyrbiÅ¡ hódnotu lon kaž tež lat funkciji \"add\" pÅ™epodać.",'pixelAddError':"DyrbiÅ¡ hódnotu x kaž tež y funkciji \"add\" pÅ™epodać.",'unsupportedGeometryType':"NjepodpÄ›rowany geometrijowy typ: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition je so njeporadźiÅ‚: element z id ${elemId} bu snano wopak zamÄ›stnjeny.",'filterEvaluateNotImplemented':"wuhódnoćenje njeje za tutón filtrowy typ implementowany."});OpenLayers.Lang["hu"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nem kezelt kérés visszatérése ${statusText}",'permalink':"Permalink",'overlays':"RávetÃtések",'baseLayer':"Alapréteg",'sameProjection':"Az áttekintÅ‘ térkép csak abban az esetben működik, ha ugyanazon a vetületen van, mint a fÅ‘ térkép.",'readNotImplemented':"Olvasás nincs végrehajtva.",'writeNotImplemented':"Ãrás nincs végrehajtva.",'noFID':"Nem frissÃthetÅ‘ olyan jellemzÅ‘, amely nem rendelkezik FID-del.",'errorLoadingGML':"Hiba GML-fájl betöltésekor ${url}",'browserNotSupported':"A böngészÅ‘je nem támogatja a vektoros renderelést. A jelenleg támogatott renderelÅ‘k:\n${renderers}",'componentShouldBe':"addFeatures : az összetevÅ‘nek ilyen tÃpusúnak kell lennie: ${geomType}",'getFeatureError':"getFeatureFromEvent réteget hÃvott meg renderelÅ‘ nélkül. Ez rendszerint azt jelenti, hogy megsemmisÃtett egy fóliát, de néhány ahhoz társÃtott kezelÅ‘t nem.",'minZoomLevelError':"A minZoomLevel tulajdonságot csak a következÅ‘vel való használatra szánták: FixedZoomLevels-leszármazott fóliák. Ez azt jelenti, hogy a minZoomLevel wfs fólia jelölÅ‘négyzetei már a múlté. Mi azonban nem távolÃthatjuk el annak a veszélye nélkül, hogy az esetlegesen ettÅ‘l függÅ‘ OL alapú alkalmazásokat tönkretennénk. Ezért ezt érvénytelenÃtjük -- a minZoomLevel az alul levÅ‘ jelölÅ‘négyzet a 3.0-s verzióból el lesz távolÃtva. Kérjük, helyette használja a min/max felbontás beállÃtást, amelyrÅ‘l az alábbi helyen talál leÃrást: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS tranzakció: SIKERES ${response}",'commitFailed':"WFS tranzakció: SIKERTELEN ${response}",'googleWarning':"A Google fólia betöltése sikertelen.\x3cbr\x3e\x3cbr\x3eAhhoz, hogy ez az üzenet eltűnjön, válasszon egy új BaseLayer fóliát a jobb felsÅ‘ sarokban található fóliakapcsoló segÃtségével.\x3cbr\x3e\x3cbr\x3eNagy valószÃnűséggel ez azért van, mert a Google Maps könyvtár parancsfájlja nem található, vagy nem tartalmazza az Ön oldalához tartozó megfelelÅ‘ API-kulcsot.\x3cbr\x3e\x3cbr\x3eFejlesztÅ‘knek: A helyes működtetésre vonatkozó segÃtség az alábbi helyen érhetÅ‘ el, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3ekattintson ide\x3c/a\x3e",'getLayerWarning':"A(z) ${layerType} fólia nem töltÅ‘dött be helyesen.\x3cbr\x3e\x3cbr\x3eAhhoz, hogy ez az üzenet eltűnjön, válasszon egy új BaseLayer fóliát a jobb felsÅ‘ sarokban található fóliakapcsoló segÃtségével.\x3cbr\x3e\x3cbr\x3eNagy valószÃnűséggel ez azért van, mert a(z) ${layerLib} könyvtár parancsfájlja helytelen.\x3cbr\x3e\x3cbr\x3eFejlesztÅ‘knek: A helyes működtetésre vonatkozó segÃtség az alábbi helyen érhetÅ‘ el, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3ekattintson ide\x3c/a\x3e",'scale':"Lépték = 1 : ${scaleDenom}",'W':"Ny",'E':"K",'N':"É",'S':"D",'layerAlreadyAdded':"Megpróbálta hozzáadni a(z) ${layerName} fóliát a térképhez, de az már hozzá van adva",'reprojectDeprecated':"Ön a \'reproject\' beállÃtást használja a(z) ${layerName} fólián. Ez a beállÃtás érvénytelen: használata az üzleti alaptérképek fölötti adatok megjelenÃtésének támogatására szolgált, de ezt a funkció ezentúl a Gömbi Mercator használatával érhetÅ‘ el. További információ az alábbi helyen érhetÅ‘ el: http://trac.openlayers.org/wiki/SphericalMercator",'methodDeprecated':"Ez a módszer érvénytelenÃtve lett és a 3.0-s verzióból el lesz távolÃtva. Használja a(z) ${newMethod} módszert helyette.",'boundsAddError':"Az x és y értékeknek egyaránt meg kell felelnie, hogy a funkciót hozzáadhassa.",'lonlatAddError':"A hossz. és szél. értékeknek egyaránt meg kell felelnie, hogy a funkciót hozzáadhassa.",'pixelAddError':"Az x és y értékeknek egyaránt meg kell felelnie, hogy a funkciót hozzáadhassa.",'unsupportedGeometryType':"Nem támogatott geometriatÃpus: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition sikertelen: lehetséges, hogy a(z) ${elemId} azonosÃtójú elem téves helyre került.",'filterEvaluateNotImplemented':"ennél a szűrÅ‘tÃpusnál kiértékelés nem hajtódik végre."});OpenLayers.Lang["ia"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Le responsa a un requesta non esseva maneate: ${statusText}",'permalink':"Permaligamine",'overlays':"Superpositiones",'baseLayer':"Strato de base",'sameProjection':"Le mini-carta functiona solmente si illo es in le mesme projection que le carta principal",'readNotImplemented':"Lectura non implementate.",'writeNotImplemented':"Scriptura non implementate.",'noFID':"Non pote actualisar un elemento sin FID.",'errorLoadingGML':"Error al cargamento del file GML ${url}",'browserNotSupported':"Tu navigator non supporta le rendition de vectores. Le renditores actualmente supportate es:\n${renderers}",'componentShouldBe':"addFeatures: le componente debe esser del typo ${geomType}",'getFeatureError':"getFeatureFromEvent ha essite appellate in un strato sin renditor. Isto significa generalmente que tu ha destruite un strato, ma lassava un gestor associate con illo.",'minZoomLevelError':"Le proprietate minZoomLevel es solmente pro uso con le stratos descendente de FixedZoomLevels. Le facto que iste strato WFS verifica minZoomLevel es un reliquia del passato. Nonobstante, si nos lo remove immediatemente, nos pote rumper applicationes a base de OL que depende de illo. Ergo nos lo declara obsolete; le verification de minZoomLevel in basso essera removite in version 3.0. Per favor usa in su loco le configuration de resolutiones min/max como describite a: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transaction WFS: SUCCESSO ${response}",'commitFailed':"Transaction WFS: FALLEVA ${response}",'googleWarning':"Le strato Google non poteva esser cargate correctemente.\x3cbr\x3e\x3cbr\x3ePro disfacer te de iste message, selige un nove BaseLayer in le selector de strato in alto a dextra.\x3cbr\x3e\x3cbr\x3eMulto probabilemente, isto es proque le script del libreria de Google Maps non esseva includite o non contine le clave API correcte pro tu sito.\x3cbr\x3e\x3cbr\x3eDisveloppatores: Pro adjuta de corriger isto, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclicca hic\x3c/a",'getLayerWarning':"Le strato ${layerType} non poteva esser cargate correctemente.\x3cbr\x3e\x3cbr\x3ePro disfacer te de iste message, selige un nove BaseLayer in le selector de strato in alto a dextra.\x3cbr\x3e\x3cbr\x3eMulto probabilemente, isto es proque le script del libreria de ${layerLib} non esseva correctemente includite.\x3cbr\x3e\x3cbr\x3eDisveloppatores: Pro adjuta de corriger isto, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclicca hic\x3c/a\x3e",'scale':"Scala = 1 : ${scaleDenom}",'W':"W",'E':"E",'N':"N",'S':"S",'layerAlreadyAdded':"Tu tentava adder le strato: ${layerName} al carta, ma illo es ja presente",'reprojectDeprecated':"Tu usa le option \'reproject\' in le strato ${layerName} layer. Iste option es obsolescente: illo esseva pro poter monstrar datos super cartas de base commercial, ma iste functionalitate pote ora esser attingite con le uso de Spherical Mercator. Ulterior information es disponibile a http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Iste methodo ha essite declarate obsolescente e essera removite in version 3.0. Per favor usa ${newMethod} in su loco.",'boundsAddError':"Tu debe passar le duo valores x e y al function add.",'lonlatAddError':"Tu debe passar le duo valores lon e lat al function add.",'pixelAddError':"Tu debe passar le duo valores x e y al function add.",'unsupportedGeometryType':"Typo de geometria non supportate: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition falleva: le elemento con id ${elemId} pote esser mal placiate.",'filterEvaluateNotImplemented':"\"evaluate\" non es implementate pro iste typo de filtro."});OpenLayers.Lang["id"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Permintaan yang tak tertangani menghasilkan ${statusText}",'permalink':"Pranala permanen",'overlays':"Hamparan",'baseLayer':"Lapisan Dasar",'sameProjection':"Peta tinjauan hanya bekerja bila dalam proyeksi yang sama dengan peta utama",'readNotImplemented':"Membaca tidak diterapkan.",'writeNotImplemented':"Menyimpan tidak diterapkan.",'noFID':"Tidak dapat memperbarui fitur yang tidak memiliki FID.",'errorLoadingGML':"Kesalahan dalam memuat berkas GML ${url}",'browserNotSupported':"Peramban Anda tidak mendukung penggambaran vektor. Penggambar yang didukung saat ini adalah:\n${renderers}",'componentShouldBe':"addFeatures : komponen harus berupa ${geomType}",'getFeatureError':"getFeatureFromEvent diterapkan pada lapisan tanpa penggambar. Ini biasanya berarti Anda menghapus sebuah lapisan, tetapi tidak menghapus penangan yang terkait dengannya.",'minZoomLevelError':"Properti minZoomLevel hanya ditujukan bekerja dengan lapisan FixedZoomLevels-descendent. Pengecekan minZoomLevel oleh lapisan wfs adalah peninggalan masa lalu. Kami tidak dapat menghapusnya tanpa kemungkinan merusak aplikasi berbasis OL yang mungkin bergantung padanya. Karenanya, kami menganggapnya tidak berlaku -- Cek minZoomLevel di bawah ini akan dihapus pada 3.0. Silakan gunakan penyetelan resolusi min/maks seperti dijabarkan di sini: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS Transaksi: BERHASIL ${respon}",'commitFailed':"WFS Transaksi: GAGAL ${respon}",'googleWarning':"Lapisan Google tidak dapat dimuat dengan benar.\x3cbr\x3e\x3cbr\x3eUntuk menghilangkan pesan ini, pilih suatu BaseLayer baru melalui penukar lapisan (layer switcher) di ujung kanan atas.\x3cbr\x3e\x3cbr\x3eKemungkinan besar ini karena pustaka skrip Google Maps tidak disertakan atau tidak mengandung kunci API yang tepat untuk situs Anda.\x3cbr\x3e\x3cbr\x3ePengembang: Untuk bantuan mengatasi masalah ini, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eklik di sini\x3c/a\x3e",'getLayerWarning':"Lapisan ${layerType} tidak dapat dimuat dengan benar.\x3cbr\x3e\x3cbr\x3eUntuk menghilangkan pesan ini, pilih suatu BaseLayer baru melalui penukar lapisan (layer switcher) di ujung kanan atas.\x3cbr\x3e\x3cbr\x3eKemungkinan besar ini karena pustaka skrip Google Maps tidak disertakan dengan benar.\x3cbr\x3e\x3cbr\x3ePengembang: Untuk bantuan mengatasi masalah ini, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eklik di sini\x3c/a\x3e",'scale':"Sekala = 1 : ${scaleDenom}",'W':"B",'E':"T",'N':"U",'S':"S",'layerAlreadyAdded':"Anda mencoba menambahkan lapisan: ${layerName} ke dalam peta, tapi lapisan itu telah ditambahkan",'reprojectDeprecated':"Anda menggunakan opsi \'reproject\' pada lapisan ${layerName}. Opsi ini telah ditinggalkan: penggunaannya dirancang untuk mendukung tampilan data melalui peta dasar komersial, tapi fungsionalitas tersebut saat ini harus dilakukan dengan menggunakan dukungan Spherical Mercator. Informasi lebih lanjut tersedia di http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Metode ini telah usang dan akan dihapus di 3.0. Sebaliknya, harap gunakan ${newMethod}.",'boundsAddError':"Anda harus memberikan kedua nilai x dan y ke fungsi penambah.",'lonlatAddError':"Anda harus memberikan kedua nilai lon dan lat ke fungsi penambah.",'pixelAddError':"Anda harus memberikan kedua nilai x dan y ke fungsi penambah.",'unsupportedGeometryType':"Tipe geometri tak didukung: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition gagal: elemen dengan id ${elemId} mungkin salah tempat.",'filterEvaluateNotImplemented':"evaluasi tidak tersedia untuk tipe filter ini."});OpenLayers.Lang["io"]=OpenLayers.Util.applyDefaults({'scale':"Skalo = 1 : ${scaleDenom}"});OpenLayers.Lang["is"]=OpenLayers.Util.applyDefaults({'permalink':"Varanlegur tengill",'overlays':"Þekjur",'baseLayer':"Grunnlag",'sameProjection':"Yfirlitskortið virkar aðeins ef það er à sömu vörpun og aðalkortið",'readNotImplemented':"Skrifun er óútfærð.",'writeNotImplemented':"Lestur er óútfærður.",'errorLoadingGML':"Villa kom upp við að hlaða inn GML skránni ${url}",'scale':"Skali = 1 : ${scaleDenom}",'layerAlreadyAdded':"Þú reyndir að bæta laginu ${layerName} á kortið en það er þegar búið að bæta þvà við",'methodDeprecated':"Þetta fall hefur verið úrelt og verður fjarlægt à 3.0. Notaðu ${newMethod} à staðin."});OpenLayers.Lang["ja"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"未処ç†ã®è¦æ±‚㯠${statusText} ã‚’è¿”ã—ã¾ã™",'permalink':"パーマリンク",'overlays':"オーãƒãƒ¼ãƒ¬ã‚¤",'baseLayer':"基底レイヤー",'sameProjection':"概観地図ã¯ãƒ¡ã‚¤ãƒ³ã®åœ°å›³ã¨åŒã˜æŠ•影法をã¨ã‚‹å ´åˆã®ã¿æ©Ÿèƒ½ã—ã¾ã™",'readNotImplemented':"èªã¿è¾¼ã¿ã¯å®Ÿè£…ã•れã¦ã„ã¾ã›ã‚“。",'writeNotImplemented':"書ãè¾¼ã¿ã¯å®Ÿè£…ã•れã¦ã„ã¾ã›ã‚“。",'noFID':"FID ã®ãªã„åœ°ç‰©ã¯æ›´æ–°ã§ãã¾ã›ã‚“。",'errorLoadingGML':"GML ファイル ${url} ã®èªã¿è¾¼ã¿ã‚¨ãƒ©ãƒ¼",'browserNotSupported':"ã‚ãªãŸã®ãƒ–ラウザã¯ãƒ™ã‚¯ã‚¿ãƒ¼ã‚°ãƒ©ãƒ•ã‚£ãƒƒã‚¯ã‚¹ã®æå†™ã«å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“ã€‚ç¾æ™‚点ã§å¯¾å¿œã—ã¦ã„るソフトウェアã¯ä»¥ä¸‹ã®ã‚‚ã®ã§ã™ã€‚\n${renderers}",'componentShouldBe':"addFeatures: è¦ç´ 㯠${geomType} ã§ã‚ã‚‹ã¹ãã§ã™",'getFeatureError':"getFeatureFromEvent ãŒãƒ¬ãƒ³ãƒ€ãƒ©ãƒ¼ã®ãªã„レイヤーã‹ã‚‰å‘¼ã°ã‚Œã¾ã—ãŸã€‚通常ã€ã“れã¯ã‚ãªãŸãŒãƒ¬ã‚¤ãƒ¤ãƒ¼ã‚’ã€ãれã«é–¢é€£ã¥ã‘られãŸã„ãã¤ã‹ã®ãƒãƒ³ãƒ‰ãƒ©ã‚’除ã„ã¦ã€ç ´å£Šã—ã¦ã—ã¾ã£ãŸã“ã¨ã‚’æ„味ã—ã¾ã™ã€‚",'minZoomLevelError':"minZoomLevel プãƒãƒ‘ティ㯠FixedZoomLevels を継承ã™ã‚‹ãƒ¬ã‚¤ãƒ¤ãƒ¼ã§ã®ä½¿ç”¨ã®ã¿ã‚’想定ã—ã¦ã„ã¾ã™ã€‚ã“ã® minZoomLevel ã«å¯¾ã™ã‚‹ WFS ãƒ¬ã‚¤ãƒ¤ãƒ¼ã®æ¤œæŸ»ã¯æ´å²çš„ãªã‚‚ã®ã§ã™ã€‚ã—ã‹ã—ãªãŒã‚‰ã€ã“ã®æ¤œæŸ»ã‚’除去ã™ã‚‹ã¨ãれã«ä¾å˜ã™ã‚‹ OpenLayers ベースã®ã‚¢ãƒ—ãƒªã‚±ãƒ¼ã‚·ãƒ§ãƒ³ã‚’ç ´å£Šã—ã¦ã—ã¾ã†å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚よã£ã¦å»ƒæ¢ãŒäºˆå®šã•れã¦ãŠã‚Šã€ã“ã® minZoomLevel 検査ã¯ãƒãƒ¼ã‚¸ãƒ§ãƒ³3.0ã§é™¤åŽ»ã•れã¾ã™ã€‚代ã‚りã«ã€http://trac.openlayers.org/wiki/SettingZoomLevels ã§è§£èª¬ã•れã¦ã„ã‚‹ã€æœ€å°ãŠã‚ˆã³æœ€å¤§è§£åƒåº¦è¨å®šã‚’使用ã—ã¦ãã ã•ã„。",'commitSuccess':"WFS トランザクション: æˆåŠŸ ${response}",'commitFailed':"WFS トランザクション: 失敗 ${response}",'googleWarning':"Google ãƒ¬ã‚¤ãƒ¤ãƒ¼ãŒæ£ã—ãèªã¿è¾¼ã¿ã‚’行ãˆã¾ã›ã‚“ã§ã—ãŸã€‚\x3cbr\x3e\x3cbr\x3eã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’消ã™ã«ã¯ã€å³ä¸Šã®éš…ã«ã‚るレイヤー切り替ãˆéƒ¨åˆ†ã§æ–°ã—ã„基底レイヤーをé¸ã‚“ã§ãã ã•ã„。\x3cbr\x3e\x3cbr\x3eãŠãらãã€ã“れ㯠Google マップ用ライブラリã®ã‚¹ã‚¯ãƒªãƒ—トãŒçµ„ã¿è¾¼ã¾ã‚Œã¦ã„ãªã„ã‹ã€ã‚ãªãŸã®ã‚µã‚¤ãƒˆã«å¯¾å¿œã™ã‚‹æ£ã—ã„ API ã‚ーãŒè¨å®šã•れã¦ã„ãªã„ãŸã‚ã§ã™ã€‚\x3cbr\x3e\x3cbr\x3eé–‹ç™ºè€…ã®æ–¹ã¸: æ£ã—ã„動作をã•ã›ã‚‹ãŸã‚ã«\x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eã“ã¡ã‚‰ã®ã‚¦ã‚£ã‚\x3c/a\x3eã‚’å‚ç…§ã—ã¦ãã ã•ã„。",'getLayerWarning':"${layerType} ãƒ¬ã‚¤ãƒ¤ãƒ¼ãŒæ£ã—ãèªã¿è¾¼ã¿ã‚’行ãˆã¾ã›ã‚“ã§ã—ãŸã€‚\x3cbr\x3e\x3cbr\x3eã“ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã‚’消ã™ã«ã¯ã€å³ä¸Šã®éš…ã«ã‚るレイヤー切り替ãˆéƒ¨åˆ†ã§æ–°ã—ã„基底レイヤーをé¸ã‚“ã§ãã ã•ã„。\x3cbr\x3e\x3cbr\x3eãŠãらãã€ã“れ㯠${layerLib} ライブラリã®ã‚¹ã‚¯ãƒªãƒ—ãƒˆãŒæ£ã—ã組ã¿è¾¼ã¾ã‚Œã¦ã„ãªã„ãŸã‚ã§ã™ã€‚\x3cbr\x3e\x3cbr\x3eé–‹ç™ºè€…ã®æ–¹ã¸: æ£ã—ã„動作をã•ã›ã‚‹ãŸã‚ã«\x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eã“ã¡ã‚‰ã®ã‚¦ã‚£ã‚\x3c/a\x3eã‚’å‚ç…§ã—ã¦ãã ã•ã„。",'scale':"縮尺 = 1 : ${scaleDenom}",'W':"西",'E':"æ±",'N':"北",'S':"å—",'layerAlreadyAdded':"ã‚ãªãŸã¯ã€Œ${layerName}ã€ã‚’地図ã«è¿½åŠ ã—よã†ã¨è©¦ã¿ã¾ã—ãŸãŒã€ãã®ãƒ¬ã‚¤ãƒ¤ãƒ¼ã¯æ—¢ã«è¿½åŠ ã•れã¦ã„ã¾ã™",'reprojectDeprecated':"ã‚ãªãŸã¯ã€Œ${layerName}ã€ãƒ¬ã‚¤ãƒ¤ãƒ¼ã§ reproject オプションを使ã£ã¦ã„ã¾ã™ã€‚ã“ã®ã‚ªãƒ—ションã¯å•†ç”¨ã®åŸºåº•åœ°å›³ä¸Šã«æƒ…å ±ã‚’è¡¨ç¤ºã™ã‚‹ç›®çš„ã§è¨è¨ˆã•れã¾ã—ãŸãŒã€ç¾åœ¨ã§ã¯ãã®æ©Ÿèƒ½ã¯ Spherical Mercator サãƒãƒ¼ãƒˆã‚’利用ã—ã¦å®Ÿç¾ã•れã¦ãŠã‚Šã€ã“ã®ã‚ªãƒ—ションã®ä½¿ç”¨ã¯éžæŽ¨å¥¨ã§ã™ã€‚è¿½åŠ ã®æƒ…å ±ã¯ http://trac.openlayers.org/wiki/SphericalMercator ã§å…¥æ‰‹ã§ãã¾ã™ã€‚",'methodDeprecated':"ã“ã®ãƒ¡ã‚½ãƒƒãƒ‰ã¯å»ƒæ¢ãŒäºˆå®šã•れã¦ãŠã‚Šã€ãƒãƒ¼ã‚¸ãƒ§ãƒ³3.0ã§é™¤åŽ»ã•れã¾ã™ã€‚代ã‚り㫠${newMethod} を使用ã—ã¦ãã ã•ã„。",'boundsAddError':"x 㨠y 両方ã®å€¤ã‚’ add é–¢æ•°ã«æ¸¡ã•ãªã‘れã°ãªã‚Šã¾ã›ã‚“。",'lonlatAddError':"lon 㨠lat 両方ã®å€¤ã‚’ add é–¢æ•°ã«æ¸¡ã•ãªã‘れã°ãªã‚Šã¾ã›ã‚“。",'pixelAddError':"x 㨠y ã®å€¤ä¸¡æ–¹ã‚’ add é–¢æ•°ã«æ¸¡ã•ãªã‘れã°ãªã‚Šã¾ã›ã‚“。",'unsupportedGeometryType':"未対応ã®å½¢çŠ¶åž‹: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition ãŒå¤±æ•—ã—ã¾ã—ãŸ: id ${elemId} ã‚’ã‚‚ã¤è¦ç´ ãŒèª¤ã£ãŸä½ç½®ã«ã‚ã‚‹å¯èƒ½æ€§ãŒã‚りã¾ã™ã€‚",'filterEvaluateNotImplemented':"ã“ã®ãƒ•ィルター型ã«ã¤ã„㦠evaluate ã¯å®Ÿè£…ã•れã¦ã„ã¾ã›ã‚“。"});OpenLayers.Lang["km"]=OpenLayers.Util.applyDefaults({'permalink':"ážáŸ†ážŽáž—្ជាប់អចិន្ážáŸ’រៃយáŸ",'baseLayer':"ស្រទាប់បាážâ€‹",'errorLoadingGML':"កំហុសកំឡុងពáŸáž›áž•្ទុកឯកសារ GML ${url}",'scale':"មាážáŸ’រដ្ឋាន = ១ ៖ ${scaleDenom}"});OpenLayers.Lang["ksh"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Met dä Antwoot op en Aanfrooch ham_mer nix aanjefange: ${statusText}",'permalink':"Lengk op Duuer",'overlays':"Drövver jelaat",'baseLayer':"Jrund-Nivoh",'sameProjection':"De Övverseeschs_Kaat deiht et bloß, wann se de sälve Projäxjuhn bruche deiht, wi de Houp_Kaat",'readNotImplemented':"„\x3ccode lang=\"en\"\x3eread\x3c/code\x3e“ is em Projramm nit fürjesinn.",'writeNotImplemented':"„\x3ccode lang=\"en\"\x3ewrite\x3c/code\x3e“ is em Projramm nit fürjesinn.",'noFID':"En Saach, woh kein \x3ci lang=\"en\"\x3eFID\x3c/i\x3e för doh es, löht sesch nit ändere.",'errorLoadingGML':"Fähler beim \x3ci lang=\"en\"\x3eGML\x3c/i\x3e-Datei-Laade vun \x3ccode\x3e${url}\x3c/code\x3e",'browserNotSupported':"Dinge Brauser kann kein Väktore ußjävve. De Zoote Ußjaabe, di em Momang jon, sen:\n${renderers}",'componentShouldBe':"\x3ccode lang=\"en\"\x3eaddFeatures\x3c/code\x3e: dä Aandeil sullt vun dä Zoot „\x3ccode lang=\"en\"\x3e${geomType}\x3c/code\x3e“ sin.",'getFeatureError':"\x3ccode lang=\"en\"\x3egetFeatureFromEvent\x3c/code\x3e es vun enem Nivoh opjeroofe woode, woh et kei Projramm zom Ußjävve jit. Dat bedügg för jewöhnlesch, dat De e Nivoh kapott jemaat häs, ävver nit e Projramm för domet ömzejonn, wat domet verbonge es.",'minZoomLevelError':"De Eijeschaff „\x3ccode lang=\"en\"\x3eminZoomLevel\x3c/code\x3e“ es bloß doför jedaach, dat mer se met dä Nivvohß bruch, di vun \x3ccode lang=\"en\"\x3eFixedZoomLevels\x3c/code\x3e affhange don. Dat dat \x3ci lang=\"en\"\x3eWFS\x3c/i\x3e-Nivvoh övverhoup de Eijeschaff „\x3ccode lang=\"en\"\x3eminZoomLevel\x3c/code\x3e“ pröhfe deiht, es noch övveresch vun fröhjer. Mer künne dat ävver jez nit fott lohße, oohne dat mer Jevaa loufe, dat Aanwendunge vun OpenLayers nit mieh loufe, di sesch doh velleijsch noch drop am verlohße sin. Dröm sare mer, dat mer et nit mieh han welle, un de „\x3ccode lang=\"en\"\x3eminZoomLevel\x3c/code\x3e“-Eijeschaff weed hee vun de Version 3.0 af nit mieh jeprööf wäde. Nemm doför de Enstellung för de hühßte un de kleinßte Oplöhsung, esu wi et en http://trac.openlayers.org/wiki/SettingZoomLevels opjeschrevve es.",'commitSuccess':"Dä \x3ci lang=\"en\"\x3eWFS\x3c/i\x3e-Vörjang es joot jeloufe: ${response}",'commitFailed':"Dä \x3ci lang=\"en\"\x3eWFS\x3c/i\x3e-Vörjang es scheif jejange: ${response}",'googleWarning':"Dat Nivvoh \x3ccode lang=\"en\"\x3eGoogle\x3c/code\x3e kunnt nit reschtesch jelaade wääde.\x3cbr /\x3e\x3cbr /\x3eÖm hee di Nohreesch loß ze krijje, donn en ander Jrund-Nivvoh ußsöhke, rähß bovve en de Äk.\x3cbr /\x3e\x3cbr /\x3eWascheinlesch es dat wiel dat \x3ci lang=\"en\"\x3eGoogle-Maps\x3c/i\x3e-Skrepp entweeder nit reschtesch enjebonge wood, udder nit dä reschtejje \x3ci lang=\"en\"\x3eAPI\x3c/i\x3e-Schlößel för Ding Web-ßait scheke deiht.\x3cbr /\x3e\x3cbr /\x3eFör Projrammierer jidd_et Hölp do_drövver, \x3ca href=\"http://trac.openlayers.org/wiki/Google\" target=\"_blank\"\x3ewi mer dat aan et Loufe brengk\x3c/a\x3e.",'getLayerWarning':"Dat Nivvoh \x3ccode\x3e${layerType}\x3c/code\x3e kunnt nit reschtesch jelaade wääde.\x3cbr /\x3e\x3cbr /\x3eÖm hee di Nohreesch loß ze krijje, donn en ander Jrund-Nivvoh ußsöhkre, rähß bovve en de Äk.\x3cbr /\x3e\x3cbr /\x3eWascheinlesch es dat, wiel dat Skrepp \x3ccode\x3e${layerLib}\x3c/code\x3e nit reschtesch enjebonge wood.\x3cbr /\x3e\x3cbr /\x3eFör Projrammierer jidd_Et Hölp do_drövver, \x3ca href=\"http://trac.openlayers.org/wiki/${layerLib}\" target=\"_blank\"\x3ewi mer dat aan et Loufe brengk\x3c/a\x3e.",'scale':"Mohßshtaab = 1 : ${scaleDenom}",'W':"W",'E':"O",'N':"N",'S':"S",'layerAlreadyAdded':"Do häß versöhk, dat Nivvoh \x3ccode\x3e${layerName}\x3c/code\x3e en di Kaat eren ze bränge, et wohr ävver ald do dren.",'reprojectDeprecated':"Do bruchs de Ußwahl \x3ccode\x3ereproject\x3c/code\x3e op däm Nivvoh \x3ccode\x3e${layerName}\x3c/code\x3e. Di Ußwahl es nit mieh jähn jesinn. Se wohr doför jedaach, öm Date op jeschääfsmäßesch eruß jejovve Kaate bovve drop ze moole, wat ävver enzwesche besser met dä Öngershtözung för de ßfääresche Mäkaator Beldscher jeiht. Doh kanns De mieh drövver fenge op dä Sigg: http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Hee di Metood es nim_mih aktoäll un et weed se en dä Version 3.0 nit mieh jävve. Nemm \x3ccode\x3e${newMethod}\x3c/code\x3e doföör.",'boundsAddError':"Do moß beeds vun de \x3ccode\x3ex\x3c/code\x3e un \x3ccode\x3ey\x3c/code\x3e Wääte aan de Fungkßjohn \x3ccode\x3eadd\x3c/code\x3e jävve.",'lonlatAddError':"Do moß beeds \x3ccode\x3elon\x3c/code\x3e un \x3ccode\x3elat\x3c/code\x3e aan de Fungkßjohn \x3ccode\x3eadd\x3c/code\x3e jävve.",'pixelAddError':"Do moß beeds \x3ccode\x3ex\x3c/code\x3e un \x3ccode\x3ey\x3c/code\x3e aan de Fungkßjohn \x3ccode\x3eadd\x3c/code\x3e jävve.",'unsupportedGeometryType':"De Zoot Jommetrii dom_mer nit ongershtöze: \x3ccode\x3e${geomType}\x3c/code\x3e",'pagePositionFailed':"\x3ccode lang=\"en\"\x3eOpenLayers.Util.pagePosition\x3c/code\x3e es donevve jejange: dat Denge met dä Kännong \x3ccode\x3e${elemId}\x3c/code\x3e künnt am verkeehte Plaz sin.",'filterEvaluateNotImplemented':"„\x3ccode lang=\"en\"\x3eevaluate\x3c/code\x3e“ es för di Zoot Fellter nit enjereschdt."});OpenLayers.Lang["nds"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Unbehannelt Trüchmellels för de Anfraag ${statusText}",'permalink':"Permalink",'overlays':"Overlays",'baseLayer':"Achtergrundkoort",'sameProjection':"De Översichtskoort geiht blot, wenn de sülve Projekschoon as bi de Hööftkoort bruukt warrt",'readNotImplemented':"Lesen is nich inricht.",'writeNotImplemented':"Schrieven is nich inricht.",'noFID':"En Feature, dat keen FID hett, kann nich aktuell maakt warrn.",'errorLoadingGML':"Fehler bi’t Laden vun de GML-Datei ${url}",'browserNotSupported':"Dien Browser ünnerstütt keen Vektorbiller. Ünnerstütt Renderers:\n${renderers}",'componentShouldBe':"addFeatures : Kumponent schull man den Typ ${geomType} hebben",'getFeatureError':"getFeatureFromEvent is von en Laag ahn Render opropen worrn. Dat bedüüdt normalerwies, dat en Laag wegmaakt worrn is, aver nich de Handler, de dor op verwiest.",'commitSuccess':"WFS-Transakschoon: hett klappt ${response}",'commitFailed':"WFS-Transakschoon: hett nich klappt ${response}",'scale':"Skaal = 1 : ${scaleDenom}",'layerAlreadyAdded':"Du versöchst de Laag „${layerName}“ to de Koort totofögen, man de is al toföögt",'methodDeprecated':"Disse Methood is oold un schall dat in 3.0 nich mehr geven. Bruuk dor man beter ${newMethod} för.",'boundsAddError':"De Weert x un y, de mööt all beid an de add-Funkschoon övergeven warrn.",'lonlatAddError':"De Weert lon un lat, de mööt all beid an de add-Funkschoon övergeven warrn.",'pixelAddError':"De Weert x un y, de mööt all beid an de add-Funkschoon övergeven warrn.",'unsupportedGeometryType':"Nich ünnerstütt Geometrie-Typ: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition güng nich: Element mit de Id ${elemId} is villicht an’n verkehrten Platz."});OpenLayers.Lang["nn"]=OpenLayers.Util.applyDefaults({'scale':"Skala = 1 : ${scaleDenom}",'layerAlreadyAdded':"Du freista Ã¥ leggja til laget «${layerName}» pÃ¥ kartet, men det har alt vorte lagt til.",'boundsAddError':"Du er nøydd til Ã¥ gje bÃ¥de ein x- og ein y-verdi til «add»-funksjonen.",'lonlatAddError':"Du er nøydd til Ã¥ gje bÃ¥de lon- og lat-verdiar til «add»-funksjonen.",'pixelAddError':"Du er nøydd til Ã¥ gje bÃ¥de ein x- og ein y-verdi til «add»-funksjonen."});OpenLayers.Lang["oc"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Requèsta pas gerida, retorna ${statusText}",'permalink':"Permaligam",'overlays':"Calques",'baseLayer':"Calc de basa",'sameProjection':"La carta de situacion fonciona pas que quora sa projeccion es la meteissa que la de la carta principala",'readNotImplemented':"Lectura pas implementada.",'writeNotImplemented':"Escritura pas implementada.",'noFID':"Impossible de metre a jorn un objècte sens identificant (fid).",'errorLoadingGML':"Error al cargament del fichièr GML ${url}",'browserNotSupported':"Vòstre navegidor supòrta pas lo rendut vectorial. Los renderers actualament suportats son : \n${renderers}",'componentShouldBe':"addFeatures : lo compausant deuriá èsser de tipe ${geomType}",'getFeatureError':"getFeatureFromEvent es estat apelat sus un calc sens renderer. Aquò significa generalament qu\'avètz destruch aqueste jaç, mas qu\'avètz conservat un handler que li èra associat.",'minZoomLevelError':"La proprietat minZoomLevel deu èsser utilizada solament per de jaces FixedZoomLevels-descendent. Lo fach qu\'aqueste jaç WFS verifique la preséncia de minZoomLevel es una relica del passat. Çaquelà , la podèm suprimir sens copar d\'aplicacions que ne poirián dependre. Es per aquò que la depreciam -- la verificacion del minZoomLevel serà suprimida en version 3.0. A la plaça, mercés d\'utilizar los paramètres de resolucions min/max tal coma descrich sus : http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transaccion WFS : SUCCES ${response}",'commitFailed':"Transaccion WFS : FRACAS ${response}",'googleWarning':"Lo jaç Google es pas estat en mesura de se cargar corrèctament.\x3cbr\x3e\x3cbr\x3ePer suprimir aqueste messatge, causissètz una BaseLayer novèla dins lo selector de jaç en naut a drecha.\x3cbr\x3e\x3cbr\x3eAquò es possiblament causat par la non-inclusion de la librariá Google Maps, o alara perque que la clau de l\'API correspond pas a vòstre site.\x3cbr\x3e\x3cbr\x3eDesvolopaires : per saber cossà corregir aquò, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclicatz aicÃ\x3c/a\x3e",'getLayerWarning':"Lo jaç ${layerType} es pas en mesura de se cargar corrèctament.\x3cbr\x3e\x3cbr\x3ePer suprimir aqueste messatge, causissètz una BaseLayer novèla dins lo selector de jaç en naut a drecha.\x3cbr\x3e\x3cbr\x3eAquò es possiblament causat per la non-inclusion de la librariá ${layerLib}.\x3cbr\x3e\x3cbr\x3eDesvolopaires : per saber cossà corregir aquÃ, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclicatz aicÃ\x3c/a\x3e",'scale':"Escala ~ 1 : ${scaleDenom}",'W':"O",'E':"È",'N':"N",'S':"S",'layerAlreadyAdded':"Avètz ensajat d\'apondre a la carta lo calc : ${layerName}, mas ja es present",'reprojectDeprecated':"Utilizatz l\'opcion \'reproject\' sul jaç ${layerName}. Aquesta opcion es despreciada : Son usatge permetiá d\'afichar de donadas al dessús de jaces raster comercials. Aquesta foncionalitat ara es suportada en utilizant lo supòrt de la projeccion Mercator Esferica. Mai d\'informacion es disponibla sus http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Aqueste metòde es despreciada, e serà suprimida a la version 3.0. Mercés d\'utilizar ${newMethod} a la plaça.",'boundsAddError':"Vos cal passar las doas valors x e y a la foncion add.",'lonlatAddError':"Vos cal passar las doas valors lon e lat a la foncion add.",'pixelAddError':"Vos cal passar las doas valors x e y a la foncion add.",'unsupportedGeometryType':"Tipe de geometria pas suportat : ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition a fracassat : l\'element d\'id ${elemId} poiriá èsser mal posicionat.",'filterEvaluateNotImplemented':"evaluar es pas encara estat implementat per aqueste tipe de filtre."});OpenLayers.Lang["pt"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Servidor devolveu erro não contemplado ${statusText}",'permalink':"Ligação permanente",'overlays':"Sobreposições",'baseLayer':"Camada Base",'sameProjection':"O mapa panorâmico só funciona quando está na mesma projeção que o mapa principal",'readNotImplemented':"Leitura não implementada.",'writeNotImplemented':"Escrita não implementada.",'noFID':"Não é possÃvel atualizar um elemento para a qual não há FID.",'errorLoadingGML':"Erro ao carregar ficheiro GML ${url}",'browserNotSupported':"O seu navegador não suporta renderização vetorial. Actualmente os renderizadores suportados são:\n${renderers}",'componentShouldBe':"addFeatures: componente deve ser um(a) ${geomType}",'getFeatureError':"getFeatureFromEvent foi chamado numa camada sem renderizador. Isto normalmente significa que destruiu uma camada, mas não um manipulador \'\'(handler)\'\' que lhe está associado.",'minZoomLevelError':"A propriedade minZoomLevel só deve ser usada com as camadas descendentes da FixedZoomLevels. A verificação da propriedade por esta camada wfs é uma relÃquia do passado. No entanto, não podemos removê-la sem correr o risco de afectar aplicações OL que dependam dela. Portanto, estamos a torná-la obsoleta -- a verificação minZoomLevel será removida na versão 3.0. Em vez dela, por favor, use as opções de resolução min/max descritas aqui: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transacção WFS: SUCESSO ${response}",'commitFailed':"Transacção WFS: FALHOU ${response}",'googleWarning':"A Camada Google não foi correctamente carregada.\x3cbr\x3e\x3cbr\x3ePara deixar de receber esta mensagem, seleccione uma nova Camada-Base no \'\'switcher\'\' de camadas no canto superior direito.\x3cbr\x3e\x3cbr\x3eProvavelmente, isto acontece porque o \'\'script\'\' da biblioteca do Google Maps não foi incluÃdo ou não contém a chave API correcta para o seu sÃtio.\x3cbr\x3e\x3cbr\x3eProgramadores: Para ajuda sobre como solucionar o problema \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclique aqui\x3c/a\x3e .",'getLayerWarning':"A camada ${layerType} não foi correctamente carregada.\x3cbr\x3e\x3cbr\x3ePara desactivar esta mensagem, seleccione uma nova Camada-Base no \'\'switcher\'\' de camadas no canto superior direito.\x3cbr\x3e\x3cbr\x3eProvavelmente, isto acontece porque o \'\'script\'\' da biblioteca ${layerLib} não foi incluÃdo correctamente.\x3cbr\x3e\x3cbr\x3eProgramadores: Para ajuda sobre como solucionar o problema \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclique aqui\x3c/a\x3e .",'scale':"Escala = 1 : ${scaleDenom}",'W':"O",'E':"E",'N':"N",'S':"S",'layerAlreadyAdded':"Você tentou adicionar a camada: ${layerName} ao mapa, mas ela já tinha sido adicionada antes",'reprojectDeprecated':"Está usando a opção \'reproject\' na camada ${layerName}. Esta opção é obsoleta: foi concebida para permitir a apresentação de dados sobre mapas-base comerciais, mas esta funcionalidade é agora suportada pelo Mercator Esférico. Mais informação está disponÃvel em http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Este método foi declarado obsoleto e será removido na versão 3.0. Por favor, use ${newMethod} em vez disso.",'boundsAddError':"Você deve passar tanto o valor x como o y à função de adição.",'lonlatAddError':"Você deve passar tanto o valor lon como o lat à função de adição.",'pixelAddError':"Você deve passar tanto o valor x como o y à função de adição.",'unsupportedGeometryType':"Tipo de geometria não suportado: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition falhou: o elemento com o id ${elemId} poderá estar mal-posicionado.",'filterEvaluateNotImplemented':"avaliar não está implementado para este tipo de filtro."});OpenLayers.Lang["ru"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Ðеобработанный Ð·Ð°Ð¿Ñ€Ð¾Ñ Ð²ÐµÑ€Ð½ÑƒÐ» ${statusText}",'permalink':"ПоÑтоÑÐ½Ð½Ð°Ñ ÑÑылка",'overlays':"Слои",'baseLayer':"ОÑновной Ñлой",'sameProjection':"ÐžÐ±Ð·Ð¾Ñ€Ð½Ð°Ñ ÐºÐ°Ñ€Ñ‚Ð° работает только тогда, когда имеет ту же проекцию, что и оÑновнаÑ",'readNotImplemented':"Чтение не реализовано.",'writeNotImplemented':"ЗапиÑÑŒ не реализована.",'noFID':"Ðевозможно обновить объект, Ð´Ð»Ñ ÐºÐ¾Ñ‚Ð¾Ñ€Ð¾Ð³Ð¾ нет FID.",'errorLoadingGML':"Ошибка при загрузке файла GML ${url}",'browserNotSupported':"Ваш браузер не поддерживает векторную графику. Ðа данный момент поддерживаютÑÑ:\n${renderers}",'componentShouldBe':"addFeatures: компонент должен быть ${geomType}",'getFeatureError':"getFeatureFromEvent вызван Ð´Ð»Ñ ÑÐ»Ð¾Ñ Ð±ÐµÐ· рендерера. Обычно Ñто говорит о том, что вы уничтожили Ñлой, но оÑтавили ÑвÑзанный Ñ Ð½Ð¸Ð¼ обработчик.",'minZoomLevelError':"СвойÑтво minZoomLevel предназначено только Ð´Ð»Ñ Ð¸ÑÐ¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ð½Ð¸Ñ Ñо ÑлоÑми, ÑвлÑющимиÑÑ Ð¿Ð¾Ñ‚Ð¾Ð¼ÐºÐ°Ð¼Ð¸ FixedZoomLevels. То, что Ñтот WFS-Ñлой проверÑетÑÑ Ð½Ð° minZoomLevel — реликт прошлого. Однако мы не можем удалить Ñту функцию, так как, возможно, от неё завиÑÑÑ‚ некоторые оÑнованные на OpenLayers приложениÑ. Ð¤ÑƒÐ½ÐºÑ†Ð¸Ñ Ð¾Ð±ÑŠÑвлена уÑтаревшей — проверка minZoomLevel будет удалена в 3.0. ПожалуйÑта, иÑпользуйте вмеÑто неё наÑтройку мин/Ð¼Ð°ÐºÑ Ñ€Ð°Ð·Ñ€ÐµÑˆÐµÐ½Ð¸Ñ, опиÑанную здеÑÑŒ: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Ð¢Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ñ WFS: УСПЕШÐО ${response}",'commitFailed':"Ð¢Ñ€Ð°Ð½Ð·Ð°ÐºÑ†Ð¸Ñ WFS: ОШИБКР${response}",'googleWarning':"Слой Google не удалоÑÑŒ нормально загрузить.\x3cbr\x3e\x3cbr\x3eЧтобы избавитьÑÑ Ð¾Ñ‚ Ñтого ÑообщениÑ, выбите другой оÑновной Ñлой в переключателе в правом верхнем углу.\x3cbr\x3e\x3cbr\x3eСкорее вÑего, причина в том, что библиотека Google Maps не была включена или не Ñодержит корректного API-ключа Ð´Ð»Ñ Ð²Ð°ÑˆÐµÐ³Ð¾ Ñайта.\x3cbr\x3e\x3cbr\x3eРазработчикам: чтобы узнать, как Ñделать, чтобы вÑÑ‘ заработало, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eщёлкните тут\x3c/a\x3e",'getLayerWarning':"Слой ${layerType} не удалоÑÑŒ нормально загрузить. \x3cbr\x3e\x3cbr\x3eЧтобы избавитьÑÑ Ð¾Ñ‚ Ñтого ÑообщениÑ, выбите другой оÑновной Ñлой в переключателе в правом верхнем углу.\x3cbr\x3e\x3cbr\x3eСкорее вÑего, причина в том, что библиотека ${layerLib} не была включена или была включена некорректно.\x3cbr\x3e\x3cbr\x3eРазработчикам: чтобы узнать, как Ñделать, чтобы вÑÑ‘ заработало, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eщёлкните тут\x3c/a\x3e",'scale':"МаÑштаб = 1 : ${scaleDenom}",'W':"З",'E':"Ð’",'N':"С",'S':"Ю",'layerAlreadyAdded':"Ð’Ñ‹ попыталиÑÑŒ добавить Ñлой «${layerName}» на карту, но он уже был добавлен",'reprojectDeprecated':"Ð’Ñ‹ иÑпользуете опцию \'reproject\' Ð´Ð»Ñ ÑÐ»Ð¾Ñ ${layerName}. Ðта Ð¾Ð¿Ñ†Ð¸Ñ ÑвлÑетÑÑ ÑƒÑтаревшей: ее иÑпользование предполагалоÑÑŒ Ð´Ð»Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ¸ показа данных поверх коммерчеÑких базовых карт, но теперь Ñтот функционал неÑёт вÑÑ‚Ñ€Ð¾ÐµÐ½Ð½Ð°Ñ Ð¿Ð¾Ð´Ð´ÐµÑ€Ð¶ÐºÐ° ÑферичеÑкой проекции Меркатора. Больше Ñведений доÑтупно на http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Ðтот метод ÑчитаетÑÑ ÑƒÑтаревшим и будет удалён в верÑии 3.0. ПожалуйÑта, пользуйтеÑÑŒ ${newMethod}.",'boundsAddError':"Функции add надо передавать оба значениÑ, x и y.",'lonlatAddError':"Функции add надо передавать оба значениÑ, lon и lat.",'pixelAddError':"Функции add надо передавать оба значениÑ, x и y.",'unsupportedGeometryType':"Ðеподдерживаемый тип геометрии: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition failed: Ñлемент Ñ id ${elemId} может находитьÑÑ Ð½Ðµ в нужном меÑте.",'filterEvaluateNotImplemented':"evaluate не реализовано Ð´Ð»Ñ Ñ„Ð¸Ð»ÑŒÑ‚Ñ€Ð° данного типа."});OpenLayers.Lang["sk"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Neobslúžené požiadavky vracajú ${statusText}",'permalink':"Trvalý odkaz",'overlays':"Prekrytia",'baseLayer':"Základná vrstva",'sameProjection':"Prehľadová mapka funguje iba vtedy, keÄ je v rovnakej projekcii ako hlavná mapa",'readNotImplemented':"ÄŒÃtanie nie je implementované.",'writeNotImplemented':"Zápis nie je implementovaný.",'noFID':"Nie je možné aktualizovaÅ¥ vlastnosÅ¥, pre ktorú neexistuje FID.",'errorLoadingGML':"Chyba pri naÄÃtanà súboru GML ${url}",'browserNotSupported':"Váš prehliadaÄ nepodporuje vykresľovanie vektorov. Momentálne podporované vykresľovaÄe sú:\n${renderers}",'componentShouldBe':"addFeatures: komponent by mal byÅ¥ ${geomType}",'getFeatureError':"getFeatureFromEvent bola zavolaná na vrstve bez vykresľovaÄa. To zvyÄajne znamená, že ste odstránili vrstvu, ale nie niektorú z obslúh, ktorá je s ňou asociovaná.",'minZoomLevelError':"VlastnosÅ¥ minZoomLevel je urÄený iba na použitie s vrstvami odvodenými od FixedZoomLevels. To, že táto wfs vrstva kontroluje minZoomLevel je pozostatok z minulosti. Nemôžeme ho vÅ¡ak odstrániÅ¥, aby sme sa vyhli možnému poruÅ¡eniu aplikácià založených na Open Layers, ktoré na tomto môže závisieÅ¥. Preto ho oznaÄujeme ako zavrhovaný - dolu uvedená kontrola minZoomLevel bude odstránená vo verzii 3.0. Použite prosÃm namiesto toho kontrolu min./max. rozlÃÅ¡enia podľa tu uvedeného popisu: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transakcia WFS: ÚSPEÅ Nà ${response}",'commitFailed':"Transakcia WFS: ZLYHALA ${response}",'googleWarning':"Vrstvu Google nebolo možné správne naÄÃtaÅ¥.\x3cbr\x3e\x3cbr\x3eAby ste sa tejto správy zbavili vyberte novú BaseLayer v prepÃnaÄi vrstiev v pravom hornom rohu.\x3cbr\x3e\x3cbr\x3eToto sa stalo pravdepodobne preto, že skript knižnice Google Maps buÄ nebol naÄÃtaný alebo neobsahuje správny kÄ¾ÃºÄ API pre vaÅ¡u lokalitu.\x3cbr\x3e\x3cbr\x3eVývojári: Tu môžete zÃskaÅ¥ \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3epomoc so sfunkÄnenÃm\x3c/a\x3e",'getLayerWarning':"Vrstvu ${layerType} nebolo možné správne naÄÃtaÅ¥.\x3cbr\x3e\x3cbr\x3eAby ste sa tejto správy zbavili vyberte novú BaseLayer v prepÃnaÄi vrstiev v pravom hornom rohu.\x3cbr\x3e\x3cbr\x3eToto sa stalo pravdepodobne preto, že skript knižnice ${layerType} buÄ nebol naÄÃtaný alebo neobsahuje správny kÄ¾ÃºÄ API pre vaÅ¡u lokalitu.\x3cbr\x3e\x3cbr\x3eVývojári: Tu môžete zÃskaÅ¥ \x3ca href=\'http://trac.openlayers.org/wiki/${layerType}\' target=\'_blank\'\x3epomoc so sfunkÄnenÃm\x3c/a\x3e",'scale':"Mierka = 1 : ${scaleDenom}",'layerAlreadyAdded':"Pokúsili ste sa do mapy pridaÅ¥ vrstvu ${layerName}, ale tá už bola pridaná",'reprojectDeprecated':"PoužÃvate voľby „reproject“ vrstvy ${layerType}. Táto voľba je zzavrhovaná: jej použitie bolo navrhnuté na podporu zobrazovania údajov nad komerÄnými základovými mapami, ale túto funkcionalitu je teraz možné dosiahnuÅ¥ pomocou Spherical Mercator. ÄŽalÅ¡ie informácie zÃskate na stránke http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Táto metóda je zavrhovaná a bude odstránená vo verzii 3.0. Použite prosÃm namiesto nej metódu ${newMethod}.",'boundsAddError':"SÄÃtacej funkcii musÃte daÅ¥ hodnoty x aj y.",'lonlatAddError':"SÄÃtacej funkcii musÃte daÅ¥ hodnoty lon (zem. dĺžka) aj lat (zem. Å¡Ãrka).",'pixelAddError':"SÄÃtacej funkcii musÃte daÅ¥ hodnoty x aj y.",'unsupportedGeometryType':"Nepodporovaný typ geometrie: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition zlyhalo: prvok s id ${elemId} môže byÅ¥ zle umiestnený.",'filterEvaluateNotImplemented':"evaluate nie je implementovaný pre tento typ filtra"});OpenLayers.Lang["te"]=OpenLayers.Util.applyDefaults({'permalink':"à°¸à±à°¥à°¿à°°à°²à°¿à°‚à°•à±",'W':"à°ª",'E':"తూ",'N':"à°‰",'S':"à°¦"});OpenLayers.Lang["vi"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Không xá» lý được phản hồi ${statusText} cho yêu cầu",'permalink':"Liên kết thưá»ng trá»±c",'overlays':"Lấp bản đồ",'baseLayer':"Lá»›p ná»n",'sameProjection':"Bản đồ toà n cảnh chỉ hoạt động khi cùng phép chiếu vá»›i bản đồ chÃnh",'readNotImplemented':"Chưa há»— trợ chức năng Ä‘á»c.",'writeNotImplemented':"Chưa há»— trợ chức năng viết.",'noFID':"Không thể cáºp nháºt tÃnh năng thiếu FID.",'errorLoadingGML':"Lá»—i tải táºp tin GML tại ${url}",'browserNotSupported':"Trình duyệt cá»§a bạn không há»— trợ chức năng vẽ bằng vectÆ¡. Hiện há»— trợ các bá»™ kết xuất:\n${renderers}",'componentShouldBe':"addFeatures: bá»™ pháºn cần phải là ${geomType}",'getFeatureError':"getFeatureFromEvent được gá»i từ lá»›p không có bá»™ kết xuất. Thưá»ng thì có lẽ lá»›p bị xóa nhưng má»™t phần xá» lý cá»§a nó vẫn còn.",'minZoomLevelError':"Chỉ nên sá» dụng thuá»™c tÃnh minZoomLevel vá»›i các lá»›p FixedZoomLevels-descendent. Việc lá»›p wfs nà y tìm cho minZoomLevel là di tÃch còn lại từ xưa. Tuy nhiên, nếu chúng tôi dá»i nó thì sẽ vỡ các chương trình OpenLayers mà dá»±a trên nó. Bởi váºy chúng tôi phản đối sá» dụng nó\x26nbsp;– bước tìm cho minZoomLevel sẽ được dá»i và o phiên bản 3.0. Xin sá» dụng thiết láºp độ phân tÃch tối thiểu / tối Ä‘a thay thế, theo hướng dẫn nà y: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Giao dịch WFS: THÀNH CÔNG ${response}",'commitFailed':"Giao dịch WFS: THẤT BẠI ${response}",'googleWarning':"Không thể tải lá»›p Google đúng đắn.\x3cbr\x3e\x3cbr\x3eÄể tránh thông báo nà y lần sau, hãy chá»n BaseLayer má»›i dùng Ä‘iá»u khiển chá»n lá»›p ở góc trên phải.\x3cbr\x3e\x3cbr\x3eChắc script thư viện Google Maps hoặc không được bao gồm hoặc không chứa khóa API hợp vá»›i website cá»§a bạn.\x3cbr\x3e\x3cbr\x3e\x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eTrợ giúp vá» tÃnh năng nà y\x3c/a\x3e cho ngưá»i phát triển.",'getLayerWarning':"Không thể tải lá»›p ${layerType} đúng đắn.\x3cbr\x3e\x3cbr\x3eÄể tránh thông báo nà y lần sau, hãy chá»n BaseLayer má»›i dùng Ä‘iá»u khiển chá»n lá»›p ở góc trên phải.\x3cbr\x3e\x3cbr\x3eChắc script thư viện ${layerLib} không được bao gồm đúng kiểu.\x3cbr\x3e\x3cbr\x3e\x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eTrợ giúp vá» tÃnh năng nà y\x3c/a\x3e cho ngưá»i phát triển.",'scale':"Tá»· lệ = 1 : ${scaleDenom}",'W':"T",'E':"Ä",'N':"B",'S':"N",'layerAlreadyAdded':"Bạn muốn thêm lá»›p ${layerName} và o bản đồ, nhưng lá»›p nà y đã được thêm",'reprojectDeprecated':"Bạn Ä‘ang áp dụng chế độ “reproject†và o lá»›p ${layerName}. Chế độ nà y đã bị phản đối: nó có mục Ä‘Ãch há»— trợ lấp dữ liệu trên các ná»n bản đồ thương mại; nên thá»±c hiện hiệu ứng đó dùng tÃnh năng Mercator Hình cầu. Có sẵn thêm chi tiết tại http://trac.openlayers.org/wiki/SphericalMercator .",'methodDeprecated':"Phương thức nà y đã bị phản đối và sẽ bị dá»i và o phiên bản 3.0. Xin hãy sá» dụng ${newMethod} thay thế.",'boundsAddError':"Cần phải cho cả giá trị x và y và o hà m add.",'lonlatAddError':"Cần phải cho cả giá trị lon và lat và o hà m add.",'pixelAddError':"Cần phải cho cả giá trị x và y và o hà m add.",'unsupportedGeometryType':"Không há»— trợ kiểu địa lý: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition bị thất bại: nguyên tố vá»›i ID ${elemId} có thể ở chá»— sai.",'filterEvaluateNotImplemented':"chưa há»— trợ evaluate cho loại bá»™ lá»c nà y."});OpenLayers.Popup.AnchoredBubble=OpenLayers.Class(OpenLayers.Popup.Anchored,{rounded:false,initialize:function(id,lonlat,contentSize,contentHTML,anchor,closeBox,closeBoxCallback){this.padding=new OpenLayers.Bounds(0,OpenLayers.Popup.AnchoredBubble.CORNER_SIZE,0,OpenLayers.Popup.AnchoredBubble.CORNER_SIZE);OpenLayers.Popup.Anchored.prototype.initialize.apply(this,arguments);},draw:function(px){OpenLayers.Popup.Anchored.prototype.draw.apply(this,arguments);this.setContentHTML();this.setBackgroundColor();this.setOpacity();return this.div;},updateRelativePosition:function(){this.setRicoCorners();},setSize:function(contentSize){OpenLayers.Popup.Anchored.prototype.setSize.apply(this,arguments);this.setRicoCorners();},setBackgroundColor:function(color){if(color!=undefined){this.backgroundColor=color;} +if(this.div!=null){if(this.contentDiv!=null){this.div.style.background="transparent";OpenLayers.Rico.Corner.changeColor(this.groupDiv,this.backgroundColor);}}},setOpacity:function(opacity){OpenLayers.Popup.Anchored.prototype.setOpacity.call(this,opacity);if(this.div!=null){if(this.groupDiv!=null){OpenLayers.Rico.Corner.changeOpacity(this.groupDiv,this.opacity);}}},setBorder:function(border){this.border=0;},setRicoCorners:function(){var corners=this.getCornersToRound(this.relativePosition);var options={corners:corners,color:this.backgroundColor,bgColor:"transparent",blend:false};if(!this.rounded){OpenLayers.Rico.Corner.round(this.div,options);this.rounded=true;}else{OpenLayers.Rico.Corner.reRound(this.groupDiv,options);this.setBackgroundColor();this.setOpacity();}},getCornersToRound:function(){var corners=['tl','tr','bl','br'];var corner=OpenLayers.Bounds.oppositeQuadrant(this.relativePosition);OpenLayers.Util.removeItem(corners,corner);return corners.join(" ");},CLASS_NAME:"OpenLayers.Popup.AnchoredBubble"});OpenLayers.Popup.AnchoredBubble.CORNER_SIZE=5;OpenLayers.Popup.Framed=OpenLayers.Class(OpenLayers.Popup.Anchored,{imageSrc:null,imageSize:null,isAlphaImage:false,positionBlocks:null,blocks:null,fixedRelativePosition:false,initialize:function(id,lonlat,contentSize,contentHTML,anchor,closeBox,closeBoxCallback){OpenLayers.Popup.Anchored.prototype.initialize.apply(this,arguments);if(this.fixedRelativePosition){this.updateRelativePosition();this.calculateRelativePosition=function(px){return this.relativePosition;};} +this.contentDiv.style.position="absolute";this.contentDiv.style.zIndex=1;if(closeBox){this.closeDiv.style.zIndex=1;} +this.groupDiv.style.position="absolute";this.groupDiv.style.top="0px";this.groupDiv.style.left="0px";this.groupDiv.style.height="100%";this.groupDiv.style.width="100%";},destroy:function(){this.imageSrc=null;this.imageSize=null;this.isAlphaImage=null;this.fixedRelativePosition=false;this.positionBlocks=null;for(var i=0;i<this.blocks.length;i++){var block=this.blocks[i];if(block.image){block.div.removeChild(block.image);} +block.image=null;if(block.div){this.groupDiv.removeChild(block.div);} +block.div=null;} +this.blocks=null;OpenLayers.Popup.Anchored.prototype.destroy.apply(this,arguments);},setBackgroundColor:function(color){},setBorder:function(){},setOpacity:function(opacity){},setSize:function(contentSize){OpenLayers.Popup.Anchored.prototype.setSize.apply(this,arguments);this.updateBlocks();},updateRelativePosition:function(){this.padding=this.positionBlocks[this.relativePosition].padding;if(this.closeDiv){var contentDivPadding=this.getContentDivPadding();this.closeDiv.style.right=contentDivPadding.right+ +this.padding.right+"px";this.closeDiv.style.top=contentDivPadding.top+ +this.padding.top+"px";} +this.updateBlocks();},calculateNewPx:function(px){var newPx=OpenLayers.Popup.Anchored.prototype.calculateNewPx.apply(this,arguments);newPx=newPx.offset(this.positionBlocks[this.relativePosition].offset);return newPx;},createBlocks:function(){this.blocks=[];var firstPosition=null;for(var key in this.positionBlocks){firstPosition=key;break;} +var position=this.positionBlocks[firstPosition];for(var i=0;i<position.blocks.length;i++){var block={};this.blocks.push(block);var divId=this.id+'_FrameDecorationDiv_'+i;block.div=OpenLayers.Util.createDiv(divId,null,null,null,"absolute",null,"hidden",null);var imgId=this.id+'_FrameDecorationImg_'+i;var imageCreator=(this.isAlphaImage)?OpenLayers.Util.createAlphaImageDiv:OpenLayers.Util.createImage;block.image=imageCreator(imgId,null,this.imageSize,this.imageSrc,"absolute",null,null,null);block.div.appendChild(block.image);this.groupDiv.appendChild(block.div);}},updateBlocks:function(){if(!this.blocks){this.createBlocks();} +if(this.size&&this.relativePosition){var position=this.positionBlocks[this.relativePosition];for(var i=0;i<position.blocks.length;i++){var positionBlock=position.blocks[i];var block=this.blocks[i];var l=positionBlock.anchor.left;var b=positionBlock.anchor.bottom;var r=positionBlock.anchor.right;var t=positionBlock.anchor.top;var w=(isNaN(positionBlock.size.w))?this.size.w-(r+l):positionBlock.size.w;var h=(isNaN(positionBlock.size.h))?this.size.h-(b+t):positionBlock.size.h;block.div.style.width=(w<0?0:w)+'px';block.div.style.height=(h<0?0:h)+'px';block.div.style.left=(l!=null)?l+'px':'';block.div.style.bottom=(b!=null)?b+'px':'';block.div.style.right=(r!=null)?r+'px':'';block.div.style.top=(t!=null)?t+'px':'';block.image.style.left=positionBlock.position.x+'px';block.image.style.top=positionBlock.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.Projection=OpenLayers.Class({proj:null,projCode:null,initialize:function(projCode,options){OpenLayers.Util.extend(this,options);this.projCode=projCode;if(window.Proj4js){this.proj=new Proj4js.Proj(projCode);}},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(projection){if(projection&&projection.getCode){return this.getCode()==projection.getCode();}else{return false;}},destroy:function(){delete this.proj;delete this.projCode;},CLASS_NAME:"OpenLayers.Projection"});OpenLayers.Projection.transforms={};OpenLayers.Projection.addTransform=function(from,to,method){if(!OpenLayers.Projection.transforms[from]){OpenLayers.Projection.transforms[from]={};} +OpenLayers.Projection.transforms[from][to]=method;};OpenLayers.Projection.transform=function(point,source,dest){if(source.proj&&dest.proj){point=Proj4js.transform(source.proj,dest.proj,point);}else if(source&&dest&&OpenLayers.Projection.transforms[source.getCode()]&&OpenLayers.Projection.transforms[source.getCode()][dest.getCode()]){OpenLayers.Projection.transforms[source.getCode()][dest.getCode()](point);} +return point;};OpenLayers.Protocol.WFS.v1=OpenLayers.Class(OpenLayers.Protocol,{version:null,srsName:"EPSG:4326",featureType:null,featureNS:null,geometryName:"the_geom",schema:null,featurePrefix:"feature",formatOptions:null,readFormat:null,initialize:function(options){OpenLayers.Protocol.prototype.initialize.apply(this,[options]);if(!options.format){this.format=OpenLayers.Format.WFST(OpenLayers.Util.extend({version:this.version,featureType:this.featureType,featureNS:this.featureNS,featurePrefix:this.featurePrefix,geometryName:this.geometryName,srsName:this.srsName,schema:this.schema},this.formatOptions));} +if(!this.featureNS&&this.featurePrefix){var readNode=this.format.readNode;this.format.readNode=function(node,obj){if(!this.featureNS&&node.prefix==this.featurePrefix){this.featureNS=node.namespaceURI;this.setNamespace("feature",this.featureNS);} +return readNode.apply(this,arguments);};}},destroy:function(){if(this.options&&!this.options.format){this.format.destroy();} +this.format=null;OpenLayers.Protocol.prototype.destroy.apply(this);},read:function(options){OpenLayers.Protocol.prototype.read.apply(this,arguments);options=OpenLayers.Util.extend({},options);OpenLayers.Util.applyDefaults(options,this.options||{});var response=new OpenLayers.Protocol.Response({requestType:"read"});var data=OpenLayers.Format.XML.prototype.write.apply(this.format,[this.format.writeNode("wfs:GetFeature",options)]);response.priv=OpenLayers.Request.POST({url:options.url,callback:this.createCallback(this.handleRead,response,options),params:options.params,headers:options.headers,data:data});return response;},handleRead:function(response,options){if(options.callback){var request=response.priv;if(request.status>=200&&request.status<300){response.features=this.parseFeatures(request);response.code=OpenLayers.Protocol.Response.SUCCESS;}else{response.code=OpenLayers.Protocol.Response.FAILURE;} +options.callback.call(options.scope,response);}},parseFeatures:function(request){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;} +if(!doc||doc.length<=0){return null;} +return(this.readFormat!==null)?this.readFormat.read(doc):this.format.read(doc);},commit:function(features,options){options=OpenLayers.Util.extend({},options);OpenLayers.Util.applyDefaults(options,this.options);var response=new OpenLayers.Protocol.Response({requestType:"commit",reqFeatures:features});response.priv=OpenLayers.Request.POST({url:options.url,data:this.format.write(features,options),callback:this.createCallback(this.handleCommit,response,options)});return response;},handleCommit:function(response,options){if(options.callback){var request=response.priv;var data=request.responseXML;if(!data||!data.documentElement){data=request.responseText;} +var obj=this.format.read(data)||{};response.insertIds=obj.insertIds||[];response.code=(obj.success)?OpenLayers.Protocol.Response.SUCCESS:OpenLayers.Protocol.Response.FAILURE;options.callback.call(options.scope,response);}},filterDelete:function(filter,options){options=OpenLayers.Util.extend({},options);OpenLayers.Util.applyDefaults(options,this.options);var response=new OpenLayers.Protocol.Response({requestType:"commit"});var root=this.format.createElementNSPlus("wfs:Transaction",{attributes:{service:"WFS",version:this.version}});var deleteNode=this.format.createElementNSPlus("wfs:Delete",{attributes:{typeName:(options.featureNS?this.featurePrefix+":":"")+ +options.featureType}});if(options.featureNS){deleteNode.setAttribute("xmlns:"+this.featurePrefix,options.featureNS);} +var filterNode=this.format.writeNode("ogc:Filter",filter);deleteNode.appendChild(filterNode);root.appendChild(deleteNode);var data=OpenLayers.Format.XML.prototype.write.apply(this.format,[root]);return OpenLayers.Request.POST({url:this.url,callback:options.callback||function(){},data:data});},abort:function(response){if(response){response.priv.abort();}},CLASS_NAME:"OpenLayers.Protocol.WFS.v1"});OpenLayers.Renderer.SVG=OpenLayers.Class(OpenLayers.Renderer.Elements,{xmlns:"http://www.w3.org/2000/svg",xlinkns:"http://www.w3.org/1999/xlink",MAX_PIXEL:15000,translationParameters:null,symbolMetrics:null,isGecko:null,supportUse:null,initialize:function(containerID){if(!this.supported()){return;} +OpenLayers.Renderer.Elements.prototype.initialize.apply(this,arguments);this.translationParameters={x:0,y:0};this.supportUse=(navigator.userAgent.toLowerCase().indexOf("applewebkit/5")==-1);this.isGecko=(navigator.userAgent.toLowerCase().indexOf("gecko/")!=-1);this.symbolMetrics={};},destroy:function(){OpenLayers.Renderer.Elements.prototype.destroy.apply(this,arguments);},supported:function(){var svgFeature="http://www.w3.org/TR/SVG11/feature#";return(document.implementation&&(document.implementation.hasFeature("org.w3c.svg","1.0")||document.implementation.hasFeature(svgFeature+"SVG","1.1")||document.implementation.hasFeature(svgFeature+"BasicStructure","1.1")));},inValidRange:function(x,y,xyOnly){var left=x+(xyOnly?0:this.translationParameters.x);var top=y+(xyOnly?0:this.translationParameters.y);return(left>=-this.MAX_PIXEL&&left<=this.MAX_PIXEL&&top>=-this.MAX_PIXEL&&top<=this.MAX_PIXEL);},setExtent:function(extent,resolutionChanged){OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,arguments);var resolution=this.getResolution();var left=-extent.left/resolution;var top=extent.top/resolution;if(resolutionChanged){this.left=left;this.top=top;var extentString="0 0 "+this.size.w+" "+this.size.h;this.rendererRoot.setAttributeNS(null,"viewBox",extentString);this.translate(0,0);return true;}else{var inRange=this.translate(left-this.left,top-this.top);if(!inRange){this.setExtent(extent,true);} +return inRange;}},translate:function(x,y){if(!this.inValidRange(x,y,true)){return false;}else{var transformString="";if(x||y){transformString="translate("+x+","+y+")";} +this.root.setAttributeNS(null,"transform",transformString);this.translationParameters={x:x,y:y};return true;}},setSize:function(size){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(geometry,style){var nodeType=null;switch(geometry.CLASS_NAME){case"OpenLayers.Geometry.Point":if(style.externalGraphic){nodeType="image";}else if(this.isComplexSymbol(style.graphicName)){nodeType=this.supportUse===false?"svg":"use";}else{nodeType="circle";} +break;case"OpenLayers.Geometry.Rectangle":nodeType="rect";break;case"OpenLayers.Geometry.LineString":nodeType="polyline";break;case"OpenLayers.Geometry.LinearRing":nodeType="polygon";break;case"OpenLayers.Geometry.Polygon":case"OpenLayers.Geometry.Curve":case"OpenLayers.Geometry.Surface":nodeType="path";break;default:break;} +return nodeType;},setStyle:function(node,style,options){style=style||node._style;options=options||node._options;var r=parseFloat(node.getAttributeNS(null,"r"));var widthFactor=1;var pos;if(node._geometryClass=="OpenLayers.Geometry.Point"&&r){node.style.visibility="";if(style.graphic===false){node.style.visibility="hidden";}else if(style.externalGraphic){pos=this.getPosition(node);if(style.graphicTitle){node.setAttributeNS(null,"title",style.graphicTitle);} +if(style.graphicWidth&&style.graphicHeight){node.setAttributeNS(null,"preserveAspectRatio","none");} +var width=style.graphicWidth||style.graphicHeight;var height=style.graphicHeight||style.graphicWidth;width=width?width:style.pointRadius*2;height=height?height:style.pointRadius*2;var xOffset=(style.graphicXOffset!=undefined)?style.graphicXOffset:-(0.5*width);var yOffset=(style.graphicYOffset!=undefined)?style.graphicYOffset:-(0.5*height);var opacity=style.graphicOpacity||style.fillOpacity;node.setAttributeNS(null,"x",(pos.x+xOffset).toFixed());node.setAttributeNS(null,"y",(pos.y+yOffset).toFixed());node.setAttributeNS(null,"width",width);node.setAttributeNS(null,"height",height);node.setAttributeNS(this.xlinkns,"href",style.externalGraphic);node.setAttributeNS(null,"style","opacity: "+opacity);}else if(this.isComplexSymbol(style.graphicName)){var offset=style.pointRadius*3;var size=offset*2;var id=this.importSymbol(style.graphicName);pos=this.getPosition(node);widthFactor=this.symbolMetrics[id][0]*3/size;var parent=node.parentNode;var nextSibling=node.nextSibling;if(parent){parent.removeChild(node);} +if(this.supportUse===false){var src=document.getElementById(id);node.firstChild&&node.removeChild(node.firstChild);node.appendChild(src.firstChild.cloneNode(true));node.setAttributeNS(null,"viewBox",src.getAttributeNS(null,"viewBox"));}else{node.setAttributeNS(this.xlinkns,"href","#"+id);} +node.setAttributeNS(null,"width",size);node.setAttributeNS(null,"height",size);node.setAttributeNS(null,"x",pos.x-offset);node.setAttributeNS(null,"y",pos.y-offset);if(nextSibling){parent.insertBefore(node,nextSibling);}else if(parent){parent.appendChild(node);}}else{node.setAttributeNS(null,"r",style.pointRadius);} +var rotation=style.rotation;if((rotation!==undefined||node._rotation!==undefined)&&pos){node._rotation=rotation;rotation|=0;if(node.nodeName!=="svg"){node.setAttributeNS(null,"transform","rotate("+rotation+" "+pos.x+" "+ +pos.y+")");}else{var metrics=this.symbolMetrics[id];node.firstChild.setAttributeNS(null,"transform","rotate("+style.rotation+" "+metrics[1]+" "+metrics[2]+")");}}} +if(options.isFilled){node.setAttributeNS(null,"fill",style.fillColor);node.setAttributeNS(null,"fill-opacity",style.fillOpacity);}else{node.setAttributeNS(null,"fill","none");} +if(options.isStroked){node.setAttributeNS(null,"stroke",style.strokeColor);node.setAttributeNS(null,"stroke-opacity",style.strokeOpacity);node.setAttributeNS(null,"stroke-width",style.strokeWidth*widthFactor);node.setAttributeNS(null,"stroke-linecap",style.strokeLinecap||"round");node.setAttributeNS(null,"stroke-linejoin","round");style.strokeDashstyle&&node.setAttributeNS(null,"stroke-dasharray",this.dashStyle(style,widthFactor));}else{node.setAttributeNS(null,"stroke","none");} +if(style.pointerEvents){node.setAttributeNS(null,"pointer-events",style.pointerEvents);} +if(style.cursor!=null){node.setAttributeNS(null,"cursor",style.cursor);} +return node;},dashStyle:function(style,widthFactor){var w=style.strokeWidth*widthFactor;var str=style.strokeDashstyle;switch(str){case'solid':return'none';case'dot':return[1,4*w].join();case'dash':return[4*w,4*w].join();case'dashdot':return[4*w,4*w,1,4*w].join();case'longdash':return[8*w,4*w].join();case'longdashdot':return[8*w,4*w,1,4*w].join();default:return OpenLayers.String.trim(str).replace(/\s+/g,",");}},createNode:function(type,id){var node=document.createElementNS(this.xmlns,type);if(id){node.setAttributeNS(null,"id",id);} +return node;},nodeTypeCompare:function(node,type){return(type==node.nodeName);},createRenderRoot:function(){return this.nodeFactory(this.container.id+"_svgRoot","svg");},createRoot:function(suffix){return this.nodeFactory(this.container.id+suffix,"g");},createDefs:function(){var defs=this.nodeFactory(this.container.id+"_defs","defs");this.rendererRoot.appendChild(defs);return defs;},drawPoint:function(node,geometry){return this.drawCircle(node,geometry,1);},drawCircle:function(node,geometry,radius){var resolution=this.getResolution();var x=(geometry.x/resolution+this.left);var y=(this.top-geometry.y/resolution);if(this.inValidRange(x,y)){node.setAttributeNS(null,"cx",x);node.setAttributeNS(null,"cy",y);node.setAttributeNS(null,"r",radius);return node;}else{return false;}},drawLineString:function(node,geometry){var componentsResult=this.getComponentsString(geometry.components);if(componentsResult.path){node.setAttributeNS(null,"points",componentsResult.path);return(componentsResult.complete?node:null);}else{return false;}},drawLinearRing:function(node,geometry){var componentsResult=this.getComponentsString(geometry.components);if(componentsResult.path){node.setAttributeNS(null,"points",componentsResult.path);return(componentsResult.complete?node:null);}else{return false;}},drawPolygon:function(node,geometry){var d="";var draw=true;var complete=true;var linearRingResult,path;for(var j=0,len=geometry.components.length;j<len;j++){d+=" M";linearRingResult=this.getComponentsString(geometry.components[j].components," ");path=linearRingResult.path;if(path){d+=" "+path;complete=linearRingResult.complete&&complete;}else{draw=false;}} +d+=" z";if(draw){node.setAttributeNS(null,"d",d);node.setAttributeNS(null,"fill-rule","evenodd");return complete?node:null;}else{return false;}},drawRectangle:function(node,geometry){var resolution=this.getResolution();var x=(geometry.x/resolution+this.left);var y=(this.top-geometry.y/resolution);if(this.inValidRange(x,y)){node.setAttributeNS(null,"x",x);node.setAttributeNS(null,"y",y);node.setAttributeNS(null,"width",geometry.width/resolution);node.setAttributeNS(null,"height",geometry.height/resolution);return node;}else{return false;}},drawSurface:function(node,geometry){var d=null;var draw=true;for(var i=0,len=geometry.components.length;i<len;i++){if((i%3)==0&&(i/3)==0){var component=this.getShortString(geometry.components[i]);if(!component){draw=false;} +d="M "+component;}else if((i%3)==1){var component=this.getShortString(geometry.components[i]);if(!component){draw=false;} +d+=" C "+component;}else{var component=this.getShortString(geometry.components[i]);if(!component){draw=false;} +d+=" "+component;}} +d+=" Z";if(draw){node.setAttributeNS(null,"d",d);return node;}else{return false;}},drawText:function(featureId,style,location){var resolution=this.getResolution();var x=(location.x/resolution+this.left);var y=(location.y/resolution-this.top);var label=this.nodeFactory(featureId+this.LABEL_ID_SUFFIX,"text");var tspan=this.nodeFactory(featureId+this.LABEL_ID_SUFFIX+"_tspan","tspan");label.setAttributeNS(null,"x",x);label.setAttributeNS(null,"y",-y);if(style.fontColor){label.setAttributeNS(null,"fill",style.fontColor);} +if(style.fontOpacity){label.setAttributeNS(null,"opacity",style.fontOpacity);} +if(style.fontFamily){label.setAttributeNS(null,"font-family",style.fontFamily);} +if(style.fontSize){label.setAttributeNS(null,"font-size",style.fontSize);} +if(style.fontWeight){label.setAttributeNS(null,"font-weight",style.fontWeight);} +if(style.labelSelect===true){label.setAttributeNS(null,"pointer-events","visible");label._featureId=featureId;tspan._featureId=featureId;tspan._geometry=location;tspan._geometryClass=location.CLASS_NAME;}else{label.setAttributeNS(null,"pointer-events","none");} +var align=style.labelAlign||"cm";label.setAttributeNS(null,"text-anchor",OpenLayers.Renderer.SVG.LABEL_ALIGN[align[0]]||"middle");if(this.isGecko){label.setAttributeNS(null,"dominant-baseline",OpenLayers.Renderer.SVG.LABEL_ALIGN[align[1]]||"central");}else{tspan.setAttributeNS(null,"baseline-shift",OpenLayers.Renderer.SVG.LABEL_VSHIFT[align[1]]||"-35%");} +tspan.textContent=style.label;if(!label.parentNode){label.appendChild(tspan);this.textRoot.appendChild(label);}},getComponentsString:function(components,separator){var renderCmp=[];var complete=true;var len=components.length;var strings=[];var str,component;for(var i=0;i<len;i++){component=components[i];renderCmp.push(component);str=this.getShortString(component);if(str){strings.push(str);}else{if(i>0){if(this.getShortString(components[i-1])){strings.push(this.clipLine(components[i],components[i-1]));}} +if(i<len-1){if(this.getShortString(components[i+1])){strings.push(this.clipLine(components[i],components[i+1]));}} +complete=false;}} +return{path:strings.join(separator||","),complete:complete};},clipLine:function(badComponent,goodComponent){if(goodComponent.equals(badComponent)){return"";} +var resolution=this.getResolution();var maxX=this.MAX_PIXEL-this.translationParameters.x;var maxY=this.MAX_PIXEL-this.translationParameters.y;var x1=goodComponent.x/resolution+this.left;var y1=this.top-goodComponent.y/resolution;var x2=badComponent.x/resolution+this.left;var y2=this.top-badComponent.y/resolution;var k;if(x2<-maxX||x2>maxX){k=(y2-y1)/(x2-x1);x2=x2<0?-maxX:maxX;y2=y1+(x2-x1)*k;} +if(y2<-maxY||y2>maxY){k=(x2-x1)/(y2-y1);y2=y2<0?-maxY:maxY;x2=x1+(y2-y1)*k;} +return x2+","+y2;},getShortString:function(point){var resolution=this.getResolution();var x=(point.x/resolution+this.left);var y=(this.top-point.y/resolution);if(this.inValidRange(x,y)){return x+","+y;}else{return false;}},getPosition:function(node){return({x:parseFloat(node.getAttributeNS(null,"cx")),y:parseFloat(node.getAttributeNS(null,"cy"))});},importSymbol:function(graphicName){if(!this.defs){this.defs=this.createDefs();} +var id=this.container.id+"-"+graphicName;if(document.getElementById(id)!=null){return id;} +var symbol=OpenLayers.Renderer.symbol[graphicName];if(!symbol){throw new Error(graphicName+' is not a valid symbol name');} +var symbolNode=this.nodeFactory(id,"symbol");var node=this.nodeFactory(null,"polygon");symbolNode.appendChild(node);var symbolExtent=new OpenLayers.Bounds(Number.MAX_VALUE,Number.MAX_VALUE,0,0);var points=[];var x,y;for(var i=0;i<symbol.length;i=i+2){x=symbol[i];y=symbol[i+1];symbolExtent.left=Math.min(symbolExtent.left,x);symbolExtent.bottom=Math.min(symbolExtent.bottom,y);symbolExtent.right=Math.max(symbolExtent.right,x);symbolExtent.top=Math.max(symbolExtent.top,y);points.push(x,",",y);} +node.setAttributeNS(null,"points",points.join(" "));var width=symbolExtent.getWidth();var height=symbolExtent.getHeight();var viewBox=[symbolExtent.left-width,symbolExtent.bottom-height,width*3,height*3];symbolNode.setAttributeNS(null,"viewBox",viewBox.join(" "));this.symbolMetrics[id]=[Math.max(width,height),symbolExtent.getCenterLonLat().lon,symbolExtent.getCenterLonLat().lat];this.defs.appendChild(symbolNode);return symbolNode.id;},getFeatureIdFromEvent:function(evt){var featureId=OpenLayers.Renderer.Elements.prototype.getFeatureIdFromEvent.apply(this,arguments);if(this.supportUse===false&&!featureId){var target=evt.target;featureId=target.parentNode&&target!=this.rendererRoot&&target.parentNode._featureId;} +return featureId;},CLASS_NAME:"OpenLayers.Renderer.SVG"});OpenLayers.Renderer.SVG.LABEL_ALIGN={"l":"start","r":"end","b":"bottom","t":"hanging"};OpenLayers.Renderer.SVG.LABEL_VSHIFT={"t":"-70%","b":"0"};OpenLayers.Renderer.VML=OpenLayers.Class(OpenLayers.Renderer.Elements,{xmlns:"urn:schemas-microsoft-com:vml",symbolCache:{},offset:null,initialize:function(containerID){if(!this.supported()){return;} +if(!document.namespaces.olv){document.namespaces.add("olv",this.xmlns);var style=document.createStyleSheet();var shapes=['shape','rect','oval','fill','stroke','imagedata','group','textbox'];for(var i=0,len=shapes.length;i<len;i++){style.addRule('olv\\:'+shapes[i],"behavior: url(#default#VML); "+"position: absolute; display: inline-block;");}} +OpenLayers.Renderer.Elements.prototype.initialize.apply(this,arguments);},destroy:function(){OpenLayers.Renderer.Elements.prototype.destroy.apply(this,arguments);},supported:function(){return!!(document.namespaces);},setExtent:function(extent,resolutionChanged){OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,arguments);var resolution=this.getResolution();var left=(extent.left/resolution)|0;var top=(extent.top/resolution-this.size.h)|0;if(resolutionChanged||!this.offset){this.offset={x:left,y:top};left=0;top=0;}else{left=left-this.offset.x;top=top-this.offset.y;} +var org=left+" "+top;this.root.coordorigin=org;var roots=[this.root,this.vectorRoot,this.textRoot];var root;for(var i=0,len=roots.length;i<len;++i){root=roots[i];var size=this.size.w+" "+this.size.h;root.coordsize=size;} +this.root.style.flip="y";return true;},setSize:function(size){OpenLayers.Renderer.prototype.setSize.apply(this,arguments);var roots=[this.rendererRoot,this.root,this.vectorRoot,this.textRoot];var w=this.size.w+"px";var h=this.size.h+"px";var root;for(var i=0,len=roots.length;i<len;++i){root=roots[i];root.style.width=w;root.style.height=h;}},getNodeType:function(geometry,style){var nodeType=null;switch(geometry.CLASS_NAME){case"OpenLayers.Geometry.Point":if(style.externalGraphic){nodeType="olv:rect";}else if(this.isComplexSymbol(style.graphicName)){nodeType="olv:shape";}else{nodeType="olv:oval";} +break;case"OpenLayers.Geometry.Rectangle":nodeType="olv:rect";break;case"OpenLayers.Geometry.LineString":case"OpenLayers.Geometry.LinearRing":case"OpenLayers.Geometry.Polygon":case"OpenLayers.Geometry.Curve":case"OpenLayers.Geometry.Surface":nodeType="olv:shape";break;default:break;} +return nodeType;},setStyle:function(node,style,options,geometry){style=style||node._style;options=options||node._options;var fillColor=style.fillColor;if(node._geometryClass==="OpenLayers.Geometry.Point"){if(style.externalGraphic){if(style.graphicTitle){node.title=style.graphicTitle;} +var width=style.graphicWidth||style.graphicHeight;var height=style.graphicHeight||style.graphicWidth;width=width?width:style.pointRadius*2;height=height?height:style.pointRadius*2;var resolution=this.getResolution();var xOffset=(style.graphicXOffset!=undefined)?style.graphicXOffset:-(0.5*width);var yOffset=(style.graphicYOffset!=undefined)?style.graphicYOffset:-(0.5*height);node.style.left=(((geometry.x/resolution-this.offset.x)+xOffset)|0)+"px";node.style.top=(((geometry.y/resolution-this.offset.y)-(yOffset+height))|0)+"px";node.style.width=width+"px";node.style.height=height+"px";node.style.flip="y";fillColor="none";options.isStroked=false;}else if(this.isComplexSymbol(style.graphicName)){var cache=this.importSymbol(style.graphicName);node.path=cache.path;node.coordorigin=cache.left+","+cache.bottom;var size=cache.size;node.coordsize=size+","+size;this.drawCircle(node,geometry,style.pointRadius);node.style.flip="y";}else{this.drawCircle(node,geometry,style.pointRadius);}} +if(options.isFilled){node.fillcolor=fillColor;}else{node.filled="false";} +var fills=node.getElementsByTagName("fill");var fill=(fills.length==0)?null:fills[0];if(!options.isFilled){if(fill){node.removeChild(fill);}}else{if(!fill){fill=this.createNode('olv:fill',node.id+"_fill");} +fill.opacity=style.fillOpacity;if(node._geometryClass==="OpenLayers.Geometry.Point"&&style.externalGraphic){if(style.graphicOpacity){fill.opacity=style.graphicOpacity;} +fill.src=style.externalGraphic;fill.type="frame";if(!(style.graphicWidth&&style.graphicHeight)){fill.aspect="atmost";}} +if(fill.parentNode!=node){node.appendChild(fill);}} +var rotation=style.rotation;if((rotation!==undefined||node._rotation!==undefined)){node._rotation=rotation;if(style.externalGraphic){this.graphicRotate(node,xOffset,yOffset,style);fill.opacity=0;}else if(node._geometryClass==="OpenLayers.Geometry.Point"){node.style.rotation=rotation||0;}} +var strokes=node.getElementsByTagName("stroke");var stroke=(strokes.length==0)?null:strokes[0];if(!options.isStroked){node.stroked=false;if(stroke){stroke.on=false;}}else{if(!stroke){stroke=this.createNode('olv:stroke',node.id+"_stroke");node.appendChild(stroke);} +stroke.on=true;stroke.color=style.strokeColor;stroke.weight=style.strokeWidth+"px";stroke.opacity=style.strokeOpacity;stroke.endcap=style.strokeLinecap=='butt'?'flat':(style.strokeLinecap||'round');if(style.strokeDashstyle){stroke.dashstyle=this.dashStyle(style);}} +if(style.cursor!="inherit"&&style.cursor!=null){node.style.cursor=style.cursor;} +return node;},graphicRotate:function(node,xOffset,yOffset,style){var style=style||node._style;var rotation=style.rotation||0;var aspectRatio,size;if(!(style.graphicWidth&&style.graphicHeight)){var img=new Image();img.onreadystatechange=OpenLayers.Function.bind(function(){if(img.readyState=="complete"||img.readyState=="interactive"){aspectRatio=img.width/img.height;size=Math.max(style.pointRadius*2,style.graphicWidth||0,style.graphicHeight||0);xOffset=xOffset*aspectRatio;style.graphicWidth=size*aspectRatio;style.graphicHeight=size;this.graphicRotate(node,xOffset,yOffset,style);}},this);img.src=style.externalGraphic;return;}else{size=Math.max(style.graphicWidth,style.graphicHeight);aspectRatio=style.graphicWidth/style.graphicHeight;} +var width=Math.round(style.graphicWidth||size*aspectRatio);var height=Math.round(style.graphicHeight||size);node.style.width=width+"px";node.style.height=height+"px";var image=document.getElementById(node.id+"_image");if(!image){image=this.createNode("olv:imagedata",node.id+"_image");node.appendChild(image);} +image.style.width=width+"px";image.style.height=height+"px";image.src=style.externalGraphic;image.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader("+"src='', sizingMethod='scale')";var rot=rotation*Math.PI/180;var sintheta=Math.sin(rot);var costheta=Math.cos(rot);var filter="progid:DXImageTransform.Microsoft.Matrix(M11="+costheta+",M12="+(-sintheta)+",M21="+sintheta+",M22="+costheta+",SizingMethod='auto expand')\n";var opacity=style.graphicOpacity||style.fillOpacity;if(opacity&&opacity!=1){filter+="progid:DXImageTransform.Microsoft.BasicImage(opacity="+ +opacity+")\n";} +node.style.filter=filter;var centerPoint=new OpenLayers.Geometry.Point(-xOffset,-yOffset);var imgBox=new OpenLayers.Bounds(0,0,width,height).toGeometry();imgBox.rotate(style.rotation,centerPoint);var imgBounds=imgBox.getBounds();node.style.left=Math.round(parseInt(node.style.left)+imgBounds.left)+"px";node.style.top=Math.round(parseInt(node.style.top)-imgBounds.bottom)+"px";},postDraw:function(node){node.style.visibility="visible";var fillColor=node._style.fillColor;var strokeColor=node._style.strokeColor;if(fillColor=="none"&&node.fillcolor!=fillColor){node.fillcolor=fillColor;} +if(strokeColor=="none"&&node.strokecolor!=strokeColor){node.strokecolor=strokeColor;}},setNodeDimension:function(node,geometry){var bbox=geometry.getBounds();if(bbox){var resolution=this.getResolution();var scaledBox=new OpenLayers.Bounds((bbox.left/resolution-this.offset.x)|0,(bbox.bottom/resolution-this.offset.y)|0,(bbox.right/resolution-this.offset.x)|0,(bbox.top/resolution-this.offset.y)|0);node.style.left=scaledBox.left+"px";node.style.top=scaledBox.top+"px";node.style.width=scaledBox.getWidth()+"px";node.style.height=scaledBox.getHeight()+"px";node.coordorigin=scaledBox.left+" "+scaledBox.top;node.coordsize=scaledBox.getWidth()+" "+scaledBox.getHeight();}},dashStyle:function(style){var dash=style.strokeDashstyle;switch(dash){case'solid':case'dot':case'dash':case'dashdot':case'longdash':case'longdashdot':return dash;default:var parts=dash.split(/[ ,]/);if(parts.length==2){if(1*parts[0]>=2*parts[1]){return"longdash";} +return(parts[0]==1||parts[1]==1)?"dot":"dash";}else if(parts.length==4){return(1*parts[0]>=2*parts[1])?"longdashdot":"dashdot";} +return"solid";}},createNode:function(type,id){var node=document.createElement(type);if(id){node.id=id;} +node.unselectable='on';node.onselectstart=OpenLayers.Function.False;return node;},nodeTypeCompare:function(node,type){var subType=type;var splitIndex=subType.indexOf(":");if(splitIndex!=-1){subType=subType.substr(splitIndex+1);} +var nodeName=node.nodeName;splitIndex=nodeName.indexOf(":");if(splitIndex!=-1){nodeName=nodeName.substr(splitIndex+1);} +return(subType==nodeName);},createRenderRoot:function(){return this.nodeFactory(this.container.id+"_vmlRoot","div");},createRoot:function(suffix){return this.nodeFactory(this.container.id+suffix,"olv:group");},drawPoint:function(node,geometry){return this.drawCircle(node,geometry,1);},drawCircle:function(node,geometry,radius){if(!isNaN(geometry.x)&&!isNaN(geometry.y)){var resolution=this.getResolution();node.style.left=(((geometry.x/resolution-this.offset.x)|0)-radius)+"px";node.style.top=(((geometry.y/resolution-this.offset.y)|0)-radius)+"px";var diameter=radius*2;node.style.width=diameter+"px";node.style.height=diameter+"px";return node;} +return false;},drawLineString:function(node,geometry){return this.drawLine(node,geometry,false);},drawLinearRing:function(node,geometry){return this.drawLine(node,geometry,true);},drawLine:function(node,geometry,closeLine){this.setNodeDimension(node,geometry);var resolution=this.getResolution();var numComponents=geometry.components.length;var parts=new Array(numComponents);var comp,x,y;for(var i=0;i<numComponents;i++){comp=geometry.components[i];x=(comp.x/resolution-this.offset.x)|0;y=(comp.y/resolution-this.offset.y)|0;parts[i]=" "+x+","+y+" l ";} +var end=(closeLine)?" x e":" e";node.path="m"+parts.join("")+end;return node;},drawPolygon:function(node,geometry){this.setNodeDimension(node,geometry);var resolution=this.getResolution();var path=[];var linearRing,i,j,len,ilen,comp,x,y;for(j=0,len=geometry.components.length;j<len;j++){linearRing=geometry.components[j];path.push("m");for(i=0,ilen=linearRing.components.length;i<ilen;i++){comp=linearRing.components[i];x=(comp.x/resolution-this.offset.x)|0;y=(comp.y/resolution-this.offset.y)|0;path.push(" "+x+","+y);if(i==0){path.push(" l");}} +path.push(" x ");} +path.push("e");node.path=path.join("");return node;},drawRectangle:function(node,geometry){var resolution=this.getResolution();node.style.left=((geometry.x/resolution-this.offset.x)|0)+"px";node.style.top=((geometry.y/resolution-this.offset.y)|0)+"px";node.style.width=((geometry.width/resolution)|0)+"px";node.style.height=((geometry.height/resolution)|0)+"px";return node;},drawText:function(featureId,style,location){var label=this.nodeFactory(featureId+this.LABEL_ID_SUFFIX,"olv:rect");var textbox=this.nodeFactory(featureId+this.LABEL_ID_SUFFIX+"_textbox","olv:textbox");var resolution=this.getResolution();label.style.left=((location.x/resolution-this.offset.x)|0)+"px";label.style.top=((location.y/resolution-this.offset.y)|0)+"px";label.style.flip="y";textbox.innerText=style.label;if(style.fontColor){textbox.style.color=style.fontColor;} +if(style.fontOpacity){textbox.style.filter='alpha(opacity='+(style.fontOpacity*100)+')';} +if(style.fontFamily){textbox.style.fontFamily=style.fontFamily;} +if(style.fontSize){textbox.style.fontSize=style.fontSize;} +if(style.fontWeight){textbox.style.fontWeight=style.fontWeight;} +if(style.labelSelect===true){label._featureId=featureId;textbox._featureId=featureId;textbox._geometry=location;textbox._geometryClass=location.CLASS_NAME;} +textbox.style.whiteSpace="nowrap";textbox.inset="1px,0px,0px,0px";if(!label.parentNode){label.appendChild(textbox);this.textRoot.appendChild(label);} +var align=style.labelAlign||"cm";if(align.length==1){align+="m";} +var xshift=textbox.clientWidth*(OpenLayers.Renderer.VML.LABEL_SHIFT[align.substr(0,1)]);var yshift=textbox.clientHeight*(OpenLayers.Renderer.VML.LABEL_SHIFT[align.substr(1,1)]);label.style.left=parseInt(label.style.left)-xshift-1+"px";label.style.top=parseInt(label.style.top)+yshift+"px";},drawSurface:function(node,geometry){this.setNodeDimension(node,geometry);var resolution=this.getResolution();var path=[];var comp,x,y;for(var i=0,len=geometry.components.length;i<len;i++){comp=geometry.components[i];x=(comp.x/resolution-this.offset.x)|0;y=(comp.y/resolution-this.offset.y)|0;if((i%3)==0&&(i/3)==0){path.push("m");}else if((i%3)==1){path.push(" c");} +path.push(" "+x+","+y);} +path.push(" x e");node.path=path.join("");return node;},moveRoot:function(renderer){var layer=this.map.getLayer(renderer.container.id);if(layer instanceof OpenLayers.Layer.Vector.RootContainer){layer=this.map.getLayer(this.container.id);} +layer&&layer.renderer.clear();OpenLayers.Renderer.Elements.prototype.moveRoot.apply(this,arguments);layer&&layer.redraw();},importSymbol:function(graphicName){var id=this.container.id+"-"+graphicName;var cache=this.symbolCache[id];if(cache){return cache;} +var symbol=OpenLayers.Renderer.symbol[graphicName];if(!symbol){throw new Error(graphicName+' is not a valid symbol name');} +var symbolExtent=new OpenLayers.Bounds(Number.MAX_VALUE,Number.MAX_VALUE,0,0);var pathitems=["m"];for(var i=0;i<symbol.length;i=i+2){var x=symbol[i];var y=symbol[i+1];symbolExtent.left=Math.min(symbolExtent.left,x);symbolExtent.bottom=Math.min(symbolExtent.bottom,y);symbolExtent.right=Math.max(symbolExtent.right,x);symbolExtent.top=Math.max(symbolExtent.top,y);pathitems.push(x);pathitems.push(y);if(i==0){pathitems.push("l");}} +pathitems.push("x e");var path=pathitems.join(" ");var diff=(symbolExtent.getWidth()-symbolExtent.getHeight())/2;if(diff>0){symbolExtent.bottom=symbolExtent.bottom-diff;symbolExtent.top=symbolExtent.top+diff;}else{symbolExtent.left=symbolExtent.left+diff;symbolExtent.right=symbolExtent.right-diff;} +cache={path:path,size:symbolExtent.getWidth(),left:symbolExtent.left,bottom:symbolExtent.bottom};this.symbolCache[id]=cache;return cache;},CLASS_NAME:"OpenLayers.Renderer.VML"});OpenLayers.Renderer.VML.LABEL_SHIFT={"l":0,"c":.5,"r":1,"t":0,"m":.5,"b":1};OpenLayers.Tile=OpenLayers.Class({EVENT_TYPES:["loadstart","loadend","reload","unload"],events:null,id:null,layer:null,url:null,bounds:null,size:null,position:null,isLoading:false,initialize:function(layer,position,bounds,url,size){this.layer=layer;this.position=position.clone();this.bounds=bounds.clone();this.url=url;this.size=size.clone();this.id=OpenLayers.Util.createUniqueID("Tile_");this.events=new OpenLayers.Events(this,null,this.EVENT_TYPES);},unload:function(){if(this.isLoading){this.isLoading=false;this.events.triggerEvent("unload");}},destroy:function(){this.layer=null;this.bounds=null;this.size=null;this.position=null;this.events.destroy();this.events=null;},clone:function(obj){if(obj==null){obj=new OpenLayers.Tile(this.layer,this.position,this.bounds,this.url,this.size);} +OpenLayers.Util.applyDefaults(obj,this);return obj;},draw:function(){var maxExtent=this.layer.maxExtent;var withinMaxExtent=(maxExtent&&this.bounds.intersectsBounds(maxExtent,false));this.shouldDraw=(withinMaxExtent||this.layer.displayOutsideMaxExtent);this.clear();return this.shouldDraw;},moveTo:function(bounds,position,redraw){if(redraw==null){redraw=true;} +this.bounds=bounds.clone();this.position=position.clone();if(redraw){this.draw();}},clear:function(){},getBoundsFromBaseLayer:function(position){var msg=OpenLayers.i18n('reprojectDeprecated',{'layerName':this.layer.name});OpenLayers.Console.warn(msg);var topLeft=this.layer.map.getLonLatFromLayerPx(position);var bottomRightPx=position.clone();bottomRightPx.x+=this.size.w;bottomRightPx.y+=this.size.h;var bottomRight=this.layer.map.getLonLatFromLayerPx(bottomRightPx);if(topLeft.lon>bottomRight.lon){if(topLeft.lon<0){topLeft.lon=-180-(topLeft.lon+180);}else{bottomRight.lon=180+bottomRight.lon+180;}} +var bounds=new OpenLayers.Bounds(topLeft.lon,bottomRight.lat,bottomRight.lon,topLeft.lat);return bounds;},showTile:function(){if(this.shouldDraw){this.show();}},show:function(){},hide:function(){},CLASS_NAME:"OpenLayers.Tile"});OpenLayers.Control.MouseToolbar=OpenLayers.Class(OpenLayers.Control.MouseDefaults,{mode:null,buttons:null,direction:"vertical",buttonClicked:null,initialize:function(position,direction){OpenLayers.Control.prototype.initialize.apply(this,arguments);this.position=new OpenLayers.Pixel(OpenLayers.Control.MouseToolbar.X,OpenLayers.Control.MouseToolbar.Y);if(position){this.position=position;} +if(direction){this.direction=direction;} +this.measureDivs=[];},destroy:function(){for(var btnId in this.buttons){var btn=this.buttons[btnId];btn.map=null;btn.events.destroy();} +OpenLayers.Control.MouseDefaults.prototype.destroy.apply(this,arguments);},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);OpenLayers.Control.MouseDefaults.prototype.draw.apply(this,arguments);this.buttons={};var sz=new OpenLayers.Size(28,28);var centered=new OpenLayers.Pixel(OpenLayers.Control.MouseToolbar.X,0);this._addButton("zoombox","drag-rectangle-off.png","drag-rectangle-on.png",centered,sz,"Shift->Drag to zoom to area");centered=centered.add((this.direction=="vertical"?0:sz.w),(this.direction=="vertical"?sz.h:0));this._addButton("pan","panning-hand-off.png","panning-hand-on.png",centered,sz,"Drag the map to pan.");centered=centered.add((this.direction=="vertical"?0:sz.w),(this.direction=="vertical"?sz.h:0));this.switchModeTo("pan");return this.div;},_addButton:function(id,img,activeImg,xy,sz,title){var imgLocation=OpenLayers.Util.getImagesLocation()+img;var activeImgLocation=OpenLayers.Util.getImagesLocation()+activeImg;var btn=OpenLayers.Util.createAlphaImageDiv("OpenLayers_Control_MouseToolbar_"+id,xy,sz,imgLocation,"absolute");this.div.appendChild(btn);btn.imgLocation=imgLocation;btn.activeImgLocation=activeImgLocation;btn.events=new OpenLayers.Events(this,btn,null,true);btn.events.on({"mousedown":this.buttonDown,"mouseup":this.buttonUp,"dblclick":OpenLayers.Event.stop,scope:this});btn.action=id;btn.title=title;btn.alt=title;btn.map=this.map;this.buttons[id]=btn;return btn;},buttonDown:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;} +this.buttonClicked=evt.element.action;OpenLayers.Event.stop(evt);},buttonUp:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;} +if(this.buttonClicked!=null){if(this.buttonClicked==evt.element.action){this.switchModeTo(evt.element.action);} +OpenLayers.Event.stop(evt);this.buttonClicked=null;}},defaultDblClick:function(evt){this.switchModeTo("pan");this.performedDrag=false;var newCenter=this.map.getLonLatFromViewPortPx(evt.xy);this.map.setCenter(newCenter,this.map.zoom+1);OpenLayers.Event.stop(evt);return false;},defaultMouseDown:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;} +this.mouseDragStart=evt.xy.clone();this.performedDrag=false;this.startViaKeyboard=false;if(evt.shiftKey&&this.mode!="zoombox"){this.switchModeTo("zoombox");this.startViaKeyboard=true;}else if(evt.altKey&&this.mode!="measure"){this.switchModeTo("measure");}else if(!this.mode){this.switchModeTo("pan");} +switch(this.mode){case"zoombox":this.map.div.style.cursor="crosshair";this.zoomBox=OpenLayers.Util.createDiv('zoomBox',this.mouseDragStart,null,null,"absolute","2px solid red");this.zoomBox.style.backgroundColor="white";this.zoomBox.style.filter="alpha(opacity=50)";this.zoomBox.style.opacity="0.50";this.zoomBox.style.fontSize="1px";this.zoomBox.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.viewPortDiv.appendChild(this.zoomBox);this.performedDrag=true;break;case"measure":var distance="";if(this.measureStart){var measureEnd=this.map.getLonLatFromViewPortPx(this.mouseDragStart);distance=OpenLayers.Util.distVincenty(this.measureStart,measureEnd);distance=Math.round(distance*100)/100;distance=distance+"km";this.measureStartBox=this.measureBox;} +this.measureStart=this.map.getLonLatFromViewPortPx(this.mouseDragStart);;this.measureBox=OpenLayers.Util.createDiv(null,this.mouseDragStart.add(-2-parseInt(this.map.layerContainerDiv.style.left),-2-parseInt(this.map.layerContainerDiv.style.top)),null,null,"absolute");this.measureBox.style.width="4px";this.measureBox.style.height="4px";this.measureBox.style.fontSize="1px";this.measureBox.style.backgroundColor="red";this.measureBox.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.layerContainerDiv.appendChild(this.measureBox);if(distance){this.measureBoxDistance=OpenLayers.Util.createDiv(null,this.mouseDragStart.add(-2-parseInt(this.map.layerContainerDiv.style.left),2-parseInt(this.map.layerContainerDiv.style.top)),null,null,"absolute");this.measureBoxDistance.innerHTML=distance;this.measureBoxDistance.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.layerContainerDiv.appendChild(this.measureBoxDistance);this.measureDivs.push(this.measureBoxDistance);} +this.measureBox.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.layerContainerDiv.appendChild(this.measureBox);this.measureDivs.push(this.measureBox);break;default:this.map.div.style.cursor="move";break;} +document.onselectstart=OpenLayers.Function.False;OpenLayers.Event.stop(evt);},switchModeTo:function(mode){if(mode!=this.mode){if(this.mode&&this.buttons[this.mode]){OpenLayers.Util.modifyAlphaImageDiv(this.buttons[this.mode],null,null,null,this.buttons[this.mode].imgLocation);} +if(this.mode=="measure"&&mode!="measure"){for(var i=0,len=this.measureDivs.length;i<len;i++){if(this.measureDivs[i]){this.map.layerContainerDiv.removeChild(this.measureDivs[i]);}} +this.measureDivs=[];this.measureStart=null;} +this.mode=mode;if(this.buttons[mode]){OpenLayers.Util.modifyAlphaImageDiv(this.buttons[mode],null,null,null,this.buttons[mode].activeImgLocation);} +switch(this.mode){case"zoombox":this.map.div.style.cursor="crosshair";break;default:this.map.div.style.cursor="";break;}}},leaveMode:function(){this.switchModeTo("pan");},defaultMouseMove:function(evt){if(this.mouseDragStart!=null){switch(this.mode){case"zoombox":var deltaX=Math.abs(this.mouseDragStart.x-evt.xy.x);var deltaY=Math.abs(this.mouseDragStart.y-evt.xy.y);this.zoomBox.style.width=Math.max(1,deltaX)+"px";this.zoomBox.style.height=Math.max(1,deltaY)+"px";if(evt.xy.x<this.mouseDragStart.x){this.zoomBox.style.left=evt.xy.x+"px";} +if(evt.xy.y<this.mouseDragStart.y){this.zoomBox.style.top=evt.xy.y+"px";} +break;default:var deltaX=this.mouseDragStart.x-evt.xy.x;var deltaY=this.mouseDragStart.y-evt.xy.y;var size=this.map.getSize();var newXY=new OpenLayers.Pixel(size.w/2+deltaX,size.h/2+deltaY);var newCenter=this.map.getLonLatFromViewPortPx(newXY);this.map.setCenter(newCenter,null,true);this.mouseDragStart=evt.xy.clone();} +this.performedDrag=true;}},defaultMouseUp:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;} +switch(this.mode){case"zoombox":this.zoomBoxEnd(evt);if(this.startViaKeyboard){this.leaveMode();} +break;case"pan":if(this.performedDrag){this.map.setCenter(this.map.center);}} +document.onselectstart=null;this.mouseDragStart=null;this.map.div.style.cursor="default";},defaultMouseOut:function(evt){if(this.mouseDragStart!=null&&OpenLayers.Util.mouseLeft(evt,this.map.div)){if(this.zoomBox){this.removeZoomBox();if(this.startViaKeyboard){this.leaveMode();}} +this.mouseDragStart=null;this.map.div.style.cursor="default";}},defaultClick:function(evt){if(this.performedDrag){this.performedDrag=false;return false;}},CLASS_NAME:"OpenLayers.Control.MouseToolbar"});OpenLayers.Control.MouseToolbar.X=6;OpenLayers.Control.MouseToolbar.Y=300;OpenLayers.Control.NavigationHistory=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOGGLE,previous:null,previousOptions:null,next:null,nextOptions:null,limit:50,autoActivate:true,clearOnDeactivate:false,registry:null,nextStack:null,previousStack:null,listeners:null,restoring:false,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,[options]);this.registry=OpenLayers.Util.extend({"moveend":this.getState},this.registry);var previousOptions={trigger:OpenLayers.Function.bind(this.previousTrigger,this),displayClass:this.displayClass+" "+this.displayClass+"Previous"};OpenLayers.Util.extend(previousOptions,this.previousOptions);this.previous=new OpenLayers.Control.Button(previousOptions);var nextOptions={trigger:OpenLayers.Function.bind(this.nextTrigger,this),displayClass:this.displayClass+" "+this.displayClass+"Next"};OpenLayers.Util.extend(nextOptions,this.nextOptions);this.next=new OpenLayers.Control.Button(nextOptions);this.clear();},onPreviousChange:function(state,length){if(state&&!this.previous.active){this.previous.activate();}else if(!state&&this.previous.active){this.previous.deactivate();}},onNextChange:function(state,length){if(state&&!this.next.active){this.next.activate();}else if(!state&&this.next.active){this.next.deactivate();}},destroy:function(){OpenLayers.Control.prototype.destroy.apply(this);this.previous.destroy();this.next.destroy();this.deactivate();for(var prop in this){this[prop]=null;}},setMap:function(map){this.map=map;this.next.setMap(map);this.previous.setMap(map);},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);this.next.draw();this.previous.draw();},previousTrigger:function(){var current=this.previousStack.shift();var state=this.previousStack.shift();if(state!=undefined){this.nextStack.unshift(current);this.previousStack.unshift(state);this.restoring=true;this.restore(state);this.restoring=false;this.onNextChange(this.nextStack[0],this.nextStack.length);this.onPreviousChange(this.previousStack[1],this.previousStack.length-1);}else{this.previousStack.unshift(current);} +return state;},nextTrigger:function(){var state=this.nextStack.shift();if(state!=undefined){this.previousStack.unshift(state);this.restoring=true;this.restore(state);this.restoring=false;this.onNextChange(this.nextStack[0],this.nextStack.length);this.onPreviousChange(this.previousStack[1],this.previousStack.length-1);} +return state;},clear:function(){this.previousStack=[];this.previous.deactivate();this.nextStack=[];this.next.deactivate();},getState:function(){return{center:this.map.getCenter(),resolution:this.map.getResolution(),projection:this.map.getProjectionObject(),units:this.map.getProjectionObject().getUnits()||this.map.units||this.map.baseLayer.units};},restore:function(state){var center,zoom;if(this.map.getProjectionObject()==state.projection){zoom=this.map.getZoomForResolution(state.resolution);center=state.center;}else{center=state.center.clone();center.transform(state.projection,this.map.getProjectionObject());var sourceUnits=state.units;var targetUnits=this.map.getProjectionObject().getUnits()||this.map.units||this.map.baseLayer.units;var resolutionFactor=sourceUnits&&targetUnits?OpenLayers.INCHES_PER_UNIT[sourceUnits]/OpenLayers.INCHES_PER_UNIT[targetUnits]:1;zoom=this.map.getZoomForResolution(resolutionFactor*state.resolution);} +this.map.setCenter(center,zoom);},setListeners:function(){this.listeners={};for(var type in this.registry){this.listeners[type]=OpenLayers.Function.bind(function(){if(!this.restoring){var state=this.registry[type].apply(this,arguments);this.previousStack.unshift(state);if(this.previousStack.length>1){this.onPreviousChange(this.previousStack[1],this.previousStack.length-1);} +if(this.previousStack.length>(this.limit+1)){this.previousStack.pop();} +if(this.nextStack.length>0){this.nextStack=[];this.onNextChange(null,0);}} +return true;},this);}},activate:function(){var activated=false;if(this.map){if(OpenLayers.Control.prototype.activate.apply(this)){if(this.listeners==null){this.setListeners();} +for(var type in this.listeners){this.map.events.register(type,this,this.listeners[type]);} +activated=true;if(this.previousStack.length==0){this.initStack();}}} +return activated;},initStack:function(){if(this.map.getCenter()){this.listeners.moveend();}},deactivate:function(){var deactivated=false;if(this.map){if(OpenLayers.Control.prototype.deactivate.apply(this)){for(var type in this.listeners){this.map.events.unregister(type,this,this.listeners[type]);} +if(this.clearOnDeactivate){this.clear();} +deactivated=true;}} +return deactivated;},CLASS_NAME:"OpenLayers.Control.NavigationHistory"});OpenLayers.Control.PanPanel=OpenLayers.Class(OpenLayers.Control.Panel,{slideFactor:50,initialize:function(options){OpenLayers.Control.Panel.prototype.initialize.apply(this,[options]);this.addControls([new OpenLayers.Control.Pan(OpenLayers.Control.Pan.NORTH,{slideFactor:this.slideFactor}),new OpenLayers.Control.Pan(OpenLayers.Control.Pan.SOUTH,{slideFactor:this.slideFactor}),new OpenLayers.Control.Pan(OpenLayers.Control.Pan.EAST,{slideFactor:this.slideFactor}),new OpenLayers.Control.Pan(OpenLayers.Control.Pan.WEST,{slideFactor:this.slideFactor})]);},CLASS_NAME:"OpenLayers.Control.PanPanel"});OpenLayers.Control.PanZoomBar=OpenLayers.Class(OpenLayers.Control.PanZoom,{zoomStopWidth:18,zoomStopHeight:11,slider:null,sliderEvents:null,zoombarDiv:null,divEvents:null,zoomWorldIcon:false,forceFixedZoomLevel:false,mouseDragStart:null,zoomStart:null,initialize:function(){OpenLayers.Control.PanZoom.prototype.initialize.apply(this,arguments);},destroy:function(){this._removeZoomBar();this.map.events.un({"changebaselayer":this.redraw,scope:this});OpenLayers.Control.PanZoom.prototype.destroy.apply(this,arguments);delete this.mouseDragStart;delete this.zoomStart;},setMap:function(map){OpenLayers.Control.PanZoom.prototype.setMap.apply(this,arguments);this.map.events.register("changebaselayer",this,this.redraw);},redraw:function(){if(this.div!=null){this.removeButtons();this._removeZoomBar();} +this.draw();},draw:function(px){OpenLayers.Control.prototype.draw.apply(this,arguments);px=this.position.clone();this.buttons=[];var sz=new OpenLayers.Size(18,18);var centered=new OpenLayers.Pixel(px.x+sz.w/2,px.y);var wposition=sz.w;if(this.zoomWorldIcon){centered=new OpenLayers.Pixel(px.x+sz.w,px.y);} +this._addButton("panup","north-mini.png",centered,sz);px.y=centered.y+sz.h;this._addButton("panleft","west-mini.png",px,sz);if(this.zoomWorldIcon){this._addButton("zoomworld","zoom-world-mini.png",px.add(sz.w,0),sz);wposition*=2;} +this._addButton("panright","east-mini.png",px.add(wposition,0),sz);this._addButton("pandown","south-mini.png",centered.add(0,sz.h*2),sz);this._addButton("zoomin","zoom-plus-mini.png",centered.add(0,sz.h*3+5),sz);centered=this._addZoomBar(centered.add(0,sz.h*4+5));this._addButton("zoomout","zoom-minus-mini.png",centered,sz);return this.div;},_addZoomBar:function(centered){var imgLocation=OpenLayers.Util.getImagesLocation();var id=this.id+"_"+this.map.id;var zoomsToEnd=this.map.getNumZoomLevels()-1-this.map.getZoom();var slider=OpenLayers.Util.createAlphaImageDiv(id,centered.add(-1,zoomsToEnd*this.zoomStopHeight),new OpenLayers.Size(20,9),imgLocation+"slider.png","absolute");this.slider=slider;this.sliderEvents=new OpenLayers.Events(this,slider,null,true,{includeXY:true});this.sliderEvents.on({"mousedown":this.zoomBarDown,"mousemove":this.zoomBarDrag,"mouseup":this.zoomBarUp,"dblclick":this.doubleClick,"click":this.doubleClick});var sz=new OpenLayers.Size();sz.h=this.zoomStopHeight*this.map.getNumZoomLevels();sz.w=this.zoomStopWidth;var div=null;if(OpenLayers.Util.alphaHack()){var id=this.id+"_"+this.map.id;div=OpenLayers.Util.createAlphaImageDiv(id,centered,new OpenLayers.Size(sz.w,this.zoomStopHeight),imgLocation+"zoombar.png","absolute",null,"crop");div.style.height=sz.h+"px";}else{div=OpenLayers.Util.createDiv('OpenLayers_Control_PanZoomBar_Zoombar'+this.map.id,centered,sz,imgLocation+"zoombar.png");} +this.zoombarDiv=div;this.divEvents=new OpenLayers.Events(this,div,null,true,{includeXY:true});this.divEvents.on({"mousedown":this.divClick,"mousemove":this.passEventToSlider,"dblclick":this.doubleClick,"click":this.doubleClick});this.div.appendChild(div);this.startTop=parseInt(div.style.top);this.div.appendChild(slider);this.map.events.register("zoomend",this,this.moveZoomBar);centered=centered.add(0,this.zoomStopHeight*this.map.getNumZoomLevels());return centered;},_removeZoomBar:function(){this.sliderEvents.un({"mousedown":this.zoomBarDown,"mousemove":this.zoomBarDrag,"mouseup":this.zoomBarUp,"dblclick":this.doubleClick,"click":this.doubleClick});this.sliderEvents.destroy();this.divEvents.un({"mousedown":this.divClick,"mousemove":this.passEventToSlider,"dblclick":this.doubleClick,"click":this.doubleClick});this.divEvents.destroy();this.div.removeChild(this.zoombarDiv);this.zoombarDiv=null;this.div.removeChild(this.slider);this.slider=null;this.map.events.unregister("zoomend",this,this.moveZoomBar);},passEventToSlider:function(evt){this.sliderEvents.handleBrowserEvent(evt);},divClick:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;} +var y=evt.xy.y;var top=OpenLayers.Util.pagePosition(evt.object)[1];var levels=(y-top)/this.zoomStopHeight;if(this.forceFixedZoomLevel||!this.map.fractionalZoom){levels=Math.floor(levels);} +var zoom=(this.map.getNumZoomLevels()-1)-levels;zoom=Math.min(Math.max(zoom,0),this.map.getNumZoomLevels()-1);this.map.zoomTo(zoom);OpenLayers.Event.stop(evt);},zoomBarDown:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;} +this.map.events.on({"mousemove":this.passEventToSlider,"mouseup":this.passEventToSlider,scope:this});this.mouseDragStart=evt.xy.clone();this.zoomStart=evt.xy.clone();this.div.style.cursor="move";this.zoombarDiv.offsets=null;OpenLayers.Event.stop(evt);},zoomBarDrag:function(evt){if(this.mouseDragStart!=null){var deltaY=this.mouseDragStart.y-evt.xy.y;var offsets=OpenLayers.Util.pagePosition(this.zoombarDiv);if((evt.clientY-offsets[1])>0&&(evt.clientY-offsets[1])<parseInt(this.zoombarDiv.style.height)-2){var newTop=parseInt(this.slider.style.top)-deltaY;this.slider.style.top=newTop+"px";this.mouseDragStart=evt.xy.clone();} +OpenLayers.Event.stop(evt);}},zoomBarUp:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;} +if(this.mouseDragStart){this.div.style.cursor="";this.map.events.un({"mouseup":this.passEventToSlider,"mousemove":this.passEventToSlider,scope:this});var deltaY=this.zoomStart.y-evt.xy.y;var zoomLevel=this.map.zoom;if(!this.forceFixedZoomLevel&&this.map.fractionalZoom){zoomLevel+=deltaY/this.zoomStopHeight;zoomLevel=Math.min(Math.max(zoomLevel,0),this.map.getNumZoomLevels()-1);}else{zoomLevel+=Math.round(deltaY/this.zoomStopHeight);} +this.map.zoomTo(zoomLevel);this.mouseDragStart=null;this.zoomStart=null;OpenLayers.Event.stop(evt);}},moveZoomBar:function(){var newTop=((this.map.getNumZoomLevels()-1)-this.map.getZoom())*this.zoomStopHeight+this.startTop+1;this.slider.style.top=newTop+"px";},CLASS_NAME:"OpenLayers.Control.PanZoomBar"});OpenLayers.Control.Permalink=OpenLayers.Class(OpenLayers.Control,{argParserClass:OpenLayers.Control.ArgParser,element:null,base:'',displayProjection:null,initialize:function(element,base,options){OpenLayers.Control.prototype.initialize.apply(this,[options]);this.element=OpenLayers.Util.getElement(element);this.base=base||document.location.href;},destroy:function(){if(this.element.parentNode==this.div){this.div.removeChild(this.element);} +this.element=null;this.map.events.unregister('moveend',this,this.updateLink);OpenLayers.Control.prototype.destroy.apply(this,arguments);},setMap:function(map){OpenLayers.Control.prototype.setMap.apply(this,arguments);for(var i=0,len=this.map.controls.length;i<len;i++){var control=this.map.controls[i];if(control.CLASS_NAME==this.argParserClass.CLASS_NAME){if(control.displayProjection!=this.displayProjection){this.displayProjection=control.displayProjection;} +break;}} +if(i==this.map.controls.length){this.map.addControl(new this.argParserClass({'displayProjection':this.displayProjection}));}},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!this.element){this.div.className=this.displayClass;this.element=document.createElement("a");this.element.innerHTML=OpenLayers.i18n("permalink");this.element.href="";this.div.appendChild(this.element);} +this.map.events.on({'moveend':this.updateLink,'changelayer':this.updateLink,'changebaselayer':this.updateLink,scope:this});this.updateLink();return this.div;},updateLink:function(){var href=this.base;if(href.indexOf('?')!=-1){href=href.substring(0,href.indexOf('?'));} +href+='?'+OpenLayers.Util.getParameterString(this.createParams());this.element.href=href;},createParams:function(center,zoom,layers){center=center||this.map.getCenter();var params=OpenLayers.Util.getParameters(this.base);if(center){params.zoom=zoom||this.map.getZoom();var lat=center.lat;var lon=center.lon;if(this.displayProjection){var mapPosition=OpenLayers.Projection.transform({x:lon,y:lat},this.map.getProjectionObject(),this.displayProjection);lon=mapPosition.x;lat=mapPosition.y;} +params.lat=Math.round(lat*100000)/100000;params.lon=Math.round(lon*100000)/100000;layers=layers||this.map.layers;params.layers='';for(var i=0,len=layers.length;i<len;i++){var layer=layers[i];if(layer.isBaseLayer){params.layers+=(layer==this.map.baseLayer)?"B":"0";}else{params.layers+=(layer.getVisibility())?"T":"F";}}} +return params;},CLASS_NAME:"OpenLayers.Control.Permalink"});OpenLayers.Control.ZoomPanel=OpenLayers.Class(OpenLayers.Control.Panel,{initialize:function(options){OpenLayers.Control.Panel.prototype.initialize.apply(this,[options]);this.addControls([new OpenLayers.Control.ZoomIn(),new OpenLayers.Control.ZoomToMaxExtent(),new OpenLayers.Control.ZoomOut()]);},CLASS_NAME:"OpenLayers.Control.ZoomPanel"});OpenLayers.Format.CSWGetDomain=function(options){options=OpenLayers.Util.applyDefaults(options,OpenLayers.Format.CSWGetDomain.DEFAULTS);var cls=OpenLayers.Format.CSWGetDomain["v"+options.version.replace(/\./g,"_")];if(!cls){throw"Unsupported CSWGetDomain version: "+options.version;} +return new cls(options);};OpenLayers.Format.CSWGetDomain.DEFAULTS={"version":"2.0.2"};OpenLayers.Format.CSWGetRecords=function(options){options=OpenLayers.Util.applyDefaults(options,OpenLayers.Format.CSWGetRecords.DEFAULTS);var cls=OpenLayers.Format.CSWGetRecords["v"+options.version.replace(/\./g,"_")];if(!cls){throw"Unsupported CSWGetRecords version: "+options.version;} +return new cls(options);};OpenLayers.Format.CSWGetRecords.DEFAULTS={"version":"2.0.2"};OpenLayers.Format.JSON=OpenLayers.Class(OpenLayers.Format,{indent:" ",space:" ",newline:"\n",level:0,pretty:false,initialize:function(options){OpenLayers.Format.prototype.initialize.apply(this,[options]);},read:function(json,filter){try{if(/^[\],:{}\s]*$/.test(json.replace(/\\["\\\/bfnrtu]/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){var object=eval('('+json+')');if(typeof filter==='function'){function walk(k,v){if(v&&typeof v==='object'){for(var i in v){if(v.hasOwnProperty(i)){v[i]=walk(i,v[i]);}}} +return filter(k,v);} +object=walk('',object);} +if(this.keepData){this.data=object;} +return object;}}catch(e){} +return null;},write:function(value,pretty){this.pretty=!!pretty;var json=null;var type=typeof value;if(this.serialize[type]){try{json=this.serialize[type].apply(this,[value]);}catch(err){OpenLayers.Console.error("Trouble serializing: "+err);}} +return json;},writeIndent:function(){var pieces=[];if(this.pretty){for(var i=0;i<this.level;++i){pieces.push(this.indent);}} +return pieces.join('');},writeNewline:function(){return(this.pretty)?this.newline:'';},writeSpace:function(){return(this.pretty)?this.space:'';},serialize:{'object':function(object){if(object==null){return"null";} +if(object.constructor==Date){return this.serialize.date.apply(this,[object]);} +if(object.constructor==Array){return this.serialize.array.apply(this,[object]);} +var pieces=['{'];this.level+=1;var key,keyJSON,valueJSON;var addComma=false;for(key in object){if(object.hasOwnProperty(key)){keyJSON=OpenLayers.Format.JSON.prototype.write.apply(this,[key,this.pretty]);valueJSON=OpenLayers.Format.JSON.prototype.write.apply(this,[object[key],this.pretty]);if(keyJSON!=null&&valueJSON!=null){if(addComma){pieces.push(',');} +pieces.push(this.writeNewline(),this.writeIndent(),keyJSON,':',this.writeSpace(),valueJSON);addComma=true;}}} +this.level-=1;pieces.push(this.writeNewline(),this.writeIndent(),'}');return pieces.join('');},'array':function(array){var json;var pieces=['['];this.level+=1;for(var i=0,len=array.length;i<len;++i){json=OpenLayers.Format.JSON.prototype.write.apply(this,[array[i],this.pretty]);if(json!=null){if(i>0){pieces.push(',');} +pieces.push(this.writeNewline(),this.writeIndent(),json);}} +this.level-=1;pieces.push(this.writeNewline(),this.writeIndent(),']');return pieces.join('');},'string':function(string){var m={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};if(/["\\\x00-\x1f]/.test(string)){return'"'+string.replace(/([\x00-\x1f\\"])/g,function(a,b){var c=m[b];if(c){return c;} +c=b.charCodeAt();return'\\u00'+ +Math.floor(c/16).toString(16)+ +(c%16).toString(16);})+'"';} +return'"'+string+'"';},'number':function(number){return isFinite(number)?String(number):"null";},'boolean':function(bool){return String(bool);},'date':function(date){function format(number){return(number<10)?'0'+number:number;} +return'"'+date.getFullYear()+'-'+ +format(date.getMonth()+1)+'-'+ +format(date.getDate())+'T'+ +format(date.getHours())+':'+ +format(date.getMinutes())+':'+ +format(date.getSeconds())+'"';}},CLASS_NAME:"OpenLayers.Format.JSON"});OpenLayers.Format.WFST=function(options){options=OpenLayers.Util.applyDefaults(options,OpenLayers.Format.WFST.DEFAULTS);var cls=OpenLayers.Format.WFST["v"+options.version.replace(/\./g,"_")];if(!cls){throw"Unsupported WFST version: "+options.version;} +return new cls(options);};OpenLayers.Format.WFST.DEFAULTS={"version":"1.0.0"};OpenLayers.Format.XML=OpenLayers.Class(OpenLayers.Format,{namespaces:null,namespaceAlias:null,defaultPrefix:null,readers:{},writers:{},xmldom:null,initialize:function(options){if(window.ActiveXObject){this.xmldom=new ActiveXObject("Microsoft.XMLDOM");} +OpenLayers.Format.prototype.initialize.apply(this,[options]);this.namespaces=OpenLayers.Util.extend({},this.namespaces);this.namespaceAlias={};for(var alias in this.namespaces){this.namespaceAlias[this.namespaces[alias]]=alias;}},destroy:function(){this.xmldom=null;OpenLayers.Format.prototype.destroy.apply(this,arguments);},setNamespace:function(alias,uri){this.namespaces[alias]=uri;this.namespaceAlias[uri]=alias;},read:function(text){var index=text.indexOf('<');if(index>0){text=text.substring(index);} +var node=OpenLayers.Util.Try(OpenLayers.Function.bind((function(){var xmldom;if(window.ActiveXObject&&!this.xmldom){xmldom=new ActiveXObject("Microsoft.XMLDOM");}else{xmldom=this.xmldom;} +xmldom.loadXML(text);return xmldom;}),this),function(){return new DOMParser().parseFromString(text,'text/xml');},function(){var req=new XMLHttpRequest();req.open("GET","data:"+"text/xml"+";charset=utf-8,"+encodeURIComponent(text),false);if(req.overrideMimeType){req.overrideMimeType("text/xml");} +req.send(null);return req.responseXML;});if(this.keepData){this.data=node;} +return node;},write:function(node){var data;if(this.xmldom){data=node.xml;}else{var serializer=new XMLSerializer();if(node.nodeType==1){var doc=document.implementation.createDocument("","",null);if(doc.importNode){node=doc.importNode(node,true);} +doc.appendChild(node);data=serializer.serializeToString(doc);}else{data=serializer.serializeToString(node);}} +return data;},createElementNS:function(uri,name){var element;if(this.xmldom){if(typeof uri=="string"){element=this.xmldom.createNode(1,name,uri);}else{element=this.xmldom.createNode(1,name,"");}}else{element=document.createElementNS(uri,name);} +return element;},createTextNode:function(text){var node;if(typeof text!=="string"){text=String(text);} +if(this.xmldom){node=this.xmldom.createTextNode(text);}else{node=document.createTextNode(text);} +return node;},getElementsByTagNameNS:function(node,uri,name){var elements=[];if(node.getElementsByTagNameNS){elements=node.getElementsByTagNameNS(uri,name);}else{var allNodes=node.getElementsByTagName("*");var potentialNode,fullName;for(var i=0,len=allNodes.length;i<len;++i){potentialNode=allNodes[i];fullName=(potentialNode.prefix)?(potentialNode.prefix+":"+name):name;if((name=="*")||(fullName==potentialNode.nodeName)){if((uri=="*")||(uri==potentialNode.namespaceURI)){elements.push(potentialNode);}}}} +return elements;},getAttributeNodeNS:function(node,uri,name){var attributeNode=null;if(node.getAttributeNodeNS){attributeNode=node.getAttributeNodeNS(uri,name);}else{var attributes=node.attributes;var potentialNode,fullName;for(var i=0,len=attributes.length;i<len;++i){potentialNode=attributes[i];if(potentialNode.namespaceURI==uri){fullName=(potentialNode.prefix)?(potentialNode.prefix+":"+name):name;if(fullName==potentialNode.nodeName){attributeNode=potentialNode;break;}}}} +return attributeNode;},getAttributeNS:function(node,uri,name){var attributeValue="";if(node.getAttributeNS){attributeValue=node.getAttributeNS(uri,name)||"";}else{var attributeNode=this.getAttributeNodeNS(node,uri,name);if(attributeNode){attributeValue=attributeNode.nodeValue;}} +return attributeValue;},getChildValue:function(node,def){var value=def||"";if(node){for(var child=node.firstChild;child;child=child.nextSibling){switch(child.nodeType){case 3:case 4:value+=child.nodeValue;}}} +return value;},concatChildValues:function(node,def){var value="";var child=node.firstChild;var childValue;while(child){childValue=child.nodeValue;if(childValue){value+=childValue;} +child=child.nextSibling;} +if(value==""&&def!=undefined){value=def;} +return value;},isSimpleContent:function(node){var simple=true;for(var child=node.firstChild;child;child=child.nextSibling){if(child.nodeType===1){simple=false;break;}} +return simple;},contentType:function(node){var simple=false,complex=false;var type=OpenLayers.Format.XML.CONTENT_TYPE.EMPTY;for(var child=node.firstChild;child;child=child.nextSibling){switch(child.nodeType){case 1:complex=true;break;case 8:break;default:simple=true;} +if(complex&&simple){break;}} +if(complex&&simple){type=OpenLayers.Format.XML.CONTENT_TYPE.MIXED;}else if(complex){return OpenLayers.Format.XML.CONTENT_TYPE.COMPLEX;}else if(simple){return OpenLayers.Format.XML.CONTENT_TYPE.SIMPLE;} +return type;},hasAttributeNS:function(node,uri,name){var found=false;if(node.hasAttributeNS){found=node.hasAttributeNS(uri,name);}else{found=!!this.getAttributeNodeNS(node,uri,name);} +return found;},setAttributeNS:function(node,uri,name,value){if(node.setAttributeNS){node.setAttributeNS(uri,name,value);}else{if(this.xmldom){if(uri){var attribute=node.ownerDocument.createNode(2,name,uri);attribute.nodeValue=value;node.setAttributeNode(attribute);}else{node.setAttribute(name,value);}}else{throw"setAttributeNS not implemented";}}},createElementNSPlus:function(name,options){options=options||{};var uri=options.uri||this.namespaces[options.prefix];if(!uri){var loc=name.indexOf(":");uri=this.namespaces[name.substring(0,loc)];} +if(!uri){uri=this.namespaces[this.defaultPrefix];} +var node=this.createElementNS(uri,name);if(options.attributes){this.setAttributes(node,options.attributes);} +var value=options.value;if(value!=null){node.appendChild(this.createTextNode(value));} +return node;},setAttributes:function(node,obj){var value,uri;for(var name in obj){if(obj[name]!=null&&obj[name].toString){value=obj[name].toString();uri=this.namespaces[name.substring(0,name.indexOf(":"))]||null;this.setAttributeNS(node,uri,name,value);}}},readNode:function(node,obj){if(!obj){obj={};} +var group=this.readers[node.namespaceURI?this.namespaceAlias[node.namespaceURI]:this.defaultPrefix];if(group){var local=node.localName||node.nodeName.split(":").pop();var reader=group[local]||group["*"];if(reader){reader.apply(this,[node,obj]);}} +return obj;},readChildNodes:function(node,obj){if(!obj){obj={};} +var children=node.childNodes;var child;for(var i=0,len=children.length;i<len;++i){child=children[i];if(child.nodeType==1){this.readNode(child,obj);}} +return obj;},writeNode:function(name,obj,parent){var prefix,local;var split=name.indexOf(":");if(split>0){prefix=name.substring(0,split);local=name.substring(split+1);}else{if(parent){prefix=this.namespaceAlias[parent.namespaceURI];}else{prefix=this.defaultPrefix;} +local=name;} +var child=this.writers[prefix][local].apply(this,[obj]);if(parent){parent.appendChild(child);} +return child;},getChildEl:function(node,name,uri){return node&&this.getThisOrNextEl(node.firstChild,name,uri);},getNextEl:function(node,name,uri){return node&&this.getThisOrNextEl(node.nextSibling,name,uri);},getThisOrNextEl:function(node,name,uri){outer:for(var sibling=node;sibling;sibling=sibling.nextSibling){switch(sibling.nodeType){case 1:if((!name||name===(sibling.localName||sibling.nodeName.split(":").pop()))&&(!uri||uri===sibling.namespaceURI)){break outer;} +sibling=null;break outer;case 3:if(/^\s*$/.test(sibling.nodeValue)){break;} +case 4:case 6:case 12:case 10:case 11:sibling=null;break outer;}} +return sibling||null;},lookupNamespaceURI:function(node,prefix){var uri=null;if(node){if(node.lookupNamespaceURI){uri=node.lookupNamespaceURI(prefix);}else{outer:switch(node.nodeType){case 1:if(node.namespaceURI!==null&&node.prefix===prefix){uri=node.namespaceURI;break outer;} +var len=node.attributes.length;if(len){var attr;for(var i=0;i<len;++i){attr=node.attributes[i];if(attr.prefix==="xmlns"&&attr.name==="xmlns:"+prefix){uri=attr.value||null;break outer;}else if(attr.name==="xmlns"&&prefix===null){uri=attr.value||null;break outer;}}} +uri=this.lookupNamespaceURI(node.parentNode,prefix);break outer;case 2:uri=this.lookupNamespaceURI(node.ownerElement,prefix);break outer;case 9:uri=this.lookupNamespaceURI(node.documentElement,prefix);break outer;case 6:case 12:case 10:case 11:break outer;default:uri=this.lookupNamespaceURI(node.parentNode,prefix);break outer;}}} +return uri;},CLASS_NAME:"OpenLayers.Format.XML"});OpenLayers.Format.XML.CONTENT_TYPE={EMPTY:0,SIMPLE:1,COMPLEX:2,MIXED:3};OpenLayers.Format.XML.lookupNamespaceURI=OpenLayers.Function.bind(OpenLayers.Format.XML.prototype.lookupNamespaceURI,OpenLayers.Format.XML.prototype);OpenLayers.Handler=OpenLayers.Class({id:null,control:null,map:null,keyMask:null,active:false,evt:null,initialize:function(control,callbacks,options){OpenLayers.Util.extend(this,options);this.control=control;this.callbacks=callbacks;var map=this.map||control.map;if(map){this.setMap(map);} +this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},setMap:function(map){this.map=map;},checkModifiers:function(evt){if(this.keyMask==null){return true;} +var keyModifiers=(evt.shiftKey?OpenLayers.Handler.MOD_SHIFT:0)|(evt.ctrlKey?OpenLayers.Handler.MOD_CTRL:0)|(evt.altKey?OpenLayers.Handler.MOD_ALT:0);return(keyModifiers==this.keyMask);},activate:function(){if(this.active){return false;} +var events=OpenLayers.Events.prototype.BROWSER_EVENTS;for(var i=0,len=events.length;i<len;i++){if(this[events[i]]){this.register(events[i],this[events[i]]);}} +this.active=true;return true;},deactivate:function(){if(!this.active){return false;} +var events=OpenLayers.Events.prototype.BROWSER_EVENTS;for(var i=0,len=events.length;i<len;i++){if(this[events[i]]){this.unregister(events[i],this[events[i]]);}} +this.active=false;return true;},callback:function(name,args){if(name&&this.callbacks[name]){this.callbacks[name].apply(this.control,args);}},register:function(name,method){this.map.events.registerPriority(name,this,method);this.map.events.registerPriority(name,this,this.setEvent);},unregister:function(name,method){this.map.events.unregister(name,this,method);this.map.events.unregister(name,this,this.setEvent);},setEvent:function(evt){this.evt=evt;return true;},destroy:function(){this.deactivate();this.control=this.map=null;},CLASS_NAME:"OpenLayers.Handler"});OpenLayers.Handler.MOD_NONE=0;OpenLayers.Handler.MOD_SHIFT=1;OpenLayers.Handler.MOD_CTRL=2;OpenLayers.Handler.MOD_ALT=4;OpenLayers.Map=OpenLayers.Class({Z_INDEX_BASE:{BaseLayer:100,Overlay:325,Feature:725,Popup:750,Control:1000},EVENT_TYPES:["preaddlayer","addlayer","removelayer","changelayer","movestart","move","moveend","zoomend","popupopen","popupclose","addmarker","removemarker","clearmarkers","mouseover","mouseout","mousemove","dragstart","drag","dragend","changebaselayer"],id:null,fractionalZoom:false,events:null,allOverlays:false,div:null,dragging:false,size:null,viewPortDiv:null,layerContainerOrigin:null,layerContainerDiv:null,layers:null,controls:null,popups:null,baseLayer:null,center:null,resolution:null,zoom:0,panRatio:1.5,viewRequestID:0,tileSize:null,projection:"EPSG:4326",units:'degrees',resolutions:null,maxResolution:1.40625,minResolution:null,maxScale:null,minScale:null,maxExtent:null,minExtent:null,restrictedExtent:null,numZoomLevels:16,theme:null,displayProjection:null,fallThrough:true,panTween:null,eventListeners:null,panMethod:OpenLayers.Easing.Expo.easeOut,panDuration:50,paddingForPopups:null,initialize:function(div,options){if(arguments.length===1&&typeof div==="object"){options=div;div=options&&options.div;} +this.tileSize=new OpenLayers.Size(OpenLayers.Map.TILE_WIDTH,OpenLayers.Map.TILE_HEIGHT);this.maxExtent=new OpenLayers.Bounds(-180,-90,180,90);this.paddingForPopups=new OpenLayers.Bounds(15,15,15,15);this.theme=OpenLayers._getScriptLocation()+'theme/default/style.css';OpenLayers.Util.extend(this,options);this.layers=[];this.id=OpenLayers.Util.createUniqueID("OpenLayers.Map_");this.div=OpenLayers.Util.getElement(div);if(!this.div){this.div=document.createElement("div");this.div.style.height="1px";this.div.style.width="1px";} +OpenLayers.Element.addClass(this.div,'olMap');var id=this.id+"_OpenLayers_ViewPort";this.viewPortDiv=OpenLayers.Util.createDiv(id,null,null,null,"relative",null,"hidden");this.viewPortDiv.style.width="100%";this.viewPortDiv.style.height="100%";this.viewPortDiv.className="olMapViewport";this.div.appendChild(this.viewPortDiv);id=this.id+"_OpenLayers_Container";this.layerContainerDiv=OpenLayers.Util.createDiv(id);this.layerContainerDiv.style.zIndex=this.Z_INDEX_BASE['Popup']-1;this.viewPortDiv.appendChild(this.layerContainerDiv);this.events=new OpenLayers.Events(this,this.div,this.EVENT_TYPES,this.fallThrough,{includeXY:true});this.updateSize();if(this.eventListeners instanceof Object){this.events.on(this.eventListeners);} +this.events.register("movestart",this,this.updateSize);if(OpenLayers.String.contains(navigator.appName,"Microsoft")){this.events.register("resize",this,this.updateSize);}else{this.updateSizeDestroy=OpenLayers.Function.bind(this.updateSize,this);OpenLayers.Event.observe(window,'resize',this.updateSizeDestroy);} +if(this.theme){var addNode=true;var nodes=document.getElementsByTagName('link');for(var i=0,len=nodes.length;i<len;++i){if(OpenLayers.Util.isEquivalentUrl(nodes.item(i).href,this.theme)){addNode=false;break;}} +if(addNode){var cssNode=document.createElement('link');cssNode.setAttribute('rel','stylesheet');cssNode.setAttribute('type','text/css');cssNode.setAttribute('href',this.theme);document.getElementsByTagName('head')[0].appendChild(cssNode);}} +if(this.controls==null){if(OpenLayers.Control!=null){this.controls=[new OpenLayers.Control.Navigation(),new OpenLayers.Control.PanZoom(),new OpenLayers.Control.ArgParser(),new OpenLayers.Control.Attribution()];}else{this.controls=[];}} +for(var i=0,len=this.controls.length;i<len;i++){this.addControlToMap(this.controls[i]);} +this.popups=[];this.unloadDestroy=OpenLayers.Function.bind(this.destroy,this);OpenLayers.Event.observe(window,'unload',this.unloadDestroy);if(options&&options.layers){this.addLayers(options.layers);if(options.center){this.setCenter(options.center,options.zoom);}}},render:function(div){this.div=OpenLayers.Util.getElement(div);OpenLayers.Element.addClass(this.div,'olMap');this.events.attachToElement(this.div);this.viewPortDiv.parentNode.removeChild(this.viewPortDiv);this.div.appendChild(this.viewPortDiv);this.updateSize();},unloadDestroy:null,updateSizeDestroy:null,destroy:function(){if(!this.unloadDestroy){return false;} +if(this.panTween){this.panTween.stop();this.panTween=null;} +OpenLayers.Event.stopObserving(window,'unload',this.unloadDestroy);this.unloadDestroy=null;if(this.updateSizeDestroy){OpenLayers.Event.stopObserving(window,'resize',this.updateSizeDestroy);}else{this.events.unregister("resize",this,this.updateSize);} +this.paddingForPopups=null;if(this.controls!=null){for(var i=this.controls.length-1;i>=0;--i){this.controls[i].destroy();} +this.controls=null;} +if(this.layers!=null){for(var i=this.layers.length-1;i>=0;--i){this.layers[i].destroy(false);} +this.layers=null;} +if(this.viewPortDiv){this.div.removeChild(this.viewPortDiv);} +this.viewPortDiv=null;if(this.eventListeners){this.events.un(this.eventListeners);this.eventListeners=null;} +this.events.destroy();this.events=null;},setOptions:function(options){OpenLayers.Util.extend(this,options);},getTileSize:function(){return this.tileSize;},getBy:function(array,property,match){var test=(typeof match.test=="function");var found=OpenLayers.Array.filter(this[array],function(item){return item[property]==match||(test&&match.test(item[property]));});return found;},getLayersBy:function(property,match){return this.getBy("layers",property,match);},getLayersByName:function(match){return this.getLayersBy("name",match);},getLayersByClass:function(match){return this.getLayersBy("CLASS_NAME",match);},getControlsBy:function(property,match){return this.getBy("controls",property,match);},getControlsByClass:function(match){return this.getControlsBy("CLASS_NAME",match);},getLayer:function(id){var foundLayer=null;for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];if(layer.id==id){foundLayer=layer;break;}} +return foundLayer;},setLayerZIndex:function(layer,zIdx){layer.setZIndex(this.Z_INDEX_BASE[layer.isBaseLayer?'BaseLayer':'Overlay'] ++zIdx*5);},resetLayersZIndex:function(){for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];this.setLayerZIndex(layer,i);}},addLayer:function(layer){for(var i=0,len=this.layers.length;i<len;i++){if(this.layers[i]==layer){var msg=OpenLayers.i18n('layerAlreadyAdded',{'layerName':layer.name});OpenLayers.Console.warn(msg);return false;}} +if(this.allOverlays){layer.isBaseLayer=false;} +if(this.events.triggerEvent("preaddlayer",{layer:layer})===false){return;} +layer.div.className="olLayerDiv";layer.div.style.overflow="";this.setLayerZIndex(layer,this.layers.length);if(layer.isFixed){this.viewPortDiv.appendChild(layer.div);}else{this.layerContainerDiv.appendChild(layer.div);} +this.layers.push(layer);layer.setMap(this);if(layer.isBaseLayer||(this.allOverlays&&!this.baseLayer)){if(this.baseLayer==null){this.setBaseLayer(layer);}else{layer.setVisibility(false);}}else{layer.redraw();} +this.events.triggerEvent("addlayer",{layer:layer});layer.afterAdd();},addLayers:function(layers){for(var i=0,len=layers.length;i<len;i++){this.addLayer(layers[i]);}},removeLayer:function(layer,setNewBaseLayer){if(setNewBaseLayer==null){setNewBaseLayer=true;} +if(layer.isFixed){this.viewPortDiv.removeChild(layer.div);}else{this.layerContainerDiv.removeChild(layer.div);} +OpenLayers.Util.removeItem(this.layers,layer);layer.removeMap(this);layer.map=null;if(this.baseLayer==layer){this.baseLayer=null;if(setNewBaseLayer){for(var i=0,len=this.layers.length;i<len;i++){var iLayer=this.layers[i];if(iLayer.isBaseLayer||this.allOverlays){this.setBaseLayer(iLayer);break;}}}} +this.resetLayersZIndex();this.events.triggerEvent("removelayer",{layer:layer});},getNumLayers:function(){return this.layers.length;},getLayerIndex:function(layer){return OpenLayers.Util.indexOf(this.layers,layer);},setLayerIndex:function(layer,idx){var base=this.getLayerIndex(layer);if(idx<0){idx=0;}else if(idx>this.layers.length){idx=this.layers.length;} +if(base!=idx){this.layers.splice(base,1);this.layers.splice(idx,0,layer);for(var i=0,len=this.layers.length;i<len;i++){this.setLayerZIndex(this.layers[i],i);} +this.events.triggerEvent("changelayer",{layer:layer,property:"order"});if(this.allOverlays){if(idx===0){this.setBaseLayer(layer);}else if(this.baseLayer!==this.layers[0]){this.setBaseLayer(this.layers[0]);}}}},raiseLayer:function(layer,delta){var idx=this.getLayerIndex(layer)+delta;this.setLayerIndex(layer,idx);},setBaseLayer:function(newBaseLayer){if(newBaseLayer!=this.baseLayer){if(OpenLayers.Util.indexOf(this.layers,newBaseLayer)!=-1){var center=this.getCenter();var newResolution=OpenLayers.Util.getResolutionFromScale(this.getScale(),newBaseLayer.units);if(this.baseLayer!=null&&!this.allOverlays){this.baseLayer.setVisibility(false);} +this.baseLayer=newBaseLayer;this.viewRequestID++;if(!this.allOverlays||this.baseLayer.visibility){this.baseLayer.setVisibility(true);} +if(center!=null){var newZoom=this.getZoomForResolution(newResolution||this.resolution,true);this.setCenter(center,newZoom,false,true);} +this.events.triggerEvent("changebaselayer",{layer:this.baseLayer});}}},addControl:function(control,px){this.controls.push(control);this.addControlToMap(control,px);},addControls:function(controls,pixels){var pxs=(arguments.length===1)?[]:pixels;for(var i=0,len=controls.length;i<len;i++){var ctrl=controls[i];var px=(pxs[i])?pxs[i]:null;this.addControl(ctrl,px);}},addControlToMap:function(control,px){control.outsideViewport=(control.div!=null);if(this.displayProjection&&!control.displayProjection){control.displayProjection=this.displayProjection;} +control.setMap(this);var div=control.draw(px);if(div){if(!control.outsideViewport){div.style.zIndex=this.Z_INDEX_BASE['Control']+ +this.controls.length;this.viewPortDiv.appendChild(div);}} +if(control.autoActivate){control.activate();}},getControl:function(id){var returnControl=null;for(var i=0,len=this.controls.length;i<len;i++){var control=this.controls[i];if(control.id==id){returnControl=control;break;}} +return returnControl;},removeControl:function(control){if((control)&&(control==this.getControl(control.id))){if(control.div&&(control.div.parentNode==this.viewPortDiv)){this.viewPortDiv.removeChild(control.div);} +OpenLayers.Util.removeItem(this.controls,control);}},addPopup:function(popup,exclusive){if(exclusive){for(var i=this.popups.length-1;i>=0;--i){this.removePopup(this.popups[i]);}} +popup.map=this;this.popups.push(popup);var popupDiv=popup.draw();if(popupDiv){popupDiv.style.zIndex=this.Z_INDEX_BASE['Popup']+ +this.popups.length;this.layerContainerDiv.appendChild(popupDiv);}},removePopup:function(popup){OpenLayers.Util.removeItem(this.popups,popup);if(popup.div){try{this.layerContainerDiv.removeChild(popup.div);} +catch(e){}} +popup.map=null;},getSize:function(){var size=null;if(this.size!=null){size=this.size.clone();} +return size;},updateSize:function(){var newSize=this.getCurrentSize();if(newSize&&!isNaN(newSize.h)&&!isNaN(newSize.w)){this.events.clearMouseCache();var oldSize=this.getSize();if(oldSize==null){this.size=oldSize=newSize;} +if(!newSize.equals(oldSize)){this.size=newSize;for(var i=0,len=this.layers.length;i<len;i++){this.layers[i].onMapResize();} +var center=this.getCenter();if(this.baseLayer!=null&¢er!=null){var zoom=this.getZoom();this.zoom=null;this.setCenter(center,zoom);}}}},getCurrentSize:function(){var size=new OpenLayers.Size(this.div.clientWidth,this.div.clientHeight);if(size.w==0&&size.h==0||isNaN(size.w)&&isNaN(size.h)){size.w=this.div.offsetWidth;size.h=this.div.offsetHeight;} +if(size.w==0&&size.h==0||isNaN(size.w)&&isNaN(size.h)){size.w=parseInt(this.div.style.width);size.h=parseInt(this.div.style.height);} +return size;},calculateBounds:function(center,resolution){var extent=null;if(center==null){center=this.getCenter();} +if(resolution==null){resolution=this.getResolution();} +if((center!=null)&&(resolution!=null)){var size=this.getSize();var w_deg=size.w*resolution;var h_deg=size.h*resolution;extent=new OpenLayers.Bounds(center.lon-w_deg/2,center.lat-h_deg/2,center.lon+w_deg/2,center.lat+h_deg/2);} +return extent;},getCenter:function(){var center=null;if(this.center){center=this.center.clone();} +return center;},getZoom:function(){return this.zoom;},pan:function(dx,dy,options){options=OpenLayers.Util.applyDefaults(options,{animate:true,dragging:false});var centerPx=this.getViewPortPxFromLonLat(this.getCenter());var newCenterPx=centerPx.add(dx,dy);if(!options.dragging||!newCenterPx.equals(centerPx)){var newCenterLonLat=this.getLonLatFromViewPortPx(newCenterPx);if(options.animate){this.panTo(newCenterLonLat);}else{this.setCenter(newCenterLonLat,null,options.dragging);}}},panTo:function(lonlat){if(this.panMethod&&this.getExtent().scale(this.panRatio).containsLonLat(lonlat)){if(!this.panTween){this.panTween=new OpenLayers.Tween(this.panMethod);} +var center=this.getCenter();if(lonlat.lon==center.lon&&lonlat.lat==center.lat){return;} +var from={lon:center.lon,lat:center.lat};var to={lon:lonlat.lon,lat:lonlat.lat};this.panTween.start(from,to,this.panDuration,{callbacks:{start:OpenLayers.Function.bind(function(lonlat){this.events.triggerEvent("movestart");},this),eachStep:OpenLayers.Function.bind(function(lonlat){lonlat=new OpenLayers.LonLat(lonlat.lon,lonlat.lat);this.moveTo(lonlat,this.zoom,{'dragging':true,'noEvent':true});},this),done:OpenLayers.Function.bind(function(lonlat){lonlat=new OpenLayers.LonLat(lonlat.lon,lonlat.lat);this.moveTo(lonlat,this.zoom,{'noEvent':true});this.events.triggerEvent("moveend");},this)}});}else{this.setCenter(lonlat);}},setCenter:function(lonlat,zoom,dragging,forceZoomChange){this.moveTo(lonlat,zoom,{'dragging':dragging,'forceZoomChange':forceZoomChange,'caller':'setCenter'});},moveTo:function(lonlat,zoom,options){if(!options){options={};} +if(zoom!=null){zoom=parseFloat(zoom);if(!this.fractionalZoom){zoom=Math.round(zoom);}} +var dragging=options.dragging;var forceZoomChange=options.forceZoomChange;var noEvent=options.noEvent;if(this.panTween&&options.caller=="setCenter"){this.panTween.stop();} +if(!this.center&&!this.isValidLonLat(lonlat)){lonlat=this.maxExtent.getCenterLonLat();} +if(this.restrictedExtent!=null){if(lonlat==null){lonlat=this.getCenter();} +if(zoom==null){zoom=this.getZoom();} +var resolution=this.getResolutionForZoom(zoom);var extent=this.calculateBounds(lonlat,resolution);if(!this.restrictedExtent.containsBounds(extent)){var maxCenter=this.restrictedExtent.getCenterLonLat();if(extent.getWidth()>this.restrictedExtent.getWidth()){lonlat=new OpenLayers.LonLat(maxCenter.lon,lonlat.lat);}else if(extent.left<this.restrictedExtent.left){lonlat=lonlat.add(this.restrictedExtent.left- +extent.left,0);}else if(extent.right>this.restrictedExtent.right){lonlat=lonlat.add(this.restrictedExtent.right- +extent.right,0);} +if(extent.getHeight()>this.restrictedExtent.getHeight()){lonlat=new OpenLayers.LonLat(lonlat.lon,maxCenter.lat);}else if(extent.bottom<this.restrictedExtent.bottom){lonlat=lonlat.add(0,this.restrictedExtent.bottom- +extent.bottom);} +else if(extent.top>this.restrictedExtent.top){lonlat=lonlat.add(0,this.restrictedExtent.top- +extent.top);}}} +var zoomChanged=forceZoomChange||((this.isValidZoomLevel(zoom))&&(zoom!=this.getZoom()));var centerChanged=(this.isValidLonLat(lonlat))&&(!lonlat.equals(this.center));if(zoomChanged||centerChanged||!dragging){if(!this.dragging&&!noEvent){this.events.triggerEvent("movestart");} +if(centerChanged){if((!zoomChanged)&&(this.center)){this.centerLayerContainer(lonlat);} +this.center=lonlat.clone();} +if((zoomChanged)||(this.layerContainerOrigin==null)){this.layerContainerOrigin=this.center.clone();this.layerContainerDiv.style.left="0px";this.layerContainerDiv.style.top="0px";} +if(zoomChanged){this.zoom=zoom;this.resolution=this.getResolutionForZoom(zoom);this.viewRequestID++;} +var bounds=this.getExtent();if(this.baseLayer.visibility){this.baseLayer.moveTo(bounds,zoomChanged,dragging);if(dragging){this.baseLayer.events.triggerEvent("move");}else{this.baseLayer.events.triggerEvent("moveend",{"zoomChanged":zoomChanged});}} +bounds=this.baseLayer.getExtent();for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];if(layer!==this.baseLayer&&!layer.isBaseLayer){var inRange=layer.calculateInRange();if(layer.inRange!=inRange){layer.inRange=inRange;if(!inRange){layer.display(false);} +this.events.triggerEvent("changelayer",{layer:layer,property:"visibility"});} +if(inRange&&layer.visibility){layer.moveTo(bounds,zoomChanged,dragging);if(dragging){layer.events.triggerEvent("move");}else{layer.events.triggerEvent("moveend",{"zoomChanged":zoomChanged});}}}} +if(zoomChanged){for(var i=0,len=this.popups.length;i<len;i++){this.popups[i].updatePosition();}} +this.events.triggerEvent("move");if(zoomChanged){this.events.triggerEvent("zoomend");}} +if(!dragging&&!noEvent){this.events.triggerEvent("moveend");} +this.dragging=!!dragging;},centerLayerContainer:function(lonlat){var originPx=this.getViewPortPxFromLonLat(this.layerContainerOrigin);var newPx=this.getViewPortPxFromLonLat(lonlat);if((originPx!=null)&&(newPx!=null)){this.layerContainerDiv.style.left=Math.round(originPx.x-newPx.x)+"px";this.layerContainerDiv.style.top=Math.round(originPx.y-newPx.y)+"px";}},isValidZoomLevel:function(zoomLevel){return((zoomLevel!=null)&&(zoomLevel>=0)&&(zoomLevel<this.getNumZoomLevels()));},isValidLonLat:function(lonlat){var valid=false;if(lonlat!=null){var maxExtent=this.getMaxExtent();valid=maxExtent.containsLonLat(lonlat);} +return valid;},getProjection:function(){var projection=this.getProjectionObject();return projection?projection.getCode():null;},getProjectionObject:function(){var projection=null;if(this.baseLayer!=null){projection=this.baseLayer.projection;} +return projection;},getMaxResolution:function(){var maxResolution=null;if(this.baseLayer!=null){maxResolution=this.baseLayer.maxResolution;} +return maxResolution;},getMaxExtent:function(options){var maxExtent=null;if(options&&options.restricted&&this.restrictedExtent){maxExtent=this.restrictedExtent;}else if(this.baseLayer!=null){maxExtent=this.baseLayer.maxExtent;} +return maxExtent;},getNumZoomLevels:function(){var numZoomLevels=null;if(this.baseLayer!=null){numZoomLevels=this.baseLayer.numZoomLevels;} +return numZoomLevels;},getExtent:function(){var extent=null;if(this.baseLayer!=null){extent=this.baseLayer.getExtent();} +return extent;},getResolution:function(){var resolution=null;if(this.baseLayer!=null){resolution=this.baseLayer.getResolution();}else if(this.allOverlays===true&&this.layers.length>0){resolution=this.layers[0].getResolution();} +return resolution;},getUnits:function(){var units=null;if(this.baseLayer!=null){units=this.baseLayer.units;} +return units;},getScale:function(){var scale=null;if(this.baseLayer!=null){var res=this.getResolution();var units=this.baseLayer.units;scale=OpenLayers.Util.getScaleFromResolution(res,units);} +return scale;},getZoomForExtent:function(bounds,closest){var zoom=null;if(this.baseLayer!=null){zoom=this.baseLayer.getZoomForExtent(bounds,closest);} +return zoom;},getResolutionForZoom:function(zoom){var resolution=null;if(this.baseLayer){resolution=this.baseLayer.getResolutionForZoom(zoom);} +return resolution;},getZoomForResolution:function(resolution,closest){var zoom=null;if(this.baseLayer!=null){zoom=this.baseLayer.getZoomForResolution(resolution,closest);} +return zoom;},zoomTo:function(zoom){if(this.isValidZoomLevel(zoom)){this.setCenter(null,zoom);}},zoomIn:function(){this.zoomTo(this.getZoom()+1);},zoomOut:function(){this.zoomTo(this.getZoom()-1);},zoomToExtent:function(bounds,closest){var center=bounds.getCenterLonLat();if(this.baseLayer.wrapDateLine){var maxExtent=this.getMaxExtent();bounds=bounds.clone();while(bounds.right<bounds.left){bounds.right+=maxExtent.getWidth();} +center=bounds.getCenterLonLat().wrapDateLine(maxExtent);} +this.setCenter(center,this.getZoomForExtent(bounds,closest));},zoomToMaxExtent:function(options){var restricted=(options)?options.restricted:true;var maxExtent=this.getMaxExtent({'restricted':restricted});this.zoomToExtent(maxExtent);},zoomToScale:function(scale,closest){var res=OpenLayers.Util.getResolutionFromScale(scale,this.baseLayer.units);var size=this.getSize();var w_deg=size.w*res;var h_deg=size.h*res;var center=this.getCenter();var extent=new OpenLayers.Bounds(center.lon-w_deg/2,center.lat-h_deg/2,center.lon+w_deg/2,center.lat+h_deg/2);this.zoomToExtent(extent,closest);},getLonLatFromViewPortPx:function(viewPortPx){var lonlat=null;if(this.baseLayer!=null){lonlat=this.baseLayer.getLonLatFromViewPortPx(viewPortPx);} +return lonlat;},getViewPortPxFromLonLat:function(lonlat){var px=null;if(this.baseLayer!=null){px=this.baseLayer.getViewPortPxFromLonLat(lonlat);} +return px;},getLonLatFromPixel:function(px){return this.getLonLatFromViewPortPx(px);},getPixelFromLonLat:function(lonlat){var px=this.getViewPortPxFromLonLat(lonlat);px.x=Math.round(px.x);px.y=Math.round(px.y);return px;},getGeodesicPixelSize:function(px){var lonlat=px?this.getLonLatFromPixel(px):(this.getCenter()||new OpenLayers.LonLat(0,0));var res=this.getResolution();var left=lonlat.add(-res/2,0);var right=lonlat.add(res/2,0);var bottom=lonlat.add(0,-res/2);var top=lonlat.add(0,res/2);var dest=new OpenLayers.Projection("EPSG:4326");var source=this.getProjectionObject()||dest;if(!source.equals(dest)){left.transform(source,dest);right.transform(source,dest);bottom.transform(source,dest);top.transform(source,dest);} +return new OpenLayers.Size(OpenLayers.Util.distVincenty(left,right),OpenLayers.Util.distVincenty(bottom,top));},getViewPortPxFromLayerPx:function(layerPx){var viewPortPx=null;if(layerPx!=null){var dX=parseInt(this.layerContainerDiv.style.left);var dY=parseInt(this.layerContainerDiv.style.top);viewPortPx=layerPx.add(dX,dY);} +return viewPortPx;},getLayerPxFromViewPortPx:function(viewPortPx){var layerPx=null;if(viewPortPx!=null){var dX=-parseInt(this.layerContainerDiv.style.left);var dY=-parseInt(this.layerContainerDiv.style.top);layerPx=viewPortPx.add(dX,dY);if(isNaN(layerPx.x)||isNaN(layerPx.y)){layerPx=null;}} +return layerPx;},getLonLatFromLayerPx:function(px){px=this.getViewPortPxFromLayerPx(px);return this.getLonLatFromViewPortPx(px);},getLayerPxFromLonLat:function(lonlat){var px=this.getPixelFromLonLat(lonlat);return this.getLayerPxFromViewPortPx(px);},CLASS_NAME:"OpenLayers.Map"});OpenLayers.Map.TILE_WIDTH=256;OpenLayers.Map.TILE_HEIGHT=256;OpenLayers.Marker=OpenLayers.Class({icon:null,lonlat:null,events:null,map:null,initialize:function(lonlat,icon){this.lonlat=lonlat;var newIcon=(icon)?icon:OpenLayers.Marker.defaultIcon();if(this.icon==null){this.icon=newIcon;}else{this.icon.url=newIcon.url;this.icon.size=newIcon.size;this.icon.offset=newIcon.offset;this.icon.calculateOffset=newIcon.calculateOffset;} +this.events=new OpenLayers.Events(this,this.icon.imageDiv,null);},destroy:function(){this.erase();this.map=null;this.events.destroy();this.events=null;if(this.icon!=null){this.icon.destroy();this.icon=null;}},draw:function(px){return this.icon.draw(px);},erase:function(){if(this.icon!=null){this.icon.erase();}},moveTo:function(px){if((px!=null)&&(this.icon!=null)){this.icon.moveTo(px);} +this.lonlat=this.map.getLonLatFromLayerPx(px);},isDrawn:function(){var isDrawn=(this.icon&&this.icon.isDrawn());return isDrawn;},onScreen:function(){var onScreen=false;if(this.map){var screenBounds=this.map.getExtent();onScreen=screenBounds.containsLonLat(this.lonlat);} +return onScreen;},inflate:function(inflate){if(this.icon){var newSize=new OpenLayers.Size(this.icon.size.w*inflate,this.icon.size.h*inflate);this.icon.setSize(newSize);}},setOpacity:function(opacity){this.icon.setOpacity(opacity);},setUrl:function(url){this.icon.setUrl(url);},display:function(display){this.icon.display(display);},CLASS_NAME:"OpenLayers.Marker"});OpenLayers.Marker.defaultIcon=function(){var url=OpenLayers.Util.getImagesLocation()+"marker.png";var size=new OpenLayers.Size(21,25);var calculateOffset=function(size){return new OpenLayers.Pixel(-(size.w/2),-size.h);};return new OpenLayers.Icon(url,size,null,calculateOffset);};OpenLayers.Popup.FramedCloud=OpenLayers.Class(OpenLayers.Popup.Framed,{contentDisplayClass:"olFramedCloudPopupContent",autoSize:true,panMapIfOutOfView:true,imageSize:new OpenLayers.Size(1276,736),isAlphaImage:false,fixedRelativePosition:false,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(id,lonlat,contentSize,contentHTML,anchor,closeBox,closeBoxCallback){this.imageSrc=OpenLayers.Util.getImagesLocation()+'cloud-popup-relative.png';OpenLayers.Popup.Framed.prototype.initialize.apply(this,arguments);this.contentDiv.className=this.contentDisplayClass;},destroy:function(){OpenLayers.Popup.Framed.prototype.destroy.apply(this,arguments);},CLASS_NAME:"OpenLayers.Popup.FramedCloud"});OpenLayers.Request={DEFAULT_CONFIG:{method:"GET",url:window.location.href,async:true,user:undefined,password:undefined,params:null,proxy:OpenLayers.ProxyHost,headers:{},data:null,callback:function(){},success:null,failure:null,scope:null},events:new OpenLayers.Events(this,null,["complete","success","failure"]),issue:function(config){var defaultConfig=OpenLayers.Util.extend(this.DEFAULT_CONFIG,{proxy:OpenLayers.ProxyHost});config=OpenLayers.Util.applyDefaults(config,defaultConfig);var request=new OpenLayers.Request.XMLHttpRequest();var url=config.url;if(config.params){var paramString=OpenLayers.Util.getParameterString(config.params);if(paramString.length>0){var separator=(url.indexOf('?')>-1)?'&':'?';url+=separator+paramString;}} +if(config.proxy&&(url.indexOf("http")==0)){if(typeof config.proxy=="function"){url=config.proxy(url);}else{url=config.proxy+encodeURIComponent(url);}} +request.open(config.method,url,config.async,config.user,config.password);for(var header in config.headers){request.setRequestHeader(header,config.headers[header]);} +var events=this.events;var self=this;request.onreadystatechange=function(){if(request.readyState==OpenLayers.Request.XMLHttpRequest.DONE){var proceed=events.triggerEvent("complete",{request:request,config:config,requestUrl:url});if(proceed!==false){self.runCallbacks({request:request,config:config,requestUrl:url});}}};if(config.async===false){request.send(config.data);}else{window.setTimeout(function(){if(request._aborted!==true){request.send(config.data);}},0);} +return request;},runCallbacks:function(options){var request=options.request;var config=options.config;var complete=(config.scope)?OpenLayers.Function.bind(config.callback,config.scope):config.callback;var success;if(config.success){success=(config.scope)?OpenLayers.Function.bind(config.success,config.scope):config.success;} +var failure;if(config.failure){failure=(config.scope)?OpenLayers.Function.bind(config.failure,config.scope):config.failure;} +complete(request);if(!request.status||(request.status>=200&&request.status<300)){this.events.triggerEvent("success",options);if(success){success(request);}} +if(request.status&&(request.status<200||request.status>=300)){this.events.triggerEvent("failure",options);if(failure){failure(request);}}},GET:function(config){config=OpenLayers.Util.extend(config,{method:"GET"});return OpenLayers.Request.issue(config);},POST:function(config){config=OpenLayers.Util.extend(config,{method:"POST"});config.headers=config.headers?config.headers:{};if(!("CONTENT-TYPE"in OpenLayers.Util.upperCaseObject(config.headers))){config.headers["Content-Type"]="application/xml";} +return OpenLayers.Request.issue(config);},PUT:function(config){config=OpenLayers.Util.extend(config,{method:"PUT"});config.headers=config.headers?config.headers:{};if(!("CONTENT-TYPE"in OpenLayers.Util.upperCaseObject(config.headers))){config.headers["Content-Type"]="application/xml";} +return OpenLayers.Request.issue(config);},DELETE:function(config){config=OpenLayers.Util.extend(config,{method:"DELETE"});return OpenLayers.Request.issue(config);},HEAD:function(config){config=OpenLayers.Util.extend(config,{method:"HEAD"});return OpenLayers.Request.issue(config);},OPTIONS:function(config){config=OpenLayers.Util.extend(config,{method:"OPTIONS"});return OpenLayers.Request.issue(config);}};OpenLayers.Tile.Image=OpenLayers.Class(OpenLayers.Tile,{url:null,imgDiv:null,frame:null,layerAlphaHack:null,isBackBuffer:false,lastRatio:1,isFirstDraw:true,backBufferTile:null,initialize:function(layer,position,bounds,url,size){OpenLayers.Tile.prototype.initialize.apply(this,arguments);this.url=url;this.frame=document.createElement('div');this.frame.style.overflow='hidden';this.frame.style.position='absolute';this.layerAlphaHack=this.layer.alpha&&OpenLayers.Util.alphaHack();},destroy:function(){if(this.imgDiv!=null){if(this.layerAlphaHack){OpenLayers.Event.stopObservingElement(this.imgDiv.childNodes[0]);} +OpenLayers.Event.stopObservingElement(this.imgDiv);if(this.imgDiv.parentNode==this.frame){this.frame.removeChild(this.imgDiv);this.imgDiv.map=null;} +this.imgDiv.urls=null;this.imgDiv.src=OpenLayers.Util.getImagesLocation()+"blank.gif";} +this.imgDiv=null;if((this.frame!=null)&&(this.frame.parentNode==this.layer.div)){this.layer.div.removeChild(this.frame);} +this.frame=null;if(this.backBufferTile){this.backBufferTile.destroy();this.backBufferTile=null;} +this.layer.events.unregister("loadend",this,this.resetBackBuffer);OpenLayers.Tile.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Tile.Image(this.layer,this.position,this.bounds,this.url,this.size);} +obj=OpenLayers.Tile.prototype.clone.apply(this,[obj]);obj.imgDiv=null;return obj;},draw:function(){if(this.layer!=this.layer.map.baseLayer&&this.layer.reproject){this.bounds=this.getBoundsFromBaseLayer(this.position);} +var drawTile=OpenLayers.Tile.prototype.draw.apply(this,arguments);if((OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS,this.layer.transitionEffect)!=-1)||this.layer.singleTile){if(drawTile){if(!this.backBufferTile){this.backBufferTile=this.clone();this.backBufferTile.hide();this.backBufferTile.isBackBuffer=true;this.events.register('loadend',this,this.resetBackBuffer);this.layer.events.register("loadend",this,this.resetBackBuffer);} +this.startTransition();}else{if(this.backBufferTile){this.backBufferTile.clear();}}}else{if(drawTile&&this.isFirstDraw){this.events.register('loadend',this,this.showTile);this.isFirstDraw=false;}} +if(!drawTile){return false;} +if(this.isLoading){this.events.triggerEvent("reload");}else{this.isLoading=true;this.events.triggerEvent("loadstart");} +return this.renderTile();},resetBackBuffer:function(){this.showTile();if(this.backBufferTile&&(this.isFirstDraw||!this.layer.numLoadingTiles)){this.isFirstDraw=false;var maxExtent=this.layer.maxExtent;var withinMaxExtent=(maxExtent&&this.bounds.intersectsBounds(maxExtent,false));if(withinMaxExtent){this.backBufferTile.position=this.position;this.backBufferTile.bounds=this.bounds;this.backBufferTile.size=this.size;this.backBufferTile.imageSize=this.layer.getImageSize(this.bounds)||this.size;this.backBufferTile.imageOffset=this.layer.imageOffset;this.backBufferTile.resolution=this.layer.getResolution();this.backBufferTile.renderTile();} +this.backBufferTile.hide();}},renderTile:function(){if(this.imgDiv==null){this.initImgDiv();} +this.imgDiv.viewRequestID=this.layer.map.viewRequestID;if(this.layer.async){this.layer.getURLasync(this.bounds,this,"url",this.positionImage);}else{if(this.layer.url instanceof Array){this.imgDiv.urls=this.layer.url.slice();} +this.url=this.layer.getURL(this.bounds);this.positionImage();} +return true;},positionImage:function(){if(this.layer===null){return;} +OpenLayers.Util.modifyDOMElement(this.frame,null,this.position,this.size);var imageSize=this.layer.getImageSize(this.bounds);if(this.layerAlphaHack){OpenLayers.Util.modifyAlphaImageDiv(this.imgDiv,null,null,imageSize,this.url);}else{OpenLayers.Util.modifyDOMElement(this.imgDiv,null,null,imageSize);this.imgDiv.src=this.url;}},clear:function(){if(this.imgDiv){this.hide();if(OpenLayers.Tile.Image.useBlankTile){this.imgDiv.src=OpenLayers.Util.getImagesLocation()+"blank.gif";}}},initImgDiv:function(){var offset=this.layer.imageOffset;var size=this.layer.getImageSize(this.bounds);if(this.layerAlphaHack){this.imgDiv=OpenLayers.Util.createAlphaImageDiv(null,offset,size,null,"relative",null,null,null,true);}else{this.imgDiv=OpenLayers.Util.createImage(null,offset,size,null,"relative",null,null,true);} +this.imgDiv.className='olTileImage';this.frame.style.zIndex=this.isBackBuffer?0:1;this.frame.appendChild(this.imgDiv);this.layer.div.appendChild(this.frame);if(this.layer.opacity!=null){OpenLayers.Util.modifyDOMElement(this.imgDiv,null,null,null,null,null,null,this.layer.opacity);} +this.imgDiv.map=this.layer.map;var onload=function(){if(this.isLoading){this.isLoading=false;this.events.triggerEvent("loadend");}};if(this.layerAlphaHack){OpenLayers.Event.observe(this.imgDiv.childNodes[0],'load',OpenLayers.Function.bind(onload,this));}else{OpenLayers.Event.observe(this.imgDiv,'load',OpenLayers.Function.bind(onload,this));} +var onerror=function(){if(this.imgDiv._attempts>OpenLayers.IMAGE_RELOAD_ATTEMPTS){onload.call(this);}};OpenLayers.Event.observe(this.imgDiv,"error",OpenLayers.Function.bind(onerror,this));},checkImgURL:function(){if(this.layer){var loaded=this.layerAlphaHack?this.imgDiv.firstChild.src:this.imgDiv.src;if(!OpenLayers.Util.isEquivalentUrl(loaded,this.url)){this.hide();}}},startTransition:function(){if(!this.backBufferTile||!this.backBufferTile.imgDiv){return;} +var ratio=1;if(this.backBufferTile.resolution){ratio=this.backBufferTile.resolution/this.layer.getResolution();} +if(ratio!=this.lastRatio){if(this.layer.transitionEffect=='resize'){var upperLeft=new OpenLayers.LonLat(this.backBufferTile.bounds.left,this.backBufferTile.bounds.top);var size=new OpenLayers.Size(this.backBufferTile.size.w*ratio,this.backBufferTile.size.h*ratio);var px=this.layer.map.getLayerPxFromLonLat(upperLeft);OpenLayers.Util.modifyDOMElement(this.backBufferTile.frame,null,px,size);var imageSize=this.backBufferTile.imageSize;imageSize=new OpenLayers.Size(imageSize.w*ratio,imageSize.h*ratio);var imageOffset=this.backBufferTile.imageOffset;if(imageOffset){imageOffset=new OpenLayers.Pixel(imageOffset.x*ratio,imageOffset.y*ratio);} +OpenLayers.Util.modifyDOMElement(this.backBufferTile.imgDiv,null,imageOffset,imageSize);this.backBufferTile.show();}}else{if(this.layer.singleTile){this.backBufferTile.show();}else{this.backBufferTile.hide();}} +this.lastRatio=ratio;},show:function(){this.frame.style.display='';if(OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS,this.layer.transitionEffect)!=-1){if(navigator.userAgent.toLowerCase().indexOf("gecko")!=-1){this.frame.scrollLeft=this.frame.scrollLeft;}}},hide:function(){this.frame.style.display='none';},CLASS_NAME:"OpenLayers.Tile.Image"});OpenLayers.Tile.Image.useBlankTile=(OpenLayers.Util.getBrowserName()=="safari"||OpenLayers.Util.getBrowserName()=="opera");OpenLayers.Control.OverviewMap=OpenLayers.Class(OpenLayers.Control,{element:null,ovmap:null,size:new OpenLayers.Size(180,90),layers:null,minRectSize:15,minRectDisplayClass:"RectReplacement",minRatio:8,maxRatio:32,mapOptions:null,autoPan:false,handlers:null,resolutionFactor:1,maximized:false,initialize:function(options){this.layers=[];this.handlers={};OpenLayers.Control.prototype.initialize.apply(this,[options]);},destroy:function(){if(!this.mapDiv){return;} +if(this.handlers.click){this.handlers.click.destroy();} +if(this.handlers.drag){this.handlers.drag.destroy();} +this.mapDiv.removeChild(this.extentRectangle);this.extentRectangle=null;if(this.rectEvents){this.rectEvents.destroy();this.rectEvents=null;} +if(this.ovmap){this.ovmap.destroy();this.ovmap=null;} +this.element.removeChild(this.mapDiv);this.mapDiv=null;this.div.removeChild(this.element);this.element=null;if(this.maximizeDiv){OpenLayers.Event.stopObservingElement(this.maximizeDiv);this.div.removeChild(this.maximizeDiv);this.maximizeDiv=null;} +if(this.minimizeDiv){OpenLayers.Event.stopObservingElement(this.minimizeDiv);this.div.removeChild(this.minimizeDiv);this.minimizeDiv=null;} +this.map.events.un({"moveend":this.update,"changebaselayer":this.baseLayerDraw,scope:this});OpenLayers.Control.prototype.destroy.apply(this,arguments);},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!(this.layers.length>0)){if(this.map.baseLayer){var layer=this.map.baseLayer.clone();this.layers=[layer];}else{this.map.events.register("changebaselayer",this,this.baseLayerDraw);return this.div;}} +this.element=document.createElement('div');this.element.className=this.displayClass+'Element';this.element.style.display='none';this.mapDiv=document.createElement('div');this.mapDiv.style.width=this.size.w+'px';this.mapDiv.style.height=this.size.h+'px';this.mapDiv.style.position='relative';this.mapDiv.style.overflow='hidden';this.mapDiv.id=OpenLayers.Util.createUniqueID('overviewMap');this.extentRectangle=document.createElement('div');this.extentRectangle.style.position='absolute';this.extentRectangle.style.zIndex=1000;this.extentRectangle.className=this.displayClass+'ExtentRectangle';this.mapDiv.appendChild(this.extentRectangle);this.element.appendChild(this.mapDiv);this.div.appendChild(this.element);if(!this.outsideViewport){this.div.className+=" "+this.displayClass+'Container';var imgLocation=OpenLayers.Util.getImagesLocation();var img=imgLocation+'layer-switcher-maximize.png';this.maximizeDiv=OpenLayers.Util.createAlphaImageDiv(this.displayClass+'MaximizeButton',null,new OpenLayers.Size(18,18),img,'absolute');this.maximizeDiv.style.display='none';this.maximizeDiv.className=this.displayClass+'MaximizeButton';OpenLayers.Event.observe(this.maximizeDiv,'click',OpenLayers.Function.bindAsEventListener(this.maximizeControl,this));this.div.appendChild(this.maximizeDiv);var img=imgLocation+'layer-switcher-minimize.png';this.minimizeDiv=OpenLayers.Util.createAlphaImageDiv('OpenLayers_Control_minimizeDiv',null,new OpenLayers.Size(18,18),img,'absolute');this.minimizeDiv.style.display='none';this.minimizeDiv.className=this.displayClass+'MinimizeButton';OpenLayers.Event.observe(this.minimizeDiv,'click',OpenLayers.Function.bindAsEventListener(this.minimizeControl,this));this.div.appendChild(this.minimizeDiv);var eventsToStop=['dblclick','mousedown'];for(var i=0,len=eventsToStop.length;i<len;i++){OpenLayers.Event.observe(this.maximizeDiv,eventsToStop[i],OpenLayers.Event.stop);OpenLayers.Event.observe(this.minimizeDiv,eventsToStop[i],OpenLayers.Event.stop);} +this.minimizeControl();}else{this.element.style.display='';} +if(this.map.getExtent()){this.update();} +this.map.events.register('moveend',this,this.update);if(this.maximized){this.maximizeControl();} +return this.div;},baseLayerDraw:function(){this.draw();this.map.events.unregister("changebaselayer",this,this.baseLayerDraw);},rectDrag:function(px){var deltaX=this.handlers.drag.last.x-px.x;var deltaY=this.handlers.drag.last.y-px.y;if(deltaX!=0||deltaY!=0){var rectTop=this.rectPxBounds.top;var rectLeft=this.rectPxBounds.left;var rectHeight=Math.abs(this.rectPxBounds.getHeight());var rectWidth=this.rectPxBounds.getWidth();var newTop=Math.max(0,(rectTop-deltaY));newTop=Math.min(newTop,this.ovmap.size.h-this.hComp-rectHeight);var newLeft=Math.max(0,(rectLeft-deltaX));newLeft=Math.min(newLeft,this.ovmap.size.w-this.wComp-rectWidth);this.setRectPxBounds(new OpenLayers.Bounds(newLeft,newTop+rectHeight,newLeft+rectWidth,newTop));}},mapDivClick:function(evt){var pxCenter=this.rectPxBounds.getCenterPixel();var deltaX=evt.xy.x-pxCenter.x;var deltaY=evt.xy.y-pxCenter.y;var top=this.rectPxBounds.top;var left=this.rectPxBounds.left;var height=Math.abs(this.rectPxBounds.getHeight());var width=this.rectPxBounds.getWidth();var newTop=Math.max(0,(top+deltaY));newTop=Math.min(newTop,this.ovmap.size.h-height);var newLeft=Math.max(0,(left+deltaX));newLeft=Math.min(newLeft,this.ovmap.size.w-width);this.setRectPxBounds(new OpenLayers.Bounds(newLeft,newTop+height,newLeft+width,newTop));this.updateMapToRect();},maximizeControl:function(e){this.element.style.display='';this.showToggle(false);if(e!=null){OpenLayers.Event.stop(e);}},minimizeControl:function(e){this.element.style.display='none';this.showToggle(true);if(e!=null){OpenLayers.Event.stop(e);}},showToggle:function(minimize){this.maximizeDiv.style.display=minimize?'':'none';this.minimizeDiv.style.display=minimize?'none':'';},update:function(){if(this.ovmap==null){this.createMap();} +if(this.autoPan||!this.isSuitableOverview()){this.updateOverview();} +this.updateRectToMap();},isSuitableOverview:function(){var mapExtent=this.map.getExtent();var maxExtent=this.map.maxExtent;var testExtent=new OpenLayers.Bounds(Math.max(mapExtent.left,maxExtent.left),Math.max(mapExtent.bottom,maxExtent.bottom),Math.min(mapExtent.right,maxExtent.right),Math.min(mapExtent.top,maxExtent.top));if(this.ovmap.getProjection()!=this.map.getProjection()){testExtent=testExtent.transform(this.map.getProjectionObject(),this.ovmap.getProjectionObject());} +var resRatio=this.ovmap.getResolution()/this.map.getResolution();return((resRatio>this.minRatio)&&(resRatio<=this.maxRatio)&&(this.ovmap.getExtent().containsBounds(testExtent)));},updateOverview:function(){var mapRes=this.map.getResolution();var targetRes=this.ovmap.getResolution();var resRatio=targetRes/mapRes;if(resRatio>this.maxRatio){targetRes=this.minRatio*mapRes;}else if(resRatio<=this.minRatio){targetRes=this.maxRatio*mapRes;} +var center;if(this.ovmap.getProjection()!=this.map.getProjection()){center=this.map.center.clone();center.transform(this.map.getProjectionObject(),this.ovmap.getProjectionObject());}else{center=this.map.center;} +this.ovmap.setCenter(center,this.ovmap.getZoomForResolution(targetRes*this.resolutionFactor));this.updateRectToMap();},createMap:function(){var options=OpenLayers.Util.extend({controls:[],maxResolution:'auto',fallThrough:false},this.mapOptions);this.ovmap=new OpenLayers.Map(this.mapDiv,options);OpenLayers.Event.stopObserving(window,'unload',this.ovmap.unloadDestroy);this.ovmap.addLayers(this.layers);this.ovmap.zoomToMaxExtent();this.wComp=parseInt(OpenLayers.Element.getStyle(this.extentRectangle,'border-left-width'))+ +parseInt(OpenLayers.Element.getStyle(this.extentRectangle,'border-right-width'));this.wComp=(this.wComp)?this.wComp:2;this.hComp=parseInt(OpenLayers.Element.getStyle(this.extentRectangle,'border-top-width'))+ +parseInt(OpenLayers.Element.getStyle(this.extentRectangle,'border-bottom-width'));this.hComp=(this.hComp)?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":true,"double":false,"stopSingle":true,"stopDouble":true,"pixelTolerance":1,map:this.ovmap});this.handlers.click.activate();this.rectEvents=new OpenLayers.Events(this,this.extentRectangle,null,true);this.rectEvents.register("mouseover",this,function(e){if(!this.handlers.drag.active&&!this.map.dragging){this.handlers.drag.activate();}});this.rectEvents.register("mouseout",this,function(e){if(!this.handlers.drag.dragging){this.handlers.drag.deactivate();}});if(this.ovmap.getProjection()!=this.map.getProjection()){var sourceUnits=this.map.getProjectionObject().getUnits()||this.map.units||this.map.baseLayer.units;var targetUnits=this.ovmap.getProjectionObject().getUnits()||this.ovmap.units||this.ovmap.baseLayer.units;this.resolutionFactor=sourceUnits&&targetUnits?OpenLayers.INCHES_PER_UNIT[sourceUnits]/OpenLayers.INCHES_PER_UNIT[targetUnits]:1;}},updateRectToMap:function(){var bounds;if(this.ovmap.getProjection()!=this.map.getProjection()){bounds=this.map.getExtent().transform(this.map.getProjectionObject(),this.ovmap.getProjectionObject());}else{bounds=this.map.getExtent();} +var pxBounds=this.getRectBoundsFromMapBounds(bounds);if(pxBounds){this.setRectPxBounds(pxBounds);}},updateMapToRect:function(){var lonLatBounds=this.getMapBoundsFromRectBounds(this.rectPxBounds);if(this.ovmap.getProjection()!=this.map.getProjection()){lonLatBounds=lonLatBounds.transform(this.ovmap.getProjectionObject(),this.map.getProjectionObject());} +this.map.panTo(lonLatBounds.getCenterLonLat());},setRectPxBounds:function(pxBounds){var top=Math.max(pxBounds.top,0);var left=Math.max(pxBounds.left,0);var bottom=Math.min(pxBounds.top+Math.abs(pxBounds.getHeight()),this.ovmap.size.h-this.hComp);var right=Math.min(pxBounds.left+pxBounds.getWidth(),this.ovmap.size.w-this.wComp);var width=Math.max(right-left,0);var height=Math.max(bottom-top,0);if(width<this.minRectSize||height<this.minRectSize){this.extentRectangle.className=this.displayClass+ +this.minRectDisplayClass;var rLeft=left+(width/2)-(this.minRectSize/2);var rTop=top+(height/2)-(this.minRectSize/2);this.extentRectangle.style.top=Math.round(rTop)+'px';this.extentRectangle.style.left=Math.round(rLeft)+'px';this.extentRectangle.style.height=this.minRectSize+'px';this.extentRectangle.style.width=this.minRectSize+'px';}else{this.extentRectangle.className=this.displayClass+'ExtentRectangle';this.extentRectangle.style.top=Math.round(top)+'px';this.extentRectangle.style.left=Math.round(left)+'px';this.extentRectangle.style.height=Math.round(height)+'px';this.extentRectangle.style.width=Math.round(width)+'px';} +this.rectPxBounds=new OpenLayers.Bounds(Math.round(left),Math.round(bottom),Math.round(right),Math.round(top));},getRectBoundsFromMapBounds:function(lonLatBounds){var leftBottomLonLat=new OpenLayers.LonLat(lonLatBounds.left,lonLatBounds.bottom);var rightTopLonLat=new OpenLayers.LonLat(lonLatBounds.right,lonLatBounds.top);var leftBottomPx=this.getOverviewPxFromLonLat(leftBottomLonLat);var rightTopPx=this.getOverviewPxFromLonLat(rightTopLonLat);var bounds=null;if(leftBottomPx&&rightTopPx){bounds=new OpenLayers.Bounds(leftBottomPx.x,leftBottomPx.y,rightTopPx.x,rightTopPx.y);} +return bounds;},getMapBoundsFromRectBounds:function(pxBounds){var leftBottomPx=new OpenLayers.Pixel(pxBounds.left,pxBounds.bottom);var rightTopPx=new OpenLayers.Pixel(pxBounds.right,pxBounds.top);var leftBottomLonLat=this.getLonLatFromOverviewPx(leftBottomPx);var rightTopLonLat=this.getLonLatFromOverviewPx(rightTopPx);return new OpenLayers.Bounds(leftBottomLonLat.lon,leftBottomLonLat.lat,rightTopLonLat.lon,rightTopLonLat.lat);},getLonLatFromOverviewPx:function(overviewMapPx){var size=this.ovmap.size;var res=this.ovmap.getResolution();var center=this.ovmap.getExtent().getCenterLonLat();var delta_x=overviewMapPx.x-(size.w/2);var delta_y=overviewMapPx.y-(size.h/2);return new OpenLayers.LonLat(center.lon+delta_x*res,center.lat-delta_y*res);},getOverviewPxFromLonLat:function(lonlat){var res=this.ovmap.getResolution();var extent=this.ovmap.getExtent();var px=null;if(extent){px=new OpenLayers.Pixel(Math.round(1/res*(lonlat.lon-extent.left)),Math.round(1/res*(extent.top-lonlat.lat)));} +return px;},CLASS_NAME:'OpenLayers.Control.OverviewMap'});OpenLayers.Feature=OpenLayers.Class({layer:null,id:null,lonlat:null,data:null,marker:null,popupClass:OpenLayers.Popup.AnchoredBubble,popup:null,initialize:function(layer,lonlat,data){this.layer=layer;this.lonlat=lonlat;this.data=(data!=null)?data:{};this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){if((this.layer!=null)&&(this.layer.map!=null)){if(this.popup!=null){this.layer.map.removePopup(this.popup);}} +if(this.layer!=null&&this.marker!=null){this.layer.removeMarker(this.marker);} +this.layer=null;this.id=null;this.lonlat=null;this.data=null;if(this.marker!=null){this.destroyMarker(this.marker);this.marker=null;} +if(this.popup!=null){this.destroyPopup(this.popup);this.popup=null;}},onScreen:function(){var onScreen=false;if((this.layer!=null)&&(this.layer.map!=null)){var screenBounds=this.layer.map.getExtent();onScreen=screenBounds.containsLonLat(this.lonlat);} +return onScreen;},createMarker:function(){if(this.lonlat!=null){this.marker=new OpenLayers.Marker(this.lonlat,this.data.icon);} +return this.marker;},destroyMarker:function(){this.marker.destroy();},createPopup:function(closeBox){if(this.lonlat!=null){var id=this.id+"_popup";var anchor=(this.marker)?this.marker.icon:null;if(!this.popup){this.popup=new this.popupClass(id,this.lonlat,this.data.popupSize,this.data.popupContentHTML,anchor,closeBox);} +if(this.data.overflow!=null){this.popup.contentDiv.style.overflow=this.data.overflow;} +this.popup.feature=this;} +return this.popup;},destroyPopup:function(){if(this.popup){this.popup.feature=null;this.popup.destroy();this.popup=null;}},CLASS_NAME:"OpenLayers.Feature"});OpenLayers.Format.CSWGetDomain.v2_0_2=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance",csw:"http://www.opengis.net/cat/csw/2.0.2"},defaultPrefix:"csw",version:"2.0.2",schemaLocation:"http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",PropertyName:null,ParameterName:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +if(data&&data.nodeType==9){data=data.documentElement;} +var obj={};this.readNode(data,obj);return obj;},readers:{"csw":{"GetDomainResponse":function(node,obj){this.readChildNodes(node,obj);},"DomainValues":function(node,obj){if(!(obj.DomainValues instanceof Array)){obj.DomainValues=[];} +var attrs=node.attributes;var domainValue={};for(var i=0,len=attrs.length;i<len;++i){domainValue[attrs[i].name]=attrs[i].nodeValue;} +this.readChildNodes(node,domainValue);obj.DomainValues.push(domainValue);},"PropertyName":function(node,obj){obj.PropertyName=this.getChildValue(node);},"ParameterName":function(node,obj){obj.ParameterName=this.getChildValue(node);},"ListOfValues":function(node,obj){if(!(obj.ListOfValues instanceof Array)){obj.ListOfValues=[];} +this.readChildNodes(node,obj.ListOfValues);},"Value":function(node,obj){var attrs=node.attributes;var value={} +for(var i=0,len=attrs.length;i<len;++i){value[attrs[i].name]=attrs[i].nodeValue;} +value.value=this.getChildValue(node);obj.push({Value:value});},"ConceptualScheme":function(node,obj){obj.ConceptualScheme={};this.readChildNodes(node,obj.ConceptualScheme);},"Name":function(node,obj){obj.Name=this.getChildValue(node);},"Document":function(node,obj){obj.Document=this.getChildValue(node);},"Authority":function(node,obj){obj.Authority=this.getChildValue(node);},"RangeOfValues":function(node,obj){obj.RangeOfValues={};this.readChildNodes(node,obj.RangeOfValues);},"MinValue":function(node,obj){var attrs=node.attributes;var value={} +for(var i=0,len=attrs.length;i<len;++i){value[attrs[i].name]=attrs[i].nodeValue;} +value.value=this.getChildValue(node);obj.MinValue=value;},"MaxValue":function(node,obj){var attrs=node.attributes;var value={} +for(var i=0,len=attrs.length;i<len;++i){value[attrs[i].name]=attrs[i].nodeValue;} +value.value=this.getChildValue(node);obj.MaxValue=value;}}},write:function(options){var node=this.writeNode("csw:GetDomain",options);return OpenLayers.Format.XML.prototype.write.apply(this,[node]);},writers:{"csw":{"GetDomain":function(options){var node=this.createElementNSPlus("csw:GetDomain",{attributes:{service:"CSW",version:this.version}});if(options.PropertyName||this.PropertyName){this.writeNode("csw:PropertyName",options.PropertyName||this.PropertyName,node);}else if(options.ParameterName||this.ParameterName){this.writeNode("csw:ParameterName",options.ParameterName||this.ParameterName,node);} +this.readChildNodes(node,options);return node;},"PropertyName":function(value){var node=this.createElementNSPlus("csw:PropertyName",{value:value});return node;},"ParameterName":function(value){var node=this.createElementNSPlus("csw:ParameterName",{value:value});return node;}}},CLASS_NAME:"OpenLayers.Format.CSWGetDomain.v2_0_2"});OpenLayers.Format.Context=OpenLayers.Class({version:null,layerOptions:null,layerParams:null,parser:null,initialize:function(options){OpenLayers.Util.extend(this,options);this.options=options;},read:function(data,options){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +var root=data.documentElement;var version=this.version;if(!version){version=root.getAttribute("version");} +var parser=this.getParser(version);var context=parser.read(data,options);var map;if(options&&options.map){this.context=context;if(options.map instanceof OpenLayers.Map){map=this.mergeContextToMap(context,options.map);}else{var mapOptions=options.map;if(OpenLayers.Util.isElement(mapOptions)||typeof mapOptions=="string"){mapOptions={div:mapOptions};} +map=this.contextToMap(context,mapOptions);}}else{map=context;} +return map;},getLayerFromContext:function(layerContext){var i,len;var options={queryable:layerContext.queryable,visibility:layerContext.visibility,maxExtent:layerContext.maxExtent,metadata:OpenLayers.Util.applyDefaults(layerContext.metadata,{styles:layerContext.styles}),numZoomLevels:layerContext.numZoomLevels,units:layerContext.units,isBaseLayer:layerContext.isBaseLayer,opacity:layerContext.opacity,displayInLayerSwitcher:layerContext.displayInLayerSwitcher,singleTile:layerContext.singleTile,tileSize:(layerContext.tileSize)?new OpenLayers.Size(layerContext.tileSize.width,layerContext.tileSize.height):undefined,minScale:layerContext.minScale||layerContext.maxScaleDenominator,maxScale:layerContext.maxScale||layerContext.minScaleDenominator};if(this.layerOptions){OpenLayers.Util.applyDefaults(options,this.layerOptions);} +var params={layers:layerContext.name,transparent:layerContext.transparent,version:layerContext.version};if(layerContext.formats&&layerContext.formats.length>0){params.format=layerContext.formats[0].value;for(i=0,len=layerContext.formats.length;i<len;i++){var format=layerContext.formats[i];if(format.current==true){params.format=format.value;break;}}} +if(layerContext.styles&&layerContext.styles.length>0){for(i=0,len=layerContext.styles.length;i<len;i++){var style=layerContext.styles[i];if(style.current==true){if(style.href){params.sld=style.href;}else if(style.body){params.sld_body=style.body;}else{params.styles=style.name;} +break;}}} +if(this.layerParams){OpenLayers.Util.applyDefaults(params,this.layerParams);} +var layer=null;var service=layerContext.service;if(service==OpenLayers.Format.Context.serviceTypes.WFS){options.strategies=[new OpenLayers.Strategy.BBOX()];options.protocol=new OpenLayers.Protocol.WFS({url:layerContext.url,featurePrefix:layerContext.name.split(":")[0],featureType:layerContext.name.split(":").pop()});layer=new OpenLayers.Layer.Vector(layerContext.title||layerContext.name,options);}else if(service==OpenLayers.Format.Context.serviceTypes.KML){options.strategies=[new OpenLayers.Strategy.Fixed()];options.protocol=new OpenLayers.Protocol.HTTP({url:layerContext.url,format:new OpenLayers.Format.KML()});layer=new OpenLayers.Layer.Vector(layerContext.title||layerContext.name,options);}else if(service==OpenLayers.Format.Context.serviceTypes.GML){options.strategies=[new OpenLayers.Strategy.Fixed()];options.protocol=new OpenLayers.Protocol.HTTP({url:layerContext.url,format:new OpenLayers.Format.GML()});layer=new OpenLayers.Layer.Vector(layerContext.title||layerContext.name,options);}else if(layerContext.features){layer=new OpenLayers.Layer.Vector(layerContext.title||layerContext.name,options);layer.addFeatures(layerContext.features);}else if(layerContext.categoryLayer!==true){layer=new OpenLayers.Layer.WMS(layerContext.title||layerContext.name,layerContext.url,params,options);} +return layer;},getLayersFromContext:function(layersContext){var layers=[];for(var i=0,len=layersContext.length;i<len;i++){var layer=this.getLayerFromContext(layersContext[i]);if(layer!==null){layers.push(layer);}} +return layers;},contextToMap:function(context,options){options=OpenLayers.Util.applyDefaults({maxExtent:context.maxExtent,projection:context.projection},options);var map=new OpenLayers.Map(options);map.addLayers(this.getLayersFromContext(context.layersContext));map.setCenter(context.bounds.getCenterLonLat(),map.getZoomForExtent(context.bounds,true));return map;},mergeContextToMap:function(context,map){map.addLayers(this.getLayersFromContext(context.layersContext));return map;},write:function(obj,options){obj=this.toContext(obj);var version=options&&options.version;var parser=this.getParser(version);var context=parser.write(obj,options);return context;},CLASS_NAME:"OpenLayers.Format.Context"});OpenLayers.Format.Context.serviceTypes={"WMS":"urn:ogc:serviceType:WMS","WFS":"urn:ogc:serviceType:WFS","WCS":"urn:ogc:serviceType:WCS","GML":"urn:ogc:serviceType:GML","SLD":"urn:ogc:serviceType:SLD","FES":"urn:ogc:serviceType:FES","KML":"urn:ogc:serviceType:KML"};if(!OpenLayers.Format.OWSCommon){OpenLayers.Format.OWSCommon={};} +OpenLayers.Format.OWSCommon.v1=OpenLayers.Class(OpenLayers.Format.XML,{regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},readers:{"ows":{"ServiceIdentification":function(node,obj){obj.serviceIdentification={};this.readChildNodes(node,obj.serviceIdentification);},"Title":function(node,obj){obj.title=this.getChildValue(node);},"Abstract":function(node,serviceIdentification){serviceIdentification["abstract"]=this.getChildValue(node);},"Keywords":function(node,serviceIdentification){serviceIdentification.keywords={};this.readChildNodes(node,serviceIdentification.keywords);},"Keyword":function(node,keywords){keywords[this.getChildValue(node)]=true;},"ServiceType":function(node,serviceIdentification){serviceIdentification.serviceType={codeSpace:node.getAttribute('codeSpace'),value:this.getChildValue(node)};},"ServiceTypeVersion":function(node,serviceIdentification){serviceIdentification.serviceTypeVersion=this.getChildValue(node);},"Fees":function(node,serviceIdentification){serviceIdentification.fees=this.getChildValue(node);},"AccessConstraints":function(node,serviceIdentification){serviceIdentification.accessConstraints=this.getChildValue(node);},"ServiceProvider":function(node,obj){obj.serviceProvider={};this.readChildNodes(node,obj.serviceProvider);},"ProviderName":function(node,serviceProvider){serviceProvider.providerName=this.getChildValue(node);},"ProviderSite":function(node,serviceProvider){serviceProvider.providerSite=this.getAttributeNS(node,this.namespaces.xlink,"href");},"ServiceContact":function(node,serviceProvider){serviceProvider.serviceContact={};this.readChildNodes(node,serviceProvider.serviceContact);},"IndividualName":function(node,serviceContact){serviceContact.individualName=this.getChildValue(node);},"PositionName":function(node,serviceContact){serviceContact.positionName=this.getChildValue(node);},"ContactInfo":function(node,serviceContact){serviceContact.contactInfo={};this.readChildNodes(node,serviceContact.contactInfo);},"Phone":function(node,contactInfo){contactInfo.phone={};this.readChildNodes(node,contactInfo.phone);},"Voice":function(node,phone){phone.voice=this.getChildValue(node);},"Address":function(node,contactInfo){contactInfo.address={};this.readChildNodes(node,contactInfo.address);},"DeliveryPoint":function(node,address){address.deliveryPoint=this.getChildValue(node);},"City":function(node,address){address.city=this.getChildValue(node);},"AdministrativeArea":function(node,address){address.administrativeArea=this.getChildValue(node);},"PostalCode":function(node,address){address.postalCode=this.getChildValue(node);},"Country":function(node,address){address.country=this.getChildValue(node);},"ElectronicMailAddress":function(node,address){address.electronicMailAddress=this.getChildValue(node);},"Role":function(node,serviceContact){serviceContact.role=this.getChildValue(node);},"OperationsMetadata":function(node,obj){obj.operationsMetadata={};this.readChildNodes(node,obj.operationsMetadata);},"Operation":function(node,operationsMetadata){var name=node.getAttribute("name");operationsMetadata[name]={};this.readChildNodes(node,operationsMetadata[name]);},"DCP":function(node,operation){operation.dcp={};this.readChildNodes(node,operation.dcp);},"HTTP":function(node,dcp){dcp.http={};this.readChildNodes(node,dcp.http);},"Get":function(node,http){http.get=this.getAttributeNS(node,this.namespaces.xlink,"href");},"Post":function(node,http){http.post=this.getAttributeNS(node,this.namespaces.xlink,"href");},"Parameter":function(node,operation){if(!operation.parameters){operation.parameters={};} +var name=node.getAttribute("name");operation.parameters[name]={};this.readChildNodes(node,operation.parameters[name]);},"Value":function(node,allowedValues){allowedValues[this.getChildValue(node)]=true;},"OutputFormat":function(node,obj){obj.formats.push({value:this.getChildValue(node)});this.readChildNodes(node,obj);},"WGS84BoundingBox":function(node,obj){var boundingBox={};boundingBox.crs=node.getAttribute("crs");if(obj.BoundingBox){obj.BoundingBox.push(boundingBox);}else{obj.projection=boundingBox.crs;boundingBox=obj;} +this.readChildNodes(node,boundingBox);},"BoundingBox":function(node,obj){this.readers['ows']['WGS84BoundingBox'].apply(this,[node,obj]);},"LowerCorner":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");str=str.replace(this.regExes.trimComma,",");var pointList=str.split(this.regExes.splitSpace);obj.left=pointList[0];obj.bottom=pointList[1];},"UpperCorner":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");str=str.replace(this.regExes.trimComma,",");var pointList=str.split(this.regExes.splitSpace);obj.right=pointList[0];obj.top=pointList[1];obj.bounds=new OpenLayers.Bounds(obj.left,obj.bottom,obj.right,obj.top);delete obj.left;delete obj.bottom;delete obj.right;delete obj.top;}}},writers:{"ows":{"BoundingBox":function(options){var node=this.createElementNSPlus("ows:BoundingBox",{attributes:{crs:options.projection}});this.writeNode("ows:LowerCorner",options,node);this.writeNode("ows:UpperCorner",options,node);return node;},"LowerCorner":function(options){var node=this.createElementNSPlus("ows:LowerCorner",{value:options.bounds.left+" "+options.bounds.bottom});return node;},"UpperCorner":function(options){var node=this.createElementNSPlus("ows:UpperCorner",{value:options.bounds.right+" "+options.bounds.top});return node;},"Title":function(title){var node=this.createElementNSPlus("ows:Title",{value:title});return node;},"OutputFormat":function(format){var node=this.createElementNSPlus("ows:OutputFormat",{value:format});return node;}}},CLASS_NAME:"OpenLayers.Format.OWSCommon.v1"});OpenLayers.Format.SOSCapabilities=OpenLayers.Class(OpenLayers.Format.XML,{defaultVersion:"1.0.0",version:null,parser:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +var root=data.documentElement;var version=this.version||root.getAttribute("version")||this.defaultVersion;if(!this.parser||this.parser.version!==version){var constr=OpenLayers.Format.SOSCapabilities["v"+version.replace(/\./g,"_")];if(!constr){throw"Can't find a SOS capabilities parser for version "+version;} +var parser=new constr(this.options);} +var capabilities=parser.read(data);capabilities.version=version;return capabilities;},CLASS_NAME:"OpenLayers.Format.SOSCapabilities"});OpenLayers.Format.WFSCapabilities=OpenLayers.Class(OpenLayers.Format.XML,{defaultVersion:"1.1.0",version:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +var root=data.documentElement;var version=this.version;if(!version){version=root.getAttribute("version");if(!version){version=this.defaultVersion;}} +var constr=OpenLayers.Format.WFSCapabilities["v"+version.replace(/\./g,"_")];if(!constr){throw"Can't find a WFS capabilities parser for version "+version;} +var parser=new constr(this.options);var capabilities=parser.read(data);capabilities.version=version;return capabilities;},CLASS_NAME:"OpenLayers.Format.WFSCapabilities"});OpenLayers.Format.WFSDescribeFeatureType=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{xsd:"http://www.w3.org/2001/XMLSchema"},initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},readers:{"xsd":{"schema":function(node,obj){var complexTypes=[];var customTypes={};var schema={complexTypes:complexTypes,customTypes:customTypes};this.readChildNodes(node,schema);var attributes=node.attributes;var attr,name;for(var i=0,len=attributes.length;i<len;++i){attr=attributes[i];name=attr.name;if(name.indexOf("xmlns")==0){this.setNamespace(name.split(":")[1]||"",attr.value);}else{obj[name]=attr.value;}} +obj.featureTypes=complexTypes;obj.targetPrefix=this.namespaceAlias[obj.targetNamespace];var complexType,customType;for(var i=0,len=complexTypes.length;i<len;++i){complexType=complexTypes[i];customType=customTypes[complexType.typeName];if(customTypes[complexType.typeName]){complexType.typeName=customType.name;}}},"complexType":function(node,obj){var complexType={"typeName":node.getAttribute("name")};this.readChildNodes(node,complexType);obj.complexTypes.push(complexType);},"complexContent":function(node,obj){this.readChildNodes(node,obj);},"extension":function(node,obj){this.readChildNodes(node,obj);},"sequence":function(node,obj){var sequence={elements:[]};this.readChildNodes(node,sequence);obj.properties=sequence.elements;},"element":function(node,obj){if(obj.elements){var element={};var attributes=node.attributes;var attr;for(var i=0,len=attributes.length;i<len;++i){attr=attributes[i];element[attr.name]=attr.value;} +var type=element.type;if(!type){type={};this.readChildNodes(node,type);element.restriction=type;element.type=type.base;} +var fullType=type.base||type;element.localType=fullType.split(":").pop();obj.elements.push(element);} +if(obj.complexTypes){var type=node.getAttribute("type");var localType=type.split(":").pop();obj.customTypes[localType]={"name":node.getAttribute("name"),"type":type};}},"simpleType":function(node,obj){this.readChildNodes(node,obj);},"restriction":function(node,obj){obj.base=node.getAttribute("base");this.readRestriction(node,obj);}}},readRestriction:function(node,obj){var children=node.childNodes;var child,nodeName,value;for(var i=0,len=children.length;i<len;++i){child=children[i];if(child.nodeType==1){nodeName=child.nodeName.split(":").pop();value=child.getAttribute("value");if(!obj[nodeName]){obj[nodeName]=value;}else{if(typeof obj[nodeName]=="string"){obj[nodeName]=[obj[nodeName]];} +obj[nodeName].push(value);}}}},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +if(data&&data.nodeType==9){data=data.documentElement;} +var schema={};this.readNode(data,schema);return schema;},CLASS_NAME:"OpenLayers.Format.WFSDescribeFeatureType"});OpenLayers.Format.WFST.v1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance",wfs:"http://www.opengis.net/wfs",gml:"http://www.opengis.net/gml",ogc:"http://www.opengis.net/ogc"},defaultPrefix:"wfs",version:null,schemaLocations:null,srsName:null,extractAttributes:true,xy:true,stateName:null,initialize:function(options){this.stateName={};this.stateName[OpenLayers.State.INSERT]="wfs:Insert";this.stateName[OpenLayers.State.UPDATE]="wfs:Update";this.stateName[OpenLayers.State.DELETE]="wfs:Delete";OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},getSrsName:function(feature,options){var srsName=options&&options.srsName;if(!srsName){if(feature&&feature.layer){srsName=feature.layer.projection.getCode();}else{srsName=this.srsName;}} +return srsName;},read:function(data,options){options=options||{};OpenLayers.Util.applyDefaults(options,{output:"features"});if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +if(data&&data.nodeType==9){data=data.documentElement;} +var obj={};if(data){this.readNode(data,obj);} +if(obj.features&&options.output==="features"){obj=obj.features;} +return obj;},readers:{"wfs":{"FeatureCollection":function(node,obj){obj.features=[];this.readChildNodes(node,obj);}}},write:function(features){var node=this.writeNode("wfs:Transaction",features);var value=this.schemaLocationAttr();if(value){this.setAttributeNS(node,this.namespaces["xsi"],"xsi:schemaLocation",value)} +return OpenLayers.Format.XML.prototype.write.apply(this,[node]);},writers:{"wfs":{"GetFeature":function(options){var node=this.createElementNSPlus("wfs:GetFeature",{attributes:{service:"WFS",version:this.version,outputFormat:options&&options.outputFormat,maxFeatures:options&&options.maxFeatures,"xsi:schemaLocation":this.schemaLocationAttr(options)}});if(typeof this.featureType=="string"){this.writeNode("Query",options,node);}else{for(var i=0,len=this.featureType.length;i<len;i++){options.featureType=this.featureType[i];this.writeNode("Query",options,node);}} +return node;},"Transaction":function(features){var node=this.createElementNSPlus("wfs:Transaction",{attributes:{service:"WFS",version:this.version}});if(features){var name,feature;for(var i=0,len=features.length;i<len;++i){feature=features[i];name=this.stateName[feature.state];if(name){this.writeNode(name,feature,node);}}} +return node;},"Insert":function(feature){var node=this.createElementNSPlus("wfs:Insert");this.srsName=this.getSrsName(feature);this.writeNode("feature:_typeName",feature,node);return node;},"Update":function(feature){var node=this.createElementNSPlus("wfs:Update",{attributes:{typeName:(this.featureNS?this.featurePrefix+":":"")+ +this.featureType}});if(this.featureNS){node.setAttribute("xmlns:"+this.featurePrefix,this.featureNS);} +if(this.geometryName!==null){this.writeNode("Property",{name:this.geometryName,value:feature},node);} +for(var key in feature.attributes){if(feature.attributes[key]!==undefined){this.writeNode("Property",{name:key,value:feature.attributes[key]},node);}} +this.writeNode("ogc:Filter",new OpenLayers.Filter.FeatureId({fids:[feature.fid]}),node);return node;},"Property":function(obj){var node=this.createElementNSPlus("wfs:Property");this.writeNode("Name",obj.name,node);if(obj.value!==null){this.writeNode("Value",obj.value,node);} +return node;},"Name":function(name){return this.createElementNSPlus("wfs:Name",{value:name});},"Value":function(obj){var node;if(obj instanceof OpenLayers.Feature.Vector){node=this.createElementNSPlus("wfs:Value");this.srsName=this.getSrsName(obj);var geom=this.writeNode("feature:_geometry",obj.geometry).firstChild;node.appendChild(geom);}else{node=this.createElementNSPlus("wfs:Value",{value:obj});} +return node;},"Delete":function(feature){var node=this.createElementNSPlus("wfs:Delete",{attributes:{typeName:(this.featureNS?this.featurePrefix+":":"")+ +this.featureType}});if(this.featureNS){node.setAttribute("xmlns:"+this.featurePrefix,this.featureNS);} +this.writeNode("ogc:Filter",new OpenLayers.Filter.FeatureId({fids:[feature.fid]}),node);return node;}}},schemaLocationAttr:function(options){options=OpenLayers.Util.extend({featurePrefix:this.featurePrefix,schema:this.schema},options);var schemaLocations=OpenLayers.Util.extend({},this.schemaLocations);if(options.schema){schemaLocations[options.featurePrefix]=options.schema;} +var parts=[];var uri;for(var key in schemaLocations){uri=this.namespaces[key];if(uri){parts.push(uri+" "+schemaLocations[key]);}} +var value=parts.join(" ")||undefined;return value;},setFilterProperty:function(filter){if(filter.filters){for(var i=0,len=filter.filters.length;i<len;++i){this.setFilterProperty(filter.filters[i]);}}else{if(filter instanceof OpenLayers.Filter.Spatial){filter.property=this.geometryName;}}},CLASS_NAME:"OpenLayers.Format.WFST.v1"});OpenLayers.Format.WMSCapabilities=OpenLayers.Class(OpenLayers.Format.XML,{defaultVersion:"1.1.1",version:null,parser:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +var root=data.documentElement;var version=this.version||root.getAttribute("version")||this.defaultVersion;if(!this.parser||this.parser.version!==version){var constr=OpenLayers.Format.WMSCapabilities["v"+version.replace(/\./g,"_")];if(!constr){throw"Can't find a WMS capabilities parser for version "+version;} +this.parser=new constr(this.options);} +var capabilities=this.parser.read(data);capabilities.version=version;return capabilities;},CLASS_NAME:"OpenLayers.Format.WMSCapabilities"});OpenLayers.Format.WMSDescribeLayer=OpenLayers.Class(OpenLayers.Format.XML,{defaultVersion:"1.1.1",version:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +var root=data.documentElement;var version=this.version;if(!version){version=root.getAttribute("version");if(!version){version=this.defaultVersion;}} +if(version=="1.1.1"||version=="1.1.0"){version="1.1";} +var constructor=OpenLayers.Format.WMSDescribeLayer["v"+version.replace(/\./g,"_")];if(!constructor){throw"Can't find a WMS DescribeLayer parser for version "+ +version;} +var parser=new constructor(this.options);var describelayer=parser.read(data);describelayer.version=version;return describelayer;},CLASS_NAME:"OpenLayers.Format.WMSDescribeLayer"});OpenLayers.Format.WMSGetFeatureInfo=OpenLayers.Class(OpenLayers.Format.XML,{layerIdentifier:'_layer',featureIdentifier:'_feature',regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},gmlFormat:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,arguments);OpenLayers.Util.extend(this,options);this.options=options;},read:function(data){var result;if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +var root=data.documentElement;if(root){var scope=this;var read=this["read_"+root.nodeName];if(read){result=read.call(this,root);}else{result=new OpenLayers.Format.GML((this.options?this.options:{})).read(data);}}else{result=data;} +return result;},read_msGMLOutput:function(data){var response=[];var layerNodes=this.getSiblingNodesByTagCriteria(data,this.layerIdentifier);if(layerNodes){for(var i=0,len=layerNodes.length;i<len;++i){var node=layerNodes[i];var layerName=node.nodeName;if(node.prefix){layerName=layerName.split(':')[1];} +var layerName=layerName.replace(this.layerIdentifier,'');var featureNodes=this.getSiblingNodesByTagCriteria(node,this.featureIdentifier);if(featureNodes){for(var j=0;j<featureNodes.length;j++){var featureNode=featureNodes[j];var geomInfo=this.parseGeometry(featureNode);var attributes=this.parseAttributes(featureNode);var feature=new OpenLayers.Feature.Vector(geomInfo.geometry,attributes,null);feature.bounds=geomInfo.bounds;feature.type=layerName;response.push(feature);}}}} +return response;},read_FeatureInfoResponse:function(data){var response=[];var featureNodes=this.getElementsByTagNameNS(data,'*','FIELDS');for(var i=0,len=featureNodes.length;i<len;i++){var featureNode=featureNodes[i];var geom=null;var attributes={};for(var j=0,jlen=featureNode.attributes.length;j<jlen;j++){var attribute=featureNode.attributes[j];attributes[attribute.nodeName]=attribute.nodeValue;} +response.push(new OpenLayers.Feature.Vector(geom,attributes,null));} +return response;},getSiblingNodesByTagCriteria:function(node,criteria){var nodes=[];var children,tagName,n,matchNodes,child;if(node&&node.hasChildNodes()){children=node.childNodes;n=children.length;for(var k=0;k<n;k++){child=children[k];while(child&&child.nodeType!=1){child=child.nextSibling;k++;} +tagName=(child?child.nodeName:'');if(tagName.length>0&&tagName.indexOf(criteria)>-1){nodes.push(child);}else{matchNodes=this.getSiblingNodesByTagCriteria(child,criteria);if(matchNodes.length>0){(nodes.length==0)?nodes=matchNodes:nodes.push(matchNodes);}}}} +return nodes;},parseAttributes:function(node){var attributes={};if(node.nodeType==1){var children=node.childNodes;var n=children.length;for(var i=0;i<n;++i){var child=children[i];if(child.nodeType==1){var grandchildren=child.childNodes;if(grandchildren.length==1){var grandchild=grandchildren[0];if(grandchild.nodeType==3||grandchild.nodeType==4){var name=(child.prefix)?child.nodeName.split(":")[1]:child.nodeName;var value=grandchild.nodeValue.replace(this.regExes.trimSpace,"");attributes[name]=value;}}}}} +return attributes;},parseGeometry:function(node){if(!this.gmlFormat){this.gmlFormat=new OpenLayers.Format.GML();} +var feature=this.gmlFormat.parseFeature(node);var geometry,bounds=null;if(feature){geometry=feature.geometry&&feature.geometry.clone();bounds=feature.bounds&&feature.bounds.clone();feature.destroy();} +return{geometry:geometry,bounds:bounds};},CLASS_NAME:"OpenLayers.Format.WMSGetFeatureInfo"});OpenLayers.Format.WMTSCapabilities=OpenLayers.Class(OpenLayers.Format.XML,{defaultVersion:"1.0.0",version:null,parser:null,yx:{"urn:ogc:def:crs:EPSG::4326":true},initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +var root=data.documentElement;var version=this.version||root.getAttribute("version")||this.defaultVersion;if(!this.parser||this.parser.version!==version){var constr=OpenLayers.Format.WMTSCapabilities["v"+version.replace(/\./g,"_")];if(!constr){throw new Error("Can't find a WMTS capabilities parser for version "+version);} +this.parser=new constr(this.options);} +return this.parser.read(data);},createLayer:function(capabilities,config){var layer;var required={layer:true,matrixSet:true};for(var prop in required){if(!(prop in config)){throw new Error("Missing property '"+prop+"' in layer configuration.");}} +var contents=capabilities.contents;var matrixSet=contents.tileMatrixSets[config.matrixSet];var layers=contents.layers;var layerDef;for(var i=0,ii=contents.layers.length;i<ii;++i){if(contents.layers[i].identifier===config.layer){layerDef=contents.layers[i];break;}} +if(layerDef&&matrixSet){var style;for(var i=0,ii=layerDef.styles.length;i<ii;++i){style=layerDef.styles[i];if(style.isDefault){break;}} +layer=new OpenLayers.Layer.WMTS(OpenLayers.Util.applyDefaults(config,{url:capabilities.operationsMetadata.GetTile.dcp.http.get,name:layerDef.title,style:style,matrixIds:matrixSet.matrixIds}));} +return layer;},CLASS_NAME:"OpenLayers.Format.WMTSCapabilities"});OpenLayers.Handler.Click=OpenLayers.Class(OpenLayers.Handler,{delay:300,single:true,'double':false,pixelTolerance:0,stopSingle:false,stopDouble:false,timerId:null,down:null,rightclickTimerId:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);if(this.pixelTolerance!=null){this.mousedown=function(evt){this.down=evt.xy;return true;};}},mousedown:null,mouseup:function(evt){var propagate=true;if(this.checkModifiers(evt)&&this.control.handleRightClicks&&OpenLayers.Event.isRightClick(evt)){propagate=this.rightclick(evt);} +return propagate;},rightclick:function(evt){if(this.passesTolerance(evt)){if(this.rightclickTimerId!=null){this.clearTimer();this.callback('dblrightclick',[evt]);return!this.stopDouble;}else{var clickEvent=this['double']?OpenLayers.Util.extend({},evt):this.callback('rightclick',[evt]);var delayedRightCall=OpenLayers.Function.bind(this.delayedRightCall,this,clickEvent);this.rightclickTimerId=window.setTimeout(delayedRightCall,this.delay);}} +return!this.stopSingle;},delayedRightCall:function(evt){this.rightclickTimerId=null;if(evt){this.callback('rightclick',[evt]);} +return!this.stopSingle;},dblclick:function(evt){if(this.passesTolerance(evt)){if(this["double"]){this.callback('dblclick',[evt]);} +this.clearTimer();} +return!this.stopDouble;},click:function(evt){if(this.passesTolerance(evt)){if(this.timerId!=null){this.clearTimer();}else{var clickEvent=this.single?OpenLayers.Util.extend({},evt):null;this.timerId=window.setTimeout(OpenLayers.Function.bind(this.delayedCall,this,clickEvent),this.delay);}} +return!this.stopSingle;},passesTolerance:function(evt){var passes=true;if(this.pixelTolerance!=null&&this.down){var dpx=Math.sqrt(Math.pow(this.down.x-evt.xy.x,2)+ +Math.pow(this.down.y-evt.xy.y,2));if(dpx>this.pixelTolerance){passes=false;}} +return passes;},clearTimer:function(){if(this.timerId!=null){window.clearTimeout(this.timerId);this.timerId=null;} +if(this.rightclickTimerId!=null){window.clearTimeout(this.rightclickTimerId);this.rightclickTimerId=null;}},delayedCall:function(evt){this.timerId=null;if(evt){this.callback('click',[evt]);}},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.clearTimer();this.down=null;deactivated=true;} +return deactivated;},CLASS_NAME:"OpenLayers.Handler.Click"});OpenLayers.Handler.Drag=OpenLayers.Class(OpenLayers.Handler,{started:false,stopDown:true,dragging:false,last:null,start:null,oldOnselectstart:null,interval:0,timeoutId:null,documentDrag:false,documentEvents:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);},down:function(evt){},move:function(evt){},up:function(evt){},out:function(evt){},mousedown:function(evt){var propagate=true;this.dragging=false;if(this.checkModifiers(evt)&&OpenLayers.Event.isLeftClick(evt)){this.started=true;this.start=evt.xy;this.last=evt.xy;OpenLayers.Element.addClass(this.map.viewPortDiv,"olDragDown");this.down(evt);this.callback("down",[evt.xy]);OpenLayers.Event.stop(evt);if(!this.oldOnselectstart){this.oldOnselectstart=(document.onselectstart)?document.onselectstart:OpenLayers.Function.True;} +document.onselectstart=OpenLayers.Function.False;propagate=!this.stopDown;}else{this.started=false;this.start=null;this.last=null;} +return propagate;},mousemove:function(evt){if(this.started&&!this.timeoutId&&(evt.xy.x!=this.last.x||evt.xy.y!=this.last.y)){if(this.documentDrag===true&&this.documentEvents){if(evt.element===document){this.adjustXY(evt);this.setEvent(evt);}else{this.destroyDocumentEvents();}} +if(this.interval>0){this.timeoutId=setTimeout(OpenLayers.Function.bind(this.removeTimeout,this),this.interval);} +this.dragging=true;this.move(evt);this.callback("move",[evt.xy]);if(!this.oldOnselectstart){this.oldOnselectstart=document.onselectstart;document.onselectstart=OpenLayers.Function.False;} +this.last=this.evt.xy;} +return true;},removeTimeout:function(){this.timeoutId=null;},mouseup:function(evt){if(this.started){if(this.documentDrag===true&&this.documentEvents){this.adjustXY(evt);this.destroyDocumentEvents();} +var dragged=(this.start!=this.last);this.started=false;this.dragging=false;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDragDown");this.up(evt);this.callback("up",[evt.xy]);if(dragged){this.callback("done",[evt.xy]);} +document.onselectstart=this.oldOnselectstart;} +return true;},mouseout:function(evt){if(this.started&&OpenLayers.Util.mouseLeft(evt,this.map.div)){if(this.documentDrag===true){this.documentEvents=new OpenLayers.Events(this,document,null,null,{includeXY:true});this.documentEvents.on({mousemove:this.mousemove,mouseup:this.mouseup});OpenLayers.Element.addClass(document.body,"olDragDown");}else{var dragged=(this.start!=this.last);this.started=false;this.dragging=false;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDragDown");this.out(evt);this.callback("out",[]);if(dragged){this.callback("done",[evt.xy]);} +if(document.onselectstart){document.onselectstart=this.oldOnselectstart;}}} +return true;},click:function(evt){return(this.start==this.last);},activate:function(){var activated=false;if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.dragging=false;activated=true;} +return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.started=false;this.dragging=false;this.start=null;this.last=null;deactivated=true;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDragDown");} +return deactivated;},adjustXY:function(evt){var pos=OpenLayers.Util.pagePosition(this.map.div);evt.xy.x-=pos[0];evt.xy.y-=pos[1];},destroyDocumentEvents:function(){OpenLayers.Element.removeClass(document.body,"olDragDown");this.documentEvents.destroy();this.documentEvents=null;},CLASS_NAME:"OpenLayers.Handler.Drag"});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}},feature:null,lastFeature:null,down:null,up:null,clickTolerance:4,geometryTypes:null,stopClick:true,stopDown:true,stopUp:false,initialize:function(control,layer,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,[control,callbacks,options]);this.layer=layer;},mousedown:function(evt){this.down=evt.xy;return this.handle(evt)?!this.stopDown:true;},mouseup:function(evt){this.up=evt.xy;return this.handle(evt)?!this.stopUp:true;},click:function(evt){return this.handle(evt)?!this.stopClick:true;},mousemove:function(evt){if(!this.callbacks['over']&&!this.callbacks['out']){return true;} +this.handle(evt);return true;},dblclick:function(evt){return!this.handle(evt);},geometryTypeMatches:function(feature){return this.geometryTypes==null||OpenLayers.Util.indexOf(this.geometryTypes,feature.geometry.CLASS_NAME)>-1;},handle:function(evt){if(this.feature&&!this.feature.layer){this.feature=null;} +var type=evt.type;var handled=false;var previouslyIn=!!(this.feature);var click=(type=="click"||type=="dblclick");this.feature=this.layer.getFeatureFromEvent(evt);if(this.feature&&!this.feature.layer){this.feature=null;} +if(this.lastFeature&&!this.lastFeature.layer){this.lastFeature=null;} +if(this.feature){var inNew=(this.feature!=this.lastFeature);if(this.geometryTypeMatches(this.feature)){if(previouslyIn&&inNew){if(this.lastFeature){this.triggerCallback(type,'out',[this.lastFeature]);} +this.triggerCallback(type,'in',[this.feature]);}else if(!previouslyIn||click){this.triggerCallback(type,'in',[this.feature]);} +this.lastFeature=this.feature;handled=true;}else{if(this.lastFeature&&(previouslyIn&&inNew||click)){this.triggerCallback(type,'out',[this.lastFeature]);} +this.feature=null;}}else{if(this.lastFeature&&(previouslyIn||click)){this.triggerCallback(type,'out',[this.lastFeature]);}} +return handled;},triggerCallback:function(type,mode,args){var key=this.EVENTMAP[type][mode];if(key){if(type=='click'&&this.up&&this.down){var dpx=Math.sqrt(Math.pow(this.up.x-this.down.x,2)+ +Math.pow(this.up.y-this.down.y,2));if(dpx<=this.clickTolerance){this.callback(key,args);}}else{this.callback(key,args);}}},activate:function(){var activated=false;if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.moveLayerToTop();this.map.events.on({"removelayer":this.handleMapEvents,"changelayer":this.handleMapEvents,scope:this});activated=true;} +return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.moveLayerBack();this.feature=null;this.lastFeature=null;this.down=null;this.up=null;this.map.events.un({"removelayer":this.handleMapEvents,"changelayer":this.handleMapEvents,scope:this});deactivated=true;} +return deactivated;},handleMapEvents:function(evt){if(!evt.property||evt.property=="order"){this.moveLayerToTop();}},moveLayerToTop:function(){var index=Math.max(this.map.Z_INDEX_BASE['Feature']-1,this.layer.getZIndex())+1;this.layer.setZIndex(index);},moveLayerBack:function(){var index=this.layer.getZIndex()-1;if(index>=this.map.Z_INDEX_BASE['Feature']){this.layer.setZIndex(index);}else{this.map.setLayerZIndex(this.layer,this.map.getLayerIndex(this.layer));}},CLASS_NAME:"OpenLayers.Handler.Feature"});OpenLayers.Handler.Hover=OpenLayers.Class(OpenLayers.Handler,{delay:500,pixelTolerance:null,stopMove:false,px:null,timerId:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);},mousemove:function(evt){if(this.passesTolerance(evt.xy)){this.clearTimer();this.callback('move',[evt]);this.px=evt.xy;evt=OpenLayers.Util.extend({},evt);this.timerId=window.setTimeout(OpenLayers.Function.bind(this.delayedCall,this,evt),this.delay);} +return!this.stopMove;},mouseout:function(evt){if(OpenLayers.Util.mouseLeft(evt,this.map.div)){this.clearTimer();this.callback('move',[evt]);} +return true;},passesTolerance:function(px){var passes=true;if(this.pixelTolerance&&this.px){var dpx=Math.sqrt(Math.pow(this.px.x-px.x,2)+ +Math.pow(this.px.y-px.y,2));if(dpx<this.pixelTolerance){passes=false;}} +return passes;},clearTimer:function(){if(this.timerId!=null){window.clearTimeout(this.timerId);this.timerId=null;}},delayedCall:function(evt){this.callback('pause',[evt]);},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.clearTimer();deactivated=true;} +return deactivated;},CLASS_NAME:"OpenLayers.Handler.Hover"});OpenLayers.Handler.Keyboard=OpenLayers.Class(OpenLayers.Handler,{KEY_EVENTS:["keydown","keyup"],eventListener:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);this.eventListener=OpenLayers.Function.bindAsEventListener(this.handleKeyEvent,this);},destroy:function(){this.deactivate();this.eventListener=null;OpenLayers.Handler.prototype.destroy.apply(this,arguments);},activate:function(){if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){for(var i=0,len=this.KEY_EVENTS.length;i<len;i++){OpenLayers.Event.observe(document,this.KEY_EVENTS[i],this.eventListener);} +return true;}else{return false;}},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){for(var i=0,len=this.KEY_EVENTS.length;i<len;i++){OpenLayers.Event.stopObserving(document,this.KEY_EVENTS[i],this.eventListener);} +deactivated=true;} +return deactivated;},handleKeyEvent:function(evt){if(this.checkModifiers(evt)){this.callback(evt.type,[evt]);}},CLASS_NAME:"OpenLayers.Handler.Keyboard"});OpenLayers.Handler.MouseWheel=OpenLayers.Class(OpenLayers.Handler,{wheelListener:null,mousePosition:null,interval:0,delta:0,cumulative:true,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);this.wheelListener=OpenLayers.Function.bindAsEventListener(this.onWheelEvent,this);},destroy:function(){OpenLayers.Handler.prototype.destroy.apply(this,arguments);this.wheelListener=null;},onWheelEvent:function(e){if(!this.map||!this.checkModifiers(e)){return;} +var overScrollableDiv=false;var overLayerDiv=false;var overMapDiv=false;var elem=OpenLayers.Event.element(e);while((elem!=null)&&!overMapDiv&&!overScrollableDiv){if(!overScrollableDiv){try{if(elem.currentStyle){overflow=elem.currentStyle["overflow"];}else{var style=document.defaultView.getComputedStyle(elem,null);var overflow=style.getPropertyValue("overflow");} +overScrollableDiv=(overflow&&(overflow=="auto")||(overflow=="scroll"));}catch(err){}} +if(!overLayerDiv){for(var i=0,len=this.map.layers.length;i<len;i++){if(elem==this.map.layers[i].div||elem==this.map.layers[i].pane){overLayerDiv=true;break;}}} +overMapDiv=(elem==this.map.div);elem=elem.parentNode;} +if(!overScrollableDiv&&overMapDiv){if(overLayerDiv){var delta=0;if(!e){e=window.event;} +if(e.wheelDelta){delta=e.wheelDelta/120;if(window.opera&&window.opera.version()<9.2){delta=-delta;}}else if(e.detail){delta=-e.detail/3;} +this.delta=this.delta+delta;if(this.interval){window.clearTimeout(this._timeoutId);this._timeoutId=window.setTimeout(OpenLayers.Function.bind(function(){this.wheelZoom(e);},this),this.interval);}else{this.wheelZoom(e);}} +OpenLayers.Event.stop(e);}},wheelZoom:function(e){var delta=this.delta;this.delta=0;if(delta){if(this.mousePosition){e.xy=this.mousePosition;} +if(!e.xy){e.xy=this.map.getPixelFromLonLat(this.map.getCenter());} +if(delta<0){this.callback("down",[e,this.cumulative?delta:-1]);}else{this.callback("up",[e,this.cumulative?delta:1]);}}},mousemove:function(evt){this.mousePosition=evt.xy;},activate:function(evt){if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){var wheelListener=this.wheelListener;OpenLayers.Event.observe(window,"DOMMouseScroll",wheelListener);OpenLayers.Event.observe(window,"mousewheel",wheelListener);OpenLayers.Event.observe(document,"mousewheel",wheelListener);return true;}else{return false;}},deactivate:function(evt){if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){var wheelListener=this.wheelListener;OpenLayers.Event.stopObserving(window,"DOMMouseScroll",wheelListener);OpenLayers.Event.stopObserving(window,"mousewheel",wheelListener);OpenLayers.Event.stopObserving(document,"mousewheel",wheelListener);return true;}else{return false;}},CLASS_NAME:"OpenLayers.Handler.MouseWheel"});OpenLayers.Layer=OpenLayers.Class({id:null,name:null,div:null,opacity:null,alwaysInRange:null,EVENT_TYPES:["loadstart","loadend","loadcancel","visibilitychanged","move","moveend"],RESOLUTION_PROPERTIES:['scales','resolutions','maxScale','minScale','maxResolution','minResolution','numZoomLevels','maxZoomLevel'],events:null,map:null,isBaseLayer:false,alpha:false,displayInLayerSwitcher:true,visibility:true,attribution:null,inRange:false,imageSize:null,imageOffset:null,options:null,eventListeners:null,gutter:0,projection:null,units:null,scales:null,resolutions:null,maxExtent:null,minExtent:null,maxResolution:null,minResolution:null,numZoomLevels:null,minScale:null,maxScale:null,displayOutsideMaxExtent:false,wrapDateLine:false,transitionEffect:null,SUPPORTED_TRANSITIONS:['resize'],metadata:{},initialize:function(name,options){this.addOptions(options);this.name=name;if(this.id==null){this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");this.div=OpenLayers.Util.createDiv(this.id);this.div.style.width="100%";this.div.style.height="100%";this.div.dir="ltr";this.events=new OpenLayers.Events(this,this.div,this.EVENT_TYPES);if(this.eventListeners instanceof Object){this.events.on(this.eventListeners);}} +if(this.wrapDateLine){this.displayOutsideMaxExtent=true;}},destroy:function(setNewBaseLayer){if(setNewBaseLayer==null){setNewBaseLayer=true;} +if(this.map!=null){this.map.removeLayer(this,setNewBaseLayer);} +this.projection=null;this.map=null;this.name=null;this.div=null;this.options=null;if(this.events){if(this.eventListeners){this.events.un(this.eventListeners);} +this.events.destroy();} +this.eventListeners=null;this.events=null;},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer(this.name,this.getOptions());} +OpenLayers.Util.applyDefaults(obj,this);obj.map=null;return obj;},getOptions:function(){var options={};for(var o in this.options){options[o]=this[o];} +return options;},setName:function(newName){if(newName!=this.name){this.name=newName;if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"name"});}}},addOptions:function(newOptions){if(this.options==null){this.options={};} +OpenLayers.Util.extend(this.options,newOptions);OpenLayers.Util.extend(this,newOptions);if(typeof this.projection=="string"){this.projection=new OpenLayers.Projection(this.projection);} +if(this.projection&&this.projection.getUnits()){this.units=this.projection.getUnits();} +if(this.map){var properties=this.RESOLUTION_PROPERTIES.concat(["projection","units","minExtent","maxExtent"]);for(var o in newOptions){if(newOptions.hasOwnProperty(o)&&OpenLayers.Util.indexOf(properties,o)>=0){this.initResolutions();break;}}}},onMapResize:function(){},redraw:function(){var redrawn=false;if(this.map){this.inRange=this.calculateInRange();var extent=this.getExtent();if(extent&&this.inRange&&this.visibility){var zoomChanged=true;this.moveTo(extent,zoomChanged,false);this.events.triggerEvent("moveend",{"zoomChanged":zoomChanged});redrawn=true;}} +return redrawn;},moveTo:function(bounds,zoomChanged,dragging){var display=this.visibility;if(!this.isBaseLayer){display=display&&this.inRange;} +this.display(display);},setMap:function(map){if(this.map==null){this.map=map;this.maxExtent=this.maxExtent||this.map.maxExtent;this.minExtent=this.minExtent||this.map.minExtent;this.projection=this.projection||this.map.projection;if(typeof this.projection=="string"){this.projection=new OpenLayers.Projection(this.projection);} +this.units=this.projection.getUnits()||this.units||this.map.units;this.initResolutions();if(!this.isBaseLayer){this.inRange=this.calculateInRange();var show=((this.visibility)&&(this.inRange));this.div.style.display=show?"":"none";} +this.setTileSize();}},afterAdd:function(){},removeMap:function(map){},getImageSize:function(bounds){return(this.imageSize||this.tileSize);},setTileSize:function(size){var tileSize=(size)?size:((this.tileSize)?this.tileSize:this.map.getTileSize());this.tileSize=tileSize;if(this.gutter){this.imageOffset=new OpenLayers.Pixel(-this.gutter,-this.gutter);this.imageSize=new OpenLayers.Size(tileSize.w+(2*this.gutter),tileSize.h+(2*this.gutter));}},getVisibility:function(){return this.visibility;},setVisibility:function(visibility){if(visibility!=this.visibility){this.visibility=visibility;this.display(visibility);this.redraw();if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"visibility"});} +this.events.triggerEvent("visibilitychanged");}},display:function(display){if(display!=(this.div.style.display!="none")){this.div.style.display=(display&&this.calculateInRange())?"block":"none";}},calculateInRange:function(){var inRange=false;if(this.alwaysInRange){inRange=true;}else{if(this.map){var resolution=this.map.getResolution();inRange=((resolution>=this.minResolution)&&(resolution<=this.maxResolution));}} +return inRange;},setIsBaseLayer:function(isBaseLayer){if(isBaseLayer!=this.isBaseLayer){this.isBaseLayer=isBaseLayer;if(this.map!=null){this.map.events.triggerEvent("changebaselayer",{layer:this});}}},initResolutions:function(){var i,len;var props={},alwaysInRange=true;for(i=0,len=this.RESOLUTION_PROPERTIES.length;i<len;i++){var p=this.RESOLUTION_PROPERTIES[i];props[p]=this.options[p];if(alwaysInRange&&this.options[p]){alwaysInRange=false;}} +if(this.alwaysInRange==null){this.alwaysInRange=alwaysInRange;} +if(props.resolutions==null){props.resolutions=this.resolutionsFromScales(props.scales);} +if(props.resolutions==null){props.resolutions=this.calculateResolutions(props);} +if(props.resolutions==null){for(i=0,len=this.RESOLUTION_PROPERTIES.length;i<len;i++){var p=this.RESOLUTION_PROPERTIES[i];props[p]=this.options[p]!=null?this.options[p]:this.map[p];} +if(props.resolutions==null){props.resolutions=this.resolutionsFromScales(props.scales);} +if(props.resolutions==null){props.resolutions=this.calculateResolutions(props);}} +var maxResolution;if(this.options.maxResolution&&this.options.maxResolution!=="auto"){maxResolution=this.options.maxResolution;} +if(this.options.minScale){maxResolution=OpenLayers.Util.getResolutionFromScale(this.options.minScale,this.units);} +var minResolution;if(this.options.minResolution&&this.options.minResolution!=="auto"){minResolution=this.options.minResolution;} +if(this.options.maxScale){minResolution=OpenLayers.Util.getResolutionFromScale(this.options.maxScale,this.units);} +if(props.resolutions){props.resolutions.sort(function(a,b){return(b-a);});if(!maxResolution){maxResolution=props.resolutions[0];} +if(!minResolution){var lastIdx=props.resolutions.length-1;minResolution=props.resolutions[lastIdx];}} +this.resolutions=props.resolutions;if(this.resolutions){len=this.resolutions.length;this.scales=new Array(len);for(i=0;i<len;i++){this.scales[i]=OpenLayers.Util.getScaleFromResolution(this.resolutions[i],this.units);} +this.numZoomLevels=len;} +this.minResolution=minResolution;if(minResolution){this.maxScale=OpenLayers.Util.getScaleFromResolution(minResolution,this.units);} +this.maxResolution=maxResolution;if(maxResolution){this.minScale=OpenLayers.Util.getScaleFromResolution(maxResolution,this.units);}},resolutionsFromScales:function(scales){if(scales==null){return;} +var resolutions,i,len;len=scales.length;resolutions=new Array(len);for(i=0;i<len;i++){resolutions[i]=OpenLayers.Util.getResolutionFromScale(scales[i],this.units);} +return resolutions;},calculateResolutions:function(props){var maxResolution=props.maxResolution;if(props.minScale!=null){maxResolution=OpenLayers.Util.getResolutionFromScale(props.minScale,this.units);}else if(maxResolution=="auto"&&this.maxExtent!=null){var viewSize=this.map.getSize();var wRes=this.maxExtent.getWidth()/viewSize.w;var hRes=this.maxExtent.getHeight()/viewSize.h;maxResolution=Math.max(wRes,hRes);} +var minResolution=props.minResolution;if(props.maxScale!=null){minResolution=OpenLayers.Util.getResolutionFromScale(props.maxScale,this.units);}else if(props.minResolution=="auto"&&this.minExtent!=null){var viewSize=this.map.getSize();var wRes=this.minExtent.getWidth()/viewSize.w;var hRes=this.minExtent.getHeight()/viewSize.h;minResolution=Math.max(wRes,hRes);} +var maxZoomLevel=props.maxZoomLevel;var numZoomLevels=props.numZoomLevels;if(typeof minResolution==="number"&&typeof maxResolution==="number"&&numZoomLevels===undefined){var ratio=maxResolution/minResolution;numZoomLevels=Math.floor(Math.log(ratio)/Math.log(2))+1;}else if(numZoomLevels===undefined&&maxZoomLevel!=null){numZoomLevels=maxZoomLevel+1;} +if(typeof numZoomLevels!=="number"||numZoomLevels<=0||(typeof maxResolution!=="number"&&typeof minResolution!=="number")){return;} +var resolutions=new Array(numZoomLevels);var base=2;if(typeof minResolution=="number"&&typeof maxResolution=="number"){base=Math.pow((maxResolution/minResolution),(1/(numZoomLevels-1)));} +var i;if(typeof maxResolution==="number"){for(i=0;i<numZoomLevels;i++){resolutions[i]=maxResolution/Math.pow(base,i);}}else{for(i=0;i<numZoomLevels;i++){resolutions[numZoomLevels-1-i]=minResolution*Math.pow(base,i);}} +return resolutions;},getResolution:function(){var zoom=this.map.getZoom();return this.getResolutionForZoom(zoom);},getExtent:function(){return this.map.calculateBounds();},getZoomForExtent:function(extent,closest){var viewSize=this.map.getSize();var idealResolution=Math.max(extent.getWidth()/viewSize.w,extent.getHeight()/viewSize.h);return this.getZoomForResolution(idealResolution,closest);},getDataExtent:function(){},getResolutionForZoom:function(zoom){zoom=Math.max(0,Math.min(zoom,this.resolutions.length-1));var resolution;if(this.map.fractionalZoom){var low=Math.floor(zoom);var high=Math.ceil(zoom);resolution=this.resolutions[low]- +((zoom-low)*(this.resolutions[low]-this.resolutions[high]));}else{resolution=this.resolutions[Math.round(zoom)];} +return resolution;},getZoomForResolution:function(resolution,closest){var zoom;if(this.map.fractionalZoom){var lowZoom=0;var highZoom=this.resolutions.length-1;var highRes=this.resolutions[lowZoom];var lowRes=this.resolutions[highZoom];var res;for(var i=0,len=this.resolutions.length;i<len;++i){res=this.resolutions[i];if(res>=resolution){highRes=res;lowZoom=i;} +if(res<=resolution){lowRes=res;highZoom=i;break;}} +var dRes=highRes-lowRes;if(dRes>0){zoom=lowZoom+((highRes-resolution)/dRes);}else{zoom=lowZoom;}}else{var diff;var minDiff=Number.POSITIVE_INFINITY;for(var i=0,len=this.resolutions.length;i<len;i++){if(closest){diff=Math.abs(this.resolutions[i]-resolution);if(diff>minDiff){break;} +minDiff=diff;}else{if(this.resolutions[i]<resolution){break;}}} +zoom=Math.max(0,i-1);} +return zoom;},getLonLatFromViewPortPx:function(viewPortPx){var lonlat=null;if(viewPortPx!=null){var size=this.map.getSize();var center=this.map.getCenter();if(center){var res=this.map.getResolution();var delta_x=viewPortPx.x-(size.w/2);var delta_y=viewPortPx.y-(size.h/2);lonlat=new OpenLayers.LonLat(center.lon+delta_x*res,center.lat-delta_y*res);if(this.wrapDateLine){lonlat=lonlat.wrapDateLine(this.maxExtent);}}} +return lonlat;},getViewPortPxFromLonLat:function(lonlat){var px=null;if(lonlat!=null){var resolution=this.map.getResolution();var extent=this.map.getExtent();px=new OpenLayers.Pixel((1/resolution*(lonlat.lon-extent.left)),(1/resolution*(extent.top-lonlat.lat)));} +return px;},setOpacity:function(opacity){if(opacity!=this.opacity){this.opacity=opacity;for(var i=0,len=this.div.childNodes.length;i<len;++i){var element=this.div.childNodes[i].firstChild;OpenLayers.Util.modifyDOMElement(element,null,null,null,null,null,null,opacity);} +if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"opacity"});}}},getZIndex:function(){return this.div.style.zIndex;},setZIndex:function(zIndex){this.div.style.zIndex=zIndex;},adjustBounds:function(bounds){if(this.gutter){var mapGutter=this.gutter*this.map.getResolution();bounds=new OpenLayers.Bounds(bounds.left-mapGutter,bounds.bottom-mapGutter,bounds.right+mapGutter,bounds.top+mapGutter);} +if(this.wrapDateLine){var wrappingOptions={'rightTolerance':this.getResolution()};bounds=bounds.wrapDateLine(this.maxExtent,wrappingOptions);} +return bounds;},CLASS_NAME:"OpenLayers.Layer"});OpenLayers.Marker.Box=OpenLayers.Class(OpenLayers.Marker,{bounds:null,div:null,initialize:function(bounds,borderColor,borderWidth){this.bounds=bounds;this.div=OpenLayers.Util.createDiv();this.div.style.overflow='hidden';this.events=new OpenLayers.Events(this,this.div,null);this.setBorder(borderColor,borderWidth);},destroy:function(){this.bounds=null;this.div=null;OpenLayers.Marker.prototype.destroy.apply(this,arguments);},setBorder:function(color,width){if(!color){color="red";} +if(!width){width=2;} +this.div.style.border=width+"px solid "+color;},draw:function(px,sz){OpenLayers.Util.modifyDOMElement(this.div,null,px,sz);return this.div;},onScreen:function(){var onScreen=false;if(this.map){var screenBounds=this.map.getExtent();onScreen=screenBounds.containsBounds(this.bounds,true,true);} +return onScreen;},display:function(display){this.div.style.display=(display)?"":"none";},CLASS_NAME:"OpenLayers.Marker.Box"});(function(){var oXMLHttpRequest=window.XMLHttpRequest;var bGecko=!!window.controllers,bIE=window.document.all&&!window.opera,bIE7=bIE&&window.navigator.userAgent.match(/MSIE ([\.0-9]+)/)&&RegExp.$1==7;function cXMLHttpRequest(){this._object=oXMLHttpRequest&&!bIE7?new oXMLHttpRequest:new window.ActiveXObject("Microsoft.XMLHTTP");this._listeners=[];};if(bGecko&&oXMLHttpRequest.wrapped) +cXMLHttpRequest.wrapped=oXMLHttpRequest.wrapped;cXMLHttpRequest.UNSENT=0;cXMLHttpRequest.OPENED=1;cXMLHttpRequest.HEADERS_RECEIVED=2;cXMLHttpRequest.LOADING=3;cXMLHttpRequest.DONE=4;cXMLHttpRequest.prototype.readyState=cXMLHttpRequest.UNSENT;cXMLHttpRequest.prototype.responseText='';cXMLHttpRequest.prototype.responseXML=null;cXMLHttpRequest.prototype.status=0;cXMLHttpRequest.prototype.statusText='';cXMLHttpRequest.prototype.onreadystatechange=null;cXMLHttpRequest.onreadystatechange=null;cXMLHttpRequest.onopen=null;cXMLHttpRequest.onsend=null;cXMLHttpRequest.onabort=null;cXMLHttpRequest.prototype.open=function(sMethod,sUrl,bAsync,sUser,sPassword){delete this._headers;if(arguments.length<3) +bAsync=true;this._async=bAsync;var oRequest=this,nState=this.readyState,fOnUnload;if(bIE&&bAsync){fOnUnload=function(){if(nState!=cXMLHttpRequest.DONE){fCleanTransport(oRequest);oRequest.abort();}};window.attachEvent("onunload",fOnUnload);} +if(cXMLHttpRequest.onopen) +cXMLHttpRequest.onopen.apply(this,arguments);if(arguments.length>4) +this._object.open(sMethod,sUrl,bAsync,sUser,sPassword);else +if(arguments.length>3) +this._object.open(sMethod,sUrl,bAsync,sUser);else +this._object.open(sMethod,sUrl,bAsync);if(!bGecko&&!bIE){this.readyState=cXMLHttpRequest.OPENED;fReadyStateChange(this);} +this._object.onreadystatechange=function(){if(bGecko&&!bAsync) +return;oRequest.readyState=oRequest._object.readyState;fSynchronizeValues(oRequest);if(oRequest._aborted){oRequest.readyState=cXMLHttpRequest.UNSENT;return;} +if(oRequest.readyState==cXMLHttpRequest.DONE){fCleanTransport(oRequest);if(bIE&&bAsync) +window.detachEvent("onunload",fOnUnload);} +if(nState!=oRequest.readyState) +fReadyStateChange(oRequest);nState=oRequest.readyState;}};cXMLHttpRequest.prototype.send=function(vData){if(cXMLHttpRequest.onsend) +cXMLHttpRequest.onsend.apply(this,arguments);if(vData&&vData.nodeType){vData=window.XMLSerializer?new window.XMLSerializer().serializeToString(vData):vData.xml;if(!this._headers["Content-Type"]) +this._object.setRequestHeader("Content-Type","application/xml");} +this._object.send(vData);if(bGecko&&!this._async){this.readyState=cXMLHttpRequest.OPENED;fSynchronizeValues(this);while(this.readyState<cXMLHttpRequest.DONE){this.readyState++;fReadyStateChange(this);if(this._aborted) +return;}}};cXMLHttpRequest.prototype.abort=function(){if(cXMLHttpRequest.onabort) +cXMLHttpRequest.onabort.apply(this,arguments);if(this.readyState>cXMLHttpRequest.UNSENT) +this._aborted=true;this._object.abort();fCleanTransport(this);};cXMLHttpRequest.prototype.getAllResponseHeaders=function(){return this._object.getAllResponseHeaders();};cXMLHttpRequest.prototype.getResponseHeader=function(sName){return this._object.getResponseHeader(sName);};cXMLHttpRequest.prototype.setRequestHeader=function(sName,sValue){if(!this._headers) +this._headers={};this._headers[sName]=sValue;return this._object.setRequestHeader(sName,sValue);};cXMLHttpRequest.prototype.addEventListener=function(sName,fHandler,bUseCapture){for(var nIndex=0,oListener;oListener=this._listeners[nIndex];nIndex++) +if(oListener[0]==sName&&oListener[1]==fHandler&&oListener[2]==bUseCapture) +return;this._listeners.push([sName,fHandler,bUseCapture]);};cXMLHttpRequest.prototype.removeEventListener=function(sName,fHandler,bUseCapture){for(var nIndex=0,oListener;oListener=this._listeners[nIndex];nIndex++) +if(oListener[0]==sName&&oListener[1]==fHandler&&oListener[2]==bUseCapture) +break;if(oListener) +this._listeners.splice(nIndex,1);};cXMLHttpRequest.prototype.dispatchEvent=function(oEvent){var oEventPseudo={'type':oEvent.type,'target':this,'currentTarget':this,'eventPhase':2,'bubbles':oEvent.bubbles,'cancelable':oEvent.cancelable,'timeStamp':oEvent.timeStamp,'stopPropagation':function(){},'preventDefault':function(){},'initEvent':function(){}};if(oEventPseudo.type=="readystatechange"&&this.onreadystatechange) +(this.onreadystatechange.handleEvent||this.onreadystatechange).apply(this,[oEventPseudo]);for(var nIndex=0,oListener;oListener=this._listeners[nIndex];nIndex++) +if(oListener[0]==oEventPseudo.type&&!oListener[2]) +(oListener[1].handleEvent||oListener[1]).apply(this,[oEventPseudo]);};cXMLHttpRequest.prototype.toString=function(){return'['+"object"+' '+"XMLHttpRequest"+']';};cXMLHttpRequest.toString=function(){return'['+"XMLHttpRequest"+']';};function fReadyStateChange(oRequest){if(cXMLHttpRequest.onreadystatechange) +cXMLHttpRequest.onreadystatechange.apply(oRequest);oRequest.dispatchEvent({'type':"readystatechange",'bubbles':false,'cancelable':false,'timeStamp':new Date+0});};function fGetDocument(oRequest){var oDocument=oRequest.responseXML,sResponse=oRequest.responseText;if(bIE&&sResponse&&oDocument&&!oDocument.documentElement&&oRequest.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)){oDocument=new window.ActiveXObject("Microsoft.XMLDOM");oDocument.async=false;oDocument.validateOnParse=false;oDocument.loadXML(sResponse);} +if(oDocument) +if((bIE&&oDocument.parseError!=0)||!oDocument.documentElement||(oDocument.documentElement&&oDocument.documentElement.tagName=="parsererror")) +return null;return oDocument;};function fSynchronizeValues(oRequest){try{oRequest.responseText=oRequest._object.responseText;}catch(e){} +try{oRequest.responseXML=fGetDocument(oRequest._object);}catch(e){} +try{oRequest.status=oRequest._object.status;}catch(e){} +try{oRequest.statusText=oRequest._object.statusText;}catch(e){}};function fCleanTransport(oRequest){oRequest._object.onreadystatechange=new window.Function;};if(!window.Function.prototype.apply){window.Function.prototype.apply=function(oRequest,oArguments){if(!oArguments) +oArguments=[];oRequest.__func=this;oRequest.__func(oArguments[0],oArguments[1],oArguments[2],oArguments[3],oArguments[4]);delete oRequest.__func;};};OpenLayers.Request.XMLHttpRequest=cXMLHttpRequest;})();OpenLayers.Tile.Image.IFrame=OpenLayers.Class(OpenLayers.Tile.Image,{initialize:function(layer,position,bounds,url,size){OpenLayers.Tile.Image.prototype.initialize.apply(this,arguments);this.layerAlphaHack=false;},destroy:function(){if(this.imgDiv!=null){OpenLayers.Event.stopObservingElement(this.imgDiv.firstChild);} +OpenLayers.Tile.Image.prototype.destroy.apply(this,arguments);},clear:function(){if(this.imgDiv){var iFrame=this.imgDiv.firstChild;OpenLayers.Event.stopObservingElement(iFrame);this.imgDiv.removeChild(iFrame);}},clone:function(obj){if(obj==null){obj=new OpenLayers.Tile.Image.IFrame(this.layer,this.position,this.bounds,this.url,this.size);} +obj=OpenLayers.Tile.Image.prototype.clone.apply(this,[obj]);return obj;},renderTile:function(){if(OpenLayers.Tile.Image.prototype.renderTile.apply(this,arguments)){var form=this.createRequestForm();this.imgDiv.appendChild(form);form.submit();this.imgDiv.removeChild(form);}},initImgDiv:function(){this.imgDiv=this.createImgDiv();OpenLayers.Util.modifyDOMElement(this.imgDiv,this.id,null,this.layer.getImageSize(),"relative");this.imgDiv.className='olTileImage';this.frame.appendChild(this.imgDiv);this.layer.div.appendChild(this.frame);if(this.layer.opacity!=null){OpenLayers.Util.modifyDOMElement(this.imgDiv,null,null,null,null,null,null,this.layer.opacity);} +this.imgDiv.map=this.layer.map;},createImgDiv:function(){var eventPane=document.createElement("div");if(OpenLayers.Util.getBrowserName()=="msie"){eventPane.style.backgroundColor='#FFFFFF';eventPane.style.filter='chroma(color=#FFFFFF)';} +OpenLayers.Util.modifyDOMElement(eventPane,null,new OpenLayers.Pixel(0,0),this.layer.getImageSize(),"absolute");var imgDiv=document.createElement("div");imgDiv.appendChild(eventPane);return imgDiv;},createIFrame:function(){var id=this.id+'_iFrame';var iframe;if(OpenLayers.Util.getBrowserName()=="msie"){iframe=document.createElement('<iframe name="'+id+'">');iframe.style.backgroundColor='#FFFFFF';iframe.style.filter='chroma(color=#FFFFFF)';} +else{iframe=document.createElement('iframe');iframe.style.backgroundColor='transparent';iframe.name=id;} +iframe.id=id;iframe.scrolling='no';iframe.marginWidth='0px';iframe.marginHeight='0px';iframe.frameBorder='0';OpenLayers.Util.modifyDOMElement(iframe,id,new OpenLayers.Pixel(0,0),this.layer.getImageSize(),"absolute");var onload=function(){this.show();if(this.isLoading){this.isLoading=false;this.events.triggerEvent("loadend");}};OpenLayers.Event.observe(iframe,'load',OpenLayers.Function.bind(onload,this));return iframe;},createRequestForm:function(){var form=document.createElement('form');form.method='POST';var cacheId=this.layer.params["_OLSALT"];cacheId=(cacheId?cacheId+"_":"")+this.bounds.toBBOX();form.action=OpenLayers.Util.urlAppend(this.layer.url,cacheId);this.imgDiv.insertBefore(this.createIFrame(),this.imgDiv.firstChild);form.target=this.id+'_iFrame';var imageSize=this.layer.getImageSize();var params=OpenLayers.Util.extend({"BBOX":this.encodeBBOX?this.bounds.toBBOX():this.bounds.toArray(),"WIDTH":imageSize.w,"HEIGHT":imageSize.h},this.layer.params);for(var par in params){var field=document.createElement('input');field.type='hidden';field.name=par;field.value=params[par];form.appendChild(field);} +return form;},CLASS_NAME:"OpenLayers.Tile.Image.IFrame"});OpenLayers.ProxyHost="";OpenLayers.nullHandler=function(request){OpenLayers.Console.userError(OpenLayers.i18n("unhandledRequest",{'statusText':request.statusText}));};OpenLayers.loadURL=function(uri,params,caller,onComplete,onFailure){if(typeof params=='string'){params=OpenLayers.Util.getParameters(params);} +var success=(onComplete)?onComplete:OpenLayers.nullHandler;var failure=(onFailure)?onFailure:OpenLayers.nullHandler;return OpenLayers.Request.GET({url:uri,params:params,success:success,failure:failure,scope:caller});};OpenLayers.parseXMLString=function(text){var index=text.indexOf('<');if(index>0){text=text.substring(index);} +var ajaxResponse=OpenLayers.Util.Try(function(){var xmldom=new ActiveXObject('Microsoft.XMLDOM');xmldom.loadXML(text);return xmldom;},function(){return new DOMParser().parseFromString(text,'text/xml');},function(){var req=new XMLHttpRequest();req.open("GET","data:"+"text/xml"+";charset=utf-8,"+encodeURIComponent(text),false);if(req.overrideMimeType){req.overrideMimeType("text/xml");} +req.send(null);return req.responseXML;});return ajaxResponse;};OpenLayers.Ajax={emptyFunction:function(){},getTransport:function(){return OpenLayers.Util.Try(function(){return new XMLHttpRequest();},function(){return new ActiveXObject('Msxml2.XMLHTTP');},function(){return new ActiveXObject('Microsoft.XMLHTTP');})||false;},activeRequestCount:0};OpenLayers.Ajax.Responders={responders:[],register:function(responderToAdd){for(var i=0;i<this.responders.length;i++){if(responderToAdd==this.responders[i]){return;}} +this.responders.push(responderToAdd);},unregister:function(responderToRemove){OpenLayers.Util.removeItem(this.reponders,responderToRemove);},dispatch:function(callback,request,transport){var responder;for(var i=0;i<this.responders.length;i++){responder=this.responders[i];if(responder[callback]&&typeof responder[callback]=='function'){try{responder[callback].apply(responder,[request,transport]);}catch(e){}}}}};OpenLayers.Ajax.Responders.register({onCreate:function(){OpenLayers.Ajax.activeRequestCount++;},onComplete:function(){OpenLayers.Ajax.activeRequestCount--;}});OpenLayers.Ajax.Base=OpenLayers.Class({initialize:function(options){this.options={method:'post',asynchronous:true,contentType:'application/xml',parameters:''};OpenLayers.Util.extend(this.options,options||{});this.options.method=this.options.method.toLowerCase();if(typeof this.options.parameters=='string'){this.options.parameters=OpenLayers.Util.getParameters(this.options.parameters);}}});OpenLayers.Ajax.Request=OpenLayers.Class(OpenLayers.Ajax.Base,{_complete:false,initialize:function(url,options){OpenLayers.Ajax.Base.prototype.initialize.apply(this,[options]);if(OpenLayers.ProxyHost&&OpenLayers.String.startsWith(url,"http")){url=OpenLayers.ProxyHost+encodeURIComponent(url);} +this.transport=OpenLayers.Ajax.getTransport();this.request(url);},request:function(url){this.url=url;this.method=this.options.method;var params=OpenLayers.Util.extend({},this.options.parameters);if(this.method!='get'&&this.method!='post'){params['_method']=this.method;this.method='post';} +this.parameters=params;if(params=OpenLayers.Util.getParameterString(params)){if(this.method=='get'){this.url+=((this.url.indexOf('?')>-1)?'&':'?')+params;}else if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)){params+='&_=';}} +try{var response=new OpenLayers.Ajax.Response(this);if(this.options.onCreate){this.options.onCreate(response);} +OpenLayers.Ajax.Responders.dispatch('onCreate',this,response);this.transport.open(this.method.toUpperCase(),this.url,this.options.asynchronous);if(this.options.asynchronous){window.setTimeout(OpenLayers.Function.bind(this.respondToReadyState,this,1),10);} +this.transport.onreadystatechange=OpenLayers.Function.bind(this.onStateChange,this);this.setRequestHeaders();this.body=this.method=='post'?(this.options.postBody||params):null;this.transport.send(this.body);if(!this.options.asynchronous&&this.transport.overrideMimeType){this.onStateChange();}}catch(e){this.dispatchException(e);}},onStateChange:function(){var readyState=this.transport.readyState;if(readyState>1&&!((readyState==4)&&this._complete)){this.respondToReadyState(this.transport.readyState);}},setRequestHeaders:function(){var headers={'X-Requested-With':'XMLHttpRequest','Accept':'text/javascript, text/html, application/xml, text/xml, */*','OpenLayers':true};if(this.method=='post'){headers['Content-type']=this.options.contentType+ +(this.options.encoding?'; charset='+this.options.encoding:'');if(this.transport.overrideMimeType&&(navigator.userAgent.match(/Gecko\/(\d{4})/)||[0,2005])[1]<2005){headers['Connection']='close';}} +if(typeof this.options.requestHeaders=='object'){var extras=this.options.requestHeaders;if(typeof extras.push=='function'){for(var i=0,length=extras.length;i<length;i+=2){headers[extras[i]]=extras[i+1];}}else{for(var i in extras){headers[i]=extras[i];}}} +for(var name in headers){this.transport.setRequestHeader(name,headers[name]);}},success:function(){var status=this.getStatus();return!status||(status>=200&&status<300);},getStatus:function(){try{return this.transport.status||0;}catch(e){return 0;}},respondToReadyState:function(readyState){var state=OpenLayers.Ajax.Request.Events[readyState];var response=new OpenLayers.Ajax.Response(this);if(state=='Complete'){try{this._complete=true;(this.options['on'+response.status]||this.options['on'+(this.success()?'Success':'Failure')]||OpenLayers.Ajax.emptyFunction)(response);}catch(e){this.dispatchException(e);} +var contentType=response.getHeader('Content-type');} +try{(this.options['on'+state]||OpenLayers.Ajax.emptyFunction)(response);OpenLayers.Ajax.Responders.dispatch('on'+state,this,response);}catch(e){this.dispatchException(e);} +if(state=='Complete'){this.transport.onreadystatechange=OpenLayers.Ajax.emptyFunction;}},getHeader:function(name){try{return this.transport.getResponseHeader(name);}catch(e){return null;}},dispatchException:function(exception){var handler=this.options.onException;if(handler){handler(this,exception);OpenLayers.Ajax.Responders.dispatch('onException',this,exception);}else{var listener=false;var responders=OpenLayers.Ajax.Responders.responders;for(var i=0;i<responders.length;i++){if(responders[i].onException){listener=true;break;}} +if(listener){OpenLayers.Ajax.Responders.dispatch('onException',this,exception);}else{throw exception;}}}});OpenLayers.Ajax.Request.Events=['Uninitialized','Loading','Loaded','Interactive','Complete'];OpenLayers.Ajax.Response=OpenLayers.Class({status:0,statusText:'',initialize:function(request){this.request=request;var transport=this.transport=request.transport,readyState=this.readyState=transport.readyState;if((readyState>2&&!(!!(window.attachEvent&&!window.opera)))||readyState==4){this.status=this.getStatus();this.statusText=this.getStatusText();this.responseText=transport.responseText==null?'':String(transport.responseText);} +if(readyState==4){var xml=transport.responseXML;this.responseXML=xml===undefined?null:xml;}},getStatus:OpenLayers.Ajax.Request.prototype.getStatus,getStatusText:function(){try{return this.transport.statusText||'';}catch(e){return'';}},getHeader:OpenLayers.Ajax.Request.prototype.getHeader,getResponseHeader:function(name){return this.transport.getResponseHeader(name);}});OpenLayers.Ajax.getElementsByTagNameNS=function(parentnode,nsuri,nsprefix,tagname){var elem=null;if(parentnode.getElementsByTagNameNS){elem=parentnode.getElementsByTagNameNS(nsuri,tagname);}else{elem=parentnode.getElementsByTagName(nsprefix+':'+tagname);} +return elem;};OpenLayers.Ajax.serializeXMLToString=function(xmldom){var serializer=new XMLSerializer();var data=serializer.serializeToString(xmldom);return data;};OpenLayers.Control.DragFeature=OpenLayers.Class(OpenLayers.Control,{geometryTypes:null,onStart:function(feature,pixel){},onDrag:function(feature,pixel){},onComplete:function(feature,pixel){},documentDrag:false,layer:null,feature:null,dragCallbacks:{},featureCallbacks:{},lastPixel:null,initialize:function(layer,options){OpenLayers.Control.prototype.initialize.apply(this,[options]);this.layer=layer;this.handlers={drag:new OpenLayers.Handler.Drag(this,OpenLayers.Util.extend({down:this.downFeature,move:this.moveFeature,up:this.upFeature,out:this.cancel,done:this.doneDragging},this.dragCallbacks),{documentDrag:this.documentDrag}),feature:new OpenLayers.Handler.Feature(this,this.layer,OpenLayers.Util.extend({over:this.overFeature,out:this.outFeature},this.featureCallbacks),{geometryTypes:this.geometryTypes})};},destroy:function(){this.layer=null;OpenLayers.Control.prototype.destroy.apply(this,[]);},activate:function(){return(this.handlers.feature.activate()&&OpenLayers.Control.prototype.activate.apply(this,arguments));},deactivate:function(){this.handlers.drag.deactivate();this.handlers.feature.deactivate();this.feature=null;this.dragging=false;this.lastPixel=null;OpenLayers.Element.removeClass(this.map.viewPortDiv,this.displayClass+"Over");return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},overFeature:function(feature){if(!this.handlers.drag.dragging){this.feature=feature;this.handlers.drag.activate();this.over=true;OpenLayers.Element.addClass(this.map.viewPortDiv,this.displayClass+"Over");}else{if(this.feature.id==feature.id){this.over=true;}else{this.over=false;}}},downFeature:function(pixel){this.lastPixel=pixel;this.onStart(this.feature,pixel);},moveFeature:function(pixel){var res=this.map.getResolution();this.feature.geometry.move(res*(pixel.x-this.lastPixel.x),res*(this.lastPixel.y-pixel.y));this.layer.drawFeature(this.feature);this.lastPixel=pixel;this.onDrag(this.feature,pixel);},upFeature:function(pixel){if(!this.over){this.handlers.drag.deactivate();}},doneDragging:function(pixel){this.onComplete(this.feature,pixel);},outFeature:function(feature){if(!this.handlers.drag.dragging){this.over=false;this.handlers.drag.deactivate();OpenLayers.Element.removeClass(this.map.viewPortDiv,this.displayClass+"Over");this.feature=null;}else{if(this.feature.id==feature.id){this.over=false;}}},cancel:function(){this.handlers.drag.deactivate();this.over=false;},setMap:function(map){this.handlers.drag.setMap(map);this.handlers.feature.setMap(map);OpenLayers.Control.prototype.setMap.apply(this,arguments);},CLASS_NAME:"OpenLayers.Control.DragFeature"});OpenLayers.Control.DragPan=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,panned:false,interval:25,documentDrag:false,draw:function(){this.handler=new OpenLayers.Handler.Drag(this,{"move":this.panMap,"done":this.panMapDone},{interval:this.interval,documentDrag:this.documentDrag});},panMap:function(xy){this.panned=true;this.map.pan(this.handler.last.x-xy.x,this.handler.last.y-xy.y,{dragging:this.handler.dragging,animate:false});},panMapDone:function(xy){if(this.panned){this.panMap(xy);this.panned=false;}},CLASS_NAME:"OpenLayers.Control.DragPan"});OpenLayers.Control.KeyboardDefaults=OpenLayers.Class(OpenLayers.Control,{autoActivate:true,slideFactor:75,initialize:function(){OpenLayers.Control.prototype.initialize.apply(this,arguments);},destroy:function(){if(this.handler){this.handler.destroy();} +this.handler=null;OpenLayers.Control.prototype.destroy.apply(this,arguments);},draw:function(){this.handler=new OpenLayers.Handler.Keyboard(this,{"keydown":this.defaultKeyPress});},defaultKeyPress:function(evt){switch(evt.keyCode){case OpenLayers.Event.KEY_LEFT:this.map.pan(-this.slideFactor,0);break;case OpenLayers.Event.KEY_RIGHT:this.map.pan(this.slideFactor,0);break;case OpenLayers.Event.KEY_UP:this.map.pan(0,-this.slideFactor);break;case OpenLayers.Event.KEY_DOWN:this.map.pan(0,this.slideFactor);break;case 33:var size=this.map.getSize();this.map.pan(0,-0.75*size.h);break;case 34:var size=this.map.getSize();this.map.pan(0,0.75*size.h);break;case 35:var size=this.map.getSize();this.map.pan(0.75*size.w,0);break;case 36:var size=this.map.getSize();this.map.pan(-0.75*size.w,0);break;case 43:case 61:case 187:case 107:this.map.zoomIn();break;case 45:case 109:case 189:case 95:this.map.zoomOut();break;}},CLASS_NAME:"OpenLayers.Control.KeyboardDefaults"});OpenLayers.Control.WMSGetFeatureInfo=OpenLayers.Class(OpenLayers.Control,{hover:false,drillDown:false,maxFeatures:10,clickCallback:"click",layers:null,queryVisible:false,url:null,layerUrls:null,infoFormat:'text/html',vendorParams:{},format:null,formatOptions:null,handlerOptions:null,handler:null,hoverRequest:null,EVENT_TYPES:["beforegetfeatureinfo","nogetfeatureinfo","getfeatureinfo"],initialize:function(options){this.EVENT_TYPES=OpenLayers.Control.WMSGetFeatureInfo.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);options=options||{};options.handlerOptions=options.handlerOptions||{};OpenLayers.Control.prototype.initialize.apply(this,[options]);if(!this.format){this.format=new OpenLayers.Format.WMSGetFeatureInfo(options.formatOptions);} +if(this.drillDown===true){this.hover=false;} +if(this.hover){this.handler=new OpenLayers.Handler.Hover(this,{'move':this.cancelHover,'pause':this.getInfoForHover},OpenLayers.Util.extend(this.handlerOptions.hover||{},{'delay':250}));}else{var callbacks={};callbacks[this.clickCallback]=this.getInfoForClick;this.handler=new OpenLayers.Handler.Click(this,callbacks,this.handlerOptions.click||{});}},activate:function(){if(!this.active){this.handler.activate();} +return OpenLayers.Control.prototype.activate.apply(this,arguments);},deactivate:function(){return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},getInfoForClick:function(evt){this.events.triggerEvent("beforegetfeatureinfo",{xy:evt.xy});OpenLayers.Element.addClass(this.map.viewPortDiv,"olCursorWait");this.request(evt.xy,{});},getInfoForHover:function(evt){this.events.triggerEvent("beforegetfeatureinfo",{xy:evt.xy});this.request(evt.xy,{hover:true});},cancelHover:function(){if(this.hoverRequest){this.hoverRequest.abort();this.hoverRequest=null;}},findLayers:function(){var candidates=this.layers||this.map.layers;var layers=[];var layer,url;for(var i=0,len=candidates.length;i<len;++i){layer=candidates[i];if(layer instanceof OpenLayers.Layer.WMS&&(!this.queryVisible||layer.getVisibility())){url=layer.url instanceof Array?layer.url[0]:layer.url;if(this.drillDown===false&&!this.url){this.url=url;} +if(this.drillDown===true||this.urlMatches(url)){layers.push(layer);}}} +return layers;},urlMatches:function(url){var matches=OpenLayers.Util.isEquivalentUrl(this.url,url);if(!matches&&this.layerUrls){for(var i=0,len=this.layerUrls.length;i<len;++i){if(OpenLayers.Util.isEquivalentUrl(this.layerUrls[i],url)){matches=true;break;}}} +return matches;},buildWMSOptions:function(url,layers,clickPosition,format){var layerNames=[],styleNames=[];for(var i=0,len=layers.length;i<len;i++){layerNames=layerNames.concat(layers[i].params.LAYERS);styleNames=styleNames.concat(this.getStyleNames(layers[i]));} +var params=OpenLayers.Util.extend({service:"WMS",version:layers[0].params.VERSION,request:"GetFeatureInfo",layers:layerNames,query_layers:layerNames,styles:styleNames,bbox:this.map.getExtent().toBBOX(null,layers[0].reverseAxisOrder()),feature_count:this.maxFeatures,height:this.map.getSize().h,width:this.map.getSize().w,format:format,info_format:this.infoFormat},(parseFloat(layers[0].params.VERSION)>=1.3)?{crs:this.map.getProjection(),i:clickPosition.x,j:clickPosition.y}:{srs:this.map.getProjection(),x:clickPosition.x,y:clickPosition.y});OpenLayers.Util.applyDefaults(params,this.vendorParams);return{url:url,params:OpenLayers.Util.upperCaseObject(params),callback:function(request){this.handleResponse(clickPosition,request);},scope:this};},getStyleNames:function(layer){var styleNames;if(layer.params.STYLES){styleNames=layer.params.STYLES;}else{if(layer.params.LAYERS instanceof Array){styleNames=new Array(layer.params.LAYERS.length);}else{styleNames=layer.params.LAYERS.replace(/[^,]/g,"");}} +return styleNames;},request:function(clickPosition,options){var layers=this.findLayers();if(layers.length==0){this.events.triggerEvent("nogetfeatureinfo");OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait");return;} +options=options||{};if(this.drillDown===false){var wmsOptions=this.buildWMSOptions(this.url,layers,clickPosition,layers[0].params.FORMAT);var request=OpenLayers.Request.GET(wmsOptions);if(options.hover===true){this.hoverRequest=request;}}else{this._requestCount=0;this._numRequests=0;this.features=[];var services={},url;for(var i=0,len=layers.length;i<len;i++){var layer=layers[i];var service,found=false;url=layer.url instanceof Array?layer.url[0]:layer.url;if(url in services){services[url].push(layer);}else{this._numRequests++;services[url]=[layer];}} +var layers;for(var url in services){layers=services[url];var wmsOptions=this.buildWMSOptions(url,layers,clickPosition,layers[0].params.FORMAT);OpenLayers.Request.GET(wmsOptions);}}},triggerGetFeatureInfo:function(request,xy,features){this.events.triggerEvent("getfeatureinfo",{text:request.responseText,features:features,request:request,xy:xy});OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait");},handleResponse:function(xy,request){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;} +var features=this.format.read(doc);if(this.drillDown===false){this.triggerGetFeatureInfo(request,xy,features);}else{this._requestCount++;this._features=(this._features||[]).concat(features);if(this._requestCount===this._numRequests){this.triggerGetFeatureInfo(request,xy,this._features.concat());delete this._features;delete this._requestCount;delete this._numRequests;}}},CLASS_NAME:"OpenLayers.Control.WMSGetFeatureInfo"});OpenLayers.Control.WMTSGetFeatureInfo=OpenLayers.Class(OpenLayers.Control,{hover:false,requestEncoding:"KVP",drillDown:false,maxFeatures:10,clickCallback:"click",layers:null,queryVisible:true,infoFormat:'text/html',vendorParams:{},format:null,formatOptions:null,handlerOptions:null,handler:null,hoverRequest:null,EVENT_TYPES:["beforegetfeatureinfo","getfeatureinfo","exception"],pending:0,initialize:function(options){this.EVENT_TYPES=OpenLayers.Control.WMTSGetFeatureInfo.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);options=options||{};options.handlerOptions=options.handlerOptions||{};OpenLayers.Control.prototype.initialize.apply(this,[options]);if(!this.format){this.format=new OpenLayers.Format.WMSGetFeatureInfo(options.formatOptions);} +if(this.drillDown===true){this.hover=false;} +if(this.hover){this.handler=new OpenLayers.Handler.Hover(this,{move:this.cancelHover,pause:this.getInfoForHover},OpenLayers.Util.extend(this.handlerOptions.hover||{},{delay:250}));}else{var callbacks={};callbacks[this.clickCallback]=this.getInfoForClick;this.handler=new OpenLayers.Handler.Click(this,callbacks,this.handlerOptions.click||{});}},activate:function(){if(!this.active){this.handler.activate();} +return OpenLayers.Control.prototype.activate.apply(this,arguments);},deactivate:function(){return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},getInfoForClick:function(evt){this.request(evt.xy,{});},getInfoForHover:function(evt){this.request(evt.xy,{hover:true});},cancelHover:function(){if(this.hoverRequest){--this.pending;if(this.pending<=0){OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait");this.pending=0;} +this.hoverRequest.abort();this.hoverRequest=null;}},findLayers:function(){var candidates=this.layers||this.map.layers;var layers=[];var layer;for(var i=candidates.length-1;i>=0;--i){layer=candidates[i];if(layer instanceof OpenLayers.Layer.WMTS&&layer.requestEncoding===this.requestEncoding&&(!this.queryVisible||layer.getVisibility())){layers.push(layer);if(!this.drillDown||this.hover){break;}}} +return layers;},buildRequestOptions:function(layer,xy){var loc=this.map.getLonLatFromPixel(xy);var getTileUrl=layer.getURL(new OpenLayers.Bounds(loc.lon,loc.lat,loc.lon,loc.lat));var params=OpenLayers.Util.getParameters(getTileUrl);var tileInfo=layer.getTileInfo(loc);OpenLayers.Util.extend(params,{service:"WMTS",version:layer.version,request:"GetFeatureInfo",infoFormat:this.infoFormat,i:tileInfo.i,j:tileInfo.j});OpenLayers.Util.applyDefaults(params,this.vendorParams);return{url:layer.url instanceof Array?layer.url[0]:layer.url,params:OpenLayers.Util.upperCaseObject(params),callback:function(request){this.handleResponse(xy,request,layer);},scope:this};},request:function(xy,options){options=options||{};var layers=this.findLayers();if(layers.length>0){var issue,layer;for(var i=0,len=layers.length;i<len;i++){layer=layers[i];issue=this.events.triggerEvent("beforegetfeatureinfo",{xy:xy,layer:layer});if(issue!==false){++this.pending;var requestOptions=this.buildRequestOptions(layer,xy);var request=OpenLayers.Request.GET(requestOptions);if(options.hover===true){this.hoverRequest=request;}}} +if(this.pending>0){OpenLayers.Element.addClass(this.map.viewPortDiv,"olCursorWait");}}},handleResponse:function(xy,request,layer){--this.pending;if(this.pending<=0){OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait");this.pending=0;} +if(request.status&&(request.status<200||request.status>=300)){this.events.triggerEvent("exception",{xy:xy,request:request,layer:layer});}else{var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;} +var features,except;try{features=this.format.read(doc);}catch(error){except=true;this.events.triggerEvent("exception",{xy:xy,request:request,error:error,layer:layer});} +if(!except){this.events.triggerEvent("getfeatureinfo",{text:request.responseText,features:features,request:request,xy:xy,layer:layer});}}},setMap:function(map){this.handler.setMap(map);OpenLayers.Control.prototype.setMap.apply(this,arguments);},CLASS_NAME:"OpenLayers.Control.WMTSGetFeatureInfo"});OpenLayers.State={UNKNOWN:'Unknown',INSERT:'Insert',UPDATE:'Update',DELETE:'Delete'};OpenLayers.Feature.Vector=OpenLayers.Class(OpenLayers.Feature,{fid:null,geometry:null,attributes:null,bounds:null,state:null,style:null,url:null,renderIntent:"default",initialize:function(geometry,attributes,style){OpenLayers.Feature.prototype.initialize.apply(this,[null,null,attributes]);this.lonlat=null;this.geometry=geometry?geometry:null;this.state=null;this.attributes={};if(attributes){this.attributes=OpenLayers.Util.extend(this.attributes,attributes);} +this.style=style?style:null;},destroy:function(){if(this.layer){this.layer.removeFeatures(this);this.layer=null;} +this.geometry=null;OpenLayers.Feature.prototype.destroy.apply(this,arguments);},clone:function(){return new OpenLayers.Feature.Vector(this.geometry?this.geometry.clone():null,this.attributes,this.style);},onScreen:function(boundsOnly){var onScreen=false;if(this.layer&&this.layer.map){var screenBounds=this.layer.map.getExtent();if(boundsOnly){var featureBounds=this.geometry.getBounds();onScreen=screenBounds.intersectsBounds(featureBounds);}else{var screenPoly=screenBounds.toGeometry();onScreen=screenPoly.intersects(this.geometry);}} +return onScreen;},getVisibility:function(){return!(this.style&&this.style.display=='none'||!this.layer||this.layer&&this.layer.styleMap&&this.layer.styleMap.createSymbolizer(this,this.renderIntent).display=='none'||this.layer&&!this.layer.getVisibility());},createMarker:function(){return null;},destroyMarker:function(){},createPopup:function(){return null;},atPoint:function(lonlat,toleranceLon,toleranceLat){var atPoint=false;if(this.geometry){atPoint=this.geometry.atPoint(lonlat,toleranceLon,toleranceLat);} +return atPoint;},destroyPopup:function(){},move:function(location){if(!this.layer||!this.geometry.move){return;} +var pixel;if(location.CLASS_NAME=="OpenLayers.LonLat"){pixel=this.layer.getViewPortPxFromLonLat(location);}else{pixel=location;} +var lastPixel=this.layer.getViewPortPxFromLonLat(this.geometry.getBounds().getCenterLonLat());var res=this.layer.map.getResolution();this.geometry.move(res*(pixel.x-lastPixel.x),res*(lastPixel.y-pixel.y));this.layer.drawFeature(this);return lastPixel;},toState:function(state){if(state==OpenLayers.State.UPDATE){switch(this.state){case OpenLayers.State.UNKNOWN:case OpenLayers.State.DELETE:this.state=state;break;case OpenLayers.State.UPDATE:case OpenLayers.State.INSERT:break;}}else if(state==OpenLayers.State.INSERT){switch(this.state){case OpenLayers.State.UNKNOWN:break;default:this.state=state;break;}}else if(state==OpenLayers.State.DELETE){switch(this.state){case OpenLayers.State.INSERT:break;case OpenLayers.State.DELETE:break;case OpenLayers.State.UNKNOWN:case OpenLayers.State.UPDATE:this.state=state;break;}}else if(state==OpenLayers.State.UNKNOWN){this.state=state;}},CLASS_NAME:"OpenLayers.Feature.Vector"});OpenLayers.Feature.Vector.style={'default':{fillColor:"#ee9900",fillOpacity:0.4,hoverFillColor:"white",hoverFillOpacity:0.8,strokeColor:"#ee9900",strokeOpacity:1,strokeWidth:1,strokeLinecap:"round",strokeDashstyle:"solid",hoverStrokeColor:"red",hoverStrokeOpacity:1,hoverStrokeWidth:0.2,pointRadius:6,hoverPointRadius:1,hoverPointUnit:"%",pointerEvents:"visiblePainted",cursor:"inherit"},'select':{fillColor:"blue",fillOpacity:0.4,hoverFillColor:"white",hoverFillOpacity:0.8,strokeColor:"blue",strokeOpacity:1,strokeWidth:2,strokeLinecap:"round",strokeDashstyle:"solid",hoverStrokeColor:"red",hoverStrokeOpacity:1,hoverStrokeWidth:0.2,pointRadius:6,hoverPointRadius:1,hoverPointUnit:"%",pointerEvents:"visiblePainted",cursor:"pointer"},'temporary':{fillColor:"#66cccc",fillOpacity:0.2,hoverFillColor:"white",hoverFillOpacity:0.8,strokeColor:"#66cccc",strokeOpacity:1,strokeLinecap:"round",strokeWidth:2,strokeDashstyle:"solid",hoverStrokeColor:"red",hoverStrokeOpacity:1,hoverStrokeWidth:0.2,pointRadius:6,hoverPointRadius:1,hoverPointUnit:"%",pointerEvents:"visiblePainted",cursor:"inherit"},'delete':{display:"none"}};OpenLayers.Feature.WFS=OpenLayers.Class(OpenLayers.Feature,{initialize:function(layer,xmlNode){var newArguments=arguments;var data=this.processXMLNode(xmlNode);newArguments=new Array(layer,data.lonlat,data);OpenLayers.Feature.prototype.initialize.apply(this,newArguments);this.createMarker();this.layer.addMarker(this.marker);},destroy:function(){if(this.marker!=null){this.layer.removeMarker(this.marker);} +OpenLayers.Feature.prototype.destroy.apply(this,arguments);},processXMLNode:function(xmlNode){var point=OpenLayers.Ajax.getElementsByTagNameNS(xmlNode,"http://www.opengis.net/gml","gml","Point");var text=OpenLayers.Util.getXmlNodeValue(OpenLayers.Ajax.getElementsByTagNameNS(point[0],"http://www.opengis.net/gml","gml","coordinates")[0]);var floats=text.split(",");return{lonlat:new OpenLayers.LonLat(parseFloat(floats[0]),parseFloat(floats[1])),id:null};},CLASS_NAME:"OpenLayers.Feature.WFS"});OpenLayers.Format.OWSCommon.v1_0_0=OpenLayers.Class(OpenLayers.Format.OWSCommon.v1,{namespaces:{ows:"http://www.opengis.net/ows/1.0",xlink:"http://www.w3.org/1999/xlink"},readers:{"ows":OpenLayers.Format.OWSCommon.v1.prototype.readers["ows"]},writers:{"ows":OpenLayers.Format.OWSCommon.v1.prototype.writers["ows"]},CLASS_NAME:"OpenLayers.Format.OWSCommon.v1_1_0"});OpenLayers.Format.OWSCommon.v1_1_0=OpenLayers.Class(OpenLayers.Format.OWSCommon.v1,{namespaces:{ows:"http://www.opengis.net/ows/1.1",xlink:"http://www.w3.org/1999/xlink"},readers:{"ows":OpenLayers.Util.applyDefaults({"AllowedValues":function(node,parameter){parameter.allowedValues={};this.readChildNodes(node,parameter.allowedValues);},"AnyValue":function(node,parameter){parameter.anyValue=true;},"Range":function(node,allowedValues){allowedValues.range={};this.readChildNodes(node,allowedValues.range);},"MinimumValue":function(node,range){range.minValue=this.getChildValue(node);},"MaximumValue":function(node,range){range.maxValue=this.getChildValue(node);},"Identifier":function(node,obj){obj.identifier=this.getChildValue(node);},"SupportedCRS":function(node,obj){obj.supportedCRS=this.getChildValue(node);}},OpenLayers.Format.OWSCommon.v1.prototype.readers["ows"])},CLASS_NAME:"OpenLayers.Format.OWSCommon.v1_1_0"});OpenLayers.Format.OWSContext=OpenLayers.Class(OpenLayers.Format.Context,{defaultVersion:"0.3.1",getParser:function(version){var v=version||this.version||this.defaultVersion;if(v==="0.3.0"){v=this.defaultVersion;} +if(!this.parser||this.parser.VERSION!=v){var format=OpenLayers.Format.OWSContext["v"+v.replace(/\./g,"_")];if(!format){throw"Can't find a OWSContext parser for version "+v;} +this.parser=new format(this.options);} +return this.parser;},toContext:function(obj){var context={};if(obj.CLASS_NAME=="OpenLayers.Map"){context.bounds=obj.getExtent();context.maxExtent=obj.maxExtent;context.projection=obj.projection;context.size=obj.getSize();context.layers=obj.layers;} +return context;},CLASS_NAME:"OpenLayers.Format.OWSContext"});OpenLayers.Format.WFSCapabilities.v1=OpenLayers.Class(OpenLayers.Format.WFSCapabilities,{initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +var capabilities={};var root=data.documentElement;this.runChildNodes(capabilities,root);return capabilities;},runChildNodes:function(obj,node){var children=node.childNodes;var childNode,processor;for(var i=0;i<children.length;++i){childNode=children[i];if(childNode.nodeType==1){processor=this["read_cap_"+childNode.nodeName];if(processor){processor.apply(this,[obj,childNode]);}}}},read_cap_FeatureTypeList:function(request,node){var featureTypeList={featureTypes:[]};this.runChildNodes(featureTypeList,node);request.featureTypeList=featureTypeList;},read_cap_FeatureType:function(featureTypeList,node,parentLayer){var featureType={};this.runChildNodes(featureType,node);featureTypeList.featureTypes.push(featureType);},read_cap_Name:function(obj,node){var name=this.getChildValue(node);if(name){var parts=name.split(":");obj.name=parts.pop();if(parts.length>0){obj.featureNS=this.lookupNamespaceURI(node,parts[0]);}}},read_cap_Title:function(obj,node){var title=this.getChildValue(node);if(title){obj.title=title;}},read_cap_Abstract:function(obj,node){var abst=this.getChildValue(node);if(abst){obj["abstract"]=abst;}},CLASS_NAME:"OpenLayers.Format.WFSCapabilities.v1"});OpenLayers.Format.WMC=OpenLayers.Class(OpenLayers.Format.Context,{defaultVersion:"1.1.0",getParser:function(version){var v=version||this.version||this.defaultVersion;if(!this.parser||this.parser.VERSION!=v){var format=OpenLayers.Format.WMC["v"+v.replace(/\./g,"_")];if(!format){throw"Can't find a WMC parser for version "+v;} +this.parser=new format(this.options);} +return this.parser;},layerToContext:function(layer){var parser=this.getParser();var layerContext={queryable:layer.queryable,visibility:layer.visibility,name:layer.params["LAYERS"],title:layer.name,metadataURL:layer.metadataURL,version:layer.params["VERSION"],url:layer.url,maxExtent:layer.maxExtent,transparent:layer.params["TRANSPARENT"],numZoomLevels:layer.numZoomLevels,units:layer.units,isBaseLayer:layer.isBaseLayer,opacity:layer.opacity,displayInLayerSwitcher:layer.displayInLayerSwitcher,singleTile:layer.singleTile,tileSize:(layer.singleTile||!layer.tileSize)?undefined:{width:layer.tileSize.w,height:layer.tileSize.h},minScale:(layer.options.resolutions||layer.options.scales||layer.options.maxResolution||layer.options.minScale)?layer.minScale:undefined,maxScale:(layer.options.resolutions||layer.options.scales||layer.options.minResolution||layer.options.maxScale)?layer.maxScale:undefined,formats:[{value:layer.params["FORMAT"],current:true}],styles:[{href:layer.params["SLD"],body:layer.params["SLD_BODY"],name:layer.params["STYLES"]||parser.defaultStyleName,title:parser.defaultStyleTitle,current:true}]};return layerContext;},toContext:function(obj){var context={};var layers=obj.layers;if(obj.CLASS_NAME=="OpenLayers.Map"){context.bounds=obj.getExtent();context.maxExtent=obj.maxExtent;context.projection=obj.projection;context.size=obj.getSize();} +else{OpenLayers.Util.applyDefaults(context,obj);if(context.layers!=undefined){delete(context.layers);}} +if(context.layersContext==undefined){context.layersContext=[];} +if(layers!=undefined&&layers instanceof Array){for(var i=0,len=layers.length;i<len;i++){var layer=layers[i];if(layer instanceof OpenLayers.Layer.WMS){context.layersContext.push(this.layerToContext(layer));}}} +return context;},CLASS_NAME:"OpenLayers.Format.WMC"});OpenLayers.Format.WMSCapabilities.v1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{wms:"http://www.opengis.net/wms",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},defaultPrefix:"wms",initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +if(data&&data.nodeType==9){data=data.documentElement;} +var capabilities={};this.readNode(data,capabilities);this.postProcessLayers(capabilities);return capabilities;},postProcessLayers:function(capabilities){if(capabilities.capability){capabilities.capability.layers=[];var layers=capabilities.capability.nestedLayers;for(var i=0,len=layers.length;i<len;++i){var layer=layers[i];this.processLayer(capabilities.capability,layer);}}},processLayer:function(capability,layer,parentLayer){if(layer.formats===undefined){layer.formats=capability.request.getmap.formats;} +if(parentLayer){layer.styles=layer.styles.concat(parentLayer.styles);var attributes=["queryable","cascaded","fixedWidth","fixedHeight","opaque","noSubsets","llbbox","minScale","maxScale","attribution"];var complexAttr=["srs","bbox","dimensions","authorityURLs"];var key;for(var j=0;j<attributes.length;j++){key=attributes[j];if(key in parentLayer){if(layer[key]==null){layer[key]=parentLayer[key];} +if(layer[key]==null){var intAttr=["cascaded","fixedWidth","fixedHeight"];var boolAttr=["queryable","opaque","noSubsets"];if(OpenLayers.Util.indexOf(intAttr,key)!=-1){layer[key]=0;} +if(OpenLayers.Util.indexOf(boolAttr,key)!=-1){layer[key]=false;}}}} +for(var j=0;j<complexAttr.length;j++){key=complexAttr[j];layer[key]=OpenLayers.Util.extend(layer[key],parentLayer[key]);}} +for(var i=0,len=layer.nestedLayers.length;i<len;i++){var childLayer=layer.nestedLayers[i];this.processLayer(capability,childLayer,layer);} +if(layer.name){capability.layers.push(layer);}},readers:{"wms":{"Service":function(node,obj){obj.service={};this.readChildNodes(node,obj.service);},"Name":function(node,obj){obj.name=this.getChildValue(node);},"Title":function(node,obj){obj.title=this.getChildValue(node);},"Abstract":function(node,obj){obj["abstract"]=this.getChildValue(node);},"BoundingBox":function(node,obj){var bbox={};bbox.bbox=[parseFloat(node.getAttribute("minx")),parseFloat(node.getAttribute("miny")),parseFloat(node.getAttribute("maxx")),parseFloat(node.getAttribute("maxy"))];var res={x:parseFloat(node.getAttribute("resx")),y:parseFloat(node.getAttribute("resy"))};if(!(isNaN(res.x)&&isNaN(res.y))){bbox.res=res;} +return bbox;},"OnlineResource":function(node,obj){obj.href=this.getAttributeNS(node,this.namespaces.xlink,"href");},"ContactInformation":function(node,obj){obj.contactInformation={};this.readChildNodes(node,obj.contactInformation);},"ContactPersonPrimary":function(node,obj){obj.personPrimary={};this.readChildNodes(node,obj.personPrimary);},"ContactPerson":function(node,obj){obj.person=this.getChildValue(node);},"ContactOrganization":function(node,obj){obj.organization=this.getChildValue(node);},"ContactPosition":function(node,obj){obj.position=this.getChildValue(node);},"ContactAddress":function(node,obj){obj.contactAddress={};this.readChildNodes(node,obj.contactAddress);},"AddressType":function(node,obj){obj.type=this.getChildValue(node);},"Address":function(node,obj){obj.address=this.getChildValue(node);},"City":function(node,obj){obj.city=this.getChildValue(node);},"StateOrProvince":function(node,obj){obj.stateOrProvince=this.getChildValue(node);},"PostCode":function(node,obj){obj.postcode=this.getChildValue(node);},"Country":function(node,obj){obj.country=this.getChildValue(node);},"ContactVoiceTelephone":function(node,obj){obj.phone=this.getChildValue(node);},"ContactFacsimileTelephone":function(node,obj){obj.fax=this.getChildValue(node);},"ContactElectronicMailAddress":function(node,obj){obj.email=this.getChildValue(node);},"Fees":function(node,obj){var fees=this.getChildValue(node);if(fees&&fees.toLowerCase()!="none"){obj.fees=fees;}},"AccessConstraints":function(node,obj){var constraints=this.getChildValue(node);if(constraints&&constraints.toLowerCase()!="none"){obj.accessConstraints=constraints;}},"Capability":function(node,obj){obj.capability={nestedLayers:[]};this.readChildNodes(node,obj.capability);},"Request":function(node,obj){obj.request={};this.readChildNodes(node,obj.request);},"GetCapabilities":function(node,obj){obj.getcapabilities={formats:[]};this.readChildNodes(node,obj.getcapabilities);},"Format":function(node,obj){if(obj.formats instanceof Array){obj.formats.push(this.getChildValue(node));}else{obj.format=this.getChildValue(node);}},"DCPType":function(node,obj){this.readChildNodes(node,obj);},"HTTP":function(node,obj){this.readChildNodes(node,obj);},"Get":function(node,obj){this.readChildNodes(node,obj);},"Post":function(node,obj){this.readChildNodes(node,obj);},"GetMap":function(node,obj){obj.getmap={formats:[]};this.readChildNodes(node,obj.getmap);},"GetFeatureInfo":function(node,obj){obj.getfeatureinfo={formats:[]};this.readChildNodes(node,obj.getfeatureinfo);},"Exception":function(node,obj){obj.exception={formats:[]};this.readChildNodes(node,obj.exception);},"Layer":function(node,obj){var attrNode=node.getAttributeNode("queryable");var queryable=(attrNode&&attrNode.specified)?node.getAttribute("queryable"):null;attrNode=node.getAttributeNode("cascaded");var cascaded=(attrNode&&attrNode.specified)?node.getAttribute("cascaded"):null;attrNode=node.getAttributeNode("opaque");var opaque=(attrNode&&attrNode.specified)?node.getAttribute('opaque'):null;var noSubsets=node.getAttribute('noSubsets');var fixedWidth=node.getAttribute('fixedWidth');var fixedHeight=node.getAttribute('fixedHeight');var layer={nestedLayers:[],styles:[],srs:{},metadataURLs:[],bbox:{},dimensions:{},authorityURLs:{},identifiers:{},keywords:[],queryable:(queryable&&queryable!=="")?(queryable==="1"||queryable==="true"):null,cascaded:(cascaded!==null)?parseInt(cascaded):null,opaque:opaque?(opaque==="1"||opaque==="true"):null,noSubsets:(noSubsets!==null)?(noSubsets==="1"||noSubsets==="true"):null,fixedWidth:(fixedWidth!=null)?parseInt(fixedWidth):null,fixedHeight:(fixedHeight!=null)?parseInt(fixedHeight):null};obj.nestedLayers.push(layer);this.readChildNodes(node,layer);if(layer.name){var parts=layer.name.split(":");if(parts.length>0){layer.prefix=parts[0];}}},"Attribution":function(node,obj){obj.attribution={};this.readChildNodes(node,obj.attribution);},"LogoURL":function(node,obj){obj.logo={width:node.getAttribute("width"),height:node.getAttribute("height")};this.readChildNodes(node,obj.logo);},"Style":function(node,obj){var style={};obj.styles.push(style);this.readChildNodes(node,style);},"LegendURL":function(node,obj){var legend={width:node.getAttribute("width"),height:node.getAttribute("height")};obj.legend=legend;this.readChildNodes(node,legend);},"MetadataURL":function(node,obj){var metadataURL={type:node.getAttribute("type")};obj.metadataURLs.push(metadataURL);this.readChildNodes(node,metadataURL);},"DataURL":function(node,obj){obj.dataURL={};this.readChildNodes(node,obj.dataURL);},"FeatureListURL":function(node,obj){obj.featureListURL={};this.readChildNodes(node,obj.featureListURL);},"AuthorityURL":function(node,obj){var name=node.getAttribute("name");var authority={};this.readChildNodes(node,authority);obj.authorityURLs[name]=authority.href;},"Identifier":function(node,obj){var authority=node.getAttribute("authority");obj.identifiers[authority]=this.getChildValue(node);},"KeywordList":function(node,obj){this.readChildNodes(node,obj);},"SRS":function(node,obj){obj.srs[this.getChildValue(node)]=true;}}},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1"});OpenLayers.Format.WMSDescribeLayer.v1_1=OpenLayers.Class(OpenLayers.Format.WMSDescribeLayer,{initialize:function(options){OpenLayers.Format.WMSDescribeLayer.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +var root=data.documentElement;var children=root.childNodes;var describelayer=[];var childNode,nodeName;for(var i=0;i<children.length;++i){childNode=children[i];nodeName=childNode.nodeName;if(nodeName=='LayerDescription'){var layerName=childNode.getAttribute('name');var owsType='';var owsURL='';var typeName='';if(childNode.getAttribute('owsType')){owsType=childNode.getAttribute('owsType');owsURL=childNode.getAttribute('owsURL');}else{if(childNode.getAttribute('wfs')!=''){owsType='WFS';owsURL=childNode.getAttribute('wfs');}else if(childNode.getAttribute('wcs')!=''){owsType='WCS';owsURL=childNode.getAttribute('wcs');}} +var query=childNode.getElementsByTagName('Query');if(query.length>0){typeName=query[0].getAttribute('typeName');if(!typeName){typeName=query[0].getAttribute('typename');}} +describelayer.push({layerName:layerName,owsType:owsType,owsURL:owsURL,typeName:typeName});}} +return describelayer;},CLASS_NAME:"OpenLayers.Format.WMSDescribeLayer.v1_1"});OpenLayers.Handler.Box=OpenLayers.Class(OpenLayers.Handler,{dragHandler:null,boxDivClassName:'olHandlerBoxZoomBox',boxCharacteristics:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);var callbacks={"down":this.startBox,"move":this.moveBox,"out":this.removeBox,"up":this.endBox};this.dragHandler=new OpenLayers.Handler.Drag(this,callbacks,{keyMask:this.keyMask});},destroy:function(){if(this.dragHandler){this.dragHandler.destroy();this.dragHandler=null;} +OpenLayers.Handler.prototype.destroy.apply(this,arguments);},setMap:function(map){OpenLayers.Handler.prototype.setMap.apply(this,arguments);if(this.dragHandler){this.dragHandler.setMap(map);}},startBox:function(xy){this.zoomBox=OpenLayers.Util.createDiv('zoomBox',this.dragHandler.start);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(xy){var startX=this.dragHandler.start.x;var startY=this.dragHandler.start.y;var deltaX=Math.abs(startX-xy.x);var deltaY=Math.abs(startY-xy.y);this.zoomBox.style.width=Math.max(1,deltaX)+"px";this.zoomBox.style.height=Math.max(1,deltaY)+"px";this.zoomBox.style.left=xy.x<startX?xy.x+"px":startX+"px";this.zoomBox.style.top=xy.y<startY?xy.y+"px":startY+"px";var box=this.getBoxCharacteristics();if(box.newBoxModel){if(xy.x>startX){this.zoomBox.style.width=Math.max(1,deltaX-box.xOffset)+"px";} +if(xy.y>startY){this.zoomBox.style.height=Math.max(1,deltaY-box.yOffset)+"px";}}},endBox:function(end){var result;if(Math.abs(this.dragHandler.start.x-end.x)>5||Math.abs(this.dragHandler.start.y-end.y)>5){var start=this.dragHandler.start;var top=Math.min(start.y,end.y);var bottom=Math.max(start.y,end.y);var left=Math.min(start.x,end.x);var right=Math.max(start.x,end.x);result=new OpenLayers.Bounds(left,bottom,right,top);}else{result=this.dragHandler.start.clone();} +this.removeBox();this.callback("done",[result]);},removeBox:function(){this.map.viewPortDiv.removeChild(this.zoomBox);this.zoomBox=null;this.boxCharacteristics=null;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDrawBox");},activate:function(){if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.dragHandler.activate();return true;}else{return false;}},deactivate:function(){if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.dragHandler.deactivate();return true;}else{return false;}},getBoxCharacteristics:function(){if(!this.boxCharacteristics){var xOffset=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-left-width"))+parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-right-width"))+1;var yOffset=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-top-width"))+parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-bottom-width"))+1;var newBoxModel=OpenLayers.Util.getBrowserName()=="msie"?document.compatMode!="BackCompat":true;this.boxCharacteristics={xOffset:xOffset,yOffset:yOffset,newBoxModel:newBoxModel};} +return this.boxCharacteristics;},CLASS_NAME:"OpenLayers.Handler.Box"});OpenLayers.Handler.RegularPolygon=OpenLayers.Class(OpenLayers.Handler.Drag,{sides:4,radius:null,snapAngle:null,snapToggle:'shiftKey',layerOptions:null,persist:false,irregular:false,angle:null,fixedRadius:false,feature:null,layer:null,origin:null,initialize:function(control,callbacks,options){if(!(options&&options.layerOptions&&options.layerOptions.styleMap)){this.style=OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'],{});} +OpenLayers.Handler.prototype.initialize.apply(this,[control,callbacks,options]);this.options=(options)?options:{};},setOptions:function(newOptions){OpenLayers.Util.extend(this.options,newOptions);OpenLayers.Util.extend(this,newOptions);},activate:function(){var activated=false;if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){var options=OpenLayers.Util.extend({displayInLayerSwitcher:false,calculateInRange:OpenLayers.Function.True},this.layerOptions);this.layer=new OpenLayers.Layer.Vector(this.CLASS_NAME,options);this.map.addLayer(this.layer);activated=true;} +return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.Drag.prototype.deactivate.apply(this,arguments)){if(this.dragging){this.cancel();} +if(this.layer.map!=null){this.layer.destroy(false);if(this.feature){this.feature.destroy();}} +this.layer=null;this.feature=null;deactivated=true;} +return deactivated;},down:function(evt){this.fixedRadius=!!(this.radius);var maploc=this.map.getLonLatFromPixel(evt.xy);this.origin=new OpenLayers.Geometry.Point(maploc.lon,maploc.lat);if(!this.fixedRadius||this.irregular){this.radius=this.map.getResolution();} +if(this.persist){this.clear();} +this.feature=new OpenLayers.Feature.Vector();this.createGeometry();this.callback("create",[this.origin,this.feature]);this.layer.addFeatures([this.feature],{silent:true});this.layer.drawFeature(this.feature,this.style);},move:function(evt){var maploc=this.map.getLonLatFromPixel(evt.xy);var point=new OpenLayers.Geometry.Point(maploc.lon,maploc.lat);if(this.irregular){var ry=Math.sqrt(2)*Math.abs(point.y-this.origin.y)/2;this.radius=Math.max(this.map.getResolution()/2,ry);}else if(this.fixedRadius){this.origin=point;}else{this.calculateAngle(point,evt);this.radius=Math.max(this.map.getResolution()/2,point.distanceTo(this.origin));} +this.modifyGeometry();if(this.irregular){var dx=point.x-this.origin.x;var dy=point.y-this.origin.y;var ratio;if(dy==0){ratio=dx/(this.radius*Math.sqrt(2));}else{ratio=dx/dy;} +this.feature.geometry.resize(1,this.origin,ratio);this.feature.geometry.move(dx/2,dy/2);} +this.layer.drawFeature(this.feature,this.style);},up:function(evt){this.finalize();if(this.start==this.last){this.callback("done",[evt.xy]);}},out:function(evt){this.finalize();},createGeometry:function(){this.angle=Math.PI*((1/this.sides)-(1/2));if(this.snapAngle){this.angle+=this.snapAngle*(Math.PI/180);} +this.feature.geometry=OpenLayers.Geometry.Polygon.createRegularPolygon(this.origin,this.radius,this.sides,this.snapAngle);},modifyGeometry:function(){var angle,point;var ring=this.feature.geometry.components[0];if(ring.components.length!=(this.sides+1)){this.createGeometry();ring=this.feature.geometry.components[0];} +for(var i=0;i<this.sides;++i){point=ring.components[i];angle=this.angle+(i*2*Math.PI/this.sides);point.x=this.origin.x+(this.radius*Math.cos(angle));point.y=this.origin.y+(this.radius*Math.sin(angle));point.clearBounds();}},calculateAngle:function(point,evt){var alpha=Math.atan2(point.y-this.origin.y,point.x-this.origin.x);if(this.snapAngle&&(this.snapToggle&&!evt[this.snapToggle])){var snapAngleRad=(Math.PI/180)*this.snapAngle;this.angle=Math.round(alpha/snapAngleRad)*snapAngleRad;}else{this.angle=alpha;}},cancel:function(){this.callback("cancel",null);this.finalize();},finalize:function(){this.origin=null;this.radius=this.options.radius;},clear:function(){if(this.layer){this.layer.renderer.clear();this.layer.destroyFeatures();}},callback:function(name,args){if(this.callbacks[name]){this.callbacks[name].apply(this.control,[this.feature.geometry.clone()]);} +if(!this.persist&&(name=="done"||name=="cancel")){this.clear();}},CLASS_NAME:"OpenLayers.Handler.RegularPolygon"});OpenLayers.Layer.EventPane=OpenLayers.Class(OpenLayers.Layer,{smoothDragPan:true,isBaseLayer:true,isFixed:true,pane:null,mapObject:null,initialize:function(name,options){OpenLayers.Layer.prototype.initialize.apply(this,arguments);if(this.pane==null){this.pane=OpenLayers.Util.createDiv(this.div.id+"_EventPane");}},destroy:function(){this.mapObject=null;this.pane=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments);},setMap:function(map){OpenLayers.Layer.prototype.setMap.apply(this,arguments);this.pane.style.zIndex=parseInt(this.div.style.zIndex)+1;this.pane.style.display=this.div.style.display;this.pane.style.width="100%";this.pane.style.height="100%";if(OpenLayers.Util.getBrowserName()=="msie"){this.pane.style.background="url("+OpenLayers.Util.getImagesLocation()+"blank.gif)";} +if(this.isFixed){this.map.viewPortDiv.appendChild(this.pane);}else{this.map.layerContainerDiv.appendChild(this.pane);} +this.loadMapObject();if(this.mapObject==null){this.loadWarningMessage();}},removeMap:function(map){if(this.pane&&this.pane.parentNode){this.pane.parentNode.removeChild(this.pane);} +OpenLayers.Layer.prototype.removeMap.apply(this,arguments);},loadWarningMessage:function(){this.div.style.backgroundColor="darkblue";var viewSize=this.map.getSize();var msgW=Math.min(viewSize.w,300);var msgH=Math.min(viewSize.h,200);var size=new OpenLayers.Size(msgW,msgH);var centerPx=new OpenLayers.Pixel(viewSize.w/2,viewSize.h/2);var topLeft=centerPx.add(-size.w/2,-size.h/2);var div=OpenLayers.Util.createDiv(this.name+"_warning",topLeft,size,null,null,null,"auto");div.style.padding="7px";div.style.backgroundColor="yellow";div.innerHTML=this.getWarningHTML();this.div.appendChild(div);},getWarningHTML:function(){return"";},display:function(display){OpenLayers.Layer.prototype.display.apply(this,arguments);this.pane.style.display=this.div.style.display;},setZIndex:function(zIndex){OpenLayers.Layer.prototype.setZIndex.apply(this,arguments);this.pane.style.zIndex=parseInt(this.div.style.zIndex)+1;},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.prototype.moveTo.apply(this,arguments);if(this.mapObject!=null){var newCenter=this.map.getCenter();var newZoom=this.map.getZoom();if(newCenter!=null){var moOldCenter=this.getMapObjectCenter();var oldCenter=this.getOLLonLatFromMapObjectLonLat(moOldCenter);var moOldZoom=this.getMapObjectZoom();var oldZoom=this.getOLZoomFromMapObjectZoom(moOldZoom);if(!(newCenter.equals(oldCenter))||!(newZoom==oldZoom)){if(dragging&&this.dragPanMapObject&&this.smoothDragPan){var oldPx=this.map.getViewPortPxFromLonLat(oldCenter);var newPx=this.map.getViewPortPxFromLonLat(newCenter);this.dragPanMapObject(newPx.x-oldPx.x,oldPx.y-newPx.y);}else{var center=this.getMapObjectLonLatFromOLLonLat(newCenter);var zoom=this.getMapObjectZoomFromOLZoom(newZoom);this.setMapObjectCenter(center,zoom,dragging);}}}}},getLonLatFromViewPortPx:function(viewPortPx){var lonlat=null;if((this.mapObject!=null)&&(this.getMapObjectCenter()!=null)){var moPixel=this.getMapObjectPixelFromOLPixel(viewPortPx);var moLonLat=this.getMapObjectLonLatFromMapObjectPixel(moPixel);lonlat=this.getOLLonLatFromMapObjectLonLat(moLonLat);} +return lonlat;},getViewPortPxFromLonLat:function(lonlat){var viewPortPx=null;if((this.mapObject!=null)&&(this.getMapObjectCenter()!=null)){var moLonLat=this.getMapObjectLonLatFromOLLonLat(lonlat);var moPixel=this.getMapObjectPixelFromMapObjectLonLat(moLonLat);viewPortPx=this.getOLPixelFromMapObjectPixel(moPixel);} +return viewPortPx;},getOLLonLatFromMapObjectLonLat:function(moLonLat){var olLonLat=null;if(moLonLat!=null){var lon=this.getLongitudeFromMapObjectLonLat(moLonLat);var lat=this.getLatitudeFromMapObjectLonLat(moLonLat);olLonLat=new OpenLayers.LonLat(lon,lat);} +return olLonLat;},getMapObjectLonLatFromOLLonLat:function(olLonLat){var moLatLng=null;if(olLonLat!=null){moLatLng=this.getMapObjectLonLatFromLonLat(olLonLat.lon,olLonLat.lat);} +return moLatLng;},getOLPixelFromMapObjectPixel:function(moPixel){var olPixel=null;if(moPixel!=null){var x=this.getXFromMapObjectPixel(moPixel);var y=this.getYFromMapObjectPixel(moPixel);olPixel=new OpenLayers.Pixel(x,y);} +return olPixel;},getMapObjectPixelFromOLPixel:function(olPixel){var moPixel=null;if(olPixel!=null){moPixel=this.getMapObjectPixelFromXY(olPixel.x,olPixel.y);} +return moPixel;},CLASS_NAME:"OpenLayers.Layer.EventPane"});OpenLayers.Layer.FixedZoomLevels=OpenLayers.Class({initialize:function(){},initResolutions:function(){var props=new Array('minZoomLevel','maxZoomLevel','numZoomLevels');for(var i=0,len=props.length;i<len;i++){var property=props[i];this[property]=(this.options[property]!=null)?this.options[property]:this.map[property];} +if((this.minZoomLevel==null)||(this.minZoomLevel<this.MIN_ZOOM_LEVEL)){this.minZoomLevel=this.MIN_ZOOM_LEVEL;} +var desiredZoomLevels;var limitZoomLevels=this.MAX_ZOOM_LEVEL-this.minZoomLevel+1;if(((this.options.numZoomLevels==null)&&(this.options.maxZoomLevel!=null))||((this.numZoomLevels==null)&&(this.maxZoomLevel!=null))){desiredZoomLevels=this.maxZoomLevel-this.minZoomLevel+1;}else{desiredZoomLevels=this.numZoomLevels;} +if(desiredZoomLevels!=null){this.numZoomLevels=Math.min(desiredZoomLevels,limitZoomLevels);}else{this.numZoomLevels=limitZoomLevels;} +this.maxZoomLevel=this.minZoomLevel+this.numZoomLevels-1;if(this.RESOLUTIONS!=null){var resolutionsIndex=0;this.resolutions=[];for(var i=this.minZoomLevel;i<=this.maxZoomLevel;i++){this.resolutions[resolutionsIndex++]=this.RESOLUTIONS[i];} +this.maxResolution=this.resolutions[0];this.minResolution=this.resolutions[this.resolutions.length-1];}},getResolution:function(){if(this.resolutions!=null){return OpenLayers.Layer.prototype.getResolution.apply(this,arguments);}else{var resolution=null;var viewSize=this.map.getSize();var extent=this.getExtent();if((viewSize!=null)&&(extent!=null)){resolution=Math.max(extent.getWidth()/viewSize.w,extent.getHeight()/viewSize.h);} +return resolution;}},getExtent:function(){var extent=null;var size=this.map.getSize();var tlPx=new OpenLayers.Pixel(0,0);var tlLL=this.getLonLatFromViewPortPx(tlPx);var brPx=new OpenLayers.Pixel(size.w,size.h);var brLL=this.getLonLatFromViewPortPx(brPx);if((tlLL!=null)&&(brLL!=null)){extent=new OpenLayers.Bounds(tlLL.lon,brLL.lat,brLL.lon,tlLL.lat);} +return extent;},getZoomForResolution:function(resolution){if(this.resolutions!=null){return OpenLayers.Layer.prototype.getZoomForResolution.apply(this,arguments);}else{var extent=OpenLayers.Layer.prototype.getExtent.apply(this,[]);return this.getZoomForExtent(extent);}},getOLZoomFromMapObjectZoom:function(moZoom){var zoom=null;if(moZoom!=null){zoom=moZoom-this.minZoomLevel;} +return zoom;},getMapObjectZoomFromOLZoom:function(olZoom){var zoom=null;if(olZoom!=null){zoom=olZoom+this.minZoomLevel;} +return zoom;},CLASS_NAME:"OpenLayers.Layer.FixedZoomLevels"});OpenLayers.Layer.HTTPRequest=OpenLayers.Class(OpenLayers.Layer,{URL_HASH_FACTOR:(Math.sqrt(5)-1)/2,url:null,params:null,reproject:false,initialize:function(name,url,params,options){var newArguments=arguments;newArguments=[name,options];OpenLayers.Layer.prototype.initialize.apply(this,newArguments);this.url=url;this.params=OpenLayers.Util.extend({},params);},destroy:function(){this.url=null;this.params=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.HTTPRequest(this.name,this.url,this.params,this.getOptions());} +obj=OpenLayers.Layer.prototype.clone.apply(this,[obj]);return obj;},setUrl:function(newUrl){this.url=newUrl;},mergeNewParams:function(newParams){this.params=OpenLayers.Util.extend(this.params,newParams);var ret=this.redraw();if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"params"});} +return ret;},redraw:function(force){if(force){return this.mergeNewParams({"_olSalt":Math.random()});}else{return OpenLayers.Layer.prototype.redraw.apply(this,[]);}},selectUrl:function(paramString,urls){var product=1;for(var i=0,len=paramString.length;i<len;i++){product*=paramString.charCodeAt(i)*this.URL_HASH_FACTOR;product-=Math.floor(product);} +return urls[Math.floor(product*urls.length)];},getFullRequestString:function(newParams,altUrl){var url=altUrl||this.url;var allParams=OpenLayers.Util.extend({},this.params);allParams=OpenLayers.Util.extend(allParams,newParams);var paramsString=OpenLayers.Util.getParameterString(allParams);if(url instanceof Array){url=this.selectUrl(paramsString,url);} +var urlParams=OpenLayers.Util.upperCaseObject(OpenLayers.Util.getParameters(url));for(var key in allParams){if(key.toUpperCase()in urlParams){delete allParams[key];}} +paramsString=OpenLayers.Util.getParameterString(allParams);return OpenLayers.Util.urlAppend(url,paramsString);},CLASS_NAME:"OpenLayers.Layer.HTTPRequest"});OpenLayers.Layer.Image=OpenLayers.Class(OpenLayers.Layer,{isBaseLayer:true,url:null,extent:null,size:null,tile:null,aspectRatio:null,initialize:function(name,url,extent,size,options){this.url=url;this.extent=extent;this.maxExtent=extent;this.size=size;OpenLayers.Layer.prototype.initialize.apply(this,[name,options]);this.aspectRatio=(this.extent.getHeight()/this.size.h)/(this.extent.getWidth()/this.size.w);},destroy:function(){if(this.tile){this.removeTileMonitoringHooks(this.tile);this.tile.destroy();this.tile=null;} +OpenLayers.Layer.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.Image(this.name,this.url,this.extent,this.size,this.getOptions());} +obj=OpenLayers.Layer.prototype.clone.apply(this,[obj]);return obj;},setMap:function(map){if(this.options.maxResolution==null){this.options.maxResolution=this.aspectRatio*this.extent.getWidth()/this.size.w;} +OpenLayers.Layer.prototype.setMap.apply(this,arguments);},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.prototype.moveTo.apply(this,arguments);var firstRendering=(this.tile==null);if(zoomChanged||firstRendering){this.setTileSize();var ul=new OpenLayers.LonLat(this.extent.left,this.extent.top);var ulPx=this.map.getLayerPxFromLonLat(ul);if(firstRendering){this.tile=new OpenLayers.Tile.Image(this,ulPx,this.extent,null,this.tileSize);this.addTileMonitoringHooks(this.tile);}else{this.tile.size=this.tileSize.clone();this.tile.position=ulPx.clone();} +this.tile.draw();}},setTileSize:function(){var tileWidth=this.extent.getWidth()/this.map.getResolution();var tileHeight=this.extent.getHeight()/this.map.getResolution();this.tileSize=new OpenLayers.Size(tileWidth,tileHeight);},addTileMonitoringHooks:function(tile){tile.onLoadStart=function(){this.events.triggerEvent("loadstart");};tile.events.register("loadstart",this,tile.onLoadStart);tile.onLoadEnd=function(){this.events.triggerEvent("loadend");};tile.events.register("loadend",this,tile.onLoadEnd);tile.events.register("unload",this,tile.onLoadEnd);},removeTileMonitoringHooks:function(tile){tile.unload();tile.events.un({"loadstart":tile.onLoadStart,"loadend":tile.onLoadEnd,"unload":tile.onLoadEnd,scope:this});},setUrl:function(newUrl){this.url=newUrl;this.tile.draw();},getURL:function(bounds){return this.url;},CLASS_NAME:"OpenLayers.Layer.Image"});OpenLayers.Layer.Markers=OpenLayers.Class(OpenLayers.Layer,{isBaseLayer:false,markers:null,drawn:false,initialize:function(name,options){OpenLayers.Layer.prototype.initialize.apply(this,arguments);this.markers=[];},destroy:function(){this.clearMarkers();this.markers=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments);},setOpacity:function(opacity){if(opacity!=this.opacity){this.opacity=opacity;for(var i=0,len=this.markers.length;i<len;i++){this.markers[i].setOpacity(this.opacity);}}},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.prototype.moveTo.apply(this,arguments);if(zoomChanged||!this.drawn){for(var i=0,len=this.markers.length;i<len;i++){this.drawMarker(this.markers[i]);} +this.drawn=true;}},addMarker:function(marker){this.markers.push(marker);if(this.opacity!=null){marker.setOpacity(this.opacity);} +if(this.map&&this.map.getExtent()){marker.map=this.map;this.drawMarker(marker);}},removeMarker:function(marker){if(this.markers&&this.markers.length){OpenLayers.Util.removeItem(this.markers,marker);marker.erase();}},clearMarkers:function(){if(this.markers!=null){while(this.markers.length>0){this.removeMarker(this.markers[0]);}}},drawMarker:function(marker){var px=this.map.getLayerPxFromLonLat(marker.lonlat);if(px==null){marker.display(false);}else{if(!marker.isDrawn()){var markerImg=marker.draw(px);this.div.appendChild(markerImg);}else if(marker.icon){marker.icon.moveTo(px);}}},getDataExtent:function(){var maxExtent=null;if(this.markers&&(this.markers.length>0)){var maxExtent=new OpenLayers.Bounds();for(var i=0,len=this.markers.length;i<len;i++){var marker=this.markers[i];maxExtent.extend(marker.lonlat);}} +return maxExtent;},CLASS_NAME:"OpenLayers.Layer.Markers"});OpenLayers.Layer.SphericalMercator={getExtent:function(){var extent=null;if(this.sphericalMercator){extent=this.map.calculateBounds();}else{extent=OpenLayers.Layer.FixedZoomLevels.prototype.getExtent.apply(this);} +return extent;},getLonLatFromViewPortPx:function(viewPortPx){return OpenLayers.Layer.prototype.getLonLatFromViewPortPx.apply(this,arguments);},getViewPortPxFromLonLat:function(lonlat){return OpenLayers.Layer.prototype.getViewPortPxFromLonLat.apply(this,arguments);},initMercatorParameters:function(){this.RESOLUTIONS=[];var maxResolution=156543.0339;for(var zoom=0;zoom<=this.MAX_ZOOM_LEVEL;++zoom){this.RESOLUTIONS[zoom]=maxResolution/Math.pow(2,zoom);} +this.units="m";this.projection=this.projection||"EPSG:900913";},forwardMercator:function(lon,lat){var x=lon*20037508.34/180;var y=Math.log(Math.tan((90+lat)*Math.PI/360))/(Math.PI/180);y=y*20037508.34/180;return new OpenLayers.LonLat(x,y);},inverseMercator:function(x,y){var lon=(x/20037508.34)*180;var lat=(y/20037508.34)*180;lat=180/Math.PI*(2*Math.atan(Math.exp(lat*Math.PI/180))-Math.PI/2);return new OpenLayers.LonLat(lon,lat);},projectForward:function(point){var lonlat=OpenLayers.Layer.SphericalMercator.forwardMercator(point.x,point.y);point.x=lonlat.lon;point.y=lonlat.lat;return point;},projectInverse:function(point){var lonlat=OpenLayers.Layer.SphericalMercator.inverseMercator(point.x,point.y);point.x=lonlat.lon;point.y=lonlat.lat;return point;}};OpenLayers.Projection.addTransform("EPSG:4326","EPSG:900913",OpenLayers.Layer.SphericalMercator.projectForward);OpenLayers.Projection.addTransform("EPSG:900913","EPSG:4326",OpenLayers.Layer.SphericalMercator.projectInverse);OpenLayers.Tile.WFS=OpenLayers.Class(OpenLayers.Tile,{features:null,url:null,request:null,initialize:function(layer,position,bounds,url,size){OpenLayers.Tile.prototype.initialize.apply(this,arguments);this.url=url;this.features=[];},destroy:function(){OpenLayers.Tile.prototype.destroy.apply(this,arguments);this.destroyAllFeatures();this.features=null;this.url=null;if(this.request){this.request.abort();this.request=null;}},clear:function(){this.destroyAllFeatures();},draw:function(){if(OpenLayers.Tile.prototype.draw.apply(this,arguments)){if(this.isLoading){this.events.triggerEvent("reload");}else{this.isLoading=true;this.events.triggerEvent("loadstart");} +this.loadFeaturesForRegion(this.requestSuccess);}},loadFeaturesForRegion:function(success,failure){if(this.request){this.request.abort();} +this.request=OpenLayers.Request.GET({url:this.url,success:success,failure:failure,scope:this});},requestSuccess:function(request){if(this.features){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;} +if(this.layer.vectorMode){this.layer.addFeatures(this.layer.formatObject.read(doc));}else{var xml=new OpenLayers.Format.XML();if(typeof doc=="string"){doc=xml.read(doc);} +var resultFeatures=xml.getElementsByTagNameNS(doc,"http://www.opengis.net/gml","featureMember");this.addResults(resultFeatures);}} +if(this.events){this.events.triggerEvent("loadend");} +this.request=null;},addResults:function(results){for(var i=0;i<results.length;i++){var feature=new this.layer.featureClass(this.layer,results[i]);this.features.push(feature);}},destroyAllFeatures:function(){while(this.features.length>0){var feature=this.features.shift();feature.destroy();}},CLASS_NAME:"OpenLayers.Tile.WFS"});OpenLayers.Control.DrawFeature=OpenLayers.Class(OpenLayers.Control,{layer:null,callbacks:null,EVENT_TYPES:["featureadded"],multi:false,featureAdded:function(){},handlerOptions:null,initialize:function(layer,handler,options){this.EVENT_TYPES=OpenLayers.Control.DrawFeature.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.callbacks=OpenLayers.Util.extend({done:this.drawFeature,modify:function(vertex,feature){this.layer.events.triggerEvent("sketchmodified",{vertex:vertex,feature:feature});},create:function(vertex,feature){this.layer.events.triggerEvent("sketchstarted",{vertex:vertex,feature:feature});}},this.callbacks);this.layer=layer;this.handlerOptions=this.handlerOptions||{};if(!("multi"in this.handlerOptions)){this.handlerOptions.multi=this.multi;} +var sketchStyle=this.layer.styleMap&&this.layer.styleMap.styles.temporary;if(sketchStyle){this.handlerOptions.layerOptions=OpenLayers.Util.applyDefaults(this.handlerOptions.layerOptions,{styleMap:new OpenLayers.StyleMap({"default":sketchStyle})});} +this.handler=new handler(this,this.callbacks,this.handlerOptions);},drawFeature:function(geometry){var feature=new OpenLayers.Feature.Vector(geometry);var proceed=this.layer.events.triggerEvent("sketchcomplete",{feature:feature});if(proceed!==false){feature.state=OpenLayers.State.INSERT;this.layer.addFeatures([feature]);this.featureAdded(feature);this.events.triggerEvent("featureadded",{feature:feature});}},CLASS_NAME:"OpenLayers.Control.DrawFeature"});OpenLayers.Control.Measure=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:['measure','measurepartial'],handlerOptions:null,callbacks:null,displaySystem:'metric',geodesic:false,displaySystemUnits:{geographic:['dd'],english:['mi','ft','in'],metric:['km','m']},partialDelay:300,delayedTrigger:null,persist:false,initialize:function(handler,options){this.EVENT_TYPES=OpenLayers.Control.Measure.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.callbacks=OpenLayers.Util.extend({done:this.measureComplete,point:this.measurePartial},this.callbacks);this.handlerOptions=OpenLayers.Util.extend({persist:this.persist},this.handlerOptions);this.handler=new handler(this,this.callbacks,this.handlerOptions);},cancel:function(){this.handler.cancel();},updateHandler:function(handler,options){var active=this.active;if(active){this.deactivate();} +this.handler=new handler(this,this.callbacks,options);if(active){this.activate();}},measureComplete:function(geometry){if(this.delayedTrigger){window.clearTimeout(this.delayedTrigger);} +this.measure(geometry,"measure");},measurePartial:function(point,geometry){if(geometry.getLength()>0){geometry=geometry.clone();this.delayedTrigger=window.setTimeout(OpenLayers.Function.bind(function(){this.measure(geometry,"measurepartial");},this),this.partialDelay);}},measure:function(geometry,eventType){var stat,order;if(geometry.CLASS_NAME.indexOf('LineString')>-1){stat=this.getBestLength(geometry);order=1;}else{stat=this.getBestArea(geometry);order=2;} +this.events.triggerEvent(eventType,{measure:stat[0],units:stat[1],order:order,geometry:geometry});},getBestArea:function(geometry){var units=this.displaySystemUnits[this.displaySystem];var unit,area;for(var i=0,len=units.length;i<len;++i){unit=units[i];area=this.getArea(geometry,unit);if(area>1){break;}} +return[area,unit];},getArea:function(geometry,units){var area,geomUnits;if(this.geodesic){area=geometry.getGeodesicArea(this.map.getProjectionObject());geomUnits="m";}else{area=geometry.getArea();geomUnits=this.map.getUnits();} +var inPerDisplayUnit=OpenLayers.INCHES_PER_UNIT[units];if(inPerDisplayUnit){var inPerMapUnit=OpenLayers.INCHES_PER_UNIT[geomUnits];area*=Math.pow((inPerMapUnit/inPerDisplayUnit),2);} +return area;},getBestLength:function(geometry){var units=this.displaySystemUnits[this.displaySystem];var unit,length;for(var i=0,len=units.length;i<len;++i){unit=units[i];length=this.getLength(geometry,unit);if(length>1){break;}} +return[length,unit];},getLength:function(geometry,units){var length,geomUnits;if(this.geodesic){length=geometry.getGeodesicLength(this.map.getProjectionObject());geomUnits="m";}else{length=geometry.getLength();geomUnits=this.map.getUnits();} +var inPerDisplayUnit=OpenLayers.INCHES_PER_UNIT[units];if(inPerDisplayUnit){var inPerMapUnit=OpenLayers.INCHES_PER_UNIT[geomUnits];length*=(inPerMapUnit/inPerDisplayUnit);} +return length;},CLASS_NAME:"OpenLayers.Control.Measure"});OpenLayers.Control.ZoomBox=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,out:false,alwaysZoom:false,draw:function(){this.handler=new OpenLayers.Handler.Box(this,{done:this.zoomBox},{keyMask:this.keyMask});},zoomBox:function(position){if(position instanceof OpenLayers.Bounds){var bounds;if(!this.out){var minXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.left,position.bottom));var maxXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.right,position.top));bounds=new OpenLayers.Bounds(minXY.lon,minXY.lat,maxXY.lon,maxXY.lat);}else{var pixWidth=Math.abs(position.right-position.left);var pixHeight=Math.abs(position.top-position.bottom);var zoomFactor=Math.min((this.map.size.h/pixHeight),(this.map.size.w/pixWidth));var extent=this.map.getExtent();var center=this.map.getLonLatFromPixel(position.getCenterPixel());var xmin=center.lon-(extent.getWidth()/2)*zoomFactor;var xmax=center.lon+(extent.getWidth()/2)*zoomFactor;var ymin=center.lat-(extent.getHeight()/2)*zoomFactor;var ymax=center.lat+(extent.getHeight()/2)*zoomFactor;bounds=new OpenLayers.Bounds(xmin,ymin,xmax,ymax);} +var lastZoom=this.map.getZoom();this.map.zoomToExtent(bounds);if(lastZoom==this.map.getZoom()&&this.alwaysZoom==true){this.map.zoomTo(lastZoom+(this.out?-1:1));}}else{if(!this.out){this.map.setCenter(this.map.getLonLatFromPixel(position),this.map.getZoom()+1);}else{this.map.setCenter(this.map.getLonLatFromPixel(position),this.map.getZoom()-1);}}},CLASS_NAME:"OpenLayers.Control.ZoomBox"});OpenLayers.Format.WFSCapabilities.v1_0_0=OpenLayers.Class(OpenLayers.Format.WFSCapabilities.v1,{initialize:function(options){OpenLayers.Format.WFSCapabilities.v1.prototype.initialize.apply(this,[options]);},read_cap_Service:function(capabilities,node){var service={};this.runChildNodes(service,node);capabilities.service=service;},read_cap_Fees:function(service,node){var fees=this.getChildValue(node);if(fees&&fees.toLowerCase()!="none"){service.fees=fees;}},read_cap_AccessConstraints:function(service,node){var constraints=this.getChildValue(node);if(constraints&&constraints.toLowerCase()!="none"){service.accessConstraints=constraints;}},read_cap_OnlineResource:function(service,node){var onlineResource=this.getChildValue(node);if(onlineResource&&onlineResource.toLowerCase()!="none"){service.onlineResource=onlineResource;}},read_cap_Keywords:function(service,node){var keywords=this.getChildValue(node);if(keywords&&keywords.toLowerCase()!="none"){service.keywords=keywords.split(', ');}},read_cap_Capability:function(capabilities,node){var capability={};this.runChildNodes(capability,node);capabilities.capability=capability;},read_cap_Request:function(obj,node){var request={};this.runChildNodes(request,node);obj.request=request;},read_cap_GetFeature:function(request,node){var getfeature={href:{},formats:[]};this.runChildNodes(getfeature,node);request.getfeature=getfeature;},read_cap_ResultFormat:function(obj,node){var children=node.childNodes;var childNode;for(var i=0;i<children.length;i++){childNode=children[i];if(childNode.nodeType==1){obj.formats.push(childNode.nodeName);}}},read_cap_DCPType:function(obj,node){this.runChildNodes(obj,node);},read_cap_HTTP:function(obj,node){this.runChildNodes(obj.href,node);},read_cap_Get:function(obj,node){obj.get=node.getAttribute("onlineResource");},read_cap_Post:function(obj,node){obj.post=node.getAttribute("onlineResource");},CLASS_NAME:"OpenLayers.Format.WFSCapabilities.v1_0_0"});OpenLayers.Format.WFSCapabilities.v1_1_0=OpenLayers.Class(OpenLayers.Format.WFSCapabilities.v1,{initialize:function(options){OpenLayers.Format.WFSCapabilities.v1.prototype.initialize.apply(this,[options]);},CLASS_NAME:"OpenLayers.Format.WFSCapabilities.v1_1_0"});OpenLayers.Format.WKT=OpenLayers.Class(OpenLayers.Format,{initialize:function(options){this.regExes={'typeStr':/^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/,'spaces':/\s+/,'parenComma':/\)\s*,\s*\(/,'doubleParenComma':/\)\s*\)\s*,\s*\(\s*\(/,'trimParens':/^\s*\(?(.*?)\)?\s*$/};OpenLayers.Format.prototype.initialize.apply(this,[options]);},read:function(wkt){var features,type,str;var matches=this.regExes.typeStr.exec(wkt);if(matches){type=matches[1].toLowerCase();str=matches[2];if(this.parse[type]){features=this.parse[type].apply(this,[str]);} +if(this.internalProjection&&this.externalProjection){if(features&&features.CLASS_NAME=="OpenLayers.Feature.Vector"){features.geometry.transform(this.externalProjection,this.internalProjection);}else if(features&&type!="geometrycollection"&&typeof features=="object"){for(var i=0,len=features.length;i<len;i++){var component=features[i];component.geometry.transform(this.externalProjection,this.internalProjection);}}}} +return features;},write:function(features){var collection,geometry,type,data,isCollection;if(features.constructor==Array){collection=features;isCollection=true;}else{collection=[features];isCollection=false;} +var pieces=[];if(isCollection){pieces.push('GEOMETRYCOLLECTION(');} +for(var i=0,len=collection.length;i<len;++i){if(isCollection&&i>0){pieces.push(',');} +geometry=collection[i].geometry;type=geometry.CLASS_NAME.split('.')[2].toLowerCase();if(!this.extract[type]){return null;} +if(this.internalProjection&&this.externalProjection){geometry=geometry.clone();geometry.transform(this.internalProjection,this.externalProjection);} +data=this.extract[type].apply(this,[geometry]);pieces.push(type.toUpperCase()+'('+data+')');} +if(isCollection){pieces.push(')');} +return pieces.join('');},extract:{'point':function(point){return point.x+' '+point.y;},'multipoint':function(multipoint){var array=[];for(var i=0,len=multipoint.components.length;i<len;++i){array.push('('+ +this.extract.point.apply(this,[multipoint.components[i]])+')');} +return array.join(',');},'linestring':function(linestring){var array=[];for(var i=0,len=linestring.components.length;i<len;++i){array.push(this.extract.point.apply(this,[linestring.components[i]]));} +return array.join(',');},'multilinestring':function(multilinestring){var array=[];for(var i=0,len=multilinestring.components.length;i<len;++i){array.push('('+ +this.extract.linestring.apply(this,[multilinestring.components[i]])+')');} +return array.join(',');},'polygon':function(polygon){var array=[];for(var i=0,len=polygon.components.length;i<len;++i){array.push('('+ +this.extract.linestring.apply(this,[polygon.components[i]])+')');} +return array.join(',');},'multipolygon':function(multipolygon){var array=[];for(var i=0,len=multipolygon.components.length;i<len;++i){array.push('('+ +this.extract.polygon.apply(this,[multipolygon.components[i]])+')');} +return array.join(',');}},parse:{'point':function(str){var coords=OpenLayers.String.trim(str).split(this.regExes.spaces);return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(coords[0],coords[1]));},'multipoint':function(str){var point;var points=OpenLayers.String.trim(str).split(this.regExes.parenComma);var components=[];for(var i=0,len=points.length;i<len;++i){point=points[i].replace(this.regExes.trimParens,'$1');components.push(this.parse.point.apply(this,[point]).geometry);} +return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.MultiPoint(components));},'linestring':function(str){var points=OpenLayers.String.trim(str).split(',');var components=[];for(var i=0,len=points.length;i<len;++i){components.push(this.parse.point.apply(this,[points[i]]).geometry);} +return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(components));},'multilinestring':function(str){var line;var lines=OpenLayers.String.trim(str).split(this.regExes.parenComma);var components=[];for(var i=0,len=lines.length;i<len;++i){line=lines[i].replace(this.regExes.trimParens,'$1');components.push(this.parse.linestring.apply(this,[line]).geometry);} +return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.MultiLineString(components));},'polygon':function(str){var ring,linestring,linearring;var rings=OpenLayers.String.trim(str).split(this.regExes.parenComma);var components=[];for(var i=0,len=rings.length;i<len;++i){ring=rings[i].replace(this.regExes.trimParens,'$1');linestring=this.parse.linestring.apply(this,[ring]).geometry;linearring=new OpenLayers.Geometry.LinearRing(linestring.components);components.push(linearring);} +return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Polygon(components));},'multipolygon':function(str){var polygon;var polygons=OpenLayers.String.trim(str).split(this.regExes.doubleParenComma);var components=[];for(var i=0,len=polygons.length;i<len;++i){polygon=polygons[i].replace(this.regExes.trimParens,'$1');components.push(this.parse.polygon.apply(this,[polygon]).geometry);} +return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.MultiPolygon(components));},'geometrycollection':function(str){str=str.replace(/,\s*([A-Za-z])/g,'|$1');var wktArray=OpenLayers.String.trim(str).split('|');var components=[];for(var i=0,len=wktArray.length;i<len;++i){components.push(OpenLayers.Format.WKT.prototype.read.apply(this,[wktArray[i]]));} +return components;}},CLASS_NAME:"OpenLayers.Format.WKT"});OpenLayers.Format.WMC.v1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{ol:"http://openlayers.org/context",wmc:"http://www.opengis.net/context",sld:"http://www.opengis.net/sld",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},schemaLocation:"",getNamespacePrefix:function(uri){var prefix=null;if(uri==null){prefix=this.namespaces[this.defaultPrefix];}else{for(prefix in this.namespaces){if(this.namespaces[prefix]==uri){break;}}} +return prefix;},defaultPrefix:"wmc",rootPrefix:null,defaultStyleName:"",defaultStyleTitle:"Default",initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +var root=data.documentElement;this.rootPrefix=root.prefix;var context={version:root.getAttribute("version")};this.runChildNodes(context,root);return context;},runChildNodes:function(obj,node){var children=node.childNodes;var childNode,processor,prefix,local;for(var i=0,len=children.length;i<len;++i){childNode=children[i];if(childNode.nodeType==1){prefix=this.getNamespacePrefix(childNode.namespaceURI);local=childNode.nodeName.split(":").pop();processor=this["read_"+prefix+"_"+local];if(processor){processor.apply(this,[obj,childNode]);}}}},read_wmc_General:function(context,node){this.runChildNodes(context,node);},read_wmc_BoundingBox:function(context,node){context.projection=node.getAttribute("SRS");context.bounds=new OpenLayers.Bounds(parseFloat(node.getAttribute("minx")),parseFloat(node.getAttribute("miny")),parseFloat(node.getAttribute("maxx")),parseFloat(node.getAttribute("maxy")));},read_wmc_LayerList:function(context,node){context.layersContext=[];this.runChildNodes(context,node);},read_wmc_Layer:function(context,node){var layerContext={visibility:(node.getAttribute("hidden")!="1"),queryable:(node.getAttribute("queryable")=="1"),formats:[],styles:[]};this.runChildNodes(layerContext,node);context.layersContext.push(layerContext);},read_wmc_Extension:function(obj,node){this.runChildNodes(obj,node);},read_ol_units:function(layerContext,node){layerContext.units=this.getChildValue(node);},read_ol_maxExtent:function(obj,node){var bounds=new OpenLayers.Bounds(node.getAttribute("minx"),node.getAttribute("miny"),node.getAttribute("maxx"),node.getAttribute("maxy"));obj.maxExtent=bounds;},read_ol_transparent:function(layerContext,node){layerContext.transparent=this.getChildValue(node);},read_ol_numZoomLevels:function(layerContext,node){layerContext.numZoomLevels=parseInt(this.getChildValue(node));},read_ol_opacity:function(layerContext,node){layerContext.opacity=parseFloat(this.getChildValue(node));},read_ol_singleTile:function(layerContext,node){layerContext.singleTile=(this.getChildValue(node)=="true");},read_ol_tileSize:function(layerContext,node){var obj={"width":node.getAttribute("width"),"height":node.getAttribute("height")};layerContext.tileSize=obj;},read_ol_isBaseLayer:function(layerContext,node){layerContext.isBaseLayer=(this.getChildValue(node)=="true");},read_ol_displayInLayerSwitcher:function(layerContext,node){layerContext.displayInLayerSwitcher=(this.getChildValue(node)=="true");},read_wmc_Server:function(layerContext,node){layerContext.version=node.getAttribute("version");var server={};var links=node.getElementsByTagName("OnlineResource");if(links.length>0){this.read_wmc_OnlineResource(server,links[0]);} +layerContext.url=server.href;},read_wmc_FormatList:function(layerContext,node){this.runChildNodes(layerContext,node);},read_wmc_Format:function(layerContext,node){var format={value:this.getChildValue(node)};if(node.getAttribute("current")=="1"){format.current=true;} +layerContext.formats.push(format);},read_wmc_StyleList:function(layerContext,node){this.runChildNodes(layerContext,node);},read_wmc_Style:function(layerContext,node){var style={};this.runChildNodes(style,node);if(node.getAttribute("current")=="1"){style.current=true;} +layerContext.styles.push(style);},read_wmc_SLD:function(style,node){this.runChildNodes(style,node);},read_sld_StyledLayerDescriptor:function(sld,node){var xml=OpenLayers.Format.XML.prototype.write.apply(this,[node]);sld.body=xml;},read_wmc_OnlineResource:function(obj,node){obj.href=this.getAttributeNS(node,this.namespaces.xlink,"href");},read_wmc_Name:function(obj,node){var name=this.getChildValue(node);if(name){obj.name=name;}},read_wmc_Title:function(obj,node){var title=this.getChildValue(node);if(title){obj.title=title;}},read_wmc_MetadataURL:function(layerContext,node){var metadataURL={};var links=node.getElementsByTagName("OnlineResource");if(links.length>0){this.read_wmc_OnlineResource(metadataURL,links[0]);} +layerContext.metadataURL=metadataURL.href;},read_wmc_Abstract:function(obj,node){var abst=this.getChildValue(node);if(abst){obj["abstract"]=abst;}},read_wmc_LegendURL:function(style,node){var legend={width:node.getAttribute('width'),height:node.getAttribute('height')};var links=node.getElementsByTagName("OnlineResource");if(links.length>0){this.read_wmc_OnlineResource(legend,links[0]);} +style.legend=legend;},write:function(context,options){var root=this.createElementDefaultNS("ViewContext");this.setAttributes(root,{version:this.VERSION,id:(options&&typeof options.id=="string")?options.id:OpenLayers.Util.createUniqueID("OpenLayers_Context_")});this.setAttributeNS(root,this.namespaces.xsi,"xsi:schemaLocation",this.schemaLocation);root.appendChild(this.write_wmc_General(context));root.appendChild(this.write_wmc_LayerList(context));return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},createElementDefaultNS:function(name,childValue,attributes){var node=this.createElementNS(this.namespaces[this.defaultPrefix],name);if(childValue){node.appendChild(this.createTextNode(childValue));} +if(attributes){this.setAttributes(node,attributes);} +return node;},setAttributes:function(node,obj){var value;for(var name in obj){value=obj[name].toString();if(value.match(/[A-Z]/)){this.setAttributeNS(node,null,name,value);}else{node.setAttribute(name,value);}}},write_wmc_General:function(context){var node=this.createElementDefaultNS("General");if(context.size){node.appendChild(this.createElementDefaultNS("Window",null,{width:context.size.w,height:context.size.h}));} +var bounds=context.bounds;node.appendChild(this.createElementDefaultNS("BoundingBox",null,{minx:bounds.left.toPrecision(18),miny:bounds.bottom.toPrecision(18),maxx:bounds.right.toPrecision(18),maxy:bounds.top.toPrecision(18),SRS:context.projection}));node.appendChild(this.createElementDefaultNS("Title",context.title));node.appendChild(this.write_ol_MapExtension(context));return node;},write_ol_MapExtension:function(context){var node=this.createElementDefaultNS("Extension");var bounds=context.maxExtent;if(bounds){var maxExtent=this.createElementNS(this.namespaces.ol,"ol:maxExtent");this.setAttributes(maxExtent,{minx:bounds.left.toPrecision(18),miny:bounds.bottom.toPrecision(18),maxx:bounds.right.toPrecision(18),maxy:bounds.top.toPrecision(18)});node.appendChild(maxExtent);} +return node;},write_wmc_LayerList:function(context){var list=this.createElementDefaultNS("LayerList");for(var i=0,len=context.layersContext.length;i<len;++i){list.appendChild(this.write_wmc_Layer(context.layersContext[i]));} +return list;},write_wmc_Layer:function(context){var node=this.createElementDefaultNS("Layer",null,{queryable:context.queryable?"1":"0",hidden:context.visibility?"0":"1"});node.appendChild(this.write_wmc_Server(context));node.appendChild(this.createElementDefaultNS("Name",context.name));node.appendChild(this.createElementDefaultNS("Title",context.title));if(context.metadataURL){node.appendChild(this.write_wmc_MetadataURL(context.metadataURL));} +return node;},write_wmc_LayerExtension:function(context){var node=this.createElementDefaultNS("Extension");var bounds=context.maxExtent;var maxExtent=this.createElementNS(this.namespaces.ol,"ol:maxExtent");this.setAttributes(maxExtent,{minx:bounds.left.toPrecision(18),miny:bounds.bottom.toPrecision(18),maxx:bounds.right.toPrecision(18),maxy:bounds.top.toPrecision(18)});node.appendChild(maxExtent);if(context.tileSize&&!context.singleTile){var size=this.createElementNS(this.namespaces.ol,"ol:tileSize");this.setAttributes(size,context.tileSize);node.appendChild(size);} +var properties=["transparent","numZoomLevels","units","isBaseLayer","opacity","displayInLayerSwitcher","singleTile"];var child;for(var i=0,len=properties.length;i<len;++i){child=this.createOLPropertyNode(context,properties[i]);if(child){node.appendChild(child);}} +return node;},createOLPropertyNode:function(obj,prop){var node=null;if(obj[prop]!=null){node=this.createElementNS(this.namespaces.ol,"ol:"+prop);node.appendChild(this.createTextNode(obj[prop].toString()));} +return node;},write_wmc_Server:function(context){var node=this.createElementDefaultNS("Server");this.setAttributes(node,{service:"OGC:WMS",version:context.version});node.appendChild(this.write_wmc_OnlineResource(context.url));return node;},write_wmc_MetadataURL:function(metadataURL){var node=this.createElementDefaultNS("MetadataURL");node.appendChild(this.write_wmc_OnlineResource(metadataURL));return node;},write_wmc_FormatList:function(context){var node=this.createElementDefaultNS("FormatList");for(var i=0,len=context.formats.length;i<len;i++){var format=context.formats[i];node.appendChild(this.createElementDefaultNS("Format",format.value,(format.current&&format.current==true)?{current:"1"}:null));} +return node;},write_wmc_StyleList:function(layer){var node=this.createElementDefaultNS("StyleList");var styles=layer.styles;if(styles&&styles instanceof Array){var sld;for(var i=0,len=styles.length;i<len;i++){var s=styles[i];var style=this.createElementDefaultNS("Style",null,(s.current&&s.current==true)?{current:"1"}:null);if(s.href){sld=this.createElementDefaultNS("SLD");var link=this.write_wmc_OnlineResource(s.href);sld.appendChild(link);sld.appendChild(this.createElementDefaultNS("Name",s.name));if(s.title){sld.appendChild(this.createElementDefaultNS("Title",s.title));} +style.appendChild(sld);}else if(s.body){sld=this.createElementDefaultNS("SLD");var doc=OpenLayers.Format.XML.prototype.read.apply(this,[s.body]);var imported=doc.documentElement;if(sld.ownerDocument&&sld.ownerDocument.importNode){imported=sld.ownerDocument.importNode(imported,true);} +sld.appendChild(imported);sld.appendChild(this.createElementDefaultNS("Name",s.name));if(s.title){sld.appendChild(this.createElementDefaultNS("Title",s.title));} +style.appendChild(sld);}else{style.appendChild(this.createElementDefaultNS("Name",s.name));style.appendChild(this.createElementDefaultNS("Title",s.title));if(s['abstract']){style.appendChild(this.createElementDefaultNS("Abstract",s['abstract']));}} +node.appendChild(style);}} +return node;},write_wmc_OnlineResource:function(href){var node=this.createElementDefaultNS("OnlineResource");this.setAttributeNS(node,this.namespaces.xlink,"xlink:type","simple");this.setAttributeNS(node,this.namespaces.xlink,"xlink:href",href);return node;},CLASS_NAME:"OpenLayers.Format.WMC.v1"});OpenLayers.Format.WMSCapabilities.v1_1=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1,{readers:{"wms":OpenLayers.Util.applyDefaults({"WMT_MS_Capabilities":function(node,obj){this.readChildNodes(node,obj);},"Keyword":function(node,obj){if(obj.keywords){obj.keywords.push(this.getChildValue(node));}},"DescribeLayer":function(node,obj){obj.describelayer={formats:[]};this.readChildNodes(node,obj.describelayer);},"GetLegendGraphic":function(node,obj){obj.getlegendgraphic={formats:[]};this.readChildNodes(node,obj.getlegendgraphic);},"GetStyles":function(node,obj){obj.getstyles={formats:[]};this.readChildNodes(node,obj.getstyles);},"PutStyles":function(node,obj){obj.putstyles={formats:[]};this.readChildNodes(node,obj.putstyles);},"UserDefinedSymbolization":function(node,obj){var userSymbols={supportSLD:parseInt(node.getAttribute("SupportSLD"))==1,userLayer:parseInt(node.getAttribute("UserLayer"))==1,userStyle:parseInt(node.getAttribute("UserStyle"))==1,remoteWFS:parseInt(node.getAttribute("RemoteWFS"))==1};obj.userSymbols=userSymbols;},"LatLonBoundingBox":function(node,obj){obj.llbbox=[parseFloat(node.getAttribute("minx")),parseFloat(node.getAttribute("miny")),parseFloat(node.getAttribute("maxx")),parseFloat(node.getAttribute("maxy"))];},"BoundingBox":function(node,obj){var bbox=OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"].BoundingBox.apply(this,[node,obj]);bbox.srs=node.getAttribute("SRS");obj.bbox[bbox.srs]=bbox;},"ScaleHint":function(node,obj){var min=node.getAttribute("min");var max=node.getAttribute("max");var rad2=Math.pow(2,0.5);var ipm=OpenLayers.INCHES_PER_UNIT["m"];obj.maxScale=parseFloat(((min/rad2)*ipm*OpenLayers.DOTS_PER_INCH).toPrecision(13));obj.minScale=parseFloat(((max/rad2)*ipm*OpenLayers.DOTS_PER_INCH).toPrecision(13));},"Dimension":function(node,obj){var name=node.getAttribute("name").toLowerCase();var dim={name:name,units:node.getAttribute("units"),unitsymbol:node.getAttribute("unitSymbol")};obj.dimensions[dim.name]=dim;},"Extent":function(node,obj){var name=node.getAttribute("name").toLowerCase();if(name in obj["dimensions"]){var extent=obj.dimensions[name];extent.nearestVal=node.getAttribute("nearestValue")==="1";extent.multipleVal=node.getAttribute("multipleValues")==="1";extent.current=node.getAttribute("current")==="1";extent["default"]=node.getAttribute("default")||"";var values=this.getChildValue(node);extent.values=values.split(",");}}},OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"])},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_1"});OpenLayers.Format.WMSCapabilities.v1_3=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1,{readers:{"wms":OpenLayers.Util.applyDefaults({"WMS_Capabilities":function(node,obj){this.readChildNodes(node,obj);},"LayerLimit":function(node,obj){obj.layerLimit=parseInt(this.getChildValue(node));},"MaxWidth":function(node,obj){obj.maxWidth=parseInt(this.getChildValue(node));},"MaxHeight":function(node,obj){obj.maxHeight=parseInt(this.getChildValue(node));},"BoundingBox":function(node,obj){var bbox=OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"].BoundingBox.apply(this,[node,obj]);bbox.srs=node.getAttribute("CRS");obj.bbox[bbox.srs]=bbox;},"CRS":function(node,obj){this.readers.wms.SRS.apply(this,[node,obj]);},"EX_GeographicBoundingBox":function(node,obj){obj.llbbox=[];this.readChildNodes(node,obj.llbbox);},"westBoundLongitude":function(node,obj){obj[0]=this.getChildValue(node);},"eastBoundLongitude":function(node,obj){obj[2]=this.getChildValue(node);},"southBoundLatitude":function(node,obj){obj[1]=this.getChildValue(node);},"northBoundLatitude":function(node,obj){obj[3]=this.getChildValue(node);},"MinScaleDenominator":function(node,obj){obj.maxScale=parseFloat(this.getChildValue(node)).toPrecision(16);},"MaxScaleDenominator":function(node,obj){obj.minScale=parseFloat(this.getChildValue(node)).toPrecision(16);},"Dimension":function(node,obj){var name=node.getAttribute("name").toLowerCase();var dim={name:name,units:node.getAttribute("units"),unitsymbol:node.getAttribute("unitSymbol"),nearestVal:node.getAttribute("nearestValue")==="1",multipleVal:node.getAttribute("multipleValues")==="1","default":node.getAttribute("default")||"",current:node.getAttribute("current")==="1",values:this.getChildValue(node).split(",")};obj.dimensions[dim.name]=dim;},"Keyword":function(node,obj){var keyword={value:this.getChildValue(node),vocabulary:node.getAttribute("vocabulary")};if(obj.keywords){obj.keywords.push(keyword);}}},OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"]),"sld":{"UserDefinedSymbolization":function(node,obj){this.readers.wms.UserDefinedSymbolization.apply(this,[node,obj]);obj.userSymbols.inlineFeature=parseInt(node.getAttribute("InlineFeature"))==1;obj.userSymbols.remoteWCS=parseInt(node.getAttribute("RemoteWCS"))==1;},"DescribeLayer":function(node,obj){this.readers.wms.DescribeLayer.apply(this,[node,obj]);},"GetLegendGraphic":function(node,obj){this.readers.wms.GetLegendGraphic.apply(this,[node,obj]);}}},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_3"});OpenLayers.Format.WMTSCapabilities.v1_0_0=OpenLayers.Class(OpenLayers.Format.OWSCommon.v1_1_0,{version:"1.0.0",namespaces:{ows:"http://www.opengis.net/ows/1.1",wmts:"http://www.opengis.net/wmts/1.0",xlink:"http://www.w3.org/1999/xlink"},yx:null,defaultPrefix:"wmts",initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;var yx=OpenLayers.Util.extend({},OpenLayers.Format.WMTSCapabilities.prototype.yx);this.yx=OpenLayers.Util.extend(yx,this.yx);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +if(data&&data.nodeType==9){data=data.documentElement;} +var capabilities={};this.readNode(data,capabilities);capabilities.version=this.version;return capabilities;},readers:{"wmts":{"Capabilities":function(node,obj){this.readChildNodes(node,obj);},"Contents":function(node,obj){obj.contents={};obj.contents.layers=[];obj.contents.tileMatrixSets={};this.readChildNodes(node,obj.contents);},"Layer":function(node,obj){var layer={styles:[],formats:[],tileMatrixSetLinks:[]};layer.layers=[];this.readChildNodes(node,layer);obj.layers.push(layer);},"Style":function(node,obj){var style={};style.isDefault=(node.getAttribute("isDefault")==="true");this.readChildNodes(node,style);obj.styles.push(style);},"Format":function(node,obj){obj.formats.push(this.getChildValue(node));},"TileMatrixSetLink":function(node,obj){var tileMatrixSetLink={};this.readChildNodes(node,tileMatrixSetLink);obj.tileMatrixSetLinks.push(tileMatrixSetLink);},"TileMatrixSet":function(node,obj){if(obj.layers){var tileMatrixSet={matrixIds:[]};this.readChildNodes(node,tileMatrixSet);obj.tileMatrixSets[tileMatrixSet.identifier]=tileMatrixSet;}else{obj.tileMatrixSet=this.getChildValue(node);}},"TileMatrix":function(node,obj){var tileMatrix={supportedCRS:obj.supportedCRS};this.readChildNodes(node,tileMatrix);obj.matrixIds.push(tileMatrix);},"ScaleDenominator":function(node,obj){obj.scaleDenominator=parseFloat(this.getChildValue(node));},"TopLeftCorner":function(node,obj){var topLeftCorner=this.getChildValue(node);var coords=topLeftCorner.split(" ");var yx;if(obj.supportedCRS){var crs=obj.supportedCRS.replace(/urn:ogc:def:crs:(\w+):.+:(\w+)$/,"urn:ogc:def:crs:$1::$2");yx=!!this.yx[crs];} +if(yx){obj.topLeftCorner=new OpenLayers.LonLat(coords[1],coords[0]);}else{obj.topLeftCorner=new OpenLayers.LonLat(coords[0],coords[1]);}},"TileWidth":function(node,obj){obj.tileWidth=parseInt(this.getChildValue(node));},"TileHeight":function(node,obj){obj.tileHeight=parseInt(this.getChildValue(node));},"MatrixWidth":function(node,obj){obj.matrixWidth=parseInt(this.getChildValue(node));},"MatrixHeight":function(node,obj){obj.matrixHeight=parseInt(this.getChildValue(node));},"WSDL":function(node,obj){obj.wsdl={};obj.wsdl.href=node.getAttribute("xlink:href");},"ServiceMetadataURL":function(node,obj){obj.serviceMetadataUrl={};obj.serviceMetadataUrl.href=node.getAttribute("xlink:href");}},"ows":OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]},CLASS_NAME:"OpenLayers.Format.WMTSCapabilities.v1_0_0"});OpenLayers.Layer.Boxes=OpenLayers.Class(OpenLayers.Layer.Markers,{initialize:function(name,options){OpenLayers.Layer.Markers.prototype.initialize.apply(this,arguments);},drawMarker:function(marker){var bounds=marker.bounds;var topleft=this.map.getLayerPxFromLonLat(new OpenLayers.LonLat(bounds.left,bounds.top));var botright=this.map.getLayerPxFromLonLat(new OpenLayers.LonLat(bounds.right,bounds.bottom));if(botright==null||topleft==null){marker.display(false);}else{var sz=new OpenLayers.Size(Math.max(1,botright.x-topleft.x),Math.max(1,botright.y-topleft.y));var markerDiv=marker.draw(topleft,sz);if(!marker.drawn){this.div.appendChild(markerDiv);marker.drawn=true;}}},removeMarker:function(marker){OpenLayers.Util.removeItem(this.markers,marker);if((marker.div!=null)&&(marker.div.parentNode==this.div)){this.div.removeChild(marker.div);}},CLASS_NAME:"OpenLayers.Layer.Boxes"});OpenLayers.Layer.GeoRSS=OpenLayers.Class(OpenLayers.Layer.Markers,{location:null,features:null,formatOptions:null,selectedFeature:null,icon:null,popupSize:null,useFeedTitle:true,initialize:function(name,location,options){OpenLayers.Layer.Markers.prototype.initialize.apply(this,[name,options]);this.location=location;this.features=[];},destroy:function(){OpenLayers.Layer.Markers.prototype.destroy.apply(this,arguments);this.clearFeatures();this.features=null;},loadRSS:function(){if(!this.loaded){this.events.triggerEvent("loadstart");OpenLayers.Request.GET({url:this.location,success:this.parseData,scope:this});this.loaded=true;}},moveTo:function(bounds,zoomChanged,minor){OpenLayers.Layer.Markers.prototype.moveTo.apply(this,arguments);if(this.visibility&&!this.loaded){this.loadRSS();}},parseData:function(ajaxRequest){var doc=ajaxRequest.responseXML;if(!doc||!doc.documentElement){doc=OpenLayers.Format.XML.prototype.read(ajaxRequest.responseText);} +if(this.useFeedTitle){var name=null;try{name=doc.getElementsByTagNameNS('*','title')[0].firstChild.nodeValue;} +catch(e){name=doc.getElementsByTagName('title')[0].firstChild.nodeValue;} +if(name){this.setName(name);}} +var options={};OpenLayers.Util.extend(options,this.formatOptions);if(this.map&&!this.projection.equals(this.map.getProjectionObject())){options.externalProjection=this.projection;options.internalProjection=this.map.getProjectionObject();} +var format=new OpenLayers.Format.GeoRSS(options);var features=format.read(doc);for(var i=0,len=features.length;i<len;i++){var data={};var feature=features[i];if(!feature.geometry){continue;} +var title=feature.attributes.title?feature.attributes.title:"Untitled";var description=feature.attributes.description?feature.attributes.description:"No description.";var link=feature.attributes.link?feature.attributes.link:"";var location=feature.geometry.getBounds().getCenterLonLat();data.icon=this.icon==null?OpenLayers.Marker.defaultIcon():this.icon.clone();data.popupSize=this.popupSize?this.popupSize.clone():new OpenLayers.Size(250,120);if(title||description){data.title=title;data.description=description;var contentHTML='<div class="olLayerGeoRSSClose">[x]</div>';contentHTML+='<div class="olLayerGeoRSSTitle">';if(link){contentHTML+='<a class="link" href="'+link+'" target="_blank">';} +contentHTML+=title;if(link){contentHTML+='</a>';} +contentHTML+='</div>';contentHTML+='<div style="" class="olLayerGeoRSSDescription">';contentHTML+=description;contentHTML+='</div>';data['popupContentHTML']=contentHTML;} +var feature=new OpenLayers.Feature(this,location,data);this.features.push(feature);var marker=feature.createMarker();marker.events.register('click',feature,this.markerClick);this.addMarker(marker);} +this.events.triggerEvent("loadend");},markerClick:function(evt){var sameMarkerClicked=(this==this.layer.selectedFeature);this.layer.selectedFeature=(!sameMarkerClicked)?this:null;for(var i=0,len=this.layer.map.popups.length;i<len;i++){this.layer.map.removePopup(this.layer.map.popups[i]);} +if(!sameMarkerClicked){var popup=this.createPopup();OpenLayers.Event.observe(popup.div,"click",OpenLayers.Function.bind(function(){for(var i=0,len=this.layer.map.popups.length;i<len;i++){this.layer.map.removePopup(this.layer.map.popups[i]);}},this));this.layer.map.addPopup(popup);} +OpenLayers.Event.stop(evt);},clearFeatures:function(){if(this.features!=null){while(this.features.length>0){var feature=this.features[0];OpenLayers.Util.removeItem(this.features,feature);feature.destroy();}}},CLASS_NAME:"OpenLayers.Layer.GeoRSS"});OpenLayers.Layer.Google=OpenLayers.Class(OpenLayers.Layer.EventPane,OpenLayers.Layer.FixedZoomLevels,{MIN_ZOOM_LEVEL:0,MAX_ZOOM_LEVEL:21,RESOLUTIONS:[1.40625,0.703125,0.3515625,0.17578125,0.087890625,0.0439453125,0.02197265625,0.010986328125,0.0054931640625,0.00274658203125,0.001373291015625,0.0006866455078125,0.00034332275390625,0.000171661376953125,0.0000858306884765625,0.00004291534423828125,0.00002145767211914062,0.00001072883605957031,0.00000536441802978515,0.00000268220901489257,0.0000013411045074462891,0.00000067055225372314453],type:null,wrapDateLine:true,sphericalMercator:false,version:null,initialize:function(name,options){options=options||{};if(!options.version){options.version=typeof GMap2==="function"?"2":"3";} +var mixin=OpenLayers.Layer.Google["v"+ +options.version.replace(/\./g,"_")];if(mixin){OpenLayers.Util.applyDefaults(options,mixin);}else{throw"Unsupported Google Maps API version: "+options.version;} +OpenLayers.Util.applyDefaults(options,mixin.DEFAULTS);if(options.maxExtent){options.maxExtent=options.maxExtent.clone();} +OpenLayers.Layer.EventPane.prototype.initialize.apply(this,[name,options]);OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this,[name,options]);if(this.sphericalMercator){OpenLayers.Util.extend(this,OpenLayers.Layer.SphericalMercator);this.initMercatorParameters();}},clone:function(){return new OpenLayers.Layer.Google(this.name,this.getOptions());},setVisibility:function(visible){var opacity=this.opacity==null?1:this.opacity;OpenLayers.Layer.EventPane.prototype.setVisibility.apply(this,arguments);this.setOpacity(opacity);},display:function(visible){if(!this._dragging){this.setGMapVisibility(visible);} +OpenLayers.Layer.EventPane.prototype.display.apply(this,arguments);},moveTo:function(bounds,zoomChanged,dragging){this._dragging=dragging;OpenLayers.Layer.EventPane.prototype.moveTo.apply(this,arguments);delete this._dragging;},setOpacity:function(opacity){if(opacity!==this.opacity){if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"opacity"});} +this.opacity=opacity;} +if(this.getVisibility()){var container=this.getMapContainer();OpenLayers.Util.modifyDOMElement(container,null,null,null,null,null,null,opacity);}},destroy:function(){if(this.map){this.setGMapVisibility(false);var cache=OpenLayers.Layer.Google.cache[this.map.id];if(cache&&cache.count<=1){this.removeGMapElements();}} +OpenLayers.Layer.EventPane.prototype.destroy.apply(this,arguments);},removeGMapElements:function(){var cache=OpenLayers.Layer.Google.cache[this.map.id];if(cache){var container=this.mapObject&&this.getMapContainer();if(container&&container.parentNode){container.parentNode.removeChild(container);} +var termsOfUse=cache.termsOfUse;if(termsOfUse&&termsOfUse.parentNode){termsOfUse.parentNode.removeChild(termsOfUse);} +var poweredBy=cache.poweredBy;if(poweredBy&&poweredBy.parentNode){poweredBy.parentNode.removeChild(poweredBy);}}},removeMap:function(map){if(this.visibility&&this.mapObject){this.setGMapVisibility(false);} +var cache=OpenLayers.Layer.Google.cache[map.id];if(cache){if(cache.count<=1){this.removeGMapElements();delete OpenLayers.Layer.Google.cache[map.id];}else{--cache.count;}} +delete this.termsOfUse;delete this.poweredBy;delete this.mapObject;delete this.dragObject;OpenLayers.Layer.EventPane.prototype.removeMap.apply(this,arguments);},getOLBoundsFromMapObjectBounds:function(moBounds){var olBounds=null;if(moBounds!=null){var sw=moBounds.getSouthWest();var ne=moBounds.getNorthEast();if(this.sphericalMercator){sw=this.forwardMercator(sw.lng(),sw.lat());ne=this.forwardMercator(ne.lng(),ne.lat());}else{sw=new OpenLayers.LonLat(sw.lng(),sw.lat());ne=new OpenLayers.LonLat(ne.lng(),ne.lat());} +olBounds=new OpenLayers.Bounds(sw.lon,sw.lat,ne.lon,ne.lat);} +return olBounds;},getWarningHTML:function(){return OpenLayers.i18n("googleWarning");},getMapObjectCenter:function(){return this.mapObject.getCenter();},getMapObjectZoom:function(){return this.mapObject.getZoom();},getLongitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.lng(),moLonLat.lat()).lon:moLonLat.lng();},getLatitudeFromMapObjectLonLat:function(moLonLat){var lat=this.sphericalMercator?this.forwardMercator(moLonLat.lng(),moLonLat.lat()).lat:moLonLat.lat();return lat;},getXFromMapObjectPixel:function(moPixel){return moPixel.x;},getYFromMapObjectPixel:function(moPixel){return moPixel.y;},CLASS_NAME:"OpenLayers.Layer.Google"});OpenLayers.Layer.Google.cache={};OpenLayers.Layer.Google.v2={termsOfUse:null,poweredBy:null,dragObject:null,loadMapObject:function(){if(!this.type){this.type=G_NORMAL_MAP;} +var mapObject,termsOfUse,poweredBy;var cache=OpenLayers.Layer.Google.cache[this.map.id];if(cache){mapObject=cache.mapObject;termsOfUse=cache.termsOfUse;poweredBy=cache.poweredBy;++cache.count;}else{var container=this.map.viewPortDiv;var div=document.createElement("div");div.id=this.map.id+"_GMap2Container";div.style.position="absolute";div.style.width="100%";div.style.height="100%";container.appendChild(div);try{mapObject=new GMap2(div);termsOfUse=div.lastChild;container.appendChild(termsOfUse);termsOfUse.style.zIndex="1100";termsOfUse.style.right="";termsOfUse.style.bottom="";termsOfUse.className="olLayerGoogleCopyright";poweredBy=div.lastChild;container.appendChild(poweredBy);poweredBy.style.zIndex="1100";poweredBy.style.right="";poweredBy.style.bottom="";poweredBy.className="olLayerGooglePoweredBy gmnoprint";}catch(e){throw(e);} +OpenLayers.Layer.Google.cache[this.map.id]={mapObject:mapObject,termsOfUse:termsOfUse,poweredBy:poweredBy,count:1};} +this.mapObject=mapObject;this.termsOfUse=termsOfUse;this.poweredBy=poweredBy;if(OpenLayers.Util.indexOf(this.mapObject.getMapTypes(),this.type)===-1){this.mapObject.addMapType(this.type);} +if(typeof mapObject.getDragObject=="function"){this.dragObject=mapObject.getDragObject();}else{this.dragPanMapObject=null;} +if(this.isBaseLayer===false){this.setGMapVisibility(this.div.style.display!=="none");}},onMapResize:function(){if(this.visibility&&this.mapObject.isLoaded()){this.mapObject.checkResize();}else{if(!this._resized){var layer=this;var handle=GEvent.addListener(this.mapObject,"load",function(){GEvent.removeListener(handle);delete layer._resized;layer.mapObject.checkResize();layer.moveTo(layer.map.getCenter(),layer.map.getZoom());});} +this._resized=true;}},setGMapVisibility:function(visible){var cache=OpenLayers.Layer.Google.cache[this.map.id];if(cache){var container=this.mapObject.getContainer();if(visible===true){this.mapObject.setMapType(this.type);container.style.display="";this.termsOfUse.style.left="";this.termsOfUse.style.display="";this.poweredBy.style.display="";cache.displayed=this.id;}else{if(cache.displayed===this.id){delete cache.displayed;} +if(!cache.displayed){container.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(olBounds){var moBounds=null;if(olBounds!=null){var sw=this.sphericalMercator?this.inverseMercator(olBounds.bottom,olBounds.left):new OpenLayers.LonLat(olBounds.bottom,olBounds.left);var ne=this.sphericalMercator?this.inverseMercator(olBounds.top,olBounds.right):new OpenLayers.LonLat(olBounds.top,olBounds.right);moBounds=new GLatLngBounds(new GLatLng(sw.lat,sw.lon),new GLatLng(ne.lat,ne.lon));} +return moBounds;},setMapObjectCenter:function(center,zoom){this.mapObject.setCenter(center,zoom);},dragPanMapObject:function(dX,dY){this.dragObject.moveBy(new GSize(-dX,dY));},getMapObjectLonLatFromMapObjectPixel:function(moPixel){return this.mapObject.fromContainerPixelToLatLng(moPixel);},getMapObjectPixelFromMapObjectLonLat:function(moLonLat){return this.mapObject.fromLatLngToContainerPixel(moLonLat);},getMapObjectZoomFromMapObjectBounds:function(moBounds){return this.mapObject.getBoundsZoomLevel(moBounds);},getMapObjectLonLatFromLonLat:function(lon,lat){var gLatLng;if(this.sphericalMercator){var lonlat=this.inverseMercator(lon,lat);gLatLng=new GLatLng(lonlat.lat,lonlat.lon);}else{gLatLng=new GLatLng(lat,lon);} +return gLatLng;},getMapObjectPixelFromXY:function(x,y){return new GPoint(x,y);}};OpenLayers.Layer.Grid=OpenLayers.Class(OpenLayers.Layer.HTTPRequest,{tileSize:null,grid:null,singleTile:false,ratio:1.5,buffer:2,numLoadingTiles:0,initialize:function(name,url,params,options){OpenLayers.Layer.HTTPRequest.prototype.initialize.apply(this,arguments);this.events.addEventType("tileloaded");this.grid=[];},destroy:function(){this.clearGrid();this.grid=null;this.tileSize=null;OpenLayers.Layer.HTTPRequest.prototype.destroy.apply(this,arguments);},clearGrid:function(){if(this.grid){for(var iRow=0,len=this.grid.length;iRow<len;iRow++){var row=this.grid[iRow];for(var iCol=0,clen=row.length;iCol<clen;iCol++){var tile=row[iCol];this.removeTileMonitoringHooks(tile);tile.destroy();}} +this.grid=[];}},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.Grid(this.name,this.url,this.params,this.getOptions());} +obj=OpenLayers.Layer.HTTPRequest.prototype.clone.apply(this,[obj]);if(this.tileSize!=null){obj.tileSize=this.tileSize.clone();} +obj.grid=[];return obj;},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.HTTPRequest.prototype.moveTo.apply(this,arguments);bounds=bounds||this.map.getExtent();if(bounds!=null){var forceReTile=!this.grid.length||zoomChanged;var tilesBounds=this.getTilesBounds();if(this.singleTile){if(forceReTile||(!dragging&&!tilesBounds.containsBounds(bounds))){this.initSingleTile(bounds);}}else{if(forceReTile||!tilesBounds.containsBounds(bounds,true)){this.initGriddedTiles(bounds);}else{this.moveGriddedTiles(bounds);}}}},setTileSize:function(size){if(this.singleTile){size=this.map.getSize();size.h=parseInt(size.h*this.ratio);size.w=parseInt(size.w*this.ratio);} +OpenLayers.Layer.HTTPRequest.prototype.setTileSize.apply(this,[size]);},getGridBounds:function(){var msg="The getGridBounds() function is deprecated. It will be "+"removed in 3.0. Please use getTilesBounds() instead.";OpenLayers.Console.warn(msg);return this.getTilesBounds();},getTilesBounds:function(){var bounds=null;if(this.grid.length){var bottom=this.grid.length-1;var bottomLeftTile=this.grid[bottom][0];var right=this.grid[0].length-1;var topRightTile=this.grid[0][right];bounds=new OpenLayers.Bounds(bottomLeftTile.bounds.left,bottomLeftTile.bounds.bottom,topRightTile.bounds.right,topRightTile.bounds.top);} +return bounds;},initSingleTile:function(bounds){var center=bounds.getCenterLonLat();var tileWidth=bounds.getWidth()*this.ratio;var tileHeight=bounds.getHeight()*this.ratio;var tileBounds=new OpenLayers.Bounds(center.lon-(tileWidth/2),center.lat-(tileHeight/2),center.lon+(tileWidth/2),center.lat+(tileHeight/2));var ul=new OpenLayers.LonLat(tileBounds.left,tileBounds.top);var px=this.map.getLayerPxFromLonLat(ul);if(!this.grid.length){this.grid[0]=[];} +var tile=this.grid[0][0];if(!tile){tile=this.addTile(tileBounds,px);this.addTileMonitoringHooks(tile);tile.draw();this.grid[0][0]=tile;}else{tile.moveTo(tileBounds,px);} +this.removeExcessTiles(1,1);},calculateGridLayout:function(bounds,extent,resolution){var tilelon=resolution*this.tileSize.w;var tilelat=resolution*this.tileSize.h;var offsetlon=bounds.left-extent.left;var tilecol=Math.floor(offsetlon/tilelon)-this.buffer;var tilecolremain=offsetlon/tilelon-tilecol;var tileoffsetx=-tilecolremain*this.tileSize.w;var tileoffsetlon=extent.left+tilecol*tilelon;var offsetlat=bounds.top-(extent.bottom+tilelat);var tilerow=Math.ceil(offsetlat/tilelat)+this.buffer;var tilerowremain=tilerow-offsetlat/tilelat;var tileoffsety=-tilerowremain*this.tileSize.h;var tileoffsetlat=extent.bottom+tilerow*tilelat;return{tilelon:tilelon,tilelat:tilelat,tileoffsetlon:tileoffsetlon,tileoffsetlat:tileoffsetlat,tileoffsetx:tileoffsetx,tileoffsety:tileoffsety};},initGriddedTiles:function(bounds){var viewSize=this.map.getSize();var minRows=Math.ceil(viewSize.h/this.tileSize.h)+ +Math.max(1,2*this.buffer);var minCols=Math.ceil(viewSize.w/this.tileSize.w)+ +Math.max(1,2*this.buffer);var extent=this.getMaxExtent();var resolution=this.map.getResolution();var tileLayout=this.calculateGridLayout(bounds,extent,resolution);var tileoffsetx=Math.round(tileLayout.tileoffsetx);var tileoffsety=Math.round(tileLayout.tileoffsety);var tileoffsetlon=tileLayout.tileoffsetlon;var tileoffsetlat=tileLayout.tileoffsetlat;var tilelon=tileLayout.tilelon;var tilelat=tileLayout.tilelat;this.origin=new OpenLayers.Pixel(tileoffsetx,tileoffsety);var startX=tileoffsetx;var startLon=tileoffsetlon;var rowidx=0;var layerContainerDivLeft=parseInt(this.map.layerContainerDiv.style.left);var layerContainerDivTop=parseInt(this.map.layerContainerDiv.style.top);do{var row=this.grid[rowidx++];if(!row){row=[];this.grid.push(row);} +tileoffsetlon=startLon;tileoffsetx=startX;var colidx=0;do{var tileBounds=new OpenLayers.Bounds(tileoffsetlon,tileoffsetlat,tileoffsetlon+tilelon,tileoffsetlat+tilelat);var x=tileoffsetx;x-=layerContainerDivLeft;var y=tileoffsety;y-=layerContainerDivTop;var px=new OpenLayers.Pixel(x,y);var tile=row[colidx++];if(!tile){tile=this.addTile(tileBounds,px);this.addTileMonitoringHooks(tile);row.push(tile);}else{tile.moveTo(tileBounds,px,false);} +tileoffsetlon+=tilelon;tileoffsetx+=this.tileSize.w;}while((tileoffsetlon<=bounds.right+tilelon*this.buffer)||colidx<minCols);tileoffsetlat-=tilelat;tileoffsety+=this.tileSize.h;}while((tileoffsetlat>=bounds.bottom-tilelat*this.buffer)||rowidx<minRows);this.removeExcessTiles(rowidx,colidx);this.spiralTileLoad();},getMaxExtent:function(){return this.maxExtent;},spiralTileLoad:function(){var tileQueue=[];var directions=["right","down","left","up"];var iRow=0;var iCell=-1;var direction=OpenLayers.Util.indexOf(directions,"right");var directionsTried=0;while(directionsTried<directions.length){var testRow=iRow;var testCell=iCell;switch(directions[direction]){case"right":testCell++;break;case"down":testRow++;break;case"left":testCell--;break;case"up":testRow--;break;} +var tile=null;if((testRow<this.grid.length)&&(testRow>=0)&&(testCell<this.grid[0].length)&&(testCell>=0)){tile=this.grid[testRow][testCell];} +if((tile!=null)&&(!tile.queued)){tileQueue.unshift(tile);tile.queued=true;directionsTried=0;iRow=testRow;iCell=testCell;}else{direction=(direction+1)%4;directionsTried++;}} +for(var i=0,len=tileQueue.length;i<len;i++){var tile=tileQueue[i];tile.draw();tile.queued=false;}},addTile:function(bounds,position){},addTileMonitoringHooks:function(tile){tile.onLoadStart=function(){if(this.numLoadingTiles==0){this.events.triggerEvent("loadstart");} +this.numLoadingTiles++;};tile.events.register("loadstart",this,tile.onLoadStart);tile.onLoadEnd=function(){this.numLoadingTiles--;this.events.triggerEvent("tileloaded");if(this.numLoadingTiles==0){this.events.triggerEvent("loadend");}};tile.events.register("loadend",this,tile.onLoadEnd);tile.events.register("unload",this,tile.onLoadEnd);},removeTileMonitoringHooks:function(tile){tile.unload();tile.events.un({"loadstart":tile.onLoadStart,"loadend":tile.onLoadEnd,"unload":tile.onLoadEnd,scope:this});},moveGriddedTiles:function(bounds){var buffer=this.buffer||1;while(true){var tlLayer=this.grid[0][0].position;var tlViewPort=this.map.getViewPortPxFromLayerPx(tlLayer);if(tlViewPort.x>-this.tileSize.w*(buffer-1)){this.shiftColumn(true);}else if(tlViewPort.x<-this.tileSize.w*buffer){this.shiftColumn(false);}else if(tlViewPort.y>-this.tileSize.h*(buffer-1)){this.shiftRow(true);}else if(tlViewPort.y<-this.tileSize.h*buffer){this.shiftRow(false);}else{break;}};},shiftRow:function(prepend){var modelRowIndex=(prepend)?0:(this.grid.length-1);var grid=this.grid;var modelRow=grid[modelRowIndex];var resolution=this.map.getResolution();var deltaY=(prepend)?-this.tileSize.h:this.tileSize.h;var deltaLat=resolution*-deltaY;var row=(prepend)?grid.pop():grid.shift();for(var i=0,len=modelRow.length;i<len;i++){var modelTile=modelRow[i];var bounds=modelTile.bounds.clone();var position=modelTile.position.clone();bounds.bottom=bounds.bottom+deltaLat;bounds.top=bounds.top+deltaLat;position.y=position.y+deltaY;row[i].moveTo(bounds,position);} +if(prepend){grid.unshift(row);}else{grid.push(row);}},shiftColumn:function(prepend){var deltaX=(prepend)?-this.tileSize.w:this.tileSize.w;var resolution=this.map.getResolution();var deltaLon=resolution*deltaX;for(var i=0,len=this.grid.length;i<len;i++){var row=this.grid[i];var modelTileIndex=(prepend)?0:(row.length-1);var modelTile=row[modelTileIndex];var bounds=modelTile.bounds.clone();var position=modelTile.position.clone();bounds.left=bounds.left+deltaLon;bounds.right=bounds.right+deltaLon;position.x=position.x+deltaX;var tile=prepend?this.grid[i].pop():this.grid[i].shift();tile.moveTo(bounds,position);if(prepend){row.unshift(tile);}else{row.push(tile);}}},removeExcessTiles:function(rows,columns){while(this.grid.length>rows){var row=this.grid.pop();for(var i=0,l=row.length;i<l;i++){var tile=row[i];this.removeTileMonitoringHooks(tile);tile.destroy();}} +while(this.grid[0].length>columns){for(var i=0,l=this.grid.length;i<l;i++){var row=this.grid[i];var tile=row.pop();this.removeTileMonitoringHooks(tile);tile.destroy();}}},onMapResize:function(){if(this.singleTile){this.clearGrid();this.setTileSize();}},getTileBounds:function(viewPortPx){var maxExtent=this.maxExtent;var resolution=this.getResolution();var tileMapWidth=resolution*this.tileSize.w;var tileMapHeight=resolution*this.tileSize.h;var mapPoint=this.getLonLatFromViewPortPx(viewPortPx);var tileLeft=maxExtent.left+(tileMapWidth*Math.floor((mapPoint.lon- +maxExtent.left)/tileMapWidth));var tileBottom=maxExtent.bottom+(tileMapHeight*Math.floor((mapPoint.lat- +maxExtent.bottom)/tileMapHeight));return new OpenLayers.Bounds(tileLeft,tileBottom,tileLeft+tileMapWidth,tileBottom+tileMapHeight);},CLASS_NAME:"OpenLayers.Layer.Grid"});OpenLayers.Layer.MultiMap=OpenLayers.Class(OpenLayers.Layer.EventPane,OpenLayers.Layer.FixedZoomLevels,{MIN_ZOOM_LEVEL:1,MAX_ZOOM_LEVEL:17,RESOLUTIONS:[9,1.40625,0.703125,0.3515625,0.17578125,0.087890625,0.0439453125,0.02197265625,0.010986328125,0.0054931640625,0.00274658203125,0.001373291015625,0.0006866455078125,0.00034332275390625,0.000171661376953125,0.0000858306884765625,0.00004291534423828125],type:null,initialize:function(name,options){OpenLayers.Layer.EventPane.prototype.initialize.apply(this,arguments);OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this,arguments);if(this.sphericalMercator){OpenLayers.Util.extend(this,OpenLayers.Layer.SphericalMercator);this.initMercatorParameters();this.RESOLUTIONS.unshift(10);}},loadMapObject:function(){try{this.mapObject=new MultimapViewer(this.div);}catch(e){}},getWarningHTML:function(){return OpenLayers.i18n("getLayerWarning",{'layerType':"MM",'layerLib':"MultiMap"});},setMapObjectCenter:function(center,zoom){this.mapObject.goToPosition(center,zoom);},getMapObjectCenter:function(){return this.mapObject.getCurrentPosition();},getMapObjectZoom:function(){return this.mapObject.getZoomFactor();},getMapObjectLonLatFromMapObjectPixel:function(moPixel){moPixel.x=moPixel.x-(this.map.getSize().w/2);moPixel.y=moPixel.y-(this.map.getSize().h/2);return this.mapObject.getMapPositionAt(moPixel);},getMapObjectPixelFromMapObjectLonLat:function(moLonLat){return this.mapObject.geoPosToContainerPixels(moLonLat);},getLongitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.lon,moLonLat.lat).lon:moLonLat.lon;},getLatitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.lon,moLonLat.lat).lat:moLonLat.lat;},getMapObjectLonLatFromLonLat:function(lon,lat){var mmLatLon;if(this.sphericalMercator){var lonlat=this.inverseMercator(lon,lat);mmLatLon=new MMLatLon(lonlat.lat,lonlat.lon);}else{mmLatLon=new MMLatLon(lat,lon);} +return mmLatLon;},getXFromMapObjectPixel:function(moPixel){return moPixel.x;},getYFromMapObjectPixel:function(moPixel){return moPixel.y;},getMapObjectPixelFromXY:function(x,y){return new MMPoint(x,y);},CLASS_NAME:"OpenLayers.Layer.MultiMap"});OpenLayers.Layer.VirtualEarth=OpenLayers.Class(OpenLayers.Layer.EventPane,OpenLayers.Layer.FixedZoomLevels,{MIN_ZOOM_LEVEL:1,MAX_ZOOM_LEVEL:19,RESOLUTIONS:[1.40625,0.703125,0.3515625,0.17578125,0.087890625,0.0439453125,0.02197265625,0.010986328125,0.0054931640625,0.00274658203125,0.001373291015625,0.0006866455078125,0.00034332275390625,0.000171661376953125,0.0000858306884765625,0.00004291534423828125,0.00002145767211914062,0.00001072883605957031,0.00000536441802978515],type:null,wrapDateLine:true,sphericalMercator:false,animationEnabled:true,initialize:function(name,options){OpenLayers.Layer.EventPane.prototype.initialize.apply(this,arguments);OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this,arguments);if(this.sphericalMercator){OpenLayers.Util.extend(this,OpenLayers.Layer.SphericalMercator);this.initMercatorParameters();}},loadMapObject:function(){var veDiv=OpenLayers.Util.createDiv(this.name);var sz=this.map.getSize();veDiv.style.width=sz.w+"px";veDiv.style.height=sz.h+"px";this.div.appendChild(veDiv);try{this.mapObject=new VEMap(this.name);}catch(e){} +if(this.mapObject!=null){try{this.mapObject.LoadMap(null,null,this.type,true);this.mapObject.AttachEvent("onmousedown",OpenLayers.Function.True);}catch(e){} +this.mapObject.HideDashboard();if(typeof this.mapObject.SetAnimationEnabled=="function"){this.mapObject.SetAnimationEnabled(this.animationEnabled);}} +if(!this.mapObject||!this.mapObject.vemapcontrol||!this.mapObject.vemapcontrol.PanMap||(typeof this.mapObject.vemapcontrol.PanMap!="function")){this.dragPanMapObject=null;}},onMapResize:function(){this.mapObject.Resize(this.map.size.w,this.map.size.h);},getWarningHTML:function(){return OpenLayers.i18n("getLayerWarning",{'layerType':'VE','layerLib':'VirtualEarth'});},setMapObjectCenter:function(center,zoom){this.mapObject.SetCenterAndZoom(center,zoom);},getMapObjectCenter:function(){return this.mapObject.GetCenter();},dragPanMapObject:function(dX,dY){this.mapObject.vemapcontrol.PanMap(dX,-dY);},getMapObjectZoom:function(){return this.mapObject.GetZoomLevel();},getMapObjectLonLatFromMapObjectPixel:function(moPixel){return(typeof VEPixel!='undefined')?this.mapObject.PixelToLatLong(moPixel):this.mapObject.PixelToLatLong(moPixel.x,moPixel.y);},getMapObjectPixelFromMapObjectLonLat:function(moLonLat){return this.mapObject.LatLongToPixel(moLonLat);},getLongitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.Longitude,moLonLat.Latitude).lon:moLonLat.Longitude;},getLatitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.Longitude,moLonLat.Latitude).lat:moLonLat.Latitude;},getMapObjectLonLatFromLonLat:function(lon,lat){var veLatLong;if(this.sphericalMercator){var lonlat=this.inverseMercator(lon,lat);veLatLong=new VELatLong(lonlat.lat,lonlat.lon);}else{veLatLong=new VELatLong(lat,lon);} +return veLatLong;},getXFromMapObjectPixel:function(moPixel){return moPixel.x;},getYFromMapObjectPixel:function(moPixel){return moPixel.y;},getMapObjectPixelFromXY:function(x,y){return(typeof VEPixel!='undefined')?new VEPixel(x,y):new Msn.VE.Pixel(x,y);},CLASS_NAME:"OpenLayers.Layer.VirtualEarth"});OpenLayers.Layer.Yahoo=OpenLayers.Class(OpenLayers.Layer.EventPane,OpenLayers.Layer.FixedZoomLevels,{MIN_ZOOM_LEVEL:0,MAX_ZOOM_LEVEL:17,RESOLUTIONS:[1.40625,0.703125,0.3515625,0.17578125,0.087890625,0.0439453125,0.02197265625,0.010986328125,0.0054931640625,0.00274658203125,0.001373291015625,0.0006866455078125,0.00034332275390625,0.000171661376953125,0.0000858306884765625,0.00004291534423828125,0.00002145767211914062,0.00001072883605957031],type:null,wrapDateLine:true,sphericalMercator:false,initialize:function(name,options){OpenLayers.Layer.EventPane.prototype.initialize.apply(this,arguments);OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this,arguments);if(this.sphericalMercator){OpenLayers.Util.extend(this,OpenLayers.Layer.SphericalMercator);this.initMercatorParameters();}},loadMapObject:function(){try{var size=this.getMapObjectSizeFromOLSize(this.map.getSize());this.mapObject=new YMap(this.div,this.type,size);this.mapObject.disableKeyControls();this.mapObject.disableDragMap();if(!this.mapObject.moveByXY||(typeof this.mapObject.moveByXY!="function")){this.dragPanMapObject=null;}}catch(e){}},onMapResize:function(){try{var size=this.getMapObjectSizeFromOLSize(this.map.getSize());this.mapObject.resizeTo(size);}catch(e){}},setMap:function(map){OpenLayers.Layer.EventPane.prototype.setMap.apply(this,arguments);this.map.events.register("moveend",this,this.fixYahooEventPane);},fixYahooEventPane:function(){var yahooEventPane=OpenLayers.Util.getElement("ygddfdiv");if(yahooEventPane!=null){if(yahooEventPane.parentNode!=null){yahooEventPane.parentNode.removeChild(yahooEventPane);} +this.map.events.unregister("moveend",this,this.fixYahooEventPane);}},getWarningHTML:function(){return OpenLayers.i18n("getLayerWarning",{'layerType':'Yahoo','layerLib':'Yahoo'});},getOLZoomFromMapObjectZoom:function(moZoom){var zoom=null;if(moZoom!=null){zoom=OpenLayers.Layer.FixedZoomLevels.prototype.getOLZoomFromMapObjectZoom.apply(this,[moZoom]);zoom=18-zoom;} +return zoom;},getMapObjectZoomFromOLZoom:function(olZoom){var zoom=null;if(olZoom!=null){zoom=OpenLayers.Layer.FixedZoomLevels.prototype.getMapObjectZoomFromOLZoom.apply(this,[olZoom]);zoom=18-zoom;} +return zoom;},setMapObjectCenter:function(center,zoom){this.mapObject.drawZoomAndCenter(center,zoom);},getMapObjectCenter:function(){return this.mapObject.getCenterLatLon();},dragPanMapObject:function(dX,dY){this.mapObject.moveByXY({'x':-dX,'y':dY});},getMapObjectZoom:function(){return this.mapObject.getZoomLevel();},getMapObjectLonLatFromMapObjectPixel:function(moPixel){return this.mapObject.convertXYLatLon(moPixel);},getMapObjectPixelFromMapObjectLonLat:function(moLonLat){return this.mapObject.convertLatLonXY(moLonLat);},getLongitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.Lon,moLonLat.Lat).lon:moLonLat.Lon;},getLatitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.Lon,moLonLat.Lat).lat:moLonLat.Lat;},getMapObjectLonLatFromLonLat:function(lon,lat){var yLatLong;if(this.sphericalMercator){var lonlat=this.inverseMercator(lon,lat);yLatLong=new YGeoPoint(lonlat.lat,lonlat.lon);}else{yLatLong=new YGeoPoint(lat,lon);} +return yLatLong;},getXFromMapObjectPixel:function(moPixel){return moPixel.x;},getYFromMapObjectPixel:function(moPixel){return moPixel.y;},getMapObjectPixelFromXY:function(x,y){return new YCoordPoint(x,y);},getMapObjectSizeFromOLSize:function(olSize){return new YSize(olSize.w,olSize.h);},CLASS_NAME:"OpenLayers.Layer.Yahoo"});OpenLayers.Style=OpenLayers.Class({id:null,name:null,title:null,description:null,layerName:null,isDefault:false,rules:null,context:null,defaultStyle:null,defaultsPerSymbolizer:false,propertyStyles:null,initialize:function(style,options){OpenLayers.Util.extend(this,options);this.rules=[];if(options&&options.rules){this.addRules(options.rules);} +this.setDefaultStyle(style||OpenLayers.Feature.Vector.style["default"]);this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){for(var i=0,len=this.rules.length;i<len;i++){this.rules[i].destroy();this.rules[i]=null;} +this.rules=null;this.defaultStyle=null;},createSymbolizer:function(feature){var style=this.defaultsPerSymbolizer?{}:this.createLiterals(OpenLayers.Util.extend({},this.defaultStyle),feature);var rules=this.rules;var rule,context;var elseRules=[];var appliedRules=false;for(var i=0,len=rules.length;i<len;i++){rule=rules[i];var applies=rule.evaluate(feature);if(applies){if(rule instanceof OpenLayers.Rule&&rule.elseFilter){elseRules.push(rule);}else{appliedRules=true;this.applySymbolizer(rule,style,feature);}}} +if(appliedRules==false&&elseRules.length>0){appliedRules=true;for(var i=0,len=elseRules.length;i<len;i++){this.applySymbolizer(elseRules[i],style,feature);}} +if(rules.length>0&&appliedRules==false){style.display="none";} +return style;},applySymbolizer:function(rule,style,feature){var symbolizerPrefix=feature.geometry?this.getSymbolizerPrefix(feature.geometry):OpenLayers.Style.SYMBOLIZER_PREFIXES[0];var symbolizer=rule.symbolizer[symbolizerPrefix]||rule.symbolizer;if(this.defaultsPerSymbolizer===true){var defaults=this.defaultStyle;OpenLayers.Util.applyDefaults(symbolizer,{pointRadius:defaults.pointRadius});if(symbolizer.stroke===true||symbolizer.graphic===true){OpenLayers.Util.applyDefaults(symbolizer,{strokeWidth:defaults.strokeWidth,strokeColor:defaults.strokeColor,strokeOpacity:defaults.strokeOpacity,strokeDashstyle:defaults.strokeDashstyle,strokeLinecap:defaults.strokeLinecap});} +if(symbolizer.fill===true||symbolizer.graphic===true){OpenLayers.Util.applyDefaults(symbolizer,{fillColor:defaults.fillColor,fillOpacity:defaults.fillOpacity});} +if(symbolizer.graphic===true){OpenLayers.Util.applyDefaults(symbolizer,{pointRadius:this.defaultStyle.pointRadius,externalGraphic:this.defaultStyle.externalGraphic,graphicName:this.defaultStyle.graphicName,graphicOpacity:this.defaultStyle.graphicOpacity,graphicWidth:this.defaultStyle.graphicWidth,graphicHeight:this.defaultStyle.graphicHeight,graphicXOffset:this.defaultStyle.graphicXOffset,graphicYOffset:this.defaultStyle.graphicYOffset});}} +return this.createLiterals(OpenLayers.Util.extend(style,symbolizer),feature);},createLiterals:function(style,feature){var context=OpenLayers.Util.extend({},feature.attributes||feature.data);OpenLayers.Util.extend(context,this.context);for(var i in this.propertyStyles){style[i]=OpenLayers.Style.createLiteral(style[i],context,feature,i);} +return style;},findPropertyStyles:function(){var propertyStyles={};var style=this.defaultStyle;this.addPropertyStyles(propertyStyles,style);var rules=this.rules;var symbolizer,value;for(var i=0,len=rules.length;i<len;i++){symbolizer=rules[i].symbolizer;for(var key in symbolizer){value=symbolizer[key];if(typeof value=="object"){this.addPropertyStyles(propertyStyles,value);}else{this.addPropertyStyles(propertyStyles,symbolizer);break;}}} +return propertyStyles;},addPropertyStyles:function(propertyStyles,symbolizer){var property;for(var key in symbolizer){property=symbolizer[key];if(typeof property=="string"&&property.match(/\$\{\w+\}/)){propertyStyles[key]=true;}} +return propertyStyles;},addRules:function(rules){Array.prototype.push.apply(this.rules,rules);this.propertyStyles=this.findPropertyStyles();},setDefaultStyle:function(style){this.defaultStyle=style;this.propertyStyles=this.findPropertyStyles();},getSymbolizerPrefix:function(geometry){var prefixes=OpenLayers.Style.SYMBOLIZER_PREFIXES;for(var i=0,len=prefixes.length;i<len;i++){if(geometry.CLASS_NAME.indexOf(prefixes[i])!=-1){return prefixes[i];}}},clone:function(){var options=OpenLayers.Util.extend({},this);if(this.rules){options.rules=[];for(var i=0,len=this.rules.length;i<len;++i){options.rules.push(this.rules[i].clone());}} +options.context=this.context&&OpenLayers.Util.extend({},this.context);var defaultStyle=OpenLayers.Util.extend({},this.defaultStyle);return new OpenLayers.Style(defaultStyle,options);},CLASS_NAME:"OpenLayers.Style"});OpenLayers.Style.createLiteral=function(value,context,feature,property){if(typeof value=="string"&&value.indexOf("${")!=-1){value=OpenLayers.String.format(value,context,[feature,property]);value=(isNaN(value)||!value)?value:parseFloat(value);} +return value;};OpenLayers.Style.SYMBOLIZER_PREFIXES=['Point','Line','Polygon','Text','Raster'];OpenLayers.Control.Navigation=OpenLayers.Class(OpenLayers.Control,{dragPan:null,dragPanOptions:null,documentDrag:false,zoomBox:null,zoomBoxEnabled:true,zoomWheelEnabled:true,mouseWheelOptions:null,handleRightClicks:false,zoomBoxKeyMask:OpenLayers.Handler.MOD_SHIFT,autoActivate:true,initialize:function(options){this.handlers={};OpenLayers.Control.prototype.initialize.apply(this,arguments);},destroy:function(){this.deactivate();if(this.dragPan){this.dragPan.destroy();} +this.dragPan=null;if(this.zoomBox){this.zoomBox.destroy();} +this.zoomBox=null;OpenLayers.Control.prototype.destroy.apply(this,arguments);},activate:function(){this.dragPan.activate();if(this.zoomWheelEnabled){this.handlers.wheel.activate();} +this.handlers.click.activate();if(this.zoomBoxEnabled){this.zoomBox.activate();} +return OpenLayers.Control.prototype.activate.apply(this,arguments);},deactivate:function(){this.zoomBox.deactivate();this.dragPan.deactivate();this.handlers.click.deactivate();this.handlers.wheel.deactivate();return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},draw:function(){if(this.handleRightClicks){this.map.viewPortDiv.oncontextmenu=OpenLayers.Function.False;} +var clickCallbacks={'dblclick':this.defaultDblClick,'dblrightclick':this.defaultDblRightClick};var clickOptions={'double':true,'stopDouble':true};this.handlers.click=new OpenLayers.Handler.Click(this,clickCallbacks,clickOptions);this.dragPan=new OpenLayers.Control.DragPan(OpenLayers.Util.extend({map:this.map,documentDrag:this.documentDrag},this.dragPanOptions));this.zoomBox=new OpenLayers.Control.ZoomBox({map:this.map,keyMask:this.zoomBoxKeyMask});this.dragPan.draw();this.zoomBox.draw();this.handlers.wheel=new OpenLayers.Handler.MouseWheel(this,{"up":this.wheelUp,"down":this.wheelDown},this.mouseWheelOptions);},defaultDblClick:function(evt){var newCenter=this.map.getLonLatFromViewPortPx(evt.xy);this.map.setCenter(newCenter,this.map.zoom+1);},defaultDblRightClick:function(evt){var newCenter=this.map.getLonLatFromViewPortPx(evt.xy);this.map.setCenter(newCenter,this.map.zoom-1);},wheelChange:function(evt,deltaZ){var currentZoom=this.map.getZoom();var newZoom=this.map.getZoom()+Math.round(deltaZ);newZoom=Math.max(newZoom,0);newZoom=Math.min(newZoom,this.map.getNumZoomLevels());if(newZoom===currentZoom){return;} +var size=this.map.getSize();var deltaX=size.w/2-evt.xy.x;var deltaY=evt.xy.y-size.h/2;var newRes=this.map.baseLayer.getResolutionForZoom(newZoom);var zoomPoint=this.map.getLonLatFromPixel(evt.xy);var newCenter=new OpenLayers.LonLat(zoomPoint.lon+deltaX*newRes,zoomPoint.lat+deltaY*newRes);this.map.setCenter(newCenter,newZoom);},wheelUp:function(evt,delta){this.wheelChange(evt,delta||1);},wheelDown:function(evt,delta){this.wheelChange(evt,delta||-1);},disableZoomBox:function(){this.zoomBoxEnabled=false;this.zoomBox.deactivate();},enableZoomBox:function(){this.zoomBoxEnabled=true;if(this.active){this.zoomBox.activate();}},disableZoomWheel:function(){this.zoomWheelEnabled=false;this.handlers.wheel.deactivate();},enableZoomWheel:function(){this.zoomWheelEnabled=true;if(this.active){this.handlers.wheel.activate();}},CLASS_NAME:"OpenLayers.Control.Navigation"});OpenLayers.Filter=OpenLayers.Class({initialize:function(options){OpenLayers.Util.extend(this,options);},destroy:function(){},evaluate:function(context){return true;},clone:function(){return null;},CLASS_NAME:"OpenLayers.Filter"});OpenLayers.Format.WMC.v1_0_0=OpenLayers.Class(OpenLayers.Format.WMC.v1,{VERSION:"1.0.0",schemaLocation:"http://www.opengis.net/context http://schemas.opengis.net/context/1.0.0/context.xsd",initialize:function(options){OpenLayers.Format.WMC.v1.prototype.initialize.apply(this,[options]);},write_wmc_Layer:function(context){var node=OpenLayers.Format.WMC.v1.prototype.write_wmc_Layer.apply(this,[context]);node.appendChild(this.write_wmc_FormatList(context));node.appendChild(this.write_wmc_StyleList(context));node.appendChild(this.write_wmc_LayerExtension(context));},CLASS_NAME:"OpenLayers.Format.WMC.v1_0_0"});OpenLayers.Format.WMC.v1_1_0=OpenLayers.Class(OpenLayers.Format.WMC.v1,{VERSION:"1.1.0",schemaLocation:"http://www.opengis.net/context http://schemas.opengis.net/context/1.1.0/context.xsd",initialize:function(options){OpenLayers.Format.WMC.v1.prototype.initialize.apply(this,[options]);},read_sld_MinScaleDenominator:function(layerContext,node){var minScaleDenominator=parseFloat(this.getChildValue(node));if(minScaleDenominator>0){layerContext.maxScale=minScaleDenominator;}},read_sld_MaxScaleDenominator:function(layerContext,node){layerContext.minScale=parseFloat(this.getChildValue(node));},write_wmc_Layer:function(context){var node=OpenLayers.Format.WMC.v1.prototype.write_wmc_Layer.apply(this,[context]);if(context.maxScale){var minSD=this.createElementNS(this.namespaces.sld,"sld:MinScaleDenominator");minSD.appendChild(this.createTextNode(context.maxScale.toPrecision(16)));node.appendChild(minSD);} +if(context.minScale){var maxSD=this.createElementNS(this.namespaces.sld,"sld:MaxScaleDenominator");maxSD.appendChild(this.createTextNode(context.minScale.toPrecision(16)));node.appendChild(maxSD);} +node.appendChild(this.write_wmc_FormatList(context));node.appendChild(this.write_wmc_StyleList(context));node.appendChild(this.write_wmc_LayerExtension(context));return node;},CLASS_NAME:"OpenLayers.Format.WMC.v1_1_0"});OpenLayers.Format.WMSCapabilities.v1_1_0=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1_1,{version:"1.1.0",initialize:function(options){OpenLayers.Format.WMSCapabilities.v1_1.prototype.initialize.apply(this,[options]);},readers:{"wms":OpenLayers.Util.applyDefaults({"SRS":function(node,obj){var srs=this.getChildValue(node);var values=srs.split(/ +/);for(var i=0,len=values.length;i<len;i++){obj.srs[values[i]]=true;}}},OpenLayers.Format.WMSCapabilities.v1_1.prototype.readers["wms"])},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_1_0"});OpenLayers.Format.WMSCapabilities.v1_1_1=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1_1,{version:"1.1.1",initialize:function(options){OpenLayers.Format.WMSCapabilities.v1_1.prototype.initialize.apply(this,[options]);},readers:{"wms":OpenLayers.Util.applyDefaults({"SRS":function(node,obj){obj.srs[this.getChildValue(node)]=true;}},OpenLayers.Format.WMSCapabilities.v1_1.prototype.readers["wms"])},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_1_1"});OpenLayers.Format.WMSCapabilities.v1_3_0=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1_3,{version:"1.3.0",CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_3_0"});OpenLayers.Geometry=OpenLayers.Class({id:null,parent:null,bounds:null,initialize:function(){this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){this.id=null;this.bounds=null;},clone:function(){return new OpenLayers.Geometry();},setBounds:function(bounds){if(bounds){this.bounds=bounds.clone();}},clearBounds:function(){this.bounds=null;if(this.parent){this.parent.clearBounds();}},extendBounds:function(newBounds){var bounds=this.getBounds();if(!bounds){this.setBounds(newBounds);}else{this.bounds.extend(newBounds);}},getBounds:function(){if(this.bounds==null){this.calculateBounds();} +return this.bounds;},calculateBounds:function(){},distanceTo:function(geometry,options){},getVertices:function(nodes){},atPoint:function(lonlat,toleranceLon,toleranceLat){var atPoint=false;var bounds=this.getBounds();if((bounds!=null)&&(lonlat!=null)){var dX=(toleranceLon!=null)?toleranceLon:0;var dY=(toleranceLat!=null)?toleranceLat:0;var toleranceBounds=new OpenLayers.Bounds(this.bounds.left-dX,this.bounds.bottom-dY,this.bounds.right+dX,this.bounds.top+dY);atPoint=toleranceBounds.containsLonLat(lonlat);} +return atPoint;},getLength:function(){return 0.0;},getArea:function(){return 0.0;},getCentroid:function(){return null;},toString:function(){return OpenLayers.Format.WKT.prototype.write(new OpenLayers.Feature.Vector(this));},CLASS_NAME:"OpenLayers.Geometry"});OpenLayers.Geometry.fromWKT=function(wkt){var format=arguments.callee.format;if(!format){format=new OpenLayers.Format.WKT();arguments.callee.format=format;} +var geom;var result=format.read(wkt);if(result instanceof OpenLayers.Feature.Vector){geom=result.geometry;}else if(result instanceof Array){var len=result.length;var components=new Array(len);for(var i=0;i<len;++i){components[i]=result[i].geometry;} +geom=new OpenLayers.Geometry.Collection(components);} +return geom;};OpenLayers.Geometry.segmentsIntersect=function(seg1,seg2,options){var point=options&&options.point;var tolerance=options&&options.tolerance;var intersection=false;var x11_21=seg1.x1-seg2.x1;var y11_21=seg1.y1-seg2.y1;var x12_11=seg1.x2-seg1.x1;var y12_11=seg1.y2-seg1.y1;var y22_21=seg2.y2-seg2.y1;var x22_21=seg2.x2-seg2.x1;var d=(y22_21*x12_11)-(x22_21*y12_11);var n1=(x22_21*y11_21)-(y22_21*x11_21);var n2=(x12_11*y11_21)-(y12_11*x11_21);if(d==0){if(n1==0&&n2==0){intersection=true;}}else{var along1=n1/d;var along2=n2/d;if(along1>=0&&along1<=1&&along2>=0&&along2<=1){if(!point){intersection=true;}else{var x=seg1.x1+(along1*x12_11);var y=seg1.y1+(along1*y12_11);intersection=new OpenLayers.Geometry.Point(x,y);}}} +if(tolerance){var dist;if(intersection){if(point){var segs=[seg1,seg2];var seg,x,y;outer:for(var i=0;i<2;++i){seg=segs[i];for(var j=1;j<3;++j){x=seg["x"+j];y=seg["y"+j];dist=Math.sqrt(Math.pow(x-intersection.x,2)+ +Math.pow(y-intersection.y,2));if(dist<tolerance){intersection.x=x;intersection.y=y;break outer;}}}}}else{var segs=[seg1,seg2];var source,target,x,y,p,result;outer:for(var i=0;i<2;++i){source=segs[i];target=segs[(i+1)%2];for(var j=1;j<3;++j){p={x:source["x"+j],y:source["y"+j]};result=OpenLayers.Geometry.distanceToSegment(p,target);if(result.distance<tolerance){if(point){intersection=new OpenLayers.Geometry.Point(p.x,p.y);}else{intersection=true;} +break outer;}}}}} +return intersection;};OpenLayers.Geometry.distanceToSegment=function(point,segment){var x0=point.x;var y0=point.y;var x1=segment.x1;var y1=segment.y1;var x2=segment.x2;var y2=segment.y2;var dx=x2-x1;var dy=y2-y1;var along=((dx*(x0-x1))+(dy*(y0-y1)))/(Math.pow(dx,2)+Math.pow(dy,2));var x,y;if(along<=0.0){x=x1;y=y1;}else if(along>=1.0){x=x2;y=y2;}else{x=x1+along*dx;y=y1+along*dy;} +return{distance:Math.sqrt(Math.pow(x-x0,2)+Math.pow(y-y0,2)),x:x,y:y};};OpenLayers.Layer.ArcGIS93Rest=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{format:"png"},isBaseLayer:true,initialize:function(name,url,params,options){var newArguments=[];params=OpenLayers.Util.upperCaseObject(params);newArguments.push(name,url,params,options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);OpenLayers.Util.applyDefaults(this.params,OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS));if(this.params.TRANSPARENT&&this.params.TRANSPARENT.toString().toLowerCase()=="true"){if((options==null)||(!options.isBaseLayer)){this.isBaseLayer=false;} +if(this.params.FORMAT=="jpg"){this.params.FORMAT=OpenLayers.Util.alphaHack()?"gif":"png";}}},destroy:function(){OpenLayers.Layer.Grid.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.ArcGIS93Rest(this.name,this.url,this.params,this.getOptions());} +obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){bounds=this.adjustBounds(bounds);var projWords=this.projection.getCode().split(":");var srid=projWords[projWords.length-1];var imageSize=this.getImageSize();var newParams={'BBOX':bounds.toBBOX(),'SIZE':imageSize.w+","+imageSize.h,'F':"image",'BBOXSR':srid,'IMAGESR':srid};if(this.layerDefs){var layerDefStrList=[];var layerID;for(layerID in this.layerDefs){if(this.layerDefs.hasOwnProperty(layerID)){if(this.layerDefs[layerID]){layerDefStrList.push(layerID);layerDefStrList.push(":");layerDefStrList.push(this.layerDefs[layerID]);layerDefStrList.push(";");}}} +if(layerDefStrList.length>0){newParams['LAYERDEFS']=layerDefStrList.join("");}} +var requestString=this.getFullRequestString(newParams);return requestString;},setLayerFilter:function(id,queryDef){if(!this.layerDefs){this.layerDefs={};} +if(queryDef){this.layerDefs[id]=queryDef;}else{delete this.layerDefs[id];}},clearLayerFilter:function(id){if(id){delete this.layerDefs[id];}else{delete this.layerDefs;}},mergeNewParams:function(newParams){var upperParams=OpenLayers.Util.upperCaseObject(newParams);var newArguments=[upperParams];return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(this,newArguments);},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},CLASS_NAME:"OpenLayers.Layer.ArcGIS93Rest"});OpenLayers.Layer.Google.v3={DEFAULTS:{maxExtent:new OpenLayers.Bounds(-128*156543.0339,-128*156543.0339,128*156543.0339,128*156543.0339),sphericalMercator:true,maxResolution:156543.0339,units:"m",projection:"EPSG:900913"},loadMapObject:function(){if(!this.type){this.type=google.maps.MapTypeId.ROADMAP;} +var mapObject;var cache=OpenLayers.Layer.Google.cache[this.map.id];if(cache){mapObject=cache.mapObject;++cache.count;}else{var container=this.map.viewPortDiv;var div=document.createElement("div");div.id=this.map.id+"_GMapContainer";div.style.position="absolute";div.style.width="100%";div.style.height="100%";container.appendChild(div);var center=this.map.getCenter();mapObject=new google.maps.Map(div,{center:center?new google.maps.LatLng(center.lat,center.lon):new google.maps.LatLng(0,0),zoom:this.map.getZoom()||0,mapTypeId:this.type,disableDefaultUI:true,keyboardShortcuts:false,draggable:false,disableDoubleClickZoom:true,scrollwheel:false});cache={mapObject:mapObject,count:1};OpenLayers.Layer.Google.cache[this.map.id]=cache;this.repositionListener=google.maps.event.addListenerOnce(mapObject,"center_changed",OpenLayers.Function.bind(this.repositionMapElements,this));} +this.mapObject=mapObject;this.setGMapVisibility(this.visibility);},repositionMapElements:function(){google.maps.event.trigger(this.mapObject,"resize");var div=this.mapObject.getDiv().firstChild;if(!div||div.childNodes.length<3){this.repositionTimer=window.setTimeout(OpenLayers.Function.bind(this.repositionMapElements,this),250);return false;} +var cache=OpenLayers.Layer.Google.cache[this.map.id];var container=this.map.viewPortDiv;var termsOfUse=div.lastChild;container.appendChild(termsOfUse);termsOfUse.style.zIndex="1100";termsOfUse.style.bottom="";termsOfUse.className="olLayerGoogleCopyright olLayerGoogleV3";termsOfUse.style.display="";cache.termsOfUse=termsOfUse;var poweredBy=div.lastChild;container.appendChild(poweredBy);poweredBy.style.zIndex="1100";poweredBy.style.bottom="";poweredBy.className="olLayerGooglePoweredBy olLayerGoogleV3 gmnoprint";poweredBy.style.display="";cache.poweredBy=poweredBy;this.setGMapVisibility(this.visibility);},onMapResize:function(){if(this.visibility){google.maps.event.trigger(this.mapObject,"resize");}else{if(!this._resized){var layer=this;google.maps.event.addListenerOnce(this.mapObject,"tilesloaded",function(){delete layer._resized;google.maps.event.trigger(layer.mapObject,"resize");layer.moveTo(layer.map.getCenter(),layer.map.getZoom());});} +this._resized=true;}},setGMapVisibility:function(visible){var cache=OpenLayers.Layer.Google.cache[this.map.id];if(cache){var type=this.type;var layers=this.map.layers;var layer;for(var i=layers.length-1;i>=0;--i){layer=layers[i];if(layer instanceof OpenLayers.Layer.Google&&layer.visibility===true&&layer.inRange===true){type=layer.type;visible=true;break;}} +var container=this.mapObject.getDiv();if(visible===true){this.mapObject.setMapTypeId(type);container.style.left="";if(cache.termsOfUse&&cache.termsOfUse.style){cache.termsOfUse.style.left="";cache.termsOfUse.style.display="";cache.poweredBy.style.display="";} +cache.displayed=this.id;}else{delete cache.displayed;container.style.left="-9999px";if(cache.termsOfUse&&cache.termsOfUse.style){cache.termsOfUse.style.display="none";cache.termsOfUse.style.left="-9999px";cache.poweredBy.style.display="none";}}}},getMapContainer:function(){return this.mapObject.getDiv();},getMapObjectBoundsFromOLBounds:function(olBounds){var moBounds=null;if(olBounds!=null){var sw=this.sphericalMercator?this.inverseMercator(olBounds.bottom,olBounds.left):new OpenLayers.LonLat(olBounds.bottom,olBounds.left);var ne=this.sphericalMercator?this.inverseMercator(olBounds.top,olBounds.right):new OpenLayers.LonLat(olBounds.top,olBounds.right);moBounds=new google.maps.LatLngBounds(new google.maps.LatLng(sw.lat,sw.lon),new google.maps.LatLng(ne.lat,ne.lon));} +return moBounds;},getMapObjectLonLatFromMapObjectPixel:function(moPixel){var size=this.map.getSize();var lon=this.getLongitudeFromMapObjectLonLat(this.mapObject.center);var lat=this.getLatitudeFromMapObjectLonLat(this.mapObject.center);var res=this.map.getResolution();var delta_x=moPixel.x-(size.w/2);var delta_y=moPixel.y-(size.h/2);var lonlat=new OpenLayers.LonLat(lon+delta_x*res,lat-delta_y*res);if(this.wrapDateLine){lonlat=lonlat.wrapDateLine(this.maxExtent);} +return this.getMapObjectLonLatFromLonLat(lonlat.lon,lonlat.lat);},getMapObjectPixelFromMapObjectLonLat:function(moLonLat){var lon=this.getLongitudeFromMapObjectLonLat(moLonLat);var lat=this.getLatitudeFromMapObjectLonLat(moLonLat);var res=this.map.getResolution();var extent=this.map.getExtent();var px=new OpenLayers.Pixel((1/res*(lon-extent.left)),(1/res*(extent.top-lat)));return this.getMapObjectPixelFromXY(px.x,px.y);},setMapObjectCenter:function(center,zoom){this.mapObject.setOptions({center:center,zoom:zoom});},getMapObjectZoomFromMapObjectBounds:function(moBounds){return this.mapObject.getBoundsZoomLevel(moBounds);},getMapObjectLonLatFromLonLat:function(lon,lat){var gLatLng;if(this.sphericalMercator){var lonlat=this.inverseMercator(lon,lat);gLatLng=new google.maps.LatLng(lonlat.lat,lonlat.lon);}else{gLatLng=new google.maps.LatLng(lat,lon);} +return gLatLng;},getMapObjectPixelFromXY:function(x,y){return new google.maps.Point(x,y);},destroy:function(){if(this.repositionListener){google.maps.event.removeListener(this.repositionListener);} +if(this.repositionTimer){window.clearTimeout(this.repositionTimer);} +OpenLayers.Layer.Google.prototype.destroy.apply(this,arguments);}};OpenLayers.Layer.KaMap=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:true,units:null,resolution:OpenLayers.DOTS_PER_INCH,DEFAULT_PARAMS:{i:'jpeg',map:''},initialize:function(name,url,params,options){var newArguments=[];newArguments.push(name,url,params,options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);this.params=OpenLayers.Util.applyDefaults(this.params,this.DEFAULT_PARAMS);},getURL:function(bounds){bounds=this.adjustBounds(bounds);var mapRes=this.map.getResolution();var scale=Math.round((this.map.getScale()*10000))/10000;var pX=Math.round(bounds.left/mapRes);var pY=-Math.round(bounds.top/mapRes);return this.getFullRequestString({t:pY,l:pX,s:scale});},addTile:function(bounds,position){var url=this.getURL(bounds);return new OpenLayers.Tile.Image(this,position,bounds,url,this.tileSize);},calculateGridLayout:function(bounds,extent,resolution){var tilelon=resolution*this.tileSize.w;var tilelat=resolution*this.tileSize.h;var offsetlon=bounds.left;var tilecol=Math.floor(offsetlon/tilelon)-this.buffer;var tilecolremain=offsetlon/tilelon-tilecol;var tileoffsetx=-tilecolremain*this.tileSize.w;var tileoffsetlon=tilecol*tilelon;var offsetlat=bounds.top;var tilerow=Math.ceil(offsetlat/tilelat)+this.buffer;var tilerowremain=tilerow-offsetlat/tilelat;var tileoffsety=-(tilerowremain+1)*this.tileSize.h;var tileoffsetlat=tilerow*tilelat;return{tilelon:tilelon,tilelat:tilelat,tileoffsetlon:tileoffsetlon,tileoffsetlat:tileoffsetlat,tileoffsetx:tileoffsetx,tileoffsety:tileoffsety};},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.KaMap(this.name,this.url,this.params,this.getOptions());} +obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);if(this.tileSize!=null){obj.tileSize=this.tileSize.clone();} +obj.grid=[];return obj;},getTileBounds:function(viewPortPx){var resolution=this.getResolution();var tileMapWidth=resolution*this.tileSize.w;var tileMapHeight=resolution*this.tileSize.h;var mapPoint=this.getLonLatFromViewPortPx(viewPortPx);var tileLeft=tileMapWidth*Math.floor(mapPoint.lon/tileMapWidth);var tileBottom=tileMapHeight*Math.floor(mapPoint.lat/tileMapHeight);return new OpenLayers.Bounds(tileLeft,tileBottom,tileLeft+tileMapWidth,tileBottom+tileMapHeight);},CLASS_NAME:"OpenLayers.Layer.KaMap"});OpenLayers.Layer.MapGuide=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:true,useHttpTile:false,singleTile:false,useOverlay:false,useAsyncOverlay:true,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),initialize:function(name,url,params,options){OpenLayers.Layer.Grid.prototype.initialize.apply(this,arguments);if(options==null||options.isBaseLayer==null){this.isBaseLayer=((this.transparent!="true")&&(this.transparent!=true));} +if(options&&options.useOverlay!=null){this.useOverlay=options.useOverlay;} +if(this.singleTile){if(this.useOverlay){OpenLayers.Util.applyDefaults(this.params,this.OVERLAY_PARAMS);if(!this.useAsyncOverlay){this.params.version="1.0.0";}}else{OpenLayers.Util.applyDefaults(this.params,this.SINGLE_TILE_PARAMS);}}else{if(this.useHttpTile){OpenLayers.Util.applyDefaults(this.params,this.FOLDER_PARAMS);}else{OpenLayers.Util.applyDefaults(this.params,this.TILE_PARAMS);} +this.setTileSize(this.defaultSize);}},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.MapGuide(this.name,this.url,this.params,this.getOptions());} +obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},getURL:function(bounds){var url;var center=bounds.getCenterLonLat();var mapSize=this.map.getSize();if(this.singleTile){var params={setdisplaydpi:OpenLayers.DOTS_PER_INCH,setdisplayheight:mapSize.h*this.ratio,setdisplaywidth:mapSize.w*this.ratio,setviewcenterx:center.lon,setviewcentery:center.lat,setviewscale:this.map.getScale()};if(this.useOverlay&&!this.useAsyncOverlay){var getVisParams={};getVisParams=OpenLayers.Util.extend(getVisParams,params);getVisParams.operation="GETVISIBLEMAPEXTENT";getVisParams.version="1.0.0";getVisParams.session=this.params.session;getVisParams.mapName=this.params.mapName;getVisParams.format='text/xml';url=this.getFullRequestString(getVisParams);OpenLayers.Request.GET({url:url,async:false});} +url=this.getFullRequestString(params);}else{var currentRes=this.map.getResolution();var colidx=Math.floor((bounds.left-this.maxExtent.left)/currentRes);colidx=Math.round(colidx/this.tileSize.w);var rowidx=Math.floor((this.maxExtent.top-bounds.top)/currentRes);rowidx=Math.round(rowidx/this.tileSize.h);if(this.useHttpTile){url=this.getImageFilePath({tilecol:colidx,tilerow:rowidx,scaleindex:this.resolutions.length-this.map.zoom-1});}else{url=this.getFullRequestString({tilecol:colidx,tilerow:rowidx,scaleindex:this.resolutions.length-this.map.zoom-1});}} +return url;},getFullRequestString:function(newParams,altUrl){var url=(altUrl==null)?this.url:altUrl;if(typeof url=="object"){url=url[Math.floor(Math.random()*url.length)];} +var requestString=url;var allParams=OpenLayers.Util.extend({},this.params);allParams=OpenLayers.Util.extend(allParams,newParams);var urlParams=OpenLayers.Util.upperCaseObject(OpenLayers.Util.getParameters(url));for(var key in allParams){if(key.toUpperCase()in urlParams){delete allParams[key];}} +var paramsString=OpenLayers.Util.getParameterString(allParams);paramsString=paramsString.replace(/,/g,"+");if(paramsString!=""){var lastServerChar=url.charAt(url.length-1);if((lastServerChar=="&")||(lastServerChar=="?")){requestString+=paramsString;}else{if(url.indexOf('?')==-1){requestString+='?'+paramsString;}else{requestString+='&'+paramsString;}}} +return requestString;},getImageFilePath:function(newParams,altUrl){var url=(altUrl==null)?this.url:altUrl;if(typeof url=="object"){url=url[Math.floor(Math.random()*url.length)];} +var requestString=url;var tileRowGroup="";var tileColGroup="";if(newParams.tilerow<0){tileRowGroup='-';} +if(newParams.tilerow==0){tileRowGroup+='0';}else{tileRowGroup+=Math.floor(Math.abs(newParams.tilerow/this.params.tileRowsPerFolder))*this.params.tileRowsPerFolder;} +if(newParams.tilecol<0){tileColGroup='-';} +if(newParams.tilecol==0){tileColGroup+='0';}else{tileColGroup+=Math.floor(Math.abs(newParams.tilecol/this.params.tileColumnsPerFolder))*this.params.tileColumnsPerFolder;} +var tilePath='/S'+Math.floor(newParams.scaleindex) ++'/'+this.params.basemaplayergroupname ++'/R'+tileRowGroup ++'/C'+tileColGroup ++'/'+(newParams.tilerow%this.params.tileRowsPerFolder) ++'_'+(newParams.tilecol%this.params.tileColumnsPerFolder) ++'.'+this.params.format;if(this.params.querystring){tilePath+="?"+this.params.querystring;} +requestString+=tilePath;return requestString;},calculateGridLayout:function(bounds,extent,resolution){var tilelon=resolution*this.tileSize.w;var tilelat=resolution*this.tileSize.h;var offsetlon=bounds.left-extent.left;var tilecol=Math.floor(offsetlon/tilelon)-this.buffer;var tilecolremain=offsetlon/tilelon-tilecol;var tileoffsetx=-tilecolremain*this.tileSize.w;var tileoffsetlon=extent.left+tilecol*tilelon;var offsetlat=extent.top-bounds.top+tilelat;var tilerow=Math.floor(offsetlat/tilelat)-this.buffer;var tilerowremain=tilerow-offsetlat/tilelat;var tileoffsety=tilerowremain*this.tileSize.h;var tileoffsetlat=extent.top-tilelat*tilerow;return{tilelon:tilelon,tilelat:tilelat,tileoffsetlon:tileoffsetlon,tileoffsetlat:tileoffsetlat,tileoffsetx:tileoffsetx,tileoffsety:tileoffsety};},CLASS_NAME:"OpenLayers.Layer.MapGuide"});OpenLayers.Layer.MapServer=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{mode:"map",map_imagetype:"png"},initialize:function(name,url,params,options){var newArguments=[];newArguments.push(name,url,params,options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);this.params=OpenLayers.Util.applyDefaults(this.params,this.DEFAULT_PARAMS);if(options==null||options.isBaseLayer==null){this.isBaseLayer=((this.params.transparent!="true")&&(this.params.transparent!=true));}},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.MapServer(this.name,this.url,this.params,this.getOptions());} +obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},getURL:function(bounds){bounds=this.adjustBounds(bounds);var extent=[bounds.left,bounds.bottom,bounds.right,bounds.top];var imageSize=this.getImageSize();var url=this.getFullRequestString({mapext:extent,imgext:extent,map_size:[imageSize.w,imageSize.h],imgx:imageSize.w/2,imgy:imageSize.h/2,imgxy:[imageSize.w,imageSize.h]});return url;},getFullRequestString:function(newParams,altUrl){var url=(altUrl==null)?this.url:altUrl;var allParams=OpenLayers.Util.extend({},this.params);allParams=OpenLayers.Util.extend(allParams,newParams);var paramsString=OpenLayers.Util.getParameterString(allParams);if(url instanceof Array){url=this.selectUrl(paramsString,url);} +var urlParams=OpenLayers.Util.upperCaseObject(OpenLayers.Util.getParameters(url));for(var key in allParams){if(key.toUpperCase()in urlParams){delete allParams[key];}} +paramsString=OpenLayers.Util.getParameterString(allParams);var requestString=url;paramsString=paramsString.replace(/,/g,"+");if(paramsString!=""){var lastServerChar=url.charAt(url.length-1);if((lastServerChar=="&")||(lastServerChar=="?")){requestString+=paramsString;}else{if(url.indexOf('?')==-1){requestString+='?'+paramsString;}else{requestString+='&'+paramsString;}}} +return requestString;},CLASS_NAME:"OpenLayers.Layer.MapServer"});OpenLayers.Layer.TMS=OpenLayers.Class(OpenLayers.Layer.Grid,{serviceVersion:"1.0.0",isBaseLayer:true,tileOrigin:null,serverResolutions:null,zoomOffset:0,initialize:function(name,url,options){var newArguments=[];newArguments.push(name,url,{},options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);},destroy:function(){OpenLayers.Layer.Grid.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.TMS(this.name,this.url,this.getOptions());} +obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){bounds=this.adjustBounds(bounds);var res=this.map.getResolution();var x=Math.round((bounds.left-this.tileOrigin.lon)/(res*this.tileSize.w));var y=Math.round((bounds.bottom-this.tileOrigin.lat)/(res*this.tileSize.h));var z=this.serverResolutions!=null?OpenLayers.Util.indexOf(this.serverResolutions,res):this.map.getZoom()+this.zoomOffset;var path=this.serviceVersion+"/"+this.layername+"/"+z+"/"+x+"/"+y+"."+this.type;var url=this.url;if(url instanceof Array){url=this.selectUrl(path,url);} +return url+path;},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},setMap:function(map){OpenLayers.Layer.Grid.prototype.setMap.apply(this,arguments);if(!this.tileOrigin){this.tileOrigin=new OpenLayers.LonLat(this.map.maxExtent.left,this.map.maxExtent.bottom);}},CLASS_NAME:"OpenLayers.Layer.TMS"});OpenLayers.Layer.TileCache=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:true,format:'image/png',serverResolutions:null,initialize:function(name,url,layername,options){this.layername=layername;OpenLayers.Layer.Grid.prototype.initialize.apply(this,[name,url,{},options]);this.extension=this.format.split('/')[1].toLowerCase();this.extension=(this.extension=='jpg')?'jpeg':this.extension;},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.TileCache(this.name,this.url,this.layername,this.getOptions());} +obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){var res=this.map.getResolution();var bbox=this.maxExtent;var size=this.tileSize;var tileX=Math.round((bounds.left-bbox.left)/(res*size.w));var tileY=Math.round((bounds.bottom-bbox.bottom)/(res*size.h));var tileZ=this.serverResolutions!=null?OpenLayers.Util.indexOf(this.serverResolutions,res):this.map.getZoom();function zeroPad(number,length){number=String(number);var zeros=[];for(var i=0;i<length;++i){zeros.push('0');} +return zeros.join('').substring(0,length-number.length)+number;} +var components=[this.layername,zeroPad(tileZ,2),zeroPad(parseInt(tileX/1000000),3),zeroPad((parseInt(tileX/1000)%1000),3),zeroPad((parseInt(tileX)%1000),3),zeroPad(parseInt(tileY/1000000),3),zeroPad((parseInt(tileY/1000)%1000),3),zeroPad((parseInt(tileY)%1000),3)+'.'+this.extension];var path=components.join('/');var url=this.url;if(url instanceof Array){url=this.selectUrl(path,url);} +url=(url.charAt(url.length-1)=='/')?url:url+'/';return url+path;},addTile:function(bounds,position){var url=this.getURL(bounds);return new OpenLayers.Tile.Image(this,position,bounds,url,this.tileSize);},CLASS_NAME:"OpenLayers.Layer.TileCache"});OpenLayers.Layer.WMS=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{service:"WMS",version:"1.1.1",request:"GetMap",styles:"",exceptions:"application/vnd.ogc.se_inimage",format:"image/jpeg"},reproject:false,isBaseLayer:true,encodeBBOX:false,noMagic:false,yx:{'EPSG:4326':true},initialize:function(name,url,params,options){var newArguments=[];params=OpenLayers.Util.upperCaseObject(params);if(parseFloat(params.VERSION)>=1.3&&!params.EXCEPTIONS){params.EXCEPTIONS="INIMAGE";} +newArguments.push(name,url,params,options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);OpenLayers.Util.applyDefaults(this.params,OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS));if(!this.noMagic&&this.params.TRANSPARENT&&this.params.TRANSPARENT.toString().toLowerCase()=="true"){if((options==null)||(!options.isBaseLayer)){this.isBaseLayer=false;} +if(this.params.FORMAT=="image/jpeg"){this.params.FORMAT=OpenLayers.Util.alphaHack()?"image/gif":"image/png";}}},destroy:function(){OpenLayers.Layer.Grid.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.WMS(this.name,this.url,this.params,this.getOptions());} +obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},reverseAxisOrder:function(){return(parseFloat(this.params.VERSION)>=1.3&&!!this.yx[this.map.getProjectionObject().getCode()]);},getURL:function(bounds){bounds=this.adjustBounds(bounds);var imageSize=this.getImageSize();var newParams={};var reverseAxisOrder=this.reverseAxisOrder();newParams.BBOX=this.encodeBBOX?bounds.toBBOX(null,reverseAxisOrder):bounds.toArray(reverseAxisOrder);newParams.WIDTH=imageSize.w;newParams.HEIGHT=imageSize.h;var requestString=this.getFullRequestString(newParams);return requestString;},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},mergeNewParams:function(newParams){var upperParams=OpenLayers.Util.upperCaseObject(newParams);var newArguments=[upperParams];return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(this,newArguments);},getFullRequestString:function(newParams,altUrl){var projectionCode=this.map.getProjection();var value=(projectionCode=="none")?null:projectionCode +if(parseFloat(this.params.VERSION)>=1.3){this.params.CRS=value;}else{this.params.SRS=value;} +return OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(this,arguments);},CLASS_NAME:"OpenLayers.Layer.WMS"});OpenLayers.Layer.WMTS=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:true,version:"1.0.0",requestEncoding:"KVP",url:null,layer:null,matrixSet:null,style:null,format:"image/jpeg",tileOrigin:null,tileFullExtent:null,formatSuffix:null,matrixIds:null,dimensions:null,params:null,zoomOffset:0,formatSuffixMap:{"image/png":"png","image/png8":"png","image/png24":"png","image/png32":"png","png":"png","image/jpeg":"jpg","image/jpg":"jpg","jpeg":"jpg","jpg":"jpg"},matrix:null,initialize:function(config){var required={url:true,layer:true,style:true,matrixSet:true};for(var prop in required){if(!(prop in config)){throw new Error("Missing property '"+prop+"' in layer configuration.");}} +config.params=OpenLayers.Util.upperCaseObject(config.params);var args=[config.name,config.url,config.params,config];OpenLayers.Layer.Grid.prototype.initialize.apply(this,args);if(!this.formatSuffix){this.formatSuffix=this.formatSuffixMap[this.format]||this.format.split("/").pop();} +if(this.matrixIds){var len=this.matrixIds.length;if(len&&typeof this.matrixIds[0]==="string"){var ids=this.matrixIds;this.matrixIds=new Array(len);for(var i=0;i<len;++i){this.matrixIds[i]={identifier:ids[i]};}}}},setMap:function(){OpenLayers.Layer.Grid.prototype.setMap.apply(this,arguments);this.updateMatrixProperties();},updateMatrixProperties:function(){this.matrix=this.getMatrix();if(this.matrix){if(this.matrix.topLeftCorner){this.tileOrigin=this.matrix.topLeftCorner;} +if(this.matrix.tileWidth&&this.matrix.tileHeight){this.tileSize=new OpenLayers.Size(this.matrix.tileWidth,this.matrix.tileHeight);} +if(!this.tileOrigin){this.tileOrigin=new OpenLayers.LonLat(this.maxExtent.left,this.maxExtent.top);} +if(!this.tileFullExtent){this.tileFullExtent=this.maxExtent;}}},moveTo:function(bounds,zoomChanged,dragging){if(zoomChanged||!this.matrix){this.updateMatrixProperties();} +return OpenLayers.Layer.Grid.prototype.moveTo.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.WMTS(this.options);} +obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getMatrix:function(){var matrix;if(!this.matrixIds||this.matrixIds.length===0){matrix={identifier:this.map.getZoom()+this.zoomOffset};}else{if("scaleDenominator"in this.matrixIds[0]){var denom=OpenLayers.METERS_PER_INCH*OpenLayers.INCHES_PER_UNIT[this.units]*this.map.getResolution()/0.28E-3;var diff=Number.POSITIVE_INFINITY;var delta;for(var i=0,ii=this.matrixIds.length;i<ii;++i){delta=Math.abs(1-(this.matrixIds[i].scaleDenominator/denom));if(delta<diff){diff=delta;matrix=this.matrixIds[i];}}}else{matrix=this.matrixIds[this.map.getZoom()+this.zoomOffset];}} +return matrix;},getTileInfo:function(loc){var res=this.map.getResolution();var fx=(loc.lon-this.tileOrigin.lon)/(res*this.tileSize.w);var fy=(this.tileOrigin.lat-loc.lat)/(res*this.tileSize.h);var col=Math.floor(fx);var row=Math.floor(fy);return{col:col,row:row,i:Math.floor((fx-col)*this.tileSize.w),j:Math.floor((fy-row)*this.tileSize.h)};},getURL:function(bounds){bounds=this.adjustBounds(bounds);var url="";if(!this.tileFullExtent||this.tileFullExtent.intersectsBounds(bounds)){var center=bounds.getCenterLonLat();var info=this.getTileInfo(center);var matrixId=this.matrix.identifier;if(this.requestEncoding.toUpperCase()==="REST"){var path=this.version+"/"+this.layer+"/"+this.style+"/";if(this.dimensions){for(var i=0;i<this.dimensions.length;i++){if(this.params[this.dimensions[i]]){path=path+this.params[this.dimensions[i]]+"/";}}} +path=path+this.matrixSet+"/"+this.matrix.identifier+"/"+info.row+"/"+info.col+"."+this.formatSuffix;if(this.url instanceof Array){url=this.selectUrl(path,this.url);}else{url=this.url;} +if(!url.match(/\/$/)){url=url+"/";} +url=url+path;}else if(this.requestEncoding.toUpperCase()==="KVP"){var params={SERVICE:"WMTS",REQUEST:"GetTile",VERSION:this.version,LAYER:this.layer,STYLE:this.style,TILEMATRIXSET:this.matrixSet,TILEMATRIX:this.matrix.identifier,TILEROW:info.row,TILECOL:info.col,FORMAT:this.format};url=OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(this,[params]);}} +return url;},mergeNewParams:function(newParams){if(this.requestEncoding.toUpperCase()==="KVP"){return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(this,[OpenLayers.Util.upperCaseObject(newParams)]);}},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},CLASS_NAME:"OpenLayers.Layer.WMTS"});OpenLayers.Layer.WorldWind=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{},isBaseLayer:true,lzd:null,zoomLevels:null,initialize:function(name,url,lzd,zoomLevels,params,options){this.lzd=lzd;this.zoomLevels=zoomLevels;var newArguments=[];newArguments.push(name,url,params,options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);this.params=OpenLayers.Util.applyDefaults(this.params,this.DEFAULT_PARAMS);},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},getZoom:function(){var zoom=this.map.getZoom();var extent=this.map.getMaxExtent();zoom=zoom-Math.log(this.maxResolution/(this.lzd/512))/Math.log(2);return zoom;},getURL:function(bounds){bounds=this.adjustBounds(bounds);var zoom=this.getZoom();var extent=this.map.getMaxExtent();var deg=this.lzd/Math.pow(2,this.getZoom());var x=Math.floor((bounds.left-extent.left)/deg);var y=Math.floor((bounds.bottom-extent.bottom)/deg);if(this.map.getResolution()<=(this.lzd/512)&&this.getZoom()<=this.zoomLevels){return this.getFullRequestString({L:zoom,X:x,Y:y});}else{return OpenLayers.Util.getImagesLocation()+"blank.gif";}},CLASS_NAME:"OpenLayers.Layer.WorldWind"});OpenLayers.Layer.XYZ=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:true,sphericalMercator:false,zoomOffset:0,initialize:function(name,url,options){if(options&&options.sphericalMercator||this.sphericalMercator){options=OpenLayers.Util.extend({maxExtent:new OpenLayers.Bounds(-128*156543.0339,-128*156543.0339,128*156543.0339,128*156543.0339),maxResolution:156543.0339,numZoomLevels:19,units:"m",projection:"EPSG:900913"},options);} +url=url||this.url;name=name||this.name;var newArguments=[name,url,{},options];OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.XYZ(this.name,this.url,this.getOptions());} +obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){var res=this.map.getResolution();var x=Math.round((bounds.left-this.maxExtent.left)/(res*this.tileSize.w));var y=Math.round((this.maxExtent.top-bounds.top)/(res*this.tileSize.h));var z=this.map.getZoom()+this.zoomOffset;var url=this.url;var s=''+x+y+z;if(url instanceof Array) +{url=this.selectUrl(s,url);} +var path=OpenLayers.String.format(url,{'x':x,'y':y,'z':z});return path;},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},setMap:function(map){OpenLayers.Layer.Grid.prototype.setMap.apply(this,arguments);if(!this.tileOrigin){this.tileOrigin=new OpenLayers.LonLat(this.maxExtent.left,this.maxExtent.bottom);}},CLASS_NAME:"OpenLayers.Layer.XYZ"});OpenLayers.Layer.OSM=OpenLayers.Class(OpenLayers.Layer.XYZ,{name:"OpenStreetMap",attribution:"Data CC-By-SA by <a href='http://openstreetmap.org/'>OpenStreetMap</a>",sphericalMercator:true,url:'http://tile.openstreetmap.org/${z}/${x}/${y}.png',clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.OSM(this.name,this.url,this.getOptions());} +obj=OpenLayers.Layer.XYZ.prototype.clone.apply(this,[obj]);return obj;},CLASS_NAME:"OpenLayers.Layer.OSM"});OpenLayers.Layer.Zoomify=OpenLayers.Class(OpenLayers.Layer.Grid,{url:null,size:null,isBaseLayer:true,standardTileSize:256,numberOfTiers:0,tileCountUpToTier:new Array(),tierSizeInTiles:new Array(),tierImageSize:new Array(),initialize:function(name,url,size,options){this.initializeZoomify(size);var newArguments=[];newArguments.push(name,url,size,{},options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);},initializeZoomify:function(size){var imageSize=size.clone() +var tiles=new OpenLayers.Size(Math.ceil(imageSize.w/this.standardTileSize),Math.ceil(imageSize.h/this.standardTileSize));this.tierSizeInTiles.push(tiles);this.tierImageSize.push(imageSize);while(imageSize.w>this.standardTileSize||imageSize.h>this.standardTileSize){imageSize=new OpenLayers.Size(Math.floor(imageSize.w/2),Math.floor(imageSize.h/2));tiles=new OpenLayers.Size(Math.ceil(imageSize.w/this.standardTileSize),Math.ceil(imageSize.h/this.standardTileSize));this.tierSizeInTiles.push(tiles);this.tierImageSize.push(imageSize);} +this.tierSizeInTiles.reverse();this.tierImageSize.reverse();this.numberOfTiers=this.tierSizeInTiles.length;this.tileCountUpToTier[0]=0;for(var i=1;i<this.numberOfTiers;i++){this.tileCountUpToTier.push(this.tierSizeInTiles[i-1].w*this.tierSizeInTiles[i-1].h+ +this.tileCountUpToTier[i-1]);}},destroy:function(){OpenLayers.Layer.Grid.prototype.destroy.apply(this,arguments);this.tileCountUpToTier.length=0 +this.tierSizeInTiles.length=0 +this.tierImageSize.length=0},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.Zoomify(this.name,this.url,this.size,this.options);} +obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){bounds=this.adjustBounds(bounds);var res=this.map.getResolution();var x=Math.round((bounds.left-this.tileOrigin.lon)/(res*this.tileSize.w));var y=Math.round((this.tileOrigin.lat-bounds.top)/(res*this.tileSize.h));var z=this.map.getZoom();var tileIndex=x+y*this.tierSizeInTiles[z].w+this.tileCountUpToTier[z];var path="TileGroup"+Math.floor((tileIndex)/256)+"/"+z+"-"+x+"-"+y+".jpg";var url=this.url;if(url instanceof Array){url=this.selectUrl(path,url);} +return url+path;},getImageSize:function(){if(arguments.length>0){bounds=this.adjustBounds(arguments[0]);var res=this.map.getResolution();var x=Math.round((bounds.left-this.tileOrigin.lon)/(res*this.tileSize.w));var y=Math.round((this.tileOrigin.lat-bounds.top)/(res*this.tileSize.h));var z=this.map.getZoom();var w=this.standardTileSize;var h=this.standardTileSize;if(x==this.tierSizeInTiles[z].w-1){var w=this.tierImageSize[z].w%this.standardTileSize;};if(y==this.tierSizeInTiles[z].h-1){var h=this.tierImageSize[z].h%this.standardTileSize;};return(new OpenLayers.Size(w,h));}else{return this.tileSize;}},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},setMap:function(map){OpenLayers.Layer.Grid.prototype.setMap.apply(this,arguments);this.tileOrigin=new OpenLayers.LonLat(this.map.maxExtent.left,this.map.maxExtent.top);},calculateGridLayout:function(bounds,extent,resolution){var tilelon=resolution*this.tileSize.w;var tilelat=resolution*this.tileSize.h;var offsetlon=bounds.left-extent.left;var tilecol=Math.floor(offsetlon/tilelon)-this.buffer;var tilecolremain=offsetlon/tilelon-tilecol;var tileoffsetx=-tilecolremain*this.tileSize.w;var tileoffsetlon=extent.left+tilecol*tilelon;var offsetlat=extent.top-bounds.top+tilelat;var tilerow=Math.floor(offsetlat/tilelat)-this.buffer;var tilerowremain=tilerow-offsetlat/tilelat;var tileoffsety=tilerowremain*this.tileSize.h;var tileoffsetlat=extent.top-tilelat*tilerow;return{tilelon:tilelon,tilelat:tilelat,tileoffsetlon:tileoffsetlon,tileoffsetlat:tileoffsetlat,tileoffsetx:tileoffsetx,tileoffsety:tileoffsety};},CLASS_NAME:"OpenLayers.Layer.Zoomify"});OpenLayers.Protocol.SQL.Gears=OpenLayers.Class(OpenLayers.Protocol.SQL,{FID_PREFIX:'__gears_fid__',NULL_GEOMETRY:'__gears_null_geometry__',NULL_FEATURE_STATE:'__gears_null_feature_state__',jsonParser:null,wktParser:null,fidRegExp:null,saveFeatureState:true,typeOfFid:"string",db:null,initialize:function(options){if(!this.supported()){return;} +OpenLayers.Protocol.SQL.prototype.initialize.apply(this,[options]);this.jsonParser=new OpenLayers.Format.JSON();this.wktParser=new OpenLayers.Format.WKT();this.fidRegExp=new RegExp('^'+this.FID_PREFIX);this.initializeDatabase();},initializeDatabase:function(){this.db=google.gears.factory.create('beta.database');this.db.open(this.databaseName);this.db.execute("CREATE TABLE IF NOT EXISTS "+this.tableName+" (fid TEXT UNIQUE, geometry TEXT, properties TEXT,"+" state TEXT)");},destroy:function(){this.db.close();this.db=null;this.jsonParser=null;this.wktParser=null;OpenLayers.Protocol.SQL.prototype.destroy.apply(this);},supported:function(){return!!(window.google&&google.gears);},read:function(options){OpenLayers.Protocol.prototype.read.apply(this,arguments);options=OpenLayers.Util.applyDefaults(options,this.options);var feature,features=[];var rs=this.db.execute("SELECT * FROM "+this.tableName);while(rs.isValidRow()){feature=this.unfreezeFeature(rs);if(this.evaluateFilter(feature,options.filter)){if(!options.noFeatureStateReset){feature.state=null;} +features.push(feature);} +rs.next();} +rs.close();var resp=new OpenLayers.Protocol.Response({code:OpenLayers.Protocol.Response.SUCCESS,requestType:"read",features:features});if(options&&options.callback){options.callback.call(options.scope,resp);} +return resp;},unfreezeFeature:function(row){var feature;var wkt=row.fieldByName('geometry');if(wkt==this.NULL_GEOMETRY){feature=new OpenLayers.Feature.Vector();}else{feature=this.wktParser.read(wkt);} +feature.attributes=this.jsonParser.read(row.fieldByName('properties'));feature.fid=this.extractFidFromField(row.fieldByName('fid'));var state=row.fieldByName('state');if(state==this.NULL_FEATURE_STATE){state=null;} +feature.state=state;return feature;},extractFidFromField:function(field){if(!field.match(this.fidRegExp)&&this.typeOfFid=="number"){field=parseFloat(field);} +return field;},create:function(features,options){options=OpenLayers.Util.applyDefaults(options,this.options);var resp=this.createOrUpdate(features);resp.requestType="create";if(options&&options.callback){options.callback.call(options.scope,resp);} +return resp;},update:function(features,options){options=OpenLayers.Util.applyDefaults(options,this.options);var resp=this.createOrUpdate(features);resp.requestType="update";if(options&&options.callback){options.callback.call(options.scope,resp);} +return resp;},createOrUpdate:function(features){if(!(features instanceof Array)){features=[features];} +var i,len=features.length,feature;var insertedFeatures=new Array(len);for(i=0;i<len;i++){feature=features[i];var params=this.freezeFeature(feature);this.db.execute("REPLACE INTO "+this.tableName+" (fid, geometry, properties, state)"+" VALUES (?, ?, ?, ?)",params);var clone=feature.clone();clone.fid=this.extractFidFromField(params[0]);insertedFeatures[i]=clone;} +return new OpenLayers.Protocol.Response({code:OpenLayers.Protocol.Response.SUCCESS,features:insertedFeatures,reqFeatures:features});},freezeFeature:function(feature){feature.fid=feature.fid!=null?""+feature.fid:OpenLayers.Util.createUniqueID(this.FID_PREFIX);var geometry=feature.geometry!=null?feature.geometry.toString():this.NULL_GEOMETRY;var properties=this.jsonParser.write(feature.attributes);var state=this.getFeatureStateForFreeze(feature);return[feature.fid,geometry,properties,state];},getFeatureStateForFreeze:function(feature){var state;if(!this.saveFeatureState){state=this.NULL_FEATURE_STATE;}else if(this.createdOffline(feature)){state=OpenLayers.State.INSERT;}else{state=feature.state;} +return state;},"delete":function(features,options){if(!(features instanceof Array)){features=[features];} +options=OpenLayers.Util.applyDefaults(options,this.options);var i,len,feature;for(i=0,len=features.length;i<len;i++){feature=features[i];if(this.saveFeatureState&&!this.createdOffline(feature)){var toDelete=feature.clone();toDelete.fid=feature.fid;if(toDelete.geometry){toDelete.geometry.destroy();toDelete.geometry=null;} +toDelete.state=feature.state;this.createOrUpdate(toDelete);}else{this.db.execute("DELETE FROM "+this.tableName+" WHERE fid = ?",[feature.fid]);}} +var resp=new OpenLayers.Protocol.Response({code:OpenLayers.Protocol.Response.SUCCESS,requestType:"delete",reqFeatures:features});if(options&&options.callback){options.callback.call(options.scope,resp);} +return resp;},createdOffline:function(feature){return(typeof feature.fid=="string"&&!!(feature.fid.match(this.fidRegExp)));},commit:function(features,options){var opt,resp=[],nRequests=0,nResponses=0;function callback(resp){if(++nResponses<nRequests){resp.last=false;} +this.callUserCallback(options,resp);} +var feature,toCreate=[],toUpdate=[],toDelete=[];for(var i=features.length-1;i>=0;i--){feature=features[i];switch(feature.state){case OpenLayers.State.INSERT:toCreate.push(feature);break;case OpenLayers.State.UPDATE:toUpdate.push(feature);break;case OpenLayers.State.DELETE:toDelete.push(feature);break;}} +if(toCreate.length>0){nRequests++;opt=OpenLayers.Util.applyDefaults({"callback":callback,"scope":this},options.create);resp.push(this.create(toCreate,opt));} +if(toUpdate.length>0){nRequests++;opt=OpenLayers.Util.applyDefaults({"callback":callback,"scope":this},options.update);resp.push(this.update(toUpdate,opt));} +if(toDelete.length>0){nRequests++;opt=OpenLayers.Util.applyDefaults({"callback":callback,"scope":this},options["delete"]);resp.push(this["delete"](toDelete,opt));} +return resp;},clear:function(){this.db.execute("DELETE FROM "+this.tableName);},callUserCallback:function(options,resp){var opt=options[resp.requestType];if(opt&&opt.callback){opt.callback.call(opt.scope,resp);} +if(resp.last&&options.callback){options.callback.call(options.scope);}},CLASS_NAME:"OpenLayers.Protocol.SQL.Gears"});OpenLayers.Rule=OpenLayers.Class({id:null,name:null,title:null,description:null,context:null,filter:null,elseFilter:false,symbolizer:null,symbolizers:null,minScaleDenominator:null,maxScaleDenominator:null,initialize:function(options){this.symbolizer={};OpenLayers.Util.extend(this,options);if(this.symbolizers){delete this.symbolizer;} +this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){for(var i in this.symbolizer){this.symbolizer[i]=null;} +this.symbolizer=null;delete this.symbolizers;},evaluate:function(feature){var context=this.getContext(feature);var applies=true;if(this.minScaleDenominator||this.maxScaleDenominator){var scale=feature.layer.map.getScale();} +if(this.minScaleDenominator){applies=scale>=OpenLayers.Style.createLiteral(this.minScaleDenominator,context);} +if(applies&&this.maxScaleDenominator){applies=scale<OpenLayers.Style.createLiteral(this.maxScaleDenominator,context);} +if(applies&&this.filter){if(this.filter.CLASS_NAME=="OpenLayers.Filter.FeatureId"){applies=this.filter.evaluate(feature);}else{applies=this.filter.evaluate(context);}} +return applies;},getContext:function(feature){var context=this.context;if(!context){context=feature.attributes||feature.data;} +if(typeof this.context=="function"){context=this.context(feature);} +return context;},clone:function(){var options=OpenLayers.Util.extend({},this);if(this.symbolizers){var len=this.symbolizers.length;options.symbolizers=new Array(len);for(var i=0;i<len;++i){options.symbolizers[i]=this.symbolizers[i].clone();}}else{options.symbolizer={};var value,type;for(var key in this.symbolizer){value=this.symbolizer[key];type=typeof value;if(type==="object"){options.symbolizer[key]=OpenLayers.Util.extend({},value);}else if(type==="string"){options.symbolizer[key]=value;}}} +options.filter=this.filter&&this.filter.clone();options.context=this.context&&OpenLayers.Util.extend({},this.context);return new OpenLayers.Rule(options);},CLASS_NAME:"OpenLayers.Rule"});OpenLayers.StyleMap=OpenLayers.Class({styles:null,extendDefault:true,initialize:function(style,options){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(style instanceof OpenLayers.Style){this.styles["default"]=style;this.styles["select"]=style;this.styles["temporary"]=style;this.styles["delete"]=style;}else if(typeof style=="object"){for(var key in style){if(style[key]instanceof OpenLayers.Style){this.styles[key]=style[key];}else if(typeof style[key]=="object"){this.styles[key]=new OpenLayers.Style(style[key]);}else{this.styles["default"]=new OpenLayers.Style(style);this.styles["select"]=new OpenLayers.Style(style);this.styles["temporary"]=new OpenLayers.Style(style);this.styles["delete"]=new OpenLayers.Style(style);break;}}} +OpenLayers.Util.extend(this,options);},destroy:function(){for(var key in this.styles){this.styles[key].destroy();} +this.styles=null;},createSymbolizer:function(feature,intent){if(!feature){feature=new OpenLayers.Feature.Vector();} +if(!this.styles[intent]){intent="default";} +feature.renderIntent=intent;var defaultSymbolizer={};if(this.extendDefault&&intent!="default"){defaultSymbolizer=this.styles["default"].createSymbolizer(feature);} +return OpenLayers.Util.extend(defaultSymbolizer,this.styles[intent].createSymbolizer(feature));},addUniqueValueRules:function(renderIntent,property,symbolizers,context){var rules=[];for(var value in symbolizers){rules.push(new OpenLayers.Rule({symbolizer:symbolizers[value],context:context,filter:new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.EQUAL_TO,property:property,value:value})}));} +this.styles[renderIntent].addRules(rules);},CLASS_NAME:"OpenLayers.StyleMap"});OpenLayers.Control.NavToolbar=OpenLayers.Class(OpenLayers.Control.Panel,{initialize:function(options){OpenLayers.Control.Panel.prototype.initialize.apply(this,[options]);this.addControls([new OpenLayers.Control.Navigation(),new OpenLayers.Control.ZoomBox()]);},draw:function(){var div=OpenLayers.Control.Panel.prototype.draw.apply(this,arguments);this.activateControl(this.controls[0]);return div;},CLASS_NAME:"OpenLayers.Control.NavToolbar"});OpenLayers.Filter.Comparison=OpenLayers.Class(OpenLayers.Filter,{type:null,property:null,value:null,matchCase:true,lowerBoundary:null,upperBoundary:null,initialize:function(options){OpenLayers.Filter.prototype.initialize.apply(this,[options]);},evaluate:function(context){if(context instanceof OpenLayers.Feature.Vector){context=context.attributes;} +var result=false;var got=context[this.property];switch(this.type){case OpenLayers.Filter.Comparison.EQUAL_TO:var exp=this.value;if(!this.matchCase&&typeof got=="string"&&typeof exp=="string"){result=(got.toUpperCase()==exp.toUpperCase());}else{result=(got==exp);} +break;case OpenLayers.Filter.Comparison.NOT_EQUAL_TO:var exp=this.value;if(!this.matchCase&&typeof got=="string"&&typeof exp=="string"){result=(got.toUpperCase()!=exp.toUpperCase());}else{result=(got!=exp);} +break;case OpenLayers.Filter.Comparison.LESS_THAN:result=got<this.value;break;case OpenLayers.Filter.Comparison.GREATER_THAN:result=got>this.value;break;case OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO:result=got<=this.value;break;case OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO:result=got>=this.value;break;case OpenLayers.Filter.Comparison.BETWEEN:result=(got>=this.lowerBoundary)&&(got<=this.upperBoundary);break;case OpenLayers.Filter.Comparison.LIKE:var regexp=new RegExp(this.value,"gi");result=regexp.test(got);break;} +return result;},value2regex:function(wildCard,singleChar,escapeChar){if(wildCard=="."){var msg="'.' is an unsupported wildCard character for "+"OpenLayers.Filter.Comparison";OpenLayers.Console.error(msg);return null;} +wildCard=wildCard?wildCard:"*";singleChar=singleChar?singleChar:".";escapeChar=escapeChar?escapeChar:"!";this.value=this.value.replace(new RegExp("\\"+escapeChar+"(.|$)","g"),"\\$1");this.value=this.value.replace(new RegExp("\\"+singleChar,"g"),".");this.value=this.value.replace(new RegExp("\\"+wildCard,"g"),".*");this.value=this.value.replace(new RegExp("\\\\.\\*","g"),"\\"+wildCard);this.value=this.value.replace(new RegExp("\\\\\\.","g"),"\\"+singleChar);return this.value;},regex2value:function(){var value=this.value;value=value.replace(/!/g,"!!");value=value.replace(/(\\)?\\\./g,function($0,$1){return $1?$0:"!.";});value=value.replace(/(\\)?\\\*/g,function($0,$1){return $1?$0:"!*";});value=value.replace(/\\\\/g,"\\");value=value.replace(/\.\*/g,"*");return value;},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.FeatureId=OpenLayers.Class(OpenLayers.Filter,{fids:null,initialize:function(options){this.fids=[];OpenLayers.Filter.prototype.initialize.apply(this,[options]);},evaluate:function(feature){for(var i=0,len=this.fids.length;i<len;i++){var fid=feature.fid||feature.id;if(fid==this.fids[i]){return true;}} +return false;},clone:function(){var filter=new OpenLayers.Filter.FeatureId();OpenLayers.Util.extend(filter,this);filter.fids=this.fids.slice();return filter;},CLASS_NAME:"OpenLayers.Filter.FeatureId"});OpenLayers.Filter.Logical=OpenLayers.Class(OpenLayers.Filter,{filters:null,type:null,initialize:function(options){this.filters=[];OpenLayers.Filter.prototype.initialize.apply(this,[options]);},destroy:function(){this.filters=null;OpenLayers.Filter.prototype.destroy.apply(this);},evaluate:function(context){switch(this.type){case OpenLayers.Filter.Logical.AND:for(var i=0,len=this.filters.length;i<len;i++){if(this.filters[i].evaluate(context)==false){return false;}} +return true;case OpenLayers.Filter.Logical.OR:for(var i=0,len=this.filters.length;i<len;i++){if(this.filters[i].evaluate(context)==true){return true;}} +return false;case OpenLayers.Filter.Logical.NOT:return(!this.filters[0].evaluate(context));}},clone:function(){var filters=[];for(var i=0,len=this.filters.length;i<len;++i){filters.push(this.filters[i].clone());} +return new OpenLayers.Filter.Logical({type:this.type,filters:filters});},CLASS_NAME:"OpenLayers.Filter.Logical"});OpenLayers.Filter.Logical.AND="&&";OpenLayers.Filter.Logical.OR="||";OpenLayers.Filter.Logical.NOT="!";OpenLayers.Filter.Spatial=OpenLayers.Class(OpenLayers.Filter,{type:null,property:null,value:null,distance:null,distanceUnits:null,initialize:function(options){OpenLayers.Filter.prototype.initialize.apply(this,[options]);},evaluate:function(feature){var intersect=false;switch(this.type){case OpenLayers.Filter.Spatial.BBOX:case OpenLayers.Filter.Spatial.INTERSECTS:if(feature.geometry){var geom=this.value;if(this.value.CLASS_NAME=="OpenLayers.Bounds"){geom=this.value.toGeometry();} +if(feature.geometry.intersects(geom)){intersect=true;}} +break;default:OpenLayers.Console.error(OpenLayers.i18n("filterEvaluateNotImplemented"));break;} +return intersect;},clone:function(){var options=OpenLayers.Util.applyDefaults({value:this.value&&this.value.clone&&this.value.clone()},this);return new OpenLayers.Filter.Spatial(options);},CLASS_NAME:"OpenLayers.Filter.Spatial"});OpenLayers.Filter.Spatial.BBOX="BBOX";OpenLayers.Filter.Spatial.INTERSECTS="INTERSECTS";OpenLayers.Filter.Spatial.DWITHIN="DWITHIN";OpenLayers.Filter.Spatial.WITHIN="WITHIN";OpenLayers.Filter.Spatial.CONTAINS="CONTAINS";OpenLayers.Geometry.Collection=OpenLayers.Class(OpenLayers.Geometry,{components:null,componentTypes:null,initialize:function(components){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);this.components=[];if(components!=null){this.addComponents(components);}},destroy:function(){this.components.length=0;this.components=null;OpenLayers.Geometry.prototype.destroy.apply(this,arguments);},clone:function(){var geometry=eval("new "+this.CLASS_NAME+"()");for(var i=0,len=this.components.length;i<len;i++){geometry.addComponent(this.components[i].clone());} +OpenLayers.Util.applyDefaults(geometry,this);return geometry;},getComponentsString:function(){var strings=[];for(var i=0,len=this.components.length;i<len;i++){strings.push(this.components[i].toShortString());} +return strings.join(",");},calculateBounds:function(){this.bounds=null;if(this.components&&this.components.length>0){this.setBounds(this.components[0].getBounds());for(var i=1,len=this.components.length;i<len;i++){this.extendBounds(this.components[i].getBounds());}}},addComponents:function(components){if(!(components instanceof Array)){components=[components];} +for(var i=0,len=components.length;i<len;i++){this.addComponent(components[i]);}},addComponent:function(component,index){var added=false;if(component){if(this.componentTypes==null||(OpenLayers.Util.indexOf(this.componentTypes,component.CLASS_NAME)>-1)){if(index!=null&&(index<this.components.length)){var components1=this.components.slice(0,index);var components2=this.components.slice(index,this.components.length);components1.push(component);this.components=components1.concat(components2);}else{this.components.push(component);} +component.parent=this;this.clearBounds();added=true;}} +return added;},removeComponents:function(components){if(!(components instanceof Array)){components=[components];} +for(var i=components.length-1;i>=0;--i){this.removeComponent(components[i]);}},removeComponent:function(component){OpenLayers.Util.removeItem(this.components,component);this.clearBounds();},getLength:function(){var length=0.0;for(var i=0,len=this.components.length;i<len;i++){length+=this.components[i].getLength();} +return length;},getArea:function(){var area=0.0;for(var i=0,len=this.components.length;i<len;i++){area+=this.components[i].getArea();} +return area;},getGeodesicArea:function(projection){var area=0.0;for(var i=0,len=this.components.length;i<len;i++){area+=this.components[i].getGeodesicArea(projection);} +return area;},getCentroid:function(weighted){if(!weighted){return this.components.length&&this.components[0].getCentroid();} +var len=this.components.length;if(!len){return false;} +var areas=[];var centroids=[];var areaSum=0;var minArea=Number.MAX_VALUE;var component;for(var i=0;i<len;++i){component=this.components[i];var area=component.getArea();var centroid=component.getCentroid(true);if(isNaN(area)||isNaN(centroid.x)||isNaN(centroid.y)){continue;} +areas.push(area);areaSum+=area;minArea=(area<minArea&&area>0)?area:minArea;centroids.push(centroid);} +len=areas.length;if(areaSum===0){for(var i=0;i<len;++i){areas[i]=1;} +areaSum=areas.length;}else{for(var i=0;i<len;++i){areas[i]/=minArea;} +areaSum/=minArea;} +var xSum=0,ySum=0,centroid,area;for(var i=0;i<len;++i){centroid=centroids[i];area=areas[i];xSum+=centroid.x*area;ySum+=centroid.y*area;} +return new OpenLayers.Geometry.Point(xSum/areaSum,ySum/areaSum);},getGeodesicLength:function(projection){var length=0.0;for(var i=0,len=this.components.length;i<len;i++){length+=this.components[i].getGeodesicLength(projection);} +return length;},move:function(x,y){for(var i=0,len=this.components.length;i<len;i++){this.components[i].move(x,y);}},rotate:function(angle,origin){for(var i=0,len=this.components.length;i<len;++i){this.components[i].rotate(angle,origin);}},resize:function(scale,origin,ratio){for(var i=0;i<this.components.length;++i){this.components[i].resize(scale,origin,ratio);} +return this;},distanceTo:function(geometry,options){var edge=!(options&&options.edge===false);var details=edge&&options&&options.details;var result,best,distance;var min=Number.POSITIVE_INFINITY;for(var i=0,len=this.components.length;i<len;++i){result=this.components[i].distanceTo(geometry,options);distance=details?result.distance:result;if(distance<min){min=distance;best=result;if(min==0){break;}}} +return best;},equals:function(geometry){var equivalent=true;if(!geometry||!geometry.CLASS_NAME||(this.CLASS_NAME!=geometry.CLASS_NAME)){equivalent=false;}else if(!(geometry.components instanceof Array)||(geometry.components.length!=this.components.length)){equivalent=false;}else{for(var i=0,len=this.components.length;i<len;++i){if(!this.components[i].equals(geometry.components[i])){equivalent=false;break;}}} +return equivalent;},transform:function(source,dest){if(source&&dest){for(var i=0,len=this.components.length;i<len;i++){var component=this.components[i];component.transform(source,dest);} +this.bounds=null;} +return this;},intersects:function(geometry){var intersect=false;for(var i=0,len=this.components.length;i<len;++i){intersect=geometry.intersects(this.components[i]);if(intersect){break;}} +return intersect;},getVertices:function(nodes){var vertices=[];for(var i=0,len=this.components.length;i<len;++i){Array.prototype.push.apply(vertices,this.components[i].getVertices(nodes));} +return vertices;},CLASS_NAME:"OpenLayers.Geometry.Collection"});OpenLayers.Geometry.Point=OpenLayers.Class(OpenLayers.Geometry,{x:null,y:null,initialize:function(x,y){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);this.x=parseFloat(x);this.y=parseFloat(y);},clone:function(obj){if(obj==null){obj=new OpenLayers.Geometry.Point(this.x,this.y);} +OpenLayers.Util.applyDefaults(obj,this);return obj;},calculateBounds:function(){this.bounds=new OpenLayers.Bounds(this.x,this.y,this.x,this.y);},distanceTo:function(geometry,options){var edge=!(options&&options.edge===false);var details=edge&&options&&options.details;var distance,x0,y0,x1,y1,result;if(geometry instanceof OpenLayers.Geometry.Point){x0=this.x;y0=this.y;x1=geometry.x;y1=geometry.y;distance=Math.sqrt(Math.pow(x0-x1,2)+Math.pow(y0-y1,2));result=!details?distance:{x0:x0,y0:y0,x1:x1,y1:y1,distance:distance};}else{result=geometry.distanceTo(this,options);if(details){result={x0:result.x1,y0:result.y1,x1:result.x0,y1:result.y0,distance:result.distance};}} +return result;},equals:function(geom){var equals=false;if(geom!=null){equals=((this.x==geom.x&&this.y==geom.y)||(isNaN(this.x)&&isNaN(this.y)&&isNaN(geom.x)&&isNaN(geom.y)));} +return equals;},toShortString:function(){return(this.x+", "+this.y);},move:function(x,y){this.x=this.x+x;this.y=this.y+y;this.clearBounds();},rotate:function(angle,origin){angle*=Math.PI/180;var radius=this.distanceTo(origin);var theta=angle+Math.atan2(this.y-origin.y,this.x-origin.x);this.x=origin.x+(radius*Math.cos(theta));this.y=origin.y+(radius*Math.sin(theta));this.clearBounds();},getCentroid:function(){return new OpenLayers.Geometry.Point(this.x,this.y);},resize:function(scale,origin,ratio){ratio=(ratio==undefined)?1:ratio;this.x=origin.x+(scale*ratio*(this.x-origin.x));this.y=origin.y+(scale*(this.y-origin.y));this.clearBounds();return this;},intersects:function(geometry){var intersect=false;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){intersect=this.equals(geometry);}else{intersect=geometry.intersects(this);} +return intersect;},transform:function(source,dest){if((source&&dest)){OpenLayers.Projection.transform(this,source,dest);this.bounds=null;} +return this;},getVertices:function(nodes){return[this];},CLASS_NAME:"OpenLayers.Geometry.Point"});OpenLayers.Geometry.Rectangle=OpenLayers.Class(OpenLayers.Geometry,{x:null,y:null,width:null,height:null,initialize:function(x,y,width,height){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);this.x=x;this.y=y;this.width=width;this.height=height;},calculateBounds:function(){this.bounds=new OpenLayers.Bounds(this.x,this.y,this.x+this.width,this.y+this.height);},getLength:function(){var length=(2*this.width)+(2*this.height);return length;},getArea:function(){var area=this.width*this.height;return area;},CLASS_NAME:"OpenLayers.Geometry.Rectangle"});OpenLayers.Geometry.Surface=OpenLayers.Class(OpenLayers.Geometry,{initialize:function(){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Geometry.Surface"});OpenLayers.Layer.KaMapCache=OpenLayers.Class(OpenLayers.Layer.KaMap,{IMAGE_EXTENSIONS:{'jpeg':'jpg','gif':'gif','png':'png','png8':'png','png24':'png','dithered':'png'},DEFAULT_FORMAT:'jpeg',initialize:function(name,url,params,options){OpenLayers.Layer.KaMap.prototype.initialize.apply(this,arguments);this.extension=this.IMAGE_EXTENSIONS[this.params.i.toLowerCase()||DEFAULT_FORMAT];},getURL:function(bounds){bounds=this.adjustBounds(bounds);var mapRes=this.map.getResolution();var scale=Math.round((this.map.getScale()*10000))/10000;var pX=Math.round(bounds.left/mapRes);var pY=-Math.round(bounds.top/mapRes);var metaX=Math.floor(pX/this.tileSize.w/this.params.metaTileSize.w)*this.tileSize.w*this.params.metaTileSize.w;var metaY=Math.floor(pY/this.tileSize.h/this.params.metaTileSize.h)*this.tileSize.h*this.params.metaTileSize.h;var url=this.url;if(url instanceof Array){url=this.selectUrl(paramsString,url);} +var components=[url,"/",this.params.map,"/",scale,"/",this.params.g.replace(/\s/g,'_'),"/def/t",metaY,"/l",metaX,"/t",pY,"l",pX,".",this.extension];return components.join("");},CLASS_NAME:"OpenLayers.Layer.KaMapCache"});OpenLayers.Layer.MapServer.Untiled=OpenLayers.Class(OpenLayers.Layer.MapServer,{singleTile:true,initialize:function(name,url,params,options){OpenLayers.Layer.MapServer.prototype.initialize.apply(this,arguments);var msg="The OpenLayers.Layer.MapServer.Untiled class is deprecated and "+"will be removed in 3.0. Instead, you should use the "+"normal OpenLayers.Layer.MapServer class, passing it the option "+"'singleTile' as true.";OpenLayers.Console.warn(msg);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.MapServer.Untiled(this.name,this.url,this.params,this.getOptions());} +obj=OpenLayers.Layer.MapServer.prototype.clone.apply(this,[obj]);return obj;},CLASS_NAME:"OpenLayers.Layer.MapServer.Untiled"});OpenLayers.Layer.Vector=OpenLayers.Class(OpenLayers.Layer,{EVENT_TYPES:["beforefeatureadded","beforefeaturesadded","featureadded","featuresadded","beforefeatureremoved","beforefeaturesremoved","featureremoved","featuresremoved","beforefeatureselected","featureselected","featureunselected","beforefeaturemodified","featuremodified","afterfeaturemodified","vertexmodified","sketchstarted","sketchmodified","sketchcomplete","refresh"],isBaseLayer:false,isFixed:false,isVector:true,features:null,filter:null,selectedFeatures:null,unrenderedFeatures:null,reportError:true,style:null,styleMap:null,strategies:null,protocol:null,renderers:['SVG','VML','Canvas'],renderer:null,rendererOptions:null,geometryType:null,drawn:false,initialize:function(name,options){this.EVENT_TYPES=OpenLayers.Layer.Vector.prototype.EVENT_TYPES.concat(OpenLayers.Layer.prototype.EVENT_TYPES);OpenLayers.Layer.prototype.initialize.apply(this,arguments);if(!this.renderer||!this.renderer.supported()){this.assignRenderer();} +if(!this.renderer||!this.renderer.supported()){this.renderer=null;this.displayError();} +if(!this.styleMap){this.styleMap=new OpenLayers.StyleMap();} +this.features=[];this.selectedFeatures=[];this.unrenderedFeatures={};if(this.strategies){for(var i=0,len=this.strategies.length;i<len;i++){this.strategies[i].setLayer(this);}}},destroy:function(){if(this.strategies){var strategy,i,len;for(i=0,len=this.strategies.length;i<len;i++){strategy=this.strategies[i];if(strategy.autoDestroy){strategy.destroy();}} +this.strategies=null;} +if(this.protocol){if(this.protocol.autoDestroy){this.protocol.destroy();} +this.protocol=null;} +this.destroyFeatures();this.features=null;this.selectedFeatures=null;this.unrenderedFeatures=null;if(this.renderer){this.renderer.destroy();} +this.renderer=null;this.geometryType=null;this.drawn=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.Vector(this.name,this.getOptions());} +obj=OpenLayers.Layer.prototype.clone.apply(this,[obj]);var features=this.features;var len=features.length;var clonedFeatures=new Array(len);for(var i=0;i<len;++i){clonedFeatures[i]=features[i].clone();} +obj.features=clonedFeatures;return obj;},refresh:function(obj){if(this.calculateInRange()&&this.visibility){this.events.triggerEvent("refresh",obj);}},assignRenderer:function(){for(var i=0,len=this.renderers.length;i<len;i++){var rendererClass=this.renderers[i];var renderer=(typeof rendererClass=="function")?rendererClass:OpenLayers.Renderer[rendererClass];if(renderer&&renderer.prototype.supported()){this.renderer=new renderer(this.div,this.rendererOptions);break;}}},displayError:function(){if(this.reportError){OpenLayers.Console.userError(OpenLayers.i18n("browserNotSupported",{'renderers':this.renderers.join("\n")}));}},setMap:function(map){OpenLayers.Layer.prototype.setMap.apply(this,arguments);if(!this.renderer){this.map.removeLayer(this);}else{this.renderer.map=this.map;this.renderer.setSize(this.map.getSize());}},afterAdd:function(){if(this.strategies){var strategy,i,len;for(i=0,len=this.strategies.length;i<len;i++){strategy=this.strategies[i];if(strategy.autoActivate){strategy.activate();}}}},removeMap:function(map){this.drawn=false;if(this.strategies){var strategy,i,len;for(i=0,len=this.strategies.length;i<len;i++){strategy=this.strategies[i];if(strategy.autoActivate){strategy.deactivate();}}}},onMapResize:function(){OpenLayers.Layer.prototype.onMapResize.apply(this,arguments);this.renderer.setSize(this.map.getSize());},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.prototype.moveTo.apply(this,arguments);var coordSysUnchanged=true;if(!dragging){this.renderer.root.style.visibility="hidden";this.div.style.left=-parseInt(this.map.layerContainerDiv.style.left)+"px";this.div.style.top=-parseInt(this.map.layerContainerDiv.style.top)+"px";var extent=this.map.getExtent();coordSysUnchanged=this.renderer.setExtent(extent,zoomChanged);this.renderer.root.style.visibility="visible";if(navigator.userAgent.toLowerCase().indexOf("gecko")!=-1){this.div.scrollLeft=this.div.scrollLeft;} +if(!zoomChanged&&coordSysUnchanged){for(var i in this.unrenderedFeatures){var feature=this.unrenderedFeatures[i];this.drawFeature(feature);}}} +if(!this.drawn||zoomChanged||!coordSysUnchanged){this.drawn=true;var feature;for(var i=0,len=this.features.length;i<len;i++){this.renderer.locked=(i!==(len-1));feature=this.features[i];this.drawFeature(feature);}}},display:function(display){OpenLayers.Layer.prototype.display.apply(this,arguments);var currentDisplay=this.div.style.display;if(currentDisplay!=this.renderer.root.style.display){this.renderer.root.style.display=currentDisplay;}},addFeatures:function(features,options){if(!(features instanceof Array)){features=[features];} +var notify=!options||!options.silent;if(notify){var event={features:features};var ret=this.events.triggerEvent("beforefeaturesadded",event);if(ret===false){return;} +features=event.features;} +var featuresAdded=[];for(var i=0,len=features.length;i<len;i++){if(i!=(features.length-1)){this.renderer.locked=true;}else{this.renderer.locked=false;} +var feature=features[i];if(this.geometryType&&!(feature.geometry instanceof this.geometryType)){var throwStr=OpenLayers.i18n('componentShouldBe',{'geomType':this.geometryType.prototype.CLASS_NAME});throw throwStr;} +feature.layer=this;if(!feature.style&&this.style){feature.style=OpenLayers.Util.extend({},this.style);} +if(notify){if(this.events.triggerEvent("beforefeatureadded",{feature:feature})===false){continue;};this.preFeatureInsert(feature);} +featuresAdded.push(feature);this.features.push(feature);this.drawFeature(feature);if(notify){this.events.triggerEvent("featureadded",{feature:feature});this.onFeatureInsert(feature);}} +if(notify){this.events.triggerEvent("featuresadded",{features:featuresAdded});}},removeFeatures:function(features,options){if(!features||features.length===0){return;} +if(features===this.features){return this.removeAllFeatures(options);} +if(!(features instanceof Array)){features=[features];} +if(features===this.selectedFeatures){features=features.slice();} +var notify=!options||!options.silent;if(notify){this.events.triggerEvent("beforefeaturesremoved",{features:features});} +for(var i=features.length-1;i>=0;i--){if(i!=0&&features[i-1].geometry){this.renderer.locked=true;}else{this.renderer.locked=false;} +var feature=features[i];delete this.unrenderedFeatures[feature.id];if(notify){this.events.triggerEvent("beforefeatureremoved",{feature:feature});} +this.features=OpenLayers.Util.removeItem(this.features,feature);feature.layer=null;if(feature.geometry){this.renderer.eraseFeatures(feature);} +if(OpenLayers.Util.indexOf(this.selectedFeatures,feature)!=-1){OpenLayers.Util.removeItem(this.selectedFeatures,feature);} +if(notify){this.events.triggerEvent("featureremoved",{feature:feature});}} +if(notify){this.events.triggerEvent("featuresremoved",{features:features});}},removeAllFeatures:function(options){var notify=!options||!options.silent;var features=this.features;if(notify){this.events.triggerEvent("beforefeaturesremoved",{features:features});} +var feature;for(var i=features.length-1;i>=0;i--){feature=features[i];if(notify){this.events.triggerEvent("beforefeatureremoved",{feature:feature});} +feature.layer=null;if(notify){this.events.triggerEvent("featureremoved",{feature:feature});}} +this.renderer.clear();this.features=[];this.unrenderedFeatures={};this.selectedFeatures=[];if(notify){this.events.triggerEvent("featuresremoved",{features:features});}},destroyFeatures:function(features,options){var all=(features==undefined);if(all){features=this.features;} +if(features){this.removeFeatures(features,options);for(var i=features.length-1;i>=0;i--){features[i].destroy();}}},drawFeature:function(feature,style){if(!this.drawn){return} +if(typeof style!="object"){if(!style&&feature.state===OpenLayers.State.DELETE){style="delete";} +var renderIntent=style||feature.renderIntent;style=feature.style||this.style;if(!style){style=this.styleMap.createSymbolizer(feature,renderIntent);}} +if(!this.renderer.drawFeature(feature,style)){this.unrenderedFeatures[feature.id]=feature;}else{delete this.unrenderedFeatures[feature.id];};},eraseFeatures:function(features){this.renderer.eraseFeatures(features);},getFeatureFromEvent:function(evt){if(!this.renderer){OpenLayers.Console.error(OpenLayers.i18n("getFeatureError"));return null;} +var featureId=this.renderer.getFeatureIdFromEvent(evt);return this.getFeatureById(featureId);},getFeatureBy:function(property,value){var feature=null;for(var i=0,len=this.features.length;i<len;++i){if(this.features[i][property]==value){feature=this.features[i];break;}} +return feature;},getFeatureById:function(featureId){return this.getFeatureBy('id',featureId);},getFeatureByFid:function(featureFid){return this.getFeatureBy('fid',featureFid);},onFeatureInsert:function(feature){},preFeatureInsert:function(feature){},getDataExtent:function(){var maxExtent=null;var features=this.features;if(features&&(features.length>0)){maxExtent=new OpenLayers.Bounds();var geometry=null;for(var i=0,len=features.length;i<len;i++){geometry=features[i].geometry;if(geometry){maxExtent.extend(geometry.getBounds());}}} +return maxExtent;},CLASS_NAME:"OpenLayers.Layer.Vector"});OpenLayers.Layer.WMS.Post=OpenLayers.Class(OpenLayers.Layer.WMS,{tileClass:null,unsupportedBrowsers:["mozilla","firefox","opera"],SUPPORTED_TRANSITIONS:[],initialize:function(name,url,params,options){var newArguments=[];newArguments.push(name,url,params,options);OpenLayers.Layer.WMS.prototype.initialize.apply(this,newArguments);this.tileClass=OpenLayers.Util.indexOf(this.unsupportedBrowsers,OpenLayers.Util.getBrowserName())!=-1?OpenLayers.Tile.Image:OpenLayers.Tile.Image.IFrame;},addTile:function(bounds,position){return new this.tileClass(this,position,bounds,null,this.tileSize);},CLASS_NAME:'OpenLayers.Layer.WMS.Post'});OpenLayers.Layer.WMS.Untiled=OpenLayers.Class(OpenLayers.Layer.WMS,{singleTile:true,initialize:function(name,url,params,options){OpenLayers.Layer.WMS.prototype.initialize.apply(this,arguments);var msg="The OpenLayers.Layer.WMS.Untiled class is deprecated and "+"will be removed in 3.0. Instead, you should use the "+"normal OpenLayers.Layer.WMS class, passing it the option "+"'singleTile' as true.";OpenLayers.Console.warn(msg);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.WMS.Untiled(this.name,this.url,this.params,this.getOptions());} +obj=OpenLayers.Layer.WMS.prototype.clone.apply(this,[obj]);return obj;},CLASS_NAME:"OpenLayers.Layer.WMS.Untiled"});OpenLayers.Strategy.Filter=OpenLayers.Class(OpenLayers.Strategy,{filter:null,cache:null,caching:false,initialize:function(options){OpenLayers.Strategy.prototype.initialize.apply(this,[options]);if(!this.filter||!(this.filter instanceof OpenLayers.Filter)){throw new Error("Filter strategy must be constructed with a filter");}},activate:function(){var activated=OpenLayers.Strategy.prototype.activate.apply(this,arguments);if(activated){this.cache=[];this.layer.events.on({"beforefeaturesadded":this.handleAdd,"beforefeaturesremoved":this.handleRemove,scope:this});} +return activated;},deactivate:function(){this.cache=null;if(this.layer&&this.layer.events){this.layer.events.un({"beforefeaturesadded":this.handleAdd,"beforefeaturesremoved":this.handleRemove,scope:this});} +return OpenLayers.Strategy.prototype.deactivate.apply(this,arguments);},handleAdd:function(event){if(!this.caching){var features=event.features;event.features=[];var feature;for(var i=0,ii=features.length;i<ii;++i){feature=features[i];if(this.filter.evaluate(feature)){event.features.push(feature);}else{this.cache.push(feature);}}}},handleRemove:function(event){if(!this.caching){this.cache=[];}},setFilter:function(filter){this.filter=filter;var previousCache=this.cache;this.cache=[];this.handleAdd({features:this.layer.features});if(this.cache.length>0){this.caching=true;this.layer.removeFeatures(this.cache.slice(),{silent:true});this.caching=false;} +if(previousCache.length>0){var event={features:previousCache};this.handleAdd(event);this.caching=true;this.layer.addFeatures(event.features,{silent:true});this.caching=false;}},CLASS_NAME:"OpenLayers.Strategy.Filter"});OpenLayers.Style2=OpenLayers.Class({id:null,name:null,title:null,description:null,layerName:null,isDefault:false,rules:null,initialize:function(config){OpenLayers.Util.extend(this,config);this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){for(var i=0,len=this.rules.length;i<len;i++){this.rules[i].destroy();} +delete this.rules;},clone:function(){var config=OpenLayers.Util.extend({},this);if(this.rules){config.rules=[];for(var i=0,len=this.rules.length;i<len;++i){config.rules.push(this.rules[i].clone());}} +return new OpenLayers.Style2(config);},CLASS_NAME:"OpenLayers.Style2"});OpenLayers.Control.GetFeature=OpenLayers.Class(OpenLayers.Control,{protocol:null,multipleKey:null,toggleKey:null,modifiers:null,multiple:false,click:true,single:true,clickout:true,toggle:false,clickTolerance:5,hover:false,box:false,maxFeatures:10,features:null,hoverFeature:null,handlerOptions:null,handlers:null,hoverResponse:null,filterType:OpenLayers.Filter.Spatial.BBOX,EVENT_TYPES:["featureselected","featuresselected","featureunselected","clickout","beforefeatureselected","beforefeaturesselected","hoverfeature","outfeature"],initialize:function(options){this.EVENT_TYPES=OpenLayers.Control.GetFeature.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);options.handlerOptions=options.handlerOptions||{};OpenLayers.Control.prototype.initialize.apply(this,[options]);this.features={};this.handlers={};if(this.click){this.handlers.click=new OpenLayers.Handler.Click(this,{click:this.selectClick},this.handlerOptions.click||{});} +if(this.box){this.handlers.box=new OpenLayers.Handler.Box(this,{done:this.selectBox},OpenLayers.Util.extend(this.handlerOptions.box,{boxDivClassName:"olHandlerBoxSelectFeature"}));} +if(this.hover){this.handlers.hover=new OpenLayers.Handler.Hover(this,{'move':this.cancelHover,'pause':this.selectHover},OpenLayers.Util.extend(this.handlerOptions.hover,{'delay':250}));}},activate:function(){if(!this.active){for(var i in this.handlers){this.handlers[i].activate();}} +return OpenLayers.Control.prototype.activate.apply(this,arguments);},deactivate:function(){if(this.active){for(var i in this.handlers){this.handlers[i].deactivate();}} +return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},selectClick:function(evt){var bounds=this.pixelToBounds(evt.xy);this.setModifiers(evt);this.request(bounds,{single:this.single});},selectBox:function(position){var bounds;if(position instanceof OpenLayers.Bounds){var minXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.left,position.bottom));var maxXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.right,position.top));bounds=new OpenLayers.Bounds(minXY.lon,minXY.lat,maxXY.lon,maxXY.lat);}else{if(this.click){return;} +bounds=this.pixelToBounds(position);} +this.setModifiers(this.handlers.box.dragHandler.evt);this.request(bounds);},selectHover:function(evt){var bounds=this.pixelToBounds(evt.xy);this.request(bounds,{single:true,hover:true});},cancelHover:function(){if(this.hoverResponse){this.protocol.abort(this.hoverResponse);this.hoverResponse=null;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait");}},request:function(bounds,options){options=options||{};var filter=new OpenLayers.Filter.Spatial({type:this.filterType,value:bounds});OpenLayers.Element.addClass(this.map.viewPortDiv,"olCursorWait");var response=this.protocol.read({maxFeatures:options.single==true?this.maxFeatures:undefined,filter:filter,callback:function(result){if(result.success()){if(result.features.length){if(options.single==true){this.selectBestFeature(result.features,bounds.getCenterLonLat(),options);}else{this.select(result.features);}}else if(options.hover){this.hoverSelect();}else{this.events.triggerEvent("clickout");if(this.clickout){this.unselectAll();}}} +OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait");},scope:this});if(options.hover==true){this.hoverResponse=response;}},selectBestFeature:function(features,clickPosition,options){options=options||{};if(features.length){var point=new OpenLayers.Geometry.Point(clickPosition.lon,clickPosition.lat);var feature,resultFeature,dist;var minDist=Number.MAX_VALUE;for(var i=0;i<features.length;++i){feature=features[i];if(feature.geometry){dist=point.distanceTo(feature.geometry,{edge:false});if(dist<minDist){minDist=dist;resultFeature=feature;if(minDist==0){break;}}}} +if(options.hover==true){this.hoverSelect(resultFeature);}else{this.select(resultFeature||features);}}},setModifiers:function(evt){this.modifiers={multiple:this.multiple||(this.multipleKey&&evt[this.multipleKey]),toggle:this.toggle||(this.toggleKey&&evt[this.toggleKey])};},select:function(features){if(!this.modifiers.multiple&&!this.modifiers.toggle){this.unselectAll();} +if(!(features instanceof Array)){features=[features];} +var cont=this.events.triggerEvent("beforefeaturesselected",{features:features});if(cont!==false){var selectedFeatures=[];var feature;for(var i=0,len=features.length;i<len;++i){feature=features[i];if(this.features[feature.fid||feature.id]){if(this.modifiers.toggle){this.unselect(this.features[feature.fid||feature.id]);}}else{cont=this.events.triggerEvent("beforefeatureselected",{feature:feature});if(cont!==false){this.features[feature.fid||feature.id]=feature;selectedFeatures.push(feature);this.events.triggerEvent("featureselected",{feature:feature});}}} +this.events.triggerEvent("featuresselected",{features:selectedFeatures});}},hoverSelect:function(feature){var fid=feature?feature.fid||feature.id:null;var hfid=this.hoverFeature?this.hoverFeature.fid||this.hoverFeature.id:null;if(hfid&&hfid!=fid){this.events.triggerEvent("outfeature",{feature:this.hoverFeature});this.hoverFeature=null;} +if(fid&&fid!=hfid){this.events.triggerEvent("hoverfeature",{feature:feature});this.hoverFeature=feature;}},unselect:function(feature){delete this.features[feature.fid||feature.id];this.events.triggerEvent("featureunselected",{feature:feature});},unselectAll:function(){for(var fid in this.features){this.unselect(this.features[fid]);}},setMap:function(map){for(var i in this.handlers){this.handlers[i].setMap(map);} +OpenLayers.Control.prototype.setMap.apply(this,arguments);},pixelToBounds:function(pixel){var llPx=pixel.add(-this.clickTolerance/2,this.clickTolerance/2);var urPx=pixel.add(this.clickTolerance/2,-this.clickTolerance/2);var ll=this.map.getLonLatFromPixel(llPx);var ur=this.map.getLonLatFromPixel(urPx);return new OpenLayers.Bounds(ll.lon,ll.lat,ur.lon,ur.lat);},CLASS_NAME:"OpenLayers.Control.GetFeature"});OpenLayers.Control.Snapping=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:["beforesnap","snap","unsnap"],DEFAULTS:{tolerance:10,node:true,edge:true,vertex:true},greedy:true,precedence:["node","vertex","edge"],resolution:null,geoToleranceCache:null,layer:null,feature:null,point:null,initialize:function(options){Array.prototype.push.apply(this.EVENT_TYPES,OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.options=options||{};if(this.options.layer){this.setLayer(this.options.layer);} +var defaults=OpenLayers.Util.extend({},this.options.defaults);this.defaults=OpenLayers.Util.applyDefaults(defaults,this.DEFAULTS);this.setTargets(this.options.targets);if(this.targets.length===0&&this.layer){this.addTargetLayer(this.layer);} +this.geoToleranceCache={};},setLayer:function(layer){if(this.active){this.deactivate();this.layer=layer;this.activate();}else{this.layer=layer;}},setTargets:function(targets){this.targets=[];if(targets&&targets.length){var target;for(var i=0,len=targets.length;i<len;++i){target=targets[i];if(target instanceof OpenLayers.Layer.Vector){this.addTargetLayer(target);}else{this.addTarget(target);}}}},addTargetLayer:function(layer){this.addTarget({layer:layer});},addTarget:function(target){target=OpenLayers.Util.applyDefaults(target,this.defaults);target.nodeTolerance=target.nodeTolerance||target.tolerance;target.vertexTolerance=target.vertexTolerance||target.tolerance;target.edgeTolerance=target.edgeTolerance||target.tolerance;this.targets.push(target);},removeTargetLayer:function(layer){var target;for(var i=this.targets.length-1;i>=0;--i){target=this.targets[i];if(target.layer===layer){this.removeTarget(target);}}},removeTarget:function(target){return OpenLayers.Util.removeItem(this.targets,target);},activate:function(){var activated=OpenLayers.Control.prototype.activate.call(this);if(activated){if(this.layer&&this.layer.events){this.layer.events.on({sketchstarted:this.onSketchModified,sketchmodified:this.onSketchModified,vertexmodified:this.onVertexModified,scope:this});}} +return activated;},deactivate:function(){var deactivated=OpenLayers.Control.prototype.deactivate.call(this);if(deactivated){if(this.layer&&this.layer.events){this.layer.events.un({sketchstarted:this.onSketchModified,sketchmodified:this.onSketchModified,vertexmodified:this.onVertexModified,scope:this});}} +this.feature=null;this.point=null;return deactivated;},onSketchModified:function(event){this.feature=event.feature;this.considerSnapping(event.vertex,event.vertex);},onVertexModified:function(event){this.feature=event.feature;var loc=this.layer.map.getLonLatFromViewPortPx(event.pixel);this.considerSnapping(event.vertex,new OpenLayers.Geometry.Point(loc.lon,loc.lat));},considerSnapping:function(point,loc){var best={rank:Number.POSITIVE_INFINITY,dist:Number.POSITIVE_INFINITY,x:null,y:null};var snapped=false;var result,target;for(var i=0,len=this.targets.length;i<len;++i){target=this.targets[i];result=this.testTarget(target,loc);if(result){if(this.greedy){best=result;best.target=target;snapped=true;break;}else{if((result.rank<best.rank)||(result.rank===best.rank&&result.dist<best.dist)){best=result;best.target=target;snapped=true;}}}} +if(snapped){var proceed=this.events.triggerEvent("beforesnap",{point:point,x:best.x,y:best.y,distance:best.dist,layer:best.target.layer,snapType:this.precedence[best.rank]});if(proceed!==false){point.x=best.x;point.y=best.y;this.point=point;this.events.triggerEvent("snap",{point:point,snapType:this.precedence[best.rank],layer:best.target.layer,distance:best.dist});}else{snapped=false;}} +if(this.point&&!snapped){point.x=loc.x;point.y=loc.y;this.point=null;this.events.triggerEvent("unsnap",{point:point});}},testTarget:function(target,loc){var tolerance={node:this.getGeoTolerance(target.nodeTolerance),vertex:this.getGeoTolerance(target.vertexTolerance),edge:this.getGeoTolerance(target.edgeTolerance)};var maxTolerance=Math.max(tolerance.node,tolerance.vertex,tolerance.edge);var result={rank:Number.POSITIVE_INFINITY,dist:Number.POSITIVE_INFINITY};var eligible=false;var features=target.layer.features;var feature,type,vertices,vertex,closest,dist,found;var numTypes=this.precedence.length;var ll=new OpenLayers.LonLat(loc.x,loc.y);for(var i=0,len=features.length;i<len;++i){feature=features[i];if(feature!==this.feature&&!feature._sketch&&feature.state!==OpenLayers.State.DELETE&&(!target.filter||target.filter.evaluate(feature.attributes))){if(feature.atPoint(ll,maxTolerance,maxTolerance)){for(var j=0,stop=Math.min(result.rank+1,numTypes);j<stop;++j){type=this.precedence[j];if(target[type]){if(type==="edge"){closest=feature.geometry.distanceTo(loc,{details:true});dist=closest.distance;if(dist<=tolerance[type]&&dist<result.dist){result={rank:j,dist:dist,x:closest.x0,y:closest.y0};eligible=true;break;}}else{vertices=feature.geometry.getVertices(type==="node");found=false;for(var k=0,klen=vertices.length;k<klen;++k){vertex=vertices[k];dist=vertex.distanceTo(loc);if(dist<=tolerance[type]&&(j<result.rank||(j===result.rank&&dist<result.dist))){result={rank:j,dist:dist,x:vertex.x,y:vertex.y};eligible=true;found=true;}} +if(found){break;}}}}}}} +return eligible?result:null;},getGeoTolerance:function(tolerance){var resolution=this.layer.map.getResolution();if(resolution!==this.resolution){this.resolution=resolution;this.geoToleranceCache={};} +var geoTolerance=this.geoToleranceCache[tolerance];if(geoTolerance===undefined){geoTolerance=tolerance*resolution;this.geoToleranceCache[tolerance]=geoTolerance;} +return geoTolerance;},destroy:function(){if(this.active){this.deactivate();} +delete this.layer;delete this.targets;OpenLayers.Control.prototype.destroy.call(this);},CLASS_NAME:"OpenLayers.Control.Snapping"});OpenLayers.Format.Filter=OpenLayers.Class(OpenLayers.Format.XML,{defaultVersion:"1.0.0",version:null,parser:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},write:function(filter,options){var version=(options&&options.version)||this.version||this.defaultVersion;if(!this.parser||this.parser.VERSION!=version){var format=OpenLayers.Format.Filter["v"+version.replace(/\./g,"_")];if(!format){throw"Can't find a Filter parser for version "+ +version;} +this.parser=new format(this.options);} +return this.parser.write(filter);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +var version=this.version;if(!version){version=this.defaultVersion;} +if(!this.parser||this.parser.VERSION!=version){var format=OpenLayers.Format.Filter["v"+version.replace(/\./g,"_")];if(!format){throw"Can't find a Filter parser for version "+ +version;} +this.parser=new format(this.options);} +var filter=this.parser.read(data);return filter;},CLASS_NAME:"OpenLayers.Format.Filter"});OpenLayers.Format.SLD=OpenLayers.Class(OpenLayers.Format.XML,{defaultVersion:"1.0.0",version:null,namedLayersAsArray:false,parser:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},write:function(sld,options){var version=(options&&options.version)||this.version||this.defaultVersion;if(!this.parser||this.parser.VERSION!=version){var format=OpenLayers.Format.SLD["v"+version.replace(/\./g,"_")];if(!format){throw"Can't find a SLD parser for version "+ +version;} +this.parser=new format(this.options);} +var root=this.parser.write(sld);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},read:function(data,options){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +var root=data.documentElement;var version=this.version;if(!version){version=root.getAttribute("version");if(!version){version=this.defaultVersion;}} +if(!this.parser||this.parser.VERSION!=version){var format=OpenLayers.Format.SLD["v"+version.replace(/\./g,"_")];if(!format){throw"Can't find a SLD parser for version "+ +version;} +this.parser=new format(this.options);} +var sld=this.parser.read(data,options);return sld;},CLASS_NAME:"OpenLayers.Format.SLD"});OpenLayers.Format.Text=OpenLayers.Class(OpenLayers.Format,{defaultStyle:null,extractStyles:true,initialize:function(options){options=options||{};if(options.extractStyles!==false){options.defaultStyle={'externalGraphic':OpenLayers.Util.getImagesLocation()+"marker.png",'graphicWidth':21,'graphicHeight':25,'graphicXOffset':-10.5,'graphicYOffset':-12.5};} +OpenLayers.Format.prototype.initialize.apply(this,[options]);},read:function(text){var lines=text.split('\n');var columns;var features=[];for(var lcv=0;lcv<(lines.length-1);lcv++){var currLine=lines[lcv].replace(/^\s*/,'').replace(/\s*$/,'');if(currLine.charAt(0)!='#'){if(!columns){columns=currLine.split('\t');}else{var vals=currLine.split('\t');var geometry=new OpenLayers.Geometry.Point(0,0);var attributes={};var style=this.defaultStyle?OpenLayers.Util.applyDefaults({},this.defaultStyle):null;var icon,iconSize,iconOffset,overflow;var set=false;for(var valIndex=0;valIndex<vals.length;valIndex++){if(vals[valIndex]){if(columns[valIndex]=='point'){var coords=vals[valIndex].split(',');geometry.y=parseFloat(coords[0]);geometry.x=parseFloat(coords[1]);set=true;}else if(columns[valIndex]=='lat'){geometry.y=parseFloat(vals[valIndex]);set=true;}else if(columns[valIndex]=='lon'){geometry.x=parseFloat(vals[valIndex]);set=true;}else if(columns[valIndex]=='title') +attributes['title']=vals[valIndex];else if(columns[valIndex]=='image'||columns[valIndex]=='icon'&&style){style['externalGraphic']=vals[valIndex];}else if(columns[valIndex]=='iconSize'&&style){var size=vals[valIndex].split(',');style['graphicWidth']=parseFloat(size[0]);style['graphicHeight']=parseFloat(size[1]);}else if(columns[valIndex]=='iconOffset'&&style){var offset=vals[valIndex].split(',');style['graphicXOffset']=parseFloat(offset[0]);style['graphicYOffset']=parseFloat(offset[1]);}else if(columns[valIndex]=='description'){attributes['description']=vals[valIndex];}else if(columns[valIndex]=='overflow'){attributes['overflow']=vals[valIndex];}else{attributes[columns[valIndex]]=vals[valIndex];}}} +if(set){if(this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection);} +var feature=new OpenLayers.Feature.Vector(geometry,attributes,style);features.push(feature);}}}} +return features;},CLASS_NAME:"OpenLayers.Format.Text"});OpenLayers.Geometry.MultiPoint=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.Point"],initialize:function(components){OpenLayers.Geometry.Collection.prototype.initialize.apply(this,arguments);},addPoint:function(point,index){this.addComponent(point,index);},removePoint:function(point){this.removeComponent(point);},CLASS_NAME:"OpenLayers.Geometry.MultiPoint"});OpenLayers.Handler.Point=OpenLayers.Class(OpenLayers.Handler,{point:null,layer:null,multi:false,drawing:false,mouseDown:false,lastDown:null,lastUp:null,persist:false,layerOptions:null,initialize:function(control,callbacks,options){if(!(options&&options.layerOptions&&options.layerOptions.styleMap)){this.style=OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'],{});} +OpenLayers.Handler.prototype.initialize.apply(this,arguments);},activate:function(){if(!OpenLayers.Handler.prototype.activate.apply(this,arguments)){return false;} +var options=OpenLayers.Util.extend({displayInLayerSwitcher:false,calculateInRange:OpenLayers.Function.True},this.layerOptions);this.layer=new OpenLayers.Layer.Vector(this.CLASS_NAME,options);this.map.addLayer(this.layer);return true;},createFeature:function(pixel){var lonlat=this.map.getLonLatFromPixel(pixel);this.point=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat));this.callback("create",[this.point.geometry,this.point]);this.point.geometry.clearBounds();this.layer.addFeatures([this.point],{silent:true});},deactivate:function(){if(!OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){return false;} +if(this.drawing){this.cancel();} +this.destroyFeature();if(this.layer.map!=null){this.layer.destroy(false);} +this.layer=null;return true;},destroyFeature:function(){if(this.layer){this.layer.destroyFeatures();} +this.point=null;},finalize:function(cancel){var key=cancel?"cancel":"done";this.drawing=false;this.mouseDown=false;this.lastDown=null;this.lastUp=null;this.callback(key,[this.geometryClone()]);if(cancel||!this.persist){this.destroyFeature();}},cancel:function(){this.finalize(true);},click:function(evt){OpenLayers.Event.stop(evt);return false;},dblclick:function(evt){OpenLayers.Event.stop(evt);return false;},modifyFeature:function(pixel){var lonlat=this.map.getLonLatFromPixel(pixel);this.point.geometry.x=lonlat.lon;this.point.geometry.y=lonlat.lat;this.callback("modify",[this.point.geometry,this.point]);this.point.geometry.clearBounds();this.drawFeature();},drawFeature:function(){this.layer.drawFeature(this.point,this.style);},getGeometry:function(){var geometry=this.point&&this.point.geometry;if(geometry&&this.multi){geometry=new OpenLayers.Geometry.MultiPoint([geometry]);} +return geometry;},geometryClone:function(){var geom=this.getGeometry();return geom&&geom.clone();},mousedown:function(evt){if(!this.checkModifiers(evt)){return true;} +if(this.lastDown&&this.lastDown.equals(evt.xy)){return true;} +this.drawing=true;if(this.lastDown==null){if(this.persist){this.destroyFeature();} +this.createFeature(evt.xy);}else{this.modifyFeature(evt.xy);} +this.lastDown=evt.xy;return false;},mousemove:function(evt){if(this.drawing){this.modifyFeature(evt.xy);} +return true;},mouseup:function(evt){if(this.drawing){this.finalize();return false;}else{return true;}},CLASS_NAME:"OpenLayers.Handler.Point"});OpenLayers.Layer.GML=OpenLayers.Class(OpenLayers.Layer.Vector,{loaded:false,format:null,formatOptions:null,initialize:function(name,url,options){var newArguments=[];newArguments.push(name,options);OpenLayers.Layer.Vector.prototype.initialize.apply(this,newArguments);this.url=url;},setVisibility:function(visibility,noEvent){OpenLayers.Layer.Vector.prototype.setVisibility.apply(this,arguments);if(this.visibility&&!this.loaded){this.loadGML();}},moveTo:function(bounds,zoomChanged,minor){OpenLayers.Layer.Vector.prototype.moveTo.apply(this,arguments);if(this.visibility&&!this.loaded){this.loadGML();}},loadGML:function(){if(!this.loaded){this.events.triggerEvent("loadstart");OpenLayers.Request.GET({url:this.url,success:this.requestSuccess,failure:this.requestFailure,scope:this});this.loaded=true;}},setUrl:function(url){this.url=url;this.destroyFeatures();this.loaded=false;this.loadGML();},requestSuccess:function(request){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;} +var options={};OpenLayers.Util.extend(options,this.formatOptions);if(this.map&&!this.projection.equals(this.map.getProjectionObject())){options.externalProjection=this.projection;options.internalProjection=this.map.getProjectionObject();} +var gml=this.format?new this.format(options):new OpenLayers.Format.GML(options);this.addFeatures(gml.read(doc));this.events.triggerEvent("loadend");},requestFailure:function(request){OpenLayers.Console.userError(OpenLayers.i18n("errorLoadingGML",{'url':this.url}));this.events.triggerEvent("loadend");},CLASS_NAME:"OpenLayers.Layer.GML"});OpenLayers.Layer.PointTrack=OpenLayers.Class(OpenLayers.Layer.Vector,{dataFrom:null,initialize:function(name,options){OpenLayers.Layer.Vector.prototype.initialize.apply(this,arguments);},addNodes:function(pointFeatures){if(pointFeatures.length<2){OpenLayers.Console.error("At least two point features have to be added to create"+"a line from");return;} +var lines=new Array(pointFeatures.length-1);var pointFeature,startPoint,endPoint;for(var i=0,len=pointFeatures.length;i<len;i++){pointFeature=pointFeatures[i];endPoint=pointFeature.geometry;if(!endPoint){var lonlat=pointFeature.lonlat;endPoint=new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat);}else if(endPoint.CLASS_NAME!="OpenLayers.Geometry.Point"){OpenLayers.Console.error("Only features with point geometries are supported.");return;} +if(i>0){var attributes=(this.dataFrom!=null)?(pointFeatures[i+this.dataFrom].data||pointFeatures[i+this.dataFrom].attributes):null;var line=new OpenLayers.Geometry.LineString([startPoint,endPoint]);lines[i-1]=new OpenLayers.Feature.Vector(line,attributes);} +startPoint=endPoint;} +this.addFeatures(lines);},CLASS_NAME:"OpenLayers.Layer.PointTrack"});OpenLayers.Layer.PointTrack.dataFrom={'SOURCE_NODE':-1,'TARGET_NODE':0};OpenLayers.Layer.Vector.RootContainer=OpenLayers.Class(OpenLayers.Layer.Vector,{displayInLayerSwitcher:false,layers:null,initialize:function(name,options){OpenLayers.Layer.Vector.prototype.initialize.apply(this,arguments);},display:function(){},getFeatureFromEvent:function(evt){var layers=this.layers;var feature;for(var i=0;i<layers.length;i++){feature=layers[i].getFeatureFromEvent(evt);if(feature){return feature;}}},setMap:function(map){OpenLayers.Layer.Vector.prototype.setMap.apply(this,arguments);this.collectRoots();map.events.register("changelayer",this,this.handleChangeLayer);},removeMap:function(map){map.events.unregister("changelayer",this,this.handleChangeLayer);this.resetRoots();OpenLayers.Layer.Vector.prototype.removeMap.apply(this,arguments);},collectRoots:function(){var layer;for(var i=0;i<this.map.layers.length;++i){layer=this.map.layers[i];if(OpenLayers.Util.indexOf(this.layers,layer)!=-1){layer.renderer.moveRoot(this.renderer);}}},resetRoots:function(){var layer;for(var i=0;i<this.layers.length;++i){layer=this.layers[i];if(this.renderer&&layer.renderer.getRenderLayerId()==this.id){this.renderer.moveRoot(layer.renderer);}}},handleChangeLayer:function(evt){var layer=evt.layer;if(evt.property=="order"&&OpenLayers.Util.indexOf(this.layers,layer)!=-1){this.resetRoots();this.collectRoots();}},CLASS_NAME:"OpenLayers.Layer.Vector.RootContainer"});OpenLayers.Layer.WFS=OpenLayers.Class(OpenLayers.Layer.Vector,OpenLayers.Layer.Markers,{isBaseLayer:false,tile:null,ratio:2,DEFAULT_PARAMS:{service:"WFS",version:"1.0.0",request:"GetFeature"},featureClass:null,format:null,formatObject:null,formatOptions:null,vectorMode:true,encodeBBOX:false,extractAttributes:false,initialize:function(name,url,params,options){if(options==undefined){options={};} +if(options.featureClass||!OpenLayers.Layer.Vector||!OpenLayers.Feature.Vector){this.vectorMode=false;} +params=OpenLayers.Util.upperCaseObject(params);OpenLayers.Util.extend(options,{'reportError':false});var newArguments=[];newArguments.push(name,options);OpenLayers.Layer.Vector.prototype.initialize.apply(this,newArguments);if(!this.renderer||!this.vectorMode){this.vectorMode=false;if(!options.featureClass){options.featureClass=OpenLayers.Feature.WFS;} +OpenLayers.Layer.Markers.prototype.initialize.apply(this,newArguments);} +if(this.params&&this.params.typename&&!this.options.typename){this.options.typename=this.params.typename;} +if(!this.options.geometry_column){this.options.geometry_column="the_geom";} +this.params=OpenLayers.Util.applyDefaults(params,OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS));this.url=url;},destroy:function(){if(this.vectorMode){OpenLayers.Layer.Vector.prototype.destroy.apply(this,arguments);}else{OpenLayers.Layer.Markers.prototype.destroy.apply(this,arguments);} +if(this.tile){this.tile.destroy();} +this.tile=null;this.ratio=null;this.featureClass=null;this.format=null;if(this.formatObject&&this.formatObject.destroy){this.formatObject.destroy();} +this.formatObject=null;this.formatOptions=null;this.vectorMode=null;this.encodeBBOX=null;this.extractAttributes=null;},setMap:function(map){if(this.vectorMode){OpenLayers.Layer.Vector.prototype.setMap.apply(this,arguments);var options={'extractAttributes':this.extractAttributes};OpenLayers.Util.extend(options,this.formatOptions);if(this.map&&!this.projection.equals(this.map.getProjectionObject())){options.externalProjection=this.projection;options.internalProjection=this.map.getProjectionObject();} +this.formatObject=this.format?new this.format(options):new OpenLayers.Format.GML(options);}else{OpenLayers.Layer.Markers.prototype.setMap.apply(this,arguments);}},moveTo:function(bounds,zoomChanged,dragging){if(this.vectorMode){OpenLayers.Layer.Vector.prototype.moveTo.apply(this,arguments);}else{OpenLayers.Layer.Markers.prototype.moveTo.apply(this,arguments);} +if(dragging){return false;} +if(zoomChanged){if(this.vectorMode){this.renderer.clear();}} +if(this.options.minZoomLevel){OpenLayers.Console.warn(OpenLayers.i18n('minZoomLevelError'));if(this.map.getZoom()<this.options.minZoomLevel){return null;}} +if(bounds==null){bounds=this.map.getExtent();} +var firstRendering=(this.tile==null);var outOfBounds=(!firstRendering&&!this.tile.bounds.containsBounds(bounds));if(zoomChanged||firstRendering||(!dragging&&outOfBounds)){var center=bounds.getCenterLonLat();var tileWidth=bounds.getWidth()*this.ratio;var tileHeight=bounds.getHeight()*this.ratio;var tileBounds=new OpenLayers.Bounds(center.lon-(tileWidth/2),center.lat-(tileHeight/2),center.lon+(tileWidth/2),center.lat+(tileHeight/2));var tileSize=this.map.getSize();tileSize.w=tileSize.w*this.ratio;tileSize.h=tileSize.h*this.ratio;var ul=new OpenLayers.LonLat(tileBounds.left,tileBounds.top);var pos=this.map.getLayerPxFromLonLat(ul);var url=this.getFullRequestString();var params=null;var filter=this.params.filter||this.params.FILTER;if(filter){params={FILTER:filter};} +else{params={BBOX:this.encodeBBOX?tileBounds.toBBOX():tileBounds.toArray()};} +if(this.map&&!this.projection.equals(this.map.getProjectionObject())){var projectedBounds=tileBounds.clone();projectedBounds.transform(this.map.getProjectionObject(),this.projection);if(!filter){params.BBOX=this.encodeBBOX?projectedBounds.toBBOX():projectedBounds.toArray();}} +url+="&"+OpenLayers.Util.getParameterString(params);if(!this.tile){this.tile=new OpenLayers.Tile.WFS(this,pos,tileBounds,url,tileSize);this.addTileMonitoringHooks(this.tile);this.tile.draw();}else{if(this.vectorMode){this.destroyFeatures();this.renderer.clear();}else{this.clearMarkers();} +this.removeTileMonitoringHooks(this.tile);this.tile.destroy();this.tile=null;this.tile=new OpenLayers.Tile.WFS(this,pos,tileBounds,url,tileSize);this.addTileMonitoringHooks(this.tile);this.tile.draw();}}},addTileMonitoringHooks:function(tile){tile.onLoadStart=function(){if(this==this.layer.tile){this.layer.events.triggerEvent("loadstart");}};tile.events.register("loadstart",tile,tile.onLoadStart);tile.onLoadEnd=function(){if(this==this.layer.tile){this.layer.events.triggerEvent("tileloaded");this.layer.events.triggerEvent("loadend");}};tile.events.register("loadend",tile,tile.onLoadEnd);tile.events.register("unload",tile,tile.onLoadEnd);},removeTileMonitoringHooks:function(tile){tile.unload();tile.events.un({"loadstart":tile.onLoadStart,"loadend":tile.onLoadEnd,"unload":tile.onLoadEnd,scope:tile});},onMapResize:function(){if(this.vectorMode){OpenLayers.Layer.Vector.prototype.onMapResize.apply(this,arguments);}else{OpenLayers.Layer.Markers.prototype.onMapResize.apply(this,arguments);}},display:function(){if(this.vectorMode){OpenLayers.Layer.Vector.prototype.display.apply(this,arguments);}else{OpenLayers.Layer.Markers.prototype.display.apply(this,arguments);}},mergeNewParams:function(newParams){var upperParams=OpenLayers.Util.upperCaseObject(newParams);var newArguments=[upperParams];return OpenLayers.Layer.HTTPRequest.prototype.mergeNewParams.apply(this,newArguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.WFS(this.name,this.url,this.params,this.getOptions());} +if(this.vectorMode){obj=OpenLayers.Layer.Vector.prototype.clone.apply(this,[obj]);}else{obj=OpenLayers.Layer.Markers.prototype.clone.apply(this,[obj]);} +return obj;},getFullRequestString:function(newParams,altUrl){var projectionCode=this.projection.getCode()||this.map.getProjection();this.params.SRS=(projectionCode=="none")?null:projectionCode;return OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(this,arguments);},commit:function(){if(!this.writer){var options={};if(this.map&&!this.projection.equals(this.map.getProjectionObject())){options.externalProjection=this.projection;options.internalProjection=this.map.getProjectionObject();} +this.writer=new OpenLayers.Format.WFS(options,this);} +var data=this.writer.write(this.features);OpenLayers.Request.POST({url:this.url,data:data,success:this.commitSuccess,failure:this.commitFailure,scope:this});},commitSuccess:function(request){var response=request.responseText;if(response.indexOf('SUCCESS')!=-1){this.commitReport(OpenLayers.i18n("commitSuccess",{'response':response}));for(var i=0;i<this.features.length;i++){this.features[i].state=null;}}else if(response.indexOf('FAILED')!=-1||response.indexOf('Exception')!=-1){this.commitReport(OpenLayers.i18n("commitFailed",{'response':response}));}},commitFailure:function(request){},commitReport:function(string,response){OpenLayers.Console.userError(string);},refresh:function(){if(this.tile){if(this.vectorMode){this.renderer.clear();this.features.length=0;}else{this.clearMarkers();this.markers.length=0;} +this.tile.draw();}},getDataExtent:function(){var extent;if(this.vectorMode){extent=OpenLayers.Layer.Vector.prototype.getDataExtent.apply(this);}else{extent=OpenLayers.Layer.Markers.prototype.getDataExtent.apply(this);} +return extent;},setOpacity:function(opacity){if(this.vectorMode){OpenLayers.Layer.Vector.prototype.setOpacity.apply(this,[opacity]);}else{OpenLayers.Layer.Markers.prototype.setOpacity.apply(this,[opacity]);}},CLASS_NAME:"OpenLayers.Layer.WFS"});OpenLayers.Protocol.HTTP=OpenLayers.Class(OpenLayers.Protocol,{url:null,headers:null,params:null,callback:null,scope:null,readWithPOST:false,wildcarded:false,initialize:function(options){options=options||{};this.params={};this.headers={};OpenLayers.Protocol.prototype.initialize.apply(this,arguments);},destroy:function(){this.params=null;this.headers=null;OpenLayers.Protocol.prototype.destroy.apply(this);},read:function(options){OpenLayers.Protocol.prototype.read.apply(this,arguments);options=OpenLayers.Util.applyDefaults(options,this.options);options.params=OpenLayers.Util.applyDefaults(options.params,this.options.params);if(options.filter){options.params=this.filterToParams(options.filter,options.params);} +var readWithPOST=(options.readWithPOST!==undefined)?options.readWithPOST:this.readWithPOST;var resp=new OpenLayers.Protocol.Response({requestType:"read"});if(readWithPOST){resp.priv=OpenLayers.Request.POST({url:options.url,callback:this.createCallback(this.handleRead,resp,options),data:OpenLayers.Util.getParameterString(options.params),headers:{"Content-Type":"application/x-www-form-urlencoded"}});}else{resp.priv=OpenLayers.Request.GET({url:options.url,callback:this.createCallback(this.handleRead,resp,options),params:options.params,headers:options.headers});} +return resp;},handleRead:function(resp,options){this.handleResponse(resp,options);},filterToParams:function(filter,params){params=params||{};var className=filter.CLASS_NAME;var filterType=className.substring(className.lastIndexOf(".")+1);switch(filterType){case"Spatial":switch(filter.type){case OpenLayers.Filter.Spatial.BBOX:params.bbox=filter.value.toArray();break;case OpenLayers.Filter.Spatial.DWITHIN:params.tolerance=filter.distance;case OpenLayers.Filter.Spatial.WITHIN:params.lon=filter.value.x;params.lat=filter.value.y;break;default:OpenLayers.Console.warn("Unknown spatial filter type "+filter.type);} +break;case"Comparison":var op=OpenLayers.Protocol.HTTP.COMP_TYPE_TO_OP_STR[filter.type];if(op!==undefined){var value=filter.value;if(filter.type==OpenLayers.Filter.Comparison.LIKE){value=this.regex2value(value);if(this.wildcarded){value="%"+value+"%";}} +params[filter.property+"__"+op]=value;params.queryable=params.queryable||[];params.queryable.push(filter.property);}else{OpenLayers.Console.warn("Unknown comparison filter type "+filter.type);} +break;case"Logical":if(filter.type===OpenLayers.Filter.Logical.AND){for(var i=0,len=filter.filters.length;i<len;i++){params=this.filterToParams(filter.filters[i],params);}}else{OpenLayers.Console.warn("Unsupported logical filter type "+filter.type);} +break;default:OpenLayers.Console.warn("Unknown filter type "+filterType);} +return params;},regex2value:function(value){value=value.replace(/%/g,"\\%");value=value.replace(/\\\\\.(\*)?/g,function($0,$1){return $1?$0:"\\\\_";});value=value.replace(/\\\\\.\*/g,"\\\\%");value=value.replace(/(\\)?\.(\*)?/g,function($0,$1,$2){return $1||$2?$0:"_";});value=value.replace(/(\\)?\.\*/g,function($0,$1){return $1?$0:"%";});value=value.replace(/\\\./g,".");value=value.replace(/(\\)?\\\*/g,function($0,$1){return $1?$0:"*";});return value;},create:function(features,options){options=OpenLayers.Util.applyDefaults(options,this.options);var resp=new OpenLayers.Protocol.Response({reqFeatures:features,requestType:"create"});resp.priv=OpenLayers.Request.POST({url:options.url,callback:this.createCallback(this.handleCreate,resp,options),headers:options.headers,data:this.format.write(features)});return resp;},handleCreate:function(resp,options){this.handleResponse(resp,options);},update:function(feature,options){options=options||{};var url=options.url||feature.url||this.options.url+"/"+feature.fid;options=OpenLayers.Util.applyDefaults(options,this.options);var resp=new OpenLayers.Protocol.Response({reqFeatures:feature,requestType:"update"});resp.priv=OpenLayers.Request.PUT({url:url,callback:this.createCallback(this.handleUpdate,resp,options),headers:options.headers,data:this.format.write(feature)});return resp;},handleUpdate:function(resp,options){this.handleResponse(resp,options);},"delete":function(feature,options){options=options||{};var url=options.url||feature.url||this.options.url+"/"+feature.fid;options=OpenLayers.Util.applyDefaults(options,this.options);var resp=new OpenLayers.Protocol.Response({reqFeatures:feature,requestType:"delete"});resp.priv=OpenLayers.Request.DELETE({url:url,callback:this.createCallback(this.handleDelete,resp,options),headers:options.headers});return resp;},handleDelete:function(resp,options){this.handleResponse(resp,options);},handleResponse:function(resp,options){var request=resp.priv;if(options.callback){if(request.status>=200&&request.status<300){if(resp.requestType!="delete"){resp.features=this.parseFeatures(request);} +resp.code=OpenLayers.Protocol.Response.SUCCESS;}else{resp.code=OpenLayers.Protocol.Response.FAILURE;} +options.callback.call(options.scope,resp);}},parseFeatures:function(request){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;} +if(!doc||doc.length<=0){return null;} +return this.format.read(doc);},commit:function(features,options){options=OpenLayers.Util.applyDefaults(options,this.options);var resp=[],nResponses=0;var types={};types[OpenLayers.State.INSERT]=[];types[OpenLayers.State.UPDATE]=[];types[OpenLayers.State.DELETE]=[];var feature,list,requestFeatures=[];for(var i=0,len=features.length;i<len;++i){feature=features[i];list=types[feature.state];if(list){list.push(feature);requestFeatures.push(feature);}} +var nRequests=(types[OpenLayers.State.INSERT].length>0?1:0)+ +types[OpenLayers.State.UPDATE].length+ +types[OpenLayers.State.DELETE].length;var success=true;var finalResponse=new OpenLayers.Protocol.Response({reqFeatures:requestFeatures});function insertCallback(response){var len=response.features?response.features.length:0;var fids=new Array(len);for(var i=0;i<len;++i){fids[i]=response.features[i].fid;} +finalResponse.insertIds=fids;callback.apply(this,[response]);} +function callback(response){this.callUserCallback(response,options);success=success&&response.success();nResponses++;if(nResponses>=nRequests){if(options.callback){finalResponse.code=success?OpenLayers.Protocol.Response.SUCCESS:OpenLayers.Protocol.Response.FAILURE;options.callback.apply(options.scope,[finalResponse]);}}} +var queue=types[OpenLayers.State.INSERT];if(queue.length>0){resp.push(this.create(queue,OpenLayers.Util.applyDefaults({callback:insertCallback,scope:this},options.create)));} +queue=types[OpenLayers.State.UPDATE];for(var i=queue.length-1;i>=0;--i){resp.push(this.update(queue[i],OpenLayers.Util.applyDefaults({callback:callback,scope:this},options.update)));} +queue=types[OpenLayers.State.DELETE];for(var i=queue.length-1;i>=0;--i){resp.push(this["delete"](queue[i],OpenLayers.Util.applyDefaults({callback:callback,scope:this},options["delete"])));} +return resp;},abort:function(response){if(response){response.priv.abort();}},callUserCallback:function(resp,options){var opt=options[resp.requestType];if(opt&&opt.callback){opt.callback.call(opt.scope,resp);}},CLASS_NAME:"OpenLayers.Protocol.HTTP"});(function(){var o=OpenLayers.Protocol.HTTP.COMP_TYPE_TO_OP_STR={};o[OpenLayers.Filter.Comparison.EQUAL_TO]="eq";o[OpenLayers.Filter.Comparison.NOT_EQUAL_TO]="ne";o[OpenLayers.Filter.Comparison.LESS_THAN]="lt";o[OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO]="lte";o[OpenLayers.Filter.Comparison.GREATER_THAN]="gt";o[OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO]="gte";o[OpenLayers.Filter.Comparison.LIKE]="ilike";})();OpenLayers.Strategy.BBOX=OpenLayers.Class(OpenLayers.Strategy,{bounds:null,resolution:null,ratio:2,resFactor:null,response:null,initialize:function(options){OpenLayers.Strategy.prototype.initialize.apply(this,[options]);},activate:function(){var activated=OpenLayers.Strategy.prototype.activate.call(this);if(activated){this.layer.events.on({"moveend":this.update,scope:this});this.layer.events.on({"refresh":this.update,scope:this});} +return activated;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.layer.events.un({"moveend":this.update,scope:this});this.layer.events.un({"refresh":this.update,scope:this});} +return deactivated;},update:function(options){var mapBounds=this.getMapBounds();if((options&&options.force)||this.invalidBounds(mapBounds)){this.calculateBounds(mapBounds);this.resolution=this.layer.map.getResolution();this.triggerRead();}},getMapBounds:function(){var bounds=this.layer.map.getExtent();if(!this.layer.projection.equals(this.layer.map.getProjectionObject())){bounds=bounds.clone().transform(this.layer.map.getProjectionObject(),this.layer.projection);} +return bounds;},invalidBounds:function(mapBounds){if(!mapBounds){mapBounds=this.getMapBounds();} +var invalid=!this.bounds||!this.bounds.containsBounds(mapBounds);if(!invalid&&this.resFactor){var ratio=this.resolution/this.layer.map.getResolution();invalid=(ratio>=this.resFactor||ratio<=(1/this.resFactor));} +return invalid;},calculateBounds:function(mapBounds){if(!mapBounds){mapBounds=this.getMapBounds();} +var center=mapBounds.getCenterLonLat();var dataWidth=mapBounds.getWidth()*this.ratio;var dataHeight=mapBounds.getHeight()*this.ratio;this.bounds=new OpenLayers.Bounds(center.lon-(dataWidth/2),center.lat-(dataHeight/2),center.lon+(dataWidth/2),center.lat+(dataHeight/2));},triggerRead:function(){if(this.response){this.layer.protocol.abort(this.response);this.layer.events.triggerEvent("loadend");} +this.layer.events.triggerEvent("loadstart");this.response=this.layer.protocol.read({filter:this.createFilter(),callback:this.merge,scope:this});},createFilter:function(){var filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.BBOX,value:this.bounds,projection:this.layer.projection});if(this.layer.filter){filter=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND,filters:[this.layer.filter,filter]});} +return filter;},merge:function(resp){this.layer.destroyFeatures();var features=resp.features;if(features&&features.length>0){var remote=this.layer.projection;var local=this.layer.map.getProjectionObject();if(!local.equals(remote)){var geom;for(var i=0,len=features.length;i<len;++i){geom=features[i].geometry;if(geom){geom.transform(remote,local);}}} +this.layer.addFeatures(features);} +this.response=null;this.layer.events.triggerEvent("loadend");},CLASS_NAME:"OpenLayers.Strategy.BBOX"});OpenLayers.Control.SelectFeature=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:["beforefeaturehighlighted","featurehighlighted","featureunhighlighted"],multipleKey:null,toggleKey:null,multiple:false,clickout:true,toggle:false,hover:false,highlightOnly:false,box:false,onBeforeSelect:function(){},onSelect:function(){},onUnselect:function(){},scope:null,geometryTypes:null,layer:null,layers:null,callbacks:null,selectStyle:null,renderIntent:"select",handlers:null,initialize:function(layers,options){this.EVENT_TYPES=OpenLayers.Control.SelectFeature.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);if(this.scope===null){this.scope=this;} +this.initLayer(layers);var callbacks={click:this.clickFeature,clickout:this.clickoutFeature};if(this.hover){callbacks.over=this.overFeature;callbacks.out=this.outFeature;} +this.callbacks=OpenLayers.Util.extend(callbacks,this.callbacks);this.handlers={feature:new OpenLayers.Handler.Feature(this,this.layer,this.callbacks,{geometryTypes:this.geometryTypes})};if(this.box){this.handlers.box=new OpenLayers.Handler.Box(this,{done:this.selectBox},{boxDivClassName:"olHandlerBoxSelectFeature"});}},initLayer:function(layers){if(layers instanceof Array){this.layers=layers;this.layer=new OpenLayers.Layer.Vector.RootContainer(this.id+"_container",{layers:layers});}else{this.layer=layers;}},destroy:function(){if(this.active&&this.layers){this.map.removeLayer(this.layer);} +OpenLayers.Control.prototype.destroy.apply(this,arguments);if(this.layers){this.layer.destroy();}},activate:function(){if(!this.active){if(this.layers){this.map.addLayer(this.layer);} +this.handlers.feature.activate();if(this.box&&this.handlers.box){this.handlers.box.activate();}} +return OpenLayers.Control.prototype.activate.apply(this,arguments);},deactivate:function(){if(this.active){this.handlers.feature.deactivate();if(this.handlers.box){this.handlers.box.deactivate();} +if(this.layers){this.map.removeLayer(this.layer);}} +return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},unselectAll:function(options){var layers=this.layers||[this.layer];var layer,feature;for(var l=0;l<layers.length;++l){layer=layers[l];for(var i=layer.selectedFeatures.length-1;i>=0;--i){feature=layer.selectedFeatures[i];if(!options||options.except!=feature){this.unselect(feature);}}}},clickFeature:function(feature){if(!this.hover){var selected=(OpenLayers.Util.indexOf(feature.layer.selectedFeatures,feature)>-1);if(selected){if(this.toggleSelect()){this.unselect(feature);}else if(!this.multipleSelect()){this.unselectAll({except:feature});}}else{if(!this.multipleSelect()){this.unselectAll({except:feature});} +this.select(feature);}}},multipleSelect:function(){return this.multiple||(this.handlers.feature.evt&&this.handlers.feature.evt[this.multipleKey]);},toggleSelect:function(){return this.toggle||(this.handlers.feature.evt&&this.handlers.feature.evt[this.toggleKey]);},clickoutFeature:function(feature){if(!this.hover&&this.clickout){this.unselectAll();}},overFeature:function(feature){var layer=feature.layer;if(this.hover){if(this.highlightOnly){this.highlight(feature);}else if(OpenLayers.Util.indexOf(layer.selectedFeatures,feature)==-1){this.select(feature);}}},outFeature:function(feature){if(this.hover){if(this.highlightOnly){if(feature._lastHighlighter==this.id){if(feature._prevHighlighter&&feature._prevHighlighter!=this.id){delete feature._lastHighlighter;var control=this.map.getControl(feature._prevHighlighter);if(control){control.highlight(feature);}}else{this.unhighlight(feature);}}}else{this.unselect(feature);}}},highlight:function(feature){var layer=feature.layer;var cont=this.events.triggerEvent("beforefeaturehighlighted",{feature:feature});if(cont!==false){feature._prevHighlighter=feature._lastHighlighter;feature._lastHighlighter=this.id;var style=this.selectStyle||this.renderIntent;layer.drawFeature(feature,style);this.events.triggerEvent("featurehighlighted",{feature:feature});}},unhighlight:function(feature){var layer=feature.layer;feature._lastHighlighter=feature._prevHighlighter;delete feature._prevHighlighter;layer.drawFeature(feature,feature.style||feature.layer.style||"default");this.events.triggerEvent("featureunhighlighted",{feature:feature});},select:function(feature){var cont=this.onBeforeSelect.call(this.scope,feature);var layer=feature.layer;if(cont!==false){cont=layer.events.triggerEvent("beforefeatureselected",{feature:feature});if(cont!==false){layer.selectedFeatures.push(feature);this.highlight(feature);if(!this.handlers.feature.lastFeature){this.handlers.feature.lastFeature=layer.selectedFeatures[0];} +layer.events.triggerEvent("featureselected",{feature:feature});this.onSelect.call(this.scope,feature);}}},unselect:function(feature){var layer=feature.layer;this.unhighlight(feature);OpenLayers.Util.removeItem(layer.selectedFeatures,feature);layer.events.triggerEvent("featureunselected",{feature:feature});this.onUnselect.call(this.scope,feature);},selectBox:function(position){if(position instanceof OpenLayers.Bounds){var minXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.left,position.bottom));var maxXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.right,position.top));var bounds=new OpenLayers.Bounds(minXY.lon,minXY.lat,maxXY.lon,maxXY.lat);if(!this.multipleSelect()){this.unselectAll();} +var prevMultiple=this.multiple;this.multiple=true;var layers=this.layers||[this.layer];var layer;for(var l=0;l<layers.length;++l){layer=layers[l];for(var i=0,len=layer.features.length;i<len;++i){var feature=layer.features[i];if(!feature.getVisibility()){continue;} +if(this.geometryTypes==null||OpenLayers.Util.indexOf(this.geometryTypes,feature.geometry.CLASS_NAME)>-1){if(bounds.toGeometry().intersects(feature.geometry)){if(OpenLayers.Util.indexOf(layer.selectedFeatures,feature)==-1){this.select(feature);}}}}} +this.multiple=prevMultiple;}},setMap:function(map){this.handlers.feature.setMap(map);if(this.box){this.handlers.box.setMap(map);} +OpenLayers.Control.prototype.setMap.apply(this,arguments);},setLayer:function(layers){var isActive=this.active;this.unselectAll();this.deactivate();if(this.layers){this.layer.destroy();this.layers=null;} +this.initLayer(layers);this.handlers.feature.layer=this.layer;if(isActive){this.activate();}},CLASS_NAME:"OpenLayers.Control.SelectFeature"});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(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){var obj={};this.readers.ogc["Filter"].apply(this,[data,obj]);return obj.filter;},readers:{"ogc":{"Filter":function(node,parent){var obj={fids:[],filters:[]};this.readChildNodes(node,obj);if(obj.fids.length>0){parent.filter=new OpenLayers.Filter.FeatureId({fids:obj.fids});}else if(obj.filters.length>0){parent.filter=obj.filters[0];}},"FeatureId":function(node,obj){var fid=node.getAttribute("fid");if(fid){obj.fids.push(fid);}},"And":function(node,obj){var filter=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND});this.readChildNodes(node,filter);obj.filters.push(filter);},"Or":function(node,obj){var filter=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.OR});this.readChildNodes(node,filter);obj.filters.push(filter);},"Not":function(node,obj){var filter=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.NOT});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsLessThan":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.LESS_THAN});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsGreaterThan":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.GREATER_THAN});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsLessThanOrEqualTo":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsGreaterThanOrEqualTo":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsBetween":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.BETWEEN});this.readChildNodes(node,filter);obj.filters.push(filter);},"Literal":function(node,obj){obj.value=OpenLayers.String.numericIf(this.getChildValue(node));},"PropertyName":function(node,filter){filter.property=this.getChildValue(node);},"LowerBoundary":function(node,filter){filter.lowerBoundary=OpenLayers.String.numericIf(this.readOgcExpression(node));},"UpperBoundary":function(node,filter){filter.upperBoundary=OpenLayers.String.numericIf(this.readOgcExpression(node));},"Intersects":function(node,obj){this.readSpatial(node,obj,OpenLayers.Filter.Spatial.INTERSECTS);},"Within":function(node,obj){this.readSpatial(node,obj,OpenLayers.Filter.Spatial.WITHIN);},"Contains":function(node,obj){this.readSpatial(node,obj,OpenLayers.Filter.Spatial.CONTAINS);},"DWithin":function(node,obj){this.readSpatial(node,obj,OpenLayers.Filter.Spatial.DWITHIN);},"Distance":function(node,obj){obj.distance=parseInt(this.getChildValue(node));obj.distanceUnits=node.getAttribute("units");}}},readSpatial:function(node,obj,type){var filter=new OpenLayers.Filter.Spatial({type:type});this.readChildNodes(node,filter);filter.value=filter.components[0];delete filter.components;obj.filters.push(filter);},readOgcExpression:function(node){var obj={};this.readChildNodes(node,obj);var value=obj.value;if(value===undefined){value=this.getChildValue(node);} +return value;},write:function(filter){return this.writers.ogc["Filter"].apply(this,[filter]);},writers:{"ogc":{"Filter":function(filter){var node=this.createElementNSPlus("ogc:Filter");var sub=filter.CLASS_NAME.split(".").pop();if(sub=="FeatureId"){for(var i=0;i<filter.fids.length;++i){this.writeNode("FeatureId",filter.fids[i],node);}}else{this.writeNode(this.getFilterType(filter),filter,node);} +return node;},"FeatureId":function(fid){return this.createElementNSPlus("ogc:FeatureId",{attributes:{fid:fid}});},"And":function(filter){var node=this.createElementNSPlus("ogc:And");var childFilter;for(var i=0;i<filter.filters.length;++i){childFilter=filter.filters[i];this.writeNode(this.getFilterType(childFilter),childFilter,node);} +return node;},"Or":function(filter){var node=this.createElementNSPlus("ogc:Or");var childFilter;for(var i=0;i<filter.filters.length;++i){childFilter=filter.filters[i];this.writeNode(this.getFilterType(childFilter),childFilter,node);} +return node;},"Not":function(filter){var node=this.createElementNSPlus("ogc:Not");var childFilter=filter.filters[0];this.writeNode(this.getFilterType(childFilter),childFilter,node);return node;},"PropertyIsLessThan":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsLessThan");this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.value,node);return node;},"PropertyIsGreaterThan":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsGreaterThan");this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.value,node);return node;},"PropertyIsLessThanOrEqualTo":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsLessThanOrEqualTo");this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.value,node);return node;},"PropertyIsGreaterThanOrEqualTo":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsGreaterThanOrEqualTo");this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.value,node);return node;},"PropertyIsBetween":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsBetween");this.writeNode("PropertyName",filter,node);this.writeNode("LowerBoundary",filter,node);this.writeNode("UpperBoundary",filter,node);return node;},"PropertyName":function(filter){return this.createElementNSPlus("ogc:PropertyName",{value:filter.property});},"Literal":function(value){return this.createElementNSPlus("ogc:Literal",{value:value});},"LowerBoundary":function(filter){var node=this.createElementNSPlus("ogc:LowerBoundary");this.writeNode("Literal",filter.lowerBoundary,node);return node;},"UpperBoundary":function(filter){var node=this.createElementNSPlus("ogc:UpperBoundary");this.writeNode("Literal",filter.upperBoundary,node);return node;},"INTERSECTS":function(filter){return this.writeSpatial(filter,"Intersects");},"WITHIN":function(filter){return this.writeSpatial(filter,"Within");},"CONTAINS":function(filter){return this.writeSpatial(filter,"Contains");},"DWITHIN":function(filter){var node=this.writeSpatial(filter,"DWithin");this.writeNode("Distance",filter,node);return node;},"Distance":function(filter){return this.createElementNSPlus("ogc:Distance",{attributes:{units:filter.distanceUnits},value:filter.distance});}}},getFilterType:function(filter){var filterType=this.filterMap[filter.type];if(!filterType){throw"Filter writing not supported for rule type: "+filter.type;} +return filterType;},filterMap:{"&&":"And","||":"Or","!":"Not","==":"PropertyIsEqualTo","!=":"PropertyIsNotEqualTo","<":"PropertyIsLessThan",">":"PropertyIsGreaterThan","<=":"PropertyIsLessThanOrEqualTo",">=":"PropertyIsGreaterThanOrEqualTo","..":"PropertyIsBetween","~":"PropertyIsLike","BBOX":"BBOX","DWITHIN":"DWITHIN","WITHIN":"WITHIN","CONTAINS":"CONTAINS","INTERSECTS":"INTERSECTS"},CLASS_NAME:"OpenLayers.Format.Filter.v1"});OpenLayers.Geometry.Curve=OpenLayers.Class(OpenLayers.Geometry.MultiPoint,{componentTypes:["OpenLayers.Geometry.Point"],initialize:function(points){OpenLayers.Geometry.MultiPoint.prototype.initialize.apply(this,arguments);},getLength:function(){var length=0.0;if(this.components&&(this.components.length>1)){for(var i=1,len=this.components.length;i<len;i++){length+=this.components[i-1].distanceTo(this.components[i]);}} +return length;},getGeodesicLength:function(projection){var geom=this;if(projection){var gg=new OpenLayers.Projection("EPSG:4326");if(!gg.equals(projection)){geom=this.clone().transform(projection,gg);}} +var length=0.0;if(geom.components&&(geom.components.length>1)){var p1,p2;for(var i=1,len=geom.components.length;i<len;i++){p1=geom.components[i-1];p2=geom.components[i];length+=OpenLayers.Util.distVincenty({lon:p1.x,lat:p1.y},{lon:p2.x,lat:p2.y});}} +return length*1000;},CLASS_NAME:"OpenLayers.Geometry.Curve"});OpenLayers.Layer.Text=OpenLayers.Class(OpenLayers.Layer.Markers,{location:null,features:null,formatOptions:null,selectedFeature:null,initialize:function(name,options){OpenLayers.Layer.Markers.prototype.initialize.apply(this,arguments);this.features=new Array();},destroy:function(){OpenLayers.Layer.Markers.prototype.destroy.apply(this,arguments);this.clearFeatures();this.features=null;},loadText:function(){if(!this.loaded){if(this.location!=null){var onFail=function(e){this.events.triggerEvent("loadend");};this.events.triggerEvent("loadstart");OpenLayers.Request.GET({url:this.location,success:this.parseData,failure:onFail,scope:this});this.loaded=true;}}},moveTo:function(bounds,zoomChanged,minor){OpenLayers.Layer.Markers.prototype.moveTo.apply(this,arguments);if(this.visibility&&!this.loaded){this.loadText();}},parseData:function(ajaxRequest){var text=ajaxRequest.responseText;var options={};OpenLayers.Util.extend(options,this.formatOptions);if(this.map&&!this.projection.equals(this.map.getProjectionObject())){options.externalProjection=this.projection;options.internalProjection=this.map.getProjectionObject();} +var parser=new OpenLayers.Format.Text(options);var features=parser.read(text);for(var i=0,len=features.length;i<len;i++){var data={};var feature=features[i];var location;var iconSize,iconOffset;location=new OpenLayers.LonLat(feature.geometry.x,feature.geometry.y);if(feature.style.graphicWidth&&feature.style.graphicHeight){iconSize=new OpenLayers.Size(feature.style.graphicWidth,feature.style.graphicHeight);} +if(feature.style.graphicXOffset!==undefined&&feature.style.graphicYOffset!==undefined){iconOffset=new OpenLayers.Pixel(feature.style.graphicXOffset,feature.style.graphicYOffset);} +if(feature.style.externalGraphic!=null){data.icon=new OpenLayers.Icon(feature.style.externalGraphic,iconSize,iconOffset);}else{data.icon=OpenLayers.Marker.defaultIcon();if(iconSize!=null){data.icon.setSize(iconSize);}} +if((feature.attributes.title!=null)&&(feature.attributes.description!=null)){data['popupContentHTML']='<h2>'+feature.attributes.title+'</h2>'+'<p>'+feature.attributes.description+'</p>';} +data['overflow']=feature.attributes.overflow||"auto";var markerFeature=new OpenLayers.Feature(this,location,data);this.features.push(markerFeature);var marker=markerFeature.createMarker();if((feature.attributes.title!=null)&&(feature.attributes.description!=null)){marker.events.register('click',markerFeature,this.markerClick);} +this.addMarker(marker);} +this.events.triggerEvent("loadend");},markerClick:function(evt){var sameMarkerClicked=(this==this.layer.selectedFeature);this.layer.selectedFeature=(!sameMarkerClicked)?this:null;for(var i=0,len=this.layer.map.popups.length;i<len;i++){this.layer.map.removePopup(this.layer.map.popups[i]);} +if(!sameMarkerClicked){this.layer.map.addPopup(this.createPopup());} +OpenLayers.Event.stop(evt);},clearFeatures:function(){if(this.features!=null){while(this.features.length>0){var feature=this.features[0];OpenLayers.Util.removeItem(this.features,feature);feature.destroy();}}},CLASS_NAME:"OpenLayers.Layer.Text"});OpenLayers.Control.ModifyFeature=OpenLayers.Class(OpenLayers.Control,{geometryTypes:null,clickout:true,toggle:true,standalone:false,layer:null,feature:null,vertices:null,virtualVertices:null,selectControl:null,dragControl:null,handlers:null,deleteCodes:null,virtualStyle:null,mode:null,modified:false,radiusHandle:null,dragHandle:null,onModificationStart:function(){},onModification:function(){},onModificationEnd:function(){},initialize:function(layer,options){this.layer=layer;this.vertices=[];this.virtualVertices=[];this.virtualStyle=OpenLayers.Util.extend({},this.layer.style||this.layer.styleMap.createSymbolizer());this.virtualStyle.fillOpacity=0.3;this.virtualStyle.strokeOpacity=0.3;this.deleteCodes=[46,68];this.mode=OpenLayers.Control.ModifyFeature.RESHAPE;OpenLayers.Control.prototype.initialize.apply(this,[options]);if(!(this.deleteCodes instanceof Array)){this.deleteCodes=[this.deleteCodes];} +var control=this;var selectOptions={geometryTypes:this.geometryTypes,clickout:this.clickout,toggle:this.toggle,onBeforeSelect:this.beforeSelectFeature,onSelect:this.selectFeature,onUnselect:this.unselectFeature,scope:this};if(this.standalone===false){this.selectControl=new OpenLayers.Control.SelectFeature(layer,selectOptions);} +var dragOptions={geometryTypes:["OpenLayers.Geometry.Point"],snappingOptions:this.snappingOptions,onStart:function(feature,pixel){control.dragStart.apply(control,[feature,pixel]);},onDrag:function(feature,pixel){control.dragVertex.apply(control,[feature,pixel]);},onComplete:function(feature){control.dragComplete.apply(control,[feature]);},featureCallbacks:{over:function(feature){if(control.standalone!==true||feature._sketch||control.feature===feature){control.dragControl.overFeature.apply(control.dragControl,[feature]);}}}};this.dragControl=new OpenLayers.Control.DragFeature(layer,dragOptions);var keyboardOptions={keydown:this.handleKeypress};this.handlers={keyboard:new OpenLayers.Handler.Keyboard(this,keyboardOptions)};},destroy:function(){this.layer=null;this.standalone||this.selectControl.destroy();this.dragControl.destroy();OpenLayers.Control.prototype.destroy.apply(this,[]);},activate:function(){return((this.standalone||this.selectControl.activate())&&this.handlers.keyboard.activate()&&OpenLayers.Control.prototype.activate.apply(this,arguments));},deactivate:function(){var deactivated=false;if(OpenLayers.Control.prototype.deactivate.apply(this,arguments)){this.layer.removeFeatures(this.vertices,{silent:true});this.layer.removeFeatures(this.virtualVertices,{silent:true});this.vertices=[];this.dragControl.deactivate();var feature=this.feature;var valid=feature&&feature.geometry&&feature.layer;if(this.standalone===false){if(valid){this.selectControl.unselect.apply(this.selectControl,[feature]);} +this.selectControl.deactivate();}else{if(valid){this.unselectFeature(feature);}} +this.handlers.keyboard.deactivate();deactivated=true;} +return deactivated;},beforeSelectFeature:function(feature){return this.layer.events.triggerEvent("beforefeaturemodified",{feature:feature});},selectFeature:function(feature){this.feature=feature;this.modified=false;this.resetVertices();this.dragControl.activate();this.onModificationStart(this.feature);},unselectFeature:function(feature){this.layer.removeFeatures(this.vertices,{silent:true});this.vertices=[];this.layer.destroyFeatures(this.virtualVertices,{silent:true});this.virtualVertices=[];if(this.dragHandle){this.layer.destroyFeatures([this.dragHandle],{silent:true});delete this.dragHandle;} +if(this.radiusHandle){this.layer.destroyFeatures([this.radiusHandle],{silent:true});delete this.radiusHandle;} +this.feature=null;this.dragControl.deactivate();this.onModificationEnd(feature);this.layer.events.triggerEvent("afterfeaturemodified",{feature:feature,modified:this.modified});this.modified=false;},dragStart:function(feature,pixel){if(feature!=this.feature&&!feature.geometry.parent&&feature!=this.dragHandle&&feature!=this.radiusHandle){if(this.standalone===false&&this.feature){this.selectControl.clickFeature.apply(this.selectControl,[this.feature]);} +if(this.geometryTypes==null||OpenLayers.Util.indexOf(this.geometryTypes,feature.geometry.CLASS_NAME)!=-1){this.standalone||this.selectControl.clickFeature.apply(this.selectControl,[feature]);this.dragControl.overFeature.apply(this.dragControl,[feature]);this.dragControl.lastPixel=pixel;this.dragControl.handlers.drag.started=true;this.dragControl.handlers.drag.start=pixel;this.dragControl.handlers.drag.last=pixel;}}},dragVertex:function(vertex,pixel){this.modified=true;if(this.feature.geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){if(this.feature!=vertex){this.feature=vertex;} +this.layer.events.triggerEvent("vertexmodified",{vertex:vertex.geometry,feature:this.feature,pixel:pixel});}else{if(vertex._index){vertex.geometry.parent.addComponent(vertex.geometry,vertex._index);delete vertex._index;OpenLayers.Util.removeItem(this.virtualVertices,vertex);this.vertices.push(vertex);}else if(vertex==this.dragHandle){this.layer.removeFeatures(this.vertices,{silent:true});this.vertices=[];if(this.radiusHandle){this.layer.destroyFeatures([this.radiusHandle],{silent:true});this.radiusHandle=null;}}else if(vertex!==this.radiusHandle){this.layer.events.triggerEvent("vertexmodified",{vertex:vertex.geometry,feature:this.feature,pixel:pixel});} +if(this.virtualVertices.length>0){this.layer.destroyFeatures(this.virtualVertices,{silent:true});this.virtualVertices=[];} +this.layer.drawFeature(this.feature,this.standalone?undefined:this.selectControl.renderIntent);} +this.layer.drawFeature(vertex);},dragComplete:function(vertex){this.resetVertices();this.setFeatureState();this.onModification(this.feature);this.layer.events.triggerEvent("featuremodified",{feature:this.feature});},setFeatureState:function(){if(this.feature.state!=OpenLayers.State.INSERT&&this.feature.state!=OpenLayers.State.DELETE){this.feature.state=OpenLayers.State.UPDATE;}},resetVertices:function(){if(this.dragControl.feature){this.dragControl.outFeature(this.dragControl.feature);} +if(this.vertices.length>0){this.layer.removeFeatures(this.vertices,{silent:true});this.vertices=[];} +if(this.virtualVertices.length>0){this.layer.removeFeatures(this.virtualVertices,{silent:true});this.virtualVertices=[];} +if(this.dragHandle){this.layer.destroyFeatures([this.dragHandle],{silent:true});this.dragHandle=null;} +if(this.radiusHandle){this.layer.destroyFeatures([this.radiusHandle],{silent:true});this.radiusHandle=null;} +if(this.feature&&this.feature.geometry.CLASS_NAME!="OpenLayers.Geometry.Point"){if((this.mode&OpenLayers.Control.ModifyFeature.DRAG)){this.collectDragHandle();} +if((this.mode&(OpenLayers.Control.ModifyFeature.ROTATE|OpenLayers.Control.ModifyFeature.RESIZE))){this.collectRadiusHandle();} +if(this.mode&OpenLayers.Control.ModifyFeature.RESHAPE){if(!(this.mode&OpenLayers.Control.ModifyFeature.RESIZE)){this.collectVertices();}}}},handleKeypress:function(evt){var code=evt.keyCode;if(this.feature&&OpenLayers.Util.indexOf(this.deleteCodes,code)!=-1){var vertex=this.dragControl.feature;if(vertex&&OpenLayers.Util.indexOf(this.vertices,vertex)!=-1&&!this.dragControl.handlers.drag.dragging&&vertex.geometry.parent){vertex.geometry.parent.removeComponent(vertex.geometry);this.layer.drawFeature(this.feature,this.standalone?undefined:this.selectControl.renderIntent);this.resetVertices();this.setFeatureState();this.onModification(this.feature);this.layer.events.triggerEvent("featuremodified",{feature:this.feature});}}},collectVertices:function(){this.vertices=[];this.virtualVertices=[];var control=this;function collectComponentVertices(geometry){var i,vertex,component,len;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){vertex=new OpenLayers.Feature.Vector(geometry);vertex._sketch=true;control.vertices.push(vertex);}else{var numVert=geometry.components.length;if(geometry.CLASS_NAME=="OpenLayers.Geometry.LinearRing"){numVert-=1;} +for(i=0;i<numVert;++i){component=geometry.components[i];if(component.CLASS_NAME=="OpenLayers.Geometry.Point"){vertex=new OpenLayers.Feature.Vector(component);vertex._sketch=true;control.vertices.push(vertex);}else{collectComponentVertices(component);}} +if(geometry.CLASS_NAME!="OpenLayers.Geometry.MultiPoint"){for(i=0,len=geometry.components.length;i<len-1;++i){var prevVertex=geometry.components[i];var nextVertex=geometry.components[i+1];if(prevVertex.CLASS_NAME=="OpenLayers.Geometry.Point"&&nextVertex.CLASS_NAME=="OpenLayers.Geometry.Point"){var x=(prevVertex.x+nextVertex.x)/2;var y=(prevVertex.y+nextVertex.y)/2;var point=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(x,y),null,control.virtualStyle);point.geometry.parent=geometry;point._index=i+1;point._sketch=true;control.virtualVertices.push(point);}}}}} +collectComponentVertices.call(this,this.feature.geometry);this.layer.addFeatures(this.virtualVertices,{silent:true});this.layer.addFeatures(this.vertices,{silent:true});},collectDragHandle:function(){var geometry=this.feature.geometry;var center=geometry.getBounds().getCenterLonLat();var originGeometry=new OpenLayers.Geometry.Point(center.lon,center.lat);var origin=new OpenLayers.Feature.Vector(originGeometry);originGeometry.move=function(x,y){OpenLayers.Geometry.Point.prototype.move.call(this,x,y);geometry.move(x,y);};origin._sketch=true;this.dragHandle=origin;this.layer.addFeatures([this.dragHandle],{silent:true});},collectRadiusHandle:function(){var geometry=this.feature.geometry;var bounds=geometry.getBounds();var center=bounds.getCenterLonLat();var originGeometry=new OpenLayers.Geometry.Point(center.lon,center.lat);var radiusGeometry=new OpenLayers.Geometry.Point(bounds.right,bounds.bottom);var radius=new OpenLayers.Feature.Vector(radiusGeometry);var resize=(this.mode&OpenLayers.Control.ModifyFeature.RESIZE);var reshape=(this.mode&OpenLayers.Control.ModifyFeature.RESHAPE);var rotate=(this.mode&OpenLayers.Control.ModifyFeature.ROTATE);radiusGeometry.move=function(x,y){OpenLayers.Geometry.Point.prototype.move.call(this,x,y);var dx1=this.x-originGeometry.x;var dy1=this.y-originGeometry.y;var dx0=dx1-x;var dy0=dy1-y;if(rotate){var a0=Math.atan2(dy0,dx0);var a1=Math.atan2(dy1,dx1);var angle=a1-a0;angle*=180/Math.PI;geometry.rotate(angle,originGeometry);} +if(resize){var scale,ratio;if(reshape){scale=dy1/dy0;ratio=(dx1/dx0)/scale;}else{var l0=Math.sqrt((dx0*dx0)+(dy0*dy0));var l1=Math.sqrt((dx1*dx1)+(dy1*dy1));scale=l1/l0;} +geometry.resize(scale,originGeometry,ratio);}};radius._sketch=true;this.radiusHandle=radius;this.layer.addFeatures([this.radiusHandle],{silent:true});},setMap:function(map){this.standalone||this.selectControl.setMap(map);this.dragControl.setMap(map);OpenLayers.Control.prototype.setMap.apply(this,arguments);},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.Geometry.LineString=OpenLayers.Class(OpenLayers.Geometry.Curve,{initialize:function(points){OpenLayers.Geometry.Curve.prototype.initialize.apply(this,arguments);},removeComponent:function(point){if(this.components&&(this.components.length>2)){OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this,arguments);}},intersects:function(geometry){var intersect=false;var type=geometry.CLASS_NAME;if(type=="OpenLayers.Geometry.LineString"||type=="OpenLayers.Geometry.LinearRing"||type=="OpenLayers.Geometry.Point"){var segs1=this.getSortedSegments();var segs2;if(type=="OpenLayers.Geometry.Point"){segs2=[{x1:geometry.x,y1:geometry.y,x2:geometry.x,y2:geometry.y}];}else{segs2=geometry.getSortedSegments();} +var seg1,seg1x1,seg1x2,seg1y1,seg1y2,seg2,seg2y1,seg2y2;outer:for(var i=0,len=segs1.length;i<len;++i){seg1=segs1[i];seg1x1=seg1.x1;seg1x2=seg1.x2;seg1y1=seg1.y1;seg1y2=seg1.y2;inner:for(var j=0,jlen=segs2.length;j<jlen;++j){seg2=segs2[j];if(seg2.x1>seg1x2){break;} +if(seg2.x2<seg1x1){continue;} +seg2y1=seg2.y1;seg2y2=seg2.y2;if(Math.min(seg2y1,seg2y2)>Math.max(seg1y1,seg1y2)){continue;} +if(Math.max(seg2y1,seg2y2)<Math.min(seg1y1,seg1y2)){continue;} +if(OpenLayers.Geometry.segmentsIntersect(seg1,seg2)){intersect=true;break outer;}}}}else{intersect=geometry.intersects(this);} +return intersect;},getSortedSegments:function(){var numSeg=this.components.length-1;var segments=new Array(numSeg),point1,point2;for(var i=0;i<numSeg;++i){point1=this.components[i];point2=this.components[i+1];if(point1.x<point2.x){segments[i]={x1:point1.x,y1:point1.y,x2:point2.x,y2:point2.y};}else{segments[i]={x1:point2.x,y1:point2.y,x2:point1.x,y2:point1.y};}} +function byX1(seg1,seg2){return seg1.x1-seg2.x1;} +return segments.sort(byX1);},splitWithSegment:function(seg,options){var edge=!(options&&options.edge===false);var tolerance=options&&options.tolerance;var lines=[];var verts=this.getVertices();var points=[];var intersections=[];var split=false;var vert1,vert2,point;var node,vertex,target;var interOptions={point:true,tolerance:tolerance};var result=null;for(var i=0,stop=verts.length-2;i<=stop;++i){vert1=verts[i];points.push(vert1.clone());vert2=verts[i+1];target={x1:vert1.x,y1:vert1.y,x2:vert2.x,y2:vert2.y};point=OpenLayers.Geometry.segmentsIntersect(seg,target,interOptions);if(point instanceof OpenLayers.Geometry.Point){if((point.x===seg.x1&&point.y===seg.y1)||(point.x===seg.x2&&point.y===seg.y2)||point.equals(vert1)||point.equals(vert2)){vertex=true;}else{vertex=false;} +if(vertex||edge){if(!point.equals(intersections[intersections.length-1])){intersections.push(point.clone());} +if(i===0){if(point.equals(vert1)){continue;}} +if(point.equals(vert2)){continue;} +split=true;if(!point.equals(vert1)){points.push(point);} +lines.push(new OpenLayers.Geometry.LineString(points));points=[point.clone()];}}} +if(split){points.push(vert2.clone());lines.push(new OpenLayers.Geometry.LineString(points));} +if(intersections.length>0){var xDir=seg.x1<seg.x2?1:-1;var yDir=seg.y1<seg.y2?1:-1;result={lines:lines,points:intersections.sort(function(p1,p2){return(xDir*p1.x-xDir*p2.x)||(yDir*p1.y-yDir*p2.y);})};} +return result;},split:function(target,options){var results=null;var mutual=options&&options.mutual;var sourceSplit,targetSplit,sourceParts,targetParts;if(target instanceof OpenLayers.Geometry.LineString){var verts=this.getVertices();var vert1,vert2,seg,splits,lines,point;var points=[];sourceParts=[];for(var i=0,stop=verts.length-2;i<=stop;++i){vert1=verts[i];vert2=verts[i+1];seg={x1:vert1.x,y1:vert1.y,x2:vert2.x,y2:vert2.y};targetParts=targetParts||[target];if(mutual){points.push(vert1.clone());} +for(var j=0;j<targetParts.length;++j){splits=targetParts[j].splitWithSegment(seg,options);if(splits){lines=splits.lines;if(lines.length>0){lines.unshift(j,1);Array.prototype.splice.apply(targetParts,lines);j+=lines.length-2;} +if(mutual){for(var k=0,len=splits.points.length;k<len;++k){point=splits.points[k];if(!point.equals(vert1)){points.push(point);sourceParts.push(new OpenLayers.Geometry.LineString(points));if(point.equals(vert2)){points=[];}else{points=[point.clone()];}}}}}}} +if(mutual&&sourceParts.length>0&&points.length>0){points.push(vert2.clone());sourceParts.push(new OpenLayers.Geometry.LineString(points));}}else{results=target.splitWith(this,options);} +if(targetParts&&targetParts.length>1){targetSplit=true;}else{targetParts=[];} +if(sourceParts&&sourceParts.length>1){sourceSplit=true;}else{sourceParts=[];} +if(targetSplit||sourceSplit){if(mutual){results=[sourceParts,targetParts];}else{results=targetParts;}} +return results;},splitWith:function(geometry,options){return geometry.split(this,options);},getVertices:function(nodes){var vertices;if(nodes===true){vertices=[this.components[0],this.components[this.components.length-1]];}else if(nodes===false){vertices=this.components.slice(1,this.components.length-1);}else{vertices=this.components.slice();} +return vertices;},distanceTo:function(geometry,options){var edge=!(options&&options.edge===false);var details=edge&&options&&options.details;var result,best={};var min=Number.POSITIVE_INFINITY;if(geometry instanceof OpenLayers.Geometry.Point){var segs=this.getSortedSegments();var x=geometry.x;var y=geometry.y;var seg;for(var i=0,len=segs.length;i<len;++i){seg=segs[i];result=OpenLayers.Geometry.distanceToSegment(geometry,seg);if(result.distance<min){min=result.distance;best=result;if(min===0){break;}}else{if(seg.x2>x&&((y>seg.y1&&y<seg.y2)||(y<seg.y1&&y>seg.y2))){break;}}} +if(details){best={distance:best.distance,x0:best.x,y0:best.y,x1:x,y1:y};}else{best=best.distance;}}else if(geometry instanceof OpenLayers.Geometry.LineString){var segs0=this.getSortedSegments();var segs1=geometry.getSortedSegments();var seg0,seg1,intersection,x0,y0;var len1=segs1.length;var interOptions={point:true};outer:for(var i=0,len=segs0.length;i<len;++i){seg0=segs0[i];x0=seg0.x1;y0=seg0.y1;for(var j=0;j<len1;++j){seg1=segs1[j];intersection=OpenLayers.Geometry.segmentsIntersect(seg0,seg1,interOptions);if(intersection){min=0;best={distance:0,x0:intersection.x,y0:intersection.y,x1:intersection.x,y1:intersection.y};break outer;}else{result=OpenLayers.Geometry.distanceToSegment({x:x0,y:y0},seg1);if(result.distance<min){min=result.distance;best={distance:min,x0:x0,y0:y0,x1:result.x,y1:result.y};}}}} +if(!details){best=best.distance;} +if(min!==0){if(seg0){result=geometry.distanceTo(new OpenLayers.Geometry.Point(seg0.x2,seg0.y2),options);var dist=details?result.distance:result;if(dist<min){if(details){best={distance:min,x0:result.x1,y0:result.y1,x1:result.x0,y1:result.y0};}else{best=dist;}}}}}else{best=geometry.distanceTo(this,options);if(details){best={distance:best.distance,x0:best.x1,y0:best.y1,x1:best.x0,y1:best.y0};}} +return best;},CLASS_NAME:"OpenLayers.Geometry.LineString"});OpenLayers.Control.TransformFeature=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:["beforesetfeature","setfeature","beforetransform","transform","transformcomplete"],geometryTypes:null,layer:null,preserveAspectRatio:false,rotate:true,feature:null,renderIntent:"temporary",rotationHandleSymbolizer:null,box:null,center:null,scale:1,ratio:1,rotation:0,handles:null,rotationHandles:null,dragControl:null,initialize:function(layer,options){this.EVENT_TYPES=OpenLayers.Control.TransformFeature.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.layer=layer;if(!this.rotationHandleSymbolizer){this.rotationHandleSymbolizer={stroke:false,pointRadius:10,fillOpacity:0,cursor:"pointer"};} +this.createBox();this.createControl();},activate:function(){var activated=false;if(OpenLayers.Control.prototype.activate.apply(this,arguments)){this.dragControl.activate();this.layer.addFeatures([this.box]);this.rotate&&this.layer.addFeatures(this.rotationHandles);this.layer.addFeatures(this.handles);activated=true;} +return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Control.prototype.deactivate.apply(this,arguments)){this.layer.removeFeatures(this.handles);this.rotate&&this.layer.removeFeatures(this.rotationHandles);this.layer.removeFeatures([this.box]);this.dragControl.deactivate();deactivated=true;} +return deactivated;},setMap:function(map){this.dragControl.setMap(map);OpenLayers.Control.prototype.setMap.apply(this,arguments);},setFeature:function(feature,initialParams){initialParams=OpenLayers.Util.applyDefaults(initialParams,{rotation:0,scale:1,ratio:1});var evt={feature:feature};var oldRotation=this.rotation;var oldCenter=this.center;OpenLayers.Util.extend(this,initialParams);if(this.events.triggerEvent("beforesetfeature",evt)===false){return;} +this.feature=feature;this.activate();this._setfeature=true;var featureBounds=this.feature.geometry.getBounds();this.box.move(featureBounds.getCenterLonLat());this.box.geometry.rotate(-oldRotation,oldCenter);this._angle=0;var ll;if(this.rotation){var geom=feature.geometry.clone();geom.rotate(-this.rotation,this.center);var box=new OpenLayers.Feature.Vector(geom.getBounds().toGeometry());box.geometry.rotate(this.rotation,this.center);this.box.geometry.rotate(this.rotation,this.center);this.box.move(box.geometry.getBounds().getCenterLonLat());var llGeom=box.geometry.components[0].components[0];ll=llGeom.getBounds().getCenterLonLat();}else{ll=new OpenLayers.LonLat(featureBounds.left,featureBounds.bottom);} +this.handles[0].move(ll);delete this._setfeature;this.events.triggerEvent("setfeature",evt);},createBox:function(){var control=this;this.center=new OpenLayers.Geometry.Point(0,0);var box=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString([new OpenLayers.Geometry.Point(-1,-1),new OpenLayers.Geometry.Point(0,-1),new OpenLayers.Geometry.Point(1,-1),new OpenLayers.Geometry.Point(1,0),new OpenLayers.Geometry.Point(1,1),new OpenLayers.Geometry.Point(0,1),new OpenLayers.Geometry.Point(-1,1),new OpenLayers.Geometry.Point(-1,0),new OpenLayers.Geometry.Point(-1,-1)]),null,typeof this.renderIntent=="string"?null:this.renderIntent);box.geometry.move=function(x,y){control._moving=true;OpenLayers.Geometry.LineString.prototype.move.apply(this,arguments);control.center.move(x,y);delete control._moving;};var vertexMoveFn=function(x,y){OpenLayers.Geometry.Point.prototype.move.apply(this,arguments);this._rotationHandle&&this._rotationHandle.geometry.move(x,y);this._handle.geometry.move(x,y);};var vertexResizeFn=function(scale,center,ratio){OpenLayers.Geometry.Point.prototype.resize.apply(this,arguments);this._rotationHandle&&this._rotationHandle.geometry.resize(scale,center,ratio);this._handle.geometry.resize(scale,center,ratio);};var vertexRotateFn=function(angle,center){OpenLayers.Geometry.Point.prototype.rotate.apply(this,arguments);this._rotationHandle&&this._rotationHandle.geometry.rotate(angle,center);this._handle.geometry.rotate(angle,center);};var handleMoveFn=function(x,y){var oldX=this.x,oldY=this.y;OpenLayers.Geometry.Point.prototype.move.call(this,x,y);if(control._moving){return;} +var evt=control.dragControl.handlers.drag.evt;var preserveAspectRatio=!control._setfeature&&control.preserveAspectRatio;var reshape=!preserveAspectRatio&&!(evt&&evt.shiftKey);var oldGeom=new OpenLayers.Geometry.Point(oldX,oldY);var centerGeometry=control.center;this.rotate(-control.rotation,centerGeometry);oldGeom.rotate(-control.rotation,centerGeometry);var dx1=this.x-centerGeometry.x;var dy1=this.y-centerGeometry.y;var dx0=dx1-(this.x-oldGeom.x);var dy0=dy1-(this.y-oldGeom.y);this.x=oldX;this.y=oldY;var scale,ratio=1;if(reshape){scale=Math.abs(dy0)<0.00001?1:dy1/dy0;ratio=(Math.abs(dx0)<0.00001?1:(dx1/dx0))/scale;}else{var l0=Math.sqrt((dx0*dx0)+(dy0*dy0));var l1=Math.sqrt((dx1*dx1)+(dy1*dy1));scale=l1/l0;} +control._moving=true;control.box.geometry.rotate(-control.rotation,centerGeometry);delete control._moving;control.box.geometry.resize(scale,centerGeometry,ratio);control.box.geometry.rotate(control.rotation,centerGeometry);control.transformFeature({scale:scale,ratio:ratio});};var rotationHandleMoveFn=function(x,y){var oldX=this.x,oldY=this.y;OpenLayers.Geometry.Point.prototype.move.call(this,x,y);if(control._moving){return;} +var evt=control.dragControl.handlers.drag.evt;var constrain=(evt&&evt.shiftKey)?45:1;var centerGeometry=control.center;var dx1=this.x-centerGeometry.x;var dy1=this.y-centerGeometry.y;var dx0=dx1-x;var dy0=dy1-y;this.x=oldX;this.y=oldY;var a0=Math.atan2(dy0,dx0);var a1=Math.atan2(dy1,dx1);var angle=a1-a0;angle*=180/Math.PI;control._angle=(control._angle+angle)%360;var diff=control.rotation%constrain;if(Math.abs(control._angle)>=constrain||diff!==0){angle=Math.round(control._angle/constrain)*constrain- +diff;control._angle=0;control.box.geometry.rotate(angle,centerGeometry);control.transformFeature({rotation:angle});}};var handles=new Array(8);var rotationHandles=new Array(4);var geom,handle,rotationHandle;for(var i=0;i<8;++i){geom=box.geometry.components[i];handle=new OpenLayers.Feature.Vector(geom.clone(),null,typeof this.renderIntent=="string"?null:this.renderIntent);if(i%2==0){rotationHandle=new OpenLayers.Feature.Vector(geom.clone(),null,typeof this.rotationHandleSymbolizer=="string"?null:this.rotationHandleSymbolizer);rotationHandle.geometry.move=rotationHandleMoveFn;geom._rotationHandle=rotationHandle;rotationHandles[i/2]=rotationHandle;} +geom.move=vertexMoveFn;geom.resize=vertexResizeFn;geom.rotate=vertexRotateFn;handle.geometry.move=handleMoveFn;geom._handle=handle;handles[i]=handle;} +this.box=box;this.rotationHandles=rotationHandles;this.handles=handles;},createControl:function(){var control=this;this.dragControl=new OpenLayers.Control.DragFeature(this.layer,{documentDrag:true,moveFeature:function(pixel){if(this.feature===control.feature){this.feature=control.box;} +OpenLayers.Control.DragFeature.prototype.moveFeature.apply(this,arguments);},onDrag:function(feature,pixel){if(feature===control.box){control.transformFeature({center:control.center});control.drawHandles();}},onStart:function(feature,pixel){var eligible=!control.geometryTypes||OpenLayers.Util.indexOf(control.geometryTypes,feature.geometry.CLASS_NAME)!==-1;var i=OpenLayers.Util.indexOf(control.handles,feature);i+=OpenLayers.Util.indexOf(control.rotationHandles,feature);if(feature!==control.feature&&feature!==control.box&&i==-2&&eligible){control.setFeature(feature);}},onComplete:function(feature,pixel){control.events.triggerEvent("transformcomplete",{feature:control.feature});}});},drawHandles:function(){var layer=this.layer;for(var i=0;i<8;++i){if(this.rotate&&i%2===0){layer.drawFeature(this.rotationHandles[i/2],this.rotationHandleSymbolizer);} +layer.drawFeature(this.handles[i],this.renderIntent);}},transformFeature:function(mods){if(!this._setfeature){this.scale*=(mods.scale||1);this.ratio*=(mods.ratio||1);var oldRotation=this.rotation;this.rotation=(this.rotation+(mods.rotation||0))%360;if(this.events.triggerEvent("beforetransform",mods)!==false){var feature=this.feature;var geom=feature.geometry;var center=this.center;geom.rotate(-oldRotation,center);if(mods.scale||mods.ratio){geom.resize(mods.scale,center,mods.ratio);}else if(mods.center){feature.move(mods.center.getBounds().getCenterLonLat());} +geom.rotate(this.rotation,center);this.layer.drawFeature(feature);feature.toState(OpenLayers.State.UPDATE);this.events.triggerEvent("transform",mods);}} +this.layer.drawFeature(this.box,this.renderIntent);this.drawHandles();},destroy:function(){var geom;for(var i=0;i<8;++i){geom=this.box.geometry.components[i];geom._handle.destroy();geom._handle=null;geom._rotationHandle&&geom._rotationHandle.destroy();geom._rotationHandle=null;} +this.box.destroy();this.box=null;this.layer=null;this.dragControl.destroy();OpenLayers.Control.prototype.destroy.apply(this,arguments);},CLASS_NAME:"OpenLayers.Control.TransformFeature"});OpenLayers.Format.GPX=OpenLayers.Class(OpenLayers.Format.XML,{extractWaypoints:true,extractTracks:true,extractRoutes:true,extractAttributes:true,initialize:function(options){this.externalProjection=new OpenLayers.Projection("EPSG:4326");OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(doc){if(typeof doc=="string"){doc=OpenLayers.Format.XML.prototype.read.apply(this,[doc]);} +var features=[];if(this.extractTracks){var tracks=doc.getElementsByTagName("trk");for(var i=0,len=tracks.length;i<len;i++){var attrs={};if(this.extractAttributes){attrs=this.parseAttributes(tracks[i]);} +var segs=this.getElementsByTagNameNS(tracks[i],tracks[i].namespaceURI,"trkseg");for(var j=0,seglen=segs.length;j<seglen;j++){var track=this.extractSegment(segs[j],"trkpt");features.push(new OpenLayers.Feature.Vector(track,attrs));}}} +if(this.extractRoutes){var routes=doc.getElementsByTagName("rte");for(var k=0,klen=routes.length;k<klen;k++){var attrs={};if(this.extractAttributes){attrs=this.parseAttributes(routes[k]);} +var route=this.extractSegment(routes[k],"rtept");features.push(new OpenLayers.Feature.Vector(route,attrs));}} +if(this.extractWaypoints){var waypoints=doc.getElementsByTagName("wpt");for(var l=0,len=waypoints.length;l<len;l++){var attrs={};if(this.extractAttributes){attrs=this.parseAttributes(waypoints[l]);} +var wpt=new OpenLayers.Geometry.Point(waypoints[l].getAttribute("lon"),waypoints[l].getAttribute("lat"));features.push(new OpenLayers.Feature.Vector(wpt,attrs));}} +if(this.internalProjection&&this.externalProjection){for(var g=0,featLength=features.length;g<featLength;g++){features[g].geometry.transform(this.externalProjection,this.internalProjection);}} +return features;},extractSegment:function(segment,segmentType){var points=this.getElementsByTagNameNS(segment,segment.namespaceURI,segmentType);var point_features=[];for(var i=0,len=points.length;i<len;i++){point_features.push(new OpenLayers.Geometry.Point(points[i].getAttribute("lon"),points[i].getAttribute("lat")));} +return new OpenLayers.Geometry.LineString(point_features);},parseAttributes:function(node){var attributes={};var attrNode=node.firstChild;while(attrNode){if(attrNode.nodeType==1){var value=attrNode.firstChild;if(value.nodeType==3||value.nodeType==4){name=(attrNode.prefix)?attrNode.nodeName.split(":")[1]:attrNode.nodeName;if(name!="trkseg"&&name!="rtept"){attributes[name]=value.nodeValue;}}} +attrNode=attrNode.nextSibling;} +return attributes;},CLASS_NAME:"OpenLayers.Format.GPX"});OpenLayers.Geometry.LinearRing=OpenLayers.Class(OpenLayers.Geometry.LineString,{componentTypes:["OpenLayers.Geometry.Point"],initialize:function(points){OpenLayers.Geometry.LineString.prototype.initialize.apply(this,arguments);},addComponent:function(point,index){var added=false;var lastPoint=this.components.pop();if(index!=null||!point.equals(lastPoint)){added=OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,arguments);} +var firstPoint=this.components[0];OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,[firstPoint]);return added;},removeComponent:function(point){if(this.components.length>4){this.components.pop();OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this,arguments);var firstPoint=this.components[0];OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,[firstPoint]);}},move:function(x,y){for(var i=0,len=this.components.length;i<len-1;i++){this.components[i].move(x,y);}},rotate:function(angle,origin){for(var i=0,len=this.components.length;i<len-1;++i){this.components[i].rotate(angle,origin);}},resize:function(scale,origin,ratio){for(var i=0,len=this.components.length;i<len-1;++i){this.components[i].resize(scale,origin,ratio);} +return this;},transform:function(source,dest){if(source&&dest){for(var i=0,len=this.components.length;i<len-1;i++){var component=this.components[i];component.transform(source,dest);} +this.bounds=null;} +return this;},getCentroid:function(){if(this.components&&(this.components.length>2)){var sumX=0.0;var sumY=0.0;for(var i=0;i<this.components.length-1;i++){var b=this.components[i];var c=this.components[i+1];sumX+=(b.x+c.x)*(b.x*c.y-c.x*b.y);sumY+=(b.y+c.y)*(b.x*c.y-c.x*b.y);} +var area=-1*this.getArea();var x=sumX/(6*area);var y=sumY/(6*area);return new OpenLayers.Geometry.Point(x,y);}else{return null;}},getArea:function(){var area=0.0;if(this.components&&(this.components.length>2)){var sum=0.0;for(var i=0,len=this.components.length;i<len-1;i++){var b=this.components[i];var c=this.components[i+1];sum+=(b.x+c.x)*(c.y-b.y);} +area=-sum/2.0;} +return area;},getGeodesicArea:function(projection){var ring=this;if(projection){var gg=new OpenLayers.Projection("EPSG:4326");if(!gg.equals(projection)){ring=this.clone().transform(projection,gg);}} +var area=0.0;var len=ring.components&&ring.components.length;if(len>2){var p1,p2;for(var i=0;i<len-1;i++){p1=ring.components[i];p2=ring.components[i+1];area+=OpenLayers.Util.rad(p2.x-p1.x)*(2+Math.sin(OpenLayers.Util.rad(p1.y))+ +Math.sin(OpenLayers.Util.rad(p2.y)));} +area=area*6378137.0*6378137.0/2.0;} +return area;},containsPoint:function(point){var approx=OpenLayers.Number.limitSigDigs;var digs=14;var px=approx(point.x,digs);var py=approx(point.y,digs);function getX(y,x1,y1,x2,y2){return(((x1-x2)*y)+((x2*y1)-(x1*y2)))/(y1-y2);} +var numSeg=this.components.length-1;var start,end,x1,y1,x2,y2,cx,cy;var crosses=0;for(var i=0;i<numSeg;++i){start=this.components[i];x1=approx(start.x,digs);y1=approx(start.y,digs);end=this.components[i+1];x2=approx(end.x,digs);y2=approx(end.y,digs);if(y1==y2){if(py==y1){if(x1<=x2&&(px>=x1&&px<=x2)||x1>=x2&&(px<=x1&&px>=x2)){crosses=-1;break;}} +continue;} +cx=approx(getX(py,x1,y1,x2,y2),digs);if(cx==px){if(y1<y2&&(py>=y1&&py<=y2)||y1>y2&&(py<=y1&&py>=y2)){crosses=-1;break;}} +if(cx<=px){continue;} +if(x1!=x2&&(cx<Math.min(x1,x2)||cx>Math.max(x1,x2))){continue;} +if(y1<y2&&(py>=y1&&py<y2)||y1>y2&&(py<y1&&py>=y2)){++crosses;}} +var contained=(crosses==-1)?1:!!(crosses&1);return contained;},intersects:function(geometry){var intersect=false;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){intersect=this.containsPoint(geometry);}else if(geometry.CLASS_NAME=="OpenLayers.Geometry.LineString"){intersect=geometry.intersects(this);}else if(geometry.CLASS_NAME=="OpenLayers.Geometry.LinearRing"){intersect=OpenLayers.Geometry.LineString.prototype.intersects.apply(this,[geometry]);}else{for(var i=0,len=geometry.components.length;i<len;++i){intersect=geometry.components[i].intersects(this);if(intersect){break;}}} +return intersect;},getVertices:function(nodes){return(nodes===true)?[]:this.components.slice(0,this.components.length-1);},CLASS_NAME:"OpenLayers.Geometry.LinearRing"});OpenLayers.Geometry.MultiLineString=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.LineString"],initialize:function(components){OpenLayers.Geometry.Collection.prototype.initialize.apply(this,arguments);},split:function(geometry,options){var results=null;var mutual=options&&options.mutual;var splits,sourceLine,sourceLines,sourceSplit,targetSplit;var sourceParts=[];var targetParts=[geometry];for(var i=0,len=this.components.length;i<len;++i){sourceLine=this.components[i];sourceSplit=false;for(var j=0;j<targetParts.length;++j){splits=sourceLine.split(targetParts[j],options);if(splits){if(mutual){sourceLines=splits[0];for(var k=0,klen=sourceLines.length;k<klen;++k){if(k===0&&sourceParts.length){sourceParts[sourceParts.length-1].addComponent(sourceLines[k]);}else{sourceParts.push(new OpenLayers.Geometry.MultiLineString([sourceLines[k]]));}} +sourceSplit=true;splits=splits[1];} +if(splits.length){splits.unshift(j,1);Array.prototype.splice.apply(targetParts,splits);break;}}} +if(!sourceSplit){if(sourceParts.length){sourceParts[sourceParts.length-1].addComponent(sourceLine.clone());}else{sourceParts=[new OpenLayers.Geometry.MultiLineString(sourceLine.clone())];}}} +if(sourceParts&&sourceParts.length>1){sourceSplit=true;}else{sourceParts=[];} +if(targetParts&&targetParts.length>1){targetSplit=true;}else{targetParts=[];} +if(sourceSplit||targetSplit){if(mutual){results=[sourceParts,targetParts];}else{results=targetParts;}} +return results;},splitWith:function(geometry,options){var results=null;var mutual=options&&options.mutual;var splits,targetLine,sourceLines,sourceSplit,targetSplit,sourceParts,targetParts;if(geometry instanceof OpenLayers.Geometry.LineString){targetParts=[];sourceParts=[geometry];for(var i=0,len=this.components.length;i<len;++i){targetSplit=false;targetLine=this.components[i];for(var j=0;j<sourceParts.length;++j){splits=sourceParts[j].split(targetLine,options);if(splits){if(mutual){sourceLines=splits[0];if(sourceLines.length){sourceLines.unshift(j,1);Array.prototype.splice.apply(sourceParts,sourceLines);j+=sourceLines.length-2;} +splits=splits[1];if(splits.length===0){splits=[targetLine.clone()];}} +for(var k=0,klen=splits.length;k<klen;++k){if(k===0&&targetParts.length){targetParts[targetParts.length-1].addComponent(splits[k]);}else{targetParts.push(new OpenLayers.Geometry.MultiLineString([splits[k]]));}} +targetSplit=true;}} +if(!targetSplit){if(targetParts.length){targetParts[targetParts.length-1].addComponent(targetLine.clone());}else{targetParts=[new OpenLayers.Geometry.MultiLineString([targetLine.clone()])];}}}}else{results=geometry.split(this);} +if(sourceParts&&sourceParts.length>1){sourceSplit=true;}else{sourceParts=[];} +if(targetParts&&targetParts.length>1){targetSplit=true;}else{targetParts=[];} +if(sourceSplit||targetSplit){if(mutual){results=[sourceParts,targetParts];}else{results=targetParts;}} +return results;},CLASS_NAME:"OpenLayers.Geometry.MultiLineString"});OpenLayers.Handler.Path=OpenLayers.Class(OpenLayers.Handler.Point,{line:null,freehand:false,freehandToggle:'shiftKey',initialize:function(control,callbacks,options){OpenLayers.Handler.Point.prototype.initialize.apply(this,arguments);},createFeature:function(pixel){var lonlat=this.control.map.getLonLatFromPixel(pixel);this.point=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat));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:true});},destroyFeature:function(){OpenLayers.Handler.Point.prototype.destroyFeature.apply(this);this.line=null;},removePoint:function(){if(this.point){this.layer.removeFeatures([this.point]);}},addPoint:function(pixel){this.layer.removeFeatures([this.point]);var lonlat=this.control.map.getLonLatFromPixel(pixel);this.point=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat));this.line.geometry.addComponent(this.point.geometry,this.line.geometry.components.length);this.callback("point",[this.point.geometry,this.getGeometry()]);this.callback("modify",[this.point.geometry,this.getSketch()]);this.drawFeature();},freehandMode:function(evt){return(this.freehandToggle&&evt[this.freehandToggle])?!this.freehand:this.freehand;},modifyFeature:function(pixel){var lonlat=this.control.map.getLonLatFromPixel(pixel);this.point.geometry.x=lonlat.lon;this.point.geometry.y=lonlat.lat;this.callback("modify",[this.point.geometry,this.getSketch()]);this.point.geometry.clearBounds();this.drawFeature();},drawFeature:function(){this.layer.drawFeature(this.line,this.style);this.layer.drawFeature(this.point,this.style);},getSketch:function(){return this.line;},getGeometry:function(){var geometry=this.line&&this.line.geometry;if(geometry&&this.multi){geometry=new OpenLayers.Geometry.MultiLineString([geometry]);} +return geometry;},mousedown:function(evt){if(this.lastDown&&this.lastDown.equals(evt.xy)){return false;} +if(this.lastDown==null){if(this.persist){this.destroyFeature();} +this.createFeature(evt.xy);}else if((this.lastUp==null)||!this.lastUp.equals(evt.xy)){this.addPoint(evt.xy);} +this.mouseDown=true;this.lastDown=evt.xy;this.drawing=true;return false;},mousemove:function(evt){if(this.drawing){if(this.mouseDown&&this.freehandMode(evt)){this.addPoint(evt.xy);}else{this.modifyFeature(evt.xy);}} +return true;},mouseup:function(evt){this.mouseDown=false;if(this.drawing){if(this.freehandMode(evt)){this.removePoint();this.finalize();}else{if(this.lastUp==null){this.addPoint(evt.xy);} +this.lastUp=evt.xy;} +return false;} +return true;},dblclick:function(evt){if(!this.freehandMode(evt)){var index=this.line.geometry.components.length-1;this.line.geometry.removeComponent(this.line.geometry.components[index]);this.removePoint();this.finalize();} +return false;},CLASS_NAME:"OpenLayers.Handler.Path"});OpenLayers.Control.Split=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:["beforesplit","split","aftersplit"],layer:null,source:null,sourceOptions:null,tolerance:null,edge:true,deferDelete:false,mutual:true,targetFilter:null,sourceFilter:null,handler:null,initialize:function(options){Array.prototype.push.apply(this.EVENT_TYPES,OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.options=options||{};if(this.options.source){this.setSource(this.options.source);}},setSource:function(layer){if(this.active){this.deactivate();if(this.handler){this.handler.destroy();delete this.handler;} +this.source=layer;this.activate();}else{this.source=layer;}},activate:function(){var activated=OpenLayers.Control.prototype.activate.call(this);if(activated){if(!this.source){if(!this.handler){this.handler=new OpenLayers.Handler.Path(this,{done:function(geometry){this.onSketchComplete({feature:new OpenLayers.Feature.Vector(geometry)});}},{layerOptions:this.sourceOptions});} +this.handler.activate();}else if(this.source.events){this.source.events.on({sketchcomplete:this.onSketchComplete,afterfeaturemodified:this.afterFeatureModified,scope:this});}} +return activated;},deactivate:function(){var deactivated=OpenLayers.Control.prototype.deactivate.call(this);if(deactivated){if(this.source&&this.source.events){this.layer.events.un({sketchcomplete:this.onSketchComplete,afterfeaturemodified:this.afterFeatureModified,scope:this});}} +return deactivated;},onSketchComplete:function(event){this.feature=null;return!this.considerSplit(event.feature);},afterFeatureModified:function(event){if(event.modified){var feature=event.feature;if(feature.geometry instanceof OpenLayers.Geometry.LineString||feature.geometry instanceof OpenLayers.Geometry.MultiLineString){this.feature=event.feature;this.considerSplit(event.feature);}}},removeByGeometry:function(features,geometry){for(var i=0,len=features.length;i<len;++i){if(features[i].geometry===geometry){features.splice(i,1);break;}}},isEligible:function(target){return(target.state!==OpenLayers.State.DELETE)&&(target.geometry instanceof OpenLayers.Geometry.LineString||target.geometry instanceof OpenLayers.Geometry.MultiLineString)&&(this.feature!==target)&&(!this.targetFilter||this.targetFilter.evaluate(target.attributes));},considerSplit:function(feature){var sourceSplit=false;var targetSplit=false;if(!this.sourceFilter||this.sourceFilter.evaluate(feature.attributes)){var features=this.layer&&this.layer.features||[];var target,results,proceed;var additions=[],removals=[];var mutual=(this.layer===this.source)&&this.mutual;var options={edge:this.edge,tolerance:this.tolerance,mutual:mutual};var sourceParts=[feature.geometry];var targetFeature,targetParts;var source,parts;for(var i=0,len=features.length;i<len;++i){targetFeature=features[i];if(this.isEligible(targetFeature)){targetParts=[targetFeature.geometry];for(var j=0;j<sourceParts.length;++j){source=sourceParts[j];for(var k=0;k<targetParts.length;++k){target=targetParts[k];if(source.getBounds().intersectsBounds(target.getBounds())){results=source.split(target,options);if(results){proceed=this.events.triggerEvent("beforesplit",{source:feature,target:targetFeature});if(proceed!==false){if(mutual){parts=results[0];if(parts.length>1){parts.unshift(j,1);Array.prototype.splice.apply(sourceParts,parts);j+=parts.length-3;} +results=results[1];} +if(results.length>1){results.unshift(k,1);Array.prototype.splice.apply(targetParts,results);k+=results.length-3;}}}}}} +if(targetParts&&targetParts.length>1){this.geomsToFeatures(targetFeature,targetParts);this.events.triggerEvent("split",{original:targetFeature,features:targetParts});Array.prototype.push.apply(additions,targetParts);removals.push(targetFeature);targetSplit=true;}}} +if(sourceParts&&sourceParts.length>1){this.geomsToFeatures(feature,sourceParts);this.events.triggerEvent("split",{original:feature,features:sourceParts});Array.prototype.push.apply(additions,sourceParts);removals.push(feature);sourceSplit=true;} +if(sourceSplit||targetSplit){if(this.deferDelete){var feat,destroys=[];for(var i=0,len=removals.length;i<len;++i){feat=removals[i];if(feat.state===OpenLayers.State.INSERT){destroys.push(feat);}else{feat.state=OpenLayers.State.DELETE;this.layer.drawFeature(feat);}} +this.layer.destroyFeatures(destroys,{silent:true});for(var i=0,len=additions.length;i<len;++i){additions[i].state=OpenLayers.State.INSERT;}}else{this.layer.destroyFeatures(removals,{silent:true});} +this.layer.addFeatures(additions,{silent:true});this.events.triggerEvent("aftersplit",{source:feature,features:additions});}} +return sourceSplit;},geomsToFeatures:function(feature,geoms){var clone=feature.clone();delete clone.geometry;var newFeature;for(var i=0,len=geoms.length;i<len;++i){newFeature=clone.clone();newFeature.geometry=geoms[i];newFeature.state=OpenLayers.State.INSERT;geoms[i]=newFeature;}},destroy:function(){if(this.active){this.deactivate();} +OpenLayers.Control.prototype.destroy.call(this);},CLASS_NAME:"OpenLayers.Control.Split"});OpenLayers.Geometry.Polygon=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.LinearRing"],initialize:function(components){OpenLayers.Geometry.Collection.prototype.initialize.apply(this,arguments);},getArea:function(){var area=0.0;if(this.components&&(this.components.length>0)){area+=Math.abs(this.components[0].getArea());for(var i=1,len=this.components.length;i<len;i++){area-=Math.abs(this.components[i].getArea());}} +return area;},getGeodesicArea:function(projection){var area=0.0;if(this.components&&(this.components.length>0)){area+=Math.abs(this.components[0].getGeodesicArea(projection));for(var i=1,len=this.components.length;i<len;i++){area-=Math.abs(this.components[i].getGeodesicArea(projection));}} +return area;},containsPoint:function(point){var numRings=this.components.length;var contained=false;if(numRings>0){contained=this.components[0].containsPoint(point);if(contained!==1){if(contained&&numRings>1){var hole;for(var i=1;i<numRings;++i){hole=this.components[i].containsPoint(point);if(hole){if(hole===1){contained=1;}else{contained=false;} +break;}}}}} +return contained;},intersects:function(geometry){var intersect=false;var i,len;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){intersect=this.containsPoint(geometry);}else if(geometry.CLASS_NAME=="OpenLayers.Geometry.LineString"||geometry.CLASS_NAME=="OpenLayers.Geometry.LinearRing"){for(i=0,len=this.components.length;i<len;++i){intersect=geometry.intersects(this.components[i]);if(intersect){break;}} +if(!intersect){for(i=0,len=geometry.components.length;i<len;++i){intersect=this.containsPoint(geometry.components[i]);if(intersect){break;}}}}else{for(i=0,len=geometry.components.length;i<len;++i){intersect=this.intersects(geometry.components[i]);if(intersect){break;}}} +if(!intersect&&geometry.CLASS_NAME=="OpenLayers.Geometry.Polygon"){var ring=this.components[0];for(i=0,len=ring.components.length;i<len;++i){intersect=geometry.containsPoint(ring.components[i]);if(intersect){break;}}} +return intersect;},distanceTo:function(geometry,options){var edge=!(options&&options.edge===false);var result;if(!edge&&this.intersects(geometry)){result=0;}else{result=OpenLayers.Geometry.Collection.prototype.distanceTo.apply(this,[geometry,options]);} +return result;},CLASS_NAME:"OpenLayers.Geometry.Polygon"});OpenLayers.Geometry.Polygon.createRegularPolygon=function(origin,radius,sides,rotation){var angle=Math.PI*((1/sides)-(1/2));if(rotation){angle+=(rotation/180)*Math.PI;} +var rotatedAngle,x,y;var points=[];for(var i=0;i<sides;++i){rotatedAngle=angle+(i*2*Math.PI/sides);x=origin.x+(radius*Math.cos(rotatedAngle));y=origin.y+(radius*Math.sin(rotatedAngle));points.push(new OpenLayers.Geometry.Point(x,y));} +var ring=new OpenLayers.Geometry.LinearRing(points);return new OpenLayers.Geometry.Polygon([ring]);};OpenLayers.Format.GeoRSS=OpenLayers.Class(OpenLayers.Format.XML,{rssns:"http://backend.userland.com/rss2",featureNS:"http://mapserver.gis.umn.edu/mapserver",georssns:"http://www.georss.org/georss",geons:"http://www.w3.org/2003/01/geo/wgs84_pos#",featureTitle:"Untitled",featureDescription:"No Description",gmlParser:null,xy:false,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},createGeometryFromItem:function(item){var point=this.getElementsByTagNameNS(item,this.georssns,"point");var lat=this.getElementsByTagNameNS(item,this.geons,'lat');var lon=this.getElementsByTagNameNS(item,this.geons,'long');var line=this.getElementsByTagNameNS(item,this.georssns,"line");var polygon=this.getElementsByTagNameNS(item,this.georssns,"polygon");var where=this.getElementsByTagNameNS(item,this.georssns,"where");var box=this.getElementsByTagNameNS(item,this.georssns,"box");if(point.length>0||(lat.length>0&&lon.length>0)){var location;if(point.length>0){location=OpenLayers.String.trim(point[0].firstChild.nodeValue).split(/\s+/);if(location.length!=2){location=OpenLayers.String.trim(point[0].firstChild.nodeValue).split(/\s*,\s*/);}}else{location=[parseFloat(lat[0].firstChild.nodeValue),parseFloat(lon[0].firstChild.nodeValue)];} +var geometry=new OpenLayers.Geometry.Point(parseFloat(location[1]),parseFloat(location[0]));}else if(line.length>0){var coords=OpenLayers.String.trim(this.concatChildValues(line[0])).split(/\s+/);var components=[];var point;for(var i=0,len=coords.length;i<len;i+=2){point=new OpenLayers.Geometry.Point(parseFloat(coords[i+1]),parseFloat(coords[i]));components.push(point);} +geometry=new OpenLayers.Geometry.LineString(components);}else if(polygon.length>0){var coords=OpenLayers.String.trim(this.concatChildValues(polygon[0])).split(/\s+/);var components=[];var point;for(var i=0,len=coords.length;i<len;i+=2){point=new OpenLayers.Geometry.Point(parseFloat(coords[i+1]),parseFloat(coords[i]));components.push(point);} +geometry=new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(components)]);}else if(where.length>0){if(!this.gmlParser){this.gmlParser=new OpenLayers.Format.GML({'xy':this.xy});} +var feature=this.gmlParser.parseFeature(where[0]);geometry=feature.geometry;}else if(box.length>0){var coords=OpenLayers.String.trim(box[0].firstChild.nodeValue).split(/\s+/);var components=[];var point;if(coords.length>3){point=new OpenLayers.Geometry.Point(parseFloat(coords[1]),parseFloat(coords[0]));components.push(point);point=new OpenLayers.Geometry.Point(parseFloat(coords[1]),parseFloat(coords[2]));components.push(point);point=new OpenLayers.Geometry.Point(parseFloat(coords[3]),parseFloat(coords[2]));components.push(point);point=new OpenLayers.Geometry.Point(parseFloat(coords[3]),parseFloat(coords[0]));components.push(point);point=new OpenLayers.Geometry.Point(parseFloat(coords[1]),parseFloat(coords[0]));components.push(point);} +geometry=new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(components)]);} +if(geometry&&this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection);} +return geometry;},createFeatureFromItem:function(item){var geometry=this.createGeometryFromItem(item);var title=this.getChildValue(item,"*","title",this.featureTitle);var description=this.getChildValue(item,"*","description",this.getChildValue(item,"*","content",this.getChildValue(item,"*","summary",this.featureDescription)));var link=this.getChildValue(item,"*","link");if(!link){try{link=this.getElementsByTagNameNS(item,"*","link")[0].getAttribute("href");}catch(e){link=null;}} +var id=this.getChildValue(item,"*","id",null);var data={"title":title,"description":description,"link":link};var feature=new OpenLayers.Feature.Vector(geometry,data);feature.fid=id;return feature;},getChildValue:function(node,nsuri,name,def){var value;var eles=this.getElementsByTagNameNS(node,nsuri,name);if(eles&&eles[0]&&eles[0].firstChild&&eles[0].firstChild.nodeValue){value=eles[0].firstChild.nodeValue;}else{value=(def==undefined)?"":def;} +return value;},read:function(doc){if(typeof doc=="string"){doc=OpenLayers.Format.XML.prototype.read.apply(this,[doc]);} +var itemlist=null;itemlist=this.getElementsByTagNameNS(doc,'*','item');if(itemlist.length==0){itemlist=this.getElementsByTagNameNS(doc,'*','entry');} +var numItems=itemlist.length;var features=new Array(numItems);for(var i=0;i<numItems;i++){features[i]=this.createFeatureFromItem(itemlist[i]);} +return features;},write:function(features){var georss;if(features instanceof Array){georss=this.createElementNS(this.rssns,"rss");for(var i=0,len=features.length;i<len;i++){georss.appendChild(this.createFeatureXML(features[i]));}}else{georss=this.createFeatureXML(features);} +return OpenLayers.Format.XML.prototype.write.apply(this,[georss]);},createFeatureXML:function(feature){var geometryNode=this.buildGeometryNode(feature.geometry);var featureNode=this.createElementNS(this.rssns,"item");var titleNode=this.createElementNS(this.rssns,"title");titleNode.appendChild(this.createTextNode(feature.attributes.title?feature.attributes.title:""));var descNode=this.createElementNS(this.rssns,"description");descNode.appendChild(this.createTextNode(feature.attributes.description?feature.attributes.description:""));featureNode.appendChild(titleNode);featureNode.appendChild(descNode);if(feature.attributes.link){var linkNode=this.createElementNS(this.rssns,"link");linkNode.appendChild(this.createTextNode(feature.attributes.link));featureNode.appendChild(linkNode);} +for(var attr in feature.attributes){if(attr=="link"||attr=="title"||attr=="description"){continue;} +var attrText=this.createTextNode(feature.attributes[attr]);var nodename=attr;if(attr.search(":")!=-1){nodename=attr.split(":")[1];} +var attrContainer=this.createElementNS(this.featureNS,"feature:"+nodename);attrContainer.appendChild(attrText);featureNode.appendChild(attrContainer);} +featureNode.appendChild(geometryNode);return featureNode;},buildGeometryNode:function(geometry){if(this.internalProjection&&this.externalProjection){geometry=geometry.clone();geometry.transform(this.internalProjection,this.externalProjection);} +var node;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Polygon"){node=this.createElementNS(this.georssns,'georss:polygon');node.appendChild(this.buildCoordinatesNode(geometry.components[0]));} +else if(geometry.CLASS_NAME=="OpenLayers.Geometry.LineString"){node=this.createElementNS(this.georssns,'georss:line');node.appendChild(this.buildCoordinatesNode(geometry));} +else if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){node=this.createElementNS(this.georssns,'georss:point');node.appendChild(this.buildCoordinatesNode(geometry));}else{throw"Couldn't parse "+geometry.CLASS_NAME;} +return node;},buildCoordinatesNode:function(geometry){var points=null;if(geometry.components){points=geometry.components;} +var path;if(points){var numPoints=points.length;var parts=new Array(numPoints);for(var i=0;i<numPoints;i++){parts[i]=points[i].y+" "+points[i].x;} +path=parts.join(" ");}else{path=geometry.y+" "+geometry.x;} +return this.createTextNode(path);},CLASS_NAME:"OpenLayers.Format.GeoRSS"});OpenLayers.Format.KML=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{kml:"http://www.opengis.net/kml/2.2",gx:"http://www.google.com/kml/ext/2.2"},kmlns:"http://earth.google.com/kml/2.0",placemarksDesc:"No description available",foldersName:"OpenLayers export",foldersDesc:"Exported on "+new Date(),extractAttributes:true,extractStyles:false,extractTracks:false,trackAttributes:null,internalns:null,features:null,styles:null,styleBaseUrl:"",fetched:null,maxDepth:0,initialize:function(options){this.regExes={trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g),kmlColor:(/(\w{2})(\w{2})(\w{2})(\w{2})/),kmlIconPalette:(/root:\/\/icons\/palette-(\d+)(\.\w+)/),straightBracket:(/\$\[(.*?)\]/g)};this.externalProjection=new OpenLayers.Projection("EPSG:4326");OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){this.features=[];this.styles={};this.fetched={};var options={depth:0,styleBaseUrl:this.styleBaseUrl};return this.parseData(data,options);},parseData:function(data,options){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +var types=["Link","NetworkLink","Style","StyleMap","Placemark"];for(var i=0,len=types.length;i<len;++i){var type=types[i];var nodes=this.getElementsByTagNameNS(data,"*",type);if(nodes.length==0){continue;} +switch(type.toLowerCase()){case"link":case"networklink":this.parseLinks(nodes,options);break;case"style":if(this.extractStyles){this.parseStyles(nodes,options);} +break;case"stylemap":if(this.extractStyles){this.parseStyleMaps(nodes,options);} +break;case"placemark":this.parseFeatures(nodes,options);break;}} +return this.features;},parseLinks:function(nodes,options){if(options.depth>=this.maxDepth){return false;} +var newOptions=OpenLayers.Util.extend({},options);newOptions.depth++;for(var i=0,len=nodes.length;i<len;i++){var href=this.parseProperty(nodes[i],"*","href");if(href&&!this.fetched[href]){this.fetched[href]=true;var data=this.fetchLink(href);if(data){this.parseData(data,newOptions);}}}},fetchLink:function(href){var request=OpenLayers.Request.GET({url:href,async:false});if(request){return request.responseText;}},parseStyles:function(nodes,options){for(var i=0,len=nodes.length;i<len;i++){var style=this.parseStyle(nodes[i]);if(style){var styleName=(options.styleBaseUrl||"")+"#"+style.id;this.styles[styleName]=style;}}},parseKmlColor:function(kmlColor){var color=null;if(kmlColor){var matches=kmlColor.match(this.regExes.kmlColor);if(matches){color={color:'#'+matches[4]+matches[3]+matches[2],opacity:parseInt(matches[1],16)/255};}} +return color;},parseStyle:function(node){var style={};var types=["LineStyle","PolyStyle","IconStyle","BalloonStyle","LabelStyle"];var type,nodeList,geometry,parser;for(var i=0,len=types.length;i<len;++i){type=types[i];styleTypeNode=this.getElementsByTagNameNS(node,"*",type)[0];if(!styleTypeNode){continue;} +switch(type.toLowerCase()){case"linestyle":var kmlColor=this.parseProperty(styleTypeNode,"*","color");var color=this.parseKmlColor(kmlColor);if(color){style["strokeColor"]=color.color;style["strokeOpacity"]=color.opacity;} +var width=this.parseProperty(styleTypeNode,"*","width");if(width){style["strokeWidth"]=width;} +break;case"polystyle":var kmlColor=this.parseProperty(styleTypeNode,"*","color");var color=this.parseKmlColor(kmlColor);if(color){style["fillOpacity"]=color.opacity;style["fillColor"]=color.color;} +var fill=this.parseProperty(styleTypeNode,"*","fill");if(fill=="0"){style["fillColor"]="none";} +var outline=this.parseProperty(styleTypeNode,"*","outline");if(outline=="0"){style["strokeWidth"]="0";} +break;case"iconstyle":var scale=parseFloat(this.parseProperty(styleTypeNode,"*","scale")||1);var width=32*scale;var height=32*scale;var iconNode=this.getElementsByTagNameNS(styleTypeNode,"*","Icon")[0];if(iconNode){var href=this.parseProperty(iconNode,"*","href");if(href){var w=this.parseProperty(iconNode,"*","w");var h=this.parseProperty(iconNode,"*","h");var google="http://maps.google.com/mapfiles/kml";if(OpenLayers.String.startsWith(href,google)&&!w&&!h){w=64;h=64;scale=scale/2;} +w=w||h;h=h||w;if(w){width=parseInt(w)*scale;} +if(h){height=parseInt(h)*scale;} +var matches=href.match(this.regExes.kmlIconPalette);if(matches){var palette=matches[1];var file_extension=matches[2];var x=this.parseProperty(iconNode,"*","x");var y=this.parseProperty(iconNode,"*","y");var posX=x?x/32:0;var posY=y?(7-y/32):7;var pos=posY*8+posX;href="http://maps.google.com/mapfiles/kml/pal" ++palette+"/icon"+pos+file_extension;} +style["graphicOpacity"]=1;style["externalGraphic"]=href;}} +var hotSpotNode=this.getElementsByTagNameNS(styleTypeNode,"*","hotSpot")[0];if(hotSpotNode){var x=parseFloat(hotSpotNode.getAttribute("x"));var y=parseFloat(hotSpotNode.getAttribute("y"));var xUnits=hotSpotNode.getAttribute("xunits");if(xUnits=="pixels"){style["graphicXOffset"]=-x*scale;} +else if(xUnits=="insetPixels"){style["graphicXOffset"]=-width+(x*scale);} +else if(xUnits=="fraction"){style["graphicXOffset"]=-width*x;} +var yUnits=hotSpotNode.getAttribute("yunits");if(yUnits=="pixels"){style["graphicYOffset"]=-height+(y*scale)+1;} +else if(yUnits=="insetPixels"){style["graphicYOffset"]=-(y*scale)+1;} +else if(yUnits=="fraction"){style["graphicYOffset"]=-height*(1-y)+1;}} +style["graphicWidth"]=width;style["graphicHeight"]=height;break;case"balloonstyle":var balloonStyle=OpenLayers.Util.getXmlNodeValue(styleTypeNode);if(balloonStyle){style["balloonStyle"]=balloonStyle.replace(this.regExes.straightBracket,"${$1}");} +break;case"labelstyle":var kmlColor=this.parseProperty(styleTypeNode,"*","color");var color=this.parseKmlColor(kmlColor);if(color){style["fontColor"]=color.color;style["fontOpacity"]=color.opacity;} +break;default:}} +if(!style["strokeColor"]&&style["fillColor"]){style["strokeColor"]=style["fillColor"];} +var id=node.getAttribute("id");if(id&&style){style.id=id;} +return style;},parseStyleMaps:function(nodes,options){for(var i=0,len=nodes.length;i<len;i++){var node=nodes[i];var pairs=this.getElementsByTagNameNS(node,"*","Pair");var id=node.getAttribute("id");for(var j=0,jlen=pairs.length;j<jlen;j++){var pair=pairs[j];var key=this.parseProperty(pair,"*","key");var styleUrl=this.parseProperty(pair,"*","styleUrl");if(styleUrl&&key=="normal"){this.styles[(options.styleBaseUrl||"")+"#"+id]=this.styles[(options.styleBaseUrl||"")+styleUrl];} +if(styleUrl&&key=="highlight"){}}}},parseFeatures:function(nodes,options){var features=[];for(var i=0,len=nodes.length;i<len;i++){var featureNode=nodes[i];var feature=this.parseFeature.apply(this,[featureNode]);if(feature){if(this.extractStyles&&feature.attributes&&feature.attributes.styleUrl){feature.style=this.getStyle(feature.attributes.styleUrl,options);} +if(this.extractStyles){var inlineStyleNode=this.getElementsByTagNameNS(featureNode,"*","Style")[0];if(inlineStyleNode){var inlineStyle=this.parseStyle(inlineStyleNode);if(inlineStyle){feature.style=OpenLayers.Util.extend(feature.style,inlineStyle);}}} +if(this.extractTracks){var tracks=this.getElementsByTagNameNS(featureNode,this.namespaces.gx,"Track");if(tracks&&tracks.length>0){var track=tracks[0];var container={features:[],feature:feature};this.readNode(track,container);if(container.features.length>0){features.push.apply(features,container.features);}}}else{features.push(feature);}}else{throw"Bad Placemark: "+i;}} +this.features=this.features.concat(features);},readers:{"kml":{"when":function(node,container){container.whens.push(OpenLayers.Date.parse(this.getChildValue(node)));},"_trackPointAttribute":function(node,container){var name=node.nodeName.split(":").pop();container.attributes[name].push(this.getChildValue(node));}},"gx":{"Track":function(node,container){var obj={whens:[],points:[],angles:[]};if(this.trackAttributes){var name;obj.attributes={};for(var i=0,ii=this.trackAttributes.length;i<ii;++i){name=this.trackAttributes[i];obj.attributes[name]=[];if(!(name in this.readers.kml)){this.readers.kml[name]=this.readers.kml._trackPointAttribute;}}} +this.readChildNodes(node,obj);if(obj.whens.length!==obj.points.length){throw new Error("gx:Track with unequal number of when ("+obj.whens.length+") and gx:coord ("+obj.points.length+") elements.");} +var hasAngles=obj.angles.length>0;if(hasAngles&&obj.whens.length!==obj.angles.length){throw new Error("gx:Track with unequal number of when ("+obj.whens.length+") and gx:angles ("+obj.angles.length+") elements.");} +var feature,point,angles;for(var i=0,ii=obj.whens.length;i<ii;++i){feature=container.feature.clone();feature.fid=container.feature.fid||container.feature.id;point=obj.points[i];feature.geometry=point;if("z"in point){feature.attributes.altitude=point.z;} +if(this.internalProjection&&this.externalProjection){feature.geometry.transform(this.externalProjection,this.internalProjection);} +if(this.trackAttributes){for(var j=0,jj=this.trackAttributes.length;j<jj;++j){feature.attributes[name]=obj.attributes[this.trackAttributes[j]][i];}} +feature.attributes.when=obj.whens[i];feature.attributes.trackId=container.feature.id;if(hasAngles){angles=obj.angles[i];feature.attributes.heading=parseFloat(angles[0]);feature.attributes.tilt=parseFloat(angles[1]);feature.attributes.roll=parseFloat(angles[2]);} +container.features.push(feature);}},"coord":function(node,container){var str=this.getChildValue(node);var coords=str.replace(this.regExes.trimSpace,"").split(/\s+/);var point=new OpenLayers.Geometry.Point(coords[0],coords[1]);if(coords.length>2){point.z=parseFloat(coords[2]);} +container.points.push(point);},"angles":function(node,container){var str=this.getChildValue(node);var parts=str.replace(this.regExes.trimSpace,"").split(/\s+/);container.angles.push(parts);}}},parseFeature:function(node){var order=["MultiGeometry","Polygon","LineString","Point"];var type,nodeList,geometry,parser;for(var i=0,len=order.length;i<len;++i){type=order[i];this.internalns=node.namespaceURI?node.namespaceURI:this.kmlns;nodeList=this.getElementsByTagNameNS(node,this.internalns,type);if(nodeList.length>0){var parser=this.parseGeometry[type.toLowerCase()];if(parser){geometry=parser.apply(this,[nodeList[0]]);if(this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection);}}else{OpenLayers.Console.error(OpenLayers.i18n("unsupportedGeometryType",{'geomType':type}));} +break;}} +var attributes;if(this.extractAttributes){attributes=this.parseAttributes(node);} +var feature=new OpenLayers.Feature.Vector(geometry,attributes);var fid=node.getAttribute("id")||node.getAttribute("name");if(fid!=null){feature.fid=fid;} +return feature;},getStyle:function(styleUrl,options){var styleBaseUrl=OpenLayers.Util.removeTail(styleUrl);var newOptions=OpenLayers.Util.extend({},options);newOptions.depth++;newOptions.styleBaseUrl=styleBaseUrl;if(!this.styles[styleUrl]&&!OpenLayers.String.startsWith(styleUrl,"#")&&newOptions.depth<=this.maxDepth&&!this.fetched[styleBaseUrl]){var data=this.fetchLink(styleBaseUrl);if(data){this.parseData(data,newOptions);}} +var style=OpenLayers.Util.extend({},this.styles[styleUrl]);return style;},parseGeometry:{point:function(node){var nodeList=this.getElementsByTagNameNS(node,this.internalns,"coordinates");var coords=[];if(nodeList.length>0){var coordString=nodeList[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.removeSpace,"");coords=coordString.split(",");} +var point=null;if(coords.length>1){if(coords.length==2){coords[2]=null;} +point=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{throw"Bad coordinate string: "+coordString;} +return point;},linestring:function(node,ring){var nodeList=this.getElementsByTagNameNS(node,this.internalns,"coordinates");var line=null;if(nodeList.length>0){var coordString=this.getChildValue(nodeList[0]);coordString=coordString.replace(this.regExes.trimSpace,"");coordString=coordString.replace(this.regExes.trimComma,",");var pointList=coordString.split(this.regExes.splitSpace);var numPoints=pointList.length;var points=new Array(numPoints);var coords,numCoords;for(var i=0;i<numPoints;++i){coords=pointList[i].split(",");numCoords=coords.length;if(numCoords>1){if(coords.length==2){coords[2]=null;} +points[i]=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{throw"Bad LineString point coordinates: "+ +pointList[i];}} +if(numPoints){if(ring){line=new OpenLayers.Geometry.LinearRing(points);}else{line=new OpenLayers.Geometry.LineString(points);}}else{throw"Bad LineString coordinates: "+coordString;}} +return line;},polygon:function(node){var nodeList=this.getElementsByTagNameNS(node,this.internalns,"LinearRing");var numRings=nodeList.length;var components=new Array(numRings);if(numRings>0){var ring;for(var i=0,len=nodeList.length;i<len;++i){ring=this.parseGeometry.linestring.apply(this,[nodeList[i],true]);if(ring){components[i]=ring;}else{throw"Bad LinearRing geometry: "+i;}}} +return new OpenLayers.Geometry.Polygon(components);},multigeometry:function(node){var child,parser;var parts=[];var children=node.childNodes;for(var i=0,len=children.length;i<len;++i){child=children[i];if(child.nodeType==1){var type=(child.prefix)?child.nodeName.split(":")[1]:child.nodeName;var parser=this.parseGeometry[type.toLowerCase()];if(parser){parts.push(parser.apply(this,[child]));}}} +return new OpenLayers.Geometry.Collection(parts);}},parseAttributes:function(node){var attributes={};var edNodes=node.getElementsByTagName("ExtendedData");if(edNodes.length){attributes=this.parseExtendedData(edNodes[0]);} +var child,grandchildren,grandchild;var children=node.childNodes;for(var i=0,len=children.length;i<len;++i){child=children[i];if(child.nodeType==1){grandchildren=child.childNodes;if(grandchildren.length>=1&&grandchildren.length<=3){var grandchild;switch(grandchildren.length){case 1:grandchild=grandchildren[0];break;case 2:var c1=grandchildren[0];var c2=grandchildren[1];grandchild=(c1.nodeType==3||c1.nodeType==4)?c1:c2;break;case 3:default:grandchild=grandchildren[1];break;} +if(grandchild.nodeType==3||grandchild.nodeType==4){var name=(child.prefix)?child.nodeName.split(":")[1]:child.nodeName;var value=OpenLayers.Util.getXmlNodeValue(grandchild);if(value){value=value.replace(this.regExes.trimSpace,"");attributes[name]=value;}}}}} +return attributes;},parseExtendedData:function(node){var attributes={};var i,len,data,key;var dataNodes=node.getElementsByTagName("Data");for(i=0,len=dataNodes.length;i<len;i++){data=dataNodes[i];key=data.getAttribute("name");var ed={};var valueNode=data.getElementsByTagName("value");if(valueNode.length){ed['value']=this.getChildValue(valueNode[0]);} +var nameNode=data.getElementsByTagName("displayName");if(nameNode.length){ed['displayName']=this.getChildValue(nameNode[0]);} +attributes[key]=ed;} +var simpleDataNodes=node.getElementsByTagName("SimpleData");for(i=0,len=simpleDataNodes.length;i<len;i++){var ed={};data=simpleDataNodes[i];key=data.getAttribute("name");ed['value']=this.getChildValue(data);ed['displayName']=key;attributes[key]=ed;} +return attributes;},parseProperty:function(xmlNode,namespace,tagName){var value;var nodeList=this.getElementsByTagNameNS(xmlNode,namespace,tagName);try{value=OpenLayers.Util.getXmlNodeValue(nodeList[0]);}catch(e){value=null;} +return value;},write:function(features){if(!(features instanceof Array)){features=[features];} +var kml=this.createElementNS(this.kmlns,"kml");var folder=this.createFolderXML();for(var i=0,len=features.length;i<len;++i){folder.appendChild(this.createPlacemarkXML(features[i]));} +kml.appendChild(folder);return OpenLayers.Format.XML.prototype.write.apply(this,[kml]);},createFolderXML:function(){var folder=this.createElementNS(this.kmlns,"Folder");if(this.foldersName){var folderName=this.createElementNS(this.kmlns,"name");var folderNameText=this.createTextNode(this.foldersName);folderName.appendChild(folderNameText);folder.appendChild(folderName);} +if(this.foldersDesc){var folderDesc=this.createElementNS(this.kmlns,"description");var folderDescText=this.createTextNode(this.foldersDesc);folderDesc.appendChild(folderDescText);folder.appendChild(folderDesc);} +return folder;},createPlacemarkXML:function(feature){var placemarkName=this.createElementNS(this.kmlns,"name");var name=feature.style&&feature.style.label?feature.style.label:feature.attributes.name||feature.id;placemarkName.appendChild(this.createTextNode(name));var placemarkDesc=this.createElementNS(this.kmlns,"description");var desc=feature.attributes.description||this.placemarksDesc;placemarkDesc.appendChild(this.createTextNode(desc));var placemarkNode=this.createElementNS(this.kmlns,"Placemark");if(feature.fid!=null){placemarkNode.setAttribute("id",feature.fid);} +placemarkNode.appendChild(placemarkName);placemarkNode.appendChild(placemarkDesc);var geometryNode=this.buildGeometryNode(feature.geometry);placemarkNode.appendChild(geometryNode);return placemarkNode;},buildGeometryNode:function(geometry){if(this.internalProjection&&this.externalProjection){geometry=geometry.clone();geometry.transform(this.internalProjection,this.externalProjection);} +var className=geometry.CLASS_NAME;var type=className.substring(className.lastIndexOf(".")+1);var builder=this.buildGeometry[type.toLowerCase()];var node=null;if(builder){node=builder.apply(this,[geometry]);} +return node;},buildGeometry:{point:function(geometry){var kml=this.createElementNS(this.kmlns,"Point");kml.appendChild(this.buildCoordinatesNode(geometry));return kml;},multipoint:function(geometry){return this.buildGeometry.collection.apply(this,[geometry]);},linestring:function(geometry){var kml=this.createElementNS(this.kmlns,"LineString");kml.appendChild(this.buildCoordinatesNode(geometry));return kml;},multilinestring:function(geometry){return this.buildGeometry.collection.apply(this,[geometry]);},linearring:function(geometry){var kml=this.createElementNS(this.kmlns,"LinearRing");kml.appendChild(this.buildCoordinatesNode(geometry));return kml;},polygon:function(geometry){var kml=this.createElementNS(this.kmlns,"Polygon");var rings=geometry.components;var ringMember,ringGeom,type;for(var i=0,len=rings.length;i<len;++i){type=(i==0)?"outerBoundaryIs":"innerBoundaryIs";ringMember=this.createElementNS(this.kmlns,type);ringGeom=this.buildGeometry.linearring.apply(this,[rings[i]]);ringMember.appendChild(ringGeom);kml.appendChild(ringMember);} +return kml;},multipolygon:function(geometry){return this.buildGeometry.collection.apply(this,[geometry]);},collection:function(geometry){var kml=this.createElementNS(this.kmlns,"MultiGeometry");var child;for(var i=0,len=geometry.components.length;i<len;++i){child=this.buildGeometryNode.apply(this,[geometry.components[i]]);if(child){kml.appendChild(child);}} +return kml;}},buildCoordinatesNode:function(geometry){var coordinatesNode=this.createElementNS(this.kmlns,"coordinates");var path;var points=geometry.components;if(points){var point;var numPoints=points.length;var parts=new Array(numPoints);for(var i=0;i<numPoints;++i){point=points[i];parts[i]=point.x+","+point.y;} +path=parts.join(" ");}else{path=geometry.x+","+geometry.y;} +var txtNode=this.createTextNode(path);coordinatesNode.appendChild(txtNode);return coordinatesNode;},CLASS_NAME:"OpenLayers.Format.KML"});OpenLayers.Format.OSM=OpenLayers.Class(OpenLayers.Format.XML,{checkTags:false,interestingTagsExclude:null,areaTags:null,initialize:function(options){var layer_defaults={'interestingTagsExclude':['source','source_ref','source:ref','history','attribution','created_by'],'areaTags':['area','building','leisure','tourism','ruins','historic','landuse','military','natural','sport']};layer_defaults=OpenLayers.Util.extend(layer_defaults,options);var interesting={};for(var i=0;i<layer_defaults.interestingTagsExclude.length;i++){interesting[layer_defaults.interestingTagsExclude[i]]=true;} +layer_defaults.interestingTagsExclude=interesting;var area={};for(var i=0;i<layer_defaults.areaTags.length;i++){area[layer_defaults.areaTags[i]]=true;} +layer_defaults.areaTags=area;this.externalProjection=new OpenLayers.Projection("EPSG:4326");OpenLayers.Format.XML.prototype.initialize.apply(this,[layer_defaults]);},read:function(doc){if(typeof doc=="string"){doc=OpenLayers.Format.XML.prototype.read.apply(this,[doc]);} +var nodes=this.getNodes(doc);var ways=this.getWays(doc);var feat_list=new Array(ways.length);for(var i=0;i<ways.length;i++){var point_list=new Array(ways[i].nodes.length);var poly=this.isWayArea(ways[i])?1:0;for(var j=0;j<ways[i].nodes.length;j++){var node=nodes[ways[i].nodes[j]];var point=new OpenLayers.Geometry.Point(node.lon,node.lat);point.osm_id=parseInt(ways[i].nodes[j]);point_list[j]=point;node.used=true;} +var geometry=null;if(poly){geometry=new OpenLayers.Geometry.Polygon(new OpenLayers.Geometry.LinearRing(point_list));}else{geometry=new OpenLayers.Geometry.LineString(point_list);} +if(this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection);} +var feat=new OpenLayers.Feature.Vector(geometry,ways[i].tags);feat.osm_id=parseInt(ways[i].id);feat.fid="way."+feat.osm_id;feat_list[i]=feat;} +for(var node_id in nodes){var node=nodes[node_id];if(!node.used||this.checkTags){var tags=null;if(this.checkTags){var result=this.getTags(node.node,true);if(node.used&&!result[1]){continue;} +tags=result[0];}else{tags=this.getTags(node.node);} +var feat=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(node['lon'],node['lat']),tags);if(this.internalProjection&&this.externalProjection){feat.geometry.transform(this.externalProjection,this.internalProjection);} +feat.osm_id=parseInt(node_id);feat.fid="node."+feat.osm_id;feat_list.push(feat);} +node.node=null;} +return feat_list;},getNodes:function(doc){var node_list=doc.getElementsByTagName("node");var nodes={};for(var i=0;i<node_list.length;i++){var node=node_list[i];var id=node.getAttribute("id");nodes[id]={'lat':node.getAttribute("lat"),'lon':node.getAttribute("lon"),'node':node};} +return nodes;},getWays:function(doc){var way_list=doc.getElementsByTagName("way");var return_ways=[];for(var i=0;i<way_list.length;i++){var way=way_list[i];var way_object={id:way.getAttribute("id")};way_object.tags=this.getTags(way);var node_list=way.getElementsByTagName("nd");way_object.nodes=new Array(node_list.length);for(var j=0;j<node_list.length;j++){way_object.nodes[j]=node_list[j].getAttribute("ref");} +return_ways.push(way_object);} +return return_ways;},getTags:function(dom_node,interesting_tags){var tag_list=dom_node.getElementsByTagName("tag");var tags={};var interesting=false;for(var j=0;j<tag_list.length;j++){var key=tag_list[j].getAttribute("k");tags[key]=tag_list[j].getAttribute("v");if(interesting_tags){if(!this.interestingTagsExclude[key]){interesting=true;}}} +return interesting_tags?[tags,interesting]:tags;},isWayArea:function(way){var poly_shaped=false;var poly_tags=false;if(way.nodes[0]==way.nodes[way.nodes.length-1]){poly_shaped=true;} +if(this.checkTags){for(var key in way.tags){if(this.areaTags[key]){poly_tags=true;break;}}} +return poly_shaped&&(this.checkTags?poly_tags:true);},write:function(features){if(!(features instanceof Array)){features=[features];} +this.osm_id=1;this.created_nodes={};var root_node=this.createElementNS(null,"osm");root_node.setAttribute("version","0.5");root_node.setAttribute("generator","OpenLayers "+OpenLayers.VERSION_NUMBER);for(var i=features.length-1;i>=0;i--){var nodes=this.createFeatureNodes(features[i]);for(var j=0;j<nodes.length;j++){root_node.appendChild(nodes[j]);}} +return OpenLayers.Format.XML.prototype.write.apply(this,[root_node]);},createFeatureNodes:function(feature){var nodes=[];var className=feature.geometry.CLASS_NAME;var type=className.substring(className.lastIndexOf(".")+1);type=type.toLowerCase();var builder=this.createXML[type];if(builder){nodes=builder.apply(this,[feature]);} +return nodes;},createXML:{'point':function(point){var id=null;var geometry=point.geometry?point.geometry:point;var already_exists=false;if(point.osm_id){id=point.osm_id;if(this.created_nodes[id]){already_exists=true;}}else{id=-this.osm_id;this.osm_id++;} +if(already_exists){node=this.created_nodes[id];}else{var node=this.createElementNS(null,"node");} +this.created_nodes[id]=node;node.setAttribute("id",id);node.setAttribute("lon",geometry.x);node.setAttribute("lat",geometry.y);if(point.attributes){this.serializeTags(point,node);} +this.setState(point,node);return already_exists?[]:[node];},linestring:function(feature){var nodes=[];var geometry=feature.geometry;if(feature.osm_id){id=feature.osm_id;}else{id=-this.osm_id;this.osm_id++;} +var way=this.createElementNS(null,"way");way.setAttribute("id",id);for(var i=0;i<geometry.components.length;i++){var node=this.createXML['point'].apply(this,[geometry.components[i]]);if(node.length){node=node[0];var node_ref=node.getAttribute("id");nodes.push(node);}else{node_ref=geometry.components[i].osm_id;node=this.created_nodes[node_ref];} +this.setState(feature,node);var nd_dom=this.createElementNS(null,"nd");nd_dom.setAttribute("ref",node_ref);way.appendChild(nd_dom);} +this.serializeTags(feature,way);nodes.push(way);return nodes;},polygon:function(feature){var attrs=OpenLayers.Util.extend({'area':'yes'},feature.attributes);var feat=new OpenLayers.Feature.Vector(feature.geometry.components[0],attrs);feat.osm_id=feature.osm_id;return this.createXML['linestring'].apply(this,[feat]);}},serializeTags:function(feature,node){for(var key in feature.attributes){var tag=this.createElementNS(null,"tag");tag.setAttribute("k",key);tag.setAttribute("v",feature.attributes[key]);node.appendChild(tag);}},setState:function(feature,node){if(feature.state){var state=null;switch(feature.state){case OpenLayers.State.UPDATE:state="modify";case OpenLayers.State.DELETE:state="delete";} +if(state){node.setAttribute("action",state);}}},CLASS_NAME:"OpenLayers.Format.OSM"});OpenLayers.Geometry.MultiPolygon=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.Polygon"],initialize:function(components){OpenLayers.Geometry.Collection.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Geometry.MultiPolygon"});OpenLayers.Handler.Polygon=OpenLayers.Class(OpenLayers.Handler.Path,{polygon:null,initialize:function(control,callbacks,options){OpenLayers.Handler.Path.prototype.initialize.apply(this,arguments);},createFeature:function(pixel){var lonlat=this.control.map.getLonLatFromPixel(pixel);this.point=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat));this.line=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LinearRing([this.point.geometry]));this.polygon=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Polygon([this.line.geometry]));this.callback("create",[this.point.geometry,this.getSketch()]);this.point.geometry.clearBounds();this.layer.addFeatures([this.polygon,this.point],{silent:true});},destroyFeature:function(){OpenLayers.Handler.Path.prototype.destroyFeature.apply(this);this.polygon=null;},drawFeature:function(){this.layer.drawFeature(this.polygon,this.style);this.layer.drawFeature(this.point,this.style);},getSketch:function(){return this.polygon;},getGeometry:function(){var geometry=this.polygon&&this.polygon.geometry;if(geometry&&this.multi){geometry=new OpenLayers.Geometry.MultiPolygon([geometry]);} +return geometry;},dblclick:function(evt){if(!this.freehandMode(evt)){var index=this.line.geometry.components.length-2;this.line.geometry.removeComponent(this.line.geometry.components[index]);this.removePoint();this.finalize();} +return false;},CLASS_NAME:"OpenLayers.Handler.Polygon"});OpenLayers.Control.EditingToolbar=OpenLayers.Class(OpenLayers.Control.Panel,{initialize:function(layer,options){OpenLayers.Control.Panel.prototype.initialize.apply(this,[options]);this.addControls([new OpenLayers.Control.Navigation()]);var controls=[new OpenLayers.Control.DrawFeature(layer,OpenLayers.Handler.Point,{'displayClass':'olControlDrawFeaturePoint'}),new OpenLayers.Control.DrawFeature(layer,OpenLayers.Handler.Path,{'displayClass':'olControlDrawFeaturePath'}),new OpenLayers.Control.DrawFeature(layer,OpenLayers.Handler.Polygon,{'displayClass':'olControlDrawFeaturePolygon'})];this.addControls(controls);},draw:function(){var div=OpenLayers.Control.Panel.prototype.draw.apply(this,arguments);this.activateControl(this.controls[0]);return div;},CLASS_NAME:"OpenLayers.Control.EditingToolbar"});OpenLayers.Control.SLDSelect=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:["selected"],clearOnDeactivate:false,layers:null,callbacks:null,selectionSymbolizer:{'Polygon':{fillColor:'#FF0000',stroke:false},'Line':{strokeColor:'#FF0000',strokeWidth:2},'Point':{graphicName:'square',fillColor:'#FF0000',pointRadius:5}},layerOptions:null,handlerOptions:null,sketchStyle:null,wfsCache:{},layerCache:{},initialize:function(handler,options){this.EVENT_TYPES=OpenLayers.Control.SLDSelect.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.callbacks=OpenLayers.Util.extend({done:this.select,click:this.select},this.callbacks);this.handlerOptions=this.handlerOptions||{};this.layerOptions=OpenLayers.Util.applyDefaults(this.layerOptions,{displayInLayerSwitcher:false});if(this.sketchStyle){this.handlerOptions.layerOptions=OpenLayers.Util.applyDefaults(this.handlerOptions.layerOptions,{styleMap:new OpenLayers.StyleMap({"default":this.sketchStyle})});} +this.handler=new handler(this,this.callbacks,this.handlerOptions);},destroy:function(){for(var key in this.layerCache){delete this.layerCache[key];} +for(var key in this.wfsCache){delete this.wfsCache[key];} +OpenLayers.Control.prototype.destroy.apply(this,arguments);},coupleLayerVisiblity:function(evt){this.setVisibility(evt.object.getVisibility());},createSelectionLayer:function(source){var selectionLayer;if(!this.layerCache[source.id]){selectionLayer=new OpenLayers.Layer.WMS.Post(source.name,source.url,source.params,OpenLayers.Util.applyDefaults(this.layerOptions,source.getOptions()));this.layerCache[source.id]=selectionLayer;if(this.layerOptions.displayInLayerSwitcher===false){source.events.on({"visibilitychanged":this.coupleLayerVisiblity,scope:selectionLayer});} +this.map.addLayer(selectionLayer);}else{selectionLayer=this.layerCache[source.id];} +return selectionLayer;},createSLD:function(layer,filters,geometryAttributes){var sld={version:"1.0.0",namedLayers:{}};var layerNames=[layer.params.LAYERS].join(",").split(",");for(var i=0,len=layerNames.length;i<len;i++){var name=layerNames[i];sld.namedLayers[name]={name:name,userStyles:[]};var symbolizer=this.selectionSymbolizer;var geometryAttribute=geometryAttributes[i];if(geometryAttribute.type.indexOf('Polygon')>=0){symbolizer={Polygon:this.selectionSymbolizer['Polygon']};}else if(geometryAttribute.type.indexOf('LineString')>=0){symbolizer={Line:this.selectionSymbolizer['Line']};}else if(geometryAttribute.type.indexOf('Point')>=0){symbolizer={Point:this.selectionSymbolizer['Point']};} +var filter=filters[i];sld.namedLayers[name].userStyles.push({name:'default',rules:[new OpenLayers.Rule({symbolizer:symbolizer,filter:filter,maxScaleDenominator:layer.options.minScale})]});} +return new OpenLayers.Format.SLD().write(sld);},parseDescribeLayer:function(request){var format=new OpenLayers.Format.WMSDescribeLayer();var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;} +var describeLayer=format.read(doc);var typeNames=[];var url=null;for(var i=0,len=describeLayer.length;i<len;i++){if(describeLayer[i].owsType=="WFS"){typeNames.push(describeLayer[i].typeName);url=describeLayer[i].owsURL;}} +var options={url:url,params:{SERVICE:"WFS",TYPENAME:typeNames.toString(),REQUEST:"DescribeFeatureType",VERSION:"1.0.0"},callback:function(request){var format=new OpenLayers.Format.WFSDescribeFeatureType();var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;} +var describeFeatureType=format.read(doc);this.control.wfsCache[this.layer.id]=describeFeatureType;this.control._queue&&this.control.applySelection();},scope:this};OpenLayers.Request.GET(options);},getGeometryAttributes:function(layer){var result=[];var cache=this.wfsCache[layer.id];for(var i=0,len=cache.featureTypes.length;i<len;i++){var typeName=cache.featureTypes[i];var properties=typeName.properties;for(var j=0,lenj=properties.length;j<lenj;j++){var property=properties[j];var type=property.type;if((type.indexOf('LineString')>=0)||(type.indexOf('GeometryAssociationType')>=0)||(type.indexOf('GeometryPropertyType')>=0)||(type.indexOf('Point')>=0)||(type.indexOf('Polygon')>=0)){result.push(property);}}} +return result;},activate:function(){var activated=OpenLayers.Control.prototype.activate.call(this);if(activated){for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];if(layer&&!this.wfsCache[layer.id]){var options={url:layer.url,params:{SERVICE:"WMS",VERSION:layer.params.VERSION,LAYERS:layer.params.LAYERS,REQUEST:"DescribeLayer"},callback:this.parseDescribeLayer,scope:{layer:layer,control:this}};OpenLayers.Request.GET(options);}}} +return activated;},deactivate:function(){var deactivated=OpenLayers.Control.prototype.deactivate.call(this);if(deactivated){for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];if(layer&&this.clearOnDeactivate===true){var layerCache=this.layerCache;var selectionLayer=layerCache[layer.id];if(selectionLayer){layer.events.un({"visibilitychanged":this.coupleLayerVisiblity,scope:selectionLayer});selectionLayer.destroy();delete layerCache[layer.id];}}}} +return deactivated;},setLayers:function(layers){if(this.active){this.deactivate();this.layers=layers;this.activate();}else{this.layers=layers;}},createFilter:function(geometryAttribute,geometry){var filter=null;if(this.handler instanceof OpenLayers.Handler.RegularPolygon){if(this.handler.irregular===true){filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.BBOX,property:geometryAttribute.name,value:geometry.getBounds()});}else{filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.INTERSECTS,property:geometryAttribute.name,value:geometry});}}else if(this.handler instanceof OpenLayers.Handler.Polygon){filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.INTERSECTS,property:geometryAttribute.name,value:geometry});}else if(this.handler instanceof OpenLayers.Handler.Path){if(geometryAttribute.type.indexOf('Point')>=0){filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.DWITHIN,property:geometryAttribute.name,distance:this.map.getExtent().getWidth()*0.01,distanceUnits:this.map.getUnits(),value:geometry});}else{filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.INTERSECTS,property:geometryAttribute.name,value:geometry});}}else if(this.handler instanceof OpenLayers.Handler.Click){if(geometryAttribute.type.indexOf('Polygon')>=0){filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.INTERSECTS,property:geometryAttribute.name,value:geometry});}else{filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.DWITHIN,property:geometryAttribute.name,distance:this.map.getExtent().getWidth()*0.01,distanceUnits:this.map.getUnits(),value:geometry});}} +return filter;},select:function(geometry){this._queue=function(){for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];var geometryAttributes=this.getGeometryAttributes(layer);var filters=[];for(var j=0,lenj=geometryAttributes.length;j<lenj;j++){var geometryAttribute=geometryAttributes[j];if(geometryAttribute!==null){if(!(geometry instanceof OpenLayers.Geometry)){var point=this.map.getLonLatFromPixel(geometry.xy);geometry=new OpenLayers.Geometry.Point(point.lon,point.lat);} +var filter=this.createFilter(geometryAttribute,geometry);if(filter!==null){filters.push(filter);}}} +var selectionLayer=this.createSelectionLayer(layer);var sld=this.createSLD(layer,filters,geometryAttributes);this.events.triggerEvent("selected",{layer:layer,filters:filters});selectionLayer.mergeNewParams({SLD_BODY:sld});delete this._queue;}};this.applySelection();},applySelection:function(){var canApply=true;for(var i=0,len=this.layers.length;i<len;i++){if(!this.wfsCache[this.layers[i].id]){canApply=false;break;}} +canApply&&this._queue.call(this);},CLASS_NAME:"OpenLayers.Control.SLDSelect"});OpenLayers.Format.ArcXML=OpenLayers.Class(OpenLayers.Format.XML,{fontStyleKeys:['antialiasing','blockout','font','fontcolor','fontsize','fontstyle','glowing','interval','outline','printmode','shadow','transparency'],request:null,response:null,initialize:function(options){this.request=new OpenLayers.Format.ArcXML.Request();this.response=new OpenLayers.Format.ArcXML.Response();if(options){if(options.requesttype=="feature"){this.request.get_image=null;var qry=this.request.get_feature.query;this.addCoordSys(qry.featurecoordsys,options.featureCoordSys);this.addCoordSys(qry.filtercoordsys,options.filterCoordSys);if(options.polygon){qry.isspatial=true;qry.spatialfilter.polygon=options.polygon;}else if(options.envelope){qry.isspatial=true;qry.spatialfilter.envelope={minx:0,miny:0,maxx:0,maxy:0};this.parseEnvelope(qry.spatialfilter.envelope,options.envelope);}}else if(options.requesttype=="image"){this.request.get_feature=null;var props=this.request.get_image.properties;this.parseEnvelope(props.envelope,options.envelope);this.addLayers(props.layerlist,options.layers);this.addImageSize(props.imagesize,options.tileSize);this.addCoordSys(props.featurecoordsys,options.featureCoordSys);this.addCoordSys(props.filtercoordsys,options.filterCoordSys);}else{this.request=null;}} +OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},parseEnvelope:function(env,arr){if(arr&&arr.length==4){env.minx=arr[0];env.miny=arr[1];env.maxx=arr[2];env.maxy=arr[3];}},addLayers:function(ll,lyrs){for(var lind=0,len=lyrs.length;lind<len;lind++){ll.push(lyrs[lind]);}},addImageSize:function(imsize,olsize){if(olsize!==null){imsize.width=olsize.w;imsize.height=olsize.h;imsize.printwidth=olsize.w;imsize.printheight=olsize.h;}},addCoordSys:function(featOrFilt,fsys){if(typeof fsys=="string"){featOrFilt.id=parseInt(fsys);featOrFilt.string=fsys;} +else if(typeof fsys=="object"&&fsys.proj!==null){featOrFilt.id=fsys.proj.srsProjNumber;featOrFilt.string=fsys.proj.srsCode;}else{featOrFilt=fsys;}},iserror:function(data){var ret=null;if(!data){ret=(this.response.error!=='');}else{data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);var errorNodes=data.documentElement.getElementsByTagName("ERROR");ret=(errorNodes!==null&&errorNodes.length>0);} +return ret;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +var arcNode=null;if(data&&data.documentElement){if(data.documentElement.nodeName=="ARCXML"){arcNode=data.documentElement;}else{arcNode=data.documentElement.getElementsByTagName("ARCXML")[0];}} +if(!arcNode||arcNode.firstChild.nodeName==='parsererror'){var error,source;try{error=data.firstChild.nodeValue;source=data.firstChild.childNodes[1].firstChild.nodeValue;}catch(err){} +throw{message:"Error parsing the ArcXML request",error:error,source:source};} +var response=this.parseResponse(arcNode);return response;},write:function(request){if(!request){request=this.request;} +var root=this.createElementNS("","ARCXML");root.setAttribute("version","1.1");var reqElem=this.createElementNS("","REQUEST");if(request.get_image!=null){var getElem=this.createElementNS("","GET_IMAGE");reqElem.appendChild(getElem);var propElem=this.createElementNS("","PROPERTIES");getElem.appendChild(propElem);var props=request.get_image.properties;if(props.featurecoordsys!=null){var feat=this.createElementNS("","FEATURECOORDSYS");propElem.appendChild(feat);if(props.featurecoordsys.id===0){feat.setAttribute("string",props.featurecoordsys['string']);} +else{feat.setAttribute("id",props.featurecoordsys.id);}} +if(props.filtercoordsys!=null){var filt=this.createElementNS("","FILTERCOORDSYS");propElem.appendChild(filt);if(props.filtercoordsys.id===0){filt.setAttribute("string",props.filtercoordsys.string);} +else{filt.setAttribute("id",props.filtercoordsys.id);}} +if(props.envelope!=null){var env=this.createElementNS("","ENVELOPE");propElem.appendChild(env);env.setAttribute("minx",props.envelope.minx);env.setAttribute("miny",props.envelope.miny);env.setAttribute("maxx",props.envelope.maxx);env.setAttribute("maxy",props.envelope.maxy);} +var imagesz=this.createElementNS("","IMAGESIZE");propElem.appendChild(imagesz);imagesz.setAttribute("height",props.imagesize.height);imagesz.setAttribute("width",props.imagesize.width);if(props.imagesize.height!=props.imagesize.printheight||props.imagesize.width!=props.imagesize.printwidth){imagesz.setAttribute("printheight",props.imagesize.printheight);imagesz.setArrtibute("printwidth",props.imagesize.printwidth);} +if(props.background!=null){var backgrnd=this.createElementNS("","BACKGROUND");propElem.appendChild(backgrnd);backgrnd.setAttribute("color",props.background.color.r+","+ +props.background.color.g+","+ +props.background.color.b);if(props.background.transcolor!==null){backgrnd.setAttribute("transcolor",props.background.transcolor.r+","+ +props.background.transcolor.g+","+ +props.background.transcolor.b);}} +if(props.layerlist!=null&&props.layerlist.length>0){var layerlst=this.createElementNS("","LAYERLIST");propElem.appendChild(layerlst);for(var ld=0;ld<props.layerlist.length;ld++){var ldef=this.createElementNS("","LAYERDEF");layerlst.appendChild(ldef);ldef.setAttribute("id",props.layerlist[ld].id);ldef.setAttribute("visible",props.layerlist[ld].visible);if(typeof props.layerlist[ld].query=="object"){var query=props.layerlist[ld].query;if(query.where.length<0){continue;} +var queryElem=null;if(typeof query.spatialfilter=="boolean"&&query.spatialfilter){queryElem=this.createElementNS("","SPATIALQUERY");} +else{queryElem=this.createElementNS("","QUERY");} +queryElem.setAttribute("where",query.where);if(typeof query.accuracy=="number"&&query.accuracy>0){queryElem.setAttribute("accuracy",query.accuracy);} +if(typeof query.featurelimit=="number"&&query.featurelimit<2000){queryElem.setAttribute("featurelimit",query.featurelimit);} +if(typeof query.subfields=="string"&&query.subfields!="#ALL#"){queryElem.setAttribute("subfields",query.subfields);} +if(typeof query.joinexpression=="string"&&query.joinexpression.length>0){queryElem.setAttribute("joinexpression",query.joinexpression);} +if(typeof query.jointables=="string"&&query.jointables.length>0){queryElem.setAttribute("jointables",query.jointables);} +ldef.appendChild(queryElem);} +if(typeof props.layerlist[ld].renderer=="object"){this.addRenderer(ldef,props.layerlist[ld].renderer);}}}}else if(request.get_feature!=null){var getElem=this.createElementNS("","GET_FEATURES");getElem.setAttribute("outputmode","newxml");getElem.setAttribute("checkesc","true");if(request.get_feature.geometry){getElem.setAttribute("geometry",request.get_feature.geometry);} +else{getElem.setAttribute("geometry","false");} +if(request.get_feature.compact){getElem.setAttribute("compact",request.get_feature.compact);} +if(request.get_feature.featurelimit=="number"){getElem.setAttribute("featurelimit",request.get_feature.featurelimit);} +getElem.setAttribute("globalenvelope","true");reqElem.appendChild(getElem);if(request.get_feature.layer!=null&&request.get_feature.layer.length>0){var lyrElem=this.createElementNS("","LAYER");lyrElem.setAttribute("id",request.get_feature.layer);getElem.appendChild(lyrElem);} +var fquery=request.get_feature.query;if(fquery!=null){var qElem=null;if(fquery.isspatial){qElem=this.createElementNS("","SPATIALQUERY");}else{qElem=this.createElementNS("","QUERY");} +getElem.appendChild(qElem);if(typeof fquery.accuracy=="number"){qElem.setAttribute("accuracy",fquery.accuracy);} +if(fquery.featurecoordsys!=null){var fcsElem1=this.createElementNS("","FEATURECOORDSYS");if(fquery.featurecoordsys.id==0){fcsElem1.setAttribute("string",fquery.featurecoordsys.string);}else{fcsElem1.setAttribute("id",fquery.featurecoordsys.id);} +qElem.appendChild(fcsElem1);} +if(fquery.filtercoordsys!=null){var fcsElem2=this.createElementNS("","FILTERCOORDSYS");if(fquery.filtercoordsys.id===0){fcsElem2.setAttribute("string",fquery.filtercoordsys.string);}else{fcsElem2.setAttribute("id",fquery.filtercoordsys.id);} +qElem.appendChild(fcsElem2);} +if(fquery.buffer>0){var bufElem=this.createElementNS("","BUFFER");bufElem.setAttribute("distance",fquery.buffer);qElem.appendChild(bufElem);} +if(fquery.isspatial){var spfElem=this.createElementNS("","SPATIALFILTER");spfElem.setAttribute("relation",fquery.spatialfilter.relation);qElem.appendChild(spfElem);if(fquery.spatialfilter.envelope){var envElem=this.createElementNS("","ENVELOPE");envElem.setAttribute("minx",fquery.spatialfilter.envelope.minx);envElem.setAttribute("miny",fquery.spatialfilter.envelope.miny);envElem.setAttribute("maxx",fquery.spatialfilter.envelope.maxx);envElem.setAttribute("maxy",fquery.spatialfilter.envelope.maxy);spfElem.appendChild(envElem);}else if(typeof fquery.spatialfilter.polygon=="object"){spfElem.appendChild(this.writePolygonGeometry(fquery.spatialfilter.polygon));}} +if(fquery.where!=null&&fquery.where.length>0){qElem.setAttribute("where",fquery.where);}}} +root.appendChild(reqElem);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},addGroupRenderer:function(ldef,toprenderer){var topRelem=this.createElementNS("","GROUPRENDERER");ldef.appendChild(topRelem);for(var rind=0;rind<toprenderer.length;rind++){var renderer=toprenderer[rind];this.addRenderer(topRelem,renderer);}},addRenderer:function(topRelem,renderer){if(renderer instanceof Array){this.addGroupRenderer(topRelem,renderer);}else{var renderElem=this.createElementNS("",renderer.type.toUpperCase()+"RENDERER");topRelem.appendChild(renderElem);if(renderElem.tagName=="VALUEMAPRENDERER"){this.addValueMapRenderer(renderElem,renderer);}else if(renderElem.tagName=="VALUEMAPLABELRENDERER"){this.addValueMapLabelRenderer(renderElem,renderer);}else if(renderElem.tagName=="SIMPLELABELRENDERER"){this.addSimpleLabelRenderer(renderElem,renderer);}else if(renderElem.tagName=="SCALEDEPENDENTRENDERER"){this.addScaleDependentRenderer(renderElem,renderer);}}},addScaleDependentRenderer:function(renderElem,renderer){if(typeof renderer.lower=="string"||typeof renderer.lower=="number"){renderElem.setAttribute("lower",renderer.lower);} +if(typeof renderer.upper=="string"||typeof renderer.upper=="number"){renderElem.setAttribute("upper",renderer.upper);} +this.addRenderer(renderElem,renderer.renderer);},addValueMapLabelRenderer:function(renderElem,renderer){renderElem.setAttribute("lookupfield",renderer.lookupfield);renderElem.setAttribute("labelfield",renderer.labelfield);if(typeof renderer.exacts=="object"){for(var ext=0,extlen=renderer.exacts.length;ext<extlen;ext++){var exact=renderer.exacts[ext];var eelem=this.createElementNS("","EXACT");if(typeof exact.value=="string"){eelem.setAttribute("value",exact.value);} +if(typeof exact.label=="string"){eelem.setAttribute("label",exact.label);} +if(typeof exact.method=="string"){eelem.setAttribute("method",exact.method);} +renderElem.appendChild(eelem);if(typeof exact.symbol=="object"){var selem=null;if(exact.symbol.type=="text"){selem=this.createElementNS("","TEXTSYMBOL");} +if(selem!=null){var keys=this.fontStyleKeys;for(var i=0,len=keys.length;i<len;i++){var key=keys[i];if(exact.symbol[key]){selem.setAttribute(key,exact.symbol[key]);}} +eelem.appendChild(selem);}}}}},addValueMapRenderer:function(renderElem,renderer){renderElem.setAttribute("lookupfield",renderer.lookupfield);if(typeof renderer.ranges=="object"){for(var rng=0,rnglen=renderer.ranges.length;rng<rnglen;rng++){var range=renderer.ranges[rng];var relem=this.createElementNS("","RANGE");relem.setAttribute("lower",range.lower);relem.setAttribute("upper",range.upper);renderElem.appendChild(relem);if(typeof range.symbol=="object"){var selem=null;if(range.symbol.type=="simplepolygon"){selem=this.createElementNS("","SIMPLEPOLYGONSYMBOL");} +if(selem!=null){if(typeof range.symbol.boundarycolor=="string"){selem.setAttribute("boundarycolor",range.symbol.boundarycolor);} +if(typeof range.symbol.fillcolor=="string"){selem.setAttribute("fillcolor",range.symbol.fillcolor);} +if(typeof range.symbol.filltransparency=="number"){selem.setAttribute("filltransparency",range.symbol.filltransparency);} +relem.appendChild(selem);}}}}else if(typeof renderer.exacts=="object"){for(var ext=0,extlen=renderer.exacts.length;ext<extlen;ext++){var exact=renderer.exacts[ext];var eelem=this.createElementNS("","EXACT");if(typeof exact.value=="string"){eelem.setAttribute("value",exact.value);} +if(typeof exact.label=="string"){eelem.setAttribute("label",exact.label);} +if(typeof exact.method=="string"){eelem.setAttribute("method",exact.method);} +renderElem.appendChild(eelem);if(typeof exact.symbol=="object"){var selem=null;if(exact.symbol.type=="simplemarker"){selem=this.createElementNS("","SIMPLEMARKERSYMBOL");} +if(selem!=null){if(typeof exact.symbol.antialiasing=="string"){selem.setAttribute("antialiasing",exact.symbol.antialiasing);} +if(typeof exact.symbol.color=="string"){selem.setAttribute("color",exact.symbol.color);} +if(typeof exact.symbol.outline=="string"){selem.setAttribute("outline",exact.symbol.outline);} +if(typeof exact.symbol.overlap=="string"){selem.setAttribute("overlap",exact.symbol.overlap);} +if(typeof exact.symbol.shadow=="string"){selem.setAttribute("shadow",exact.symbol.shadow);} +if(typeof exact.symbol.transparency=="number"){selem.setAttribute("transparency",exact.symbol.transparency);} +if(typeof exact.symbol.usecentroid=="string"){selem.setAttribute("usecentroid",exact.symbol.usecentroid);} +if(typeof exact.symbol.width=="number"){selem.setAttribute("width",exact.symbol.width);} +eelem.appendChild(selem);}}}}},addSimpleLabelRenderer:function(renderElem,renderer){renderElem.setAttribute("field",renderer.field);var keys=['featureweight','howmanylabels','labelbufferratio','labelpriorities','labelweight','linelabelposition','rotationalangles'];for(var i=0,len=keys.length;i<len;i++){var key=keys[i];if(renderer[key]){renderElem.setAttribute(key,renderer[key]);}} +if(renderer.symbol.type=="text"){var symbol=renderer.symbol;var selem=this.createElementNS("","TEXTSYMBOL");renderElem.appendChild(selem);var keys=this.fontStyleKeys;for(var i=0,len=keys.length;i<len;i++){var key=keys[i];if(symbol[key]){selem.setAttribute(key,renderer[key]);}}}},writePolygonGeometry:function(polygon){if(!(polygon instanceof OpenLayers.Geometry.Polygon)){throw{message:'Cannot write polygon geometry to ArcXML with an '+ +polygon.CLASS_NAME+' object.',geometry:polygon};} +var polyElem=this.createElementNS("","POLYGON");for(var ln=0,lnlen=polygon.components.length;ln<lnlen;ln++){var ring=polygon.components[ln];var ringElem=this.createElementNS("","RING");for(var rn=0,rnlen=ring.components.length;rn<rnlen;rn++){var point=ring.components[rn];var pointElem=this.createElementNS("","POINT");pointElem.setAttribute("x",point.x);pointElem.setAttribute("y",point.y);ringElem.appendChild(pointElem);} +polyElem.appendChild(ringElem);} +return polyElem;},parseResponse:function(data){if(typeof data=="string"){var newData=new OpenLayers.Format.XML();data=newData.read(data);} +var response=new OpenLayers.Format.ArcXML.Response();var errorNode=data.getElementsByTagName("ERROR");if(errorNode!=null&&errorNode.length>0){response.error=this.getChildValue(errorNode,"Unknown error.");}else{var responseNode=data.getElementsByTagName("RESPONSE");if(responseNode==null||responseNode.length==0){response.error="No RESPONSE tag found in ArcXML response.";return response;} +var rtype=responseNode[0].firstChild.nodeName;if(rtype=="#text"){rtype=responseNode[0].firstChild.nextSibling.nodeName;} +if(rtype=="IMAGE"){var envelopeNode=data.getElementsByTagName("ENVELOPE");var outputNode=data.getElementsByTagName("OUTPUT");if(envelopeNode==null||envelopeNode.length==0){response.error="No ENVELOPE tag found in ArcXML response.";}else if(outputNode==null||outputNode.length==0){response.error="No OUTPUT tag found in ArcXML response.";}else{var envAttr=this.parseAttributes(envelopeNode[0]);var outputAttr=this.parseAttributes(outputNode[0]);if(typeof outputAttr.type=="string"){response.image={envelope:envAttr,output:{type:outputAttr.type,data:this.getChildValue(outputNode[0])}};}else{response.image={envelope:envAttr,output:outputAttr};}}}else if(rtype=="FEATURES"){var features=responseNode[0].getElementsByTagName("FEATURES");var featureCount=features[0].getElementsByTagName("FEATURECOUNT");response.features.featurecount=featureCount[0].getAttribute("count");if(response.features.featurecount>0){var envelope=features[0].getElementsByTagName("ENVELOPE");response.features.envelope=this.parseAttributes(envelope[0],typeof(0));var featureList=features[0].getElementsByTagName("FEATURE");for(var fn=0;fn<featureList.length;fn++){var feature=new OpenLayers.Feature.Vector();var fields=featureList[fn].getElementsByTagName("FIELD");for(var fdn=0;fdn<fields.length;fdn++){var fieldName=fields[fdn].getAttribute("name");var fieldValue=fields[fdn].getAttribute("value");feature.attributes[fieldName]=fieldValue;} +var geom=featureList[fn].getElementsByTagName("POLYGON");if(geom.length>0){var ring=geom[0].getElementsByTagName("RING");var polys=[];for(var rn=0;rn<ring.length;rn++){var linearRings=[];linearRings.push(this.parsePointGeometry(ring[rn]));var holes=ring[rn].getElementsByTagName("HOLE");for(var hn=0;hn<holes.length;hn++){linearRings.push(this.parsePointGeometry(holes[hn]));} +holes=null;polys.push(new OpenLayers.Geometry.Polygon(linearRings));linearRings=null;} +ring=null;if(polys.length==1){feature.geometry=polys[0];}else +{feature.geometry=new OpenLayers.Geometry.MultiPolygon(polys);}} +response.features.feature.push(feature);}}}else{response.error="Unidentified response type.";}} +return response;},parseAttributes:function(node,type){var attributes={};for(var attr=0;attr<node.attributes.length;attr++){if(type=="number"){attributes[node.attributes[attr].nodeName]=parseFloat(node.attributes[attr].nodeValue);}else{attributes[node.attributes[attr].nodeName]=node.attributes[attr].nodeValue;}} +return attributes;},parsePointGeometry:function(node){var ringPoints=[];var coords=node.getElementsByTagName("COORDS");if(coords.length>0){var coordArr=this.getChildValue(coords[0]);coordArr=coordArr.split(/;/);for(var cn=0;cn<coordArr.length;cn++){var coordItems=coordArr[cn].split(/ /);ringPoints.push(new OpenLayers.Geometry.Point(parseFloat(coordItems[0]),parseFloat(coordItems[1])));} +coords=null;}else{var point=node.getElementsByTagName("POINT");if(point.length>0){for(var pn=0;pn<point.length;pn++){ringPoints.push(new OpenLayers.Geometry.Point(parseFloat(point[pn].getAttribute("x")),parseFloat(point[pn].getAttribute("y"))));}} +point=null;} +return new OpenLayers.Geometry.LinearRing(ringPoints);},CLASS_NAME:"OpenLayers.Format.ArcXML"});OpenLayers.Format.ArcXML.Request=OpenLayers.Class({initialize:function(params){var defaults={get_image:{properties:{background:null,draw:true,envelope:{minx:0,miny:0,maxx:0,maxy:0},featurecoordsys:{id:0,string:"",datumtransformid:0,datumtransformstring:""},filtercoordsys:{id:0,string:"",datumtransformid:0,datumtransformstring:""},imagesize:{height:0,width:0,dpi:96,printheight:0,printwidth:0,scalesymbols:false},layerlist:[],output:{baseurl:"",legendbaseurl:"",legendname:"",legendpath:"",legendurl:"",name:"",path:"",type:"jpg",url:""}}},get_feature:{layer:"",query:{isspatial:false,featurecoordsys:{id:0,string:"",datumtransformid:0,datumtransformstring:""},filtercoordsys:{id:0,string:"",datumtransformid:0,datumtransformstring:""},buffer:0,where:"",spatialfilter:{relation:"envelope_intersection",envelope:null}}},environment:{separators:{cs:" ",ts:";"}},layer:[],workspaces:[]};return OpenLayers.Util.extend(this,defaults);},CLASS_NAME:"OpenLayers.Format.ArcXML.Request"});OpenLayers.Format.ArcXML.Response=OpenLayers.Class({initialize:function(params){var defaults={image:{envelope:null,output:''},features:{featurecount:0,envelope:null,feature:[]},error:''};return OpenLayers.Util.extend(this,defaults);},CLASS_NAME:"OpenLayers.Format.ArcXML.Response"});OpenLayers.Format.GML=OpenLayers.Class(OpenLayers.Format.XML,{featureNS:"http://mapserver.gis.umn.edu/mapserver",featurePrefix:"feature",featureName:"featureMember",layerName:"features",geometryName:"geometry",collectionName:"FeatureCollection",gmlns:"http://www.opengis.net/gml",extractAttributes:true,xy:true,initialize:function(options){this.regExes={trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)};OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +var featureNodes=this.getElementsByTagNameNS(data.documentElement,this.gmlns,this.featureName);var features=[];for(var i=0;i<featureNodes.length;i++){var feature=this.parseFeature(featureNodes[i]);if(feature){features.push(feature);}} +return features;},parseFeature:function(node){var order=["MultiPolygon","Polygon","MultiLineString","LineString","MultiPoint","Point","Envelope"];var type,nodeList,geometry,parser;for(var i=0;i<order.length;++i){type=order[i];nodeList=this.getElementsByTagNameNS(node,this.gmlns,type);if(nodeList.length>0){parser=this.parseGeometry[type.toLowerCase()];if(parser){geometry=parser.apply(this,[nodeList[0]]);if(this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection);}}else{OpenLayers.Console.error(OpenLayers.i18n("unsupportedGeometryType",{'geomType':type}));} +break;}} +var bounds;var boxNodes=this.getElementsByTagNameNS(node,this.gmlns,"Box");for(i=0;i<boxNodes.length;++i){var boxNode=boxNodes[i];var box=this.parseGeometry["box"].apply(this,[boxNode]);var parentNode=boxNode.parentNode;var parentName=parentNode.localName||parentNode.nodeName.split(":").pop();if(parentName==="boundedBy"){bounds=box;}else{geometry=box.toGeometry();}} +var attributes;if(this.extractAttributes){attributes=this.parseAttributes(node);} +var feature=new OpenLayers.Feature.Vector(geometry,attributes);feature.bounds=bounds;feature.gml={featureType:node.firstChild.nodeName.split(":")[1],featureNS:node.firstChild.namespaceURI,featureNSPrefix:node.firstChild.prefix};var childNode=node.firstChild;var fid;while(childNode){if(childNode.nodeType==1){fid=childNode.getAttribute("fid")||childNode.getAttribute("id");if(fid){break;}} +childNode=childNode.nextSibling;} +feature.fid=fid;return feature;},parseGeometry:{point:function(node){var nodeList,coordString;var coords=[];var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"pos");if(nodeList.length>0){coordString=nodeList[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace);} +if(coords.length==0){nodeList=this.getElementsByTagNameNS(node,this.gmlns,"coordinates");if(nodeList.length>0){coordString=nodeList[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.removeSpace,"");coords=coordString.split(",");}} +if(coords.length==0){nodeList=this.getElementsByTagNameNS(node,this.gmlns,"coord");if(nodeList.length>0){var xList=this.getElementsByTagNameNS(nodeList[0],this.gmlns,"X");var yList=this.getElementsByTagNameNS(nodeList[0],this.gmlns,"Y");if(xList.length>0&&yList.length>0){coords=[xList[0].firstChild.nodeValue,yList[0].firstChild.nodeValue];}}} +if(coords.length==2){coords[2]=null;} +if(this.xy){return new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);} +else{return new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}},multipoint:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"Point");var components=[];if(nodeList.length>0){var point;for(var i=0;i<nodeList.length;++i){point=this.parseGeometry.point.apply(this,[nodeList[i]]);if(point){components.push(point);}}} +return new OpenLayers.Geometry.MultiPoint(components);},linestring:function(node,ring){var nodeList,coordString;var coords=[];var points=[];nodeList=this.getElementsByTagNameNS(node,this.gmlns,"posList");if(nodeList.length>0){coordString=this.getChildValue(nodeList[0]);coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace);var dim=parseInt(nodeList[0].getAttribute("dimension"));var j,x,y,z;for(var i=0;i<coords.length/dim;++i){j=i*dim;x=coords[j];y=coords[j+1];z=(dim==2)?null:coords[j+2];if(this.xy){points.push(new OpenLayers.Geometry.Point(x,y,z));}else{points.push(new OpenLayers.Geometry.Point(y,x,z));}}} +if(coords.length==0){nodeList=this.getElementsByTagNameNS(node,this.gmlns,"coordinates");if(nodeList.length>0){coordString=this.getChildValue(nodeList[0]);coordString=coordString.replace(this.regExes.trimSpace,"");coordString=coordString.replace(this.regExes.trimComma,",");var pointList=coordString.split(this.regExes.splitSpace);for(var i=0;i<pointList.length;++i){coords=pointList[i].split(",");if(coords.length==2){coords[2]=null;} +if(this.xy){points.push(new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]));}else{points.push(new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]));}}}} +var line=null;if(points.length!=0){if(ring){line=new OpenLayers.Geometry.LinearRing(points);}else{line=new OpenLayers.Geometry.LineString(points);}} +return line;},multilinestring:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"LineString");var components=[];if(nodeList.length>0){var line;for(var i=0;i<nodeList.length;++i){line=this.parseGeometry.linestring.apply(this,[nodeList[i]]);if(line){components.push(line);}}} +return new OpenLayers.Geometry.MultiLineString(components);},polygon:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"LinearRing");var components=[];if(nodeList.length>0){var ring;for(var i=0;i<nodeList.length;++i){ring=this.parseGeometry.linestring.apply(this,[nodeList[i],true]);if(ring){components.push(ring);}}} +return new OpenLayers.Geometry.Polygon(components);},multipolygon:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"Polygon");var components=[];if(nodeList.length>0){var polygon;for(var i=0;i<nodeList.length;++i){polygon=this.parseGeometry.polygon.apply(this,[nodeList[i]]);if(polygon){components.push(polygon);}}} +return new OpenLayers.Geometry.MultiPolygon(components);},envelope:function(node){var components=[];var coordString;var envelope;var lpoint=this.getElementsByTagNameNS(node,this.gmlns,"lowerCorner");if(lpoint.length>0){var coords=[];if(lpoint.length>0){coordString=lpoint[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace);} +if(coords.length==2){coords[2]=null;} +if(this.xy){var lowerPoint=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{var lowerPoint=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}} +var upoint=this.getElementsByTagNameNS(node,this.gmlns,"upperCorner");if(upoint.length>0){var coords=[];if(upoint.length>0){coordString=upoint[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace);} +if(coords.length==2){coords[2]=null;} +if(this.xy){var upperPoint=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{var upperPoint=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}} +if(lowerPoint&&upperPoint){components.push(new OpenLayers.Geometry.Point(lowerPoint.x,lowerPoint.y));components.push(new OpenLayers.Geometry.Point(upperPoint.x,lowerPoint.y));components.push(new OpenLayers.Geometry.Point(upperPoint.x,upperPoint.y));components.push(new OpenLayers.Geometry.Point(lowerPoint.x,upperPoint.y));components.push(new OpenLayers.Geometry.Point(lowerPoint.x,lowerPoint.y));var ring=new OpenLayers.Geometry.LinearRing(components);envelope=new OpenLayers.Geometry.Polygon([ring]);} +return envelope;},box:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"coordinates");var coordString;var coords,beginPoint=null,endPoint=null;if(nodeList.length>0){coordString=nodeList[0].firstChild.nodeValue;coords=coordString.split(" ");if(coords.length==2){beginPoint=coords[0].split(",");endPoint=coords[1].split(",");}} +if(beginPoint!==null&&endPoint!==null){return new OpenLayers.Bounds(parseFloat(beginPoint[0]),parseFloat(beginPoint[1]),parseFloat(endPoint[0]),parseFloat(endPoint[1]));}}},parseAttributes:function(node){var attributes={};var childNode=node.firstChild;var children,i,child,grandchildren,grandchild,name,value;while(childNode){if(childNode.nodeType==1){children=childNode.childNodes;for(i=0;i<children.length;++i){child=children[i];if(child.nodeType==1){grandchildren=child.childNodes;if(grandchildren.length==1){grandchild=grandchildren[0];if(grandchild.nodeType==3||grandchild.nodeType==4){name=(child.prefix)?child.nodeName.split(":")[1]:child.nodeName;value=grandchild.nodeValue.replace(this.regExes.trimSpace,"");attributes[name]=value;}}else{attributes[child.nodeName.split(":").pop()]=null;}}} +break;} +childNode=childNode.nextSibling;} +return attributes;},write:function(features){if(!(features instanceof Array)){features=[features];} +var gml=this.createElementNS("http://www.opengis.net/wfs","wfs:"+this.collectionName);for(var i=0;i<features.length;i++){gml.appendChild(this.createFeatureXML(features[i]));} +return OpenLayers.Format.XML.prototype.write.apply(this,[gml]);},createFeatureXML:function(feature){var geometry=feature.geometry;var geometryNode=this.buildGeometryNode(geometry);var geomContainer=this.createElementNS(this.featureNS,this.featurePrefix+":"+ +this.geometryName);geomContainer.appendChild(geometryNode);var featureNode=this.createElementNS(this.gmlns,"gml:"+this.featureName);var featureContainer=this.createElementNS(this.featureNS,this.featurePrefix+":"+ +this.layerName);var fid=feature.fid||feature.id;featureContainer.setAttribute("fid",fid);featureContainer.appendChild(geomContainer);for(var attr in feature.attributes){var attrText=this.createTextNode(feature.attributes[attr]);var nodename=attr.substring(attr.lastIndexOf(":")+1);var attrContainer=this.createElementNS(this.featureNS,this.featurePrefix+":"+ +nodename);attrContainer.appendChild(attrText);featureContainer.appendChild(attrContainer);} +featureNode.appendChild(featureContainer);return featureNode;},buildGeometryNode:function(geometry){if(this.externalProjection&&this.internalProjection){geometry=geometry.clone();geometry.transform(this.internalProjection,this.externalProjection);} +var className=geometry.CLASS_NAME;var type=className.substring(className.lastIndexOf(".")+1);var builder=this.buildGeometry[type.toLowerCase()];return builder.apply(this,[geometry]);},buildGeometry:{point:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:Point");gml.appendChild(this.buildCoordinatesNode(geometry));return gml;},multipoint:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:MultiPoint");var points=geometry.components;var pointMember,pointGeom;for(var i=0;i<points.length;i++){pointMember=this.createElementNS(this.gmlns,"gml:pointMember");pointGeom=this.buildGeometry.point.apply(this,[points[i]]);pointMember.appendChild(pointGeom);gml.appendChild(pointMember);} +return gml;},linestring:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:LineString");gml.appendChild(this.buildCoordinatesNode(geometry));return gml;},multilinestring:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:MultiLineString");var lines=geometry.components;var lineMember,lineGeom;for(var i=0;i<lines.length;++i){lineMember=this.createElementNS(this.gmlns,"gml:lineStringMember");lineGeom=this.buildGeometry.linestring.apply(this,[lines[i]]);lineMember.appendChild(lineGeom);gml.appendChild(lineMember);} +return gml;},linearring:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:LinearRing");gml.appendChild(this.buildCoordinatesNode(geometry));return gml;},polygon:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:Polygon");var rings=geometry.components;var ringMember,ringGeom,type;for(var i=0;i<rings.length;++i){type=(i==0)?"outerBoundaryIs":"innerBoundaryIs";ringMember=this.createElementNS(this.gmlns,"gml:"+type);ringGeom=this.buildGeometry.linearring.apply(this,[rings[i]]);ringMember.appendChild(ringGeom);gml.appendChild(ringMember);} +return gml;},multipolygon:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:MultiPolygon");var polys=geometry.components;var polyMember,polyGeom;for(var i=0;i<polys.length;++i){polyMember=this.createElementNS(this.gmlns,"gml:polygonMember");polyGeom=this.buildGeometry.polygon.apply(this,[polys[i]]);polyMember.appendChild(polyGeom);gml.appendChild(polyMember);} +return gml;},bounds:function(bounds){var gml=this.createElementNS(this.gmlns,"gml:Box");gml.appendChild(this.buildCoordinatesNode(bounds));return gml;}},buildCoordinatesNode:function(geometry){var coordinatesNode=this.createElementNS(this.gmlns,"gml:coordinates");coordinatesNode.setAttribute("decimal",".");coordinatesNode.setAttribute("cs",",");coordinatesNode.setAttribute("ts"," ");var parts=[];if(geometry instanceof OpenLayers.Bounds){parts.push(geometry.left+","+geometry.bottom);parts.push(geometry.right+","+geometry.top);}else{var points=(geometry.components)?geometry.components:[geometry];for(var i=0;i<points.length;i++){parts.push(points[i].x+","+points[i].y);}} +var txtNode=this.createTextNode(parts.join(" "));coordinatesNode.appendChild(txtNode);return coordinatesNode;},CLASS_NAME:"OpenLayers.Format.GML"});OpenLayers.Format.GeoJSON=OpenLayers.Class(OpenLayers.Format.JSON,{ignoreExtraDims:false,initialize:function(options){OpenLayers.Format.JSON.prototype.initialize.apply(this,[options]);},read:function(json,type,filter){type=(type)?type:"FeatureCollection";var results=null;var obj=null;if(typeof json=="string"){obj=OpenLayers.Format.JSON.prototype.read.apply(this,[json,filter]);}else{obj=json;} +if(!obj){OpenLayers.Console.error("Bad JSON: "+json);}else if(typeof(obj.type)!="string"){OpenLayers.Console.error("Bad GeoJSON - no type: "+json);}else if(this.isValidType(obj,type)){switch(type){case"Geometry":try{results=this.parseGeometry(obj);}catch(err){OpenLayers.Console.error(err);} +break;case"Feature":try{results=this.parseFeature(obj);results.type="Feature";}catch(err){OpenLayers.Console.error(err);} +break;case"FeatureCollection":results=[];switch(obj.type){case"Feature":try{results.push(this.parseFeature(obj));}catch(err){results=null;OpenLayers.Console.error(err);} +break;case"FeatureCollection":for(var i=0,len=obj.features.length;i<len;++i){try{results.push(this.parseFeature(obj.features[i]));}catch(err){results=null;OpenLayers.Console.error(err);}} +break;default:try{var geom=this.parseGeometry(obj);results.push(new OpenLayers.Feature.Vector(geom));}catch(err){results=null;OpenLayers.Console.error(err);}} +break;}} +return results;},isValidType:function(obj,type){var valid=false;switch(type){case"Geometry":if(OpenLayers.Util.indexOf(["Point","MultiPoint","LineString","MultiLineString","Polygon","MultiPolygon","Box","GeometryCollection"],obj.type)==-1){OpenLayers.Console.error("Unsupported geometry type: "+ +obj.type);}else{valid=true;} +break;case"FeatureCollection":valid=true;break;default:if(obj.type==type){valid=true;}else{OpenLayers.Console.error("Cannot convert types from "+ +obj.type+" to "+type);}} +return valid;},parseFeature:function(obj){var feature,geometry,attributes,bbox;attributes=(obj.properties)?obj.properties:{};bbox=(obj.geometry&&obj.geometry.bbox)||obj.bbox;try{geometry=this.parseGeometry(obj.geometry);}catch(err){throw err;} +feature=new OpenLayers.Feature.Vector(geometry,attributes);if(bbox){feature.bounds=OpenLayers.Bounds.fromArray(bbox);} +if(obj.id){feature.fid=obj.id;} +return feature;},parseGeometry:function(obj){if(obj==null){return null;} +var geometry,collection=false;if(obj.type=="GeometryCollection"){if(!(obj.geometries instanceof Array)){throw"GeometryCollection must have geometries array: "+obj;} +var numGeom=obj.geometries.length;var components=new Array(numGeom);for(var i=0;i<numGeom;++i){components[i]=this.parseGeometry.apply(this,[obj.geometries[i]]);} +geometry=new OpenLayers.Geometry.Collection(components);collection=true;}else{if(!(obj.coordinates instanceof Array)){throw"Geometry must have coordinates array: "+obj;} +if(!this.parseCoords[obj.type.toLowerCase()]){throw"Unsupported geometry type: "+obj.type;} +try{geometry=this.parseCoords[obj.type.toLowerCase()].apply(this,[obj.coordinates]);}catch(err){throw err;}} +if(this.internalProjection&&this.externalProjection&&!collection){geometry.transform(this.externalProjection,this.internalProjection);} +return geometry;},parseCoords:{"point":function(array){if(this.ignoreExtraDims==false&&array.length!=2){throw"Only 2D points are supported: "+array;} +return new OpenLayers.Geometry.Point(array[0],array[1]);},"multipoint":function(array){var points=[];var p=null;for(var i=0,len=array.length;i<len;++i){try{p=this.parseCoords["point"].apply(this,[array[i]]);}catch(err){throw err;} +points.push(p);} +return new OpenLayers.Geometry.MultiPoint(points);},"linestring":function(array){var points=[];var p=null;for(var i=0,len=array.length;i<len;++i){try{p=this.parseCoords["point"].apply(this,[array[i]]);}catch(err){throw err;} +points.push(p);} +return new OpenLayers.Geometry.LineString(points);},"multilinestring":function(array){var lines=[];var l=null;for(var i=0,len=array.length;i<len;++i){try{l=this.parseCoords["linestring"].apply(this,[array[i]]);}catch(err){throw err;} +lines.push(l);} +return new OpenLayers.Geometry.MultiLineString(lines);},"polygon":function(array){var rings=[];var r,l;for(var i=0,len=array.length;i<len;++i){try{l=this.parseCoords["linestring"].apply(this,[array[i]]);}catch(err){throw err;} +r=new OpenLayers.Geometry.LinearRing(l.components);rings.push(r);} +return new OpenLayers.Geometry.Polygon(rings);},"multipolygon":function(array){var polys=[];var p=null;for(var i=0,len=array.length;i<len;++i){try{p=this.parseCoords["polygon"].apply(this,[array[i]]);}catch(err){throw err;} +polys.push(p);} +return new OpenLayers.Geometry.MultiPolygon(polys);},"box":function(array){if(array.length!=2){throw"GeoJSON box coordinates must have 2 elements";} +return new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing([new OpenLayers.Geometry.Point(array[0][0],array[0][1]),new OpenLayers.Geometry.Point(array[1][0],array[0][1]),new OpenLayers.Geometry.Point(array[1][0],array[1][1]),new OpenLayers.Geometry.Point(array[0][0],array[1][1]),new OpenLayers.Geometry.Point(array[0][0],array[0][1])])]);}},write:function(obj,pretty){var geojson={"type":null};if(obj instanceof Array){geojson.type="FeatureCollection";var numFeatures=obj.length;geojson.features=new Array(numFeatures);for(var i=0;i<numFeatures;++i){var element=obj[i];if(!element instanceof OpenLayers.Feature.Vector){var msg="FeatureCollection only supports collections "+"of features: "+element;throw msg;} +geojson.features[i]=this.extract.feature.apply(this,[element]);}}else if(obj.CLASS_NAME.indexOf("OpenLayers.Geometry")==0){geojson=this.extract.geometry.apply(this,[obj]);}else if(obj instanceof OpenLayers.Feature.Vector){geojson=this.extract.feature.apply(this,[obj]);if(obj.layer&&obj.layer.projection){geojson.crs=this.createCRSObject(obj);}} +return OpenLayers.Format.JSON.prototype.write.apply(this,[geojson,pretty]);},createCRSObject:function(object){var proj=object.layer.projection.toString();var crs={};if(proj.match(/epsg:/i)){var code=parseInt(proj.substring(proj.indexOf(":")+1));if(code==4326){crs={"type":"OGC","properties":{"urn":"urn:ogc:def:crs:OGC:1.3:CRS84"}};}else{crs={"type":"EPSG","properties":{"code":code}};}} +return crs;},extract:{'feature':function(feature){var geom=this.extract.geometry.apply(this,[feature.geometry]);return{"type":"Feature","id":feature.fid==null?feature.id:feature.fid,"properties":feature.attributes,"geometry":geom};},'geometry':function(geometry){if(geometry==null){return null;} +if(this.internalProjection&&this.externalProjection){geometry=geometry.clone();geometry.transform(this.internalProjection,this.externalProjection);} +var geometryType=geometry.CLASS_NAME.split('.')[2];var data=this.extract[geometryType.toLowerCase()].apply(this,[geometry]);var json;if(geometryType=="Collection"){json={"type":"GeometryCollection","geometries":data};}else{json={"type":geometryType,"coordinates":data};} +return json;},'point':function(point){return[point.x,point.y];},'multipoint':function(multipoint){var array=[];for(var i=0,len=multipoint.components.length;i<len;++i){array.push(this.extract.point.apply(this,[multipoint.components[i]]));} +return array;},'linestring':function(linestring){var array=[];for(var i=0,len=linestring.components.length;i<len;++i){array.push(this.extract.point.apply(this,[linestring.components[i]]));} +return array;},'multilinestring':function(multilinestring){var array=[];for(var i=0,len=multilinestring.components.length;i<len;++i){array.push(this.extract.linestring.apply(this,[multilinestring.components[i]]));} +return array;},'polygon':function(polygon){var array=[];for(var i=0,len=polygon.components.length;i<len;++i){array.push(this.extract.linestring.apply(this,[polygon.components[i]]));} +return array;},'multipolygon':function(multipolygon){var array=[];for(var i=0,len=multipolygon.components.length;i<len;++i){array.push(this.extract.polygon.apply(this,[multipolygon.components[i]]));} +return array;},'collection':function(collection){var len=collection.components.length;var array=new Array(len);for(var i=0;i<len;++i){array[i]=this.extract.geometry.apply(this,[collection.components[i]]);} +return array;}},CLASS_NAME:"OpenLayers.Format.GeoJSON"});OpenLayers.Format.ArcXML.Features=OpenLayers.Class(OpenLayers.Format.XML,{initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){var axl=new OpenLayers.Format.ArcXML();var parsed=axl.read(data);return parsed.features.feature;}});if(!OpenLayers.Format.GML){OpenLayers.Format.GML={};} +OpenLayers.Format.GML.Base=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{gml:"http://www.opengis.net/gml",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance",wfs:"http://www.opengis.net/wfs"},defaultPrefix:"gml",schemaLocation:null,featureType:null,featureNS:null,geometryName:"geometry",extractAttributes:true,srsName:null,xy:true,geometryTypes:null,singleFeatureType:null,regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.setGeometryTypes();if(options&&options.featureNS){this.setNamespace("feature",options.featureNS);} +this.singleFeatureType=!options||(typeof options.featureType==="string");},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +if(data&&data.nodeType==9){data=data.documentElement;} +var features=[];this.readNode(data,{features:features});if(features.length==0){var elements=this.getElementsByTagNameNS(data,this.namespaces.gml,"featureMember");if(elements.length){for(var i=0,len=elements.length;i<len;++i){this.readNode(elements[i],{features:features});}}else{var elements=this.getElementsByTagNameNS(data,this.namespaces.gml,"featureMembers");if(elements.length){this.readNode(elements[0],{features:features});}}} +return features;},readers:{"gml":{"featureMember":function(node,obj){this.readChildNodes(node,obj);},"featureMembers":function(node,obj){this.readChildNodes(node,obj);},"name":function(node,obj){obj.name=this.getChildValue(node);},"boundedBy":function(node,obj){var container={};this.readChildNodes(node,container);if(container.components&&container.components.length>0){obj.bounds=container.components[0];}},"Point":function(node,container){var obj={points:[]};this.readChildNodes(node,obj);if(!container.components){container.components=[];} +container.components.push(obj.points[0]);},"coordinates":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");str=str.replace(this.regExes.trimComma,",");var pointList=str.split(this.regExes.splitSpace);var coords;var numPoints=pointList.length;var points=new Array(numPoints);for(var i=0;i<numPoints;++i){coords=pointList[i].split(",");if(this.xy){points[i]=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{points[i]=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}} +obj.points=points;},"coord":function(node,obj){var coord={};this.readChildNodes(node,coord);if(!obj.points){obj.points=[];} +obj.points.push(new OpenLayers.Geometry.Point(coord.x,coord.y,coord.z));},"X":function(node,coord){coord.x=this.getChildValue(node);},"Y":function(node,coord){coord.y=this.getChildValue(node);},"Z":function(node,coord){coord.z=this.getChildValue(node);},"MultiPoint":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.MultiPoint(obj.components)];},"pointMember":function(node,obj){this.readChildNodes(node,obj);},"LineString":function(node,container){var obj={};this.readChildNodes(node,obj);if(!container.components){container.components=[];} +container.components.push(new OpenLayers.Geometry.LineString(obj.points));},"MultiLineString":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.MultiLineString(obj.components)];},"lineStringMember":function(node,obj){this.readChildNodes(node,obj);},"Polygon":function(node,container){var obj={outer:null,inner:[]};this.readChildNodes(node,obj);obj.inner.unshift(obj.outer);if(!container.components){container.components=[];} +container.components.push(new OpenLayers.Geometry.Polygon(obj.inner));},"LinearRing":function(node,obj){var container={};this.readChildNodes(node,container);obj.components=[new OpenLayers.Geometry.LinearRing(container.points)];},"MultiPolygon":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.MultiPolygon(obj.components)];},"polygonMember":function(node,obj){this.readChildNodes(node,obj);},"GeometryCollection":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.Collection(obj.components)];},"geometryMember":function(node,obj){this.readChildNodes(node,obj);}},"feature":{"*":function(node,obj){var name;var local=node.localName||node.nodeName.split(":").pop();if(obj.features){if(!this.singleFeatureType&&(OpenLayers.Util.indexOf(this.featureType,local)!==-1)){name="_typeName";}else if(local===this.featureType){name="_typeName";}}else{if(node.childNodes.length==0||(node.childNodes.length==1&&node.firstChild.nodeType==3)){if(this.extractAttributes){name="_attribute";}}else{name="_geometry";}} +if(name){this.readers.feature[name].apply(this,[node,obj]);}},"_typeName":function(node,obj){var container={components:[],attributes:{}};this.readChildNodes(node,container);if(container.name){container.attributes.name=container.name;} +var feature=new OpenLayers.Feature.Vector(container.components[0],container.attributes);if(!this.singleFeatureType){feature.type=node.nodeName.split(":").pop();feature.namespace=node.namespaceURI;} +var fid=node.getAttribute("fid")||this.getAttributeNS(node,this.namespaces["gml"],"id");if(fid){feature.fid=fid;} +if(this.internalProjection&&this.externalProjection&&feature.geometry){feature.geometry.transform(this.externalProjection,this.internalProjection);} +if(container.bounds){feature.bounds=container.bounds;} +obj.features.push(feature);},"_geometry":function(node,obj){this.readChildNodes(node,obj);},"_attribute":function(node,obj){var local=node.localName||node.nodeName.split(":").pop();var value=this.getChildValue(node);obj.attributes[local]=value;}},"wfs":{"FeatureCollection":function(node,obj){this.readChildNodes(node,obj);}}},write:function(features){var name;if(features instanceof Array){name="featureMembers";}else{name="featureMember";} +var root=this.writeNode("gml:"+name,features);this.setAttributeNS(root,this.namespaces["xsi"],"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},writers:{"gml":{"featureMember":function(feature){var node=this.createElementNSPlus("gml:featureMember");this.writeNode("feature:_typeName",feature,node);return node;},"MultiPoint":function(geometry){var node=this.createElementNSPlus("gml:MultiPoint");for(var i=0;i<geometry.components.length;++i){this.writeNode("pointMember",geometry.components[i],node);} +return node;},"pointMember":function(geometry){var node=this.createElementNSPlus("gml:pointMember");this.writeNode("Point",geometry,node);return node;},"MultiLineString":function(geometry){var node=this.createElementNSPlus("gml:MultiLineString");for(var i=0;i<geometry.components.length;++i){this.writeNode("lineStringMember",geometry.components[i],node);} +return node;},"lineStringMember":function(geometry){var node=this.createElementNSPlus("gml:lineStringMember");this.writeNode("LineString",geometry,node);return node;},"MultiPolygon":function(geometry){var node=this.createElementNSPlus("gml:MultiPolygon");for(var i=0;i<geometry.components.length;++i){this.writeNode("polygonMember",geometry.components[i],node);} +return node;},"polygonMember":function(geometry){var node=this.createElementNSPlus("gml:polygonMember");this.writeNode("Polygon",geometry,node);return node;},"GeometryCollection":function(geometry){var node=this.createElementNSPlus("gml:GeometryCollection");for(var i=0,len=geometry.components.length;i<len;++i){this.writeNode("geometryMember",geometry.components[i],node);} +return node;},"geometryMember":function(geometry){var node=this.createElementNSPlus("gml:geometryMember");var child=this.writeNode("feature:_geometry",geometry);node.appendChild(child.firstChild);return node;}},"feature":{"_typeName":function(feature){var node=this.createElementNSPlus("feature:"+this.featureType,{attributes:{fid:feature.fid}});if(feature.geometry){this.writeNode("feature:_geometry",feature.geometry,node);} +for(var name in feature.attributes){var value=feature.attributes[name];if(value!=null){this.writeNode("feature:_attribute",{name:name,value:value},node);}} +return node;},"_geometry":function(geometry){if(this.externalProjection&&this.internalProjection){geometry=geometry.clone().transform(this.internalProjection,this.externalProjection);} +var node=this.createElementNSPlus("feature:"+this.geometryName);var type=this.geometryTypes[geometry.CLASS_NAME];var child=this.writeNode("gml:"+type,geometry,node);if(this.srsName){child.setAttribute("srsName",this.srsName);} +return node;},"_attribute":function(obj){return this.createElementNSPlus("feature:"+obj.name,{value:obj.value});}},"wfs":{"FeatureCollection":function(features){var node=this.createElementNSPlus("wfs:FeatureCollection");for(var i=0,len=features.length;i<len;++i){this.writeNode("gml:featureMember",features[i],node);} +return node;}}},setGeometryTypes:function(){this.geometryTypes={"OpenLayers.Geometry.Point":"Point","OpenLayers.Geometry.MultiPoint":"MultiPoint","OpenLayers.Geometry.LineString":"LineString","OpenLayers.Geometry.MultiLineString":"MultiLineString","OpenLayers.Geometry.Polygon":"Polygon","OpenLayers.Geometry.MultiPolygon":"MultiPolygon","OpenLayers.Geometry.Collection":"GeometryCollection"};},CLASS_NAME:"OpenLayers.Format.GML.Base"});OpenLayers.Format.WFS=OpenLayers.Class(OpenLayers.Format.GML,{layer:null,wfsns:"http://www.opengis.net/wfs",ogcns:"http://www.opengis.net/ogc",initialize:function(options,layer){OpenLayers.Format.GML.prototype.initialize.apply(this,[options]);this.layer=layer;if(this.layer.featureNS){this.featureNS=this.layer.featureNS;} +if(this.layer.options.geometry_column){this.geometryName=this.layer.options.geometry_column;} +if(this.layer.options.typename){this.featureName=this.layer.options.typename;}},write:function(features){var transaction=this.createElementNS(this.wfsns,'wfs:Transaction');transaction.setAttribute("version","1.0.0");transaction.setAttribute("service","WFS");for(var i=0;i<features.length;i++){switch(features[i].state){case OpenLayers.State.INSERT:transaction.appendChild(this.insert(features[i]));break;case OpenLayers.State.UPDATE:transaction.appendChild(this.update(features[i]));break;case OpenLayers.State.DELETE:transaction.appendChild(this.remove(features[i]));break;}} +return OpenLayers.Format.XML.prototype.write.apply(this,[transaction]);},createFeatureXML:function(feature){var geometryNode=this.buildGeometryNode(feature.geometry);var geomContainer=this.createElementNS(this.featureNS,"feature:"+this.geometryName);geomContainer.appendChild(geometryNode);var featureContainer=this.createElementNS(this.featureNS,"feature:"+this.featureName);featureContainer.appendChild(geomContainer);for(var attr in feature.attributes){var attrText=this.createTextNode(feature.attributes[attr]);var nodename=attr;if(attr.search(":")!=-1){nodename=attr.split(":")[1];} +var attrContainer=this.createElementNS(this.featureNS,"feature:"+nodename);attrContainer.appendChild(attrText);featureContainer.appendChild(attrContainer);} +return featureContainer;},insert:function(feature){var insertNode=this.createElementNS(this.wfsns,'wfs:Insert');insertNode.appendChild(this.createFeatureXML(feature));return insertNode;},update:function(feature){if(!feature.fid){OpenLayers.Console.userError(OpenLayers.i18n("noFID"));} +var updateNode=this.createElementNS(this.wfsns,'wfs:Update');updateNode.setAttribute("typeName",this.featurePrefix+':'+this.featureName);updateNode.setAttribute("xmlns:"+this.featurePrefix,this.featureNS);var propertyNode=this.createElementNS(this.wfsns,'wfs:Property');var nameNode=this.createElementNS(this.wfsns,'wfs:Name');var txtNode=this.createTextNode(this.geometryName);nameNode.appendChild(txtNode);propertyNode.appendChild(nameNode);var valueNode=this.createElementNS(this.wfsns,'wfs:Value');var geometryNode=this.buildGeometryNode(feature.geometry);if(feature.layer){geometryNode.setAttribute("srsName",feature.layer.projection.getCode());} +valueNode.appendChild(geometryNode);propertyNode.appendChild(valueNode);updateNode.appendChild(propertyNode);for(var propName in feature.attributes){propertyNode=this.createElementNS(this.wfsns,'wfs:Property');nameNode=this.createElementNS(this.wfsns,'wfs:Name');nameNode.appendChild(this.createTextNode(propName));propertyNode.appendChild(nameNode);valueNode=this.createElementNS(this.wfsns,'wfs:Value');valueNode.appendChild(this.createTextNode(feature.attributes[propName]));propertyNode.appendChild(valueNode);updateNode.appendChild(propertyNode);} +var filterNode=this.createElementNS(this.ogcns,'ogc:Filter');var filterIdNode=this.createElementNS(this.ogcns,'ogc:FeatureId');filterIdNode.setAttribute("fid",feature.fid);filterNode.appendChild(filterIdNode);updateNode.appendChild(filterNode);return updateNode;},remove:function(feature){if(!feature.fid){OpenLayers.Console.userError(OpenLayers.i18n("noFID"));return false;} +var deleteNode=this.createElementNS(this.wfsns,'wfs:Delete');deleteNode.setAttribute("typeName",this.featurePrefix+':'+this.featureName);deleteNode.setAttribute("xmlns:"+this.featurePrefix,this.featureNS);var filterNode=this.createElementNS(this.ogcns,'ogc:Filter');var filterIdNode=this.createElementNS(this.ogcns,'ogc:FeatureId');filterIdNode.setAttribute("fid",feature.fid);filterNode.appendChild(filterIdNode);deleteNode.appendChild(filterNode);return deleteNode;},destroy:function(){this.layer=null;},CLASS_NAME:"OpenLayers.Format.WFS"});OpenLayers.Layer.ArcIMS=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{ClientVersion:"9.2",ServiceName:''},tileSize:null,featureCoordSys:"4326",filterCoordSys:"4326",layers:null,async:true,name:"ArcIMS",isBaseLayer:true,DEFAULT_OPTIONS:{tileSize:new OpenLayers.Size(512,512),featureCoordSys:"4326",filterCoordSys:"4326",layers:null,isBaseLayer:true,async:true,name:"ArcIMS"},initialize:function(name,url,options){this.tileSize=new OpenLayers.Size(512,512);this.params=OpenLayers.Util.applyDefaults({ServiceName:options.serviceName},this.DEFAULT_PARAMS);this.options=OpenLayers.Util.applyDefaults(options,this.DEFAULT_OPTIONS);OpenLayers.Layer.Grid.prototype.initialize.apply(this,[name,url,this.params,options]);if(this.transparent){if(!this.isBaseLayer){this.isBaseLayer=false;} +if(this.format=="image/jpeg"){this.format=OpenLayers.Util.alphaHack()?"image/gif":"image/png";}} +if(this.options.layers===null){this.options.layers=[];}},destroy:function(){OpenLayers.Layer.Grid.prototype.destroy.apply(this,arguments);},getURL:function(bounds){var url="";bounds=this.adjustBounds(bounds);var axlReq=new OpenLayers.Format.ArcXML(OpenLayers.Util.extend(this.options,{requesttype:"image",envelope:bounds.toArray(),tileSize:this.tileSize}));var req=new OpenLayers.Request.POST({url:this.getFullRequestString(),data:axlReq.write(),async:false});if(req!=null){var doc=req.responseXML;if(!doc||!doc.documentElement){doc=req.responseText;} +var axlResp=new OpenLayers.Format.ArcXML();var arcxml=axlResp.read(doc);url=this.getUrlOrImage(arcxml.image.output);} +return url;},getURLasync:function(bounds,scope,prop,callback){bounds=this.adjustBounds(bounds);var axlReq=new OpenLayers.Format.ArcXML(OpenLayers.Util.extend(this.options,{requesttype:"image",envelope:bounds.toArray(),tileSize:this.tileSize}));OpenLayers.Request.POST({url:this.getFullRequestString(),async:true,data:axlReq.write(),callback:function(req){var doc=req.responseXML;if(!doc||!doc.documentElement){doc=req.responseText;} +var axlResp=new OpenLayers.Format.ArcXML();var arcxml=axlResp.read(doc);scope[prop]=this.getUrlOrImage(arcxml.image.output);callback.apply(scope);},scope:this});},getUrlOrImage:function(output){var ret="";if(output.url){ret=output.url;}else if(output.data){ret="data:image/"+output.type+";base64,"+output.data;} +return ret;},setLayerQuery:function(id,querydef){for(var lyr=0;lyr<this.options.layers.length;lyr++){if(id==this.options.layers[lyr].id){this.options.layers[lyr].query=querydef;return;}} +this.options.layers.push({id:id,visible:true,query:querydef});},getFeatureInfo:function(geometry,layer,options){var buffer=options.buffer||1;var callback=options.callback||function(){};var scope=options.scope||window;var requestOptions={};OpenLayers.Util.extend(requestOptions,this.options);requestOptions.requesttype="feature";if(geometry instanceof OpenLayers.LonLat){requestOptions.polygon=null;requestOptions.envelope=[geometry.lon-buffer,geometry.lat-buffer,geometry.lon+buffer,geometry.lat+buffer];}else if(geometry instanceof OpenLayers.Geometry.Polygon){requestOptions.envelope=null;requestOptions.polygon=geometry;} +var arcxml=new OpenLayers.Format.ArcXML(requestOptions);OpenLayers.Util.extend(arcxml.request.get_feature,options);arcxml.request.get_feature.layer=layer.id;if(typeof layer.query.accuracy=="number"){arcxml.request.get_feature.query.accuracy=layer.query.accuracy;}else{var mapCenter=this.map.getCenter();var viewPx=this.map.getViewPortPxFromLonLat(mapCenter);viewPx.x++;var mapOffCenter=this.map.getLonLatFromPixel(viewPx);arcxml.request.get_feature.query.accuracy=mapOffCenter.lon-mapCenter.lon;} +arcxml.request.get_feature.query.where=layer.query.where;arcxml.request.get_feature.query.spatialfilter.relation="area_intersection";OpenLayers.Request.POST({url:this.getFullRequestString({'CustomService':'Query'}),data:arcxml.write(),callback:function(request){var response=arcxml.parseResponse(request.responseText);if(!arcxml.iserror()){callback.call(scope,response.features);}else{callback.call(scope,null);}}});},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.ArcIMS(this.name,this.url,this.getOptions());} +obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},CLASS_NAME:"OpenLayers.Layer.ArcIMS"});OpenLayers.Format.GML.v2=OpenLayers.Class(OpenLayers.Format.GML.Base,{schemaLocation:"http://www.opengis.net/gml http://schemas.opengis.net/gml/2.1.2/feature.xsd",initialize:function(options){OpenLayers.Format.GML.Base.prototype.initialize.apply(this,[options]);},readers:{"gml":OpenLayers.Util.applyDefaults({"outerBoundaryIs":function(node,container){var obj={};this.readChildNodes(node,obj);container.outer=obj.components[0];},"innerBoundaryIs":function(node,container){var obj={};this.readChildNodes(node,obj);container.inner.push(obj.components[0]);},"Box":function(node,container){var obj={};this.readChildNodes(node,obj);if(!container.components){container.components=[];} +var min=obj.points[0];var max=obj.points[1];container.components.push(new OpenLayers.Bounds(min.x,min.y,max.x,max.y));}},OpenLayers.Format.GML.Base.prototype.readers["gml"]),"feature":OpenLayers.Format.GML.Base.prototype.readers["feature"],"wfs":OpenLayers.Format.GML.Base.prototype.readers["wfs"]},write:function(features){var name;if(features instanceof Array){name="wfs:FeatureCollection";}else{name="gml:featureMember";} +var root=this.writeNode(name,features);this.setAttributeNS(root,this.namespaces["xsi"],"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},writers:{"gml":OpenLayers.Util.applyDefaults({"Point":function(geometry){var node=this.createElementNSPlus("gml:Point");this.writeNode("coordinates",[geometry],node);return node;},"coordinates":function(points){var numPoints=points.length;var parts=new Array(numPoints);var point;for(var i=0;i<numPoints;++i){point=points[i];if(this.xy){parts[i]=point.x+","+point.y;}else{parts[i]=point.y+","+point.x;} +if(point.z!=undefined){parts[i]+=","+point.z;}} +return this.createElementNSPlus("gml:coordinates",{attributes:{decimal:".",cs:",",ts:" "},value:(numPoints==1)?parts[0]:parts.join(" ")});},"LineString":function(geometry){var node=this.createElementNSPlus("gml:LineString");this.writeNode("coordinates",geometry.components,node);return node;},"Polygon":function(geometry){var node=this.createElementNSPlus("gml:Polygon");this.writeNode("outerBoundaryIs",geometry.components[0],node);for(var i=1;i<geometry.components.length;++i){this.writeNode("innerBoundaryIs",geometry.components[i],node);} +return node;},"outerBoundaryIs":function(ring){var node=this.createElementNSPlus("gml:outerBoundaryIs");this.writeNode("LinearRing",ring,node);return node;},"innerBoundaryIs":function(ring){var node=this.createElementNSPlus("gml:innerBoundaryIs");this.writeNode("LinearRing",ring,node);return node;},"LinearRing":function(ring){var node=this.createElementNSPlus("gml:LinearRing");this.writeNode("coordinates",ring.components,node);return node;},"Box":function(bounds){var node=this.createElementNSPlus("gml:Box");this.writeNode("coordinates",[{x:bounds.left,y:bounds.bottom},{x:bounds.right,y:bounds.top}],node);if(this.srsName){node.setAttribute("srsName",this.srsName);} +return node;}},OpenLayers.Format.GML.Base.prototype.writers["gml"]),"feature":OpenLayers.Format.GML.Base.prototype.writers["feature"],"wfs":OpenLayers.Format.GML.Base.prototype.writers["wfs"]},CLASS_NAME:"OpenLayers.Format.GML.v2"});OpenLayers.Format.GML.v3=OpenLayers.Class(OpenLayers.Format.GML.Base,{schemaLocation:"http://www.opengis.net/gml http://schemas.opengis.net/gml/3.1.1/profiles/gmlsfProfile/1.0.0/gmlsf.xsd",curve:false,multiCurve:true,surface:false,multiSurface:true,initialize:function(options){OpenLayers.Format.GML.Base.prototype.initialize.apply(this,[options]);},readers:{"gml":OpenLayers.Util.applyDefaults({"featureMembers":function(node,obj){this.readChildNodes(node,obj);},"Curve":function(node,container){var obj={points:[]};this.readChildNodes(node,obj);if(!container.components){container.components=[];} +container.components.push(new OpenLayers.Geometry.LineString(obj.points));},"segments":function(node,obj){this.readChildNodes(node,obj);},"LineStringSegment":function(node,container){var obj={};this.readChildNodes(node,obj);if(obj.points){Array.prototype.push.apply(container.points,obj.points);}},"pos":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");var coords=str.split(this.regExes.splitSpace);var point;if(this.xy){point=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{point=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);} +obj.points=[point];},"posList":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");var coords=str.split(this.regExes.splitSpace);var dim=parseInt(node.getAttribute("dimension"))||2;var j,x,y,z;var numPoints=coords.length/dim;var points=new Array(numPoints);for(var i=0,len=coords.length;i<len;i+=dim){x=coords[i];y=coords[i+1];z=(dim==2)?undefined:coords[i+2];if(this.xy){points[i/dim]=new OpenLayers.Geometry.Point(x,y,z);}else{points[i/dim]=new OpenLayers.Geometry.Point(y,x,z);}} +obj.points=points;},"Surface":function(node,obj){this.readChildNodes(node,obj);},"patches":function(node,obj){this.readChildNodes(node,obj);},"PolygonPatch":function(node,obj){this.readers.gml.Polygon.apply(this,[node,obj]);},"exterior":function(node,container){var obj={};this.readChildNodes(node,obj);container.outer=obj.components[0];},"interior":function(node,container){var obj={};this.readChildNodes(node,obj);container.inner.push(obj.components[0]);},"MultiCurve":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);if(obj.components.length>0){container.components=[new OpenLayers.Geometry.MultiLineString(obj.components)];}},"curveMember":function(node,obj){this.readChildNodes(node,obj);},"MultiSurface":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);if(obj.components.length>0){container.components=[new OpenLayers.Geometry.MultiPolygon(obj.components)];}},"surfaceMember":function(node,obj){this.readChildNodes(node,obj);},"surfaceMembers":function(node,obj){this.readChildNodes(node,obj);},"pointMembers":function(node,obj){this.readChildNodes(node,obj);},"lineStringMembers":function(node,obj){this.readChildNodes(node,obj);},"polygonMembers":function(node,obj){this.readChildNodes(node,obj);},"geometryMembers":function(node,obj){this.readChildNodes(node,obj);},"Envelope":function(node,container){var obj={points:new Array(2)};this.readChildNodes(node,obj);if(!container.components){container.components=[];} +var min=obj.points[0];var max=obj.points[1];container.components.push(new OpenLayers.Bounds(min.x,min.y,max.x,max.y));},"lowerCorner":function(node,container){var obj={};this.readers.gml.pos.apply(this,[node,obj]);container.points[0]=obj.points[0];},"upperCorner":function(node,container){var obj={};this.readers.gml.pos.apply(this,[node,obj]);container.points[1]=obj.points[0];}},OpenLayers.Format.GML.Base.prototype.readers["gml"]),"feature":OpenLayers.Format.GML.Base.prototype.readers["feature"],"wfs":OpenLayers.Format.GML.Base.prototype.readers["wfs"]},write:function(features){var name;if(features instanceof Array){name="featureMembers";}else{name="featureMember";} +var root=this.writeNode("gml:"+name,features);this.setAttributeNS(root,this.namespaces["xsi"],"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},writers:{"gml":OpenLayers.Util.applyDefaults({"featureMembers":function(features){var node=this.createElementNSPlus("gml:featureMembers");for(var i=0,len=features.length;i<len;++i){this.writeNode("feature:_typeName",features[i],node);} +return node;},"Point":function(geometry){var node=this.createElementNSPlus("gml:Point");this.writeNode("pos",geometry,node);return node;},"pos":function(point){var pos=(this.xy)?(point.x+" "+point.y):(point.y+" "+point.x);return this.createElementNSPlus("gml:pos",{value:pos});},"LineString":function(geometry){var node=this.createElementNSPlus("gml:LineString");this.writeNode("posList",geometry.components,node);return node;},"Curve":function(geometry){var node=this.createElementNSPlus("gml:Curve");this.writeNode("segments",geometry,node);return node;},"segments":function(geometry){var node=this.createElementNSPlus("gml:segments");this.writeNode("LineStringSegment",geometry,node);return node;},"LineStringSegment":function(geometry){var node=this.createElementNSPlus("gml:LineStringSegment");this.writeNode("posList",geometry.components,node);return node;},"posList":function(points){var len=points.length;var parts=new Array(len);var point;for(var i=0;i<len;++i){point=points[i];if(this.xy){parts[i]=point.x+" "+point.y;}else{parts[i]=point.y+" "+point.x;}} +return this.createElementNSPlus("gml:posList",{value:parts.join(" ")});},"Surface":function(geometry){var node=this.createElementNSPlus("gml:Surface");this.writeNode("patches",geometry,node);return node;},"patches":function(geometry){var node=this.createElementNSPlus("gml:patches");this.writeNode("PolygonPatch",geometry,node);return node;},"PolygonPatch":function(geometry){var node=this.createElementNSPlus("gml:PolygonPatch",{attributes:{interpolation:"planar"}});this.writeNode("exterior",geometry.components[0],node);for(var i=1,len=geometry.components.length;i<len;++i){this.writeNode("interior",geometry.components[i],node);} +return node;},"Polygon":function(geometry){var node=this.createElementNSPlus("gml:Polygon");this.writeNode("exterior",geometry.components[0],node);for(var i=1,len=geometry.components.length;i<len;++i){this.writeNode("interior",geometry.components[i],node);} +return node;},"exterior":function(ring){var node=this.createElementNSPlus("gml:exterior");this.writeNode("LinearRing",ring,node);return node;},"interior":function(ring){var node=this.createElementNSPlus("gml:interior");this.writeNode("LinearRing",ring,node);return node;},"LinearRing":function(ring){var node=this.createElementNSPlus("gml:LinearRing");this.writeNode("posList",ring.components,node);return node;},"MultiCurve":function(geometry){var node=this.createElementNSPlus("gml:MultiCurve");for(var i=0,len=geometry.components.length;i<len;++i){this.writeNode("curveMember",geometry.components[i],node);} +return node;},"curveMember":function(geometry){var node=this.createElementNSPlus("gml:curveMember");if(this.curve){this.writeNode("Curve",geometry,node);}else{this.writeNode("LineString",geometry,node);} +return node;},"MultiSurface":function(geometry){var node=this.createElementNSPlus("gml:MultiSurface");for(var i=0,len=geometry.components.length;i<len;++i){this.writeNode("surfaceMember",geometry.components[i],node);} +return node;},"surfaceMember":function(polygon){var node=this.createElementNSPlus("gml:surfaceMember");if(this.surface){this.writeNode("Surface",polygon,node);}else{this.writeNode("Polygon",polygon,node);} +return node;},"Envelope":function(bounds){var node=this.createElementNSPlus("gml:Envelope");this.writeNode("lowerCorner",bounds,node);this.writeNode("upperCorner",bounds,node);if(this.srsName){node.setAttribute("srsName",this.srsName);} +return node;},"lowerCorner":function(bounds){var pos=(this.xy)?(bounds.left+" "+bounds.bottom):(bounds.bottom+" "+bounds.left);return this.createElementNSPlus("gml:lowerCorner",{value:pos});},"upperCorner":function(bounds){var pos=(this.xy)?(bounds.right+" "+bounds.top):(bounds.top+" "+bounds.right);return this.createElementNSPlus("gml:upperCorner",{value:pos});}},OpenLayers.Format.GML.Base.prototype.writers["gml"]),"feature":OpenLayers.Format.GML.Base.prototype.writers["feature"],"wfs":OpenLayers.Format.GML.Base.prototype.writers["wfs"]},setGeometryTypes:function(){this.geometryTypes={"OpenLayers.Geometry.Point":"Point","OpenLayers.Geometry.MultiPoint":"MultiPoint","OpenLayers.Geometry.LineString":(this.curve===true)?"Curve":"LineString","OpenLayers.Geometry.MultiLineString":(this.multiCurve===false)?"MultiLineString":"MultiCurve","OpenLayers.Geometry.Polygon":(this.surface===true)?"Surface":"Polygon","OpenLayers.Geometry.MultiPolygon":(this.multiSurface===false)?"MultiPolygon":"MultiSurface","OpenLayers.Geometry.Collection":"GeometryCollection"};},CLASS_NAME:"OpenLayers.Format.GML.v3"});OpenLayers.Format.Atom=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{atom:"http://www.w3.org/2005/Atom",georss:"http://www.georss.org/georss"},feedTitle:"untitled",defaultEntryTitle:"untitled",gmlParser:null,xy:false,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(doc){if(typeof doc=="string"){doc=OpenLayers.Format.XML.prototype.read.apply(this,[doc]);} +return this.parseFeatures(doc);},write:function(features){var doc;if(features instanceof Array){doc=this.createElementNSPlus("atom:feed");doc.appendChild(this.createElementNSPlus("atom:title",{value:this.feedTitle}));for(var i=0,ii=features.length;i<ii;i++){doc.appendChild(this.buildEntryNode(features[i]));}} +else{doc=this.buildEntryNode(features);} +return OpenLayers.Format.XML.prototype.write.apply(this,[doc]);},buildContentNode:function(content){var node=this.createElementNSPlus("atom:content",{attributes:{type:content.type||null}});if(content.src){node.setAttribute("src",content.src);}else{if(content.type=="text"||content.type==null){node.appendChild(this.createTextNode(content.value));}else if(content.type=="html"){if(typeof content.value!="string"){throw"HTML content must be in form of an escaped string";} +node.appendChild(this.createTextNode(content.value));}else if(content.type=="xhtml"){node.appendChild(content.value);}else if(content.type=="xhtml"||content.type.match(/(\+|\/)xml$/)){node.appendChild(content.value);} +else{node.appendChild(this.createTextNode(content.value));}} +return node;},buildEntryNode:function(feature){var attrib=feature.attributes;var atomAttrib=attrib.atom||{};var entryNode=this.createElementNSPlus("atom:entry");if(atomAttrib.authors){var authors=atomAttrib.authors instanceof Array?atomAttrib.authors:[atomAttrib.authors];for(var i=0,ii=authors.length;i<ii;i++){entryNode.appendChild(this.buildPersonConstructNode("author",authors[i]));}} +if(atomAttrib.categories){var categories=atomAttrib.categories instanceof Array?atomAttrib.categories:[atomAttrib.categories];var category;for(var i=0,ii=categories.length;i<ii;i++){category=categories[i];entryNode.appendChild(this.createElementNSPlus("atom:category",{attributes:{term:category.term,scheme:category.scheme||null,label:category.label||null}}));}} +if(atomAttrib.content){entryNode.appendChild(this.buildContentNode(atomAttrib.content));} +if(atomAttrib.contributors){var contributors=atomAttrib.contributors instanceof Array?atomAttrib.contributors:[atomAttrib.contributors];for(var i=0,ii=contributors.length;i<ii;i++){entryNode.appendChild(this.buildPersonConstructNode("contributor",contributors[i]));}} +if(feature.fid){entryNode.appendChild(this.createElementNSPlus("atom:id",{value:feature.fid}));} +if(atomAttrib.links){var links=atomAttrib.links instanceof Array?atomAttrib.links:[atomAttrib.links];var link;for(var i=0,ii=links.length;i<ii;i++){link=links[i];entryNode.appendChild(this.createElementNSPlus("atom:link",{attributes:{href:link.href,rel:link.rel||null,type:link.type||null,hreflang:link.hreflang||null,title:link.title||null,length:link.length||null}}));}} +if(atomAttrib.published){entryNode.appendChild(this.createElementNSPlus("atom:published",{value:atomAttrib.published}));} +if(atomAttrib.rights){entryNode.appendChild(this.createElementNSPlus("atom:rights",{value:atomAttrib.rights}));} +if(atomAttrib.summary||attrib.description){entryNode.appendChild(this.createElementNSPlus("atom:summary",{value:atomAttrib.summary||attrib.description}));} +entryNode.appendChild(this.createElementNSPlus("atom:title",{value:atomAttrib.title||attrib.title||this.defaultEntryTitle}));if(atomAttrib.updated){entryNode.appendChild(this.createElementNSPlus("atom:updated",{value:atomAttrib.updated}));} +if(feature.geometry){var whereNode=this.createElementNSPlus("georss:where");whereNode.appendChild(this.buildGeometryNode(feature.geometry));entryNode.appendChild(whereNode);} +return entryNode;},initGmlParser:function(){this.gmlParser=new OpenLayers.Format.GML.v3({xy:this.xy,featureNS:"http://example.com#feature",internalProjection:this.internalProjection,externalProjection:this.externalProjection});},buildGeometryNode:function(geometry){if(!this.gmlParser){this.initGmlParser();} +var node=this.gmlParser.writeNode("feature:_geometry",geometry);return node.firstChild;},buildPersonConstructNode:function(name,value){var oNames=["uri","email"];var personNode=this.createElementNSPlus("atom:"+name);personNode.appendChild(this.createElementNSPlus("atom:name",{value:value.name}));for(var i=0,ii=oNames.length;i<ii;i++){if(value[oNames[i]]){personNode.appendChild(this.createElementNSPlus("atom:"+oNames[i],{value:value[oNames[i]]}));}} +return personNode;},getFirstChildValue:function(node,nsuri,name,def){var value;var nodes=this.getElementsByTagNameNS(node,nsuri,name);if(nodes&&nodes.length>0){value=this.getChildValue(nodes[0],def);}else{value=def;} +return value;},parseFeature:function(node){var atomAttrib={};var value=null;var nodes=null;var attval=null;var atomns=this.namespaces.atom;this.parsePersonConstructs(node,"author",atomAttrib);nodes=this.getElementsByTagNameNS(node,atomns,"category");if(nodes.length>0){atomAttrib.categories=[];} +for(var i=0,ii=nodes.length;i<ii;i++){value={};value.term=nodes[i].getAttribute("term");attval=nodes[i].getAttribute("scheme");if(attval){value.scheme=attval;} +attval=nodes[i].getAttribute("label");if(attval){value.label=attval;} +atomAttrib.categories.push(value);} +nodes=this.getElementsByTagNameNS(node,atomns,"content");if(nodes.length>0){value={};attval=nodes[0].getAttribute("type");if(attval){value.type=attval;} +attval=nodes[0].getAttribute("src");if(attval){value.src=attval;}else{if(value.type=="text"||value.type=="html"||value.type==null){value.value=this.getFirstChildValue(node,atomns,"content",null);}else if(value.type=="xhtml"||value.type.match(/(\+|\/)xml$/)){value.value=this.getChildEl(nodes[0]);}else{value.value=this.getFirstChildValue(node,atomns,"content",null);} +atomAttrib.content=value;}} +this.parsePersonConstructs(node,"contributor",atomAttrib);atomAttrib.id=this.getFirstChildValue(node,atomns,"id",null);nodes=this.getElementsByTagNameNS(node,atomns,"link");if(nodes.length>0){atomAttrib.links=new Array(nodes.length);} +var oAtts=["rel","type","hreflang","title","length"];for(var i=0,ii=nodes.length;i<ii;i++){value={};value.href=nodes[i].getAttribute("href");for(var j=0,jj=oAtts.length;j<jj;j++){attval=nodes[i].getAttribute(oAtts[j]);if(attval){value[oAtts[j]]=attval;}} +atomAttrib.links[i]=value;} +value=this.getFirstChildValue(node,atomns,"published",null);if(value){atomAttrib.published=value;} +value=this.getFirstChildValue(node,atomns,"rights",null);if(value){atomAttrib.rights=value;} +value=this.getFirstChildValue(node,atomns,"summary",null);if(value){atomAttrib.summary=value;} +atomAttrib.title=this.getFirstChildValue(node,atomns,"title",null);atomAttrib.updated=this.getFirstChildValue(node,atomns,"updated",null);var featureAttrib={title:atomAttrib.title,description:atomAttrib.summary,atom:atomAttrib};var geometry=this.parseLocations(node)[0];var feature=new OpenLayers.Feature.Vector(geometry,featureAttrib);feature.fid=atomAttrib.id;return feature;},parseFeatures:function(node){var features=[];var entries=this.getElementsByTagNameNS(node,this.namespaces.atom,"entry");if(entries.length==0){entries=[node];} +for(var i=0,ii=entries.length;i<ii;i++){features.push(this.parseFeature(entries[i]));} +return features;},parseLocations:function(node){var georssns=this.namespaces.georss;var locations={components:[]};var where=this.getElementsByTagNameNS(node,georssns,"where");if(where&&where.length>0){if(!this.gmlParser){this.initGmlParser();} +for(var i=0,ii=where.length;i<ii;i++){this.gmlParser.readChildNodes(where[i],locations);}} +var components=locations.components;var point=this.getElementsByTagNameNS(node,georssns,"point");if(point&&point.length>0){for(var i=0,ii=point.length;i<ii;i++){var xy=OpenLayers.String.trim(point[i].firstChild.nodeValue).split(/\s+/);if(xy.length!=2){xy=OpenLayers.String.trim(point[i].firstChild.nodeValue).split(/\s*,\s*/);} +components.push(new OpenLayers.Geometry.Point(parseFloat(xy[1]),parseFloat(xy[0])));}} +var line=this.getElementsByTagNameNS(node,georssns,"line");if(line&&line.length>0){var coords;var p;var points;for(var i=0,ii=line.length;i<ii;i++){coords=OpenLayers.String.trim(line[i].firstChild.nodeValue).split(/\s+/);points=[];for(var j=0,jj=coords.length;j<jj;j+=2){p=new OpenLayers.Geometry.Point(parseFloat(coords[j+1]),parseFloat(coords[j]));points.push(p);} +components.push(new OpenLayers.Geometry.LineString(points));}} +var polygon=this.getElementsByTagNameNS(node,georssns,"polygon");if(polygon&&polygon.length>0){var coords;var p;var points;for(var i=0,ii=polygon.length;i<ii;i++){coords=OpenLayers.String.trim(polygon[i].firstChild.nodeValue).split(/\s+/);points=[];for(var j=0,jj=coords.length;j<jj;j+=2){p=new OpenLayers.Geometry.Point(parseFloat(coords[j+1]),parseFloat(coords[j]));points.push(p);} +components.push(new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(components)]));}} +if(this.internalProjection&&this.externalProjection){for(var i=0,ii=components.length;i<ii;i++){if(components[i]){components[i].transform(this.externalProjection,this.internalProjection);}}} +return components;},parsePersonConstructs:function(node,name,data){var persons=[];var atomns=this.namespaces.atom;var nodes=this.getElementsByTagNameNS(node,atomns,name);var oAtts=["uri","email"];for(var i=0,ii=nodes.length;i<ii;i++){var value={};value.name=this.getFirstChildValue(nodes[i],atomns,"name",null);for(var j=0,jj=oAtts.length;j<jj;j++){var attval=this.getFirstChildValue(nodes[i],atomns,oAtts[j],null);if(attval){value[oAtts[j]]=attval;}} +persons.push(value);} +if(persons.length>0){data[name+"s"]=persons;}},CLASS_NAME:"OpenLayers.Format.Atom"});OpenLayers.Format.Filter.v1_0_0=OpenLayers.Class(OpenLayers.Format.GML.v2,OpenLayers.Format.Filter.v1,{VERSION:"1.0.0",schemaLocation:"http://www.opengis.net/ogc/filter/1.0.0/filter.xsd",initialize:function(options){OpenLayers.Format.GML.v2.prototype.initialize.apply(this,[options]);},readers:{"ogc":OpenLayers.Util.applyDefaults({"PropertyIsEqualTo":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.EQUAL_TO});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsNotEqualTo":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.NOT_EQUAL_TO});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsLike":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.LIKE});this.readChildNodes(node,filter);var wildCard=node.getAttribute("wildCard");var singleChar=node.getAttribute("singleChar");var esc=node.getAttribute("escape");filter.value2regex(wildCard,singleChar,esc);obj.filters.push(filter);}},OpenLayers.Format.Filter.v1.prototype.readers["ogc"]),"gml":OpenLayers.Format.GML.v2.prototype.readers["gml"],"feature":OpenLayers.Format.GML.v2.prototype.readers["feature"]},writers:{"ogc":OpenLayers.Util.applyDefaults({"PropertyIsEqualTo":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsEqualTo");this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.value,node);return node;},"PropertyIsNotEqualTo":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsNotEqualTo");this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.value,node);return node;},"PropertyIsLike":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsLike",{attributes:{wildCard:"*",singleChar:".",escape:"!"}});this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.regex2value(),node);return node;},"BBOX":function(filter){var node=this.createElementNSPlus("ogc:BBOX");this.writeNode("PropertyName",filter,node);var box=this.writeNode("gml:Box",filter.value,node);if(filter.projection){box.setAttribute("srsName",filter.projection);} +return node;}},OpenLayers.Format.Filter.v1.prototype.writers["ogc"]),"gml":OpenLayers.Format.GML.v2.prototype.writers["gml"],"feature":OpenLayers.Format.GML.v2.prototype.writers["feature"]},writeSpatial:function(filter,name){var node=this.createElementNSPlus("ogc:"+name);this.writeNode("PropertyName",filter,node);var child;if(filter.value instanceof OpenLayers.Geometry){child=this.writeNode("feature:_geometry",filter.value).firstChild;}else{child=this.writeNode("gml:Box",filter.value);} +if(filter.projection){child.setAttribute("srsName",filter.projection);} +node.appendChild(child);return node;},CLASS_NAME:"OpenLayers.Format.Filter.v1_0_0"});OpenLayers.Format.Filter.v1_1_0=OpenLayers.Class(OpenLayers.Format.GML.v3,OpenLayers.Format.Filter.v1,{VERSION:"1.1.0",schemaLocation:"http://www.opengis.net/ogc/filter/1.1.0/filter.xsd",initialize:function(options){OpenLayers.Format.GML.v3.prototype.initialize.apply(this,[options]);},readers:{"ogc":OpenLayers.Util.applyDefaults({"PropertyIsEqualTo":function(node,obj){var matchCase=node.getAttribute("matchCase");var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.EQUAL_TO,matchCase:!(matchCase==="false"||matchCase==="0")});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsNotEqualTo":function(node,obj){var matchCase=node.getAttribute("matchCase");var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.NOT_EQUAL_TO,matchCase:!(matchCase==="false"||matchCase==="0")});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsLike":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.LIKE});this.readChildNodes(node,filter);var wildCard=node.getAttribute("wildCard");var singleChar=node.getAttribute("singleChar");var esc=node.getAttribute("escapeChar");filter.value2regex(wildCard,singleChar,esc);obj.filters.push(filter);}},OpenLayers.Format.Filter.v1.prototype.readers["ogc"]),"gml":OpenLayers.Format.GML.v3.prototype.readers["gml"],"feature":OpenLayers.Format.GML.v3.prototype.readers["feature"]},writers:{"ogc":OpenLayers.Util.applyDefaults({"PropertyIsEqualTo":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsEqualTo",{attributes:{matchCase:filter.matchCase}});this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.value,node);return node;},"PropertyIsNotEqualTo":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsNotEqualTo",{attributes:{matchCase:filter.matchCase}});this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.value,node);return node;},"PropertyIsLike":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsLike",{attributes:{wildCard:"*",singleChar:".",escapeChar:"!"}});this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.regex2value(),node);return node;},"BBOX":function(filter){var node=this.createElementNSPlus("ogc:BBOX");this.writeNode("PropertyName",filter,node);var box=this.writeNode("gml:Envelope",filter.value);if(filter.projection){box.setAttribute("srsName",filter.projection);} +node.appendChild(box);return node;}},OpenLayers.Format.Filter.v1.prototype.writers["ogc"]),"gml":OpenLayers.Format.GML.v3.prototype.writers["gml"],"feature":OpenLayers.Format.GML.v3.prototype.writers["feature"]},writeSpatial:function(filter,name){var node=this.createElementNSPlus("ogc:"+name);this.writeNode("PropertyName",filter,node);var child;if(filter.value instanceof OpenLayers.Geometry){child=this.writeNode("feature:_geometry",filter.value).firstChild;}else{child=this.writeNode("gml:Envelope",filter.value);} +if(filter.projection){child.setAttribute("srsName",filter.projection);} +node.appendChild(child);return node;},CLASS_NAME:"OpenLayers.Format.Filter.v1_1_0"});OpenLayers.Format.SOSCapabilities.v1_0_0=OpenLayers.Class(OpenLayers.Format.SOSCapabilities,{namespaces:{ows:"http://www.opengis.net/ows/1.1",sos:"http://www.opengis.net/sos/1.0",gml:"http://www.opengis.net/gml",xlink:"http://www.w3.org/1999/xlink"},regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +if(data&&data.nodeType==9){data=data.documentElement;} +var capabilities={};this.readNode(data,capabilities);return capabilities;},readers:{"gml":OpenLayers.Util.applyDefaults({"name":function(node,obj){obj.name=this.getChildValue(node);},"TimePeriod":function(node,obj){obj.timePeriod={};this.readChildNodes(node,obj.timePeriod);},"beginPosition":function(node,timePeriod){timePeriod.beginPosition=this.getChildValue(node);},"endPosition":function(node,timePeriod){timePeriod.endPosition=this.getChildValue(node);}},OpenLayers.Format.GML.v3.prototype.readers["gml"]),"sos":{"Capabilities":function(node,obj){this.readChildNodes(node,obj);},"Contents":function(node,obj){obj.contents={};this.readChildNodes(node,obj.contents);},"ObservationOfferingList":function(node,contents){contents.offeringList={};this.readChildNodes(node,contents.offeringList);},"ObservationOffering":function(node,offeringList){var id=this.getAttributeNS(node,this.namespaces.gml,"id");offeringList[id]={procedures:[],observedProperties:[],featureOfInterestIds:[],responseFormats:[],resultModels:[],responseModes:[]};this.readChildNodes(node,offeringList[id]);},"time":function(node,offering){offering.time={};this.readChildNodes(node,offering.time);},"procedure":function(node,offering){offering.procedures.push(this.getAttributeNS(node,this.namespaces.xlink,"href"));},"observedProperty":function(node,offering){offering.observedProperties.push(this.getAttributeNS(node,this.namespaces.xlink,"href"));},"featureOfInterest":function(node,offering){offering.featureOfInterestIds.push(this.getAttributeNS(node,this.namespaces.xlink,"href"));},"responseFormat":function(node,offering){offering.responseFormats.push(this.getChildValue(node));},"resultModel":function(node,offering){offering.resultModels.push(this.getChildValue(node));},"responseMode":function(node,offering){offering.responseModes.push(this.getChildValue(node));;}},"ows":OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]},CLASS_NAME:"OpenLayers.Format.SOSCapabilities.v1_0_0"});OpenLayers.Format.SOSGetFeatureOfInterest=OpenLayers.Class(OpenLayers.Format.XML,{VERSION:"1.0.0",namespaces:{sos:"http://www.opengis.net/sos/1.0",gml:"http://www.opengis.net/gml",sa:"http://www.opengis.net/sampling/1.0",xsi:"http://www.w3.org/2001/XMLSchema-instance"},schemaLocation:"http://www.opengis.net/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosAll.xsd",defaultPrefix:"sos",regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +if(data&&data.nodeType==9){data=data.documentElement;} +var info={features:[]};this.readNode(data,info);var features=[];for(var i=0,len=info.features.length;i<len;i++){var container=info.features[i];if(this.internalProjection&&this.externalProjection&&container.components[0]){container.components[0].transform(this.externalProjection,this.internalProjection);} +var feature=new OpenLayers.Feature.Vector(container.components[0],container.attributes);features.push(feature);} +return features;},readers:{"sa":{"SamplingPoint":function(node,obj){if(!obj.attributes){var feature={attributes:{}};obj.features.push(feature);obj=feature;} +obj.attributes.id=this.getAttributeNS(node,this.namespaces.gml,"id");this.readChildNodes(node,obj);},"position":function(node,obj){this.readChildNodes(node,obj);}},"gml":OpenLayers.Util.applyDefaults({"FeatureCollection":function(node,obj){this.readChildNodes(node,obj);},"featureMember":function(node,obj){var feature={attributes:{}};obj.features.push(feature);this.readChildNodes(node,feature);},"name":function(node,obj){obj.attributes.name=this.getChildValue(node);},"pos":function(node,obj){if(!this.externalProjection){this.externalProjection=new OpenLayers.Projection(node.getAttribute("srsName"));} +OpenLayers.Format.GML.v3.prototype.readers.gml.pos.apply(this,[node,obj]);}},OpenLayers.Format.GML.v3.prototype.readers.gml)},writers:{"sos":{"GetFeatureOfInterest":function(options){var node=this.createElementNSPlus("GetFeatureOfInterest",{attributes:{version:this.VERSION,service:'SOS',"xsi:schemaLocation":this.schemaLocation}});for(var i=0,len=options.fois.length;i<len;i++){this.writeNode("FeatureOfInterestId",{foi:options.fois[i]},node);} +return node;},"FeatureOfInterestId":function(options){var node=this.createElementNSPlus("FeatureOfInterestId",{value:options.foi});return node;}}},CLASS_NAME:"OpenLayers.Format.SOSGetFeatureOfInterest"});OpenLayers.Format.SOSGetObservation=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{ows:"http://www.opengis.net/ows",gml:"http://www.opengis.net/gml",sos:"http://www.opengis.net/sos/1.0",ogc:"http://www.opengis.net/ogc",om:"http://www.opengis.net/om/1.0",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/sos/1.0 http://schemas.opengis.net/sos/1.0.0/sosGetObservation.xsd",defaultPrefix:"sos",initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +if(data&&data.nodeType==9){data=data.documentElement;} +var info={measurements:[]};this.readNode(data,info);return info;},write:function(options){var node=this.writeNode("sos:GetObservation",options);node.setAttribute("xmlns:om",this.namespaces.om);this.setAttributeNS(node,this.namespaces.xsi,"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[node]);},readers:{"om":{"ObservationCollection":function(node,obj){obj.id=this.getAttributeNS(node,this.namespaces.gml,"id");this.readChildNodes(node,obj);},"member":function(node,observationCollection){this.readChildNodes(node,observationCollection);},"Measurement":function(node,observationCollection){var measurement={};observationCollection.measurements.push(measurement);this.readChildNodes(node,measurement);},"samplingTime":function(node,measurement){var samplingTime={};measurement.samplingTime=samplingTime;this.readChildNodes(node,samplingTime);},"observedProperty":function(node,measurement){measurement.observedProperty=this.getAttributeNS(node,this.namespaces.xlink,"href");this.readChildNodes(node,measurement);},"procedure":function(node,measurement){measurement.procedure=this.getAttributeNS(node,this.namespaces.xlink,"href");this.readChildNodes(node,measurement);},"result":function(node,measurement){var result={};measurement.result=result;if(this.getChildValue(node)!==''){result.value=this.getChildValue(node);result.uom=node.getAttribute("uom");}else{this.readChildNodes(node,result);}}},"gml":OpenLayers.Util.applyDefaults({"TimeInstant":function(node,samplingTime){var timeInstant={};samplingTime.timeInstant=timeInstant;this.readChildNodes(node,timeInstant);},"timePosition":function(node,timeInstant){timeInstant.timePosition=this.getChildValue(node);}},OpenLayers.Format.GML.v3.prototype.readers.gml)},writers:{"sos":{"GetObservation":function(options){var node=this.createElementNSPlus("GetObservation",{attributes:{version:this.VERSION,service:'SOS'}});this.writeNode("offering",options,node);this.writeNode("eventTime",options,node);this.writeNode("procedure",options,node);this.writeNode("observedProperty",options,node);this.writeNode("responseFormat",options,node);this.writeNode("resultModel",options,node);this.writeNode("responseMode",options,node);return node;},"responseFormat":function(options){return this.createElementNSPlus("responseFormat",{value:options.responseFormat});},"procedure":function(options){return this.createElementNSPlus("procedure",{value:options.procedure});},"offering":function(options){return this.createElementNSPlus("offering",{value:options.offering});},"observedProperty":function(options){return this.createElementNSPlus("observedProperty",{value:options.observedProperty});},"eventTime":function(options){var node=this.createElementNSPlus("eventTime");if(options.eventTime==='latest'){this.writeNode("ogc:TM_Equals",options,node);} +return node;},"resultModel":function(options){return this.createElementNSPlus("resultModel",{value:options.resultModel});},"responseMode":function(options){return this.createElementNSPlus("responseMode",{value:options.responseMode});}},"ogc":{"TM_Equals":function(options){var node=this.createElementNSPlus("ogc:TM_Equals");this.writeNode("ogc:PropertyName",{property:"urn:ogc:data:time:iso8601"},node);if(options.eventTime==='latest'){this.writeNode("gml:TimeInstant",{value:'latest'},node);} +return node;},"PropertyName":function(options){return this.createElementNSPlus("ogc:PropertyName",{value:options.property});}},"gml":{"TimeInstant":function(options){var node=this.createElementNSPlus("gml:TimeInstant");this.writeNode("gml:timePosition",options,node);return node;},"timePosition":function(options){var node=this.createElementNSPlus("gml:timePosition",{value:options.value});return node;}}},CLASS_NAME:"OpenLayers.Format.SOSGetObservation"});OpenLayers.Format.CSWGetRecords.v2_0_2=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance",csw:"http://www.opengis.net/cat/csw/2.0.2",dc:"http://purl.org/dc/elements/1.1/",dct:"http://purl.org/dc/terms/",ows:"http://www.opengis.net/ows"},defaultPrefix:"csw",version:"2.0.2",schemaLocation:"http://www.opengis.net/cat/csw/2.0.2 http://schemas.opengis.net/csw/2.0.2/CSW-discovery.xsd",requestId:null,resultType:null,outputFormat:null,outputSchema:null,startPosition:null,maxRecords:null,DistributedSearch:null,ResponseHandler:null,Query:null,regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +if(data&&data.nodeType==9){data=data.documentElement;} +var obj={};this.readNode(data,obj);return obj;},readers:{"csw":{"GetRecordsResponse":function(node,obj){obj.records=[];this.readChildNodes(node,obj);var version=this.getAttributeNS(node,"",'version');if(version!=""){obj.version=version;}},"RequestId":function(node,obj){obj.RequestId=this.getChildValue(node);},"SearchStatus":function(node,obj){obj.SearchStatus={};var timestamp=this.getAttributeNS(node,"",'timestamp');if(timestamp!=""){obj.SearchStatus.timestamp=timestamp;}},"SearchResults":function(node,obj){this.readChildNodes(node,obj);var attrs=node.attributes;var SearchResults={};for(var i=0,len=attrs.length;i<len;++i){if((attrs[i].name=="numberOfRecordsMatched")||(attrs[i].name=="numberOfRecordsReturned")||(attrs[i].name=="nextRecord")){SearchResults[attrs[i].name]=parseInt(attrs[i].nodeValue);}else{SearchResults[attrs[i].name]=attrs[i].nodeValue;}} +obj.SearchResults=SearchResults;},"SummaryRecord":function(node,obj){var record={type:"SummaryRecord"};this.readChildNodes(node,record);obj.records.push(record);},"BriefRecord":function(node,obj){var record={type:"BriefRecord"};this.readChildNodes(node,record);obj.records.push(record);},"DCMIRecord":function(node,obj){var record={type:"DCMIRecord"};this.readChildNodes(node,record);obj.records.push(record);},"Record":function(node,obj){var record={type:"Record"};this.readChildNodes(node,record);obj.records.push(record);}},"dc":{"*":function(node,obj){var name=node.localName||node.nodeName.split(":").pop();if(!(obj[name]instanceof Array)){obj[name]=new Array();} +var dc_element={};var attrs=node.attributes;for(var i=0,len=attrs.length;i<len;++i){dc_element[attrs[i].name]=attrs[i].nodeValue;} +dc_element.value=this.getChildValue(node);obj[name].push(dc_element);}},"dct":{"*":function(node,obj){var name=node.localName||node.nodeName.split(":").pop();if(!(obj[name]instanceof Array)){obj[name]=new Array();} +obj[name].push(this.getChildValue(node));}},"ows":OpenLayers.Util.applyDefaults({"BoundingBox":function(node,obj){if(obj.bounds){obj.BoundingBox=[{crs:obj.projection,value:[obj.bounds.left,obj.bounds.bottom,obj.bounds.right,obj.bounds.top]}];delete obj.projection;delete obj.bounds;} +OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"]["BoundingBox"].apply(this,arguments);}},OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"])},write:function(options){var node=this.writeNode("csw:GetRecords",options);return OpenLayers.Format.XML.prototype.write.apply(this,[node]);},writers:{"csw":{"GetRecords":function(options){if(!options){options={};} +var node=this.createElementNSPlus("csw:GetRecords",{attributes:{service:"CSW",version:this.version,requestId:options.requestId||this.requestId,resultType:options.resultType||this.resultType,outputFormat:options.outputFormat||this.outputFormat,outputSchema:options.outputSchema||this.outputSchema,startPosition:options.startPosition||this.startPosition,maxRecords:options.maxRecords||this.maxRecords}});if(options.DistributedSearch||this.DistributedSearch){this.writeNode("csw:DistributedSearch",options.DistributedSearch||this.DistributedSearch,node);} +var ResponseHandler=options.ResponseHandler||this.ResponseHandler;if(ResponseHandler instanceof Array&&ResponseHandler.length>0){for(var i=0,len=ResponseHandler.length;i<len;i++){this.writeNode("csw:ResponseHandler",ResponseHandler[i],node);}} +this.writeNode("Query",options.Query||this.Query,node);return node;},"DistributedSearch":function(options){var node=this.createElementNSPlus("csw:DistributedSearch",{attributes:{hopCount:options.hopCount}});return node;},"ResponseHandler":function(options){var node=this.createElementNSPlus("csw:ResponseHandler",{value:options.value});return node;},"Query":function(options){if(!options){options={};} +var node=this.createElementNSPlus("csw:Query",{attributes:{typeNames:options.typeNames||"csw:Record"}});var ElementName=options.ElementName;if(ElementName instanceof Array&&ElementName.length>0){for(var i=0,len=ElementName.length;i<len;i++){this.writeNode("csw:ElementName",ElementName[i],node);}}else{this.writeNode("csw:ElementSetName",options.ElementSetName||{value:'summary'},node);} +if(options.Constraint){this.writeNode("csw:Constraint",options.Constraint,node);} +return node;},"ElementName":function(options){var node=this.createElementNSPlus("csw:ElementName",{value:options.value});return node;},"ElementSetName":function(options){var node=this.createElementNSPlus("csw:ElementSetName",{attributes:{typeNames:options.typeNames},value:options.value});return node;},"Constraint":function(options){var node=this.createElementNSPlus("csw:Constraint",{attributes:{version:options.version}});if(options.Filter){var format=new OpenLayers.Format.Filter({version:options.version});node.appendChild(format.write(options.Filter));}else if(options.CqlText){var child=this.createElementNSPlus("CqlText",{value:options.CqlText.value});node.appendChild(child);} +return node;}}},CLASS_NAME:"OpenLayers.Format.CSWGetRecords.v2_0_2"});OpenLayers.Format.SLD.v1=OpenLayers.Class(OpenLayers.Format.Filter.v1_0_0,{namespaces:{sld:"http://www.opengis.net/sld",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:"sld",schemaLocation:null,multipleSymbolizers:false,featureTypeCounter:null,defaultSymbolizer:{fillColor:"#808080",fillOpacity:1,strokeColor:"#000000",strokeOpacity:1,strokeWidth:1,strokeDashstyle:"solid",pointRadius:3,graphicName:"square"},initialize:function(options){OpenLayers.Format.Filter.v1_0_0.prototype.initialize.apply(this,[options]);},read:function(data,options){options=OpenLayers.Util.applyDefaults(options,this.options);var sld={namedLayers:options.namedLayersAsArray===true?[]:{}};this.readChildNodes(data,sld);return sld;},readers:OpenLayers.Util.applyDefaults({"sld":{"StyledLayerDescriptor":function(node,sld){sld.version=node.getAttribute("version");this.readChildNodes(node,sld);},"Name":function(node,obj){obj.name=this.getChildValue(node);},"Title":function(node,obj){obj.title=this.getChildValue(node);},"Abstract":function(node,obj){obj.description=this.getChildValue(node);},"NamedLayer":function(node,sld){var layer={userStyles:[],namedStyles:[]};this.readChildNodes(node,layer);for(var i=0,len=layer.userStyles.length;i<len;++i){layer.userStyles[i].layerName=layer.name;} +if(sld.namedLayers instanceof Array){sld.namedLayers.push(layer);}else{sld.namedLayers[layer.name]=layer;}},"NamedStyle":function(node,layer){layer.namedStyles.push(this.getChildName(node.firstChild));},"UserStyle":function(node,layer){var obj={defaultsPerSymbolizer:true,rules:[]};this.featureTypeCounter=-1;this.readChildNodes(node,obj);var style;if(this.multipleSymbolizers){delete obj.defaultsPerSymbolizer;style=new OpenLayers.Style2(obj);}else{style=new OpenLayers.Style(this.defaultSymbolizer,obj);} +layer.userStyles.push(style);},"IsDefault":function(node,style){if(this.getChildValue(node)=="1"){style.isDefault=true;}},"FeatureTypeStyle":function(node,style){++this.featureTypeCounter;var obj={rules:this.multipleSymbolizers?style.rules:[]};this.readChildNodes(node,obj);if(!this.multipleSymbolizers){style.rules=obj.rules;}},"Rule":function(node,obj){var config;if(this.multipleSymbolizers){config={symbolizers:[]};} +var rule=new OpenLayers.Rule(config);this.readChildNodes(node,rule);obj.rules.push(rule);},"ElseFilter":function(node,rule){rule.elseFilter=true;},"MinScaleDenominator":function(node,rule){rule.minScaleDenominator=parseFloat(this.getChildValue(node));},"MaxScaleDenominator":function(node,rule){rule.maxScaleDenominator=parseFloat(this.getChildValue(node));},"TextSymbolizer":function(node,rule){var config={};this.readChildNodes(node,config);if(this.multipleSymbolizers){config.zIndex=this.featureTypeCounter;rule.symbolizers.push(new OpenLayers.Symbolizer.Text(config));}else{rule.symbolizer["Text"]=OpenLayers.Util.applyDefaults(config,rule.symbolizer["Text"]);}},"Label":function(node,symbolizer){var obj={};this.readChildNodes(node,obj);if(obj.property){symbolizer.label="${"+obj.property+"}";}else{var value=this.readOgcExpression(node);if(value){symbolizer.label=value;}}},"Font":function(node,symbolizer){this.readChildNodes(node,symbolizer);},"Halo":function(node,symbolizer){var obj={};this.readChildNodes(node,obj);symbolizer.haloRadius=obj.haloRadius;symbolizer.haloColor=obj.fillColor;symbolizer.haloOpacity=obj.fillOpacity;},"Radius":function(node,symbolizer){var radius=this.readOgcExpression(node);if(radius!=null){symbolizer.haloRadius=radius;}},"RasterSymbolizer":function(node,rule){var config={};this.readChildNodes(node,config);if(this.multipleSymbolizers){config.zIndex=this.featureTypeCounter;rule.symbolizers.push(new OpenLayers.Symbolizer.Raster(config));}else{rule.symbolizer["Raster"]=OpenLayers.Util.applyDefaults(config,rule.symbolizer["Raster"]);}},"Geometry":function(node,obj){obj.geometry={};this.readChildNodes(node,obj.geometry);},"ColorMap":function(node,symbolizer){symbolizer.colorMap=[];this.readChildNodes(node,symbolizer.colorMap);},"ColorMapEntry":function(node,colorMap){var q=node.getAttribute("quantity");var o=node.getAttribute("opacity");colorMap.push({color:node.getAttribute("color"),quantity:q!==null?parseFloat(q):undefined,label:node.getAttribute("label")||undefined,opacity:o!==null?parseFloat(o):undefined});},"LineSymbolizer":function(node,rule){var config={};this.readChildNodes(node,config);if(this.multipleSymbolizers){config.zIndex=this.featureTypeCounter;rule.symbolizers.push(new OpenLayers.Symbolizer.Line(config));}else{rule.symbolizer["Line"]=OpenLayers.Util.applyDefaults(config,rule.symbolizer["Line"]);}},"PolygonSymbolizer":function(node,rule){var config={fill:false,stroke:false};if(!this.multipleSymbolizers){config=rule.symbolizer["Polygon"]||config;} +this.readChildNodes(node,config);if(this.multipleSymbolizers){config.zIndex=this.featureTypeCounter;rule.symbolizers.push(new OpenLayers.Symbolizer.Polygon(config));}else{rule.symbolizer["Polygon"]=config;}},"PointSymbolizer":function(node,rule){var config={fill:false,stroke:false,graphic:false};if(!this.multipleSymbolizers){config=rule.symbolizer["Point"]||config;} +this.readChildNodes(node,config);if(this.multipleSymbolizers){config.zIndex=this.featureTypeCounter;rule.symbolizers.push(new OpenLayers.Symbolizer.Point(config));}else{rule.symbolizer["Point"]=config;}},"Stroke":function(node,symbolizer){symbolizer.stroke=true;this.readChildNodes(node,symbolizer);},"Fill":function(node,symbolizer){symbolizer.fill=true;this.readChildNodes(node,symbolizer);},"CssParameter":function(node,symbolizer){var cssProperty=node.getAttribute("name");var symProperty=this.cssMap[cssProperty];if(symProperty){var value=this.readOgcExpression(node);if(value){symbolizer[symProperty]=value;}}},"Graphic":function(node,symbolizer){symbolizer.graphic=true;var graphic={};this.readChildNodes(node,graphic);var properties=["stroke","strokeColor","strokeWidth","strokeOpacity","strokeLinecap","fill","fillColor","fillOpacity","graphicName","rotation","graphicFormat"];var prop,value;for(var i=0,len=properties.length;i<len;++i){prop=properties[i];value=graphic[prop];if(value!=undefined){symbolizer[prop]=value;}} +if(graphic.opacity!=undefined){symbolizer.graphicOpacity=graphic.opacity;} +if(graphic.size!=undefined){symbolizer.pointRadius=graphic.size/2;} +if(graphic.href!=undefined){symbolizer.externalGraphic=graphic.href;} +if(graphic.rotation!=undefined){symbolizer.rotation=graphic.rotation;}},"ExternalGraphic":function(node,graphic){this.readChildNodes(node,graphic);},"Mark":function(node,graphic){this.readChildNodes(node,graphic);},"WellKnownName":function(node,graphic){graphic.graphicName=this.getChildValue(node);},"Opacity":function(node,obj){var opacity=this.readOgcExpression(node);if(opacity){obj.opacity=opacity;}},"Size":function(node,obj){var size=this.readOgcExpression(node);if(size){obj.size=size;}},"Rotation":function(node,obj){var rotation=this.readOgcExpression(node);if(rotation){obj.rotation=rotation;}},"OnlineResource":function(node,obj){obj.href=this.getAttributeNS(node,this.namespaces.xlink,"href");},"Format":function(node,graphic){graphic.graphicFormat=this.getChildValue(node);}}},OpenLayers.Format.Filter.v1_0_0.prototype.readers),cssMap:{"stroke":"strokeColor","stroke-opacity":"strokeOpacity","stroke-width":"strokeWidth","stroke-linecap":"strokeLinecap","stroke-dasharray":"strokeDashstyle","fill":"fillColor","fill-opacity":"fillOpacity","font-family":"fontFamily","font-size":"fontSize","font-weight":"fontWeight","font-style":"fontStyle"},getCssProperty:function(sym){var css=null;for(var prop in this.cssMap){if(this.cssMap[prop]==sym){css=prop;break;}} +return css;},getGraphicFormat:function(href){var format,regex;for(var key in this.graphicFormats){if(this.graphicFormats[key].test(href)){format=key;break;}} +return format||this.defautlGraphicFormat;},defaultGraphicFormat:"image/png",graphicFormats:{"image/jpeg":/\.jpe?g$/i,"image/gif":/\.gif$/i,"image/png":/\.png$/i},write:function(sld){return this.writers.sld.StyledLayerDescriptor.apply(this,[sld]);},writers:OpenLayers.Util.applyDefaults({"sld":{"StyledLayerDescriptor":function(sld){var root=this.createElementNSPlus("sld:StyledLayerDescriptor",{attributes:{"version":this.VERSION,"xsi:schemaLocation":this.schemaLocation}});root.setAttribute("xmlns:ogc",this.namespaces.ogc);root.setAttribute("xmlns:gml",this.namespaces.gml);if(sld.name){this.writeNode("Name",sld.name,root);} +if(sld.title){this.writeNode("Title",sld.title,root);} +if(sld.description){this.writeNode("Abstract",sld.description,root);} +if(sld.namedLayers instanceof Array){for(var i=0,len=sld.namedLayers.length;i<len;++i){this.writeNode("NamedLayer",sld.namedLayers[i],root);}}else{for(var name in sld.namedLayers){this.writeNode("NamedLayer",sld.namedLayers[name],root);}} +return root;},"Name":function(name){return this.createElementNSPlus("sld:Name",{value:name});},"Title":function(title){return this.createElementNSPlus("sld:Title",{value:title});},"Abstract":function(description){return this.createElementNSPlus("sld:Abstract",{value:description});},"NamedLayer":function(layer){var node=this.createElementNSPlus("sld:NamedLayer");this.writeNode("Name",layer.name,node);if(layer.namedStyles){for(var i=0,len=layer.namedStyles.length;i<len;++i){this.writeNode("NamedStyle",layer.namedStyles[i],node);}} +if(layer.userStyles){for(var i=0,len=layer.userStyles.length;i<len;++i){this.writeNode("UserStyle",layer.userStyles[i],node);}} +return node;},"NamedStyle":function(name){var node=this.createElementNSPlus("sld:NamedStyle");this.writeNode("Name",name,node);return node;},"UserStyle":function(style){var node=this.createElementNSPlus("sld:UserStyle");if(style.name){this.writeNode("Name",style.name,node);} +if(style.title){this.writeNode("Title",style.title,node);} +if(style.description){this.writeNode("Abstract",style.description,node);} +if(style.isDefault){this.writeNode("IsDefault",style.isDefault,node);} +if(this.multipleSymbolizers&&style.rules){var rulesByZ={0:[]};var zValues=[0];var rule,ruleMap,symbolizer,zIndex,clone;for(var i=0,ii=style.rules.length;i<ii;++i){rule=style.rules[i];if(rule.symbolizers){ruleMap={};for(var j=0,jj=rule.symbolizers.length;j<jj;++j){symbolizer=rule.symbolizers[j];zIndex=symbolizer.zIndex;if(!(zIndex in ruleMap)){clone=rule.clone();clone.symbolizers=[];ruleMap[zIndex]=clone;} +ruleMap[zIndex].symbolizers.push(symbolizer.clone());} +for(zIndex in ruleMap){if(!(zIndex in rulesByZ)){zValues.push(zIndex);rulesByZ[zIndex]=[];} +rulesByZ[zIndex].push(ruleMap[zIndex]);}}else{rulesByZ[0].push(rule.clone());}} +zValues.sort();var rules;for(var i=0,ii=zValues.length;i<ii;++i){rules=rulesByZ[zValues[i]];if(rules.length>0){clone=style.clone();clone.rules=rulesByZ[zValues[i]];this.writeNode("FeatureTypeStyle",clone,node);}}}else{this.writeNode("FeatureTypeStyle",style,node);} +return node;},"IsDefault":function(bool){return this.createElementNSPlus("sld:IsDefault",{value:(bool)?"1":"0"});},"FeatureTypeStyle":function(style){var node=this.createElementNSPlus("sld:FeatureTypeStyle");for(var i=0,len=style.rules.length;i<len;++i){this.writeNode("Rule",style.rules[i],node);} +return node;},"Rule":function(rule){var node=this.createElementNSPlus("sld:Rule");if(rule.name){this.writeNode("Name",rule.name,node);} +if(rule.title){this.writeNode("Title",rule.title,node);} +if(rule.description){this.writeNode("Abstract",rule.description,node);} +if(rule.elseFilter){this.writeNode("ElseFilter",null,node);}else if(rule.filter){this.writeNode("ogc:Filter",rule.filter,node);} +if(rule.minScaleDenominator!=undefined){this.writeNode("MinScaleDenominator",rule.minScaleDenominator,node);} +if(rule.maxScaleDenominator!=undefined){this.writeNode("MaxScaleDenominator",rule.maxScaleDenominator,node);} +var type,symbolizer;if(this.multipleSymbolizers&&rule.symbolizers){var symbolizer;for(var i=0,ii=rule.symbolizers.length;i<ii;++i){symbolizer=rule.symbolizers[i];type=symbolizer.CLASS_NAME.split(".").pop();this.writeNode(type+"Symbolizer",symbolizer,node);}}else{var types=OpenLayers.Style.SYMBOLIZER_PREFIXES;for(var i=0,len=types.length;i<len;++i){type=types[i];symbolizer=rule.symbolizer[type];if(symbolizer){this.writeNode(type+"Symbolizer",symbolizer,node);}}} +return node;},"ElseFilter":function(){return this.createElementNSPlus("sld:ElseFilter");},"MinScaleDenominator":function(scale){return this.createElementNSPlus("sld:MinScaleDenominator",{value:scale});},"MaxScaleDenominator":function(scale){return this.createElementNSPlus("sld:MaxScaleDenominator",{value:scale});},"LineSymbolizer":function(symbolizer){var node=this.createElementNSPlus("sld:LineSymbolizer");this.writeNode("Stroke",symbolizer,node);return node;},"Stroke":function(symbolizer){var node=this.createElementNSPlus("sld:Stroke");if(symbolizer.strokeColor!=undefined){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"strokeColor"},node);} +if(symbolizer.strokeOpacity!=undefined){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"strokeOpacity"},node);} +if(symbolizer.strokeWidth!=undefined){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"strokeWidth"},node);} +if(symbolizer.strokeDashstyle!=undefined&&symbolizer.strokeDashstyle!=="solid"){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"strokeDashstyle"},node);} +if(symbolizer.strokeLinecap!=undefined){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"strokeLinecap"},node);} +return node;},"CssParameter":function(obj){return this.createElementNSPlus("sld:CssParameter",{attributes:{name:this.getCssProperty(obj.key)},value:obj.symbolizer[obj.key]});},"TextSymbolizer":function(symbolizer){var node=this.createElementNSPlus("sld:TextSymbolizer");if(symbolizer.label!=null){this.writeNode("Label",symbolizer.label,node);} +if(symbolizer.fontFamily!=null||symbolizer.fontSize!=null||symbolizer.fontWeight!=null||symbolizer.fontStyle!=null){this.writeNode("Font",symbolizer,node);} +if(symbolizer.haloRadius!=null||symbolizer.haloColor!=null||symbolizer.haloOpacity!=null){this.writeNode("Halo",symbolizer,node);} +if(symbolizer.fillColor!=null||symbolizer.fillOpacity!=null){this.writeNode("Fill",symbolizer,node);} +return node;},"Font":function(symbolizer){var node=this.createElementNSPlus("sld:Font");if(symbolizer.fontFamily){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"fontFamily"},node);} +if(symbolizer.fontSize){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"fontSize"},node);} +if(symbolizer.fontWeight){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"fontWeight"},node);} +if(symbolizer.fontStyle){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"fontStyle"},node);} +return node;},"Label":function(label){var node=this.createElementNSPlus("sld:Label");var tokens=label.split("${");node.appendChild(this.createTextNode(tokens[0]));var item,last;for(var i=1,len=tokens.length;i<len;i++){item=tokens[i];last=item.indexOf("}");if(last>0){this.writeNode("ogc:PropertyName",{property:item.substring(0,last)},node);node.appendChild(this.createTextNode(item.substring(++last)));}else{node.appendChild(this.createTextNode("${"+item));}} +return node;},"Halo":function(symbolizer){var node=this.createElementNSPlus("sld:Halo");if(symbolizer.haloRadius){this.writeNode("Radius",symbolizer.haloRadius,node);} +if(symbolizer.haloColor||symbolizer.haloOpacity){this.writeNode("Fill",{fillColor:symbolizer.haloColor,fillOpacity:symbolizer.haloOpacity},node);} +return node;},"Radius":function(value){return this.createElementNSPlus("sld:Radius",{value:value});},"RasterSymbolizer":function(symbolizer){var node=this.createElementNSPlus("sld:RasterSymbolizer");if(symbolizer.geometry){this.writeNode("Geometry",symbolizer.geometry,node);} +if(symbolizer.opacity){this.writeNode("Opacity",symbolizer.opacity,node);} +if(symbolizer.colorMap){this.writeNode("ColorMap",symbolizer.colorMap,node);} +return node;},"Geometry":function(geometry){var node=this.createElementNSPlus("sld:Geometry");if(geometry.property){this.writeNode("ogc:PropertyName",geometry,node);} +return node;},"ColorMap":function(colorMap){var node=this.createElementNSPlus("sld:ColorMap");for(var i=0,len=colorMap.length;i<len;++i){this.writeNode("ColorMapEntry",colorMap[i],node);} +return node;},"ColorMapEntry":function(colorMapEntry){var node=this.createElementNSPlus("sld:ColorMapEntry");var a=colorMapEntry;node.setAttribute("color",a.color);a.opacity!==undefined&&node.setAttribute("opacity",parseFloat(a.opacity));a.quantity!==undefined&&node.setAttribute("quantity",parseFloat(a.quantity));a.label!==undefined&&node.setAttribute("label",a.label);return node;},"PolygonSymbolizer":function(symbolizer){var node=this.createElementNSPlus("sld:PolygonSymbolizer");if(symbolizer.fill!==false){this.writeNode("Fill",symbolizer,node);} +if(symbolizer.stroke!==false){this.writeNode("Stroke",symbolizer,node);} +return node;},"Fill":function(symbolizer){var node=this.createElementNSPlus("sld:Fill");if(symbolizer.fillColor){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"fillColor"},node);} +if(symbolizer.fillOpacity!=null){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"fillOpacity"},node);} +return node;},"PointSymbolizer":function(symbolizer){var node=this.createElementNSPlus("sld:PointSymbolizer");this.writeNode("Graphic",symbolizer,node);return node;},"Graphic":function(symbolizer){var node=this.createElementNSPlus("sld:Graphic");if(symbolizer.externalGraphic!=undefined){this.writeNode("ExternalGraphic",symbolizer,node);}else{this.writeNode("Mark",symbolizer,node);} +if(symbolizer.graphicOpacity!=undefined){this.writeNode("Opacity",symbolizer.graphicOpacity,node);} +if(symbolizer.pointRadius!=undefined){this.writeNode("Size",symbolizer.pointRadius*2,node);} +if(symbolizer.rotation!=undefined){this.writeNode("Rotation",symbolizer.rotation,node);} +return node;},"ExternalGraphic":function(symbolizer){var node=this.createElementNSPlus("sld:ExternalGraphic");this.writeNode("OnlineResource",symbolizer.externalGraphic,node);var format=symbolizer.graphicFormat||this.getGraphicFormat(symbolizer.externalGraphic);this.writeNode("Format",format,node);return node;},"Mark":function(symbolizer){var node=this.createElementNSPlus("sld:Mark");if(symbolizer.graphicName){this.writeNode("WellKnownName",symbolizer.graphicName,node);} +if(symbolizer.fill!==false){this.writeNode("Fill",symbolizer,node);} +if(symbolizer.stroke!==false){this.writeNode("Stroke",symbolizer,node);} +return node;},"WellKnownName":function(name){return this.createElementNSPlus("sld:WellKnownName",{value:name});},"Opacity":function(value){return this.createElementNSPlus("sld:Opacity",{value:value});},"Size":function(value){return this.createElementNSPlus("sld:Size",{value:value});},"Rotation":function(value){return this.createElementNSPlus("sld:Rotation",{value:value});},"OnlineResource":function(href){return this.createElementNSPlus("sld:OnlineResource",{attributes:{"xlink:type":"simple","xlink:href":href}});},"Format":function(format){return this.createElementNSPlus("sld:Format",{value:format});}}},OpenLayers.Format.Filter.v1_0_0.prototype.writers),CLASS_NAME:"OpenLayers.Format.SLD.v1"});OpenLayers.Format.WFST.v1_0_0=OpenLayers.Class(OpenLayers.Format.Filter.v1_0_0,OpenLayers.Format.WFST.v1,{version:"1.0.0",srsNameInQuery:false,schemaLocations:{"wfs":"http://schemas.opengis.net/wfs/1.0.0/WFS-transaction.xsd"},initialize:function(options){OpenLayers.Format.Filter.v1_0_0.prototype.initialize.apply(this,[options]);OpenLayers.Format.WFST.v1.prototype.initialize.apply(this,[options]);},readers:{"wfs":OpenLayers.Util.applyDefaults({"WFS_TransactionResponse":function(node,obj){obj.insertIds=[];obj.success=false;this.readChildNodes(node,obj);},"InsertResult":function(node,container){var obj={fids:[]};this.readChildNodes(node,obj);container.insertIds.push(obj.fids[0]);},"TransactionResult":function(node,obj){this.readChildNodes(node,obj);},"Status":function(node,obj){this.readChildNodes(node,obj);},"SUCCESS":function(node,obj){obj.success=true;}},OpenLayers.Format.WFST.v1.prototype.readers["wfs"]),"gml":OpenLayers.Format.GML.v2.prototype.readers["gml"],"feature":OpenLayers.Format.GML.v2.prototype.readers["feature"],"ogc":OpenLayers.Format.Filter.v1_0_0.prototype.readers["ogc"]},writers:{"wfs":OpenLayers.Util.applyDefaults({"Query":function(options){options=OpenLayers.Util.extend({featureNS:this.featureNS,featurePrefix:this.featurePrefix,featureType:this.featureType,srsName:this.srsName,srsNameInQuery:this.srsNameInQuery},options);var node=this.createElementNSPlus("wfs:Query",{attributes:{typeName:(options.featureNS?options.featurePrefix+":":"")+ +options.featureType}});if(options.srsNameInQuery&&options.srsName){node.setAttribute("srsName",options.srsName);} +if(options.featureNS){node.setAttribute("xmlns:"+options.featurePrefix,options.featureNS);} +if(options.propertyNames){for(var i=0,len=options.propertyNames.length;i<len;i++){this.writeNode("ogc:PropertyName",{property:options.propertyNames[i]},node);}} +if(options.filter){this.setFilterProperty(options.filter);this.writeNode("ogc:Filter",options.filter,node);} +return node;}},OpenLayers.Format.WFST.v1.prototype.writers["wfs"]),"gml":OpenLayers.Format.GML.v2.prototype.writers["gml"],"feature":OpenLayers.Format.GML.v2.prototype.writers["feature"],"ogc":OpenLayers.Format.Filter.v1_0_0.prototype.writers["ogc"]},CLASS_NAME:"OpenLayers.Format.WFST.v1_0_0"});OpenLayers.Format.WFST.v1_1_0=OpenLayers.Class(OpenLayers.Format.Filter.v1_1_0,OpenLayers.Format.WFST.v1,{version:"1.1.0",schemaLocations:{"wfs":"http://schemas.opengis.net/wfs/1.1.0/wfs.xsd"},initialize:function(options){OpenLayers.Format.Filter.v1_1_0.prototype.initialize.apply(this,[options]);OpenLayers.Format.WFST.v1.prototype.initialize.apply(this,[options]);},readers:{"wfs":OpenLayers.Util.applyDefaults({"FeatureCollection":function(node,obj){obj.numberOfFeatures=parseInt(node.getAttribute("numberOfFeatures"));OpenLayers.Format.WFST.v1.prototype.readers["wfs"]["FeatureCollection"].apply(this,arguments);},"TransactionResponse":function(node,obj){obj.insertIds=[];obj.success=false;this.readChildNodes(node,obj);},"TransactionSummary":function(node,obj){obj.success=true;},"InsertResults":function(node,obj){this.readChildNodes(node,obj);},"Feature":function(node,container){var obj={fids:[]};this.readChildNodes(node,obj);container.insertIds.push(obj.fids[0]);}},OpenLayers.Format.WFST.v1.prototype.readers["wfs"]),"gml":OpenLayers.Format.GML.v3.prototype.readers["gml"],"feature":OpenLayers.Format.GML.v3.prototype.readers["feature"],"ogc":OpenLayers.Format.Filter.v1_1_0.prototype.readers["ogc"]},writers:{"wfs":OpenLayers.Util.applyDefaults({"GetFeature":function(options){var node=OpenLayers.Format.WFST.v1.prototype.writers["wfs"]["GetFeature"].apply(this,arguments);options&&options.resultType&&this.setAttributes(node,{resultType:options.resultType});return node;},"Query":function(options){options=OpenLayers.Util.extend({featureNS:this.featureNS,featurePrefix:this.featurePrefix,featureType:this.featureType,srsName:this.srsName},options);var node=this.createElementNSPlus("wfs:Query",{attributes:{typeName:(options.featureNS?options.featurePrefix+":":"")+ +options.featureType,srsName:options.srsName}});if(options.featureNS){node.setAttribute("xmlns:"+options.featurePrefix,options.featureNS);} +if(options.propertyNames){for(var i=0,len=options.propertyNames.length;i<len;i++){this.writeNode("wfs:PropertyName",{property:options.propertyNames[i]},node);}} +if(options.filter){this.setFilterProperty(options.filter);this.writeNode("ogc:Filter",options.filter,node);} +return node;},"PropertyName":function(obj){return this.createElementNSPlus("wfs:PropertyName",{value:obj.property});}},OpenLayers.Format.WFST.v1.prototype.writers["wfs"]),"gml":OpenLayers.Format.GML.v3.prototype.writers["gml"],"feature":OpenLayers.Format.GML.v3.prototype.writers["feature"],"ogc":OpenLayers.Format.Filter.v1_1_0.prototype.writers["ogc"]},CLASS_NAME:"OpenLayers.Format.WFST.v1_1_0"});OpenLayers.Protocol.SOS.v1_0_0=OpenLayers.Class(OpenLayers.Protocol,{fois:null,formatOptions:null,initialize:function(options){OpenLayers.Protocol.prototype.initialize.apply(this,[options]);if(!options.format){this.format=new OpenLayers.Format.SOSGetFeatureOfInterest(this.formatOptions);}},destroy:function(){if(this.options&&!this.options.format){this.format.destroy();} +this.format=null;OpenLayers.Protocol.prototype.destroy.apply(this);},read:function(options){options=OpenLayers.Util.extend({},options);OpenLayers.Util.applyDefaults(options,this.options||{});var response=new OpenLayers.Protocol.Response({requestType:"read"});var format=this.format;var data=OpenLayers.Format.XML.prototype.write.apply(format,[format.writeNode("sos:GetFeatureOfInterest",{fois:this.fois})]);response.priv=OpenLayers.Request.POST({url:options.url,callback:this.createCallback(this.handleRead,response,options),data:data});return response;},handleRead:function(response,options){if(options.callback){var request=response.priv;if(request.status>=200&&request.status<300){response.features=this.parseFeatures(request);response.code=OpenLayers.Protocol.Response.SUCCESS;}else{response.code=OpenLayers.Protocol.Response.FAILURE;} +options.callback.call(options.scope,response);}},parseFeatures:function(request){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;} +if(!doc||doc.length<=0){return null;} +return this.format.read(doc);},CLASS_NAME:"OpenLayers.Protocol.SOS.v1_0_0"});OpenLayers.Format.SLD.v1_0_0=OpenLayers.Class(OpenLayers.Format.SLD.v1,{VERSION:"1.0.0",schemaLocation:"http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd",initialize:function(options){OpenLayers.Format.SLD.v1.prototype.initialize.apply(this,[options]);},CLASS_NAME:"OpenLayers.Format.SLD.v1_0_0"});OpenLayers.Protocol.WFS.v1_0_0=OpenLayers.Class(OpenLayers.Protocol.WFS.v1,{version:"1.0.0",CLASS_NAME:"OpenLayers.Protocol.WFS.v1_0_0"});OpenLayers.Protocol.WFS.v1_1_0=OpenLayers.Class(OpenLayers.Protocol.WFS.v1,{version:"1.1.0",CLASS_NAME:"OpenLayers.Protocol.WFS.v1_1_0"});OpenLayers.Format.OWSContext.v0_3_1=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{owc:"http://www.opengis.net/ows-context",gml:"http://www.opengis.net/gml",kml:"http://www.opengis.net/kml/2.2",ogc:"http://www.opengis.net/ogc",ows:"http://www.opengis.net/ows",sld:"http://www.opengis.net/sld",xlink:"http://www.w3.org/1999/xlink",xsi:"http://www.w3.org/2001/XMLSchema-instance"},VERSION:"0.3.1",schemaLocation:"http://www.opengis.net/ows-context http://www.ogcnetwork.net/schemas/owc/0.3.1/owsContext.xsd",defaultPrefix:"owc",extractAttributes:true,xy:true,regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},featureNS:"http://mapserver.gis.umn.edu/mapserver",featureType:'vector',geometryName:'geometry',nestingLayerLookup:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);OpenLayers.Format.GML.v2.prototype.setGeometryTypes.call(this);},setNestingPath:function(l){if(l.layersContext){for(var i=0,len=l.layersContext.length;i<len;i++){var layerContext=l.layersContext[i];var nPath=[];var nTitle=l.title||"";if(l.metadata&&l.metadata.nestingPath){nPath=l.metadata.nestingPath.slice();} +if(nTitle!=""){nPath.push(nTitle);} +layerContext.metadata.nestingPath=nPath;if(layerContext.layersContext){this.setNestingPath(layerContext);}}}},decomposeNestingPath:function(nPath){var a=[];if(nPath instanceof Array){while(nPath.length>0){a.push(nPath.slice());nPath.pop();} +a.reverse();} +return a;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);} +if(data&&data.nodeType==9){data=data.documentElement;} +var context={};this.readNode(data,context);this.setNestingPath({layersContext:context.layersContext});var layers=[];this.processLayer(layers,context);delete context.layersContext;context.layersContext=layers;return context;},processLayer:function(layerArray,layer){if(layer.layersContext){for(var i=0,len=layer.layersContext.length;i<len;i++){var l=layer.layersContext[i];layerArray.push(l);if(l.layersContext){this.processLayer(layerArray,l);}}}},write:function(context,options){var name="OWSContext";this.nestingLayerLookup={};options=options||{};OpenLayers.Util.applyDefaults(options,context);var root=this.writeNode(name,options);this.nestingLayerLookup=null;this.setAttributeNS(root,this.namespaces["xsi"],"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},readers:{"kml":{"Document":function(node,obj){obj.features=new OpenLayers.Format.KML({kmlns:this.namespaces.kml,extractStyles:true}).read(node);}},"owc":{"OWSContext":function(node,obj){this.readChildNodes(node,obj);},"General":function(node,obj){this.readChildNodes(node,obj);},"ResourceList":function(node,obj){this.readChildNodes(node,obj);},"Layer":function(node,obj){var layerContext={metadata:{},visibility:(node.getAttribute("hidden")!="1"),queryable:(node.getAttribute("queryable")=="1"),opacity:((node.getAttribute("opacity")!=null)?parseFloat(node.getAttribute("opacity")):null),name:node.getAttribute("name"),categoryLayer:(node.getAttribute("name")==null),formats:[],styles:[]};if(!obj.layersContext){obj.layersContext=[];} +obj.layersContext.push(layerContext);this.readChildNodes(node,layerContext);},"InlineGeometry":function(node,obj){obj.features=[];var elements=this.getElementsByTagNameNS(node,this.namespaces.gml,"featureMember");var el;if(elements.length>=1){el=elements[0];} +if(el&&el.firstChild){var featurenode=(el.firstChild.nextSibling)?el.firstChild.nextSibling:el.firstChild;this.setNamespace("feature",featurenode.namespaceURI);this.featureType=featurenode.localName||featurenode.nodeName.split(":").pop();this.readChildNodes(node,obj);}},"Server":function(node,obj){if((!obj.service&&!obj.version)||(obj.service!=OpenLayers.Format.Context.serviceTypes.WMS)){obj.service=node.getAttribute("service");obj.version=node.getAttribute("version");this.readChildNodes(node,obj);}},"Name":function(node,obj){obj.name=this.getChildValue(node);this.readChildNodes(node,obj);},"Title":function(node,obj){obj.title=this.getChildValue(node);this.readChildNodes(node,obj);},"StyleList":function(node,obj){this.readChildNodes(node,obj.styles);},"Style":function(node,obj){var style={};obj.push(style);this.readChildNodes(node,style);},"LegendURL":function(node,obj){var legend={};obj.legend=legend;this.readChildNodes(node,legend);},"OnlineResource":function(node,obj){obj.url=this.getAttributeNS(node,this.namespaces.xlink,"href");this.readChildNodes(node,obj);}},"ows":OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers.ows,"gml":OpenLayers.Format.GML.v2.prototype.readers.gml,"sld":OpenLayers.Format.SLD.v1_0_0.prototype.readers.sld,"feature":OpenLayers.Format.GML.v2.prototype.readers.feature},writers:{"owc":{"OWSContext":function(options){var node=this.createElementNSPlus("OWSContext",{attributes:{version:this.VERSION,id:options.id||OpenLayers.Util.createUniqueID("OpenLayers_OWSContext_")}});this.writeNode("General",options,node);this.writeNode("ResourceList",options,node);return node;},"General":function(options){var node=this.createElementNSPlus("General");this.writeNode("ows:BoundingBox",options,node);this.writeNode("ows:Title",options.title||'OpenLayers OWSContext',node);return node;},"ResourceList":function(options){var node=this.createElementNSPlus("ResourceList");for(var i=0,len=options.layers.length;i<len;i++){var layer=options.layers[i];var decomposedPath=this.decomposeNestingPath(layer.metadata.nestingPath);this.writeNode("_Layer",{layer:layer,subPaths:decomposedPath},node);} +return node;},"Server":function(options){var node=this.createElementNSPlus("Server",{attributes:{version:options.version,service:options.service}});this.writeNode("OnlineResource",options,node);return node;},"OnlineResource":function(options){var node=this.createElementNSPlus("OnlineResource",{attributes:{"xlink:href":options.url}});return node;},"InlineGeometry":function(layer){var node=this.createElementNSPlus("InlineGeometry");this.writeNode("gml:boundedBy",layer.getDataExtent(),node);for(var i=0,len=layer.features.length;i<len;i++){this.writeNode("gml:featureMember",layer.features[i],node);} +return node;},"StyleList":function(styles){var node=this.createElementNSPlus("StyleList");for(var i=0,len=styles.length;i<len;i++){this.writeNode("Style",styles[i],node);} +return node;},"Style":function(style){var node=this.createElementNSPlus("Style");this.writeNode("Name",style,node);this.writeNode("Title",style,node);this.writeNode("LegendURL",style,node);return node;},"Name":function(obj){var node=this.createElementNSPlus("Name",{value:obj.name});return node;},"Title":function(obj){var node=this.createElementNSPlus("Title",{value:obj.title});return node;},"LegendURL":function(style){var node=this.createElementNSPlus("LegendURL");this.writeNode("OnlineResource",style.legend,node);return node;},"_WMS":function(layer){var node=this.createElementNSPlus("Layer",{attributes:{name:layer.params.LAYERS,queryable:layer.queryable?"1":"0",hidden:layer.visibility?"0":"1",opacity:layer.opacity?layer.opacity:null}});this.writeNode("ows:Title",layer.name,node);this.writeNode("ows:OutputFormat",layer.params.FORMAT,node);this.writeNode("Server",{service:OpenLayers.Format.Context.serviceTypes.WMS,version:layer.params.VERSION,url:layer.url},node);if(layer.metadata.styles&&layer.metadata.styles.length>0){this.writeNode("StyleList",layer.metadata.styles,node);} +return node;},"_Layer":function(options){var layer,subPaths,node,title;layer=options.layer;subPaths=options.subPaths;node=null;title=null;if(subPaths.length>0){var path=subPaths[0].join("/");var index=path.lastIndexOf("/");node=this.nestingLayerLookup[path];title=(index>0)?path.substring(index+1,path.length):path;if(!node){node=this.createElementNSPlus("Layer");this.writeNode("ows:Title",title,node);this.nestingLayerLookup[path]=node;} +options.subPaths.shift();this.writeNode("_Layer",options,node);return node;}else{if(layer instanceof OpenLayers.Layer.WMS){node=this.writeNode("_WMS",layer);}else if(layer instanceof OpenLayers.Layer.Vector){if(layer.protocol instanceof OpenLayers.Protocol.WFS.v1){node=this.writeNode("_WFS",layer);}else if(layer.protocol instanceof OpenLayers.Protocol.HTTP){if(layer.protocol.format instanceof OpenLayers.Format.GML){layer.protocol.format.version="2.1.2";node=this.writeNode("_GML",layer);}else if(layer.protocol.format instanceof OpenLayers.Format.KML){layer.protocol.format.version="2.2";node=this.writeNode("_KML",layer);}}else{this.setNamespace("feature",this.featureNS);node=this.writeNode("_InlineGeometry",layer);}} +if(layer.options.maxScale){this.writeNode("sld:MinScaleDenominator",layer.options.maxScale,node);} +if(layer.options.minScale){this.writeNode("sld:MaxScaleDenominator",layer.options.minScale,node);} +this.nestingLayerLookup[layer.name]=node;return node;}},"_WFS":function(layer){var node=this.createElementNSPlus("Layer",{attributes:{name:layer.protocol.featurePrefix+":"+layer.protocol.featureType,hidden:layer.visibility?"0":"1"}});this.writeNode("ows:Title",layer.name,node);this.writeNode("Server",{service:OpenLayers.Format.Context.serviceTypes.WFS,version:layer.protocol.version,url:layer.protocol.url},node);return node;},"_InlineGeometry":function(layer){var node=this.createElementNSPlus("Layer",{attributes:{name:this.featureType,hidden:layer.visibility?"0":"1"}});this.writeNode("ows:Title",layer.name,node);this.writeNode("InlineGeometry",layer,node);return node;},"_GML":function(layer){var node=this.createElementNSPlus("Layer");this.writeNode("ows:Title",layer.name,node);this.writeNode("Server",{service:OpenLayers.Format.Context.serviceTypes.GML,url:layer.protocol.url,version:layer.protocol.format.version},node);return node;},"_KML":function(layer){var node=this.createElementNSPlus("Layer");this.writeNode("ows:Title",layer.name,node);this.writeNode("Server",{service:OpenLayers.Format.Context.serviceTypes.KML,version:layer.protocol.format.version,url:layer.protocol.url},node);return node;}},"gml":OpenLayers.Util.applyDefaults({"boundedBy":function(bounds){var node=this.createElementNSPlus("gml:boundedBy");this.writeNode("gml:Box",bounds,node);return node;}},OpenLayers.Format.GML.v2.prototype.writers.gml),"ows":OpenLayers.Format.OWSCommon.v1_0_0.prototype.writers.ows,"sld":OpenLayers.Format.SLD.v1_0_0.prototype.writers.sld,"feature":OpenLayers.Format.GML.v2.prototype.writers.feature},CLASS_NAME:"OpenLayers.Format.OWSContext.v0_3_1"}); + +// OpenStreetMaps.js merged + +/** + * Namespace: Util.OSM + */ +OpenLayers.Util.OSM = {}; + +/** + * Constant: MISSING_TILE_URL + * {String} URL of image to display for missing tiles + */ +OpenLayers.Util.OSM.MISSING_TILE_URL = "http://www.openstreetmap.org/openlayers/img/404.png"; + +/** + * Property: originalOnImageLoadError + * {Function} Original onImageLoadError function. + */ +OpenLayers.Util.OSM.originalOnImageLoadError = OpenLayers.Util.onImageLoadError; + +/** + * Function: onImageLoadError + */ +OpenLayers.Util.onImageLoadError = function() { + if (this.src.match(/^http:\/\/[abc]\.[a-z]+\.openstreetmap\.org\//)) { + this.src = OpenLayers.Util.OSM.MISSING_TILE_URL; + } else if (this.src.match(/^http:\/\/[def]\.tah\.openstreetmap\.org\//)) { + // do nothing - this layer is transparent + } else { + OpenLayers.Util.OSM.originalOnImageLoadError; + } +}; + +/** + * Class: OpenLayers.Layer.OSM.Mapnik + * + * Inherits from: + * - <OpenLayers.Layer.OSM> + */ +OpenLayers.Layer.OSM.Mapnik = OpenLayers.Class(OpenLayers.Layer.OSM, { + /** + * Constructor: OpenLayers.Layer.OSM.Mapnik + * + * Parameters: + * name - {String} + * options - {Object} Hashtable of extra options to tag onto the layer + */ + initialize: function(name, options) { + var url = [ + "http://a.tile.openstreetmap.org/${z}/${x}/${y}.png", + "http://b.tile.openstreetmap.org/${z}/${x}/${y}.png", + "http://c.tile.openstreetmap.org/${z}/${x}/${y}.png" + ]; + options = OpenLayers.Util.extend({ + numZoomLevels: 19, + buffer: 0, + transitionEffect: "resize" + }, options); + var newArguments = [name, url, options]; + OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments); + }, + + CLASS_NAME: "OpenLayers.Layer.OSM.Mapnik" +}); + +/** + * Class: OpenLayers.Layer.OSM.Osmarender + * + * Inherits from: + * - <OpenLayers.Layer.OSM> + */ +OpenLayers.Layer.OSM.Osmarender = OpenLayers.Class(OpenLayers.Layer.OSM, { + /** + * Constructor: OpenLayers.Layer.OSM.Osmarender + * + * Parameters: + * name - {String} + * options - {Object} Hashtable of extra options to tag onto the layer + */ + initialize: function(name, options) { + var url = [ + "http://a.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png", + "http://b.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png", + "http://c.tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png" + ]; + options = OpenLayers.Util.extend({ + numZoomLevels: 18, + buffer: 0, + transitionEffect: "resize" + }, options); + var newArguments = [name, url, options]; + OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments); + }, + + CLASS_NAME: "OpenLayers.Layer.OSM.Osmarender" +}); + +/** + * Class: OpenLayers.Layer.OSM.CycleMap + * + * Inherits from: + * - <OpenLayers.Layer.OSM> + */ +OpenLayers.Layer.OSM.CycleMap = OpenLayers.Class(OpenLayers.Layer.OSM, { + /** + * Constructor: OpenLayers.Layer.OSM.CycleMap + * + * Parameters: + * name - {String} + * options - {Object} Hashtable of extra options to tag onto the layer + */ + initialize: function(name, options) { + var url = [ + "http://a.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png", + "http://b.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png", + "http://c.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png" + ]; + options = OpenLayers.Util.extend({ + numZoomLevels: 19, + buffer: 0, + transitionEffect: "resize" + }, options); + var newArguments = [name, url, options]; + OpenLayers.Layer.OSM.prototype.initialize.apply(this, newArguments); + }, + + CLASS_NAME: "OpenLayers.Layer.OSM.CycleMap" +});
\ No newline at end of file diff --git a/hugo/js/openlayers/img/blank.gif b/hugo/js/openlayers/img/blank.gif Binary files differnew file mode 100644 index 0000000..4bcc753 --- /dev/null +++ b/hugo/js/openlayers/img/blank.gif diff --git a/hugo/js/openlayers/img/cloud-popup-relative.png b/hugo/js/openlayers/img/cloud-popup-relative.png Binary files differnew file mode 100644 index 0000000..1215a36 --- /dev/null +++ b/hugo/js/openlayers/img/cloud-popup-relative.png diff --git a/hugo/js/openlayers/img/drag-rectangle-off.png b/hugo/js/openlayers/img/drag-rectangle-off.png Binary files differnew file mode 100644 index 0000000..fc6daf4 --- /dev/null +++ b/hugo/js/openlayers/img/drag-rectangle-off.png diff --git a/hugo/js/openlayers/img/drag-rectangle-on.png b/hugo/js/openlayers/img/drag-rectangle-on.png Binary files differnew file mode 100644 index 0000000..7f783ce --- /dev/null +++ b/hugo/js/openlayers/img/drag-rectangle-on.png diff --git a/hugo/js/openlayers/img/east-mini.png b/hugo/js/openlayers/img/east-mini.png Binary files differnew file mode 100644 index 0000000..0707567 --- /dev/null +++ b/hugo/js/openlayers/img/east-mini.png diff --git a/hugo/js/openlayers/img/layer-switcher-maximize.png b/hugo/js/openlayers/img/layer-switcher-maximize.png Binary files differnew file mode 100644 index 0000000..8d7bb16 --- /dev/null +++ b/hugo/js/openlayers/img/layer-switcher-maximize.png diff --git a/hugo/js/openlayers/img/layer-switcher-minimize.png b/hugo/js/openlayers/img/layer-switcher-minimize.png Binary files differnew file mode 100644 index 0000000..e80bf21 --- /dev/null +++ b/hugo/js/openlayers/img/layer-switcher-minimize.png diff --git a/hugo/js/openlayers/img/marker-blue.png b/hugo/js/openlayers/img/marker-blue.png Binary files differnew file mode 100644 index 0000000..83a90b4 --- /dev/null +++ b/hugo/js/openlayers/img/marker-blue.png diff --git a/hugo/js/openlayers/img/marker-gold.png b/hugo/js/openlayers/img/marker-gold.png Binary files differnew file mode 100644 index 0000000..2ff9ec5 --- /dev/null +++ b/hugo/js/openlayers/img/marker-gold.png diff --git a/hugo/js/openlayers/img/marker-green.png b/hugo/js/openlayers/img/marker-green.png Binary files differnew file mode 100644 index 0000000..17168f1 --- /dev/null +++ b/hugo/js/openlayers/img/marker-green.png diff --git a/hugo/js/openlayers/img/marker.png b/hugo/js/openlayers/img/marker.png Binary files differnew file mode 100644 index 0000000..ccd1913 --- /dev/null +++ b/hugo/js/openlayers/img/marker.png diff --git a/hugo/js/openlayers/img/measuring-stick-off.png b/hugo/js/openlayers/img/measuring-stick-off.png Binary files differnew file mode 100644 index 0000000..70c2dff --- /dev/null +++ b/hugo/js/openlayers/img/measuring-stick-off.png diff --git a/hugo/js/openlayers/img/measuring-stick-on.png b/hugo/js/openlayers/img/measuring-stick-on.png Binary files differnew file mode 100644 index 0000000..cdb8f34 --- /dev/null +++ b/hugo/js/openlayers/img/measuring-stick-on.png diff --git a/hugo/js/openlayers/img/north-mini.png b/hugo/js/openlayers/img/north-mini.png Binary files differnew file mode 100644 index 0000000..a8a0b40 --- /dev/null +++ b/hugo/js/openlayers/img/north-mini.png diff --git a/hugo/js/openlayers/img/panning-hand-off.png b/hugo/js/openlayers/img/panning-hand-off.png Binary files differnew file mode 100644 index 0000000..4c912ac --- /dev/null +++ b/hugo/js/openlayers/img/panning-hand-off.png diff --git a/hugo/js/openlayers/img/panning-hand-on.png b/hugo/js/openlayers/img/panning-hand-on.png Binary files differnew file mode 100644 index 0000000..6094c64 --- /dev/null +++ b/hugo/js/openlayers/img/panning-hand-on.png diff --git a/hugo/js/openlayers/img/slider.png b/hugo/js/openlayers/img/slider.png Binary files differnew file mode 100644 index 0000000..23afd57 --- /dev/null +++ b/hugo/js/openlayers/img/slider.png diff --git a/hugo/js/openlayers/img/south-mini.png b/hugo/js/openlayers/img/south-mini.png Binary files differnew file mode 100644 index 0000000..6c4ac8a --- /dev/null +++ b/hugo/js/openlayers/img/south-mini.png diff --git a/hugo/js/openlayers/img/west-mini.png b/hugo/js/openlayers/img/west-mini.png Binary files differnew file mode 100644 index 0000000..db5f420 --- /dev/null +++ b/hugo/js/openlayers/img/west-mini.png diff --git a/hugo/js/openlayers/img/zoom-minus-mini.png b/hugo/js/openlayers/img/zoom-minus-mini.png Binary files differnew file mode 100644 index 0000000..f9b63ab --- /dev/null +++ b/hugo/js/openlayers/img/zoom-minus-mini.png diff --git a/hugo/js/openlayers/img/zoom-plus-mini.png b/hugo/js/openlayers/img/zoom-plus-mini.png Binary files differnew file mode 100644 index 0000000..eecf2eb --- /dev/null +++ b/hugo/js/openlayers/img/zoom-plus-mini.png diff --git a/hugo/js/openlayers/img/zoom-world-mini.png b/hugo/js/openlayers/img/zoom-world-mini.png Binary files differnew file mode 100644 index 0000000..2159dde --- /dev/null +++ b/hugo/js/openlayers/img/zoom-world-mini.png diff --git a/hugo/js/openlayers/img/zoombar.png b/hugo/js/openlayers/img/zoombar.png Binary files differnew file mode 100644 index 0000000..959f01a --- /dev/null +++ b/hugo/js/openlayers/img/zoombar.png diff --git a/hugo/js/openlayers/theme/default/framedCloud.css b/hugo/js/openlayers/theme/default/framedCloud.css new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/hugo/js/openlayers/theme/default/framedCloud.css diff --git a/hugo/js/openlayers/theme/default/google.css b/hugo/js/openlayers/theme/default/google.css new file mode 100644 index 0000000..3c1c187 --- /dev/null +++ b/hugo/js/openlayers/theme/default/google.css @@ -0,0 +1,10 @@ +.olLayerGoogleCopyright { + right: 3px; + bottom: 2px; + left: auto; +} +.olLayerGooglePoweredBy { + left: 2px; + bottom: 2px; +} + diff --git a/hugo/js/openlayers/theme/default/ie6-style.css b/hugo/js/openlayers/theme/default/ie6-style.css new file mode 100644 index 0000000..65f6b19 --- /dev/null +++ b/hugo/js/openlayers/theme/default/ie6-style.css @@ -0,0 +1,7 @@ +.olControlZoomPanel div { + background-image: url(img/zoom-panel-NOALPHA.png); +} +.olControlPanPanel div { + background-image: url(img/pan-panel-NOALPHA.png); +} + diff --git a/hugo/js/openlayers/theme/default/img/add_point_off.png b/hugo/js/openlayers/theme/default/img/add_point_off.png Binary files differnew file mode 100644 index 0000000..aefd09c --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/add_point_off.png diff --git a/hugo/js/openlayers/theme/default/img/add_point_on.png b/hugo/js/openlayers/theme/default/img/add_point_on.png Binary files differnew file mode 100644 index 0000000..1294a2c --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/add_point_on.png diff --git a/hugo/js/openlayers/theme/default/img/blank.gif b/hugo/js/openlayers/theme/default/img/blank.gif Binary files differnew file mode 100644 index 0000000..4bcc753 --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/blank.gif diff --git a/hugo/js/openlayers/theme/default/img/close.gif b/hugo/js/openlayers/theme/default/img/close.gif Binary files differnew file mode 100644 index 0000000..a8958de --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/close.gif diff --git a/hugo/js/openlayers/theme/default/img/drag-rectangle-off.png b/hugo/js/openlayers/theme/default/img/drag-rectangle-off.png Binary files differnew file mode 100644 index 0000000..fc6daf4 --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/drag-rectangle-off.png diff --git a/hugo/js/openlayers/theme/default/img/drag-rectangle-on.png b/hugo/js/openlayers/theme/default/img/drag-rectangle-on.png Binary files differnew file mode 100644 index 0000000..7f783ce --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/drag-rectangle-on.png diff --git a/hugo/js/openlayers/theme/default/img/draw_line_off.png b/hugo/js/openlayers/theme/default/img/draw_line_off.png Binary files differnew file mode 100644 index 0000000..7f15612 --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/draw_line_off.png diff --git a/hugo/js/openlayers/theme/default/img/draw_line_on.png b/hugo/js/openlayers/theme/default/img/draw_line_on.png Binary files differnew file mode 100644 index 0000000..ba09186 --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/draw_line_on.png diff --git a/hugo/js/openlayers/theme/default/img/draw_point_off.png b/hugo/js/openlayers/theme/default/img/draw_point_off.png Binary files differnew file mode 100644 index 0000000..fde94bd --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/draw_point_off.png diff --git a/hugo/js/openlayers/theme/default/img/draw_point_on.png b/hugo/js/openlayers/theme/default/img/draw_point_on.png Binary files differnew file mode 100644 index 0000000..8804221 --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/draw_point_on.png diff --git a/hugo/js/openlayers/theme/default/img/draw_polygon_off.png b/hugo/js/openlayers/theme/default/img/draw_polygon_off.png Binary files differnew file mode 100644 index 0000000..53ce9d7 --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/draw_polygon_off.png diff --git a/hugo/js/openlayers/theme/default/img/draw_polygon_on.png b/hugo/js/openlayers/theme/default/img/draw_polygon_on.png Binary files differnew file mode 100644 index 0000000..2a33376 --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/draw_polygon_on.png diff --git a/hugo/js/openlayers/theme/default/img/editing_tool_bar.png b/hugo/js/openlayers/theme/default/img/editing_tool_bar.png Binary files differnew file mode 100644 index 0000000..464340e --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/editing_tool_bar.png diff --git a/hugo/js/openlayers/theme/default/img/move_feature_off.png b/hugo/js/openlayers/theme/default/img/move_feature_off.png Binary files differnew file mode 100644 index 0000000..9f588db --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/move_feature_off.png diff --git a/hugo/js/openlayers/theme/default/img/move_feature_on.png b/hugo/js/openlayers/theme/default/img/move_feature_on.png Binary files differnew file mode 100644 index 0000000..072f066 --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/move_feature_on.png diff --git a/hugo/js/openlayers/theme/default/img/navigation_history.png b/hugo/js/openlayers/theme/default/img/navigation_history.png Binary files differnew file mode 100644 index 0000000..053d1e0 --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/navigation_history.png diff --git a/hugo/js/openlayers/theme/default/img/overview_replacement.gif b/hugo/js/openlayers/theme/default/img/overview_replacement.gif Binary files differnew file mode 100644 index 0000000..a82cf5f --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/overview_replacement.gif diff --git a/hugo/js/openlayers/theme/default/img/pan-panel-NOALPHA.png b/hugo/js/openlayers/theme/default/img/pan-panel-NOALPHA.png Binary files differnew file mode 100644 index 0000000..2740d8b --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/pan-panel-NOALPHA.png diff --git a/hugo/js/openlayers/theme/default/img/pan-panel.png b/hugo/js/openlayers/theme/default/img/pan-panel.png Binary files differnew file mode 100644 index 0000000..9910121 --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/pan-panel.png diff --git a/hugo/js/openlayers/theme/default/img/pan_off.png b/hugo/js/openlayers/theme/default/img/pan_off.png Binary files differnew file mode 100644 index 0000000..30b2aed --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/pan_off.png diff --git a/hugo/js/openlayers/theme/default/img/pan_on.png b/hugo/js/openlayers/theme/default/img/pan_on.png Binary files differnew file mode 100644 index 0000000..d73e7dd --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/pan_on.png diff --git a/hugo/js/openlayers/theme/default/img/panning-hand-off.png b/hugo/js/openlayers/theme/default/img/panning-hand-off.png Binary files differnew file mode 100644 index 0000000..4c912ac --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/panning-hand-off.png diff --git a/hugo/js/openlayers/theme/default/img/panning-hand-on.png b/hugo/js/openlayers/theme/default/img/panning-hand-on.png Binary files differnew file mode 100644 index 0000000..6094c64 --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/panning-hand-on.png diff --git a/hugo/js/openlayers/theme/default/img/remove_point_off.png b/hugo/js/openlayers/theme/default/img/remove_point_off.png Binary files differnew file mode 100644 index 0000000..76c8606 --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/remove_point_off.png diff --git a/hugo/js/openlayers/theme/default/img/remove_point_on.png b/hugo/js/openlayers/theme/default/img/remove_point_on.png Binary files differnew file mode 100644 index 0000000..0ff28fc --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/remove_point_on.png diff --git a/hugo/js/openlayers/theme/default/img/ruler.png b/hugo/js/openlayers/theme/default/img/ruler.png Binary files differnew file mode 100644 index 0000000..aa4883b --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/ruler.png diff --git a/hugo/js/openlayers/theme/default/img/save_features_off.png b/hugo/js/openlayers/theme/default/img/save_features_off.png Binary files differnew file mode 100644 index 0000000..2bf2906 --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/save_features_off.png diff --git a/hugo/js/openlayers/theme/default/img/save_features_on.png b/hugo/js/openlayers/theme/default/img/save_features_on.png Binary files differnew file mode 100644 index 0000000..93c8f08 --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/save_features_on.png diff --git a/hugo/js/openlayers/theme/default/img/view_next_off.png b/hugo/js/openlayers/theme/default/img/view_next_off.png Binary files differnew file mode 100644 index 0000000..23c5ac1 --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/view_next_off.png diff --git a/hugo/js/openlayers/theme/default/img/view_next_on.png b/hugo/js/openlayers/theme/default/img/view_next_on.png Binary files differnew file mode 100644 index 0000000..e41fb7b --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/view_next_on.png diff --git a/hugo/js/openlayers/theme/default/img/view_previous_off.png b/hugo/js/openlayers/theme/default/img/view_previous_off.png Binary files differnew file mode 100644 index 0000000..b9c230f --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/view_previous_off.png diff --git a/hugo/js/openlayers/theme/default/img/view_previous_on.png b/hugo/js/openlayers/theme/default/img/view_previous_on.png Binary files differnew file mode 100644 index 0000000..c009c25 --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/view_previous_on.png diff --git a/hugo/js/openlayers/theme/default/img/zoom-panel-NOALPHA.png b/hugo/js/openlayers/theme/default/img/zoom-panel-NOALPHA.png Binary files differnew file mode 100644 index 0000000..cdde6fc --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/zoom-panel-NOALPHA.png diff --git a/hugo/js/openlayers/theme/default/img/zoom-panel.png b/hugo/js/openlayers/theme/default/img/zoom-panel.png Binary files differnew file mode 100644 index 0000000..f2c7c51 --- /dev/null +++ b/hugo/js/openlayers/theme/default/img/zoom-panel.png diff --git a/hugo/js/openlayers/theme/default/style.css b/hugo/js/openlayers/theme/default/style.css new file mode 100644 index 0000000..0627f0e --- /dev/null +++ b/hugo/js/openlayers/theme/default/style.css @@ -0,0 +1,397 @@ +div.olMap { + z-index: 0; + padding: 0px!important; + margin: 0px!important; + cursor: default; +} + +div.olMapViewport { + text-align: left; +} + +div.olLayerDiv { + -moz-user-select: none; +} + +.olLayerGoogleCopyright { + left: 2px; + bottom: 2px; +} +.olLayerGooglePoweredBy { + left: 2px; + bottom: 15px; +} +.olControlAttribution { + font-size: smaller; + right: 3px; + bottom: 4.5em; + position: absolute; + display: block; +} +.olControlScale { + right: 3px; + bottom: 3em; + display: block; + position: absolute; + font-size: smaller; +} +.olControlScaleLine { + display: block; + position: absolute; + left: 10px; + bottom: 15px; + font-size: xx-small; +} +.olControlScaleLineBottom { + border: solid 2px black; + border-bottom: none; + margin-top:-2px; + text-align: center; +} +.olControlScaleLineTop { + border: solid 2px black; + border-top: none; + text-align: center; +} + +.olControlPermalink { + right: 3px; + bottom: 1.5em; + display: block; + position: absolute; + font-size: smaller; +} + +div.olControlMousePosition { + bottom: 0em; + right: 3px; + display: block; + position: absolute; + font-family: Arial; + font-size: smaller; +} + +.olControlOverviewMapContainer { + position: absolute; + bottom: 0px; + right: 0px; +} + +.olControlOverviewMapElement { + padding: 10px 18px 10px 10px; + background-color: #00008B; + -moz-border-radius: 1em 0 0 0; +} + +.olControlOverviewMapMinimizeButton { + right: 0px; + bottom: 80px; +} + +.olControlOverviewMapMaximizeButton { + right: 0px; + bottom: 80px; +} + +.olControlOverviewMapExtentRectangle { + overflow: hidden; + background-image: url("img/blank.gif"); + cursor: move; + border: 2px dotted red; +} +.olControlOverviewMapRectReplacement { + overflow: hidden; + cursor: move; + background-image: url("img/overview_replacement.gif"); + background-repeat: no-repeat; + background-position: center; +} + +.olLayerGeoRSSDescription { + float:left; + width:100%; + overflow:auto; + font-size:1.0em; +} +.olLayerGeoRSSClose { + float:right; + color:gray; + font-size:1.2em; + margin-right:6px; + font-family:sans-serif; +} +.olLayerGeoRSSTitle { + float:left;font-size:1.2em; +} + +.olPopupContent { + padding:5px; + overflow: auto; +} +.olControlNavToolbar { + width:0px; + height:0px; +} +.olControlNavToolbar div { + display:block; + width: 28px; + height: 28px; + top: 300px; + left: 6px; + position: relative; +} + +.olControlNavigationHistory { + background-image: url("img/navigation_history.png"); + background-repeat: no-repeat; + width: 24px; + height: 24px; + +} +.olControlNavigationHistoryPreviousItemActive { + background-position: 0px 0px; +} +.olControlNavigationHistoryPreviousItemInactive { + background-position: 0px -24px; +} +.olControlNavigationHistoryNextItemActive { + background-position: -24px 0px; +} +.olControlNavigationHistoryNextItemInactive { + background-position: -24px -24px; +} + +.olControlNavToolbar .olControlNavigationItemActive { + background-image: url("img/panning-hand-on.png"); + background-repeat: no-repeat; +} +.olControlNavToolbar .olControlNavigationItemInactive { + background-image: url("img/panning-hand-off.png"); + background-repeat: no-repeat; +} +.olControlNavToolbar .olControlZoomBoxItemActive { + background-image: url("img/drag-rectangle-on.png"); + background-color: orange; + background-repeat: no-repeat; +} +.olControlNavToolbar .olControlZoomBoxItemInactive { + background-image: url("img/drag-rectangle-off.png"); + background-repeat: no-repeat; +} +.olControlEditingToolbar { + float:right; + right: 0px; + height: 30px; + width: 200px; +} +.olControlEditingToolbar div { + background-image: url("img/editing_tool_bar.png"); + background-repeat: no-repeat; + float:right; + width: 24px; + height: 24px; + margin: 5px; +} +.olControlEditingToolbar .olControlNavigationItemActive { + background-position: -103px -23px; +} +.olControlEditingToolbar .olControlNavigationItemInactive { + background-position: -103px -0px; +} +.olControlEditingToolbar .olControlDrawFeaturePointItemActive { + background-position: -77px -23px; +} +.olControlEditingToolbar .olControlDrawFeaturePointItemInactive { + background-position: -77px -0px; +} +.olControlEditingToolbar .olControlDrawFeaturePathItemInactive { + background-position: -51px 0px; +} +.olControlEditingToolbar .olControlDrawFeaturePathItemActive { + background-position: -51px -23px; +} +.olControlEditingToolbar .olControlDrawFeaturePolygonItemInactive { + background-position: -26px 0px; +} +.olControlEditingToolbar .olControlDrawFeaturePolygonItemActive { + background-position: -26px -23px ; +} +div.olControlSaveFeaturesItemActive { + background-image: url(img/save_features_on.png); + background-repeat: no-repeat; + background-position: 0px 1px; +} +div.olControlSaveFeaturesItemInactive { + background-image: url(img/save_features_off.png); + background-repeat: no-repeat; + background-position: 0px 1px; +} + +.olHandlerBoxZoomBox { + border: 2px solid red; + position: absolute; + background-color: white; + opacity: 0.50; + font-size: 1px; + filter: alpha(opacity=50); +} +.olHandlerBoxSelectFeature { + border: 2px solid blue; + position: absolute; + background-color: white; + opacity: 0.50; + font-size: 1px; + filter: alpha(opacity=50); +} + +.olControlPanPanel { + top: 10px; + left: 5px; +} + +.olControlPanPanel div { + background-image: url(img/pan-panel.png); + height: 18px; + width: 18px; + cursor: pointer; + position: absolute; +} + +.olControlPanPanel .olControlPanNorthItemInactive { + top: 0px; + left: 9px; + background-position: 0px 0px; +} +.olControlPanPanel .olControlPanSouthItemInactive { + top: 36px; + left: 9px; + background-position: 18px 0px; +} +.olControlPanPanel .olControlPanWestItemInactive { + position: absolute; + top: 18px; + left: 0px; + background-position: 0px 18px; +} +.olControlPanPanel .olControlPanEastItemInactive { + top: 18px; + left: 18px; + background-position: 18px 18px; +} + +.olControlZoomPanel { + top: 71px; + left: 14px; +} + +.olControlZoomPanel div { + background-image: url(img/zoom-panel.png); + position: absolute; + height: 18px; + width: 18px; + cursor: pointer; +} + +.olControlZoomPanel .olControlZoomInItemInactive { + top: 0px; + left: 0px; + background-position: 0px 0px; +} + +.olControlZoomPanel .olControlZoomToMaxExtentItemInactive { + top: 18px; + left: 0px; + background-position: 0px -18px; +} + +.olControlZoomPanel .olControlZoomOutItemInactive { + top: 36px; + left: 0px; + background-position: 0px 18px; +} + +.olPopupCloseBox { + background: url("img/close.gif") no-repeat; + cursor: pointer; +} + +.olFramedCloudPopupContent { + padding: 5px; + overflow: auto; +} + +.olControlNoSelect { + -moz-user-select: none; +} + +.olImageLoadError { + background-color: pink; + opacity: 0.5; + filter: alpha(opacity=50); /* IE */ +} + +/** + * Cursor styles + */ + +.olCursorWait { + cursor: wait; +} +.olDragDown { + cursor: move; +} +.olDrawBox { + cursor: crosshair; +} +.olControlDragFeatureOver { + cursor: move; +} +.olControlDragFeatureActive.olControlDragFeatureOver.olDragDown { + cursor: -moz-grabbing; +} + +/** + * Layer switcher + */ +.olControlLayerSwitcher { + position: absolute; + top: 25px; + right: 0px; + width: 20em; + font-family: sans-serif; + font-weight: bold; + margin-top: 3px; + margin-left: 3px; + margin-bottom: 3px; + font-size: smaller; + color: white; + background-color: transparent; +} + +.olControlLayerSwitcher .layersDiv { + padding-top: 5px; + padding-left: 10px; + padding-bottom: 5px; + padding-right: 75px; + background-color: darkblue; + width: 100%; + height: 100%; +} + +.olControlLayerSwitcher .layersDiv .baseLbl, +.olControlLayerSwitcher .layersDiv .dataLbl { + margin-top: 3px; + margin-left: 3px; + margin-bottom: 3px; +} + +.olControlLayerSwitcher .layersDiv .baseLayersDiv, +.olControlLayerSwitcher .layersDiv .dataLayersDiv { + padding-left: 10px; +} + +.olControlLayerSwitcher .maximizeDiv, +.olControlLayerSwitcher .minimizeDiv { + top: 5px; + right: 0px; +} diff --git a/hugo/js/pmd/ajax.js b/hugo/js/pmd/ajax.js new file mode 100644 index 0000000..766c3dd --- /dev/null +++ b/hugo/js/pmd/ajax.js @@ -0,0 +1,60 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * + * @package PhpMyAdmin-Designer + */ + +/** + * + */ +function makeRequest(url, parameters) +{ + var $msg = PMA_ajaxShowMessage(); + $.post(url, parameters, function (data) { + PMA_ajaxRemoveMessage($msg); + PrintXML(data); + }); + return true; +} + +/** + * + */ +function PrintXML(data) +{ + var $root = $(data).find('root'); + if ($root.length == 0) { + // error + var myWin=window.open('','Report','width=400, height=250, resizable=1, scrollbars=1, status=1'); + var tmp = myWin.document; + tmp.write(data); + tmp.close(); + } else { + // success + if ($root.attr('act') == 'save_pos') { + PMA_ajaxShowMessage($root.attr('return')); + } else if ($root.attr('act') == 'relation_upd') { + PMA_ajaxShowMessage($root.attr('return')); + if ($root.attr('b') == '1') { + contr.splice($root.attr('K'), 1); + Re_load(); + } + } else if ($root.attr('act') == 'relation_new') { + PMA_ajaxShowMessage($root.attr('return')); + if ($root.attr('b') == '1') { + var i = contr.length; + var t1 = $root.attr('DB1') + '.' + $root.attr('T1'); + var f1 = $root.attr('F1'); + var t2 = $root.attr('DB2') + '.' + $root.attr('T2'); + var f2 = $root.attr('F2'); + contr[i] = []; + contr[i][''] = []; + contr[i][''][t2] = []; + contr[i][''][t2][f2] = []; + contr[i][''][t2][f2][0] = t1; + contr[i][''][t2][f2][1] = f1; + Re_load(); + } + } + } +} diff --git a/hugo/js/pmd/history.js b/hugo/js/pmd/history.js new file mode 100644 index 0000000..3df4746 --- /dev/null +++ b/hugo/js/pmd/history.js @@ -0,0 +1,784 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * @fileoverview function used in this file builds history tab and generates query. + * + * @requires jQuery + * @requires moves.js + * @version $Id$ + */ + +var history_array = []; // Global array to store history objects +var select_field = []; // Global array to store informaation for columns which are used in select clause +var g_index; + +/** + * function for panel, hides and shows toggle_container <div>,which is for history elements uses {@link JQuery}. + * + * @param index has value 1 or 0,decides wheter to hide toggle_container on load. +**/ + +function panel(index) +{ + if (!index) { + $(".toggle_container").hide(); + } + $("h2.tiger").click(function() { + $(this).toggleClass("active").next().slideToggle("slow"); + }); +} + +/** + * Sorts history_array[] first,using table name as the key and then generates the HTML code for history tab, + * clubbing all objects of same tables together + * This function is called whenever changes are made in history_array[] + * + * + * @param {int} init starting index of unsorted array + * @param {int} finit last index of unsorted array + * +**/ + +function display(init,finit) +{ + var str,i,j,k,sto; + // this part sorts the history array based on table name,this is needed for clubbing all object of same name together. + for (i = init; i < finit; i++) { + sto = history_array[i]; + var temp = history_array[i].get_tab() ;//+ '.' + history_array[i].get_obj_no(); for Self JOINS + for (j = 0; j < i; j++) { + if (temp > (history_array[j].get_tab())) {//+ '.' + history_array[j].get_obj_no())) { //for Self JOINS + for (k = i; k > j; k--) { + history_array[k] = history_array[k-1]; + } + history_array[j] = sto; + break; + } + } + } + // this part generates HTML code for history tab.adds delete,edit,and/or and detail features with objects. + str =''; // string to store Html code for history tab + for (var i=0; i < history_array.length; i++) { + var temp = history_array[i].get_tab(); //+ '.' + history_array[i].get_obj_no(); for Self JOIN + str += '<h2 class="tiger"><a href="#">' + temp + '</a></h2>'; + str += '<div class="toggle_container">\n'; + while ((history_array[i].get_tab()) == temp) { //+ '.' + history_array[i].get_obj_no()) == temp) { + str +='<div class="block"> <table width ="250">'; + str += '<thead><tr><td>'; + if (history_array[i].get_and_or()) { + str +='<img src="' + pmaThemeImage + 'pmd/or_icon.png" onclick="and_or('+i+')" title="OR"/></td>'; + } else { + str +='<img src="' + pmaThemeImage + 'pmd/and_icon.png" onclick="and_or('+i+')" title="AND"/></td>'; + } + str +='<td style="padding-left: 5px;" class="right">' + PMA_getImage('b_sbrowse.png', 'column name') + '</td><td width="175" style="padding-left: 5px">' + history_array[i].get_column_name(); + if (history_array[i].get_type() == "GroupBy" || history_array[i].get_type() == "OrderBy") { + str += '</td><td class="center">' + PMA_getImage('b_info.png', detail(i)) + '<td title="' + detail(i) +'">' + history_array[i].get_type() + '</td></td><td onmouseover="this.className=\'history_table\';" onmouseout="this.className=\'history_table2\'" onclick=history_delete('+ i +')>' + PMA_getImage('b_drop.png', 'Delete') + '</td></tr></thead>'; + } else { + str += '</td><td class="center">' + PMA_getImage('b_info.png', detail(i)) + '</td><td title="' + detail(i) +'">' + history_array[i]. get_type() + '</td><td <td onmouseover="this.className=\'history_table\';" onmouseout="this.className=\'history_table2\'" onclick=history_edit('+ i +')>' + PMA_getImage('b_edit.png', PMA_messages['strEdit']) + '</td><td onmouseover="this.className=\'history_table\';" onmouseout="this.className=\'history_table2\'" onclick=history_delete('+ i +')><img src="themes/original/img/b_drop.png" title="Delete"></td></tr></thead>'; + } + i++; + if (i >= history_array.length) { + break; + } + str += '</table></div><br/>'; + } + i--; + str += '</div><br/>'; + } + return str; +} + +/** + * To change And/Or relation in history tab + * + * + * @param {int} index of history_array where change is to be made + * +**/ + +function and_or(index) +{ + if (history_array[index].get_and_or()) { + history_array[index].set_and_or(0); + } else { + history_array[index].set_and_or(1); + } + var existingDiv = document.getElementById('ab'); + existingDiv.innerHTML = display(0,0); + panel(1); +} + +/** + * To display details of obects(where,rename,Having,aggregate,groupby,orderby,having) + * + * @param index index of history_array where change is to be made + * +**/ + +function detail (index) +{ + var type = history_array[index].get_type(); + var str; + if (type == "Where") { + str = 'Where ' + history_array[index].get_column_name() + history_array[index].get_obj().getrelation_operator() + history_array[index].get_obj().getquery(); + } + if (type == "Rename") { + str = 'Rename ' + history_array[index].get_column_name() + ' To ' + history_array[index].get_obj().getrename_to(); + } + if (type == "Aggregate") { + str = 'Select ' + history_array[index].get_obj().get_operator() + '( ' + history_array[index].get_column_name() + ' )'; + } + if (type == "GroupBy") { + str = 'GroupBy ' + history_array[index].get_column_name() ; + } + if (type == "OrderBy") { + str = 'OrderBy ' + history_array[index].get_column_name() ; + } + if (type == "Having") { + str = 'Having '; + if (history_array[index].get_obj().get_operator() != 'None') { + str += history_array[index].get_obj().get_operator() + '( ' + history_array[index].get_column_name() + ' )'; + str += history_array[index].get_obj().getrelation_operator() + history_array[index].get_obj().getquery(); + } else { + str = 'Having ' + history_array[index].get_column_name() + history_array[index].get_obj().getrelation_operator() + history_array[index].get_obj().getquery(); + } + } + return str; +} + +/** + * Deletes entry in history_array + * + * @param index index of history_array[] which is to be deleted + * +**/ + +function history_delete(index) +{ + for (var k = 0; k < from_array.length; k++) { + if (from_array[k] == history_array[index].get_tab()) { + from_array.splice(k,1); + break; + } + } + history_array.splice(index,1); + var existingDiv = document.getElementById('ab'); + existingDiv.innerHTML = display(0,0); + panel(1); +} + +/** + * To show where,rename,aggregate,having forms to edit a object + * + * @param{int} index index of history_array where change is to be made + * +**/ + +function history_edit(index) +{ + g_index = index; + var type = history_array[index].get_type(); + if (type == "Where") { + document.getElementById('eQuery').value = history_array[index].get_obj().getquery(); + document.getElementById('erel_opt').value = history_array[index].get_obj().getrelation_operator(); + document.getElementById('query_where').style.left = '530px'; + document.getElementById('query_where').style.top = '130px'; + document.getElementById('query_where').style.position = 'absolute'; + document.getElementById('query_where').style.zIndex = '9'; + document.getElementById('query_where').style.visibility = 'visible'; + } + if (type == "Having") { + document.getElementById('hQuery').value = history_array[index].get_obj().getquery(); + document.getElementById('hrel_opt').value = history_array[index].get_obj().getrelation_operator(); + document.getElementById('hoperator').value = history_array[index].get_obj().get_operator(); + document.getElementById('query_having').style.left = '530px'; + document.getElementById('query_having').style.top = '130px'; + document.getElementById('query_having').style.position = 'absolute'; + document.getElementById('query_having').style.zIndex = '9'; + document.getElementById('query_having').style.visibility = 'visible'; + } + if (type == "Rename") { + document.getElementById('query_rename_to').style.left = '530px'; + document.getElementById('query_rename_to').style.top = '130px'; + document.getElementById('query_rename_to').style.position = 'absolute'; + document.getElementById('query_rename_to').style.zIndex = '9'; + document.getElementById('query_rename_to').style.visibility = 'visible'; + } + if (type == "Aggregate") { + document.getElementById('query_Aggregate').style.left = '530px'; + document.getElementById('query_Aggregate').style.top = '130px'; + document.getElementById('query_Aggregate').style.position = 'absolute'; + document.getElementById('query_Aggregate').style.zIndex = '9'; + document.getElementById('query_Aggregate').style.visibility = 'visible'; + } +} + +/** + * Make changes in history_array when Edit button is clicked + * checks for the type of object and then sets the new value + * + * @param index index of history_array where change is to be made +**/ + +function edit(type) +{ + if (type == "Rename") { + if (document.getElementById('e_rename').value != "") { + history_array[g_index].get_obj().setrename_to(document.getElementById('e_rename').value); + document.getElementById('e_rename').value = ""; + } + document.getElementById('query_rename_to').style.visibility = 'hidden'; + } + if (type == "Aggregate") { + if (document.getElementById('e_operator').value != '---') { + history_array[g_index].get_obj().set_operator(document.getElementById('e_operator').value); + document.getElementById('e_operator').value = '---'; + } + document.getElementById('query_Aggregate').style.visibility = 'hidden'; + } + if (type == "Where") { + if (document.getElementById('erel_opt').value != '--' && document.getElementById('eQuery').value !="") { + history_array[g_index].get_obj().setquery(document.getElementById('eQuery').value); + history_array[g_index].get_obj().setrelation_operator(document.getElementById('erel_opt').value); + } + document.getElementById('query_where').style.visibility = 'hidden'; + } + if (type == "Having") { + if (document.getElementById('hrel_opt').value != '--' && document.getElementById('hQuery').value !="") { + history_array[g_index].get_obj().setquery(document.getElementById('hQuery').value); + history_array[g_index].get_obj().setrelation_operator(document.getElementById('hrel_opt').value); + history_array[g_index].get_obj().set_operator(document.getElementById('hoperator').value); + } + document.getElementById('query_having').style.visibility = 'hidden'; + } + var existingDiv = document.getElementById('ab'); + existingDiv.innerHTML = display(0,0); + panel(1); +} + +/** + * history object closure + * + * @param ncolumn_name name of the column on which conditions are put + * @param nobj object details(where,rename,orderby,groupby,aggregate) + * @param ntab table name of the column on which conditions are applied + * @param nobj_no object no used for inner join + * @param ntype type of object + * +**/ + +function history(ncolumn_name,nobj,ntab,nobj_no,ntype) +{ + var and_or; + var obj; + var tab; + var column_name; + var obj_no; + var type; + this.set_column_name = function (ncolumn_name) { + column_name = ncolumn_name; + }; + this.get_column_name = function() { + return column_name; + }; + this.set_and_or = function(nand_or) { + and_or = nand_or; + }; + this.get_and_or = function() { + return and_or; + }; + this.get_relation = function() { + return and_or; + }; + this.set_obj = function(nobj) { + obj = nobj; + }; + this.get_obj = function() { + return obj; + }; + this.set_tab = function(ntab) { + tab = ntab; + }; + this.get_tab = function() { + return tab; + }; + this.set_obj_no = function(nobj_no) { + obj_no = nobj_no; + }; + this.get_obj_no = function() { + return obj_no; + }; + this.set_type = function(ntype) { + type = ntype; + }; + this.get_type = function() { + return type; + }; + this.set_obj_no(nobj_no); + this.set_tab(ntab); + this.set_and_or(0); + this.set_obj(nobj); + this.set_column_name(ncolumn_name); + this.set_type(ntype); +} + +/** + * where object closure, makes an object with all information of where + * + * @param nrelation_operator type of relation operator to be applied + * @param nquery stores value of value/sub-query + * +**/ + + +var where = function (nrelation_operator,nquery) { + var relation_operator; + var query; + this.setrelation_operator = function(nrelation_operator) { + relation_operator = nrelation_operator; + }; + this.setquery = function(nquery) { + query = nquery; + }; + this.getquery = function() { + return query; + }; + this.getrelation_operator = function() { + return relation_operator; + }; + this.setquery(nquery); + this.setrelation_operator(nrelation_operator); +}; + + +/** + * Having object closure, makes an object with all information of where + * + * @param nrelation_operator type of relation operator to be applied + * @param nquery stores value of value/sub-query + * +**/ + +var having = function (nrelation_operator,nquery,noperator) { + var relation_operator; + var query; + var operator; + this.set_operator = function(noperator) { + operator = noperator; + }; + this.setrelation_operator = function(nrelation_operator) { + relation_operator = nrelation_operator; + }; + this.setquery = function(nquery) { + query = nquery; + }; + this.getquery = function() { + return query; + }; + this.getrelation_operator = function() { + return relation_operator; + }; + this.get_operator = function() { + return operator; + }; + this.setquery(nquery); + this.setrelation_operator(nrelation_operator); + this.set_operator(noperator); +}; + +/** + * rename object closure,makes an object with all information of rename + * + * @param nrename_to new name information + * +**/ + +var rename = function(nrename_to) { + var rename_to; + this.setrename_to = function(nrename_to) { + rename_to = nrename_to; + }; + this.getrename_to =function() { + return rename_to; + }; + this.setrename_to(nrename_to); +}; + +/** + * aggregate object closure + * + * @param noperator aggregte operator + * +**/ + +var aggregate = function(noperator) { + var operator; + this.set_operator = function(noperator) { + operator = noperator; + }; + this.get_operator = function() { + return operator; + }; + this.set_operator(noperator); +}; + +/** + * This function returns unique element from an array + * + * @param arraName array from which duplicate elem are to be removed. + * @return unique array + */ + +function unique(arrayName) +{ + var newArray=[]; + label:for (var i=0; i<arrayName.length; i++ ) + { + for (var j=0; j<newArray.length; j++ ) + { + if (newArray[j]==arrayName[i]) { + continue label; + } + } + newArray[newArray.length] = arrayName[i]; + } + return newArray; +} + +/** + * This function takes in array and a value as input and returns 1 if values is present in array + * else returns -1 + * + * @param arrayName array + * @param value value which is to be searched in the array + */ + +function found(arrayName,value) +{ + for (var i=0; i<arrayName.length; i++) { + if (arrayName[i] == value) { return 1;} + } + return -1; +} + +/** + * This function is the main function for query building. + * uses history object details for this. + * + * @ uses query_where() + * @ uses query_groupby() + * @ uses query_having() + * @ uses query_orderby() + * + * @param formtitle title for the form + * @param fadin + */ + +function build_query(formtitle, fadin) +{ + var q_select = "SELECT "; + var temp; + for (var i = 0;i < select_field.length; i++) { + temp = check_aggregate(select_field[i]); + if (temp != "") { + q_select += temp; + temp = check_rename(select_field[i]); + q_select += temp + ","; + } else { + temp = check_rename(select_field[i]); + q_select += select_field[i] + temp +","; + } + } + q_select = q_select.substring(0,q_select.length - 1); + q_select += " FROM " + query_from(); + if (query_where() != "") { + q_select +="\n WHERE"; + q_select += query_where(); + } + if (query_groupby() != "") { q_select += "\nGROUP BY " + query_groupby(); } + if (query_having() != "") { q_select += "\nHAVING " + query_having(); } + if (query_orderby() != "") { q_select += "\nORDER BY " + query_orderby(); } + var box = document.getElementById('box'); + document.getElementById('filter').style.display='block'; + var btitle = document.getElementById('boxtitle'); + btitle.innerHTML = 'SELECT';//formtitle; + if (fadin) { + gradient("box", 0); + fadein("box"); + } else{ + box.style.display='block'; + } + document.getElementById('textSqlquery').innerHTML = q_select; +} + /** + * This function builds from clause of query + * makes automatic joins. + * + * + */ + + +function query_from() +{ + var i; + var tab_left = []; + var tab_used = []; + var t_tab_used = []; + var t_tab_left = []; + var temp; + var query = ""; + var quer = ""; + var parts = []; + var t_array = []; + t_array = from_array; + var K = 0; + var k; + var key; + var key2; + var key3; + var parts1; + for (i = 0; i < history_array.length ; i++) { + from_array.push(history_array[i].get_tab()); + } + from_array = unique( from_array ); + tab_left = from_array; + temp = tab_left.shift(); + quer = temp; + tab_used.push(temp); + // if master table (key2) matches with tab used get all keys and check if tab_left matches + // after this check if master table (key2) matches with tab left then check if any foreign matches with master . + for (i =0; i<2 ; i++) { + for (K in contr) { + for (key in contr[K]) {// contr name + for (key2 in contr[K][key]) {// table name + parts = key2.split("."); + if (found(tab_used,parts[1]) > 0) { + for (key3 in contr[K][key][key2]) { + parts1 = contr[K][key][key2][key3][0].split("."); + if (found(tab_left,parts1[1]) > 0) { + query += "\n" + 'LEFT JOIN '; + query += '`' + parts1[0] + '`.`' + parts1[1] + '` ON ' ; + query += '`' + parts[1] +'`.`' + key3 + '` = '; + query += '`' + parts1[1] + '`.`' + contr[K][key][key2][key3][1] + '` '; + t_tab_left.push(parts1[1]); + } + } + } + } + } + } + K = 0; + t_tab_left = unique (t_tab_left); + tab_used = add_array(t_tab_left,tab_used); + tab_left = remove_array(t_tab_left,tab_left); + t_tab_left = []; + for (K in contr) { + for (key in contr[K]) { + for (key2 in contr[K][key]) {// table name + parts = key2.split("."); + if (found(tab_left,parts[1]) > 0) { + for (key3 in contr[K][key][key2]) { + parts1 = contr[K][key][key2][key3][0].split("."); + if (found(tab_used,parts1[1]) > 0) { + query += "\n" + 'LEFT JOIN '; + query += '`' + parts[0] + '`.`' + parts[1] + '` ON ' ; + query += '`' + parts1[1] + '`.`' + contr[K][key][key2][key3][1] + '` = '; + query += '`' + parts[1] + '`.`' + key3 + '` '; + t_tab_left.push(parts[1]); + } + } + } + } + } + } + t_tab_left = unique (t_tab_left); + tab_used = add_array(t_tab_left,tab_used); + tab_left = remove_array(t_tab_left,tab_left); + t_tab_left = []; + } + for (k in tab_left) { + quer += " , `" + tab_left[k] + "`"; + } + query = quer + query; + from_array = t_array; + return query; +} + +/** + * This function concatenates two array + * + * @params add array elements of which are pushed in + * @params arr array in which elemnets are added + */ +function add_array(add,arr) +{ + for (var i=0; i<add.length; i++) { + arr.push(add[i]); + } + return arr; +} + +/* This fucntion removes all elements present in one array from the other. + * + * @params rem array from which each element is removed from other array. + * @params arr array from which elements are removed. + * + */ +function remove_array(rem,arr) +{ + for (var i=0; i<rem.length; i++) { + for (var j=0; j<arr.length; j++) { + if (rem[i] == arr[j]) { + arr.splice(j,1); + } + } + } + return arr; +} + +/** + * This function builds the groupby clause from history object + * + */ + +function query_groupby() +{ + var i; + var str = ""; + for (i = 0; i < history_array.length;i++) { + if (history_array[i].get_type() == "GroupBy") { str +=history_array[i].get_column_name() + ", ";} + } + str = str.substr(0,str.length -1); + return str; +} + +/** + * This function builds the Having clause from the history object. + * + */ + +function query_having() +{ + var i; + var and = "("; + for (i = 0; i < history_array.length;i++) { + if (history_array[i].get_type() == "Having") { + if (history_array[i].get_obj().get_operator() != 'None') { + and += history_array[i].get_obj().get_operator() + "(" + history_array[i].get_column_name() + " ) " + history_array[i].get_obj().getrelation_operator(); + and += " " + history_array[i].get_obj().getquery() + ", " ; + } else { + and += history_array[i].get_column_name() + " " + history_array[i].get_obj().getrelation_operator() + " " + history_array[i].get_obj().getquery() + ", "; + } + } + } + if (and =="(") { + and = "" ; + } else { + and = and.substr(0,and.length -2) + ")"; + } + return and; +} + + +/** + * This function builds the orderby clause from the history object. + * + */ + +function query_orderby() +{ + var i; + var str = "" ; + for (i = 0; i < history_array.length;i++) { + if (history_array[i].get_type() == "OrderBy") { str += history_array[i].get_column_name() + " , "; } + } + str = str.substr(0,str.length -1); + return str; +} + + +/** + * This function builds the Where clause from the history object. + * + */ + +function query_where() +{ + var i; + var and = "("; + var or = "("; + for (i = 0; i < history_array.length;i++) { + if (history_array[i].get_type() == "Where") { + if (history_array[i].get_and_or() == 0) { + and += "( " + history_array[i].get_column_name() + " " + history_array[i].get_obj().getrelation_operator() +" " + history_array[i].get_obj().getquery() + ")"; and += " AND "; + } else { + or +="( " + history_array[i].get_column_name() + " " + history_array[i].get_obj().getrelation_operator() + " " + history_array[i].get_obj().getquery() +")"; + or +=" OR " ; + } + } + } + if (or != "(") { + or = or.substring(0,(or.length - 4 )) + ")"; + } else { + or = "" ; + } + if (and !="(") { + and = and.substring(0,(and.length - 5)) + ")"; + } else { + and = "" ; + } + if (or != "" ) { + and = and + " OR " + or + " )"; + } + return and; +} + +function check_aggregate(id_this) +{ + var i; + for (i = 0;i < history_array.length;i++) { + var temp = '`' + history_array[i].get_tab() + '`.`' +history_array[i].get_column_name() +'`'; + if (temp == id_this && history_array[i].get_type() == "Aggregate") { + return history_array[i].get_obj().get_operator() + '(' + id_this +')'; + } + } + return ""; +} + +function check_rename(id_this) +{ + var i; + for (i = 0;i < history_array.length;i++) { + var temp = '`' + history_array[i].get_tab() + '`.`' +history_array[i].get_column_name() +'`'; + if (temp == id_this && history_array[i].get_type() == "Rename") { + return " AS `" + history_array[i].get_obj().getrename_to() +"`"; + } + } + return ""; +} + +function gradient(id, level) +{ + var box = document.getElementById(id); + box.style.opacity = level; + box.style.MozOpacity = level; + box.style.KhtmlOpacity = level; + box.style.filter = "alpha(opacity=" + level * 100 + ")"; + box.style.display="block"; + return; +} + + +function fadein(id) +{ + var level = 0; + while (level <= 1) { + setTimeout( "gradient('" + id + "'," + level + ")", (level* 1000) + 10); + level += 0.01; + } +} + +function closebox() +{ + document.getElementById('box').style.display='none'; + document.getElementById('filter').style.display='none'; +} diff --git a/hugo/js/pmd/iecanvas.js b/hugo/js/pmd/iecanvas.js new file mode 100644 index 0000000..90e1cae --- /dev/null +++ b/hugo/js/pmd/iecanvas.js @@ -0,0 +1,151 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * + * @package PhpMyAdmin-Designer + */ + +/** + * + */ +if (!window.all) // if IE +{ + document.attachEvent("onreadystatechange", // document load + function () { + if (document.readyState == "complete") { + var el = document.getElementById("canvas"); + var outerHTML = el.outerHTML; + var newEl = document.createElement(outerHTML); + el.parentNode.replaceChild(newEl, el); + el = newEl; + el.getContext = function () { + if (this.cont) { + return this.cont; + } + return this.cont = new PMD_2D(this); + }; + + el.style.width = el.attributes.width.nodeValue + "px"; + el.style.height = el.attributes.height.nodeValue + "px"; + } + } + ); + +//***************************************************************************************************** + + function convert_style(str) { + var m = []; + m = str.match(/.*\((\d*),(\d*),(\d*),(\d*)\)/); + for (var i = 1; i<=3; i++) { + m[i] = (m[i]*1).toString(16).length < 2 ? '0' + (m[i]*1).toString(16) : (m[i]*1).toString(16); + } + return ['#' + m[1] + m[2] + m[3], 1]; + } +//------------------------------------------------------------------------------ + function PMD_2D(th) { + this.element_ = th; + this.pmd_arr = []; + this.strokeStyle; + this.fillStyle; + this.lineWidth; + + this.closePath = function() { + this.pmd_arr.push({type: "close"}); + }; + + this.clearRect = function() { + this.element_.innerHTML = ""; + this.pmd_arr = []; + }; + + this.beginPath = function() { + this.pmd_arr = []; + }; + + this.moveTo = function(aX, aY) { + this.pmd_arr.push({type: "moveTo", x: aX, y: aY}); + }; + + this.lineTo = function(aX, aY) { + this.pmd_arr.push({type: "lineTo", x: aX, y: aY}); + }; + + this.arc = function(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise) { + if (!aClockwise) { + var t = aStartAngle; + aStartAngle = aEndAngle; + aEndAngle = t; + } + + var xStart = aX + (Math.cos(aStartAngle) * aRadius); + var yStart = aY + (Math.sin(aStartAngle) * aRadius); + + var xEnd = aX + (Math.cos(aEndAngle) * aRadius); + var yEnd = aY + (Math.sin(aEndAngle) * aRadius); + + this.pmd_arr.push({type: "arc", x: aX, y: aY, + radius: aRadius, xStart: xStart, yStart: yStart, xEnd: xEnd, yEnd: yEnd}); + }; + + this.rect = function(aX, aY, aW, aH) { + this.moveTo(aX, aY); + this.lineTo(aX + aW, aY); + this.lineTo(aX + aW, aY + aH); + this.lineTo(aX, aY + aH); + this.closePath(); + }; + + this.fillRect = function(aX, aY, aW, aH) { + this.beginPath(); + this.moveTo(aX, aY); + this.lineTo(aX + aW, aY); + this.lineTo(aX + aW, aY + aH); + this.lineTo(aX, aY + aH); + this.closePath(); + this.stroke(true); + }; + + this.stroke = function(aFill) { + var Str = []; + var a = convert_style(aFill ? this.fillStyle : this.strokeStyle); + var color = a[0]; + + Str.push('<v:shape', + ' fillcolor="', color, '"', + ' filled="', Boolean(aFill), '"', + ' style="position:absolute;width:10;height:10;"', + ' coordorigin="0 0" coordsize="10 10"', + ' stroked="', !aFill, '"', + ' strokeweight="', this.lineWidth, '"', + ' strokecolor="', color, '"', + ' path="'); + + for (var i = 0; i < this.pmd_arr.length; i++) { + var p = this.pmd_arr[i]; + + if (p.type == "moveTo") { + Str.push(" m "); + Str.push(Math.floor(p.x), ",",Math.floor(p.y)); + } else if (p.type == "lineTo") { + Str.push(" l "); + Str.push(Math.floor(p.x), ",",Math.floor(p.y)); + } else if (p.type == "close") { + Str.push(" x "); + } else if (p.type == "arc") { + Str.push(" ar "); + Str.push(Math.floor(p.x - p.radius), ",", + Math.floor(p.y - p.radius), " ", + Math.floor(p.x + p.radius), ",", + Math.floor(p.y + p.radius), " ", + Math.floor(p.xStart), ",", Math.floor(p.yStart), " ", + Math.floor(p.xEnd), ",", Math.floor(p.yEnd)); + } + } + + Str.push(' ">'); + Str.push("</v:shape>"); + + this.element_.insertAdjacentHTML("beforeEnd", Str.join("")); + this.pmd_arr = []; + } + } +} diff --git a/hugo/js/pmd/init.js b/hugo/js/pmd/init.js new file mode 100644 index 0000000..00b09b9 --- /dev/null +++ b/hugo/js/pmd/init.js @@ -0,0 +1,31 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Initialises the data required to run PMD, then fires it up. + */ + +var j_tabs, h_tabs, contr, server, db, token; + +AJAX.registerTeardown('pmd/init.js', function() { + $(".trigger").unbind('click'); +}); + +AJAX.registerOnload('pmd/init.js', function() { + $(".trigger").click(function() { + $(".panel").toggle("fast"); + $(this).toggleClass("active"); + return false; + }); + + var tables_data = $.parseJSON($("#script_tables").html()); + + j_tabs = tables_data.j_tabs; + h_tabs = tables_data.h_tabs; + contr = $.parseJSON($("#script_contr").html()); + display_field = $.parseJSON($("#script_display_field").html()); + + server = $("#script_server").html(); + db = $("#script_db").html(); + token = $("#script_token").html(); + + Main(); +}); diff --git a/hugo/js/pmd/move.js b/hugo/js/pmd/move.js new file mode 100644 index 0000000..eed06f8 --- /dev/null +++ b/hugo/js/pmd/move.js @@ -0,0 +1,1264 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * @package PhpMyAdmin-Designer + */ + +/** + * init + */ + + + var _change = 0; // variable to track any change in designer layout. + var _staying = 0; // variable to check if the user stayed after seeing the confirmation prompt. + var show_relation_lines = true; + +AJAX.registerTeardown('pmd/move.js', function() { + if ($.FullScreen.supported) { + $(document).unbind($.FullScreen.prefix + 'fullscreenchange'); + } +}); + +AJAX.registerOnload('pmd/move.js', function() { + $('#page_content').css({'margin-left': '3px'}); + $('#exitFullscreen').hide(); + if ($.FullScreen.supported) { + $(document).fullScreenChange(function() { + if (! $.FullScreen.isFullScreen()) { + $('#page_content').removeClass('content_fullscreen') + .css({'width': 'auto', 'height': 'auto'}); + $('#enterFullscreen').show(); + $('#exitFullscreen').hide(); + Top_menu_reposition($('#key_Left_Right')[0]); + } + }); + } else { + $('#enterFullscreen').hide(); + } +}); + +// Below is the function to bind onbeforeunload events with the content_frame as well as the top window. + +/* +FIXME: we can't register the beforeonload event because it will persist between pageloads + +AJAX.registerOnload('pmd/move.js', function(){ + $(window).bind('beforeunload', function() { // onbeforeunload for the frame window. + if (_change == 1 && _staying == 0) { + return PMA_messages['strLeavingDesigner']; + } else if (_change == 1 && _staying == 1) { + _staying = 0; + } + }); + $(window).unload(function() { + _change = 0; + }); + window.top.onbeforeunload = function() { // onbeforeunload for the browser main window. + if (_change == 1 && _staying == 0) { + _staying = 1; // Helps if the user stays on the page as there + setTimeout('make_zero();', 100); // is no other way of knowing whether the user stayed or not. + return PMA_messages['strLeavingDesigner']; + } + }; +});*/ + +function make_zero() { // Function called if the user stays after seeing the confirmation prompt. + _staying = 0; +} + + +var dx, dy, dy2; +var cur_click; +// update in Main() +var sm_x = 2, sm_y = 2; +var sm_s = 0; +var sm_add = 10; +var s_left = 0; +var s_right = 0; +var ON_relation = 0; +var ON_grid = 0; +var ON_display_field = 0; +// relation_style: 0 - angular 1 - direct +var ON_angular_direct = 1; +var click_field = 0; +var link_relation = ""; +var id_hint; +var canvas_width = 0; +var canvas_height = 0; +var osn_tab_width = 0; +var osn_tab_height = 0; +var height_field = 7; +var Glob_X, Glob_Y; +var timeoutID; +var layer_menu_cur_click = 0; +var step = 10; +var old_class; +var from_array = []; +var downer; + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + + +//window.captureEvents(Event.MOUSEDOWN | Event.MOUSEUP); +//---CROSS +document.onmousedown = MouseDown; +document.onmouseup = MouseUp; +document.onmousemove = MouseMove; + +var isIE = document.all && !window.opera; +var isNN = !document.all && document.getElementById; +var isN4 = document.layers; + +if (isIE) { + window.onscroll = General_scroll; + document.onselectstart = function () {return false;}; +} + +//document.onmouseup = function(){General_scroll_end();} +function MouseDown(e) +{ + var offsetx, offsety; + if (cur_click != null) { + offsetx = isIE ? event.clientX + document.body.scrollLeft : e.pageX; + offsety = isIE ? event.clientY + document.body.scrollTop : e.pageY; + dx = offsetx - parseInt(cur_click.style.left); + dy = offsety - parseInt(cur_click.style.top); + //alert(" dx = " + dx + " dy = " +dy); + document.getElementById("canvas").style.display = 'none'; + /* + var left = parseInt(cur_click.style.left); + var top = parseInt(cur_click.style.top); + dx = e.pageX - left; + dy = e.pageY - top; + + alert(" dx = " + dx + " dy = " +dy); + */ + cur_click.style.zIndex = 2; + } + if (layer_menu_cur_click) { + offsetx = e.pageX; + dx = offsetx - parseInt(document.getElementById("layer_menu").style.width); + } +} + +function MouseMove(e) +{ + //Glob_X = e.pageX; + //Glob_Y = e.pageY; + Glob_X = isIE ? event.clientX + document.body.scrollLeft : e.pageX; + Glob_Y = isIE ? event.clientY + document.body.scrollTop : e.pageY; + + //mouseX = (bw.ns4||bw.ns6)? e.pageX: bw.ie&&bw.win&&!bw.ie4? (event.clientX-2)+document.body.scrollLeft : event.clientX+document.body.scrollLeft; + //mouseY = (bw.ns4||bw.ns6)? e.pageY: bw.ie&&bw.win&&!bw.ie4? (event.clientY-2)+document.body.scrollTop : event.clientY+document.body.scrollTop; + + //window.status = "X = "+ Glob_X + " Y = "+ Glob_Y; + + if (cur_click != null) { + _change = 1; + var mGx = Glob_X - dx; + var mGy = Glob_Y - dy; + mGx = mGx > 0 ? mGx : 0; + mGy = mGy > 0 ? mGy : 0; + + if (ON_grid) { + mGx = mGx % step < step / 2 ? mGx - mGx % step : mGx - mGx % step + step; + mGy = mGy % step < step / 2 ? mGy - mGy % step : mGy - mGy % step + step; + } + + cur_click.style.left = mGx + 'px'; + cur_click.style.top = mGy + 'px'; + } + + if (ON_relation || ON_display_field) { + document.getElementById('pmd_hint').style.left = (Glob_X + 20) + 'px'; + document.getElementById('pmd_hint').style.top = (Glob_Y + 20) + 'px'; + } + + if (layer_menu_cur_click) { + document.getElementById("layer_menu").style.width = ((Glob_X - dx) >= 150 ? Glob_X - dx : 150) + 'px'; + //document.getElementById("layer_menu").style.height = Glob_Y - dy>=200?Glob_Y - dy:200; + //document.getElementById("id_scroll_tab").style.height = Glob_Y - dy2; + } +} + +function MouseUp(e) +{ + if (cur_click != null) { + document.getElementById("canvas").style.display = 'inline-block'; + Re_load(); + cur_click.style.zIndex = 1; + cur_click = null; + } + layer_menu_cur_click = 0; + //window.releaseEvents(Event.MOUSEMOVE); +} +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + + +//function ToInt(s) +//{ +// return s.substring(0,s.length-2)*1; //re = /(\d+)\w*/; newstr = str.replace(re, "$1"); +//} + +function Canvas_pos() +{ + canvas_width = document.getElementById('canvas').width = osn_tab_width - 3; + canvas_height = document.getElementById('canvas').height = osn_tab_height - 3; + + if (isIE) { + document.getElementById('canvas').style.width = ((osn_tab_width - 3)?(osn_tab_width - 3):0) + 'px'; + document.getElementById('canvas').style.height = ((osn_tab_height - 3)?(osn_tab_height - 3):0) + 'px'; + } +} + +function Osn_tab_pos() +{ + osn_tab_width = parseInt(document.getElementById('osn_tab').style.width); + osn_tab_height = parseInt(document.getElementById('osn_tab').style.height); +} + + +function Main() +{ + //alert( document.getElementById('osn_tab').offsetTop); + //---CROSS + + document.getElementById("layer_menu").style.top = -1000 + 'px'; //fast scroll + sm_x += document.getElementById('osn_tab').offsetLeft; + sm_y += document.getElementById('osn_tab').offsetTop; + Osn_tab_pos(); + Canvas_pos(); + Small_tab_refresh(); + Re_load(); + id_hint = document.getElementById('pmd_hint'); + if (isIE) { + General_scroll(); + } +} + + +//-------------------------------- new ----------------------------------------- +function Rezize_osn_tab() +{ + var max_X = 0; + var max_Y = 0; + for (var key in j_tabs) { + var k_x = parseInt(document.getElementById(key).style.left) + document.getElementById(key).offsetWidth; + var k_y = parseInt(document.getElementById(key).style.top) + document.getElementById(key).offsetHeight; + max_X = max_X < k_x ? k_x : max_X; + max_Y = max_Y < k_y ? k_y : max_Y; + } + + osn_tab_width = max_X + 50; + osn_tab_height = max_Y + 50; + Canvas_pos(); + document.getElementById('osn_tab').style.width = osn_tab_width + 'px'; + document.getElementById('osn_tab').style.height = osn_tab_height + 'px'; +} +//------------------------------------------------------------------------------ + +/** + * refreshes display, must be called after state changes + */ +function Re_load() +{ + Rezize_osn_tab(); + var n; + var x1; + var x2; + var a = []; + var K; + var key; + var key2; + var key3; + Clear(); + for (K in contr) { + for (key in contr[K]) { + // contr name + for (key2 in contr[K][key]) { + // table name + for (key3 in contr[K][key][key2]) { + // field name + if (!document.getElementById("check_vis_" + key2).checked || + !document.getElementById("check_vis_" + contr[K][key][key2][key3][0]).checked) { + // if hide + continue; + } + var x1_left = document.getElementById(key2).offsetLeft+1; + var x1_right = x1_left + document.getElementById(key2).offsetWidth; + var x2_left = document.getElementById(contr[K][key][key2][key3][0]).offsetLeft; + var x2_right = x2_left + document.getElementById(contr[K][key][key2][key3][0]).offsetWidth; + a[0] = Math.abs(x1_left - x2_left); + a[1] = Math.abs(x1_left - x2_right); + a[2] = Math.abs(x1_right - x2_left); + a[3] = Math.abs(x1_right - x2_right); + n = s_left = s_right = 0; + for (var i = 1; i < 4; i++) { + if (a[n] > a[i]) { + n = i; + } + } + if (n == 1) { + x1 = x1_left - sm_s; + x2 = x2_right + sm_s; + if (x1 < x2) { + n = 0; + } + } + if (n == 2) { + x1 = x1_right + sm_s; + x2 = x2_left - sm_s; + if (x1 > x2) { + n = 0; + } + } + if (n == 3) { + x1 = x1_right + sm_s; + x2 = x2_right + sm_s; + s_right = 1; + } + if (n == 0) { + x1 = x1_left - sm_s; + x2 = x2_left - sm_s; + s_left = 1; + } + //alert(key2 + "." + key3); + + var row_offset_top = 0; + //alert('id_tbody_' + key2); + //alert(document.getElementById('id_hide_tbody_' + key2)); + var tab_hide_button = document.getElementById('id_hide_tbody_' + key2); + + //alert(tab_hide_button.innerHTML); + if (tab_hide_button.innerHTML == 'v') { + row_offset_top = document.getElementById(key2 + "." + key3).offsetTop; + } + + var y1 = document.getElementById(key2).offsetTop + + row_offset_top + + height_field; + //alert(1); + + row_offset_top = 0; + var tab_hide_button = document.getElementById('id_hide_tbody_' + contr[K][key][key2][key3][0]); + if (tab_hide_button.innerHTML == 'v') { + row_offset_top = document.getElementById(contr[K][key][key2][key3][0] + + '.' + contr[K][key][key2][key3][1]).offsetTop; + } + + var y2 = + document.getElementById(contr[K][key][key2][key3][0]).offsetTop + + row_offset_top + + height_field; + + //alert(y1 + ' - ' + key2 + "." + key3); + Line0(x1 - sm_x, y1 - sm_y, x2 - sm_x, y2 - sm_y, getColorByTarget( contr[K][key][key2][key3][0]+'.'+contr[K][key][key2][key3][1] ) ); + } + } + } + } +} + +/** + * draws a line from x1:y1 to x2:y2 with color + */ +function Line(x1, y1, x2, y2, color_line) +{ + var canvas = document.getElementById("canvas"); + var ctx = canvas.getContext("2d"); + ctx.strokeStyle = color_line; + ctx.lineWidth = 1; + ctx.beginPath(); + ctx.moveTo(x1, y1); + ctx.lineTo(x2, y2); + ctx.stroke(); +} + +/** + * draws a relation/constraint line, whether angular or not + */ +function Line0(x1, y1, x2, y2, color_line) +{ + if (! show_relation_lines) { + return; + } + Circle(x1, y1, 3, 3, color_line); + Rect(x2 - 1, y2 - 2, 4, 4, color_line); + + if (ON_angular_direct) { + Line2(x1, y1, x2, y2, color_line); + } else { + Line3(x1, y1, x2, y2, color_line); + } +} + +/** + * draws a angualr relation/constraint line + */ +function Line2(x1, y1, x2, y2, color_line) +{ + var x1_ = x1; + var x2_ = x2; + + if (s_right) { + x1_ += sm_add; + x2_ += sm_add; + } else if (s_left) { + x1_ -= sm_add; + x2_ -= sm_add; + } else if (x1 < x2) { + x1_ += sm_add; + x2_ -= sm_add; + } else { + x1_ -= sm_add; + x2_ += sm_add; + } + + Line(x1, y1, x1_, y1, color_line); + Line(x2, y2, x2_, y2, color_line); + Line(x1_, y1, x2_, y2, color_line); +} + +/** + * draws a relation/constraint line + */ +function Line3(x1, y1, x2, y2, color_line) +{ + var x1_ = x1; + var x2_ = x2; + + if (s_right) { + if (x1 < x2) { + x1_ += x2 - x1 + sm_add; + x2_ += sm_add; + } else { + x2_ += x1 - x2 + sm_add; + x1_ += sm_add; + } + + Line(x1, y1, x1_, y1, color_line); + Line(x2, y2, x2_, y2, color_line); + Line(x1_, y1, x2_, y2, color_line); + return; + } + if (s_left) { + if (x1 < x2) { + x2_ -= x2 - x1 + sm_add; + x1_ -= sm_add; + } else { + x1_ -= x1 - x2 + sm_add; + x2_ -= sm_add; + } + + Line(x1, y1, x1_, y1, color_line); + Line(x2, y2, x2_, y2, color_line); + Line(x1_, y1, x2_, y2, color_line); + return; + } + + var x_s = (x1 + x2) / 2; + Line(x1, y1, x_s, y1, color_line); + Line(x_s, y2, x2, y2, color_line); + Line(x_s, y1, x_s, y2, color_line); +} + +function Circle(x, y, r, w, color) +{ + var ctx = document.getElementById('canvas').getContext('2d'); + ctx.beginPath(); + ctx.moveTo(x, y); + ctx.lineWidth = w; + ctx.strokeStyle = color; + ctx.arc(x, y, r, 0, 2 * Math.PI, true); + ctx.stroke(); +} + +function Clear() +{ + var canvas = document.getElementById("canvas"); + var ctx = canvas.getContext("2d"); + ctx.clearRect(0, 0, canvas_width, canvas_height); +} + +function Rect(x1, y1, w, h, color) +{ + var ctx = document.getElementById('canvas').getContext('2d'); + ctx.fillStyle = color; + ctx.fillRect(x1, y1, w, h); +} +//--------------------------- FULLSCREEN ------------------------------------- +function Enter_fullscreen() +{ + if (! $.FullScreen.isFullScreen()) { + $('#enterFullscreen').hide(); + $('#exitFullscreen').show(); + $('#page_content') + .addClass('content_fullscreen') + .css({'width': screen.width - 5, 'height': screen.height - 5}) + .requestFullScreen(); + Top_menu_reposition($('#key_Left_Right')[0]); + } +} + +function Exit_fullscreen() +{ + if ($.FullScreen.isFullScreen()) { + $.FullScreen.cancelFullScreen(); + } +} +//------------------------------ SAVE ------------------------------------------ +function Save(url) // (del?) no for pdf +{ + for (var key in j_tabs) { + document.getElementById('t_x_' + key + '_').value = parseInt(document.getElementById(key).style.left); + document.getElementById('t_y_' + key + '_').value = parseInt(document.getElementById(key).style.top); + document.getElementById('t_v_' + key + '_').value = document.getElementById('id_tbody_' + key).style.display == 'none' ? 0 : 1; + document.getElementById('t_h_' + key + '_').value = document.getElementById('check_vis_' + key).checked ? 1 : 0; + } + document.form1.action = url; + $(document.form1).submit(); +} + +function Get_url_pos() +{ + var poststr = ''; + for (var key in j_tabs) { + poststr += '&t_x[' + key + ']=' + parseInt(document.getElementById(key).style.left); + poststr += '&t_y[' + key + ']=' + parseInt(document.getElementById(key).style.top); + poststr += '&t_v[' + key + ']=' + (document.getElementById('id_tbody_' + key).style.display == 'none' ? 0 : 1); + poststr += '&t_h[' + key + ']=' + (document.getElementById('check_vis_' + key).checked ? 1 : 0); + } + return poststr; +} + +function Save2() +{ + _change = 0; + var poststr = 'IS_AJAX=1&server='+server+'&db=' + db + '&token=' + token + '&die_save_pos=1'; + poststr += Get_url_pos(); + makeRequest('pmd_save_pos.php', poststr); +} + +function Grid() +{ + if (!ON_grid) { + ON_grid = 1; + document.getElementById('grid_button').className = 'M_butt_Selected_down'; + } else { + document.getElementById('grid_button').className = 'M_butt'; + ON_grid = 0; + } +} + +function Angular_direct() +{ + if (ON_angular_direct) { + ON_angular_direct = 0; + document.getElementById('angular_direct_button').className = 'M_butt_Selected_down'; + } else { + ON_angular_direct = 1; + document.getElementById('angular_direct_button').className = 'M_butt'; + } + Re_load(); +} +//++++++++++++++++++++++++++++++ RELATION ++++++++++++++++++++++++++++++++++++++ +function Start_relation() +{ + if (ON_display_field) { + return; + } + + if (!ON_relation) { + document.getElementById('foreign_relation').style.display = ''; + ON_relation = 1; + document.getElementById('pmd_hint').innerHTML = PMA_messages['strSelectReferencedKey']; + document.getElementById('pmd_hint').style.display = 'block'; + document.getElementById('rel_button').className = 'M_butt_Selected_down'; + } else { + document.getElementById('pmd_hint').innerHTML = ""; + document.getElementById('pmd_hint').style.display = 'none'; + document.getElementById('rel_button').className = 'M_butt'; + click_field = 0; + ON_relation = 0; + } +} + +function Click_field(T, f, PK) // table field +{ + if (ON_relation) { + if (!click_field) { + //.style.display=='none' .style.display = 'none' + if (!PK) { + alert(PMA_messages['strPleaseSelectPrimaryOrUniqueKey']); + return;// 0; + }//PK + if (j_tabs[db + '.' + T] != '1') { + document.getElementById('foreign_relation').style.display = 'none'; + } + click_field = 1; + link_relation = "T1=" + T + "&F1=" + f; + document.getElementById('pmd_hint').innerHTML = PMA_messages['strSelectForeignKey']; + } else { + Start_relation(); // hidden hint... + if (j_tabs[db + '.' + T] != '1' || !PK) { + document.getElementById('foreign_relation').style.display = 'none'; + } + var left = Glob_X - (document.getElementById('layer_new_relation').offsetWidth>>1); + document.getElementById('layer_new_relation').style.left = left + 'px'; + var top = Glob_Y - document.getElementById('layer_new_relation').offsetHeight; + document.getElementById('layer_new_relation').style.top = top + 'px'; + document.getElementById('layer_new_relation').style.display = 'block'; + link_relation += '&T2=' + T + '&F2=' + f; + } + } + + if (ON_display_field) { + // if is display field + if (display_field[T] == f) { + //alert(T); + //s = '';for(k in display_field)s += k + ' = ' + display_field[k] + ',';alert(s); + old_class = 'tab_field'; + //display_field.splice(T, 1); + delete display_field[T]; + //s = '';for(k in display_field)s += k + ' = ' + display_field[k] + ', ';alert(s); + //n = 0;for(k in display_field)n++;alert(n); + } else { + old_class = 'tab_field_3'; + if (display_field[T]) { + document.getElementById('id_tr_' + T + '.' + display_field[T]).className = 'tab_field'; + //display_field.splice(T, 1); + delete display_field[T]; + } + display_field[T] = f; + } + ON_display_field = 0; + document.getElementById('pmd_hint').innerHTML = ""; + document.getElementById('pmd_hint').style.display = 'none'; + document.getElementById('display_field_button').className = 'M_butt'; + makeRequest('pmd_display_field.php', 'T=' + T + '&F=' + f + '&server=' + server + '&db=' + db + '&token=' + token); + } +} + +function New_relation() +{ + document.getElementById('layer_new_relation').style.display = 'none'; + link_relation += '&server=' + server + '&db=' + db + '&token=' + token + '&die_save_pos=0'; + link_relation += '&on_delete=' + document.getElementById('on_delete').value + '&on_update=' + document.getElementById('on_update').value; + link_relation += Get_url_pos(); + + //alert(link_relation); + makeRequest('pmd_relation_new.php', link_relation); +} + +//-------------------------- create tables ------------------------------------- + +function Start_table_new() +{ + PMA_commonParams.set('table', ''); + PMA_commonActions.refreshMain('tbl_create.php'); +} + +function Start_tab_upd(table) +{ + PMA_commonParams.set('table', table); + PMA_commonActions.refreshMain('tbl_structure.php'); +} +//--------------------------- hide tables -------------------------------------- + +function Small_tab_all(id_this) // max/min all tables +{ + if (id_this.alt == "v") { + for (var key in j_tabs) { + if (document.getElementById('id_hide_tbody_'+key).innerHTML == "v") { + Small_tab(key, 0); + } + } + id_this.alt = ">"; + id_this.src = pmaThemeImage + "pmd/rightarrow1.png"; + } else { + for (var key in j_tabs) { + if (document.getElementById('id_hide_tbody_'+key).innerHTML != "v") { + Small_tab(key, 0); + } + } + id_this.alt = "v"; + id_this.src = pmaThemeImage + "pmd/downarrow1.png"; + } + Re_load(); +} + +function Small_tab_invert() // invert max/min all tables +{ + for (var key in j_tabs) { + Small_tab(key, 0); + } + Re_load(); +} + +function Relation_lines_invert() +{ + show_relation_lines = ! show_relation_lines; + Re_load(); +} + +function Small_tab_refresh() +{ + for (var key in j_tabs) { + if(document.getElementById('id_hide_tbody_'+key).innerHTML != "v") { + Small_tab(key, 0); + Small_tab(key, 0); + } + } +} + +function Small_tab(t, re_load) +{ + var id = document.getElementById('id_tbody_' + t); + var id_this = document.getElementById('id_hide_tbody_' + t); + var id_t = document.getElementById(t); + id_t.style.width = id_t.offsetWidth + 'px'; + if (id_this.innerHTML == "v") { + //---CROSS + id.style.display = 'none'; + id_this.innerHTML = '>'; + } else { + id.style.display = ''; + id_this.innerHTML = 'v'; + } + if (re_load) { + Re_load(); + } +} +//------------------------------------------------------------------------------ +function Select_tab(t) +{ + var id_zag = document.getElementById('id_zag_' + t); + if (id_zag.className != 'tab_zag_3') { + document.getElementById('id_zag_' + t).className = 'tab_zag_2'; + } else { + document.getElementById('id_zag_' + t).className = 'tab_zag'; + } + //---------- + var id_t = document.getElementById(t); + window.scrollTo(parseInt(id_t.style.left) - 300, parseInt(id_t.style.top) - 300); + setTimeout(function(){document.getElementById('id_zag_' + t).className = 'tab_zag';}, 800); +} +//------------------------------------------------------------------------------ + +function Canvas_click(id) +{ + var n = 0; + var relation_name = 0; + var selected = 0; + var a = []; + var Key0, Key1, Key2, Key3, Key, x1, x2; + var K, key, key2, key3; + var Local_X = $.FullScreen.isFullScreen() ? Glob_X : Glob_X - document.getElementById("canvas_outer").offsetLeft; + var Local_Y = Glob_Y - document.getElementById("canvas_outer").offsetTop; + Clear(); + for (K in contr) { + for (key in contr[K]) { + for (key2 in contr[K][key]) { + for (key3 in contr[K][key][key2]) { + if (!document.getElementById("check_vis_"+key2).checked + || !document.getElementById("check_vis_"+contr[K][key][key2][key3][0]).checked) { + continue; // if hide + } + var x1_left = document.getElementById(key2).offsetLeft + 1;//document.getElementById(key2+"."+key3).offsetLeft; + var x1_right = x1_left + document.getElementById(key2).offsetWidth; + var x2_left = document.getElementById(contr[K][key][key2][key3][0]).offsetLeft;//+document.getElementById(contr[K][key2][key3][0]+"."+contr[K][key2][key3][1]).offsetLeft + var x2_right = x2_left + document.getElementById(contr[K][key][key2][key3][0]).offsetWidth; + a[0] = Math.abs(x1_left - x2_left); + a[1] = Math.abs(x1_left - x2_right); + a[2] = Math.abs(x1_right - x2_left); + a[3] = Math.abs(x1_right - x2_right); + n = s_left = s_right = 0; + for (var i = 1; i < 4; i++) { + if (a[n] > a[i]) { + n = i; + } + } + if (n == 1) { + x1 = x1_left - sm_s; + x2 = x2_right + sm_s; + if (x1 < x2) { + n = 0; + } + } + if (n == 2) { + x1 = x1_right + sm_s; + x2 = x2_left - sm_s; + if (x1 > x2) { + n = 0; + } + } + if (n == 3) { + x1 = x1_right + sm_s; + x2 = x2_right + sm_s; + s_right = 1; + } + if (n == 0) { + x1 = x1_left - sm_s; + x2 = x2_left - sm_s; + s_left = 1; + } + + var y1 = document.getElementById(key2).offsetTop + document.getElementById(key2+"."+key3).offsetTop + height_field; + var y2 = document.getElementById(contr[K][key][key2][key3][0]).offsetTop + + document.getElementById(contr[K][key][key2][key3][0]+"."+contr[K][key][key2][key3][1]).offsetTop + height_field; + if (!selected && Local_X > x1 - 10 && Local_X < x1 + 10 && Local_Y > y1 - 7 && Local_Y < y1 + 7) { + Line0(x1 - sm_x, y1 - sm_y, x2 - sm_x, y2 - sm_y, "rgba(255,0,0,1)"); + selected = 1; // Rect(x1-sm_x,y1-sm_y,10,10,"rgba(0,255,0,1)"); + relation_name = key; // + Key0 = contr[K][key][key2][key3][0]; + Key1 = contr[K][key][key2][key3][1]; + Key2 = key2; Key3 = key3; + Key = K; + } else { + Line0(x1 - sm_x, y1 - sm_y, x2 - sm_x, y2 - sm_y, getColorByTarget( contr[K][key][key2][key3][0]+'.'+contr[K][key][key2][key3][1] )); + } + } + } + } + } + if (selected) { + // select relations + //alert(Key0+' - '+Key1+' - '+Key2+' - '+Key3); + var left = Glob_X - (document.getElementById('layer_upd_relation').offsetWidth>>1); + document.getElementById('layer_upd_relation').style.left = left + 'px'; + var top = Glob_Y - document.getElementById('layer_upd_relation').offsetHeight - 10; + document.getElementById('layer_upd_relation').style.top = top + 'px'; + document.getElementById('layer_upd_relation').style.display = 'block'; + link_relation = 'T1=' + Key0 + '&F1=' + Key1 + '&T2=' + Key2 + '&F2=' + Key3 + '&K=' + Key; + } +} + +function Upd_relation() +{ + document.getElementById('layer_upd_relation').style.display = 'none'; + link_relation += '&server=' + server + '&db=' + db + '&token=' + token + '&die_save_pos=0'; + link_relation += Get_url_pos(); + makeRequest('pmd_relation_upd.php', link_relation); +} + +function VisibleTab(id, t_n) +{ + if (id.checked) { + document.getElementById(t_n).style.display = 'block'; + } else { + document.getElementById(t_n).style.display = 'none'; + } + Re_load(); +} + +function Hide_tab_all(id_this) // max/min all tables +{ + if (id_this.alt == 'v') { + id_this.alt = '>'; + id_this.src = pmaThemeImage + "pmd/rightarrow1.png"; + } else { + id_this.alt = 'v'; + id_this.src = pmaThemeImage + "pmd/downarrow1.png"; + } + var E = document.form1; + for (var i = 0; i < E.elements.length; i++) { + if (E.elements[i].type == "checkbox" && E.elements[i].id.substring(0, 10) == 'check_vis_') { + if (id_this.alt == 'v') { + E.elements[i].checked = true; + document.getElementById(E.elements[i].value).style.display = ''; + } else { + E.elements[i].checked = false; + document.getElementById(E.elements[i].value).style.display = 'none'; + } + } + } + Re_load(); +} + +function in_array_k(x, m) +{ + var b = 0; + for (var u in m) { + if (x == u) { + b=1; + break; + } + } + return b; +} + +function No_have_constr(id_this) +{ + var a = []; + var K, key, key2, key3; + for (K in contr) { + for (key in contr[K]) { + // contr name + for (key2 in contr[K][key]) { + // table name + for (key3 in contr[K][key][key2]) { + // field name + a[key2] = a[contr[K][key][key2][key3][0]] = 1; // exist constr + } + } + } + } + + if (id_this.alt == 'v') { + id_this.alt = '>'; + id_this.src = pmaThemeImage + "pmd/rightarrow2.png"; + } else { + id_this.alt = 'v'; + id_this.src = pmaThemeImage + "pmd/downarrow2.png"; + } + var E = document.form1; + for (var i = 0; i < E.elements.length; i++) { + if (E.elements[i].type == "checkbox" && E.elements[i].id.substring(0, 10) == 'check_vis_') { + if (!in_array_k(E.elements[i].value, a)) { + if (id_this.alt == 'v') { + E.elements[i].checked = true; + document.getElementById(E.elements[i].value).style.display = ''; + } else { + E.elements[i].checked = false; + document.getElementById(E.elements[i].value).style.display = 'none'; + } + } + } + } +} + +function PDF_save() +{ + // var WinPDF = + // window.open("pmd_pdf.php?token="+token+"&db="+db,"wind1", "top=200,left=200,width=200,height=100,resizable=yes,scrollbars=yes,menubar=no"); + Save('pmd_pdf.php?server=' + server + '&token=' + token + '&db=' + db); +} + +function General_scroll() +{ + /* + if (!document.getElementById('show_relation_olways').checked) { + document.getElementById("canvas").style.display = 'none'; + clearTimeout(timeoutID); + timeoutID = setTimeout(General_scroll_end, 500); + } + */ + //if (timeoutID) + clearTimeout(timeoutID); + timeoutID = setTimeout + ( + function() + { + document.getElementById('top_menu').style.left = document.body.scrollLeft + 'px'; + document.getElementById('top_menu').style.top = document.body.scrollTop + 'px'; + } + ,200 + ); +} + +/* +function General_scroll_end() +{ + document.getElementById('layer_menu').style.left = document.body.scrollLeft; + document.getElementById('layer_menu').style.top = document.body.scrollTop + document.getElementById('top_menu').offsetHeight; + if (isIE) { + document.getElementById('layer_menu').style.left = document.body.scrollLeft; + document.getElementById('layer_menu').style.top = document.body.scrollTop + document.getElementById('top_menu').offsetHeight; + } + document.getElementById("canvas").style.display = 'block'; +} +*/ + +function Show_left_menu(id_this) // max/min all tables +{ + if (id_this.alt == "v") { + var pos = $("#top_menu").offset(); + var height = $("#top_menu").height(); + document.getElementById("layer_menu").style.top = '0px'; + document.getElementById("layer_menu").style.display = 'block'; + id_this.alt = ">"; + id_this.src = pmaThemeImage + "pmd/uparrow2_m.png"; + if (isIE) { + General_scroll(); + } + } else { + document.getElementById("layer_menu").style.top = -1000 + 'px'; //fast scroll + document.getElementById("layer_menu").style.display = 'none'; + id_this.alt = "v"; + id_this.src = pmaThemeImage + "pmd/downarrow2_m.png"; + } +} +//------------------------------------------------------------------------------ +function Top_menu_right(id_this) +{ + if (id_this.alt == ">") { + moveTopMenuToRight(id_this); + id_this.alt = "<"; + id_this.src = pmaThemeImage + "pmd/2leftarrow_m.png"; + } else { + document.getElementById('top_menu').style.paddingLeft = 0; + id_this.alt = ">"; + id_this.src = pmaThemeImage + "pmd/2rightarrow_m.png"; + } +} + +function Top_menu_reposition(id_this) +{ + if (id_this.alt == "<") { + moveTopMenuToRight(id_this); + } +} + +function moveTopMenuToRight(id_this) +{ + var top_menu_width = 10; + $('#top_menu').children().each(function () { + top_menu_width += $(this).outerWidth(true); + }); + var offset = parseInt(document.getElementById('canvas_outer').offsetWidth - top_menu_width, 10); + document.getElementById('top_menu').style.paddingLeft = offset + 'px'; +} +//------------------------------------------------------------------------------ +function Start_display_field() +{ + if (ON_relation) { + return; + } + if (!ON_display_field) { + ON_display_field = 1; + document.getElementById('pmd_hint').innerHTML = PMA_messages['strChangeDisplay']; + document.getElementById('pmd_hint').style.display = 'block'; + document.getElementById('display_field_button').className = 'M_butt_Selected_down';//'#FFEE99';gray #AAAAAA + + if (isIE) { // correct for IE + document.getElementById('display_field_button').className = 'M_butt_Selected_down_IE'; + } + } else { + document.getElementById('pmd_hint').innerHTML = ""; + document.getElementById('pmd_hint').style.display = 'none'; + document.getElementById('display_field_button').className = 'M_butt'; + ON_display_field = 0; + } +} +//------------------------------------------------------------------------------ +var TargetColors = []; +function getColorByTarget( target ) +{ + var color = ''; //"rgba(0,100,150,1)"; + + for (var i in TargetColors) { + if (TargetColors[i][0]==target) { + color = TargetColors[i][1]; + break; + } + } + + + if (color.length==0) { + var i = TargetColors.length+1; + var d = i % 6; + var j = (i - d) / 6; + j = j % 4; + j++; + var color_case = new Array( + new Array(1, 0, 0), + new Array(0, 1, 0), + new Array(0, 0, 1), + new Array(1, 1, 0), + new Array(1, 0, 1), + new Array(0, 1, 1) + ); + var a = color_case[d][0]; + var b = color_case[d][1]; + var c = color_case[d][2]; + var e = (1 - (j - 1) / 6); + + var r = Math.round(a * 200 * e); + var g = Math.round(b * 200 * e); + var b = Math.round(c * 200 * e); + var color = "rgba("+r+","+g+","+b+",1)"; + + TargetColors.push( new Array(target, color) ); + + + } + + return color; +} + +function Click_option(id_this,column_name,table_name) +{ + var left = Glob_X - (document.getElementById(id_this).offsetWidth>>1); + document.getElementById(id_this).style.left = left + 'px'; + // var top = Glob_Y - document.getElementById(id_this).offsetHeight - 10; + document.getElementById(id_this).style.top = (screen.height / 4) + 'px'; + document.getElementById(id_this).style.display = 'block'; + document.getElementById('option_col_name').innerHTML = '<strong>' + PMA_messages['strAddOption'] +'"' +column_name+ '"</strong>'; + col_name = column_name; + tab_name = table_name; +} + +function Close_option() +{ + document.getElementById('pmd_optionse').style.display = 'none'; +} + +function Select_all(id_this,owner) +{ + var parent= document.form1; + downer =owner; + var i; + var k; + var tab = []; + for (i = 0; i < parent.elements.length; i++) { + if (parent.elements[i].type == "checkbox" && parent.elements[i].id.substring(0,(9 + id_this.length)) == 'select_' + id_this + '._') { + if(document.getElementById('select_all_' + id_this).checked == true) { + parent.elements[i].checked = true; + parent.elements[i].disabled = true; + var temp = '`' + id_this.substring(owner.length +1) + '`.*'; + } + else { + parent.elements[i].checked = false; + parent.elements[i].disabled = false; + } + } + } + if (document.getElementById('select_all_' + id_this).checked == true) { + select_field.push('`' + id_this.substring(owner.length +1) + '`.*'); + tab = id_this.split("."); + from_array.push(tab[1]); + } + else { + for (i =0; i < select_field.length; i++) { + if (select_field[i] == ('`' + id_this.substring(owner.length +1) + '`.*')) { + select_field.splice(i,1); + } + } + for (k =0 ;k < from_array.length; k++){ + if (from_array[k] == id_this){ + from_array.splice(k,1); + break; + } + } + } + Re_load(); +} + +function Table_onover(id_this,val,buil) +{ + if(!val) { + document.getElementById("id_zag_" + id_this).className="tab_zag_2"; + if(buil) { + document.getElementById("id_zag_" + id_this + "_2").className="tab_zag_2"; + } + } + else { + document.getElementById("id_zag_" + id_this).className="tab_zag"; + if(buil) { + document.getElementById("id_zag_" + id_this + "_2").className="tab_zag"; + } + } +} + +/* This function stores selected column information in select_field[] + * In case column is checked it add else it deletes + * + */ +function store_column(id_this,owner,col) +{ + var i; + var k; + if (document.getElementById('select_' + owner + '.' + id_this + '._' + col).checked == true) { + select_field.push('`' + id_this + '`.`' + col +'`'); + from_array.push(id_this); + } + else { + for (i = 0; i < select_field.length ;i++) { + if (select_field[i] == ('`' + id_this + '`.`' + col +'`')) { + select_field.splice(i,1); + break; + } + } + for (k = 0 ;k < from_array.length;k++){ + if(from_array[k] == id_this){ + from_array.splice(k,1); + break; + } + } + } +} + +/** + * This function builds object and adds them to history_array + * first it does a few checks on each object, then makes an object(where,rename,groupby,aggregate,orderby) + * then a new history object is made and finally all these history objects are addded to history_array[] + * +**/ + +function add_object() +{ + var rel = document.getElementById('rel_opt'); + var sum = 0; + var init = history_array.length; + if (rel.value != '--') { + if (document.getElementById('Query').value == "") { + document.getElementById('pmd_hint').innerHTML = "value/subQuery is empty" ; + document.getElementById('pmd_hint').style.display = 'block'; + return; + } + var p = document.getElementById('Query'); + var where_obj = new where(rel.value,p.value);//make where object + history_array.push(new history(col_name,where_obj,tab_name,h_tabs[downer + '.' + tab_name],"Where")); + sum = sum + 1; + rel.value = '--'; + p.value = ""; + } + if (document.getElementById('new_name').value !="") { + var rename_obj = new rename(document.getElementById('new_name').value);//make Rename object + history_array.push(new history(col_name,rename_obj,tab_name,h_tabs[downer + '.' + tab_name],"Rename")); + sum = sum + 1; + document.getElementById('new_name').value = "" ; + } + if (document.getElementById('operator').value != '---') { + var aggregate_obj = new aggregate(document.getElementById('operator').value) ; + history_array.push(new history(col_name,aggregate_obj,tab_name,h_tabs[downer + '.' + tab_name],"Aggregate")); + sum = sum + 1; + document.getElementById('operator').value = '---'; + //make aggregate operator + } + if (document.getElementById('groupby').checked == true ) { + history_array.push(new history(col_name,'GroupBy',tab_name,h_tabs[downer + '.' +tab_name],"GroupBy")); + sum = sum + 1; + document.getElementById('groupby').checked = false; + //make groupby + } + if (document.getElementById('h_rel_opt').value != '--') { + if (document.getElementById('having').value == "") { + document.getElementById('pmd_hint').innerHTML = "value/subQuery is empty" ; + document.getElementById('pmd_hint').style.display = 'block'; + return; + } + var p = document.getElementById('having'); + var where_obj = new having(document.getElementById('h_rel_opt').value,p.value,document.getElementById('h_operator').value);//make where object + history_array.push(new history(col_name,where_obj,tab_name,h_tabs[downer + '.' + tab_name],"Having")); + sum = sum + 1; + document.getElementById('h_rel_opt').value = '--'; + document.getElementById('h_operator').value = '---'; + p.value = ""; //make having + } + if (document.getElementById('orderby').checked == true) { + history_array.push(new history(col_name,'OrderBy',tab_name,h_tabs[downer + '.' + tab_name],"OrderBy")); + sum = sum + 1; + document.getElementById('orderby').checked = false; + //make orderby + } + PMA_ajaxShowMessage($.sprintf(PMA_messages['strObjectsCreated'], sum)); + //output sum new objects created + var existingDiv = document.getElementById('ab'); + existingDiv.innerHTML = display(init,history_array.length); + Close_option(); + panel(0); +} diff --git a/hugo/js/querywindow.js b/hugo/js/querywindow.js new file mode 100644 index 0000000..d10069c --- /dev/null +++ b/hugo/js/querywindow.js @@ -0,0 +1,25 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +function PMA_queryAutoCommit() +{ + var sqlqueryform = document.getElementById('sqlqueryform'); + sqlqueryform.target = window.opener.frame_content.name; + sqlqueryform.submit(); + return; +} + +function PMA_querywindowCommit(tab) +{ + var $hiddenqueryform = $('#hiddenqueryform'); + $hiddenqueryform.find("input[name='querydisplay_tab']").val(tab); + $hiddenqueryform.addClass('disableAjax').submit(); + return false; +} + +function PMA_querywindowSetFocus() +{ + $('#sqlquery').focus(); +} + +$(function () { + $('#topmenucontainer').css('padding', 0); +}); diff --git a/hugo/js/replication.js b/hugo/js/replication.js new file mode 100644 index 0000000..8c09de4 --- /dev/null +++ b/hugo/js/replication.js @@ -0,0 +1,72 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * for server_replication.php + * + */ + +var random_server_id = Math.floor(Math.random() * 10000000); +var conf_prefix = "server-id=" + random_server_id + "\nlog_bin=mysql-bin\nlog_error=mysql-bin.err\n"; + +function update_config() +{ + var conf_ignore = "binlog_ignore_db="; + var conf_do = "binlog_do_db="; + var database_list = ''; + + if ($('#db_select option:selected').size() == 0) { + $('#rep').text(conf_prefix); + } else if ($('#db_type option:selected').val() == 'all') { + $('#db_select option:selected').each(function() { + database_list += conf_ignore + $(this).val() + "\n"; + }); + $('#rep').text(conf_prefix + database_list); + } else { + $('#db_select option:selected').each(function() { + database_list += conf_do + $(this).val() + "\n"; + }); + $('#rep').text(conf_prefix + database_list); + } +} + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('replication.js', function() { + $('#db_type').unbind('change'); + $('#db_select').unbind('change'); + $('#master_status_href').unbind('click'); + $('#master_slaves_href').unbind('click'); + $('#slave_status_href').unbind('click'); + $('#slave_control_href').unbind('click'); + $('#slave_errormanagement_href').unbind('click'); + $('#slave_synchronization_href').unbind('click'); + $('#db_reset_href').unbind('click'); +}); + +AJAX.registerOnload('replication.js', function() { + $('#rep').text(conf_prefix); + $('#db_type').change(update_config); + $('#db_select').change(update_config); + + $('#master_status_href').click(function() { + $('#replication_master_section').toggle(); + }); + $('#master_slaves_href').click(function() { + $('#replication_slaves_section').toggle(); + }); + $('#slave_status_href').click(function() { + $('#replication_slave_section').toggle(); + }); + $('#slave_control_href').click(function() { + $('#slave_control_gui').toggle(); + }); + $('#slave_errormanagement_href').click(function() { + $('#slave_errormanagement_gui').toggle(); + }); + $('#slave_synchronization_href').click(function() { + $('#slave_synchronization_gui').toggle(); + }); + $('#db_reset_href').click(function() { + $('#db_select option:selected').prop('selected', false); + }); +}); diff --git a/hugo/js/rte.js b/hugo/js/rte.js new file mode 100644 index 0000000..e9863a4 --- /dev/null +++ b/hugo/js/rte.js @@ -0,0 +1,898 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * JavaScript functionality for Routines, Triggers and Events. + * + * @package PhpMyadmin + */ +/** + * @var RTE Contains all the JavaScript functionality + * for Routines, Triggers and Events + */ +var RTE = { + /** + * Construct for the object that provides the + * functionality for Routines, Triggers and Events + */ + object: function (type) { + $.extend(this, RTE.COMMON); + switch (type) { + case 'routine': + $.extend(this, RTE.ROUTINE); + break; + case 'trigger': + // nothing extra yet for triggers + break; + case 'event': + $.extend(this, RTE.EVENT); + break; + default: + break; + } + }, + /** + * @var string param_template Template for a row in the routine editor + */ + param_template: '' +}; + +/** + * @var RTE.COMMON a JavaScript namespace containing the functionality + * for Routines, Triggers and Events + * + * This namespace is extended by the functionality required + * to handle a specific item (a routine, trigger or event) + * in the relevant javascript files in this folder + */ +RTE.COMMON = { + /** + * @var $ajaxDialog Query object containing the reference to the + * dialog that contains the editor + */ + $ajaxDialog: null, + /** + * @var syntaxHiglighter Reference to the codemirror editor + */ + syntaxHiglighter: null, + /** + * @var buttonOptions Object containing options for + * the jQueryUI dialog buttons + */ + buttonOptions: {}, + /** + * Validate editor form fields. + */ + validate: function () { + /** + * @var $elm a jQuery object containing the reference + * to an element that is being validated + */ + var $elm = null; + // Common validation. At the very least the name + // and the definition must be provided for an item + $elm = $('table.rte_table').last().find('input[name=item_name]'); + if ($elm.val() === '') { + $elm.focus(); + alert(PMA_messages['strFormEmpty']); + return false; + } + $elm = $('table.rte_table').find('textarea[name=item_definition]'); + if ($elm.val() === '') { + if (this.syntaxHiglighter !== null) { + this.syntaxHiglighter.focus(); + } + else { + $('textarea[name=item_definition]').last().focus(); + } + alert(PMA_messages['strFormEmpty']); + return false; + } + // The validation has so far passed, so now + // we can validate item-specific fields. + return this.validateCustom(); + }, // end validate() + /** + * Validate custom editor form fields. + * This function can be overridden by + * other files in this folder + */ + validateCustom: function () { + return true; + }, // end validateCustom() + /** + * Execute some code after the ajax + * dialog for the ditor is shown. + * This function can be overridden by + * other files in this folder + */ + postDialogShow: function () { + // Nothing by default + }, // end postDialogShow() + + exportDialog: function ($this) { + var $msg = PMA_ajaxShowMessage(); + // Fire the ajax request straight away + $.get($this.attr('href'), {'ajax_request': true}, function (data) { + if (data.success === true) { + PMA_ajaxRemoveMessage($msg); + /** + * @var button_options Object containing options + * for jQueryUI dialog buttons + */ + var button_options = {}; + button_options[PMA_messages['strClose']] = function () { + $(this).dialog("close").remove(); + }; + /** + * Display the dialog to the user + */ + var $ajaxDialog = $('<div>' + data.message + '</div>').dialog({ + width: 500, + buttons: button_options, + title: data.title + }); + // Attach syntax highlited editor to export dialog + /** + * @var $elm jQuery object containing the reference + * to the Export textarea. + */ + var $elm = $ajaxDialog.find('textarea'); + /** + * @var opts Options to pass to the codemirror editor + */ + var opts = { + lineNumbers: true, + matchBrackets: true, + indentUnit: 4, + mode: "text/x-mysql" + }; + CodeMirror.fromTextArea($elm[0], opts); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.get() + }, // end exportDialog() + editorDialog: function (is_new, $this) { + var that = this; + /** + * @var $edit_row jQuery object containing the reference to + * the row of the the item being edited + * from the list of items + */ + var $edit_row = null; + if ($this.hasClass('edit_anchor')) { + // Remeber the row of the item being edited for later, + // so that if the edit is successful, we can replace the + // row with info about the modified item. + $edit_row = $this.parents('tr'); + } + /** + * @var $msg jQuery object containing the reference to + * the AJAX message shown to the user + */ + var $msg = PMA_ajaxShowMessage(); + $.get($this.attr('href'), {'ajax_request': true}, function (data) { + if (data.success === true) { + // We have successfully fetched the editor form + PMA_ajaxRemoveMessage($msg); + // Now define the function that is called when + // the user presses the "Go" button + that.buttonOptions[PMA_messages['strGo']] = function () { + // Move the data from the codemirror editor back to the + // textarea, where it can be used in the form submission. + if (typeof CodeMirror != 'undefined') { + that.syntaxHiglighter.save(); + } + // Validate editor and submit request, if passed. + if (that.validate()) { + /** + * @var data Form data to be sent in the AJAX request + */ + var data = $('form.rte_form').last().serialize(); + $msg = PMA_ajaxShowMessage( + PMA_messages['strProcessingRequest'] + ); + var url = $('form.rte_form').last().attr('action'); + $.post(url, data, function (data) { + if (data.success === true) { + // Item created successfully + PMA_ajaxRemoveMessage($msg); + PMA_slidingMessage(data.message); + that.$ajaxDialog.dialog('close'); + // If we are in 'edit' mode, we must + // remove the reference to the old row. + if (mode === 'edit') { + $edit_row.remove(); + } + // Sometimes, like when moving a trigger from + // a table to another one, the new row should + // not be inserted into the list. In this case + // "data.insert" will be set to false. + if (data.insert) { + // Insert the new row at the correct + // location in the list of items + /** + * @var text Contains the name of an item from + * the list that is used in comparisons + * to find the correct location where + * to insert a new row. + */ + var text = ''; + /** + * @var inserted Whether a new item has been + * inserted in the list or not + */ + var inserted = false; + $('table.data').find('tr').each(function () { + text = $(this) + .children('td') + .eq(0) + .find('strong') + .text() + .toUpperCase(); + text = $.trim(text); + if (text !== '' && text > data.name) { + $(this).before(data.new_row); + inserted = true; + return false; + } + }); + if (! inserted) { + // If we didn't manage to insert the row yet, + // it must belong at the end of the list, + // so we insert it there. + $('table.data').append(data.new_row); + } + // Fade-in the new row + $('tr.ajaxInsert') + .show('slow') + .removeClass('ajaxInsert'); + } else if ($('table.data').find('tr').has('td').length === 0) { + // If we are not supposed to insert the new row, + // we will now check if the table is empty and + // needs to be hidden. This will be the case if + // we were editing the only item in the list, + // which we removed and will not be inserting + // something else in its place. + $('table.data').hide("slow", function () { + $('#nothing2display').show("slow"); + }); + } + // Now we have inserted the row at the correct + // position, but surely at least some row classes + // are wrong now. So we will itirate throught + // all rows and assign correct classes to them + /** + * @var ct Count of processed rows + */ + var ct = 0; + /** + * @var rowclass Class to be attached to the row + * that is being processed + */ + var rowclass = ''; + $('table.data').find('tr').has('td').each(function () { + rowclass = (ct % 2 === 0) ? 'odd' : 'even'; + $(this).removeClass().addClass(rowclass); + ct++; + }); + // If this is the first item being added, remove + // the "No items" message and show the list. + if ($('table.data').find('tr').has('td').length > 0 + && $('#nothing2display').is(':visible')) { + $('#nothing2display').hide("slow", function () { + $('table.data').show("slow"); + }); + } + PMA_reloadNavigation(); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.post() + } // end "if (that.validate())" + }; // end of function that handles the submission of the Editor + that.buttonOptions[PMA_messages['strClose']] = function () { + $(this).dialog("close"); + }; + /** + * Display the dialog to the user + */ + that.$ajaxDialog = $('<div>' + data.message + '</div>').dialog({ + width: 700, + minWidth: 500, + buttons: that.buttonOptions, + title: data.title, + modal: true, + close: function () { + $(this).remove(); + } + }); + that.$ajaxDialog.find('input[name=item_name]').focus(); + that.$ajaxDialog.find('input.datefield, input.datetimefield').each(function () { + PMA_addDatepicker($(this).css('width', '95%')); + }); + /** + * @var mode Used to remeber whether the editor is in + * "Edit" or "Add" mode + */ + var mode = 'add'; + if ($('input[name=editor_process_edit]').length > 0) { + mode = 'edit'; + } + // Attach syntax highlited editor to the definition + /** + * @var elm jQuery object containing the reference to + * the Definition textarea. + */ + var $elm = $('textarea[name=item_definition]').last(); + /** + * @var opts Options to pass to the codemirror editor + */ + var opts = { + lineNumbers: true, + matchBrackets: true, + indentUnit: 4, + mode: "text/x-mysql" + }; + if (typeof CodeMirror != 'undefined') { + that.syntaxHiglighter = CodeMirror.fromTextArea($elm[0], opts); + } + // Execute item-specific code + that.postDialogShow(data); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.get() + }, + + dropDialog: function ($this) { + /** + * @var $curr_row Object containing reference to the current row + */ + var $curr_row = $this.parents('tr'); + /** + * @var question String containing the question to be asked for confirmation + */ + var question = $('<div/>').text( + $curr_row.children('td').children('.drop_sql').html() + ); + // We ask for confirmation first here, before submitting the ajax request + $this.PMA_confirm(question, $this.attr('href'), function (url) { + /** + * @var msg jQuery object containing the reference to + * the AJAX message shown to the user + */ + var $msg = PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); + $.get(url, {'is_js_confirmed': 1, 'ajax_request': true}, function (data) { + if (data.success === true) { + /** + * @var $table Object containing reference + * to the main list of elements + */ + var $table = $curr_row.parent(); + // Check how many rows will be left after we remove + // the one that the user has requested us to remove + if ($table.find('tr').length === 3) { + // If there are two rows left, it means that they are + // the header of the table and the rows that we are + // about to remove, so after the removal there will be + // nothing to show in the table, so we hide it. + $table.hide("slow", function () { + $(this).find('tr.even, tr.odd').remove(); + $('#nothing2display').show("slow"); + }); + } else { + $curr_row.hide("slow", function () { + $(this).remove(); + // Now we have removed the row from the list, but maybe + // some row classes are wrong now. So we will itirate + // throught all rows and assign correct classes to them. + /** + * @var ct Count of processed rows + */ + var ct = 0; + /** + * @var rowclass Class to be attached to the row + * that is being processed + */ + var rowclass = ''; + $table.find('tr').has('td').each(function () { + rowclass = (ct % 2 === 0) ? 'odd' : 'even'; + $(this).removeClass().addClass(rowclass); + ct++; + }); + }); + } + // Get rid of the "Loading" message + PMA_ajaxRemoveMessage($msg); + // Show the query that we just executed + PMA_slidingMessage(data.sql_query); + PMA_reloadNavigation(); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.get() + }); // end $.PMA_confirm() + } +}; // end RTE namespace + +/** + * @var RTE.EVENT JavaScript functionality for events + */ +RTE.EVENT = { + validateCustom: function () { + /** + * @var elm a jQuery object containing the reference + * to an element that is being validated + */ + var $elm = null; + if (this.$ajaxDialog.find('select[name=item_type]').find(':selected').val() === 'RECURRING') { + // The interval field must not be empty for recurring events + $elm = this.$ajaxDialog.find('input[name=item_interval_value]'); + if ($elm.val() === '') { + $elm.focus(); + alert(PMA_messages['strFormEmpty']); + return false; + } + } else { + // The execute_at field must not be empty for "once off" events + $elm = this.$ajaxDialog.find('input[name=item_execute_at]'); + if ($elm.val() === '') { + $elm.focus(); + alert(PMA_messages['strFormEmpty']); + return false; + } + } + return true; + } +}; + +/** + * @var RTE.ROUTINE JavaScript functionality for routines + */ +RTE.ROUTINE = { + /** + * Overriding the postDialogShow() function defined in common.js + * + * @param data JSON-encoded data from the ajax request + */ + postDialogShow: function (data) { + // Cache the template for a parameter table row + RTE.param_template = data.param_template; + var that = this; + // Make adjustments in the dialog to make it AJAX compatible + $('td.routine_param_remove').show(); + $('input[name=routine_removeparameter]').remove(); + $('input[name=routine_addparameter]').css('width', '100%'); + // Enable/disable the 'options' dropdowns for parameters as necessary + $('table.routine_params_table').last().find('th[colspan=2]').attr('colspan', '1'); + $('table.routine_params_table').last().find('tr').has('td').each(function () { + that.setOptionsForParameter( + $(this).find('select[name^=item_param_type]'), + $(this).find('input[name^=item_param_length]'), + $(this).find('select[name^=item_param_opts_text]'), + $(this).find('select[name^=item_param_opts_num]') + ); + }); + // Enable/disable the 'options' dropdowns for + // function return value as necessary + this.setOptionsForParameter( + $('table.rte_table').last().find('select[name=item_returntype]'), + $('table.rte_table').last().find('input[name=item_returnlength]'), + $('table.rte_table').last().find('select[name=item_returnopts_text]'), + $('table.rte_table').last().find('select[name=item_returnopts_num]') + ); + }, + /** + * Overriding the validateCustom() function defined in common.js + */ + validateCustom: function () { + /** + * @var isSuccess Stores the outcome of the validation + */ + var isSuccess = true; + /** + * @var inputname The value of the "name" attribute for + * the field that is being processed + */ + var inputname = ''; + this.$ajaxDialog.find('table.routine_params_table').last().find('tr').each(function () { + // Every parameter of a routine must have + // a non-empty direction, name and type + if (isSuccess) { + $(this).find(':input').each(function () { + inputname = $(this).attr('name'); + if (inputname.substr(0, 14) === 'item_param_dir' || + inputname.substr(0, 15) === 'item_param_name' || + inputname.substr(0, 15) === 'item_param_type') { + if ($(this).val() === '') { + $(this).focus(); + isSuccess = false; + return false; + } + } + }); + } else { + return false; + } + }); + if (! isSuccess) { + alert(PMA_messages['strFormEmpty']); + return false; + } + this.$ajaxDialog.find('table.routine_params_table').last().find('tr').each(function () { + // SET, ENUM, VARCHAR and VARBINARY fields must have length/values + var $inputtyp = $(this).find('select[name^=item_param_type]'); + var $inputlen = $(this).find('input[name^=item_param_length]'); + if ($inputtyp.length && $inputlen.length) { + if (($inputtyp.val() === 'ENUM' || $inputtyp.val() === 'SET' || $inputtyp.val().substr(0, 3) === 'VAR') + && $inputlen.val() === '') { + $inputlen.focus(); + isSuccess = false; + return false; + } + } + }); + if (! isSuccess) { + alert(PMA_messages['strFormEmpty']); + return false; + } + if (this.$ajaxDialog.find('select[name=item_type]').find(':selected').val() === 'FUNCTION') { + // The length/values of return variable for functions must + // be set, if the type is SET, ENUM, VARCHAR or VARBINARY. + var $returntyp = this.$ajaxDialog.find('select[name=item_returntype]'); + var $returnlen = this.$ajaxDialog.find('input[name=item_returnlength]'); + if (($returntyp.val() === 'ENUM' || $returntyp.val() === 'SET' || $returntyp.val().substr(0, 3) === 'VAR') + && $returnlen.val() === '') { + $returnlen.focus(); + alert(PMA_messages['strFormEmpty']); + return false; + } + } + if ($('select[name=item_type]').find(':selected').val() === 'FUNCTION') { + // A function must contain a RETURN statement in its definition + if (this.$ajaxDialog.find('table.rte_table').find('textarea[name=item_definition]').val().toUpperCase().indexOf('RETURN') < 0) { + this.syntaxHiglighter.focus(); + alert(PMA_messages['MissingReturn']); + return false; + } + } + return true; + }, + /** + * Enable/disable the "options" dropdown and "length" input for + * parameters and the return variable in the routine editor + * as necessary. + * + * @param type a jQuery object containing the reference + * to the "Type" dropdown box + * @param len a jQuery object containing the reference + * to the "Length" input box + * @param text a jQuery object containing the reference + * to the dropdown box with options for + * parameters of text type + * @param num a jQuery object containing the reference + * to the dropdown box with options for + * parameters of numeric type + */ + setOptionsForParameter: function ($type, $len, $text, $num) { + /** + * @var no_opts a jQuery object containing the reference + * to an element to be displayed when no + * options are available + */ + var $no_opts = $text.parent().parent().find('.no_opts'); + /** + * @var no_len a jQuery object containing the reference + * to an element to be displayed when no + * "length/values" field is available + */ + var $no_len = $len.parent().parent().find('.no_len'); + + // Process for parameter options + switch ($type.val()) { + case 'TINYINT': + case 'SMALLINT': + case 'MEDIUMINT': + case 'INT': + case 'BIGINT': + case 'DECIMAL': + case 'FLOAT': + case 'DOUBLE': + case 'REAL': + $text.parent().hide(); + $num.parent().show(); + $no_opts.hide(); + break; + case 'TINYTEXT': + case 'TEXT': + case 'MEDIUMTEXT': + case 'LONGTEXT': + case 'CHAR': + case 'VARCHAR': + case 'SET': + case 'ENUM': + $text.parent().show(); + $num.parent().hide(); + $no_opts.hide(); + break; + default: + $text.parent().hide(); + $num.parent().hide(); + $no_opts.show(); + break; + } + // Process for parameter length + switch ($type.val()) { + case 'DATE': + case 'DATETIME': + case 'TIME': + case 'TINYBLOB': + case 'TINYTEXT': + case 'BLOB': + case 'TEXT': + case 'MEDIUMBLOB': + case 'MEDIUMTEXT': + case 'LONGBLOB': + case 'LONGTEXT': + $text.closest('tr').find('a:first').hide(); + $len.parent().hide(); + $no_len.show(); + break; + default: + if ($type.val() == 'ENUM' || $type.val() == 'SET') { + $text.closest('tr').find('a:first').show(); + } else { + $text.closest('tr').find('a:first').hide(); + } + $len.parent().show(); + $no_len.hide(); + break; + } + }, + executeDialog: function ($this) { + var that = this; + /** + * @var msg jQuery object containing the reference to + * the AJAX message shown to the user + */ + var $msg = PMA_ajaxShowMessage(); + $.get($this.attr('href'), {'ajax_request': true}, function (data) { + if (data.success === true) { + PMA_ajaxRemoveMessage($msg); + // If 'data.dialog' is true we show a dialog with a form + // to get the input parameters for routine, otherwise + // we just show the results of the query + if (data.dialog) { + // Define the function that is called when + // the user presses the "Go" button + that.buttonOptions[PMA_messages['strGo']] = function () { + /** + * @var data Form data to be sent in the AJAX request + */ + var data = $('form.rte_form').last().serialize(); + $msg = PMA_ajaxShowMessage( + PMA_messages['strProcessingRequest'] + ); + $.post('db_routines.php', data, function (data) { + if (data.success === true) { + // Routine executed successfully + PMA_ajaxRemoveMessage($msg); + PMA_slidingMessage(data.message); + $ajaxDialog.dialog('close'); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); + }; + that.buttonOptions[PMA_messages['strClose']] = function () { + $(this).dialog("close"); + }; + /** + * Display the dialog to the user + */ + $ajaxDialog = $('<div>' + data.message + '</div>').dialog({ + width: 650, + buttons: that.buttonOptions, + title: data.title, + modal: true, + close: function () { + $(this).remove(); + } + }); + $ajaxDialog.find('input[name^=params]').first().focus(); + /** + * Attach the datepickers to the relevant form fields + */ + $ajaxDialog.find('input.datefield, input.datetimefield').each(function () { + PMA_addDatepicker($(this).css('width', '95%')); + }); + } else { + // Routine executed successfully + PMA_slidingMessage(data.message); + } + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.get() + } +}; + +/** + * Attach Ajax event handlers for the Routines, Triggers and Events editor + * + * FIXME: submit on ENTER keypress in dialog + */ +$(function () { + /** + * Attach Ajax event handlers for the Add/Edit functionality. + */ + $('a.ajax.add_anchor, a.ajax.edit_anchor').live('click', function (event) { + event.preventDefault(); + var type = $(this).attr('href').substr(0, $(this).attr('href').indexOf('?')); + if (type.indexOf('routine') != -1) { + type = 'routine'; + } else if (type.indexOf('trigger') != -1) { + type = 'trigger'; + } else if (type.indexOf('event') != -1) { + type = 'event'; + } else { + type = ''; + } + var dialog = new RTE.object(type); + dialog.editorDialog($(this).hasClass('add_anchor'), $(this)); + }); // end $.live() + + /** + * Attach Ajax event handlers for the Execute routine functionality + */ + $('a.ajax.exec_anchor').live('click', function (event) { + event.preventDefault(); + var dialog = new RTE.object('routine'); + dialog.executeDialog($(this)); + }); // end $.live() + + /** + * Attach Ajax event handlers for Export of Routines, Triggers and Events + */ + $('a.ajax.export_anchor').live('click', function (event) { + event.preventDefault(); + var dialog = new RTE.object(); + dialog.exportDialog($(this)); + }); // end $.live() + + /** + * Attach Ajax event handlers for Drop functionality + * of Routines, Triggers and Events. + */ + $('a.ajax.drop_anchor').live('click', function (event) { + event.preventDefault(); + var dialog = new RTE.object(); + dialog.dropDialog($(this)); + }); // end $.live() + + /** + * Attach Ajax event handlers for the "Change event/routine type" + * functionality in the events editor, so that the correct + * rows are shown in the editor when changing the event type + */ + $('select[name=item_type]').live('change', function () { + $(this) + .closest('table') + .find('tr.recurring_event_row, tr.onetime_event_row, tr.routine_return_row, td.routine_direction_cell') + .toggle(); + }); // end $.live() + + /** + * Attach Ajax event handlers for the "Change parameter type" + * functionality in the routines editor, so that the correct + * option/length fields, if any, are shown when changing + * a parameter type + */ + $('select[name^=item_param_type]').live('change', function () { + /** + * @var row jQuery object containing the reference to + * a row in the routine parameters table + */ + var $row = $(this).parents('tr').first(); + var rte = new RTE.object('routine'); + rte.setOptionsForParameter( + $row.find('select[name^=item_param_type]'), + $row.find('input[name^=item_param_length]'), + $row.find('select[name^=item_param_opts_text]'), + $row.find('select[name^=item_param_opts_num]') + ); + }); // end $.live() + + /** + * Attach Ajax event handlers for the "Change the type of return + * variable of function" functionality, so that the correct fields, + * if any, are shown when changing the function return type type + */ + $('select[name=item_returntype]').live('change', function () { + var rte = new RTE.object('routine'); + var $table = $(this).closest('table.rte_table'); + rte.setOptionsForParameter( + $table.find('select[name=item_returntype]'), + $table.find('input[name=item_returnlength]'), + $table.find('select[name=item_returnopts_text]'), + $table.find('select[name=item_returnopts_num]') + ); + }); // end $.live() + + /** + * Attach Ajax event handlers for the "Add parameter to routine" functionality + */ + $('input[name=routine_addparameter]').live('click', function (event) { + event.preventDefault(); + /** + * @var routine_params_table jQuery object containing the reference + * to the routine parameters table + */ + var $routine_params_table = $(this).closest('div.ui-dialog').find('.routine_params_table'); + /** + * @var new_param_row A string containing the HTML code for the + * new row for the routine paramaters table + */ + var new_param_row = RTE.param_template.replace(/%s/g, $routine_params_table.find('tr').length - 1); + // Append the new row to the parameters table + $routine_params_table.append(new_param_row); + // Make sure that the row is correctly shown according to the type of routine + if ($(this).closest('div.ui-dialog').find('table.rte_table select[name=item_type]').val() === 'FUNCTION') { + $('tr.routine_return_row').show(); + $('td.routine_direction_cell').hide(); + } + /** + * @var newrow jQuery object containing the reference to the newly + * inserted row in the routine parameters table + */ + var $newrow = $(this).closest('div.ui-dialog').find('table.routine_params_table').find('tr').has('td').last(); + // Enable/disable the 'options' dropdowns for parameters as necessary + var rte = new RTE.object('routine'); + rte.setOptionsForParameter( + $newrow.find('select[name^=item_param_type]'), + $newrow.find('input[name^=item_param_length]'), + $newrow.find('select[name^=item_param_opts_text]'), + $newrow.find('select[name^=item_param_opts_num]') + ); + }); // end $.live() + + /** + * Attach Ajax event handlers for the + * "Remove parameter from routine" functionality + */ + $('a.routine_param_remove_anchor').live('click', function (event) { + event.preventDefault(); + $(this).parent().parent().remove(); + // After removing a parameter, the indices of the name attributes in + // the input fields lose the correct order and need to be reordered. + /** + * @var index Counter used for reindexing the input + * fields in the routine parameters table + */ + var index = 0; + $(this).closest('div.ui-dialog').find('table.routine_params_table').find('tr').has('td').each(function () { + $(this).find(':input').each(function () { + /** + * @var inputname The value of the name attribute of + * the input field being reindexed + */ + var inputname = $(this).attr('name'); + if (inputname.substr(0, 14) === 'item_param_dir') { + $(this).attr('name', inputname.substr(0, 14) + '[' + index + ']'); + } else if (inputname.substr(0, 15) === 'item_param_name') { + $(this).attr('name', inputname.substr(0, 15) + '[' + index + ']'); + } else if (inputname.substr(0, 15) === 'item_param_type') { + $(this).attr('name', inputname.substr(0, 15) + '[' + index + ']'); + } else if (inputname.substr(0, 17) === 'item_param_length') { + $(this).attr('name', inputname.substr(0, 17) + '[' + index + ']'); + $(this).attr('id', 'item_param_length_' + index); + } else if (inputname.substr(0, 20) === 'item_param_opts_text') { + $(this).attr('name', inputname.substr(0, 20) + '[' + index + ']'); + } else if (inputname.substr(0, 19) === 'item_param_opts_num') { + $(this).attr('name', inputname.substr(0, 19) + '[' + index + ']'); + } + }); + index++; + }); + }); // end $.live() +}); // end of $() diff --git a/hugo/js/server_databases.js b/hugo/js/server_databases.js new file mode 100644 index 0000000..8408a86 --- /dev/null +++ b/hugo/js/server_databases.js @@ -0,0 +1,125 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * @fileoverview functions used on the server databases list page + * @name Server Databases + * + * @requires jQuery + * @requires jQueryUI + * @required js/functions.js + */ + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('server_databases.js', function() { + $("#dbStatsForm").die('submit'); + $('#create_database_form.ajax').die('submit'); +}); + +/** + * AJAX scripts for server_databases.php + * + * Actions ajaxified here: + * Drop Databases + * + */ +AJAX.registerOnload('server_databases.js', function() { + /** + * Attach Event Handler for 'Drop Databases' + */ + $("#dbStatsForm").live('submit', function(event) { + event.preventDefault(); + + var $form = $(this); + + /** + * @var selected_dbs Array containing the names of the checked databases + */ + var selected_dbs = []; + // loop over all checked checkboxes, except the #checkall checkbox + $form.find('input:checkbox:checked:not(#checkall)').each(function () { + $(this).closest('tr').addClass('removeMe'); + selected_dbs[selected_dbs.length] = 'DROP DATABASE `' + escapeHtml($(this).val()) + '`;'; + }); + if (! selected_dbs.length) { + PMA_ajaxShowMessage( + $('<div class="notice" />').text( + PMA_messages.strNoDatabasesSelected + ), + 2000 + ); + return; + } + /** + * @var question String containing the question to be asked for confirmation + */ + var question = + PMA_messages.strDropDatabaseStrongWarning + ' ' + + $.sprintf(PMA_messages.strDoYouReally, selected_dbs.join('<br />')); + + $(this).PMA_confirm( + question, + $form.prop('action') + + '?' + $(this).serialize() + + '&drop_selected_dbs=1&is_js_confirmed=1&ajax_request=true', + function(url) { + PMA_ajaxShowMessage(PMA_messages.strProcessingRequest, false); + + $.post(url, function(data) { + if (data.success == true) { + PMA_ajaxShowMessage(data.message); + + var $rowsToRemove = $form.find('tr.removeMe'); + var $databasesCount = $('#databases_count'); + var newCount = parseInt($databasesCount.text()) - $rowsToRemove.length; + $databasesCount.text(newCount); + + $rowsToRemove.remove(); + $form.find('tbody').PMA_sort_table('.name'); + PMA_reloadNavigation(); + } else { + $form.find('tr.removeMe').removeClass('removeMe'); + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.post() + }); // end $.PMA_confirm() + }) ; //end of Drop Database action + + /** + * Attach Ajax event handlers for 'Create Database'. + */ + $('#create_database_form.ajax').live('submit', function(event) { + event.preventDefault(); + + $form = $(this); + + var newDbNameInput = $form.find('input[name=new_db]'); + if (newDbNameInput.val() === '') { + newDbNameInput.focus(); + alert(PMA_messages['strFormEmpty']); + return; + } + + PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); + PMA_prepareForAjaxRequest($form); + + $.post($form.attr('action'), $form.serialize(), function(data) { + if (data.success == true) { + PMA_ajaxShowMessage(data.message); + + //Append database's row to table + $("#tabledatabases") + .find('tbody') + .append(data.new_db_string) + .PMA_sort_table('.name'); + + var $databases_count_object = $('#databases_count'); + var databases_count = parseInt($databases_count_object.text()) + 1; + $databases_count_object.text(databases_count); + PMA_reloadNavigation(); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.post() + }); // end $().live() +}); // end $() diff --git a/hugo/js/server_plugins.js b/hugo/js/server_plugins.js new file mode 100644 index 0000000..17391af --- /dev/null +++ b/hugo/js/server_plugins.js @@ -0,0 +1,30 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Functions used in server plugins pages + */ +var pma_theme_image; // filled in server_plugins.php + +AJAX.registerOnload('server_plugins.js', function() { + // Add tabs + $('#pluginsTabs').tabs({ + // Tab persistence + cookie: { name: 'pma_serverStatusTabs', expires: 1 }, + show: function(event, ui) { + // Fixes line break in the menu bar when the page overflows and scrollbar appears + $('#topmenu').menuResizer('resize'); + // 'Plugins' tab is too high due to hiding of 'Modules' by negative left position, + // hide tabs by changing display to fix it + $(ui.panel).closest('.ui-tabs').find('> div').not(ui.panel).css('display', 'none'); + $(ui.panel).css('display', 'block'); + } + }); + + // Make columns sortable, but only for tables with more than 1 data row + var $tables = $('#plugins_plugins table:has(tbody tr + tr)'); + $tables.tablesorter({ + sortList: [[0,0]], + widgets: ['zebra'] + }); + $tables.find('thead th') + .append('<img class="sortableIcon" src="' + pma_theme_image + 'cleardot.gif" alt="">'); +}); diff --git a/hugo/js/server_privileges.js b/hugo/js/server_privileges.js new file mode 100644 index 0000000..86f4526 --- /dev/null +++ b/hugo/js/server_privileges.js @@ -0,0 +1,581 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * @fileoverview functions used in server privilege pages + * @name Server Privileges + * + * @requires jQuery + * @requires jQueryUI + * @requires js/functions.js + * + */ + +/** + * Validates the "add a user" form + * + * @return boolean whether the form is validated or not + */ +function checkAddUser(the_form) +{ + if (the_form.elements['pred_hostname'].value == 'userdefined' && the_form.elements['hostname'].value == '') { + alert(PMA_messages['strHostEmpty']); + the_form.elements['hostname'].focus(); + return false; + } + + if (the_form.elements['pred_username'].value == 'userdefined' && the_form.elements['username'].value == '') { + alert(PMA_messages['strUserEmpty']); + the_form.elements['username'].focus(); + return false; + } + + return PMA_checkPassword($(the_form)); +} // end of the 'checkAddUser()' function + +/** + * When a new user is created and retrieved over Ajax, append the user's row to + * the user's table + * + * @param new_user_string the html for the new user's row + * @param new_user_initial the first alphabet of the user's name + * @param new_user_initial_string html to replace the initial for pagination + */ +function appendNewUser(new_user_string, new_user_initial, new_user_initial_string) +{ + //Append the newly retrieved user to the table now + + //Calculate the index for the new row + var $curr_last_row = $("#usersForm").find('tbody').find('tr:last'); + var $curr_first_row = $("#usersForm").find('tbody').find('tr:first'); + var first_row_initial = $curr_first_row.find('label').html().substr(0, 1).toUpperCase(); + var curr_shown_initial = $curr_last_row.find('label').html().substr(0, 1).toUpperCase(); + var curr_last_row_index_string = $curr_last_row.find('input:checkbox').attr('id').match(/\d+/)[0]; + var curr_last_row_index = parseFloat(curr_last_row_index_string); + var new_last_row_index = curr_last_row_index + 1; + var new_last_row_id = 'checkbox_sel_users_' + new_last_row_index; + var is_show_all = (first_row_initial != curr_shown_initial) ? true : false; + + //Append to the table and set the id/names correctly + if ((curr_shown_initial == new_user_initial) || is_show_all) { + $(new_user_string) + .insertAfter($curr_last_row) + .find('input:checkbox') + .attr('id', new_last_row_id) + .val(function() { + //the insert messes up the &27; part. let's fix it + return $(this).val().replace(/&/,'&'); + }) + .end() + .find('label') + .attr('for', new_last_row_id) + .end(); + } + + //Let us sort the table alphabetically + $("#usersForm").find('tbody').PMA_sort_table('label'); + + $("#initials_table").find('td:contains('+new_user_initial+')') + .html(new_user_initial_string); + + //update the checkall checkbox + $(checkboxes_sel).trigger("change"); +} + +function addUser($form) +{ + if (! checkAddUser($form.get(0))) { + return false; + } + + //We also need to post the value of the submit button in order to get this to work correctly + $.post($form.attr('action'), $form.serialize() + "&adduser_submit=" + $("input[name=adduser_submit]").val(), function(data) { + if (data.success == true) { + // Refresh navigation, if we created a database with the name + // that is the same as the username of the new user + if ($('#add_user_dialog #createdb-1:checked').length) { + PMA_reloadNavigation(); + } + + $('#page_content').show(); + $("#add_user_dialog").remove(); + + PMA_ajaxShowMessage(data.message); + $("#result_query").remove(); + $('#page_content').prepend(data.sql_query); + $("#result_query").css({ + 'margin-top' : '0.5em' + }); + + //Remove the empty notice div generated due to a NULL query passed to PMA_getMessage() + var $notice_class = $("#result_query").find('.notice'); + if ($notice_class.text() == '') { + $notice_class.remove(); + } + if ($('#fieldset_add_user a.ajax').attr('name') == 'db_specific') { + + /*process the fieldset_add_user attribute and get the val of privileges*/ + var url = $('#fieldset_add_user a.ajax').attr('rel'); + + if (url.substring(url.length - 23, url.length) == "&goto=db_operations.php") { + url = url.substring(0, url.length - 23); + } + url = url + "&ajax_request=true&db_specific=true"; + + /* post request for get the updated userForm table */ + $.post($form.attr('action'), url, function(priv_data) { + + /*Remove the old userForm table*/ + if ($('#userFormDiv').length != 0) { + $('#userFormDiv').remove(); + } else { + $("#usersForm").remove(); + } + if (priv_data.success == true) { + $('<div id="userFormDiv"></div>') + .html(priv_data.user_form) + .insertAfter('#result_query'); + } else { + PMA_ajaxShowMessage(PMA_messages['strErrorProcessingRequest'] + " : " + priv_data.error, false); + } + }); + } else { + appendNewUser(data.new_user_string, data.new_user_initial, data.new_user_initial_string); + } + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); +} + +/** + * AJAX scripts for server_privileges page. + * + * Actions ajaxified here: + * Add user + * Revoke a user + * Edit privileges + * Export privileges + * Paginate table of users + * Flush privileges + * + * @memberOf jQuery + * @name document.ready + */ + + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('server_privileges.js', function() { + $("#fieldset_add_user a.ajax").die("click"); + $('form[name=usersForm]').unbind('submit'); + $("#fieldset_delete_user_footer #buttonGo.ajax").die('click'); + $("a.edit_user_anchor.ajax").die('click'); + $("#edit_user_dialog").find("form.ajax").die('submit'); + $("button.mult_submit[value=export]").die('click'); + $("a.export_user_anchor.ajax").die('click'); + $("#initials_table").find("a.ajax").die('click'); + $('#checkbox_drop_users_db').unbind('click'); +}); + +AJAX.registerOnload('server_privileges.js', function() { + /** + * AJAX event handler for 'Add a New User' + * + * @see PMA_ajaxShowMessage() + * @see appendNewUser() + * @memberOf jQuery + * @name add_user_click + * + */ + $("#fieldset_add_user a.ajax").live("click", function(event) { + /** @lends jQuery */ + event.preventDefault(); + var $msgbox = PMA_ajaxShowMessage(); + + $.get($(this).attr("href"), {'ajax_request':true}, function(data) { + if (data.success == true) { + $('#page_content').hide(); + var $div = $('#add_user_dialog'); + if ($div.length == 0) { + $div = $('<div id="add_user_dialog" style="margin: 0.5em;"></div>') + .insertBefore('#page_content'); + } else { + $div.empty(); + } + $div.html(data.message) + .find("form[name=usersForm]") + .append('<input type="hidden" name="ajax_request" value="true" />') + .end(); + displayPasswordGenerateButton(); + PMA_showHints($div); + PMA_ajaxRemoveMessage($msgbox); + $div.find("input.autofocus").focus(); + + $div.find('form[name=usersForm]').bind('submit', function (event) { + event.preventDefault(); + addUser($(this)); + }); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.get() + + });//end of Add New User AJAX event handler + + /** + * AJAX handler for 'Revoke User' + * + * @see PMA_ajaxShowMessage() + * @memberOf jQuery + * @name revoke_user_click + */ + $("#fieldset_delete_user_footer #buttonGo.ajax").live('click', function(event) { + event.preventDefault(); + + PMA_ajaxShowMessage(PMA_messages['strRemovingSelectedUsers']); + + var $form = $("#usersForm"); + + $.post($form.attr('action'), $form.serialize() + "&delete=" + $(this).val() + "&ajax_request=true", function(data) { + if (data.success == true) { + PMA_ajaxShowMessage(data.message); + // Refresh navigation, if we droppped some databases with the name + // that is the same as the username of the deleted user + if ($('#checkbox_drop_users_db:checked').length) { + PMA_reloadNavigation(); + } + //Remove the revoked user from the users list + $form.find("input:checkbox:checked").parents("tr").slideUp("medium", function() { + var this_user_initial = $(this).find('input:checkbox').val().charAt(0).toUpperCase(); + $(this).remove(); + + //If this is the last user with this_user_initial, remove the link from #initials_table + if ($("#tableuserrights").find('input:checkbox[value^=' + this_user_initial + ']').length == 0) { + $("#initials_table").find('td > a:contains(' + this_user_initial + ')').parent('td').html(this_user_initial); + } + + //Re-check the classes of each row + $form + .find('tbody').find('tr:odd') + .removeClass('even').addClass('odd') + .end() + .find('tr:even') + .removeClass('odd').addClass('even'); + + //update the checkall checkbox + $(checkboxes_sel).trigger("change"); + }); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.post() + }); // end Revoke User + + /** + * AJAX handler for 'Edit User' + * + * @see PMA_ajaxShowMessage() + * + */ + + /** + * Step 1: Load Edit User Dialog + * @memberOf jQuery + * @name edit_user_click + */ + $("a.edit_user_anchor.ajax").live('click', function(event) { + /** @lends jQuery */ + event.preventDefault(); + + var $msgbox = PMA_ajaxShowMessage(); + + $(this).parents('tr').addClass('current_row'); + + var token = $(this).parents('form').find('input[name="token"]').val(); + $.get( + $(this).attr('href'), + { + 'ajax_request':true, + 'edit_user_dialog': true, + 'token': token + }, + function(data) { + if (data.success == true) { + $('#page_content').hide(); + var $div = $('#edit_user_dialog'); + if ($div.length == 0) { + $div = $('<div id="edit_user_dialog" style="margin: 0.5em;"></div>') + .insertBefore('#page_content'); + } else { + $div.empty(); + } + $div.html(data.message); + displayPasswordGenerateButton(); + PMA_ajaxRemoveMessage($msgbox); + PMA_showHints($div); + } else { + PMA_ajaxShowMessage(data.error, false); + } + } + ); // end $.get() + }); + + /** + * Step 2: Submit the Edit User Dialog + * + * @see PMA_ajaxShowMessage() + * @memberOf jQuery + * @name edit_user_submit + */ + $("#edit_user_dialog").find("form.ajax").live('submit', function(event) { + /** @lends jQuery */ + event.preventDefault(); + + var $t = $(this); + + if ($t.is('.copyUserForm') && ! PMA_checkPassword($t)) { + return false; + } + + PMA_ajaxShowMessage(PMA_messages['strProcessingRequest']); + + $t.append('<input type="hidden" name="ajax_request" value="true" />'); + + /** + * @var curr_submit_name name of the current button being submitted + */ + var curr_submit_name = $t.find('.tblFooters').find('input:submit').attr('name'); + + /** + * @var curr_submit_value value of the current button being submitted + */ + var curr_submit_value = $t.find('.tblFooters').find('input:submit').val(); + + // If any option other than 'keep the old one'(option 4) is chosen, we need to remove + // the old one from the table. + var $row_to_remove; + if (curr_submit_name == 'change_copy' + && $('input[name=mode]:checked', '#fieldset_mode').val() != '4') { + var old_username = $t.find('input[name="old_username"]').val(); + var old_hostname = $t.find('input[name="old_hostname"]').val(); + $('#usersForm tbody tr').each(function() { + var $tr = $(this); + if ($tr.find('td:nth-child(2) label').text() == old_username + && $tr.find('td:nth-child(3)').text() == old_hostname) { + $row_to_remove = $tr; + return false; + } + }); + } + + $.post($t.attr('action'), $t.serialize() + '&' + curr_submit_name + '=' + curr_submit_value, function(data) { + if (data.success == true) { + $('#page_content').show(); + $("#edit_user_dialog").remove(); + + PMA_ajaxShowMessage(data.message); + + if (data.sql_query) { + $("#result_query").remove(); + $('#page_content').prepend(data.sql_query); + $("#result_query").css({ + 'margin-top' : '0.5em' + }); + var $notice_class = $("#result_query").find('.notice'); + if ($notice_class.text() == '') { + $notice_class.remove(); + } + } //Show SQL Query that was executed + + // Remove the old row if the old user is deleted + if ($row_to_remove != null) { + $row_to_remove.remove(); + } + + //Append new user if necessary + if (data.new_user_string) { + appendNewUser(data.new_user_string, data.new_user_initial, data.new_user_initial_string); + } + + //Check if we are on the page of the db-specific privileges + var db_priv_page = !!($('#dbspecificuserrights').length); // the "!!" part is merely there to ensure a value of type boolean + // we always need to reload on the db-specific privilege page + // and on the global page when adjusting global privileges, + // but not on the global page when adjusting db-specific privileges. + var reload_privs = false; + if (data.db_specific_privs == false || (db_priv_page == data.db_specific_privs)) { + reload_privs = true; + } + if (data.db_wildcard_privs) { + reload_privs = false; + } + + //Change privileges, if they were edited and need to be reloaded + if (data.new_privileges && reload_privs) { + $("#usersForm") + .find('.current_row') + .find('code') + .html(data.new_privileges); + } + + $("#usersForm") + .find('.current_row') + .removeClass('current_row'); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); + }); + //end Edit user + + /** + * AJAX handler for 'Export Privileges' + * + * @see PMA_ajaxShowMessage() + * @memberOf jQuery + * @name export_user_click + */ + $("button.mult_submit[value=export]").live('click', function(event) { + event.preventDefault(); + // can't export if no users checked + if ($(this.form).find("input:checked").length == 0) { + return; + } + var $msgbox = PMA_ajaxShowMessage(); + var button_options = {}; + button_options[PMA_messages['strClose']] = function() { + $(this).dialog("close"); + }; + $.post( + $(this.form).prop('action'), + $(this.form).serialize() + '&submit_mult=export&ajax_request=true', + function(data) { + if (data.success == true) { + var $ajaxDialog = $('<div />') + .append(data.message) + .dialog({ + title: data.title, + width: 500, + buttons: button_options, + close: function () { + $(this).remove(); + } + }); + PMA_ajaxRemoveMessage($msgbox); + // Attach syntax highlited editor to export dialog + if (typeof CodeMirror != 'undefined') { + CodeMirror.fromTextArea( + $ajaxDialog.find('textarea')[0], + { + lineNumbers: true, + matchBrackets: true, + indentUnit: 4, + mode: "text/x-mysql" + } + ); + } + } else { + PMA_ajaxShowMessage(data.error, false); + } + } + ); //end $.post + }); + // if exporting non-ajax, highlight anyways + if ($("textarea.export").length > 0 + && typeof CodeMirror != 'undefined') + { + CodeMirror.fromTextArea( + $('textarea.export')[0], + { + lineNumbers: true, + matchBrackets: true, + indentUnit: 4, + mode: "text/x-mysql" + } + ); + } + + $("a.export_user_anchor.ajax").live('click', function(event) { + event.preventDefault(); + var $msgbox = PMA_ajaxShowMessage(); + /** + * @var button_options Object containing options for jQueryUI dialog buttons + */ + var button_options = {}; + button_options[PMA_messages['strClose']] = function() { + $(this).dialog("close"); + }; + $.get($(this).attr('href'), {'ajax_request': true}, function(data) { + if (data.success == true) { + var $ajaxDialog = $('<div />') + .append(data.message) + .dialog({ + title: data.title, + width: 500, + buttons: button_options, + close: function () { + $(this).remove(); + } + }); + PMA_ajaxRemoveMessage($msgbox); + // Attach syntax highlited editor to export dialog + if (typeof CodeMirror != 'undefined') { + CodeMirror.fromTextArea( + $ajaxDialog.find('textarea')[0], + { + lineNumbers: true, + matchBrackets: true, + indentUnit: 4, + mode: "text/x-mysql" + } + ); + } + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); //end $.get + }); //end export privileges + + /** + * AJAX handler to Paginate the Users Table + * + * @see PMA_ajaxShowMessage() + * @name paginate_users_table_click + * @memberOf jQuery + */ + $("#initials_table").find("a.ajax").live('click', function(event) { + event.preventDefault(); + var $msgbox = PMA_ajaxShowMessage(); + $.get($(this).attr('href'), {'ajax_request' : true}, function(data) { + if (data.success == true) { + PMA_ajaxRemoveMessage($msgbox); + // This form is not on screen when first entering Privileges + // if there are more than 50 users + $("div.notice").remove(); + $("#usersForm").hide("medium").remove(); + $("#fieldset_add_user").hide("medium").remove(); + $("#initials_table") + .after(data.message).show("medium") + .siblings("h2").not(":first").remove(); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.get + }); // end of the paginate users table + + /* + * Additional confirmation dialog after clicking + * 'Drop the databases...' + */ + $('#checkbox_drop_users_db').click(function() { + var $this_checkbox = $(this); + if ($this_checkbox.is(':checked')) { + var is_confirmed = confirm(PMA_messages['strDropDatabaseStrongWarning'] + '\n' + $.sprintf(PMA_messages['strDoYouReally'], 'DROP DATABASE')); + if (! is_confirmed) { + $this_checkbox.prop('checked', false); + } + } + }); + + displayPasswordGenerateButton(); +}); diff --git a/hugo/js/server_status.js b/hugo/js/server_status.js new file mode 100644 index 0000000..e9fb326 --- /dev/null +++ b/hugo/js/server_status.js @@ -0,0 +1,25 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * @fileoverview functions used in server status pages + * @name Server Status + */ + +var pma_token, + url_query, + server_time_diff, + server_os, + is_superuser, + server_db_isLocal; + +// Add a tablesorter parser to properly handle thousands seperated numbers and SI prefixes +AJAX.registerOnload('server_status.js', function() { + + var $js_data_form = $('#js_data'); + pma_token = $js_data_form.find("input[name=pma_token]").val(); + url_query = $js_data_form.find("input[name=url_query]").val(); + server_time_diff = eval($js_data_form.find("input[name=server_time_diff]").val()); + server_os = $js_data_form.find("input[name=server_os]").val(); + is_superuser = $js_data_form.find("input[name=is_superuser]").val(); + server_db_isLocal = $js_data_form.find("input[name=server_db_isLocal]").val(); + +}); diff --git a/hugo/js/server_status_advisor.js b/hugo/js/server_status_advisor.js new file mode 100644 index 0000000..d581a68 --- /dev/null +++ b/hugo/js/server_status_advisor.js @@ -0,0 +1,93 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * Server Status Advisor + * + * @package PhpMyAdmin + */ + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('server_status_advisor.js', function() { + $('a[href="#openAdvisorInstructions"]').unbind('click'); + $('#statustabs_advisor').html(''); + $('#advisorDialog').remove(); + $('#instructionsDialog').remove(); +}); + +AJAX.registerOnload('server_status_advisor.js', function() { + /**** Server config advisor ****/ + var $dialog = $('<div />').attr('id', 'advisorDialog'); + var $instructionsDialog = $('<div />') + .attr('id', 'instructionsDialog') + .html($('#advisorInstructionsDialog').html()); + + $('a[href="#openAdvisorInstructions"]').click(function() { + var dlgBtns = {}; + dlgBtns[PMA_messages['strClose']] = function() { + $(this).dialog('close'); + }; + $instructionsDialog.dialog({ + title: PMA_messages['strAdvisorSystem'], + width: 700, + buttons: dlgBtns + }); + }); + + var $cnt = $('#statustabs_advisor'); + var $tbody, $tr, str, even = true; + + data = $.parseJSON($('#advisorData').text()); + $cnt.html(''); + + if (data.parse.errors.length > 0) { + $cnt.append('<b>Rules file not well formed, following errors were found:</b><br />- '); + $cnt.append(data.parse.errors.join('<br/>- ')); + $cnt.append('<p></p>'); + } + + if (data.run.errors.length > 0) { + $cnt.append('<b>Errors occured while executing rule expressions:</b><br />- '); + $cnt.append(data.run.errors.join('<br/>- ')); + $cnt.append('<p></p>'); + } + + if (data.run.fired.length > 0) { + $cnt.append('<p><b>' + PMA_messages['strPerformanceIssues'] + '</b></p>'); + $cnt.append('<table class="data" id="rulesFired" border="0"><thead><tr>' + + '<th>' + PMA_messages['strIssuse'] + '</th><th>' + PMA_messages['strRecommendation'] + + '</th></tr></thead><tbody></tbody></table>'); + $tbody = $cnt.find('table#rulesFired'); + + var rc_stripped; + + $.each(data.run.fired, function(key, value) { + // recommendation may contain links, don't show those in overview table (clicking on them redirects the user) + rc_stripped = $.trim($('<div>').html(value.recommendation).text()); + $tbody.append($tr = $('<tr class="linkElem noclick ' + (even ? 'even' : 'odd') + '"><td>' + + value.issue + '</td><td>' + rc_stripped + ' </td></tr>')); + even = !even; + $tr.data('rule', value); + + $tr.click(function() { + var rule = $(this).data('rule'); + $dialog + .dialog({title: PMA_messages['strRuleDetails']}) + .html( + '<p><b>' + PMA_messages['strIssuse'] + ':</b><br />' + rule.issue + '</p>' + + '<p><b>' + PMA_messages['strRecommendation'] + ':</b><br />' + rule.recommendation + '</p>' + + '<p><b>' + PMA_messages['strJustification'] + ':</b><br />' + rule.justification + '</p>' + + '<p><b>' + PMA_messages['strFormula'] + ':</b><br />' + rule.formula + '</p>' + + '<p><b>' + PMA_messages['strTest'] + ':</b><br />' + rule.test + '</p>' + ); + + var dlgBtns = {}; + dlgBtns[PMA_messages['strClose']] = function() { + $(this).dialog('close'); + }; + + $dialog.dialog({ width: 600, buttons: dlgBtns }); + }); + }); + } +}); diff --git a/hugo/js/server_status_monitor.js b/hugo/js/server_status_monitor.js new file mode 100644 index 0000000..dc97ec0 --- /dev/null +++ b/hugo/js/server_status_monitor.js @@ -0,0 +1,2290 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +var runtime = {}, + server_time_diff, + server_os, + is_superuser, + server_db_isLocal; +AJAX.registerOnload('server_status_monitor.js', function() { + var $js_data_form = $('#js_data'); + server_time_diff = new Date().getTime() - $js_data_form.find("input[name=server_time]").val(); + server_os = $js_data_form.find("input[name=server_os]").val(); + is_superuser = $js_data_form.find("input[name=is_superuser]").val(); + server_db_isLocal = $js_data_form.find("input[name=server_db_isLocal]").val(); +}); + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('server_status_monitor.js', function() { + $('#emptyDialog').remove(); + $('#addChartDialog').remove(); + $('a.popupLink').unbind('click'); + $('body').unbind('click'); +}); +/** + * Popup behaviour + */ +AJAX.registerOnload('server_status_monitor.js', function() { + $('<div />') + .attr('id', 'emptyDialog') + .appendTo('#page_content'); + $('#addChartDialog') + .appendTo('#page_content'); + + $('a.popupLink').click( function() { + var $link = $(this); + $('div.' + $link.attr('href').substr(1)) + .show() + .offset({ top: $link.offset().top + $link.height() + 5, left: $link.offset().left }) + .addClass('openedPopup'); + + return false; + }); + $('body').click( function(event) { + $('div.openedPopup').each(function() { + var $cnt = $(this); + var pos = $cnt.offset(); + // Hide if the mouseclick is outside the popupcontent + if (event.pageX < pos.left + || event.pageY < pos.top + || event.pageX > pos.left + $cnt.outerWidth() + || event.pageY > pos.top + $cnt.outerHeight() + ) { + $cnt.hide().removeClass('openedPopup'); + } + }); + }); +}); + +AJAX.registerTeardown('server_status_monitor.js', function() { + $('a[href="#rearrangeCharts"], a[href="#endChartEditMode"]').unbind('click'); + $('div.popupContent select[name="chartColumns"]').unbind('change'); + $('div.popupContent select[name="gridChartRefresh"]').unbind('change'); + $('a[href="#addNewChart"]').unbind('click'); + $('a[href="#exportMonitorConfig"]').unbind('click'); + $('a[href="#importMonitorConfig"]').unbind('click'); + $('a[href="#clearMonitorConfig"]').unbind('click'); + $('a[href="#pauseCharts"]').unbind('click'); + $('a[href="#monitorInstructionsDialog"]').unbind('click'); + $('input[name="chartType"]').unbind('click'); + $('input[name="useDivisor"]').unbind('click'); + $('input[name="useUnit"]').unbind('click'); + $('select[name="varChartList"]').unbind('click'); + $('a[href="#kibDivisor"]').unbind('click'); + $('a[href="#mibDivisor"]').unbind('click'); + $('a[href="#submitClearSeries"]').unbind('click'); + $('a[href="#submitAddSeries"]').unbind('click'); + // $("input#variableInput").destroy(); + $('#chartPreset').unbind('click'); + $('#chartStatusVar').unbind('click'); + destroyGrid(); +}); + +AJAX.registerOnload('server_status_monitor.js', function() { + // Show tab links + $('div.tabLinks').show(); + $('#loadingMonitorIcon').remove(); + // Codemirror is loaded on demand so we might need to initialize it + if (! codemirror_editor) { + var $elm = $('#sqlquery'); + if ($elm.length > 0 && typeof CodeMirror != 'undefined') { + codemirror_editor = CodeMirror.fromTextArea( + $elm[0], + { + lineNumbers: true, + matchBrackets: true, + indentUnit: 4, + mode: "text/x-mysql" + } + ); + } + } + // Timepicker is loaded on demand so we need to initialize + // datetime fields from the 'load log' dialog + $('#logAnalyseDialog .datetimefield').each(function() { + PMA_addDatepicker($(this)); + }); + + /**** Monitor charting implementation ****/ + /* Saves the previous ajax response for differential values */ + var oldChartData = null; + // Holds about to be created chart + var newChart = null; + var chartSpacing; + + // Whenever the monitor object (runtime.charts) or the settings object + // (monitorSettings) changes in a way incompatible to the previous version, + // increase this number. It will reset the users monitor and settings object + // in his localStorage to the default configuration + var monitorProtocolVersion = '1.0'; + + // Runtime parameter of the monitor, is being fully set in initGrid() + runtime = { + // Holds all visible charts in the grid + charts: null, + // Stores the timeout handler so it can be cleared + refreshTimeout: null, + // Stores the GET request to refresh the charts + refreshRequest: null, + // Chart auto increment + chartAI: 0, + // To play/pause the monitor + redrawCharts: false, + // Object that contains a list of nodes that need to be retrieved + // from the server for chart updates + dataList: [], + // Current max points per chart (needed for auto calculation) + gridMaxPoints: 20, + // displayed time frame + xmin: -1, + xmax: -1 + }; + var monitorSettings = null; + + var defaultMonitorSettings = { + columns: 3, + chartSize: { width: 295, height: 250 }, + // Max points in each chart. Settings it to 'auto' sets + // gridMaxPoints to (chartwidth - 40) / 12 + gridMaxPoints: 'auto', + /* Refresh rate of all grid charts in ms */ + gridRefresh: 5000 + }; + + // Allows drag and drop rearrange and print/edit icons on charts + var editMode = false; + + /* List of preconfigured charts that the user may select */ + var presetCharts = { + // Query cache efficiency + 'qce': { + title: PMA_messages['strQueryCacheEfficiency'], + series: [ { + label: PMA_messages['strQueryCacheEfficiency'] + } ], + nodes: [ { + dataPoints: [{type: 'statusvar', name: 'Qcache_hits'}, {type: 'statusvar', name: 'Com_select'}], + transformFn: 'qce' + } ], + maxYLabel: 0 + }, + // Query cache usage + 'qcu': { + title: PMA_messages['strQueryCacheUsage'], + series: [ { + label: PMA_messages['strQueryCacheUsed'] + } ], + nodes: [ { + dataPoints: [{type: 'statusvar', name: 'Qcache_free_memory'}, {type: 'servervar', name: 'query_cache_size'}], + transformFn: 'qcu' + } ], + maxYLabel: 0 + } + }; + + // time span selection + var selectionTimeDiff = []; + var selectionStartX, selectionStartY, selectionEndX, selectionEndY; + var drawTimeSpan = false; + + // chart tooltip + var tooltipBox; + + /* Add OS specific system info charts to the preset chart list */ + switch(server_os) { + case 'WINNT': + $.extend(presetCharts, { + 'cpu': { + title: PMA_messages['strSystemCPUUsage'], + series: [ { + label: PMA_messages['strAverageLoad'] + } ], + nodes: [ { + dataPoints: [{ type: 'cpu', name: 'loadavg'}] + } ], + maxYLabel: 100 + }, + + 'memory': { + title: PMA_messages['strSystemMemory'], + series: [ { + label: PMA_messages['strTotalMemory'], + fill:true + }, { + dataType: 'memory', + label: PMA_messages['strUsedMemory'], + fill:true + } ], + nodes: [{ dataPoints: [{ type: 'memory', name: 'MemTotal' }], valueDivisor: 1024 }, + { dataPoints: [{ type: 'memory', name: 'MemUsed' }], valueDivisor: 1024 } + ], + maxYLabel: 0 + }, + + 'swap': { + title: PMA_messages['strSystemSwap'], + series: [ { + label: PMA_messages['strTotalSwap'], + fill:true + }, { + label: PMA_messages['strUsedSwap'], + fill:true + } ], + nodes: [{ dataPoints: [{ type: 'memory', name: 'SwapTotal' }]}, + { dataPoints: [{ type: 'memory', name: 'SwapUsed' }]} + ], + maxYLabel: 0 + } + }); + break; + + case 'Linux': + $.extend(presetCharts, { + 'cpu': { + title: PMA_messages['strSystemCPUUsage'], + series: [ { + label: PMA_messages['strAverageLoad'] + } ], + nodes: [{ dataPoints: [{ type: 'cpu', name: 'irrelevant' }], transformFn: 'cpu-linux'}], + maxYLabel: 0 + }, + 'memory': { + title: PMA_messages['strSystemMemory'], + series: [ + { label: PMA_messages['strBufferedMemory'], fill:true}, + { label: PMA_messages['strUsedMemory'], fill:true}, + { label: PMA_messages['strCachedMemory'], fill:true}, + { label: PMA_messages['strFreeMemory'], fill:true} + ], + nodes: [ + { dataPoints: [{ type: 'memory', name: 'Buffers' }], valueDivisor: 1024 }, + { dataPoints: [{ type: 'memory', name: 'MemUsed' }], valueDivisor: 1024 }, + { dataPoints: [{ type: 'memory', name: 'Cached' }], valueDivisor: 1024 }, + { dataPoints: [{ type: 'memory', name: 'MemFree' }], valueDivisor: 1024 } + ], + maxYLabel: 0 + }, + 'swap': { + title: PMA_messages['strSystemSwap'], + series: [ + { label: PMA_messages['strCachedSwap'], fill:true}, + { label: PMA_messages['strUsedSwap'], fill:true}, + { label: PMA_messages['strFreeSwap'], fill:true} + ], + nodes: [ + { dataPoints: [{ type: 'memory', name: 'SwapCached' }], valueDivisor: 1024 }, + { dataPoints: [{ type: 'memory', name: 'SwapUsed' }], valueDivisor: 1024 }, + { dataPoints: [{ type: 'memory', name: 'SwapFree' }], valueDivisor: 1024 } + ], + maxYLabel: 0 + } + }); + break; + + case 'SunOS': + $.extend(presetCharts, { + 'cpu': { + title: PMA_messages['strSystemCPUUsage'], + series: [ { + label: PMA_messages['strAverageLoad'] + } ], + nodes: [ { + dataPoints: [{ type: 'cpu', name: 'loadavg'}] + } ], + maxYLabel: 0 + }, + 'memory': { + title: PMA_messages['strSystemMemory'], + series: [ + { label: PMA_messages['strUsedMemory'], fill:true }, + { label: PMA_messages['strFreeMemory'], fill:true } + ], + nodes: [ + { dataPoints: [{ type: 'memory', name: 'MemUsed' }], valueDivisor: 1024 }, + { dataPoints: [{ type: 'memory', name: 'MemFree' }], valueDivisor: 1024 } + ], + maxYLabel: 0 + }, + 'swap': { + title: PMA_messages['strSystemSwap'], + series: [ + { label: PMA_messages['strUsedSwap'], fill:true }, + { label: PMA_messages['strFreeSwap'], fill:true } + ], + nodes: [ + { dataPoints: [{ type: 'memory', name: 'SwapUsed' }], valueDivisor: 1024 }, + { dataPoints: [{ type: 'memory', name: 'SwapFree' }], valueDivisor: 1024 } + ], + maxYLabel: 0 + } + }); + break; + } + + // Default setting for the chart grid + var defaultChartGrid = { + 'c0': { title: PMA_messages['strQuestions'], + series: [{label: PMA_messages['strQuestions']}], + nodes: [{dataPoints: [{ type: 'statusvar', name: 'Questions' }], display: 'differential' }], + maxYLabel: 0 + }, + 'c1': { + title: PMA_messages['strChartConnectionsTitle'], + series: [ { label: PMA_messages['strConnections']}, + { label: PMA_messages['strProcesses']} ], + nodes: [ { dataPoints: [{ type: 'statusvar', name: 'Connections' }], display: 'differential' }, + { dataPoints: [{ type: 'proc', name: 'processes' }] } + ], + maxYLabel: 0 + }, + 'c2': { + title: PMA_messages['strTraffic'], + series: [ + { label: PMA_messages['strBytesSent']}, + { label: PMA_messages['strBytesReceived']} + ], + nodes: [ + { dataPoints: [{ type: 'statusvar', name: 'Bytes_sent' }], display: 'differential', valueDivisor: 1024 }, + { dataPoints: [{ type: 'statusvar', name: 'Bytes_received' }], display: 'differential', valueDivisor: 1024 } + ], + maxYLabel: 0 + } + }; + + // Server is localhost => We can add cpu/memory/swap to the default chart + if (server_db_isLocal) { + defaultChartGrid['c3'] = presetCharts['cpu']; + defaultChartGrid['c4'] = presetCharts['memory']; + defaultChartGrid['c5'] = presetCharts['swap']; + } + + /* Buttons that are on the top right corner of each chart */ + var gridbuttons = { + cogButton: { + //enabled: true, + symbol: 'url(' + pmaThemeImage + 's_cog.png)', + x: -36, + symbolFill: '#B5C9DF', + hoverSymbolFill: '#779ABF', + _titleKey: 'settings', + menuName: 'gridsettings', + menuItems: [{ + textKey: 'editChart', + onclick: function() { + editChart(this); + } + }, { + textKey: 'removeChart', + onclick: function() { + removeChart(this); + } + }] + } + }; + + $('a[href="#rearrangeCharts"], a[href="#endChartEditMode"]').click(function(event) { + event.preventDefault(); + editMode = !editMode; + if ($(this).attr('href') == '#endChartEditMode') { + editMode = false; + } + + // Icon graphics have zIndex 19, 20 and 21. + // Let's just hope nothing else has the same zIndex + $('#chartGrid div svg').find('*[zIndex=20], *[zIndex=21], *[zIndex=19]').toggle(editMode); + + $('a[href="#endChartEditMode"]').toggle(editMode); + + if (editMode) { + // Close the settings popup + $('div.popupContent').hide().removeClass('openedPopup'); + + $("#chartGrid").sortableTable({ + ignoreRect: { + top: 8, + left: chartSize().width - 63, + width: 54, + height: 24 + }, + events: { + // Drop event. The drag child element is moved into the drop element + // and vice versa. So the parameters are switched. + drop: function(drag, drop, pos) { + var dragKey, dropKey, dropRender; + var dragRender = $(drag).children().first().attr('id'); + + if ($(drop).children().length > 0) { + dropRender = $(drop).children().first().attr('id'); + } + + // Find the charts in the array + $.each(runtime.charts, function(key, value) { + if (value.chart.options.chart.renderTo == dragRender) { + dragKey = key; + } + if (dropRender && value.chart.options.chart.renderTo == dropRender) { + dropKey = key; + } + }); + + // Case 1: drag and drop are charts -> Switch keys + if (dropKey) { + if (dragKey) { + dragChart = runtime.charts[dragKey]; + runtime.charts[dragKey] = runtime.charts[dropKey]; + runtime.charts[dropKey] = dragChart; + } else { + // Case 2: drop is a empty cell => just completely rebuild the ids + var keys = []; + var dropKeyNum = parseInt(dropKey.substr(1)); + var insertBefore = pos.col + pos.row * monitorSettings.columns; + var values = []; + var newChartList = {}; + var c = 0; + + $.each(runtime.charts, function(key, value) { + if (key != dropKey) { + keys.push(key); + } + }); + + keys.sort(); + + // Rebuilds all ids, with the dragged chart correctly inserted + for (var i = 0; i<keys.length; i++) { + if (keys[i] == insertBefore) { + newChartList['c' + (c++)] = runtime.charts[dropKey]; + insertBefore = -1; // Insert ok + } + newChartList['c' + (c++)] = runtime.charts[keys[i]]; + } + + // Not inserted => put at the end + if (insertBefore != -1) { + newChartList['c' + (c++)] = runtime.charts[dropKey]; + } + + runtime.charts = newChartList; + } + + saveMonitor(); + } + } + } + }); + + } else { + $("#chartGrid").sortableTable('destroy'); + saveMonitor(); // Save settings + } + + return false; + }); + + // global settings + $('div.popupContent select[name="chartColumns"]').change(function() { + monitorSettings.columns = parseInt(this.value); + + var newSize = chartSize(); + + // Empty cells should keep their size so you can drop onto them + $('#chartGrid tr td').css('width', newSize.width + 'px'); + + /* Reorder all charts that it fills all column cells */ + var numColumns; + var $tr = $('#chartGrid tr:first'); + var row = 0; + while($tr.length != 0) { + numColumns = 1; + // To many cells in one row => put into next row + $tr.find('td').each(function() { + if (numColumns > monitorSettings.columns) { + if ($tr.next().length == 0) { + $tr.after('<tr></tr>'); + } + $tr.next().prepend($(this)); + } + numColumns++; + }); + + // To little cells in one row => for each cell to little, + // move all cells backwards by 1 + if ($tr.next().length > 0) { + var cnt = monitorSettings.columns - $tr.find('td').length; + for (var i = 0; i < cnt; i++) { + $tr.append($tr.next().find('td:first')); + $tr.nextAll().each(function() { + if ($(this).next().length != 0) { + $(this).append($(this).next().find('td:first')); + } + }); + } + } + + $tr = $tr.next(); + row++; + } + + /* Apply new chart size to all charts */ + $.each(runtime.charts, function(key, value) { + value.chart.setSize( + newSize.width, + newSize.height, + false + ); + }); + + if (monitorSettings.gridMaxPoints == 'auto') { + runtime.gridMaxPoints = Math.round((newSize.width - 40) / 12); + } + + runtime.xmin = new Date().getTime() - server_time_diff - runtime.gridMaxPoints * monitorSettings.gridRefresh; + runtime.xmax = new Date().getTime() - server_time_diff + monitorSettings.gridRefresh; + + if (editMode) { + $("#chartGrid").sortableTable('refresh'); + } + + saveMonitor(); // Save settings + }); + + $('div.popupContent select[name="gridChartRefresh"]').change(function() { + monitorSettings.gridRefresh = parseInt(this.value) * 1000; + clearTimeout(runtime.refreshTimeout); + + if (runtime.refreshRequest) { + runtime.refreshRequest.abort(); + } + + runtime.xmin = new Date().getTime() - server_time_diff - runtime.gridMaxPoints * monitorSettings.gridRefresh; + // fixing chart shift towards left on refresh rate change + //runtime.xmax = new Date().getTime() - server_time_diff + monitorSettings.gridRefresh; + runtime.refreshTimeout = setTimeout(refreshChartGrid, monitorSettings.gridRefresh); + + saveMonitor(); // Save settings + }); + + $('a[href="#addNewChart"]').click(function(event) { + event.preventDefault(); + var dlgButtons = { }; + + dlgButtons[PMA_messages['strAddChart']] = function() { + var type = $('input[name="chartType"]:checked').val(); + + if (type == 'preset') { + newChart = presetCharts[$('#addChartDialog select[name="presetCharts"]').prop('value')]; + } else { + // If user builds his own chart, it's being set/updated + // each time he adds a series + // So here we only warn if he didn't add a series yet + if (! newChart || ! newChart.nodes || newChart.nodes.length == 0) { + alert(PMA_messages['strAddOneSeriesWarning']); + return; + } + } + + newChart.title = $('input[name="chartTitle"]').val(); + // Add a cloned object to the chart grid + addChart($.extend(true, {}, newChart)); + + newChart = null; + + saveMonitor(); // Save settings + + $(this).dialog("close"); + }; + + dlgButtons[PMA_messages['strClose']] = function() { + newChart = null; + $('span#clearSeriesLink').hide(); + $('#seriesPreview').html(''); + $(this).dialog("close"); + }; + + var $presetList = $('#addChartDialog select[name="presetCharts"]'); + if ($presetList.html().length == 0) { + $.each(presetCharts, function(key, value) { + $presetList.append('<option value="' + key + '">' + value.title + '</option>'); + }); + $presetList.change(function() { + $('input[name="chartTitle"]').val( + $presetList.find(':selected').text() + ); + $('#chartPreset').prop('checked', true); + }); + $('#chartPreset').click(function () { + $('input[name="chartTitle"]').val( + $presetList.find(':selected').text() + ); + }); + $('#chartStatusVar').click(function () { + $('input[name="chartTitle"]').val( + $('#chartSeries').find(':selected').text().replace(/_/g, " ") + ); + }); + $('#chartSeries').change(function () { + $('input[name="chartTitle"]').val( + $('#chartSeries').find(':selected').text().replace(/_/g, " ") + ); + }); + } + + $('#addChartDialog').dialog({ + width: 'auto', + height: 'auto', + buttons: dlgButtons + }); + + $('#addChartDialog #seriesPreview').html('<i>' + PMA_messages['strNone'] + '</i>'); + + return false; + }); + + $('a[href="#exportMonitorConfig"]').click(function(event) { + event.preventDefault(); + var gridCopy = {}; + $.each(runtime.charts, function(key, elem) { + gridCopy[key] = {}; + gridCopy[key].nodes = elem.nodes; + gridCopy[key].settings = elem.settings; + gridCopy[key].title = elem.title; + }); + var exportData = { + monitorCharts: gridCopy, + monitorSettings: monitorSettings + }; + $('<form />', { + "class": "disableAjax", + method: "post", + action: "file_echo.php?" + PMA_commonParams.get('common_query') + "&filename=1", + style: "display:none;" + }) + .append( + $('<input />', { + type: "hidden", + name: "monitorconfig", + value: $.toJSON(exportData) + }) + ) + .appendTo('body') + .submit() + .remove(); + }); + + $('a[href="#importMonitorConfig"]').click(function(event) { + event.preventDefault(); + $('#emptyDialog').dialog({title: PMA_messages['strImportDialogTitle']}); + $('#emptyDialog').html(PMA_messages['strImportDialogMessage'] + ':<br/><form action="file_echo.php?' + PMA_commonParams.get('common_query') + '&import=1" method="post" enctype="multipart/form-data">' + + '<input type="file" name="file"> <input type="hidden" name="import" value="1"> </form>'); + + var dlgBtns = {}; + + dlgBtns[PMA_messages['strImport']] = function() { + var $iframe, $form; + $('body').append($iframe = $('<iframe id="monitorConfigUpload" style="display:none;"></iframe>')); + var d = $iframe[0].contentWindow.document; + d.open(); d.close(); + mew = d; + + $iframe.load(function() { + var json; + + // Try loading config + try { + var data = $('body', $('iframe#monitorConfigUpload')[0].contentWindow.document).html(); + // Chrome wraps around '<pre style="word-wrap: break-word; white-space: pre-wrap;">' to any text content -.- + json = $.secureEvalJSON(data.substring(data.indexOf("{"), data.lastIndexOf("}") + 1)); + } catch (err) { + alert(PMA_messages['strFailedParsingConfig']); + $('#emptyDialog').dialog('close'); + return; + } + + // Basic check, is this a monitor config json? + if (!json || ! json.monitorCharts || ! json.monitorCharts) { + alert(PMA_messages['strFailedParsingConfig']); + $('#emptyDialog').dialog('close'); + return; + } + + // If json ok, try applying config + try { + window.localStorage['monitorCharts'] = $.toJSON(json.monitorCharts); + window.localStorage['monitorSettings'] = $.toJSON(json.monitorSettings); + rebuildGrid(); + } catch(err) { + alert(PMA_messages['strFailedBuildingGrid']); + // If an exception is thrown, load default again + window.localStorage.removeItem('monitorCharts'); + window.localStorage.removeItem('monitorSettings'); + rebuildGrid(); + } + + $('#emptyDialog').dialog('close'); + }); + + $("body", d).append($form = $('#emptyDialog').find('form')); + $form.submit(); + $('#emptyDialog').append('<img class="ajaxIcon" src="' + pmaThemeImage + 'ajax_clock_small.gif" alt="">'); + }; + + dlgBtns[PMA_messages['strCancel']] = function() { + $(this).dialog('close'); + }; + + + $('#emptyDialog').dialog({ + width: 'auto', + height: 'auto', + buttons: dlgBtns + }); + }); + + $('a[href="#clearMonitorConfig"]').click(function(event) { + event.preventDefault(); + window.localStorage.removeItem('monitorCharts'); + window.localStorage.removeItem('monitorSettings'); + window.localStorage.removeItem('monitorVersion'); + $(this).hide(); + rebuildGrid(); + }); + + $('a[href="#pauseCharts"]').click(function(event) { + event.preventDefault(); + runtime.redrawCharts = ! runtime.redrawCharts; + if (! runtime.redrawCharts) { + $(this).html(PMA_getImage('play.png') + ' ' + PMA_messages['strResumeMonitor']); + } else { + $(this).html(PMA_getImage('pause.png') + ' ' + PMA_messages['strPauseMonitor']); + if (! runtime.charts) { + initGrid(); + $('a[href="#settingsPopup"]').show(); + } + } + return false; + }); + + $('a[href="#monitorInstructionsDialog"]').click(function(event) { + event.preventDefault(); + + var $dialog = $('#monitorInstructionsDialog'); + + $dialog.dialog({ + width: 595, + height: 'auto' + }).find('img.ajaxIcon').show(); + + var loadLogVars = function(getvars) { + var vars = { ajax_request: true, logging_vars: true }; + if (getvars) { + $.extend(vars, getvars); + } + + $.get('server_status_monitor.php?' + PMA_commonParams.get('common_query'), vars, + function(data) { + var logVars; + if (data.success == true) { + logVars = data.message; + } else { + return serverResponseError(); + } + var icon = PMA_getImage('s_success.png'), msg='', str=''; + + if (logVars['general_log'] == 'ON') { + if (logVars['slow_query_log'] == 'ON') { + msg = PMA_messages['strBothLogOn']; + } else { + msg = PMA_messages['strGenLogOn']; + } + } + + if (msg.length == 0 && logVars['slow_query_log'] == 'ON') { + msg = PMA_messages['strSlowLogOn']; + } + + if (msg.length == 0) { + icon = PMA_getImage('s_error.png'); + msg = PMA_messages['strBothLogOff']; + } + + str = '<b>' + PMA_messages['strCurrentSettings'] + '</b><br/><div class="smallIndent">'; + str += icon + msg + '<br />'; + + if (logVars['log_output'] != 'TABLE') { + str += PMA_getImage('s_error.png') + ' ' + PMA_messages['strLogOutNotTable'] + '<br />'; + } else { + str += PMA_getImage('s_success.png') + ' ' + PMA_messages['strLogOutIsTable'] + '<br />'; + } + + if (logVars['slow_query_log'] == 'ON') { + if (logVars['long_query_time'] > 2) { + str += PMA_getImage('s_attention.png') + ' ' + + $.sprintf(PMA_messages['strSmallerLongQueryTimeAdvice'], logVars['long_query_time']) + + '<br />'; + } + + if (logVars['long_query_time'] < 2) { + str += PMA_getImage('s_success.png') + ' ' + + $.sprintf(PMA_messages['strLongQueryTimeSet'], logVars['long_query_time']) + + '<br />'; + } + } + + str += '</div>'; + + if (is_superuser) { + str += '<p></p><b>' + PMA_messages['strChangeSettings'] + '</b>'; + str += '<div class="smallIndent">'; + str += PMA_messages['strSettingsAppliedGlobal'] + '<br/>'; + + var varValue = 'TABLE'; + if (logVars['log_output'] == 'TABLE') { + varValue = 'FILE'; + } + + str += '- <a class="set" href="#log_output-' + varValue + '">' + + $.sprintf(PMA_messages['strSetLogOutput'], varValue) + + ' </a><br />'; + + if (logVars['general_log'] != 'ON') { + str += '- <a class="set" href="#general_log-ON">' + + $.sprintf(PMA_messages['strEnableVar'], 'general_log') + + ' </a><br />'; + } else { + str += '- <a class="set" href="#general_log-OFF">' + + $.sprintf(PMA_messages['strDisableVar'], 'general_log') + + ' </a><br />'; + } + + if (logVars['slow_query_log'] != 'ON') { + str += '- <a class="set" href="#slow_query_log-ON">' + + $.sprintf(PMA_messages['strEnableVar'], 'slow_query_log') + + ' </a><br />'; + } else { + str += '- <a class="set" href="#slow_query_log-OFF">' + + $.sprintf(PMA_messages['strDisableVar'], 'slow_query_log') + + ' </a><br />'; + } + + varValue = 5; + if (logVars['long_query_time'] > 2) { + varValue = 1; + } + + str += '- <a class="set" href="#long_query_time-' + varValue + '">' + + $.sprintf(PMA_messages['setSetLongQueryTime'], varValue) + + ' </a><br />'; + + } else { + str += PMA_messages['strNoSuperUser'] + '<br/>'; + } + + str += '</div>'; + + $dialog.find('div.monitorUse').toggle( + logVars['log_output'] == 'TABLE' && (logVars['slow_query_log'] == 'ON' || logVars['general_log'] == 'ON') + ); + + $dialog.find('div.ajaxContent').html(str); + $dialog.find('img.ajaxIcon').hide(); + $dialog.find('a.set').click(function() { + var nameValue = $(this).attr('href').split('-'); + loadLogVars({ varName: nameValue[0].substr(1), varValue: nameValue[1]}); + $dialog.find('img.ajaxIcon').show(); + }); + } + ); + }; + + + loadLogVars(); + + return false; + }); + + $('input[name="chartType"]').change(function() { + $('#chartVariableSettings').toggle(this.checked && this.value == 'variable'); + var title = $('input[name="chartTitle"]').val(); + if (title == PMA_messages['strChartTitle'] + || title == $('label[for="' + $('input[name="chartTitle"]').data('lastRadio') + '"]').text() + ) { + $('input[name="chartTitle"]') + .data('lastRadio', $(this).attr('id')) + .val($('label[for="' + $(this).attr('id') + '"]').text()); + } + + }); + + $('input[name="useDivisor"]').change(function() { + $('span.divisorInput').toggle(this.checked); + }); + + $('input[name="useUnit"]').change(function() { + $('span.unitInput').toggle(this.checked); + }); + + $('select[name="varChartList"]').change(function () { + if (this.selectedIndex != 0) { + $('#variableInput').val(this.value); + } + }); + + $('a[href="#kibDivisor"]').click(function(event) { + event.preventDefault(); + $('input[name="valueDivisor"]').val(1024); + $('input[name="valueUnit"]').val(PMA_messages['strKiB']); + $('span.unitInput').toggle(true); + $('input[name="useUnit"]').prop('checked', true); + return false; + }); + + $('a[href="#mibDivisor"]').click(function(event) { + event.preventDefault(); + $('input[name="valueDivisor"]').val(1024*1024); + $('input[name="valueUnit"]').val(PMA_messages['strMiB']); + $('span.unitInput').toggle(true); + $('input[name="useUnit"]').prop('checked', true); + return false; + }); + + $('a[href="#submitClearSeries"]').click(function(event) { + event.preventDefault(); + $('#seriesPreview').html('<i>' + PMA_messages['strNone'] + '</i>'); + newChart = null; + $('#clearSeriesLink').hide(); + }); + + $('a[href="#submitAddSeries"]').click(function(event) { + event.preventDefault(); + if ($('#variableInput').val() == "") { + return false; + } + + if (newChart == null) { + $('#seriesPreview').html(''); + + newChart = { + title: $('input[name="chartTitle"]').val(), + nodes: [], + series: [], + maxYLabel: 0 + }; + } + + var serie = { + dataPoints: [{ type: 'statusvar', name: $('#variableInput').val() }], + display: $('input[name="differentialValue"]').prop('checked') ? 'differential' : '' + }; + + if (serie.dataPoints[0].name == 'Processes') { + serie.dataPoints[0].type ='proc'; + } + + if ($('input[name="useDivisor"]').prop('checked')) { + serie.valueDivisor = parseInt($('input[name="valueDivisor"]').val()); + } + + if ($('input[name="useUnit"]').prop('checked')) { + serie.unit = $('input[name="valueUnit"]').val(); + } + + var str = serie.display == 'differential' ? ', ' + PMA_messages['strDifferential'] : ''; + str += serie.valueDivisor ? (', ' + $.sprintf(PMA_messages['strDividedBy'], serie.valueDivisor)) : ''; + str += serie.unit ? (', ' + PMA_messages['strUnit'] + ': ' + serie.unit) : ''; + + var newSeries = { + label: $('#variableInput').val().replace(/_/g, " ") + }; + newChart.series.push(newSeries); + $('#seriesPreview').append('- ' + newSeries.label + str + '<br/>'); + newChart.nodes.push(serie); + $('#variableInput').val(''); + $('input[name="differentialValue"]').prop('checked', true); + $('input[name="useDivisor"]').prop('checked', false); + $('input[name="useUnit"]').prop('checked', false); + $('input[name="useDivisor"]').trigger('change'); + $('input[name="useUnit"]').trigger('change'); + $('select[name="varChartList"]').get(0).selectedIndex = 0; + + $('#clearSeriesLink').show(); + + return false; + }); + + $("#variableInput").autocomplete({ + source: variableNames + }); + + /* Initializes the monitor, called only once */ + function initGrid() { + + /* Apply default values & config */ + if (window.localStorage) { + if (window.localStorage['monitorCharts']) { + runtime.charts = $.parseJSON(window.localStorage['monitorCharts']); + } + if (window.localStorage['monitorSettings']) { + monitorSettings = $.parseJSON(window.localStorage['monitorSettings']); + } + + $('a[href="#clearMonitorConfig"]').toggle(runtime.charts != null); + + if (runtime.charts != null && monitorProtocolVersion != window.localStorage['monitorVersion']) { + $('#emptyDialog').dialog({title: PMA_messages['strIncompatibleMonitorConfig']}); + $('#emptyDialog').html(PMA_messages['strIncompatibleMonitorConfigDescription']); + + var dlgBtns = {}; + dlgBtns[PMA_messages['strClose']] = function() { $(this).dialog('close'); }; + + $('#emptyDialog').dialog({ + width: 400, + buttons: dlgBtns + }); + } + } + + if (runtime.charts == null) { + runtime.charts = defaultChartGrid; + } + if (monitorSettings == null) { + monitorSettings = defaultMonitorSettings; + } + + $('select[name="gridChartRefresh"]').val(monitorSettings.gridRefresh / 1000); + $('select[name="chartColumns"]').val(monitorSettings.columns); + + if (monitorSettings.gridMaxPoints == 'auto') { + runtime.gridMaxPoints = Math.round((monitorSettings.chartSize.width - 40) / 12); + } else { + runtime.gridMaxPoints = monitorSettings.gridMaxPoints; + } + + runtime.xmin = new Date().getTime() - server_time_diff - runtime.gridMaxPoints * monitorSettings.gridRefresh; + runtime.xmax = new Date().getTime() - server_time_diff + monitorSettings.gridRefresh; + + /* Calculate how much spacing there is between each chart */ + $('#chartGrid').html('<tr><td></td><td></td></tr><tr><td></td><td></td></tr>'); + chartSpacing = { + width: $('#chartGrid td:nth-child(2)').offset().left + - $('#chartGrid td:nth-child(1)').offset().left, + height: $('#chartGrid tr:nth-child(2) td:nth-child(2)').offset().top + - $('#chartGrid tr:nth-child(1) td:nth-child(1)').offset().top + }; + $('#chartGrid').html(''); + + /* Add all charts - in correct order */ + var keys = []; + $.each(runtime.charts, function(key, value) { + keys.push(key); + }); + keys.sort(); + for (var i = 0; i < keys.length; i++) { + addChart(runtime.charts[keys[i]], true); + } + + /* Fill in missing cells */ + var numCharts = $('#chartGrid .monitorChart').length; + var numMissingCells = (monitorSettings.columns - numCharts % monitorSettings.columns) % monitorSettings.columns; + for (var i = 0; i < numMissingCells; i++) { + $('#chartGrid tr:last').append('<td></td>'); + } + + // Empty cells should keep their size so you can drop onto them + $('#chartGrid tr td').css('width', chartSize().width + 'px'); + + buildRequiredDataList(); + refreshChartGrid(); + } + + /* Calls destroyGrid() and initGrid(), but before doing so it saves the chart + * data from each chart and restores it after the monitor is initialized again */ + function rebuildGrid() { + var oldData = null; + if (runtime.charts) { + oldData = {}; + $.each(runtime.charts, function(key, chartObj) { + for (var i = 0, l = chartObj.nodes.length; i < l; i++) { + oldData[chartObj.nodes[i].dataPoint] = []; + for (var j = 0, ll = chartObj.chart.series[i].data.length; j < ll; j++) { + oldData[chartObj.nodes[i].dataPoint].push([chartObj.chart.series[i].data[j].x, chartObj.chart.series[i].data[j].y]); + } + } + }); + } + + destroyGrid(); + initGrid(); + + if (oldData) { + $.each(runtime.charts, function(key, chartObj) { + for (var j = 0, l = chartObj.nodes.length; j < l; j++) { + if (oldData[chartObj.nodes[j].dataPoint]) { + chartObj.chart.series[j].setData(oldData[chartObj.nodes[j].dataPoint]); + } + } + }); + } + } + + /* Calculactes the dynamic chart size that depends on the column width */ + function chartSize() { + var wdt = $('#logTable').innerWidth() / monitorSettings.columns - (monitorSettings.columns - 1) * chartSpacing.width; + return { + width: wdt, + height: 0.75 * wdt + }; + } + + /* Adds a chart to the chart grid */ + function addChart(chartObj, initialize) { + + var settings = { + title: escapeHtml(chartObj.title), + grid: { + drawBorder: false, + shadow: false, + background: 'rgba(0,0,0,0)' + }, + axes: { + xaxis: { + renderer: $.jqplot.DateAxisRenderer, + tickOptions: { + formatString: '%H:%M:%S', + showGridline: false + }, + min: runtime.xmin, + max: runtime.xmax + }, + yaxis: { + min:0, + max:100, + tickInterval: 20 + } + }, + seriesDefaults: { + rendererOptions: { + smooth: true + }, + showLine: true, + lineWidth: 2 + }, + highlighter: { + show: true + } + }; + + if (settings.title === PMA_messages['strSystemCPUUsage'] + || settings.title === PMA_messages['strQueryCacheEfficiency']) { + settings.axes.yaxis.tickOptions = { + formatString: "%d %%" + }; + } else if (settings.title === PMA_messages['strSystemMemory'] + || settings.title === PMA_messages['strSystemSwap'] + ) { + settings.stackSeries = true; + settings.axes.yaxis.tickOptions = { + formatter: $.jqplot.byteFormatter(2) // MiB + }; + } else if (settings.title === PMA_messages['strTraffic']) { + settings.axes.yaxis.tickOptions = { + formatter: $.jqplot.byteFormatter(1) // KiB + }; + } else if (settings.title === PMA_messages.strQuestions + || settings.title === PMA_messages.strConnections + ) { + settings.axes.yaxis.tickOptions = { + formatter: function(format, val) { + if (Math.abs(val) >= 1000000) + return $.jqplot.sprintf("%.3g M", val/1000000); + else if (Math.abs(val) >= 1000) + return $.jqplot.sprintf("%.3g k", val/1000); + else + return $.jqplot.sprintf("%d", val); + } + }; + } + + settings.series = chartObj.series; + + if ($('#' + 'gridchart' + runtime.chartAI).length == 0) { + var numCharts = $('#chartGrid .monitorChart').length; + + if (numCharts == 0 || !( numCharts % monitorSettings.columns)) { + $('#chartGrid').append('<tr></tr>'); + } + + $('#chartGrid tr:last').append('<td><div id="gridChartContainer' + + runtime.chartAI + '" class=""><div class="ui-state-default monitorChart" id="' + + 'gridchart' + runtime.chartAI + '"></div></div></td>'); + } + + // Set series' data as [0,0], smooth lines won't plot with data array having null values. + // also chart won't plot initially with no data and data comes on refreshChartGrid() + var series = []; + for (i in chartObj.series) { + series.push([[0,0]]); + } + + // set Tooltip for each series + for(i in settings.series) { + settings.series[i].highlighter = { + show: true, + tooltipContentEditor: function (str, seriesIndex, pointIndex, plot) { + var tooltipHtml = '<div style="font-size:12px;background-color:#FFFFFF;' + + 'opacity:0.95;filter:alpha(opacity=95);padding:5px;">'; + // x value i.e. time + var timeValue = str.split(",")[0]; + tooltipHtml += 'Time: ' + timeValue; + tooltipHtml += '<span style="font-weight:bold;">'; + // Add y values to the tooltip per series + for (j in plot.series) { + // get y value if present + if (plot.series[j].data.length > pointIndex) { + var seriesValue = plot.series[j].data[pointIndex][1]; + } + else { + return; + } + var seriesLabel = plot.series[j].label; + var seriesColor = plot.series[j].color; + // format y value + if (plot.series[0]._yaxis.tickOptions.formatter) { + // using formatter function + seriesValue = plot.series[0]._yaxis.tickOptions.formatter('%s', seriesValue); + } else if (plot.series[0]._yaxis.tickOptions.formatString) { + // using format string + seriesValue = $.sprintf(plot.series[0]._yaxis.tickOptions.formatString, seriesValue); + } + tooltipHtml += '<br /><span style="color:' + seriesColor + '">' + + seriesLabel + ': ' + seriesValue + '</span>'; + } + tooltipHtml += '</span></div>'; + return tooltipHtml; + } + }; + } + + chartObj.chart = $.jqplot('gridchart' + runtime.chartAI, series, settings); + // remove [0,0] after plotting + for (i in chartObj.chart.series) { + chartObj.chart.series[i].data.shift(); + } + + var $legend = $('<div />').css('padding', '0.5em'); + for (var i in chartObj.chart.series) { + $legend.append( + $('<div />').append( + $('<div>').css({ + width: '1em', + height: '1em', + background: chartObj.chart.seriesColors[i] + }).addClass('floatleft') + ).append( + $('<div>').text( + chartObj.chart.series[i].label + ).addClass('floatleft') + ).append( + $('<div class="clearfloat">') + ).addClass('floatleft') + ); + } + $('#gridchart' + runtime.chartAI) + .parent() + .append($legend); + + if (initialize != true) { + runtime.charts['c' + runtime.chartAI] = chartObj; + buildRequiredDataList(); + } + + // time span selection + $('#gridchart' + runtime.chartAI).bind('jqplotMouseDown', function(ev, gridpos, datapos, neighbor, plot) { + drawTimeSpan = true; + selectionTimeDiff.push(datapos.xaxis); + if ($('#selection_box').length) { + $('#selection_box').remove(); + } + selectionBox = $('<div id="selection_box" style="z-index:1000;height:250px;position:absolute;background-color:#87CEEB;opacity:0.4;filter:alpha(opacity=40);pointer-events:none;">'); + $(document.body).append(selectionBox); + selectionStartX = ev.pageX; + selectionStartY = ev.pageY; + selectionBox + .attr({id: 'selection_box'}) + .css({ + top: selectionStartY-gridpos.y, + left: selectionStartX + }) + .fadeIn(); + }); + + $('#gridchart' + runtime.chartAI).bind('jqplotMouseUp', function (ev, gridpos, datapos, neighbor, plot) { + if (! drawTimeSpan || editMode) { + return; + } + + selectionTimeDiff.push(datapos.xaxis); + + if (selectionTimeDiff[1] <= selectionTimeDiff[0]) { + selectionTimeDiff = []; + return; + } + //get date from timestamp + var min = new Date(Math.ceil(selectionTimeDiff[0])); + var max = new Date(Math.ceil(selectionTimeDiff[1])); + PMA_getLogAnalyseDialog(min, max); + selectionTimeDiff = []; + drawTimeSpan = false; + }); + + $('#gridchart' + runtime.chartAI).bind('jqplotMouseMove', function (ev, gridpos, datapos, neighbor, plot) { + if (! drawTimeSpan || editMode) { + return; + } + if (selectionStartX != undefined) { + $('#selection_box') + .css({ + width: Math.ceil(ev.pageX - selectionStartX) + }) + .fadeIn(); + } + }); + + $('#gridchart' + runtime.chartAI).bind('jqplotMouseLeave', function(ev, gridpos, datapos, neighbor, plot) { + drawTimeSpan = false; + }); + + $(document.body).mouseup(function() { + if ($('#selection_box').length) { + selectionBox.remove(); + } + }); + + // Edit, Print icon only in edit mode + $('#chartGrid div svg').find('*[zIndex=20], *[zIndex=21], *[zIndex=19]').toggle(editMode); + + runtime.chartAI++; + } + + /* Opens a dialog that allows one to edit the title and series labels of the supplied chart */ + function editChart(chartObj) { + var htmlnode = chartObj.options.chart.renderTo; + if (! htmlnode ) { + return; + } + + var chart = null; + var chartKey = null; + $.each(runtime.charts, function(key, value) { + if (value.chart.options.chart.renderTo == htmlnode) { + chart = value; + chartKey = key; + return false; + } + }); + + if (chart == null) { + return; + } + + var htmlStr = '<p><b>' + PMA_messages['strChartTitle'] + ': </b> <br/> <input type="text" size="35" name="chartTitle" value="' + chart.title + '" />'; + htmlStr += '</p><p><b>' + PMA_messages['strSeries'] + ':</b> </p><ol>'; + for (var i = 0; i<chart.nodes.length; i++) { + htmlStr += '<li><i>' + chart.nodes[i].dataPoints[0].name + ': </i><br/><input type="text" name="chartSerie-' + i + '" value="' + chart.nodes[i].name + '" /></li>'; + } + + dlgBtns = {}; + dlgBtns[PMA_messages['strSave']] = function() { + runtime.charts[chartKey].title = $('#emptyDialog input[name="chartTitle"]').val(); + runtime.charts[chartKey].chart.setTitle({ text: runtime.charts[chartKey].title }); + + $('#emptyDialog input[name*="chartSerie"]').each(function() { + var $t = $(this); + var idx = $t.attr('name').split('-')[1]; + runtime.charts[chartKey].nodes[idx].name = $t.val(); + runtime.charts[chartKey].chart.series[idx].name = $t.val(); + }); + + $(this).dialog('close'); + saveMonitor(); + }; + dlgBtns[PMA_messages['strCancel']] = function() { + $(this).dialog('close'); + }; + + $('#emptyDialog').html(htmlStr + '</ol>'); + $('#emptyDialog').dialog({ + title: PMA_messages['strChartEdit'], + width: 'auto', + height: 'auto', + buttons: dlgBtns + }); + } + + function PMA_getLogAnalyseDialog(min, max) { + $('#logAnalyseDialog input[name="dateStart"]') + .val(PMA_formatDateTime(min, true)); + $('#logAnalyseDialog input[name="dateEnd"]') + .val(PMA_formatDateTime(max, true)); + + var dlgBtns = { }; + + dlgBtns[PMA_messages['strFromSlowLog']] = function() { + loadLog('slow', min, max); + $(this).dialog("close"); + }; + + dlgBtns[PMA_messages['strFromGeneralLog']] = function() { + loadLog('general', min, max); + $(this).dialog("close"); + }; + + $('#logAnalyseDialog').dialog({ + width: 'auto', + height: 'auto', + buttons: dlgBtns + }); + } + + function loadLog(type, min, max) { + var dateStart = Date.parse($('#logAnalyseDialog input[name="dateStart"]').prop('value')) || min; + var dateEnd = Date.parse($('#logAnalyseDialog input[name="dateEnd"]').prop('value')) || max; + + loadLogStatistics({ + src: type, + start: dateStart, + end: dateEnd, + removeVariables: $('#removeVariables').prop('checked'), + limitTypes: $('#limitTypes').prop('checked') + }); + } + + /* Removes a chart from the grid */ + function removeChart(chartObj) { + var htmlnode = chartObj.options.chart.renderTo; + if (! htmlnode ) { + return; + } + + $.each(runtime.charts, function(key, value) { + if (value.chart.options.chart.renderTo == htmlnode) { + delete runtime.charts[key]; + return false; + } + }); + + buildRequiredDataList(); + + // Using settimeout() because clicking the remove link fires an onclick event + // which throws an error when the chart is destroyed + setTimeout(function() { + chartObj.destroy(); + $('#' + htmlnode).remove(); + }, 10); + + saveMonitor(); // Save settings + } + + /* Called in regular intervalls, this function updates the values of each chart in the grid */ + function refreshChartGrid() { + /* Send to server */ + runtime.refreshRequest = $.post('server_status_monitor.php?' + PMA_commonParams.get('common_query'), { + ajax_request: true, + chart_data: 1, + type: 'chartgrid', + requiredData: $.toJSON(runtime.dataList) + }, function(data) { + var chartData; + if (data.success == true) { + chartData = data.message; + } else { + return serverResponseError(); + } + var value, i = 0; + var diff; + var total; + + /* Update values in each graph */ + $.each(runtime.charts, function(orderKey, elem) { + var key = elem.chartID; + // If newly added chart, we have no data for it yet + if (! chartData[key]) { + return; + } + // Draw all series + total = 0; + for (var j = 0; j < elem.nodes.length; j++) { + // Update x-axis + if (i == 0 && j == 0) { + if (oldChartData == null) { + diff = chartData.x - runtime.xmax; + } else { + diff = parseInt(chartData.x - oldChartData.x); + } + + runtime.xmin += diff; + runtime.xmax += diff; + } + + //elem.chart.xAxis[0].setExtremes(runtime.xmin, runtime.xmax, false); + /* Calculate y value */ + + // If transform function given, use it + if (elem.nodes[j].transformFn) { + value = chartValueTransform( + elem.nodes[j].transformFn, + chartData[key][j], + // Check if first iteration (oldChartData==null), or if newly added chart oldChartData[key]==null + (oldChartData == null || oldChartData[key] == null ? null : oldChartData[key][j]) + ); + + // Otherwise use original value and apply differential and divisor if given, + // in this case we have only one data point per series - located at chartData[key][j][0] + } else { + value = parseFloat(chartData[key][j][0].value); + + if (elem.nodes[j].display == 'differential') { + if (oldChartData == null || oldChartData[key] == null) { + continue; + } + value -= oldChartData[key][j][0].value; + } + + if (elem.nodes[j].valueDivisor) { + value = value / elem.nodes[j].valueDivisor; + } + } + + // Set y value, if defined + if (value != undefined) { + elem.chart.series[j].data.push([chartData.x, value]); + if (value > elem.maxYLabel) { + elem.maxYLabel = value; + } else if (elem.maxYLabel == 0) { + elem.maxYLabel = 0.5; + } + // free old data point values and update maxYLabel + if (elem.chart.series[j].data.length > runtime.gridMaxPoints + && elem.chart.series[j].data[0][0] < runtime.xmin) { + // check if the next freeable point is highest + if (elem.maxYLabel <= elem.chart.series[j].data[0][1]) { + elem.chart.series[j].data.splice(0, elem.chart.series[j].data.length - runtime.gridMaxPoints); + elem.maxYLabel = getMaxYLabel(elem.chart.series[j].data); + } else { + elem.chart.series[j].data.splice(0, elem.chart.series[j].data.length - runtime.gridMaxPoints); + } + } + if (elem.title === PMA_messages['strSystemMemory'] + || elem.title === PMA_messages['strSystemSwap'] + ) { + total += value; + } + } + } + + // update chart options + // keep ticks number/positioning consistent while refreshrate changes + var tickInterval = (runtime.xmax - runtime.xmin)/5; + elem.chart['axes']['xaxis'].ticks = [(runtime.xmax - tickInterval*4), + (runtime.xmax - tickInterval*3), (runtime.xmax - tickInterval*2), + (runtime.xmax - tickInterval), runtime.xmax]; + + if (elem.title !== PMA_messages['strSystemCPUUsage'] + && elem.title !== PMA_messages['strQueryCacheEfficiency'] + && elem.title !== PMA_messages['strSystemMemory'] + && elem.title !== PMA_messages['strSystemSwap'] + ) { + elem.chart['axes']['yaxis']['max'] = Math.ceil(elem.maxYLabel*1.1); + elem.chart['axes']['yaxis']['tickInterval'] = Math.ceil(elem.maxYLabel*1.1/5); + } else if (elem.title === PMA_messages['strSystemMemory'] + || elem.title === PMA_messages['strSystemSwap'] + ) { + elem.chart['axes']['yaxis']['max'] = Math.ceil(total * 1.1 / 100) * 100; + elem.chart['axes']['yaxis']['tickInterval'] = Math.ceil(total * 1.1 / 5); + } + i++; + + if (runtime.redrawCharts) { + elem.chart.replot(); + } + }); + + oldChartData = chartData; + + runtime.refreshTimeout = setTimeout(refreshChartGrid, monitorSettings.gridRefresh); + }); + } + + /* Function to get highest plotted point's y label, to scale the chart, + * TODO: make jqplot's autoscale:true work here + */ + function getMaxYLabel(dataValues) { + var maxY = dataValues[0][1]; + $.each(dataValues,function(k,v){maxY = (v[1]>maxY) ? v[1] : maxY}); + return maxY; + } + + /* Function that supplies special value transform functions for chart values */ + function chartValueTransform(name, cur, prev) { + switch(name) { + case 'cpu-linux': + if (prev == null) { + return undefined; + } + // cur and prev are datapoint arrays, but containing + // only 1 element for cpu-linux + cur = cur[0]; + prev = prev[0]; + + var diff_total = cur.busy + cur.idle - (prev.busy + prev.idle); + var diff_idle = cur.idle - prev.idle; + return 100 * (diff_total - diff_idle) / diff_total; + + // Query cache efficiency (%) + case 'qce': + if (prev == null) { + return undefined; + } + // cur[0].value is Qcache_hits, cur[1].value is Com_select + var diffQHits = cur[0].value - prev[0].value; + // No NaN please :-) + if (cur[1].value - prev[1].value == 0) { + return 0; + } + + return diffQHits / (cur[1].value - prev[1].value + diffQHits) * 100; + + // Query cache usage (%) + case 'qcu': + if (cur[1].value == 0) { + return 0; + } + // cur[0].value is Qcache_free_memory, cur[1].value is query_cache_size + return 100 - cur[0].value / cur[1].value * 100; + + } + return undefined; + } + + /* Build list of nodes that need to be retrieved from server. + * It creates something like a stripped down version of the runtime.charts object. + */ + function buildRequiredDataList() { + runtime.dataList = {}; + // Store an own id, because the property name is subject of reordering, + // thus destroying our mapping with runtime.charts <=> runtime.dataList + var chartID = 0; + $.each(runtime.charts, function(key, chart) { + runtime.dataList[chartID] = []; + for (var i=0, l=chart.nodes.length; i < l; i++) { + runtime.dataList[chartID][i] = chart.nodes[i].dataPoints; + } + runtime.charts[key].chartID = chartID; + chartID++; + }); + } + + /* Loads the log table data, generates the table and handles the filters */ + function loadLogStatistics(opts) { + var tableStr = ''; + var logRequest = null; + + if (! opts.removeVariables) { + opts.removeVariables = false; + } + if (! opts.limitTypes) { + opts.limitTypes = false; + } + + $('#emptyDialog').dialog({title: PMA_messages['strAnalysingLogsTitle']}); + $('#emptyDialog').html(PMA_messages['strAnalysingLogs'] + + ' <img class="ajaxIcon" src="' + pmaThemeImage + + 'ajax_clock_small.gif" alt="">'); + var dlgBtns = {}; + + dlgBtns[PMA_messages['strCancelRequest']] = function() { + if (logRequest != null) { + logRequest.abort(); + } + + $(this).dialog("close"); + }; + + $('#emptyDialog').dialog({ + width: 'auto', + height: 'auto', + buttons: dlgBtns + }); + + + logRequest = $.get('server_status_monitor.php?' + PMA_commonParams.get('common_query'), + { ajax_request: true, + log_data: 1, + type: opts.src, + time_start: Math.round(opts.start / 1000), + time_end: Math.round(opts.end / 1000), + removeVariables: opts.removeVariables, + limitTypes: opts.limitTypes + }, + function(data) { + var logData; + if (data.success == true) { + logData = data.message; + } else { + return serverResponseError(); + } + + if (logData.rows.length != 0) { + runtime.logDataCols = buildLogTable(logData); + + /* Show some stats in the dialog */ + $('#emptyDialog').dialog({title: PMA_messages['strLoadingLogs']}); + $('#emptyDialog').html('<p>' + PMA_messages['strLogDataLoaded'] + '</p>'); + $.each(logData.sum, function(key, value) { + key = key.charAt(0).toUpperCase() + key.slice(1).toLowerCase(); + if (key == 'Total') { + key = '<b>' + key + '</b>'; + } + $('#emptyDialog').append(key + ': ' + value + '<br/>'); + }); + + /* Add filter options if more than a bunch of rows there to filter */ + if (logData.numRows > 12) { + $('#logTable').prepend( + '<fieldset id="logDataFilter">' + + ' <legend>' + PMA_messages['strFiltersForLogTable'] + '</legend>' + + ' <div class="formelement">' + + ' <label for="filterQueryText">' + PMA_messages['strFilterByWordRegexp'] + '</label>' + + ' <input name="filterQueryText" type="text" id="filterQueryText" style="vertical-align: baseline;" />' + + ' </div>' + + ((logData.numRows > 250) ? ' <div class="formelement"><button name="startFilterQueryText" id="startFilterQueryText">' + PMA_messages['strFilter'] + '</button></div>' : '') + + ' <div class="formelement">' + + ' <input type="checkbox" id="noWHEREData" name="noWHEREData" value="1" /> ' + + ' <label for="noWHEREData"> ' + PMA_messages['strIgnoreWhereAndGroup'] + '</label>' + + ' </div' + + '</fieldset>' + ); + + $('#logTable #noWHEREData').change(function() { + filterQueries(true); + }); + + if (logData.numRows > 250) { + $('#logTable #startFilterQueryText').click(filterQueries); + } else { + $('#logTable #filterQueryText').keyup(filterQueries); + } + + } + + var dlgBtns = {}; + dlgBtns[PMA_messages['strJumpToTable']] = function() { + $(this).dialog("close"); + $(document).scrollTop($('#logTable').offset().top); + }; + + $('#emptyDialog').dialog( "option", "buttons", dlgBtns); + + } else { + $('#emptyDialog').dialog({title: PMA_messages['strNoDataFoundTitle']}); + $('#emptyDialog').html('<p>' + PMA_messages['strNoDataFound'] + '</p>'); + + var dlgBtns = {}; + dlgBtns[PMA_messages['strClose']] = function() { + $(this).dialog("close"); + }; + + $('#emptyDialog').dialog( "option", "buttons", dlgBtns ); + } + } + ); + + /* Handles the actions performed when the user uses any of the + * log table filters which are the filter by name and grouping + * with ignoring data in WHERE clauses + * + * @param boolean Should be true when the users enabled or disabled + * to group queries ignoring data in WHERE clauses + */ + function filterQueries(varFilterChange) { + var odd_row = false, cell, textFilter; + var val = $('#logTable #filterQueryText').val(); + + if (val.length == 0) { + textFilter = null; + } else { + textFilter = new RegExp(val, 'i'); + } + + var rowSum = 0, totalSum = 0, i = 0, q; + var noVars = $('#logTable #noWHEREData').prop('checked'); + var equalsFilter = /([^=]+)=(\d+|((\'|"|).*?[^\\])\4((\s+)|$))/gi; + var functionFilter = /([a-z0-9_]+)\(.+?\)/gi; + var filteredQueries = {}, filteredQueriesLines = {}; + var hide = false, rowData; + var queryColumnName = runtime.logDataCols[runtime.logDataCols.length - 2]; + var sumColumnName = runtime.logDataCols[runtime.logDataCols.length - 1]; + var isSlowLog = opts.src == 'slow'; + var columnSums = {}; + + // For the slow log we have to count many columns (query_time, lock_time, rows_examined, rows_sent, etc.) + var countRow = function(query, row) { + var cells = row.match(/<td>(.*?)<\/td>/gi); + if (!columnSums[query]) { + columnSums[query] = [0, 0, 0, 0]; + } + + // lock_time and query_time and displayed in timespan format + columnSums[query][0] += timeToSec(cells[2].replace(/(<td>|<\/td>)/gi, '')); + columnSums[query][1] += timeToSec(cells[3].replace(/(<td>|<\/td>)/gi, '')); + // rows_examind and rows_sent are just numbers + columnSums[query][2] += parseInt(cells[4].replace(/(<td>|<\/td>)/gi, '')); + columnSums[query][3] += parseInt(cells[5].replace(/(<td>|<\/td>)/gi, '')); + }; + + // We just assume the sql text is always in the second last column, and that the total count is right of it + $('#logTable table tbody tr td:nth-child(' + (runtime.logDataCols.length - 1) + ')').each(function() { + var $t = $(this); + // If query is a SELECT and user enabled or disabled to group + // queries ignoring data in where statements, we + // need to re-calculate the sums of each row + if (varFilterChange && $t.html().match(/^SELECT/i)) { + if (noVars) { + // Group on => Sum up identical columns, and hide all but 1 + + q = $t.text().replace(equalsFilter, '$1=...$6').trim(); + q = q.replace(functionFilter, ' $1(...)'); + + // Js does not specify a limit on property name length, + // so we can abuse it as index :-) + if (filteredQueries[q]) { + filteredQueries[q] += parseInt($t.next().text()); + totalSum += parseInt($t.next().text()); + hide = true; + } else { + filteredQueries[q] = parseInt($t.next().text()); + filteredQueriesLines[q] = i; + $t.text(q); + } + if (isSlowLog) { + countRow(q, $t.parent().html()); + } + + } else { + // Group off: Restore original columns + + rowData = $t.parent().data('query'); + // Restore SQL text + $t.text(rowData[queryColumnName]); + // Restore total count + $t.next().text(rowData[sumColumnName]); + // Restore slow log columns + if (isSlowLog) { + $t.parent().children('td:nth-child(3)').text(rowData['query_time']); + $t.parent().children('td:nth-child(4)').text(rowData['lock_time']); + $t.parent().children('td:nth-child(5)').text(rowData['rows_sent']); + $t.parent().children('td:nth-child(6)').text(rowData['rows_examined']); + } + } + } + + // If not required to be hidden, do we need + // to hide because of a not matching text filter? + if (! hide && (textFilter != null && ! textFilter.exec($t.text()))) { + hide = true; + } + + // Now display or hide this column + if (hide) { + $t.parent().css('display', 'none'); + } else { + totalSum += parseInt($t.next().text()); + rowSum++; + + odd_row = ! odd_row; + $t.parent().css('display', ''); + if (odd_row) { + $t.parent().addClass('odd'); + $t.parent().removeClass('even'); + } else { + $t.parent().addClass('even'); + $t.parent().removeClass('odd'); + } + } + + hide = false; + i++; + }); + + // We finished summarizing counts => Update count values of all grouped entries + if (varFilterChange) { + if (noVars) { + var numCol, row, $table = $('#logTable table tbody'); + $.each(filteredQueriesLines, function(key, value) { + if (filteredQueries[key] <= 1) { + return; + } + + row = $table.children('tr:nth-child(' + (value + 1) + ')'); + numCol = row.children(':nth-child(' + (runtime.logDataCols.length) + ')'); + numCol.text(filteredQueries[key]); + + if (isSlowLog) { + row.children('td:nth-child(3)').text(secToTime(columnSums[key][0])); + row.children('td:nth-child(4)').text(secToTime(columnSums[key][1])); + row.children('td:nth-child(5)').text(columnSums[key][2]); + row.children('td:nth-child(6)').text(columnSums[key][3]); + } + }); + } + + $('#logTable table').trigger("update"); + setTimeout(function() { + $('#logTable table').trigger('sorton', [[[runtime.logDataCols.length - 1, 1]]]); + }, 0); + } + + // Display some stats at the bottom of the table + $('#logTable table tfoot tr') + .html('<th colspan="' + (runtime.logDataCols.length - 1) + '">' + + PMA_messages['strSumRows'] + ' ' + rowSum + '<span style="float:right">' + + PMA_messages['strTotal'] + '</span></th><th class="right">' + totalSum + '</th>'); + } + } + + /* Turns a timespan (12:12:12) into a number */ + function timeToSec(timeStr) { + var time = timeStr.split(':'); + return parseInt(time[0]*3600) + parseInt(time[1]*60) + parseInt(time[2]); + } + + /* Turns a number into a timespan (100 into 00:01:40) */ + function secToTime(timeInt) { + var hours = Math.floor(timeInt / 3600); + timeInt -= hours*3600; + var minutes = Math.floor(timeInt / 60); + timeInt -= minutes*60; + + if (hours < 10) { + hours = '0' + hours; + } + if (minutes < 10) { + minutes = '0' + minutes; + } + if (timeInt < 10) { + timeInt = '0' + timeInt; + } + + return hours + ':' + minutes + ':' + timeInt; + } + + /* Constructs the log table out of the retrieved server data */ + function buildLogTable(data) { + var rows = data.rows; + var cols = []; + var $table = $('<table class="sortable"></table>'); + var $tBody, $tRow, $tCell; + + $('#logTable').html($table); + + var formatValue = function(name, value) { + switch(name) { + case 'user_host': + return value.replace(/(\[.*?\])+/g, ''); + } + return value; + }; + + for (var i = 0, l = rows.length; i < l; i++) { + if (i == 0) { + $.each(rows[0], function(key, value) { + cols.push(key); + }); + $table.append( '<thead>' + + '<tr><th class="nowrap">' + cols.join('</th><th class="nowrap">') + '</th></tr>' + + '</thead>'); + + $table.append($tBody = $('<tbody></tbody>')); + } + + $tBody.append($tRow = $('<tr class="noclick"></tr>')); + var cl = ''; + for (var j = 0, ll = cols.length; j < ll; j++) { + // Assuming the query column is the second last + if (j == cols.length - 2 && rows[i][cols[j]].match(/^SELECT/i)) { + $tRow.append($tCell = $('<td class="linkElem">' + formatValue(cols[j], rows[i][cols[j]]) + '</td>')); + $tCell.click(openQueryAnalyzer); + } else { + $tRow.append('<td>' + formatValue(cols[j], rows[i][cols[j]]) + '</td>'); + } + + $tRow.data('query', rows[i]); + } + } + + $table.append('<tfoot>' + + '<tr><th colspan="' + (cols.length - 1) + '">' + PMA_messages['strSumRows'] + + ' ' + data.numRows + '<span style="float:right">' + PMA_messages['strTotal'] + + '</span></th><th class="right">' + data.sum.TOTAL + '</th></tr></tfoot>'); + + // Append a tooltip to the count column, if there exist one + if ($('#logTable th:last').html() == '#') { + $('#logTable th:last').append(' ' + PMA_getImage('b_docs.png', '', {'class': 'qroupedQueryInfoIcon'})); + + var tooltipContent = PMA_messages['strCountColumnExplanation']; + if (groupInserts) { + tooltipContent += '<p>' + PMA_messages['strMoreCountColumnExplanation'] + '</p>'; + } + + PMA_tooltip( + $('img.qroupedQueryInfoIcon'), + 'img', + tooltipContent + ); + } + + $('#logTable table').tablesorter({ + sortList: [[cols.length - 1, 1]], + widgets: ['fast-zebra'] + }); + + $('#logTable table thead th') + .append('<img class="icon sortableIcon" src="themes/dot.gif" alt="">'); + + return cols; + } + + /* Opens the query analyzer dialog */ + function openQueryAnalyzer() { + var rowData = $(this).parent().data('query'); + var query = rowData.argument || rowData.sql_text; + + if (codemirror_editor) { + //TODO: somehow PMA_SQLPrettyPrint messes up the query, needs be fixed + //query = PMA_SQLPrettyPrint(query); + codemirror_editor.setValue(query); + // Codemirror is bugged, it doesn't refresh properly sometimes. + // Following lines seem to fix that + setTimeout(function() { + codemirror_editor.refresh(); + },50); + } + else { + $('#sqlquery').val(query); + } + + var profilingChart = null; + var dlgBtns = {}; + + dlgBtns[PMA_messages['strAnalyzeQuery']] = function() { + loadQueryAnalysis(rowData); + }; + dlgBtns[PMA_messages['strClose']] = function () { + $(this).dialog('close'); + }; + + $('#queryAnalyzerDialog').dialog({ + width: 'auto', + height: 'auto', + resizable: false, + buttons: dlgBtns, + close: function() { + if (profilingChart != null) { + profilingChart.destroy(); + } + $('#queryAnalyzerDialog div.placeHolder').html(''); + if (codemirror_editor) { + codemirror_editor.setValue(''); + } else { + $('#sqlquery').val(''); + } + } + }); + } + + /* Loads and displays the analyzed query data */ + function loadQueryAnalysis(rowData) { + var db = rowData.db || ''; + + $('#queryAnalyzerDialog div.placeHolder').html( + PMA_messages['strAnalyzing'] + ' <img class="ajaxIcon" src="' + + pmaThemeImage + 'ajax_clock_small.gif" alt="">'); + + $.post('server_status_monitor.php?' + PMA_commonParams.get('common_query'), { + ajax_request: true, + query_analyzer: true, + query: codemirror_editor ? codemirror_editor.getValue() : $('#sqlquery').val(), + database: db + }, function(data) { + if (data.success == true) { + data = data.message; + } + if (data.error) { + if(data.error.indexOf('1146') != -1 || data.error.indexOf('1046') != -1) + data.error = PMA_messages['strServerLogError']; + $('#queryAnalyzerDialog div.placeHolder').html('<div class="error">' + data.error + '</div>'); + return; + } + var totalTime = 0; + // Float sux, I'll use table :( + $('#queryAnalyzerDialog div.placeHolder') + .html('<table width="100%" border="0"><tr><td class="explain"></td><td class="chart"></td></tr></table>'); + + var explain = '<b>' + PMA_messages['strExplainOutput'] + '</b> ' + $('#explain_docu').html(); + if (data.explain.length > 1) { + explain += ' ('; + for (var i = 0; i < data.explain.length; i++) { + if (i > 0) { + explain += ', '; + } + explain += '<a href="#showExplain-' + i + '">' + i + '</a>'; + } + explain += ')'; + } + explain += '<p></p>'; + for (var i = 0, l = data.explain.length; i < l; i++) { + explain += '<div class="explain-' + i + '"' + (i>0? 'style="display:none;"' : '' ) + '>'; + $.each(data.explain[i], function(key, value) { + value = (value == null)?'null':value; + + if (key == 'type' && value.toLowerCase() == 'all') { + value = '<span class="attention">' + value + '</span>'; + } + if (key == 'Extra') { + value = value.replace(/(using (temporary|filesort))/gi, '<span class="attention">$1</span>'); + } + explain += key + ': ' + value + '<br />'; + }); + explain += '</div>'; + } + + explain += '<p><b>' + PMA_messages['strAffectedRows'] + '</b> ' + data.affectedRows; + + $('#queryAnalyzerDialog div.placeHolder td.explain').append(explain); + + $('#queryAnalyzerDialog div.placeHolder a[href*="#showExplain"]').click(function() { + var id = $(this).attr('href').split('-')[1]; + $(this).parent().find('div[class*="explain"]').hide(); + $(this).parent().find('div[class*="explain-' + id + '"]').show(); + }); + + if (data.profiling) { + var chartData = []; + var numberTable = '<table class="queryNums"><thead><tr><th>' + PMA_messages['strStatus'] + '</th><th>' + PMA_messages['strTime'] + '</th></tr></thead><tbody>'; + var duration; + var otherTime = 0; + + for (var i = 0, l = data.profiling.length; i < l; i++) { + duration = parseFloat(data.profiling[i].duration); + + totalTime += duration; + + numberTable += '<tr><td>' + data.profiling[i].state + ' </td><td> ' + PMA_prettyProfilingNum(duration, 2) + '</td></tr>'; + } + + // Only put those values in the pie which are > 2% + for (var i = 0, l = data.profiling.length; i < l; i++) { + duration = parseFloat(data.profiling[i].duration); + + if (duration / totalTime > 0.02) { + chartData.push([PMA_prettyProfilingNum(duration, 2) + ' ' + data.profiling[i].state, duration]); + } else { + otherTime += duration; + } + } + + if (otherTime > 0) { + chartData.push([PMA_prettyProfilingNum(otherTime, 2) + ' ' + PMA_messages['strOther'], otherTime]); + } + + numberTable += '<tr><td><b>' + PMA_messages['strTotalTime'] + '</b></td><td>' + PMA_prettyProfilingNum(totalTime, 2) + '</td></tr>'; + numberTable += '</tbody></table>'; + + $('#queryAnalyzerDialog div.placeHolder td.chart').append( + '<b>' + PMA_messages['strProfilingResults'] + ' ' + $('#profiling_docu').html() + '</b> ' + + '(<a href="#showNums">' + PMA_messages['strTable'] + '</a>, <a href="#showChart">' + PMA_messages['strChart'] + '</a>)<br/>' + + numberTable + ' <div id="queryProfiling"></div>'); + + $('#queryAnalyzerDialog div.placeHolder a[href="#showNums"]').click(function() { + $('#queryAnalyzerDialog #queryProfiling').hide(); + $('#queryAnalyzerDialog table.queryNums').show(); + return false; + }); + + $('#queryAnalyzerDialog div.placeHolder a[href="#showChart"]').click(function() { + $('#queryAnalyzerDialog #queryProfiling').show(); + $('#queryAnalyzerDialog table.queryNums').hide(); + return false; + }); + + profilingChart = PMA_createProfilingChartJqplot( + 'queryProfiling', + chartData + ); + + //$('#queryProfiling').resizable(); + } + }); + } + + /* Saves the monitor to localstorage */ + function saveMonitor() { + var gridCopy = {}; + + $.each(runtime.charts, function(key, elem) { + gridCopy[key] = {}; + gridCopy[key].nodes = elem.nodes; + gridCopy[key].settings = elem.settings; + gridCopy[key].title = elem.title; + gridCopy[key].series = elem.series; + gridCopy[key].maxYLabel = elem.maxYLabel; + }); + + if (window.localStorage) { + window.localStorage['monitorCharts'] = $.toJSON(gridCopy); + window.localStorage['monitorSettings'] = $.toJSON(monitorSettings); + window.localStorage['monitorVersion'] = monitorProtocolVersion; + } + + $('a[href="#clearMonitorConfig"]').show(); + } +}); + +// Run the monitor once loaded +AJAX.registerOnload('server_status_monitor.js', function() { + $('a[href="#pauseCharts"]').trigger('click'); +}); + +function serverResponseError() { + var btns = {}; + btns[PMA_messages['strReloadPage']] = function() { + window.location.reload(); + }; + $('#emptyDialog').dialog({title: PMA_messages['strRefreshFailed']}); + $('#emptyDialog').html( + PMA_getImage('s_attention.png') + + PMA_messages['strInvalidResponseExplanation'] + ); + $('#emptyDialog').dialog({ buttons: btns }); +} + +/* Destroys all monitor related resources */ +function destroyGrid() { + if (runtime.charts) { + $.each(runtime.charts, function(key, value) { + try { + value.chart.destroy(); + } catch(err) {} + }); + } + + try { + runtime.refreshRequest.abort(); + } catch(err) {} + try { + clearTimeout(runtime.refreshTimeout); + } catch(err) {} + $('#chartGrid').html(''); + runtime.charts = null; + runtime.chartAI = 0; + monitorSettings = null; //TODO:this not global variable +} diff --git a/hugo/js/server_status_queries.js b/hugo/js/server_status_queries.js new file mode 100644 index 0000000..3faeec4 --- /dev/null +++ b/hugo/js/server_status_queries.js @@ -0,0 +1,40 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + */ + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('server_status_queries.js', function() { + var queryPieChart = $('#serverstatusquerieschart').data('queryPieChart'); + if (queryPieChart) { + queryPieChart.destroy(); + } +}); + +AJAX.registerOnload('server_status_queries.js', function() { + // Build query statistics chart + var cdata = []; + try { + $.each(jQuery.parseJSON($('#serverstatusquerieschart_data').text()), function(key, value) { + cdata.push([key, parseInt(value)]); + }); + $('#serverstatusquerieschart').data( + 'queryPieChart', + PMA_createProfilingChartJqplot( + 'serverstatusquerieschart', + cdata + ) + ); + } catch (exception) { + // Could not load chart, no big deal... + } + + /*** Table sort tooltip ***/ + PMA_tooltip( + $('table.sortable>thead>tr:first').find('th'), + 'th', + PMA_messages['strSortHint'] + ); + initTableSorter('statustabs_queries'); +}); diff --git a/hugo/js/server_status_sorter.js b/hugo/js/server_status_sorter.js new file mode 100644 index 0000000..383cb8a --- /dev/null +++ b/hugo/js/server_status_sorter.js @@ -0,0 +1,89 @@ +// TODO: tablesorter shouldn't sort already sorted columns +function initTableSorter(tabid) { + var $table, opts; + switch(tabid) { + case 'statustabs_queries': + $table = $('#serverstatusqueriesdetails'); + opts = { + sortList: [[3, 1]], + widgets: ['fast-zebra'], + headers: { + 1: { sorter: 'fancyNumber' }, + 2: { sorter: 'fancyNumber' } + } + }; + break; + case 'statustabs_allvars': + $table = $('#serverstatusvariables'); + opts = { + sortList: [[0, 0]], + widgets: ['fast-zebra'], + headers: { + 1: { sorter: 'withinSpanNumber' } + } + }; + break; + } + $table.tablesorter(opts); + $table.find('tr:first th') + .append('<img class="icon sortableIcon" src="themes/dot.gif" alt="">'); +} + +$(function () { + $.tablesorter.addParser({ + id: "fancyNumber", + is: function(s) { + return /^[0-9]?[0-9,\.]*\s?(k|M|G|T|%)?$/.test(s); + }, + format: function(s) { + var num = jQuery.tablesorter.formatFloat( + s.replace(PMA_messages['strThousandsSeparator'], '') + .replace(PMA_messages['strDecimalSeparator'], '.') + ); + + var factor = 1; + switch (s.charAt(s.length - 1)) { + case '%': factor = -2; break; + // Todo: Complete this list (as well as in the regexp a few lines up) + case 'k': factor = 3; break; + case 'M': factor = 6; break; + case 'G': factor = 9; break; + case 'T': factor = 12; break; + } + + return num * Math.pow(10, factor); + }, + type: "numeric" + }); + + $.tablesorter.addParser({ + id: "withinSpanNumber", + is: function(s) { + return /<span class="original"/.test(s); + }, + format: function(s, table, html) { + var res = html.innerHTML.match(/<span(\s*style="display:none;"\s*)?\s*class="original">(.*)?<\/span>/); + return (res && res.length >= 3) ? res[2] : 0; + }, + type: "numeric" + }); + + // faster zebra widget: no row visibility check, faster css class switching, no cssChildRow check + $.tablesorter.addWidget({ + id: "fast-zebra", + format: function (table) { + if (table.config.debug) { + var time = new Date(); + } + $("tr:even", table.tBodies[0]) + .removeClass(table.config.widgetZebra.css[0]) + .addClass(table.config.widgetZebra.css[1]); + $("tr:odd", table.tBodies[0]) + .removeClass(table.config.widgetZebra.css[1]) + .addClass(table.config.widgetZebra.css[0]); + if (table.config.debug) { + $.tablesorter.benchmark("Applying Fast-Zebra widget", time); + } + } + }); +}); diff --git a/hugo/js/server_status_variables.js b/hugo/js/server_status_variables.js new file mode 100644 index 0000000..2f67066 --- /dev/null +++ b/hugo/js/server_status_variables.js @@ -0,0 +1,110 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * + * + * @package PhpMyAdmin + */ + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('server_status_variables.js', function() { + $('#filterAlert').unbind('change'); + $('#filterText').unbind('keyup'); + $('#filterCategory').unbind('change'); + $('#dontFormat').unbind('change'); +}); + +AJAX.registerOnload('server_status_variables.js', function() { + /*** Table sort tooltip ***/ + PMA_tooltip( + $('table.sortable>thead>tr:first').find('th'), + 'th', + PMA_messages['strSortHint'] + ); + initTableSorter('statustabs_allvars'); + + // Filters for status variables + var textFilter = null; + var alertFilter = $('#filterAlert').prop('checked'); + var categoryFilter = $('#filterCategory').find(':selected').val(); + var odd_row = false; + var text = ''; // Holds filter text + + /* 3 Filtering functions */ + $('#filterAlert').change(function() { + alertFilter = this.checked; + filterVariables(); + }); + + $('#filterCategory').change(function() { + categoryFilter = $(this).val(); + filterVariables(); + }); + + $('#dontFormat').change(function() { + // Hiding the table while changing values speeds up the process a lot + $('#serverstatusvariables').hide(); + $('#serverstatusvariables td.value span.original').toggle(this.checked); + $('#serverstatusvariables td.value span.formatted').toggle(! this.checked); + $('#serverstatusvariables').show(); + }).trigger('change'); + + $('#filterText').keyup(function(e) { + var word = $(this).val().replace(/_/g, ' '); + if (word.length == 0) { + textFilter = null; + } else { + textFilter = new RegExp("(^| )" + word, 'i'); + } + text = word; + filterVariables(); + }).trigger('keyup'); + + /* Filters the status variables by name/category/alert in the variables tab */ + function filterVariables() { + var useful_links = 0; + var section = text; + + if (categoryFilter.length > 0) { + section = categoryFilter; + } + + if (section.length > 1) { + $('#linkSuggestions span').each(function() { + if ($(this).attr('class').indexOf('status_' + section) != -1) { + useful_links++; + $(this).css('display', ''); + } else { + $(this).css('display', 'none'); + } + }); + } + + if (useful_links > 0) { + $('#linkSuggestions').css('display', ''); + } else { + $('#linkSuggestions').css('display', 'none'); + } + + odd_row = false; + $('#serverstatusvariables th.name').each(function() { + if ((textFilter == null || textFilter.exec($(this).text())) + && (! alertFilter || $(this).next().find('span.attention').length>0) + && (categoryFilter.length == 0 || $(this).parent().hasClass('s_' + categoryFilter)) + ) { + odd_row = ! odd_row; + $(this).parent().css('display', ''); + if (odd_row) { + $(this).parent().addClass('odd'); + $(this).parent().removeClass('even'); + } else { + $(this).parent().addClass('even'); + $(this).parent().removeClass('odd'); + } + } else { + $(this).parent().css('display', 'none'); + } + }); + } +}); diff --git a/hugo/js/server_variables.js b/hugo/js/server_variables.js new file mode 100644 index 0000000..12ae9d0 --- /dev/null +++ b/hugo/js/server_variables.js @@ -0,0 +1,158 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('server_variables.js', function() { + $('#serverVariables .var-row').unbind('hover'); + $('#filterText').unbind('keyup'); + $('a.editLink').die('click'); + $('#serverVariables').find('.var-name').find('a img').remove(); +}); + +AJAX.registerOnload('server_variables.js', function() { + var $editLink = $('a.editLink'); + var $saveLink = $('a.saveLink'); + var $cancelLink = $('a.cancelLink'); + var $filterField = $('#filterText'); + + /* Show edit link on hover */ + $('#serverVariables').delegate('.var-row', 'hover', function(event) { + if (event.type === 'mouseenter') { + var $elm = $(this).find('.var-value'); + // Only add edit element if the element is not being edited + if ($elm.hasClass('editable') && ! $elm.hasClass('edit')) { + $elm.prepend($editLink.clone().show()); + } + } else { + $(this).find('a.editLink').remove(); + } + }).find('.var-name').find('a').append( + $('#docImage').clone().show() + ); + + /* Launches the variable editor */ + $editLink.live('click', function (event) { + event.preventDefault(); + editVariable(this); + }); + + /* Event handler for variables filter */ + $filterField.keyup(function() { + var textFilter = null, val = $(this).val(); + if (val.length !== 0) { + textFilter = new RegExp("(^| )"+val.replace(/_/g,' '),'i'); + } + filterVariables(textFilter); + }); + + /* Trigger filtering of the list based on incoming variable name */ + if ($filterField.val()) { + $filterField.trigger('keyup').select(); + } + + /* Filters the rows by the user given regexp */ + function filterVariables(textFilter) { + var mark_next = false, $row, odd_row = false; + $('#serverVariables .var-row').not('.var-header').each(function() { + $row = $(this); + if ( mark_next + || textFilter === null + || textFilter.exec($row.find('.var-name').text()) + ) { + // If current global value is different from session value + // (has class diffSession), then display that one too + mark_next = $row.hasClass('diffSession') && ! mark_next; + + odd_row = ! odd_row; + $row.css('display', ''); + if (odd_row) { + $row.addClass('odd').removeClass('even'); + } else { + $row.addClass('even').removeClass('odd'); + } + } else { + $row.css('display', 'none'); + } + }); + } + + /* Allows the user to edit a server variable */ + function editVariable(link) { + var $cell = $(link).parent(); + var varName = $cell.parent().find('.var-name').text().replace(/ /g,'_'); + var $mySaveLink = $saveLink.clone().show(); + var $myCancelLink = $cancelLink.clone().show(); + var $msgbox = PMA_ajaxShowMessage(); + + $cell + .addClass('edit') // variable is being edited + .find('a.editLink') + .remove(); // remove edit link + + $mySaveLink.click(function() { + var $msgbox = PMA_ajaxShowMessage(PMA_messages.strProcessingRequest); + $.get($(this).attr('href'), { + ajax_request: true, + type: 'setval', + varName: varName, + varValue: $cell.find('input').val() + }, function(data) { + if (data.success) { + $cell + .html(data.variable) + .data('content', data.variable); + PMA_ajaxRemoveMessage($msgbox); + } else { + PMA_ajaxShowMessage(data.error, false); + $cell.html($cell.data('content')); + } + $cell.removeClass('edit'); + }); + return false; + }); + + $myCancelLink.click(function() { + $cell + .html($cell.data('content')) + .removeClass('edit'); + return false; + }); + + $.get($mySaveLink.attr('href'), { + ajax_request: true, + type: 'getval', + varName: varName + }, function(data) { + if (data.success === true) { + var $editor = $('<div />', {'class':'serverVariableEditor'}) + .append($myCancelLink) + .append(' ') + .append($mySaveLink) + .append(' ') + .append( + $('<div/>').append( + $('<input />', {type: 'text'}).val(data.message) + ) + ); + // Save and replace content + $cell + .data('content', $cell.html()) + .html($editor) + .find('input') + .focus() + .keydown(function(event) { // Keyboard shortcuts + if (event.keyCode === 13) { // Enter key + $mySaveLink.trigger('click'); + } else if (event.keyCode === 27) { // Escape key + $myCancelLink.trigger('click'); + } + }); + PMA_ajaxRemoveMessage($msgbox); + } else { + $cell.removeClass('edit'); + PMA_ajaxShowMessage(data.error); + } + }); + } +}); diff --git a/hugo/js/sql.js b/hugo/js/sql.js new file mode 100644 index 0000000..7e84701 --- /dev/null +++ b/hugo/js/sql.js @@ -0,0 +1,605 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * @fileoverview functions used wherever an sql query form is used + * + * @requires jQuery + * @requires js/functions.js + * + */ + +var $data_a; + +/** + * decode a string URL_encoded + * + * @param string str + * @return string the URL-decoded string + */ +function PMA_urldecode(str) +{ + return decodeURIComponent(str.replace(/\+/g, '%20')); +} + +/** + * endecode a string URL_decoded + * + * @param string str + * @return string the URL-encoded string + */ +function PMA_urlencode(str) +{ + return encodeURIComponent(str).replace(/\%20/g, '+'); +} + +/** + * Get the field name for the current field. Required to construct the query + * for grid editing + * + * @param $this_field jQuery object that points to the current field's tr + */ +function getFieldName($this_field) +{ + + var this_field_index = $this_field.index(); + // ltr or rtl direction does not impact how the DOM was generated + // check if the action column in the left exist + var left_action_exist = !$('#table_results').find('th:first').hasClass('draggable'); + // number of column span for checkbox and Actions + var left_action_skip = left_action_exist ? $('#table_results').find('th:first').attr('colspan') - 1 : 0; + var field_name = $('#table_results').find('thead').find('th:eq('+ (this_field_index - left_action_skip) + ') a').text(); + // happens when just one row (headings contain no a) + if ("" == field_name) { + var $heading = $('#table_results').find('thead').find('th:eq('+ (this_field_index - left_action_skip) + ')').children('span'); + // may contain column comment enclosed in a span - detach it temporarily to read the column name + var $tempColComment = $heading.children().detach(); + field_name = $heading.text(); + // re-attach the column comment + $heading.append($tempColComment); + } + + field_name = $.trim(field_name); + + return field_name; +} + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('sql.js', function() { + $('a.delete_row.ajax').unbind('click'); + $('#bookmarkQueryForm').die('submit'); + $('input#bkm_label').unbind('keyup'); + $("#sqlqueryresults").die('makegrid'); + $("#togglequerybox").unbind('click'); + $("#button_submit_query").die('click'); + $("input[name=bookmark_variable]").unbind("keypress"); + $("#sqlqueryform.ajax").die('submit'); + $("input[name=navig].ajax").die('click'); + $("#pageselector").die('change'); + $("#table_results.ajax").find("a[title=Sort]").die('click'); + $("#displayOptionsForm.ajax").die('submit'); + $("#resultsForm.ajax .mult_submit[value=edit]").die('click'); + $("#insertForm .insertRowTable.ajax input[type=submit]").die('click'); + $("#buttonYes.ajax").die('click'); + $('a.browse_foreign').die('click'); + $('th.column_heading.pointer').die('hover'); + $('th.column_heading.marker').die('click'); +}); + +/** + * @description <p>Ajax scripts for sql and browse pages</p> + * + * Actions ajaxified here: + * <ul> + * <li>Retrieve results of an SQL query</li> + * <li>Paginate the results table</li> + * <li>Sort the results table</li> + * <li>Change table according to display options</li> + * <li>Grid editing of data</li> + * <li>Saving a bookmark</li> + * </ul> + * + * @name document.ready + * @memberOf jQuery + */ +AJAX.registerOnload('sql.js', function() { + // Delete row from SQL results + $('a.delete_row.ajax').click(function (e) { + e.preventDefault(); + var question = $.sprintf(PMA_messages['strDoYouReally'], $(this).closest('td').find('div').text()); + var $link = $(this); + $link.PMA_confirm(question, $link.attr('href'), function (url) { + $msgbox = PMA_ajaxShowMessage(); + $.get(url, {'ajax_request':true, 'is_js_confirmed': true}, function (data) { + if (data.success) { + PMA_ajaxShowMessage(data.message); + $link.closest('tr').remove(); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }) + }); + }); + + // Ajaxification for 'Bookmark this SQL query' + $('#bookmarkQueryForm').live('submit', function (e) { + e.preventDefault(); + PMA_ajaxShowMessage(); + $.post($(this).attr('action'), 'ajax_request=1&' + $(this).serialize(), function (data) { + if (data.success) { + PMA_ajaxShowMessage(data.message); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); + }); + + /* Hides the bookmarkoptions checkboxes when the bookmark label is empty */ + $('input#bkm_label').keyup(function() { + $('input#id_bkm_all_users, input#id_bkm_replace') + .parent() + .toggle($(this).val().length > 0); + }).trigger('keyup'); + + /** + * Attach the {@link makegrid} function to a custom event, which will be + * triggered manually everytime the table of results is reloaded + * @memberOf jQuery + */ + $("#sqlqueryresults").live('makegrid', function() { + PMA_makegrid($('#table_results')[0]); + }); + + /** + * Append the "Show/Hide query box" message to the query input form + * + * @memberOf jQuery + * @name appendToggleSpan + */ + // do not add this link more than once + if (! $('#sqlqueryform').find('a').is('#togglequerybox')) { + $('<a id="togglequerybox"></a>') + .html(PMA_messages['strHideQueryBox']) + .appendTo("#sqlqueryform") + // initially hidden because at this point, nothing else + // appears under the link + .hide(); + + // Attach the toggling of the query box visibility to a click + $("#togglequerybox").bind('click', function() { + var $link = $(this); + $link.siblings().slideToggle("fast"); + if ($link.text() == PMA_messages['strHideQueryBox']) { + $link.text(PMA_messages['strShowQueryBox']); + // cheap trick to add a spacer between the menu tabs + // and "Show query box"; feel free to improve! + $('#togglequerybox_spacer').remove(); + $link.before('<br id="togglequerybox_spacer" />'); + } else { + $link.text(PMA_messages['strHideQueryBox']); + } + // avoid default click action + return false; + }); + } + + + /** + * Event handler for sqlqueryform.ajax button_submit_query + * + * @memberOf jQuery + */ + $("#button_submit_query").live('click', function(event) { + var $form = $(this).closest("form"); + // the Go button related to query submission was clicked, + // instead of the one related to Bookmarks, so empty the + // id_bookmark selector to avoid misinterpretation in + // import.php about what needs to be done + $form.find("select[name=id_bookmark]").val(""); + // let normal event propagation happen + }); + + /** + * Event handler for hitting enter on sqlqueryform bookmark_variable + * (the Variable textfield in Bookmarked SQL query section) + * + * @memberOf jQuery + */ + $("input[name=bookmark_variable]").bind("keypress", function(event) { + // force the 'Enter Key' to implicitly click the #button_submit_bookmark + var keycode = (event.keyCode ? event.keyCode : (event.which ? event.which : event.charCode)); + if (keycode == 13) { // keycode for enter key + // When you press enter in the sqlqueryform, which + // has 2 submit buttons, the default is to run the + // #button_submit_query, because of the tabindex + // attribute. + // This submits #button_submit_bookmark instead, + // because when you are in the Bookmarked SQL query + // section and hit enter, you expect it to do the + // same action as the Go button in that section. + $("#button_submit_bookmark").click(); + return false; + } else { + return true; + } + }); + + /** + * Ajax Event handler for 'SQL Query Submit' + * + * @see PMA_ajaxShowMessage() + * @memberOf jQuery + * @name sqlqueryform_submit + */ + $("#sqlqueryform.ajax").live('submit', function(event) { + event.preventDefault(); + + var $form = $(this); + if (! checkSqlQuery($form[0])) { + return false; + } + + // remove any div containing a previous error message + $('div.error').remove(); + + var $msgbox = PMA_ajaxShowMessage(); + var $sqlqueryresults = $('#sqlqueryresults'); + + PMA_prepareForAjaxRequest($form); + + $.post($form.attr('action'), $form.serialize() , function(data) { + if (data.success == true) { + // success happens if the query returns rows or not + // + // fade out previous messages, if any + $('div.success, div.sqlquery_message').fadeOut(); + if ($('#result_query').length) { + $('#result_query').remove(); + } + + // show a message that stays on screen + if (typeof data.action_bookmark != 'undefined') { + // view only + if ('1' == data.action_bookmark) { + $('#sqlquery').text(data.sql_query); + // send to codemirror if possible + setQuery(data.sql_query); + } + // delete + if ('2' == data.action_bookmark) { + $("#id_bookmark option[value='" + data.id_bookmark + "']").remove(); + } + $sqlqueryresults + .show() + .html(data.message); + } else if (typeof data.sql_query != 'undefined') { + $('<div class="sqlquery_message"></div>') + .html(data.sql_query) + .insertBefore('#sqlqueryform'); + // unnecessary div that came from data.sql_query + $('div.notice').remove(); + } else { + $sqlqueryresults + .show() + .html(data.message); + } + + if (typeof data.ajax_reload != 'undefined') { + if (data.ajax_reload.reload) { + if (data.ajax_reload.table_name) { + PMA_commonParams.set('table', data.ajax_reload.table_name); + PMA_commonActions.refreshMain(); + } else { + PMA_reloadNavigation(); + } + } + } else if (typeof data.reload != 'undefined') { + // this happens if a USE or DROP command was typed + PMA_commonActions.setDb(data.db); + var url; + if (data.db) { + if (data.table) { + url = 'table_sql.php'; + } else { + url = 'db_sql.php'; + } + } else { + url = 'server_sql.php'; + } + PMA_commonActions.refreshMain(url, function () { + if ($('#result_query').length) { + $('#result_query').remove(); + } + if (data.sql_query) { + $('<div id="result_query"></div>') + .html(data.sql_query) + .prependTo('#page_content'); + } + }); + } + + $sqlqueryresults.show().trigger('makegrid'); + $('#togglequerybox').show(); + PMA_init_slider(); + + if (typeof data.action_bookmark == 'undefined') { + if ( $('#sqlqueryform input[name="retain_query_box"]').is(':checked') != true ) { + if ($("#togglequerybox").siblings(":visible").length > 0) { + $("#togglequerybox").trigger('click'); + } + } + } + } else if (data.success == false ) { + // show an error message that stays on screen + $('#sqlqueryform').before(data.error); + $sqlqueryresults.hide(); + } + PMA_ajaxRemoveMessage($msgbox); + }); // end $.post() + }); // end SQL Query submit + + /** + * Paginate results with Page Selector dropdown + * @memberOf jQuery + * @name paginate_dropdown_change + */ + $("#pageselector").live('change', function(event) { + var $form = $(this).parent("form"); + $form.submit(); + }); // end Paginate results with Page Selector + + /** + * Ajax Event handler for the display options + * @memberOf jQuery + * @name displayOptionsForm_submit + */ + $("#displayOptionsForm.ajax").live('submit', function(event) { + event.preventDefault(); + + $form = $(this); + + $.post($form.attr('action'), $form.serialize() + '&ajax_request=true' , function(data) { + $("#sqlqueryresults") + .html(data.message) + .trigger('makegrid'); + PMA_init_slider(); + }); // end $.post() + }); //end displayOptionsForm handler + +/** + * Ajax Event for table row change + * */ + $("#resultsForm.ajax .mult_submit[value=edit]").live('click', function(event){ + event.preventDefault(); + + /*Check whether atleast one row is selected for change*/ + if ($("#table_results tbody tr, #table_results tbody tr td").hasClass("marked")) { + var $div = $('<div id="change_row_dialog"></div>'); + + /** + * @var button_options Object that stores the options passed to jQueryUI + * dialog + */ + var button_options = {}; + // in the following function we need to use $(this) + button_options[PMA_messages['strCancel']] = function() { + $(this).dialog('close'); + }; + + var button_options_error = {}; + button_options_error[PMA_messages['strOK']] = function() { + $(this).dialog('close'); + }; + var $form = $("#resultsForm"); + var $msgbox = PMA_ajaxShowMessage(); + + $.get($form.attr('action'), $form.serialize()+"&ajax_request=true&submit_mult=row_edit", function(data) { + //in the case of an error, show the error message returned. + if (data.success != undefined && data.success == false) { + $div + .append(data.error) + .dialog({ + title: PMA_messages['strChangeTbl'], + height: 230, + width: 900, + open: PMA_verifyColumnsProperties, + close: function(event, ui) { + $(this).remove(); + }, + buttons : button_options_error + }); // end dialog options + } else { + $div + .append(data.message) + .dialog({ + title: PMA_messages['strChangeTbl'], + height: 600, + width: 900, + open: PMA_verifyColumnsProperties, + close: function(event, ui) { + $(this).remove(); + }, + buttons : button_options + }) + //Remove the top menu container from the dialog + .find("#topmenucontainer").hide() + ; // end dialog options + $("table.insertRowTable").addClass("ajax"); + $("#buttonYes").addClass("ajax"); + } + PMA_ajaxRemoveMessage($msgbox); + }); // end $.get() + } else { + PMA_ajaxShowMessage(PMA_messages['strNoRowSelected']); + } + }); + +/** + * Click action for "Go" button in ajax dialog insertForm -> insertRowTable + */ + $("#insertForm .insertRowTable.ajax input[type=submit]").live('click', function(event) { + event.preventDefault(); + /** + * @var the_form object referring to the insert form + */ + var $form = $("#insertForm"); + PMA_prepareForAjaxRequest($form); + //User wants to submit the form + $.post($form.attr('action'), $form.serialize(), function(data) { + if (data.success == true) { + PMA_ajaxShowMessage(data.message); + if ($("#pageselector").length != 0) { + $("#pageselector").trigger('change'); + } else { + $("input[name=navig].ajax").trigger('click'); + } + + } else { + PMA_ajaxShowMessage(data.error, false); + $("#table_results tbody tr.marked .multi_checkbox " + + ", #table_results tbody tr td.marked .multi_checkbox").prop("checked", false); + $("#table_results tbody tr.marked .multi_checkbox " + + ", #table_results tbody tr td.marked .multi_checkbox").removeClass("last_clicked"); + $("#table_results tbody tr" + + ", #table_results tbody tr td").removeClass("marked"); + } + if ($("#change_row_dialog").length > 0) { + $("#change_row_dialog").dialog("close").remove(); + } + /**Update the row count at the tableForm*/ + $("#result_query").remove(); + $("#sqlqueryresults").prepend(data.sql_query); + $("#result_query .notice").remove(); + $("#result_query").prepend((data.message)); + }); // end $.post() + }); // end insert table button "Go" + +/**$("#buttonYes.ajax").live('click' + * Click action for #buttonYes button in ajax dialog insertForm + */ + + $("#buttonYes.ajax").live('click', function(event){ + event.preventDefault(); + /** + * @var the_form object referring to the insert form + */ + var $form = $("#insertForm"); + /**Get the submit type in the form*/ + var selected_submit_type = $("#insertForm").find("#actions_panel .control_at_footer option:selected").val(); + $("#result_query").remove(); + PMA_prepareForAjaxRequest($form); + //User wants to submit the form + $.post($form.attr('action'), $form.serialize() , function(data) { + if (data.success == true) { + PMA_ajaxShowMessage(data.message); + if (selected_submit_type == "showinsert") { + $("#sqlqueryresults").prepend(data.sql_query); + $("#result_query .notice").remove(); + $("#result_query").prepend(data.message); + $("#table_results tbody tr.marked .multi_checkbox " + + ", #table_results tbody tr td.marked .multi_checkbox").prop("checked", false); + $("#table_results tbody tr.marked .multi_checkbox " + + ", #table_results tbody tr td.marked .multi_checkbox").removeClass("last_clicked"); + $("#table_results tbody tr" + + ", #table_results tbody tr td").removeClass("marked"); + } else { + if ($("#pageselector").length != 0) { + $("#pageselector").trigger('change'); + } else { + $("input[name=navig].ajax").trigger('click'); + } + $("#result_query").remove(); + $("#sqlqueryresults").prepend(data.sql_query); + $("#result_query .notice").remove(); + $("#result_query").prepend((data.message)); + } + } else { + PMA_ajaxShowMessage(data.error, false); + $("#table_results tbody tr.marked .multi_checkbox " + + ", #table_results tbody tr td.marked .multi_checkbox").prop("checked", false); + $("#table_results tbody tr.marked .multi_checkbox " + + ", #table_results tbody tr td.marked .multi_checkbox").removeClass("last_clicked"); + $("#table_results tbody tr" + + ", #table_results tbody tr td").removeClass("marked"); + } + if ($("#change_row_dialog").length > 0) { + $("#change_row_dialog").dialog("close").remove(); + } + }); // end $.post() + }); + +}); // end $() + + +/** + * Starting from some th, change the class of all td under it. + * If isAddClass is specified, it will be used to determine whether to add or remove the class. + */ +function PMA_changeClassForColumn($this_th, newclass, isAddClass) +{ + // index 0 is the th containing the big T + var th_index = $this_th.index(); + var has_big_t = !$this_th.closest('tr').children(':first').hasClass('column_heading'); + // .eq() is zero-based + if (has_big_t) { + th_index--; + } + var $tds = $this_th.closest('table').find('tbody tr').find('td.data:eq('+th_index+')'); + if (isAddClass == undefined) { + $tds.toggleClass(newclass); + } else { + $tds.toggleClass(newclass, isAddClass); + } +} + +AJAX.registerOnload('sql.js', function() { + + $('a.browse_foreign').live('click', function(e) { + e.preventDefault(); + window.open(this.href, 'foreigners', 'width=640,height=240,scrollbars=yes,resizable=yes'); + $anchor = $(this); + $anchor.addClass('browse_foreign_clicked'); + }); + + /** + * vertical column highlighting in horizontal mode when hovering over the column header + */ + $('th.column_heading.pointer').live('hover', function(e) { + PMA_changeClassForColumn($(this), 'hover', e.type == 'mouseenter'); + }); + + /** + * vertical column marking in horizontal mode when clicking the column header + */ + $('th.column_heading.marker').live('click', function() { + PMA_changeClassForColumn($(this), 'marked'); + }); + + /** + * create resizable table + */ + $("#sqlqueryresults").trigger('makegrid'); +}); + +/* + * Profiling Chart + */ +function makeProfilingChart() +{ + if ($('#profilingchart').length == 0 + || $('#profilingchart').html().length != 0 + ) { + return; + } + + var data = []; + $.each(jQuery.parseJSON($('#profilingChartData').html()),function(key,value) { + data.push([key,parseFloat(value)]); + }); + + // Remove chart and data divs contents + $('#profilingchart').html('').show(); + $('#profilingChartData').html(''); + + PMA_createProfilingChartJqplot('profilingchart', data); +} diff --git a/hugo/js/tbl_change.js b/hugo/js/tbl_change.js new file mode 100644 index 0000000..28f3b29 --- /dev/null +++ b/hugo/js/tbl_change.js @@ -0,0 +1,495 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * @fileoverview function used in table data manipulation pages + * + * @requires jQuery + * @requires jQueryUI + * @requires js/functions.js + * + */ + +/** + * Modify form controls when the "NULL" checkbox is checked + * + * @param theType string the MySQL field type + * @param urlField string the urlencoded field name - OBSOLETE + * @param md5Field string the md5 hashed field name + * @param multi_edit string the multi_edit row sequence number + * + * @return boolean always true + */ +function nullify(theType, urlField, md5Field, multi_edit) +{ + var rowForm = document.forms['insertForm']; + + if (typeof(rowForm.elements['funcs' + multi_edit + '[' + md5Field + ']']) != 'undefined') { + rowForm.elements['funcs' + multi_edit + '[' + md5Field + ']'].selectedIndex = -1; + } + + // "ENUM" field with more than 20 characters + if (theType == 1) { + rowForm.elements['fields' + multi_edit + '[' + md5Field + ']'][1].selectedIndex = -1; + } + // Other "ENUM" field + else if (theType == 2) { + var elts = rowForm.elements['fields' + multi_edit + '[' + md5Field + ']']; + // when there is just one option in ENUM: + if (elts.checked) { + elts.checked = false; + } else { + var elts_cnt = elts.length; + for (var i = 0; i < elts_cnt; i++ ) { + elts[i].checked = false; + } // end for + + } // end if + } + // "SET" field + else if (theType == 3) { + rowForm.elements['fields' + multi_edit + '[' + md5Field + '][]'].selectedIndex = -1; + } + // Foreign key field (drop-down) + else if (theType == 4) { + rowForm.elements['fields' + multi_edit + '[' + md5Field + ']'].selectedIndex = -1; + } + // foreign key field (with browsing icon for foreign values) + else if (theType == 6) { + rowForm.elements['fields' + multi_edit + '[' + md5Field + ']'].value = ''; + } + // Other field types + else /*if (theType == 5)*/ { + rowForm.elements['fields' + multi_edit + '[' + md5Field + ']'].value = ''; + } // end if... else if... else + + return true; +} // end of the 'nullify()' function + + +/** + * javascript DateTime format validation. + * its used to prevent adding default (0000-00-00 00:00:00) to database when user enter wrong values + * Start of validation part + */ +//function checks the number of days in febuary +function daysInFebruary (year) +{ + return (((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0))) ? 29 : 28 ); +} +//function to convert single digit to double digit +function fractionReplace(num) +{ + num = parseInt(num); + return num >= 1 && num <= 9 ? '0' + num : '00'; +} + +/* function to check the validity of date +* The following patterns are accepted in this validation (accepted in mysql as well) +* 1) 2001-12-23 +* 2) 2001-1-2 +* 3) 02-12-23 +* 4) And instead of using '-' the following punctuations can be used (+,.,*,^,@,/) All these are accepted by mysql as well. Therefore no issues +*/ +function isDate(val,tmstmp) +{ + val = val.replace(/[.|*|^|+|//|@]/g,'-'); + var arrayVal = val.split("-"); + for (var a=0;a<arrayVal.length;a++) { + if (arrayVal[a].length==1) { + arrayVal[a]=fractionReplace(arrayVal[a]); + } + } + val=arrayVal.join("-"); + var pos=2; + var dtexp=new RegExp(/^([0-9]{4})-(((01|03|05|07|08|10|12)-((0[0-9])|([1-2][0-9])|(3[0-1])))|((02|04|06|09|11)-((0[0-9])|([1-2][0-9])|30)))$/); + if (val.length == 8) { + pos=0; + } + if (dtexp.test(val)) { + var month=parseInt(val.substring(pos+3,pos+5)); + var day=parseInt(val.substring(pos+6,pos+8)); + var year=parseInt(val.substring(0,pos+2)); + if (month == 2 && day > daysInFebruary(year)) { + return false; + } + if (val.substring(0, pos + 2).length == 2) { + year = parseInt("20" + val.substring(0,pos+2)); + } + if (tmstmp == true) { + if (year < 1978) { + return false; + } + if (year > 2038 || (year > 2037 && day > 19 && month >= 1) || (year > 2037 && month > 1)) { + return false; + } + } + } else { + return false; + } + return true; +} + +/* function to check the validity of time +* The following patterns are accepted in this validation (accepted in mysql as well) +* 1) 2:3:4 +* 2) 2:23:43 +*/ +function isTime(val) +{ + var arrayVal = val.split(":"); + for (var a = 0, l = arrayVal.length; a < l; a++) { + if (arrayVal[a].length == 1) { + arrayVal[a] = fractionReplace(arrayVal[a]); + } + } + val = arrayVal.join(":"); + var tmexp = new RegExp(/^(([0-1][0-9])|(2[0-3])):((0[0-9])|([1-5][0-9])):((0[0-9])|([1-5][0-9]))$/); + return tmexp.test(val); +} + +function verificationsAfterFieldChange(urlField, multi_edit, theType) +{ + var evt = window.event || arguments.callee.caller.arguments[0]; + var target = evt.target || evt.srcElement; + + // Unchecks the corresponding "NULL" control + $("input[name='fields_null[multi_edit][" + multi_edit + "][" + urlField + "]']").prop('checked', false); + + // Unchecks the Ignore checkbox for the current row + $("input[name='insert_ignore_" + multi_edit + "']").prop('checked', false); + var $this_input = $("input[name='fields[multi_edit][" + multi_edit + "][" + urlField + "]']"); + + // Does this field come from datepicker? + if ($this_input.data('comes_from') == 'datepicker') { + // Yes, so do not validate because the final value is not yet in + // the field and hopefully the datepicker returns a valid date+time + $this_input.removeClass("invalid_value"); + return true; + } + + if (target.name.substring(0,6)=="fields") { + // validate for date time + if (theType=="datetime"||theType=="time"||theType=="date"||theType=="timestamp") { + $this_input.removeClass("invalid_value"); + var dt_value = $this_input.val(); + if (theType=="date"){ + if (! isDate(dt_value)) { + $this_input.addClass("invalid_value"); + return false; + } + } else if (theType=="time") { + if (! isTime(dt_value)) { + $this_input.addClass("invalid_value"); + return false; + } + } else if (theType=="datetime"||theType=="timestamp") { + var tmstmp=false; + if (dt_value == "CURRENT_TIMESTAMP") { + return true; + } + if (theType=="timestamp") { + tmstmp=true; + } + if (dt_value=="0000-00-00 00:00:00") { + return true; + } + var dv=dt_value.indexOf(" "); + if (dv==-1) { + $this_input.addClass("invalid_value"); + return false; + } else { + if (! (isDate(dt_value.substring(0,dv),tmstmp) && isTime(dt_value.substring(dv+1)))) { + $this_input.addClass("invalid_value"); + return false; + } + } + } + } + //validate for integer type + if (theType.substring(0,3) == "int"){ + $this_input.removeClass("invalid_value"); + if (isNaN($this_input.val())){ + $this_input.addClass("invalid_value"); + return false; + } + } + } + } + /* End of datetime validation*/ + + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('tbl_change.js', function() { + $('span.open_gis_editor').die('click'); + $("input[name='gis_data[save]']").die('click'); + $('input.checkbox_null').unbind('click'); + $('select[name="submit_type"]').unbind('change'); + $("#insert_rows").die('change'); +}); + +/** + * Ajax handlers for Change Table page + * + * Actions Ajaxified here: + * Submit Data to be inserted into the table. + * Restart insertion with 'N' rows. + */ +AJAX.registerOnload('tbl_change.js', function() { + $.datepicker.initialized = false; + + $('span.open_gis_editor').live('click', function(event) { + event.preventDefault(); + + var $span = $(this); + // Current value + var value = $span.parent('td').children("input[type='text']").val(); + // Field name + var field = $span.parents('tr').children('td:first').find("input[type='hidden']").val(); + // Column type + var type = $span.parents('tr').find('span.column_type').text(); + // Names of input field and null checkbox + var input_name = $span.parent('td').children("input[type='text']").attr('name'); + //Token + var token = $("input[name='token']").val(); + + openGISEditor(); + if (!gisEditorLoaded) { + loadJSAndGISEditor(value, field, type, input_name, token); + } else { + loadGISEditor(value, field, type, input_name, token); + } + }); + + /** + * Uncheck the null checkbox as geometry data is placed on the input field + */ + $("input[name='gis_data[save]']").live('click', function(event) { + var input_name = $('form#gis_data_editor_form').find("input[name='input_name']").val(); + var $null_checkbox = $("input[name='" + input_name + "']").parents('tr').find('.checkbox_null'); + $null_checkbox.prop('checked', false); + }); + + /** + * Handles all current checkboxes for Null; this only takes care of the + * checkboxes on currently displayed rows as the rows generated by + * "Continue insertion" are handled in the "Continue insertion" code + * + */ + $('input.checkbox_null').bind('click', function(e) { + nullify( + // use hidden fields populated by tbl_change.php + $(this).siblings('.nullify_code').val(), + $(this).closest('tr').find('input:hidden').first().val(), + $(this).siblings('.hashed_field').val(), + $(this).siblings('.multi_edit').val() + ); + }); + + + /** + * Reset the auto_increment column to 0 when selecting any of the + * insert options in submit_type-dropdown. Only perform the reset + * when we are in edit-mode, and not in insert-mode(no previous value + * available). + */ + $('select[name="submit_type"]').bind('change', function (e) { + var $table = $('table.insertRowTable'); + var auto_increment_column = $table.find('input[name^="auto_increment"]').attr('name'); + if (auto_increment_column) { + var prev_value_field = $table.find('input[name="' + auto_increment_column.replace('auto_increment', 'fields_prev') + '"]'); + var value_field = $table.find('input[name="' + auto_increment_column.replace('auto_increment', 'fields') + '"]'); + var previous_value = $(prev_value_field).val(); + if (previous_value !== undefined) { + if ($(this).val() == 'insert' || $(this).val() == 'insertignore' || $(this).val() == 'showinsert' ) { + $(value_field).val(0); + } else { + $(value_field).val(previous_value); + } + } + } + }); + + /** + * Continue Insertion form + */ + $("#insert_rows").live('change', function(event) { + event.preventDefault(); + + /** + * @var curr_rows Number of current insert rows already on page + */ + var curr_rows = $("table.insertRowTable").length; + /** + * @var target_rows Number of rows the user wants + */ + var target_rows = $("#insert_rows").val(); + + // remove all datepickers + $('input.datefield, input.datetimefield').each(function(){ + $(this).datepicker('destroy'); + }); + + if (curr_rows < target_rows ) { + while( curr_rows < target_rows ) { + + /** + * @var $last_row Object referring to the last row + */ + var $last_row = $("#insertForm").find(".insertRowTable:last"); + + // need to access this at more than one level + // (also needs improvement because it should be calculated + // just once per cloned row, not once per column) + var new_row_index = 0; + + //Clone the insert tables + $last_row + .clone() + .insertBefore("#actions_panel") + .find('input[name*=multi_edit],select[name*=multi_edit],textarea[name*=multi_edit]') + .each(function() { + + var $this_element = $(this); + /** + * Extract the index from the name attribute for all input/select fields and increment it + * name is of format funcs[multi_edit][10][<long random string of alphanum chars>] + */ + + /** + * @var this_name String containing name of the input/select elements + */ + var this_name = $this_element.attr('name'); + /** split {@link this_name} at [10], so we have the parts that can be concatenated later */ + var name_parts = this_name.split(/\[\d+\]/); + /** extract the [10] from {@link name_parts} */ + var old_row_index_string = this_name.match(/\[\d+\]/)[0]; + /** extract 10 - had to split into two steps to accomodate double digits */ + var old_row_index = parseInt(old_row_index_string.match(/\d+/)[0]); + + /** calculate next index i.e. 11 */ + new_row_index = old_row_index + 1; + /** generate the new name i.e. funcs[multi_edit][11][foobarbaz] */ + var new_name = name_parts[0] + '[' + new_row_index + ']' + name_parts[1]; + + var hashed_field = name_parts[1].match(/\[(.+)\]/)[1]; + $this_element.attr('name', new_name); + + if ($this_element.is('.textfield')) { + // do not remove the 'value' attribute for ENUM columns + if ($this_element.closest('tr').find('span.column_type').html() != 'enum') { + $this_element.val($this_element.closest('tr').find('span.default_value').html()); + } + $this_element + .unbind('change') + // Remove onchange attribute that was placed + // by tbl_change.php; it refers to the wrong row index + .attr('onchange', null) + // Keep these values to be used when the element + // will change + .data('hashed_field', hashed_field) + .data('new_row_index', new_row_index) + .bind('change', function(e) { + var $changed_element = $(this); + verificationsAfterFieldChange( + $changed_element.data('hashed_field'), + $changed_element.data('new_row_index'), + $changed_element.closest('tr').find('span.column_type').html() + ); + }); + } + + if ($this_element.is('.checkbox_null')) { + $this_element + // this event was bound earlier by jQuery but + // to the original row, not the cloned one, so unbind() + .unbind('click') + // Keep these values to be used when the element + // will be clicked + .data('hashed_field', hashed_field) + .data('new_row_index', new_row_index) + .bind('click', function(e) { + var $changed_element = $(this); + nullify( + $changed_element.siblings('.nullify_code').val(), + $this_element.closest('tr').find('input:hidden').first().val(), + $changed_element.data('hashed_field'), + '[multi_edit][' + $changed_element.data('new_row_index') + ']' + ); + }); + } + }) // end each + .end() + .find('.foreign_values_anchor') + .each(function() { + var $anchor = $(this); + var new_value = 'rownumber=' + new_row_index; + // needs improvement in case something else inside + // the href contains this pattern + var new_href = $anchor.attr('href').replace(/rownumber=\d+/, new_value); + $anchor.attr('href', new_href ); + }); + + //Insert/Clone the ignore checkboxes + if (curr_rows == 1 ) { + $('<input id="insert_ignore_1" type="checkbox" name="insert_ignore_1" checked="checked" />') + .insertBefore("table.insertRowTable:last") + .after('<label for="insert_ignore_1">' + PMA_messages['strIgnore'] + '</label>'); + } + else { + + /** + * @var $last_checkbox Object reference to the last checkbox in #insertForm + */ + var $last_checkbox = $("#insertForm").children('input:checkbox:last'); + + /** name of {@link $last_checkbox} */ + var last_checkbox_name = $last_checkbox.attr('name'); + /** index of {@link $last_checkbox} */ + var last_checkbox_index = parseInt(last_checkbox_name.match(/\d+/)); + /** name of new {@link $last_checkbox} */ + var new_name = last_checkbox_name.replace(/\d+/,last_checkbox_index+1); + + $last_checkbox + .clone() + .attr({'id':new_name, 'name': new_name}) + .prop('checked', true) + .add('label[for^=insert_ignore]:last') + .clone() + .attr('for', new_name) + .before('<br />') + .insertBefore("table.insertRowTable:last"); + } + curr_rows++; + } + // recompute tabindex for text fields and other controls at footer; + // IMO it's not really important to handle the tabindex for + // function and Null + var tabindex = 0; + $('.textfield, .char') + .each(function() { + tabindex++; + $(this).attr('tabindex', tabindex); + // update the IDs of textfields to ensure that they are unique + $(this).attr('id', "field_" + tabindex + "_3"); + }); + $('.control_at_footer') + .each(function() { + tabindex++; + $(this).attr('tabindex', tabindex); + }); + // Add all the required datepickers back + $('input.datefield, input.datetimefield').each(function(){ + PMA_addDatepicker($(this)); + }); + } else if ( curr_rows > target_rows) { + while(curr_rows > target_rows) { + $("input[id^=insert_ignore]:last") + .nextUntil("fieldset") + .andSelf() + .remove(); + curr_rows--; + } + } + }) +}); diff --git a/hugo/js/tbl_chart.js b/hugo/js/tbl_chart.js new file mode 100644 index 0000000..dc292fd --- /dev/null +++ b/hugo/js/tbl_chart.js @@ -0,0 +1,320 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ + +var chart_data = {}; +var temp_chart_title; + +var currentChart = null; +var currentSettings = null; + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('tbl_chart.js', function() { + $('input[name="chartType"]').unbind('click'); + $('input[name="barStacked"]').unbind('click'); + $('input[name="chartTitle"]').unbind('focus').unbind('keyup').unbind('blur'); + $('select[name="chartXAxis"]').unbind('change'); + $('select[name="chartSeries"]').unbind('change'); + $('input[name="xaxis_label"]').unbind('keyup'); + $('input[name="yaxis_label"]').unbind('keyup'); + $('#resizer').unbind('resizestop'); +}); + +AJAX.registerOnload('tbl_chart.js', function() { + + // from jQuery UI + $('#resizer').resizable({ + minHeight: 240, + minWidth: 300 + }) + .width($('#div_view_options').width() - 50); + + $('#resizer').bind('resizestop', function(event, ui) { + // make room so that the handle will still appear + $('#querychart').height($('#resizer').height() * 0.96); + $('#querychart').width($('#resizer').width() * 0.96); + currentChart.redraw({ + resetAxes : true + }); + }); + + currentSettings = { + type : 'line', + width : $('#resizer').width() - 20, + height : $('#resizer').height() - 20, + xaxisLabel : $('input[name="xaxis_label"]').val(), + yaxisLabel : $('input[name="yaxis_label"]').val(), + title : $('input[name="chartTitle"]').val(), + stackSeries : false, + mainAxis : parseInt($('select[name="chartXAxis"]').val()), + selectedSeries : getSelectedSeries() + }; + + // handle chart type changes + $('input[name="chartType"]').click(function() { + currentSettings.type = $(this).val(); + drawChart(); + if ($(this).val() == 'bar' || $(this).val() == 'column' + || $(this).val() == 'line' || $(this).val() == 'area' + || $(this).val() == 'timeline' || $(this).val() == 'spline') { + $('span.barStacked').show(); + } else { + $('span.barStacked').hide(); + } + }); + + // handle stacking for bar, column and area charts + $('input[name="barStacked"]').click(function() { + if (this.checked) { + $.extend(true, currentSettings, {stackSeries : true}); + } else { + $.extend(true, currentSettings, {stackSeries : false}); + } + drawChart(); + }); + + // handle changes in chart title + $('input[name="chartTitle"]').focus(function() { + temp_chart_title = $(this).val(); + }).keyup(function() { + var title = $(this).val(); + if (title.length == 0) { + title = ' '; + } + currentSettings.title = $('input[name="chartTitle"]').val(); + drawChart(); + }).blur(function() { + if ($(this).val() != temp_chart_title) { + drawChart(); + } + }); + + var dateTimeCols = []; + var vals = $('input[name="dateTimeCols"]').val().split(' '); + $.each(vals, function(i, v) { + dateTimeCols.push(parseInt(v)); + }); + + // handle changing the x-axis + $('select[name="chartXAxis"]').change(function() { + currentSettings.mainAxis = parseInt($(this).val()); + if (dateTimeCols.indexOf(currentSettings.mainAxis) != -1) { + $('span.span_timeline').show(); + } else { + $('span.span_timeline').hide(); + if (currentSettings.type == 'timeline') { + $('input#radio_line').prop('checked', true); + currentSettings.type = 'line'; + } + } + var xaxis_title = $(this).children('option:selected').text(); + $('input[name="xaxis_label"]').val(xaxis_title); + currentSettings.xaxisLabel = xaxis_title; + drawChart(); + }); + + // handle changing the selected data series + $('select[name="chartSeries"]').change(function() { + currentSettings.selectedSeries = getSelectedSeries(); + var yaxis_title; + if (currentSettings.selectedSeries.length == 1) { + $('span.span_pie').show(); + yaxis_title = $(this).children('option:selected').text(); + } else { + $('span.span_pie').hide(); + if (currentSettings.type == 'pie') { + $('input#radio_line').prop('checked', true); + currentSettings.type = 'line'; + } + yaxis_title = PMA_messages['strYValues']; + } + $('input[name="yaxis_label"]').val(yaxis_title); + currentSettings.yaxisLabel = yaxis_title; + drawChart(); + }); + + // handle manual changes to the chart axis labels + $('input[name="xaxis_label"]').keyup(function() { + currentSettings.xaxisLabel = $(this).val(); + drawChart(); + }); + $('input[name="yaxis_label"]').keyup(function() { + currentSettings.yaxisLabel = $(this).val(); + drawChart(); + }); + + $("#tblchartform").submit(); +}); + +/** + * Ajax Event handler for 'Go' button click + * + */ +$("#tblchartform").live('submit', function(event) { + if (!checkFormElementInRange(this, 'session_max_rows', PMA_messages['strNotValidRowNumber'], 1) + || !checkFormElementInRange(this, 'pos', PMA_messages['strNotValidRowNumber'], 0 - 1)) { + return false; + } + + var $form = $(this); + if (!checkSqlQuery($form[0])) { + return false; + } + // remove any div containing a previous error message + $('.error').remove(); + var $msgbox = PMA_ajaxShowMessage(); + PMA_prepareForAjaxRequest($form); + + $.post($form.attr('action'), $form.serialize(), function(data) { + if (data.success == true) { + $('.success').fadeOut(); + if (typeof data.chartData != 'undefined') { + chart_data = jQuery.parseJSON(data.chartData); + drawChart(); + $('div#querychart').height($('div#resizer').height() * 0.96); + $('div#querychart').width($('div#resizer').width() * 0.96); + currentChart.redraw({ + resetAxes : true + }); + $('#querychart').show(); + } + } else { + PMA_ajaxRemoveMessage($msgbox); + PMA_ajaxShowMessage(data.error, false); + chart_data = null; + drawChart(); + } + PMA_ajaxRemoveMessage($msgbox); + }, "json"); // end $.post() + + return false; +}); // end + +function drawChart() { + currentSettings.width = $('#resizer').width() - 20; + currentSettings.height = $('#resizer').height() - 20; + + // todo: a better way using .redraw() ? + if (currentChart != null) { + currentChart.destroy(); + } + + var columnNames = []; + $('select[name="chartXAxis"] option').each(function() { + columnNames.push($(this).text()); + }); + try { + currentChart = PMA_queryChart(chart_data, columnNames, currentSettings); + } catch(err) { + PMA_ajaxShowMessage(err.message, false); + } +} + +function getSelectedSeries() { + var val = $('select[name="chartSeries"]').val() || []; + var ret = []; + $.each(val, function(i, v) { + ret.push(parseInt(v)); + }); + return ret; +} + +function extractDate(dateString) { + var matches, match; + var dateTimeRegExp = /[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}/; + var dateRegExp = /[0-9]{4}-[0-9]{2}-[0-9]{2}/; + + matches = dateTimeRegExp.exec(dateString); + if (matches != null && matches.length > 0) { + match = matches[0]; + return new Date(match.substr(0, 4), match.substr(5, 2), match.substr(8, 2), match.substr(11, 2), match.substr(14, 2), match.substr(17, 2)); + } else { + matches = dateRegExp.exec(dateString); + if (matches != null && matches.length > 0) { + match = matches[0]; + return new Date(match.substr(0, 4), match.substr(5, 2), match.substr(8, 2)); + } + } + return null; +} + +function PMA_queryChart(data, columnNames, settings) { + if ($('#querychart').length == 0) { + return; + } + + var jqPlotSettings = { + title : { + text : settings.title, + escapeHtml: true + }, + grid : { + drawBorder : false, + shadow : false, + background : 'rgba(0,0,0,0)' + }, + legend : { + show : true, + placement : 'outsideGrid', + location : 'e' + }, + axes : { + xaxis : { + label : settings.xaxisLabel + }, + yaxis : { + label : settings.yaxisLabel + } + }, + stackSeries : settings.stackSeries, + highlighter: { + show: true, + showTooltip: true, + tooltipAxes: 'xy' + } + }; + + // create the chart + var factory = new JQPlotChartFactory(); + var chart = factory.createChart(settings.type, "querychart"); + + // create the data table and add columns + var dataTable = new DataTable(); + if (settings.type == 'timeline') { + dataTable.addColumn(ColumnType.DATE, columnNames[settings.mainAxis]); + } else { + dataTable.addColumn(ColumnType.STRING, columnNames[settings.mainAxis]); + } + $.each(settings.selectedSeries, function(index, element) { + dataTable.addColumn(ColumnType.NUMBER, columnNames[element]); + }); + + // set data to the data table + var columnsToExtract = [ settings.mainAxis ]; + $.each(settings.selectedSeries, function(index, element) { + columnsToExtract.push(element); + }); + var values = [], newRow, row, col; + for ( var i = 0; i < data.length; i++) { + row = data[i]; + newRow = []; + for ( var j = 0; j < columnsToExtract.length; j++) { + col = columnNames[columnsToExtract[j]]; + if (j == 0) { + if (settings.type == 'timeline') { // first column is date type + newRow.push(extractDate(row[col])); + } else { // first column is string type + newRow.push(row[col]); + } + } else { // subsequent columns are of type, number + newRow.push(parseFloat(row[col])); + } + } + values.push(newRow); + } + dataTable.setData(values); + + // draw the chart and return the chart object + chart.draw(dataTable, jqPlotSettings); + return chart; +} diff --git a/hugo/js/tbl_gis_visualization.js b/hugo/js/tbl_gis_visualization.js new file mode 100644 index 0000000..bd364ce --- /dev/null +++ b/hugo/js/tbl_gis_visualization.js @@ -0,0 +1,350 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * @fileoverview functions used for visualizing GIS data + * + * @requires jquery + * @requires jquery/jquery.svg.js + * @requires jquery/jquery.mousewheel.js + * @requires jquery/jquery.event.drag-2.2.js + */ + +// Constants +var zoomFactor = 1.5; +var defaultX = 0; +var defaultY = 0; + +// Variables +var x; +var y; +var scale; + +var svg; + +/** + * Zooms and pans the visualization. + */ +function zoomAndPan() +{ + var g = svg.getElementById('groupPanel'); + + g.setAttribute('transform', 'translate(' + x + ', ' + y + ') scale(' + scale + ')'); + var id; + var circle; + $('circle.vector').each(function() { + id = $(this).attr('id'); + circle = svg.getElementById(id); + svg.change(circle, { + r : (3 / scale), + "stroke-width" : (2 / scale) + }); + }); + + var line; + $('polyline.vector').each(function() { + id = $(this).attr('id'); + line = svg.getElementById(id); + svg.change(line, { + "stroke-width" : (2 / scale) + }); + }); + + var polygon; + $('path.vector').each(function() { + id = $(this).attr('id'); + polygon = svg.getElementById(id); + svg.change(polygon, { + "stroke-width" : (0.5 / scale) + }); + }); +} + +/** + * Initially loads either SVG or OSM visualization based on the choice. + */ +function selectVisualization() { + if ($('#choice').prop('checked') != true) { + $('#openlayersmap').hide(); + } else { + $('#placeholder').hide(); + } +} + +/** + * Adds necessary styles to the div that coontains the openStreetMap. + */ +function styleOSM() { + var $placeholder = $('#placeholder'); + var cssObj = { + 'border' : '1px solid #aaa', + 'width' : $placeholder.width(), + 'height' : $placeholder.height(), + 'float' : 'right' + }; + $('#openlayersmap').css(cssObj); +} + +/** + * Loads the SVG element and make a reference to it. + */ +function loadSVG() { + var $placeholder = $('#placeholder'); + + $placeholder.svg({ + onLoad: function(svg_ref) { + svg = svg_ref; + } + }); + + // Removes the second SVG element unnecessarily added due to the above command + $placeholder.find('svg:nth-child(2)').remove(); +} + +/** + * Adds controllers for zooming and panning. + */ +function addZoomPanControllers() { + var $placeholder = $('#placeholder'); + if ($("#placeholder svg").length > 0) { + var pmaThemeImage = $('#pmaThemeImage').val(); + // add panning arrows + $('<img class="button" id="left_arrow" src="' + pmaThemeImage + 'west-mini.png">').appendTo($placeholder); + $('<img class="button" id="right_arrow" src="' + pmaThemeImage + 'east-mini.png">').appendTo($placeholder); + $('<img class="button" id="up_arrow" src="' + pmaThemeImage + 'north-mini.png">').appendTo($placeholder); + $('<img class="button" id="down_arrow" src="' + pmaThemeImage + 'south-mini.png">').appendTo($placeholder); + // add zooming controls + $('<img class="button" id="zoom_in" src="' + pmaThemeImage + 'zoom-plus-mini.png">').appendTo($placeholder); + $('<img class="button" id="zoom_world" src="' + pmaThemeImage + 'zoom-world-mini.png">').appendTo($placeholder); + $('<img class="button" id="zoom_out" src="' + pmaThemeImage + 'zoom-minus-mini.png">').appendTo($placeholder); + } +} + +/** + * Resizes the GIS visualization to fit into the space available. + */ +function resizeGISVisualization() { + var $placeholder = $('#placeholder'); + var old_width = $placeholder.width(); + var visWidth = $('#div_view_options').width() - 48; + + // Assign new value for width + $placeholder.width(visWidth); + $('svg').attr('width', visWidth); + + // Assign the offset created due to resizing to defaultX and center the svg. + defaultX = (visWidth - old_width) / 2; + x = defaultX; + y = 0; + scale = 1; +} + +/** + * Initialize the GIS visualization. + */ +function initGISVisualization() { + // Loads either SVG or OSM visualization based on the choice + selectVisualization(); + // Resizes the GIS visualization to fit into the space available + resizeGISVisualization(); + // Adds necessary styles to the div that coontains the openStreetMap + styleOSM(); + // Draws openStreetMap with openLayers + drawOpenLayers(); + // Loads the SVG element and make a reference to it + loadSVG(); + // Adds controllers for zooming and panning + addZoomPanControllers(); + zoomAndPan(); +} + +function getRelativeCoords(e) { + var position = $('#placeholder').offset(); + return { + x : e.pageX - position.left, + y : e.pageY - position.top + }; +} + +/** + * Ajax handlers for GIS visualization page + * + * Actions Ajaxified here: + * + * Zooming in and zooming out on mousewheel movement. + * Panning the visualization on dragging. + * Zooming in on double clicking. + * Zooming out on clicking the zoom out button. + * Panning on clicking the arrow buttons. + * Displaying tooltips for GIS objects. + */ + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('tbl_gis_visualization.js', function() { + $('#choice').die('click'); + $('#placeholder').die('mousewheel'); + $('svg').die('dragstart'); + $('svg').die('mouseup'); + $('svg').die('drag'); + $('#placeholder').die('dblclick'); + $('#zoom_in').die('click'); + $('#zoom_world').die('click'); + $('#zoom_out').die('click'); + $('#left_arrow').die('click'); + $('#right_arrow').die('click'); + $('#up_arrow').die('click'); + $('#down_arrow').die('click'); + $('.vector').unbind('mousemove').unbind('mouseout'); +}); + +AJAX.registerOnload('tbl_gis_visualization.js', function() { + + // If we are in GIS visualization, initialize it + if ($('table.gis_table').length > 0) { + initGISVisualization(); + } + + $('#choice').live('click', function() { + if ($(this).prop('checked') == false) { + $('#placeholder').show(); + $('#openlayersmap').hide(); + } else { + $('#placeholder').hide(); + $('#openlayersmap').show(); + } + }); + + $('#placeholder').live('mousewheel', function(event, delta) { + var relCoords = getRelativeCoords(event); + if (delta > 0) { + //zoom in + scale *= zoomFactor; + // zooming in keeping the position under mouse pointer unmoved. + x = relCoords.x - (relCoords.x - x) * zoomFactor; + y = relCoords.y - (relCoords.y - y) * zoomFactor; + zoomAndPan(); + } else { + //zoom out + scale /= zoomFactor; + // zooming out keeping the position under mouse pointer unmoved. + x = relCoords.x - (relCoords.x - x) / zoomFactor; + y = relCoords.y - (relCoords.y - y) / zoomFactor; + zoomAndPan(); + } + return true; + }); + + var dragX = 0; var dragY = 0; + $('svg').live('dragstart', function(event, dd) { + $('#placeholder').addClass('placeholderDrag'); + dragX = Math.round(dd.offsetX); + dragY = Math.round(dd.offsetY); + }); + + $('svg').live('mouseup', function(event) { + $('#placeholder').removeClass('placeholderDrag'); + }); + + $('svg').live('drag', function(event, dd) { + newX = Math.round(dd.offsetX); + x += newX - dragX; + dragX = newX; + newY = Math.round(dd.offsetY); + y += newY - dragY; + dragY = newY; + zoomAndPan(); + }); + + $('#placeholder').live('dblclick', function(event) { + scale *= zoomFactor; + // zooming in keeping the position under mouse pointer unmoved. + var relCoords = getRelativeCoords(event); + x = relCoords.x - (relCoords.x - x) * zoomFactor; + y = relCoords.y - (relCoords.y - y) * zoomFactor; + zoomAndPan(); + }); + + $('#zoom_in').live('click', function(e) { + e.preventDefault(); + //zoom in + scale *= zoomFactor; + + width = $('#placeholder svg').attr('width'); + height = $('#placeholder svg').attr('height'); + // zooming in keeping the center unmoved. + x = width / 2 - (width / 2 - x) * zoomFactor; + y = height / 2 - (height / 2 - y) * zoomFactor; + zoomAndPan(); + }); + + $('#zoom_world').live('click', function(e) { + e.preventDefault(); + scale = 1; + x = defaultX; + y = defaultY; + zoomAndPan(); + }); + + $('#zoom_out').live('click', function(e) { + e.preventDefault(); + //zoom out + scale /= zoomFactor; + + width = $('#placeholder svg').attr('width'); + height = $('#placeholder svg').attr('height'); + // zooming out keeping the center unmoved. + x = width / 2 - (width / 2 - x) / zoomFactor; + y = height / 2 - (height / 2 - y) / zoomFactor; + zoomAndPan(); + }); + + $('#left_arrow').live('click', function(e) { + e.preventDefault(); + x += 100; + zoomAndPan(); + }); + + $('#right_arrow').live('click', function(e) { + e.preventDefault(); + x -= 100; + zoomAndPan(); + }); + + $('#up_arrow').live('click', function(e) { + e.preventDefault(); + y += 100; + zoomAndPan(); + }); + + $('#down_arrow').live('click', function(e) { + e.preventDefault(); + y -= 100; + zoomAndPan(); + }); + + /** + * Detect the mousemove event and show tooltips. + */ + $('.vector').bind('mousemove', function(event) { + var contents = $.trim(escapeHtml($(this).attr('name'))); + $("#tooltip").remove(); + if (contents != '') { + $('<div id="tooltip">' + contents + '</div>').css({ + position : 'absolute', + top : event.pageY + 10, + left : event.pageX + 10, + border : '1px solid #fdd', + padding : '2px', + 'background-color' : '#fee', + opacity : 0.90 + }).appendTo("body").fadeIn(200); + } + }); + + /** + * Detect the mouseout event and hide tooltips. + */ + $('.vector').bind('mouseout', function(event) { + $("#tooltip").remove(); + }); +}); diff --git a/hugo/js/tbl_relation.js b/hugo/js/tbl_relation.js new file mode 100644 index 0000000..4ce3985 --- /dev/null +++ b/hugo/js/tbl_relation.js @@ -0,0 +1,34 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * for tbl_relation.php + * + */ +function show_hide_clauses($thisDropdown) +{ + // here, one span contains the label and the clause dropdown + // and we have one span for ON DELETE and one for ON UPDATE + // + if ($thisDropdown.val() != '') { + $thisDropdown.parent().nextAll('span').show(); + } else { + $thisDropdown.parent().nextAll('span').hide(); + } +} + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('tbl_relation.js', function() { + $('select.referenced_column_dropdown').unbind('change'); +}); + +AJAX.registerOnload('tbl_relation.js', function() { + // initial display + $('select.referenced_column_dropdown').each(function(index, one_dropdown) { + show_hide_clauses($(one_dropdown)); + }); + // change + $('select.referenced_column_dropdown').change(function() { + show_hide_clauses($(this)); + }); +}); diff --git a/hugo/js/tbl_select.js b/hugo/js/tbl_select.js new file mode 100644 index 0000000..e8a13ec --- /dev/null +++ b/hugo/js/tbl_select.js @@ -0,0 +1,224 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * @fileoverview JavaScript functions used on tbl_select.php + * + * @requires jQuery + * @requires js/functions.js + */ + +/** + * Ajax event handlers for this page + * + * Actions ajaxified here: + * Table Search + */ + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('tbl_select.js', function() { + $('#togglesearchformlink').unbind('click'); + $("#tbl_search_form.ajax").die('submit'); + $('select.geom_func').unbind('change'); + $('span.open_search_gis_editor').die('click'); +}); + +AJAX.registerOnload('tbl_select.js', function() { + /** + * Prepare a div containing a link, otherwise it's incorrectly displayed + * after a couple of clicks + */ + $('<div id="togglesearchformdiv"><a id="togglesearchformlink"></a></div>') + .insertAfter('#tbl_search_form') + // don't show it until we have results on-screen + .hide(); + + $('#togglesearchformlink') + .html(PMA_messages['strShowSearchCriteria']) + .bind('click', function() { + var $link = $(this); + $('#tbl_search_form').slideToggle(); + if ($link.text() == PMA_messages['strHideSearchCriteria']) { + $link.text(PMA_messages['strShowSearchCriteria']); + } else { + $link.text(PMA_messages['strHideSearchCriteria']); + } + // avoid default click action + return false; + }); + + /** + * Ajax event handler for Table Search + */ + $("#tbl_search_form.ajax").live('submit', function(event) { + var unaryFunctions = [ + 'IS NULL', + 'IS NOT NULL', + "= ''", + "!= ''"]; + + // jQuery object to reuse + $search_form = $(this); + event.preventDefault(); + + // empty previous search results while we are waiting for new results + $("#sqlqueryresults").empty(); + var $msgbox = PMA_ajaxShowMessage(PMA_messages['strSearching'], false); + + PMA_prepareForAjaxRequest($search_form); + + var values = {}; + $search_form.find(':input').each(function() { + var $input = $(this); + if ($input.attr('type') == 'checkbox' || $input.attr('type') == 'radio') { + if ($input.is(':checked')) { + values[this.name] = $input.val(); + } + } else { + values[this.name] = $input.val(); + } + }); + var columnCount = $('select[name="columnsToDisplay[]"] option').length; + // Submit values only for the columns that have unary column operator or a search criteria + for (var a = 0; a < columnCount; a++) { + if ($.inArray(values['criteriaColumnOperators[' + a + ']'], unaryFunctions) >= 0) { + continue; + } + + if (values['criteriaValues[' + a + ']'] == '' || values['criteriaValues[' + a + ']'] == null) { + delete values['criteriaValues[' + a + ']']; + delete values['criteriaColumnOperators[' + a + ']']; + delete values['criteriaColumnNames[' + a + ']']; + delete values['criteriaColumnTypes[' + a + ']']; + delete values['criteriaColumnCollations[' + a + ']']; + } + } + // If all columns are selected, use a single parameter to indicate that + if (values['columnsToDisplay[]'] != null) { + if (values['columnsToDisplay[]'].length == columnCount) { + delete values['columnsToDisplay[]']; + values['displayAllColumns'] = true; + } + } else { + values['displayAllColumns'] = true; + } + + $.post($search_form.attr('action'), values, function(data) { + PMA_ajaxRemoveMessage($msgbox); + if (data.success == true) { + if (data.sql_query != null) { // zero rows + $("#sqlqueryresults").html(data.sql_query); + } else { // results found + $("#sqlqueryresults").html(data.message); + $("#sqlqueryresults").trigger('makegrid'); + } + $('#tbl_search_form') + // workaround for bug #3168569 - Issue on toggling the "Hide search criteria" in chrome. + .slideToggle() + .hide(); + $('#togglesearchformlink') + // always start with the Show message + .text(PMA_messages['strShowSearchCriteria']); + $('#togglesearchformdiv') + // now it's time to show the div containing the link + .show(); + // needed for the display options slider in the results + PMA_init_slider(); + } else { + $("#sqlqueryresults").html(data.error); + } + }); // end $.post() + }); + + // Following section is related to the 'function based search' for geometry data types. + // Initialy hide all the open_gis_editor spans + $('span.open_search_gis_editor').hide(); + + $('select.geom_func').bind('change', function() { + var $geomFuncSelector = $(this); + + var binaryFunctions = [ + 'Contains', + 'Crosses', + 'Disjoint', + 'Equals', + 'Intersects', + 'Overlaps', + 'Touches', + 'Within', + 'MBRContains', + 'MBRDisjoint', + 'MBREquals', + 'MBRIntersects', + 'MBROverlaps', + 'MBRTouches', + 'MBRWithin', + 'ST_Contains', + 'ST_Crosses', + 'ST_Disjoint', + 'ST_Equals', + 'ST_Intersects', + 'ST_Overlaps', + 'ST_Touches', + 'ST_Within' + ]; + + var tempArray = [ + 'Envelope', + 'EndPoint', + 'StartPoint', + 'ExteriorRing', + 'Centroid', + 'PointOnSurface' + ]; + var outputGeomFunctions = binaryFunctions.concat(tempArray); + + // If the chosen function takes two geometry objects as parameters + var $operator = $geomFuncSelector.parents('tr').find('td:nth-child(5)').find('select'); + if ($.inArray($geomFuncSelector.val(), binaryFunctions) >= 0){ + $operator.prop('readonly', true); + } else { + $operator.prop('readonly', false); + } + + // if the chosen function's output is a geometry, enable GIS editor + var $editorSpan = $geomFuncSelector.parents('tr').find('span.open_search_gis_editor'); + if ($.inArray($geomFuncSelector.val(), outputGeomFunctions) >= 0){ + $editorSpan.show(); + } else { + $editorSpan.hide(); + } + + }); + + $('span.open_search_gis_editor').live('click', function(event) { + event.preventDefault(); + + var $span = $(this); + // Current value + var value = $span.parent('td').children("input[type='text']").val(); + // Field name + var field = 'Parameter'; + // Column type + var geom_func = $span.parents('tr').find('.geom_func').val(); + if (geom_func == 'Envelope') { + var type = 'polygon'; + } else if (geom_func == 'ExteriorRing') { + var type = 'linestring'; + } else { + var type = 'point'; + } + // Names of input field and null checkbox + var input_name = $span.parent('td').children("input[type='text']").attr('name'); + //Token + var token = $("input[name='token']").val(); + + openGISEditor(); + if (!gisEditorLoaded) { + loadJSAndGISEditor(value, field, type, input_name, token); + } else { + loadGISEditor(value, field, type, input_name, token); + } + }); + +}); diff --git a/hugo/js/tbl_structure.js b/hugo/js/tbl_structure.js new file mode 100644 index 0000000..7b1433e --- /dev/null +++ b/hugo/js/tbl_structure.js @@ -0,0 +1,420 @@ +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + * @fileoverview functions used on the table structure page + * @name Table Structure + * + * @requires jQuery + * @requires jQueryUI + * @required js/functions.js + */ + +/** + * AJAX scripts for tbl_structure.php + * + * Actions ajaxified here: + * Drop Column + * Add Primary Key + * Drop Primary Key/Index + * + */ + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('tbl_structure.js', function() { + $("a.change_column_anchor.ajax").die('click'); + $("button.change_columns_anchor.ajax, input.change_columns_anchor.ajax").die('click'); + $("a.drop_column_anchor.ajax").die('click'); + $("a.add_primary_key_anchor.ajax").die('click'); + $("#move_columns_anchor").die('click'); + $(".append_fields_form.ajax").unbind('submit'); +}); + +AJAX.registerOnload('tbl_structure.js', function() { + + /** + *Ajax action for submitting the "Column Change" and "Add Column" form + */ + $(".append_fields_form.ajax").die().live('submit', function(event) { + event.preventDefault(); + /** + * @var the_form object referring to the export form + */ + var $form = $(this); + + /* + * First validate the form; if there is a problem, avoid submitting it + * + * checkTableEditForm() needs a pure element and not a jQuery object, + * this is why we pass $form[0] as a parameter (the jQuery object + * is actually an array of DOM elements) + */ + if (checkTableEditForm($form[0], $form.find('input[name=orig_num_fields]').val())) { + // OK, form passed validation step + PMA_prepareForAjaxRequest($form); + //User wants to submit the form + $msg = PMA_ajaxShowMessage(); + $.post($form.attr('action'), $form.serialize() + '&do_save_data=1', function(data) { + if ($("#sqlqueryresults").length != 0) { + $("#sqlqueryresults").remove(); + } else if ($(".error:not(.tab)").length != 0) { + $(".error:not(.tab)").remove(); + } + if (data.success == true) { + $("#page_content") + .empty() + .append(data.message) + .append(data.sql_query) + .show(); + $("#result_query .notice").remove(); + $form.remove(); + PMA_ajaxRemoveMessage($msg); + PMA_reloadNavigation(); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); // end $.post() + } + }); // end change table button "do_save_data" + + /** + * Attach Event Handler for 'Change Column' + */ + $("a.change_column_anchor.ajax").live('click', function(event) { + event.preventDefault(); + var $msg = PMA_ajaxShowMessage(); + $('#page_content').hide(); + $.get($(this).attr('href'), {'ajax_request': true}, function (data) { + PMA_ajaxRemoveMessage($msg); + if (data.success) { + $('<div id="change_column_dialog" class="margin"></div>') + .html(data.message) + .insertBefore('#page_content'); + PMA_showHints(); + PMA_verifyColumnsProperties(); + } else { + PMA_ajaxShowMessage(PMA_messages['strErrorProcessingRequest'] + " : " + data.error, false); + } + }); + }); + + /** + * Attach Event Handler for 'Change multiple columns' + */ + $("button.change_columns_anchor.ajax, input.change_columns_anchor.ajax").live('click', function(event) { + event.preventDefault(); + var $msg = PMA_ajaxShowMessage(); + $('#page_content').hide(); + var $form = $(this).closest('form'); + var params = $form.serialize() + "&ajax_request=true&submit_mult=change"; + $.post($form.prop("action"), params, function (data) { + PMA_ajaxRemoveMessage($msg); + if (data.success) { + $('#page_content') + .empty() + .append( + $('<div id="change_column_dialog"></div>') + .html(data.message) + ) + .show(); + PMA_showHints(); + PMA_verifyColumnsProperties(); + } else { + $('#page_content').show(); + PMA_ajaxShowMessage(data.error); + } + }); + }); + + /** + * Attach Event Handler for 'Drop Column' + */ + $("a.drop_column_anchor.ajax").live('click', function(event) { + event.preventDefault(); + /** + * @var curr_table_name String containing the name of the current table + */ + var curr_table_name = $(this).closest('form').find('input[name=table]').val(); + /** + * @var curr_row Object reference to the currently selected row (i.e. field in the table) + */ + var $curr_row = $(this).parents('tr'); + /** + * @var curr_column_name String containing name of the field referred to by {@link curr_row} + */ + var curr_column_name = $curr_row.children('th').children('label').text(); + /** + * @var $after_field_item Corresponding entry in the 'After' field. + */ + var $after_field_item = $("select[name='after_field'] option[value='" + curr_column_name + "']"); + /** + * @var question String containing the question to be asked for confirmation + */ + var question = $.sprintf(PMA_messages['strDoYouReally'], 'ALTER TABLE `' + escapeHtml(curr_table_name) + '` DROP `' + escapeHtml(curr_column_name) + '`;'); + $(this).PMA_confirm(question, $(this).attr('href'), function(url) { + var $msg = PMA_ajaxShowMessage(PMA_messages['strDroppingColumn'], false); + $.get(url, {'is_js_confirmed' : 1, 'ajax_request' : true, 'ajax_page_request' : true}, function (data) { + if (data.success == true) { + PMA_ajaxRemoveMessage($msg); + if ($('#result_query').length) { + $('#result_query').remove(); + } + if (data.sql_query) { + $('<div id="result_query"></div>') + .html(data.sql_query) + .prependTo('#page_content'); + } + toggleRowColors($curr_row.next()); + // Adjust the row numbers + for (var $row = $curr_row.next(); $row.length > 0; $row = $row.next()) { + var new_val = parseInt($row.find('td:nth-child(2)').text()) - 1; + $row.find('td:nth-child(2)').text(new_val); + } + $after_field_item.remove(); + $curr_row.hide("medium").remove(); + //refresh table stats + if (data.tableStat) { + $('#tablestatistics').html(data.tableStat); + } + // refresh the list of indexes (comes from sql.php) + $('.index_info').replaceWith(data.indexes_list); + PMA_reloadNavigation(); + } else { + PMA_ajaxShowMessage(PMA_messages['strErrorProcessingRequest'] + " : " + data.error, false); + } + }); // end $.get() + }); // end $.PMA_confirm() + }) ; //end of Drop Column Anchor action + + /** + * Ajax Event handler for 'Add Primary Key' + */ + $("a.add_primary_key_anchor.ajax").live('click', function(event) { + event.preventDefault(); + /** + * @var curr_table_name String containing the name of the current table + */ + var curr_table_name = $(this).closest('form').find('input[name=table]').val(); + /** + * @var curr_column_name String containing name of the field referred to by {@link curr_row} + */ + var curr_column_name = $(this).parents('tr').children('th').children('label').text(); + /** + * @var question String containing the question to be asked for confirmation + */ + var question = $.sprintf(PMA_messages['strDoYouReally'], 'ALTER TABLE `' + escapeHtml(curr_table_name) + '` ADD PRIMARY KEY(`' + escapeHtml(curr_column_name) + '`);'); + $(this).PMA_confirm(question, $(this).attr('href'), function(url) { + var $msg = PMA_ajaxShowMessage(PMA_messages['strAddingPrimaryKey'], false); + $.get(url, {'is_js_confirmed' : 1, 'ajax_request' : true}, function(data) { + if (data.success == true) { + PMA_ajaxRemoveMessage($msg); + $(this).remove(); + if (typeof data.reload != 'undefined') { + PMA_commonActions.refreshMain(false, function () { + if ($('#result_query').length) { + $('#result_query').remove(); + } + if (data.sql_query) { + $('<div id="result_query"></div>') + .html(data.sql_query) + .prependTo('#page_content'); + } + }); + PMA_reloadNavigation(); + } + } else { + PMA_ajaxShowMessage(PMA_messages['strErrorProcessingRequest'] + " : " + data.error, false); + } + }); // end $.get() + }); // end $.PMA_confirm() + }); //end Add Primary Key + + /** + * Inline move columns + **/ + $("#move_columns_anchor").live('click', function(e) { + e.preventDefault(); + + if ($(this).hasClass("move-active")) { + return; + } + + /** + * @var button_options Object that stores the options passed to jQueryUI + * dialog + */ + var button_options = {}; + + button_options[PMA_messages['strGo']] = function(event) { + event.preventDefault(); + var $msgbox = PMA_ajaxShowMessage(); + var $this = $(this); + var $form = $this.find("form"); + var serialized = $form.serialize(); + + // check if any columns were moved at all + if (serialized == $form.data("serialized-unmoved")) { + PMA_ajaxRemoveMessage($msgbox); + $this.dialog('close'); + return; + } + + $.post($form.prop("action"), serialized + "&ajax_request=true", function (data) { + if (data.success == false) { + PMA_ajaxRemoveMessage($msgbox); + $this + .clone() + .html(data.error) + .dialog({ + title: $(this).prop("title"), + height: 230, + width: 900, + modal: true, + buttons: button_options_error + }); // end dialog options + } else { + $('#fieldsForm ul.table-structure-actions').menuResizer('destroy'); + // sort the fields table + var $fields_table = $("table#tablestructure tbody"); + // remove all existing rows and remember them + var $rows = $fields_table.find("tr").remove(); + // loop through the correct order + for (var i in data.columns) { + var the_column = data.columns[i]; + var $the_row = $rows + .find("input:checkbox[value=" + the_column + "]") + .closest("tr"); + // append the row for this column to the table + $fields_table.append($the_row); + } + var $firstrow = $fields_table.find("tr").eq(0); + // Adjust the row numbers and colors + for (var $row = $firstrow; $row.length > 0; $row = $row.next()) { + $row + .find('td:nth-child(2)') + .text($row.index() + 1) + .end() + .removeClass("odd even") + .addClass($row.index() % 2 == 0 ? "odd" : "even"); + } + PMA_ajaxShowMessage(data.message); + $this.dialog('close'); + $('#fieldsForm ul.table-structure-actions').menuResizer(PMA_tbl_structure_menu_resizer_callback); + } + }); + }; + button_options[PMA_messages['strCancel']] = function() { + $(this).dialog('close'); + }; + + var button_options_error = {}; + button_options_error[PMA_messages['strOK']] = function() { + $(this).dialog('close').remove(); + }; + + var columns = []; + + $("#tablestructure tbody tr").each(function () { + var col_name = $(this).find("input:checkbox").eq(0).val(); + var hidden_input = $("<input/>") + .prop({ + name: "move_columns[]", + type: "hidden" + }) + .val(col_name); + columns[columns.length] = $("<li/>") + .addClass("placeholderDrag") + .text(col_name) + .append(hidden_input); + }); + + var col_list = $("#move_columns_dialog ul") + .find("li").remove().end(); + for (var i in columns) { + col_list.append(columns[i]); + } + col_list.sortable({ + axis: 'y', + containment: $("#move_columns_dialog div") + }).disableSelection(); + var $form = $("#move_columns_dialog form"); + $form.data("serialized-unmoved", $form.serialize()); + + $("#move_columns_dialog").dialog({ + modal: true, + buttons: button_options, + beforeClose: function () { + $("#move_columns_anchor").removeClass("move-active"); + } + }); + }); +}); + +/** + * Reload fields table + */ +function reloadFieldForm(message) { + $.post($("#fieldsForm").attr('action'), $("#fieldsForm").serialize()+"&ajax_request=true", function(form_data) { + var $temp_div = $("<div id='temp_div'><div>").append(form_data.message); + $("#fieldsForm").replaceWith($temp_div.find("#fieldsForm")); + $("#addColumns").replaceWith($temp_div.find("#addColumns")); + $('#move_columns_dialog ul').replaceWith($temp_div.find("#move_columns_dialog ul")); + $("#moveColumns").removeClass("move-active"); + /* reinitialise the more options in table */ + $('#fieldsForm ul.table-structure-actions').menuResizer(PMA_tbl_structure_menu_resizer_callback); + setTimeout(function() { + PMA_ajaxShowMessage(message); + }, 500); + }); + $('#page_content').show(); +} + +/** + * This function returns the horizontal space available for the menu in pixels. + * To calculate this value we start we the width of the main panel, then we + * substract the margin of the page content, then we substract any cellspacing + * that the table may have (original theme only) and finally we substract the + * width of all columns of the table except for the last one (which is where + * the menu will go). What we should end up with is the distance between the + * start of the last column on the table and the edge of the page, again this + * is the space available for the menu. + * + * In the case where the table cell where the menu will be displayed is already + * off-screen (the table is wider than the page), a negative value will be returned, + * but this will be treated as a zero by the menuResizer plugin. + * + * @return int + */ +function PMA_tbl_structure_menu_resizer_callback() { + var pagewidth = $('body').width(); + var $page = $('#page_content'); + pagewidth -= $page.outerWidth(true) - $page.outerWidth(); + var columnsWidth = 0; + var $columns = $('#tablestructure').find('tr:eq(1)').find('td,th'); + $columns.not(':last').each(function (){ + columnsWidth += $(this).outerWidth(true) + }); + var totalCellSpacing = $('#tablestructure').width(); + $columns.each(function (){ + totalCellSpacing -= $(this).outerWidth(true); + }); + return pagewidth - columnsWidth - totalCellSpacing - 15; // 15px extra margin +} + +/** Handler for "More" dropdown in structure table rows */ +AJAX.registerOnload('tbl_structure.js', function() { + if ($('#fieldsForm').hasClass('HideStructureActions')) { + $('#fieldsForm ul.table-structure-actions').menuResizer(PMA_tbl_structure_menu_resizer_callback); + } +}); +AJAX.registerTeardown('tbl_structure.js', function() { + $('#fieldsForm ul.table-structure-actions').menuResizer('destroy'); +}); +$(function () { + $(window).resize($.throttle(function () { + var $list = $('#fieldsForm ul.table-structure-actions'); + if ($list.length) { + $list.menuResizer('resize'); + } + })); +}); diff --git a/hugo/js/tbl_zoom_plot_jqplot.js b/hugo/js/tbl_zoom_plot_jqplot.js new file mode 100644 index 0000000..e6ed6f3 --- /dev/null +++ b/hugo/js/tbl_zoom_plot_jqplot.js @@ -0,0 +1,614 @@ +// todo: change the axis +/* vim: set expandtab sw=4 ts=4 sts=4: */ +/** + ** @fileoverview JavaScript functions used on tbl_select.php + ** + ** @requires jQuery + ** @requires js/functions.js + **/ + + +/** + ** Display Help/Info + **/ +function displayHelp() { + PMA_ajaxShowMessage(PMA_messages['strDisplayHelp'], 10000); +} + +/** + ** Extend the array object for max function + ** @param array + **/ +Array.max = function (array) { + return Math.max.apply( Math, array ); +}; + +/** + ** Extend the array object for min function + ** @param array + **/ +Array.min = function (array) { + return Math.min.apply( Math, array ); +}; + +/** + ** Checks if a string contains only numeric value + ** @param n: String (to be checked) + **/ +function isNumeric(n) { + return !isNaN(parseFloat(n)) && isFinite(n); +} + +/** + ** Checks if an object is empty + ** @param n: Object (to be checked) + **/ +function isEmpty(obj) { + var name; + for (name in obj) { + return false; + } + return true; +} + +/** + ** Converts a date/time into timestamp + ** @param val String Date + ** @param type Sring Field type(datetime/timestamp/time/date) + **/ +function getTimeStamp(val, type) { + if (type.toString().search(/datetime/i) != -1 || type.toString().search(/timestamp/i) != -1) { + return $.datepicker.parseDateTime('yy-mm-dd', 'HH:mm:ss', val); + } + else if (type.toString().search(/time/i) != -1) { + return $.datepicker.parseDateTime('yy-mm-dd', 'HH:mm:ss', '1970-01-01 ' + val); + } + else if (type.toString().search(/date/i) != -1) { + return $.datepicker.parseDate('yy-mm-dd', val); + } +} + +/** + ** Classifies the field type into numeric,timeseries or text + ** @param field: field type (as in database structure) + **/ +function getType(field) { + if (field.toString().search(/int/i) != -1 || field.toString().search(/decimal/i) != -1 + || field.toString().search(/year/i) != -1) { + return 'numeric'; + } else if (field.toString().search(/time/i) != -1 || field.toString().search(/date/i) != -1) { + return 'time'; + } else { + return 'text'; + } +} +/** + ** Converts a categorical array into numeric array + ** @param array categorical values array + **/ +function getCord(arr) { + var newCord = []; + var original = $.extend(true, [], arr); + var arr = jQuery.unique(arr).sort(); + $.each(original, function(index, value) { + newCord.push(jQuery.inArray(value, arr)); + }); + return [newCord, arr, original]; +} + +/** + ** Scrolls the view to the display section + **/ +function scrollToChart() { + var x = $('#dataDisplay').offset().top - 100; // 100 provides buffer in viewport + $('html,body').animate({scrollTop: x}, 500); +} + +/** + * Unbind all event handlers before tearing down a page + */ +AJAX.registerTeardown('tbl_zoom_plot_jqplot.js', function() { + $('#tableid_0').unbind('change'); + $('#tableid_1').unbind('change'); + $('#tableid_2').unbind('change'); + $('#tableid_3').unbind('change'); + $('#inputFormSubmitId').unbind('click'); + $('#togglesearchformlink').unbind('click'); + $("#dataDisplay").find(':input').die('keydown'); + $('button.button-reset').unbind('click'); + $('div#resizer').unbind('resizestop'); + $('div#querychart').unbind('jqplotDataClick'); +}); + +AJAX.registerOnload('tbl_zoom_plot_jqplot.js', function() { + var cursorMode = ($("input[name='mode']:checked").val() == 'edit') ? 'crosshair' : 'pointer'; + var currentChart = null; + var searchedDataKey = null; + var xLabel = $('#tableid_0').val(); + var yLabel = $('#tableid_1').val(); + // will be updated via Ajax + var xType = $('#types_0').val(); + var yType = $('#types_1').val(); + var dataLabel = $('#dataLabel').val(); + var lastX; + var lastY; + var zoomRatio = 1; + + + // Get query result + var searchedData = jQuery.parseJSON($('#querydata').html()); + + /** + ** Input form submit on field change + **/ + + // first column choice corresponds to the X axis + $('#tableid_0').change(function() { + //AJAX request for field type, collation, operators, and value field + $.post('tbl_zoom_select.php',{ + 'ajax_request' : true, + 'change_tbl_info' : true, + 'db' : PMA_commonParams.get('db'), + 'table' : PMA_commonParams.get('table'), + 'field' : $('#tableid_0').val(), + 'it' : 0, + 'token' : PMA_commonParams.get('token') + },function(data) { + $('#tableFieldsId tr:eq(1) td:eq(0)').html(data.field_type); + $('#tableFieldsId tr:eq(1) td:eq(1)').html(data.field_collation); + $('#tableFieldsId tr:eq(1) td:eq(2)').html(data.field_operators); + $('#tableFieldsId tr:eq(1) td:eq(3)').html(data.field_value); + xLabel = $('#tableid_0').val(); + $('#types_0').val(data.field_type); + xType = data.field_type; + $('#collations_0').val(data.field_collations); + addDateTimePicker(); + }); + }); + + // second column choice corresponds to the Y axis + $('#tableid_1').change(function() { + //AJAX request for field type, collation, operators, and value field + $.post('tbl_zoom_select.php',{ + 'ajax_request' : true, + 'change_tbl_info' : true, + 'db' : PMA_commonParams.get('db'), + 'table' : PMA_commonParams.get('table'), + 'field' : $('#tableid_1').val(), + 'it' : 1, + 'token' : PMA_commonParams.get('token') + },function(data) { + $('#tableFieldsId tr:eq(3) td:eq(0)').html(data.field_type); + $('#tableFieldsId tr:eq(3) td:eq(1)').html(data.field_collation); + $('#tableFieldsId tr:eq(3) td:eq(2)').html(data.field_operators); + $('#tableFieldsId tr:eq(3) td:eq(3)').html(data.field_value); + yLabel = $('#tableid_1').val(); + $('#types_1').val(data.field_type); + yType = data.field_type; + $('#collations_1').val(data.field_collations); + addDateTimePicker(); + }); + }); + + $('#tableid_2').change(function() { + //AJAX request for field type, collation, operators, and value field + $.post('tbl_zoom_select.php',{ + 'ajax_request' : true, + 'change_tbl_info' : true, + 'db' : PMA_commonParams.get('db'), + 'table' : PMA_commonParams.get('table'), + 'field' : $('#tableid_2').val(), + 'it' : 2, + 'token' : PMA_commonParams.get('token') + },function(data) { + $('#tableFieldsId tr:eq(6) td:eq(0)').html(data.field_type); + $('#tableFieldsId tr:eq(6) td:eq(1)').html(data.field_collation); + $('#tableFieldsId tr:eq(6) td:eq(2)').html(data.field_operators); + $('#tableFieldsId tr:eq(6) td:eq(3)').html(data.field_value); + $('#types_2').val(data.field_type); + $('#collations_2').val(data.field_collations); + addDateTimePicker(); + }); + }); + + $('#tableid_3').change(function() { + //AJAX request for field type, collation, operators, and value field + $.post('tbl_zoom_select.php',{ + 'ajax_request' : true, + 'change_tbl_info' : true, + 'db' : PMA_commonParams.get('db'), + 'table' : PMA_commonParams.get('table'), + 'field' : $('#tableid_3').val(), + 'it' : 3, + 'token' : PMA_commonParams.get('token') + },function(data) { + $('#tableFieldsId tr:eq(8) td:eq(0)').html(data.field_type); + $('#tableFieldsId tr:eq(8) td:eq(1)').html(data.field_collation); + $('#tableFieldsId tr:eq(8) td:eq(2)').html(data.field_operators); + $('#tableFieldsId tr:eq(8) td:eq(3)').html(data.field_value); + $('#types_3').val(data.field_type); + $('#collations_3').val(data.field_collations); + addDateTimePicker(); + }); + }); + + /** + * Input form validation + **/ + $('#inputFormSubmitId').click(function() { + if ($('#tableid_0').get(0).selectedIndex == 0 || $('#tableid_1').get(0).selectedIndex == 0) { + PMA_ajaxShowMessage(PMA_messages['strInputNull']); + } else if (xLabel == yLabel) { + PMA_ajaxShowMessage(PMA_messages['strSameInputs']); + } + }); + + /** + ** Prepare a div containing a link, otherwise it's incorrectly displayed + ** after a couple of clicks + **/ + $('<div id="togglesearchformdiv"><a id="togglesearchformlink"></a></div>') + .insertAfter('#zoom_search_form') + // don't show it until we have results on-screen + .hide(); + + $('#togglesearchformlink') + .html(PMA_messages['strShowSearchCriteria']) + .bind('click', function() { + var $link = $(this); + $('#zoom_search_form').slideToggle(); + if ($link.text() == PMA_messages['strHideSearchCriteria']) { + $link.text(PMA_messages['strShowSearchCriteria']); + } else { + $link.text(PMA_messages['strHideSearchCriteria']); + } + // avoid default click action + return false; + }); + + /** + ** Set dialog properties for the data display form + **/ + var buttonOptions = {}; + /* + * Handle saving of a row in the editor + */ + buttonOptions[PMA_messages['strSave']] = function () { + //Find changed values by comparing form values with selectedRow Object + var newValues = {};//Stores the values changed from original + var sqlTypes = {}; + var it = 0; + var xChange = false; + var yChange = false; + var key; + for (key in selectedRow) { + var oldVal = selectedRow[key]; + var newVal = ($('#edit_fields_null_id_' + it).prop('checked')) ? null : $('#edit_fieldID_' + it).val(); + if (newVal instanceof Array) { // when the column is of type SET + newVal = $('#edit_fieldID_' + it).map(function(){ + return $(this).val(); + }).get().join(","); + } + if (oldVal != newVal) { + selectedRow[key] = newVal; + newValues[key] = newVal; + if (key == xLabel) { + xChange = true; + searchedData[searchedDataKey][xLabel] = newVal; + } else if (key == yLabel) { + yChange = true; + searchedData[searchedDataKey][yLabel] = newVal; + } + } + var $input = $('#edit_fieldID_' + it); + if ($input.hasClass('bit')) { + sqlTypes[key] = 'bit'; + } + it++; + } //End data update + + //Update the chart series and replot + if (xChange || yChange) { + //Logic similar to plot generation, replot only if xAxis changes or yAxis changes. + //Code includes a lot of checks so as to replot only when necessary + if (xChange) { + xCord[searchedDataKey] = selectedRow[xLabel]; + // [searchedDataKey][0] contains the x value + if (xType == 'numeric') { + series[0][searchedDataKey][0] = selectedRow[xLabel]; + } else if (xType == 'time') { + series[0][searchedDataKey][0] = + getTimeStamp(selectedRow[xLabel], $('#types_0').val()); + } else { + // todo: text values + } + currentChart.series[0].data = series[0]; + // todo: axis changing + currentChart.replot(); + + } + if (yChange) { + yCord[searchedDataKey] = selectedRow[yLabel]; + // [searchedDataKey][1] contains the y value + if (yType == 'numeric') { + series[0][searchedDataKey][1] = selectedRow[yLabel]; + } else if (yType == 'time') { + series[0][searchedDataKey][1] = + getTimeStamp(selectedRow[yLabel], $('#types_1').val()); + } else { + // todo: text values + } + currentChart.series[0].data = series[0]; + // todo: axis changing + currentChart.replot(); + } + } //End plot update + + //Generate SQL query for update + if (!isEmpty(newValues)) { + var sql_query = 'UPDATE `' + PMA_commonParams.get('table') + '` SET '; + for (key in newValues) { + sql_query += '`' + key + '`=' ; + var value = newValues[key]; + + // null + if (value == null) { + sql_query += 'NULL, '; + + // empty + } else if ($.trim(value) == '') { + sql_query += "'', "; + + // other + } else { + // type explicitly identified + if (sqlTypes[key] != null) { + if (sqlTypes[key] == 'bit') { + sql_query += "b'" + value + "', "; + } + // type not explicitly identified + } else { + if (!isNumeric(value)) { + sql_query += "'" + value + "', "; + } else { + sql_query += value + ', '; + } + } + } + } + sql_query = sql_query.substring(0, sql_query.length - 2); + sql_query += ' WHERE ' + PMA_urldecode(searchedData[searchedDataKey]['where_clause']); + + //Post SQL query to sql.php + $.post('sql.php', { + 'token' : PMA_commonParams.get('token'), + 'db' : PMA_commonParams.get('db'), + 'ajax_request' : true, + 'sql_query' : sql_query, + 'inline_edit' : false + }, function(data) { + if (data.success == true) { + $('#sqlqueryresults').html(data.sql_query); + $("#sqlqueryresults").trigger('appendAnchor'); + } else { + PMA_ajaxShowMessage(data.error, false); + } + }); //End $.post + }//End database update + $("#dataDisplay").dialog('close'); + }; + buttonOptions[PMA_messages['strCancel']] = function () { + $(this).dialog('close'); + }; + $("#dataDisplay").dialog({ + autoOpen: false, + title: PMA_messages['strDataPointContent'], + modal: true, + buttons: buttonOptions, + width: $('#dataDisplay').width() + 80, + open: function () { + $(this).find('input[type=checkbox]').css('margin', '0.5em'); + } + }); + /** + * Attach Ajax event handlers for input fields + * in the dialog. Used to submit the Ajax + * request when the ENTER key is pressed. + */ + $("#dataDisplay").find(':input').live('keydown', function (e) { + if (e.which === 13) { // 13 is the ENTER key + e.preventDefault(); + if (typeof buttonOptions[PMA_messages['strSave']] === 'function') { + buttonOptions[PMA_messages['strSave']].call(); + } + } + }); + + + /* + * Generate plot using jqplot + */ + + if (searchedData != null) { + $('#zoom_search_form') + .slideToggle() + .hide(); + $('#togglesearchformlink') + .text(PMA_messages['strShowSearchCriteria']); + $('#togglesearchformdiv').show(); + var selectedRow; + var colorCodes = ['#FF0000', '#00FFFF', '#0000FF', '#0000A0', '#FF0080', '#800080', '#FFFF00', '#00FF00', '#FF00FF']; + var series = []; + var xCord = []; + var yCord = []; + var tempX, tempY; + var it = 0; + var xMax; // xAxis extreme max + var xMin; // xAxis extreme min + var yMax; // yAxis extreme max + var yMin; // yAxis extreme min + + var options = { + series: [ + // for a scatter plot + { showLine: false } + ], + grid: { + drawBorder: false, + shadow: false, + background: 'rgba(0,0,0,0)' + }, + axes: { + xaxis: { + label: $('#tableid_0').val(), + labelRenderer: $.jqplot.CanvasAxisLabelRenderer + }, + yaxis: { + label: $('#tableid_1').val(), + labelRenderer: $.jqplot.CanvasAxisLabelRenderer + } + }, + highlighter: { + show: true, + tooltipAxes: 'y', + yvalues: 2, + // hide the first y value + formatString: '<span class="hide">%s</span>%s' + }, + cursor: { + show: true, + zoom: true, + showTooltip: false + } + }; + + // If data label is not set, do not show tooltips + if (dataLabel == '') { + options.highlighter.show = false; + } + + // Classify types as either numeric,time,text + xType = getType(xType); + yType = getType(yType); + + // could have multiple series but we'll have just one + series[0] = []; + + if (xType == 'time') { + var originalXType = $('#types_0').val(); + var format; + if (originalXType == 'date') { + format = '%Y-%m-%d'; + } + // todo: does not seem to work + //else if (originalXType == 'time') { + // format = '%H:%M'; + //} else { + // format = '%Y-%m-%d %H:%M'; + //} + $.extend(options.axes.xaxis, { + renderer:$.jqplot.DateAxisRenderer, + tickOptions: { + formatString: format + } + }); + } + if (yType == 'time') { + var originalYType = $('#types_1').val(); + var format; + if (originalYType == 'date') { + format = '%Y-%m-%d'; + } + $.extend(options.axes.yaxis, { + renderer:$.jqplot.DateAxisRenderer, + tickOptions: { + formatString: format + } + }); + } + + $.each(searchedData, function(key, value) { + if (xType == 'numeric') { + var xVal = parseFloat(value[xLabel]); + } + if (xType == 'time') { + var xVal = getTimeStamp(value[xLabel], originalXType); + } + if (yType == 'numeric') { + var yVal = parseFloat(value[yLabel]); + } + if (yType == 'time') { + var yVal = getTimeStamp(value[yLabel], originalYType); + } + series[0].push([ + xVal, + yVal, + // extra Y values + value[dataLabel], // for highlighter + // (may set an undefined value) + value['where_clause'], // for click on point + key // key from searchedData + ]); + }); + + // under IE 8, the initial display is mangled; after a manual + // resizing, it's ok + // under IE 9, everything is fine + currentChart = $.jqplot('querychart', series, options); + currentChart.resetZoom(); + + $('button.button-reset').click(function(event) { + event.preventDefault(); + currentChart.resetZoom(); + }); + + $('div#resizer').resizable(); + $('div#resizer').bind('resizestop', function(event, ui) { + // make room so that the handle will still appear + $('div#querychart').height($('div#resizer').height() * 0.96); + $('div#querychart').width($('div#resizer').width() * 0.96); + currentChart.replot( {resetAxes: true}) + }); + + $('div#querychart').bind('jqplotDataClick', + function(event, seriesIndex, pointIndex, data) { + searchedDataKey = data[4]; // key from searchedData (global) + var field_id = 0; + var post_params = { + 'ajax_request' : true, + 'get_data_row' : true, + 'db' : PMA_commonParams.get('db'), + 'table' : PMA_commonParams.get('table'), + 'where_clause' : data[3], + 'token' : PMA_commonParams.get('token') + }; + + $.post('tbl_zoom_select.php', post_params, function(data) { + // Row is contained in data.row_info, + // now fill the displayResultForm with row values + var key; + for (key in data.row_info) { + $field = $('#edit_fieldID_' + field_id); + $field_null = $('#edit_fields_null_id_' + field_id); + if (data.row_info[key] == null) { + $field_null.prop('checked', true); + $field.val(''); + } else { + $field_null.prop('checked', false); + if ($field.attr('multiple')) { // when the column is of type SET + $field.val(data.row_info[key].split(',')); + } else { + $field.val(data.row_info[key]); + } + } + field_id++; + } + selectedRow = {}; + selectedRow = data.row_info; + }); + + $("#dataDisplay").dialog("open"); + } + ); + } +}); |
