From e8c641afdfbce6cae7460e9d72c71cb6eed8f16f Mon Sep 17 00:00:00 2001 From: Kris Borchers Date: Wed, 22 Aug 2012 08:10:36 -0500 Subject: [PATCH] Better encapsulation of pipes and a first pass at auto-generated docs --- Rakefile | 33 + dist/aerogear.js | 355 +- dist/aerogear.min.js | 4 +- docs/AeroGear/Pipeline/adapters/index.html | 159 + .../Pipeline/adapters/read/index.html | 164 + .../Pipeline/adapters/remove/index.html | 151 + .../Pipeline/adapters/rest/index.html | 179 + .../adapters/rest/prototype/read/index.html | 175 + .../adapters/rest/prototype/remove/index.html | 168 + .../adapters/rest/prototype/save/index.html | 174 + .../Pipeline/adapters/rest/read/index.html | 166 + .../Pipeline/adapters/rest/remove/index.html | 153 + .../Pipeline/adapters/rest/save/index.html | 159 + .../Pipeline/adapters/save/index.html | 157 + docs/AeroGear/Pipeline/add/index.html | 147 + docs/AeroGear/Pipeline/index.html | 195 + .../Pipeline/prototype/adapters/index.html | 120 + .../Pipeline/prototype/add/index.html | 160 + .../Pipeline/prototype/remove/index.html | 158 + docs/AeroGear/Pipeline/remove/index.html | 146 + docs/AeroGear/index.html | 154 + docs/add/index.html | 139 + docs/images/pdoc/alias.png | Bin 0 -> 733 bytes docs/images/pdoc/class.png | Bin 0 -> 591 bytes docs/images/pdoc/class_deprecated.png | Bin 0 -> 702 bytes docs/images/pdoc/class_method.png | Bin 0 -> 857 bytes docs/images/pdoc/class_property.png | Bin 0 -> 599 bytes docs/images/pdoc/constant.png | Bin 0 -> 981 bytes docs/images/pdoc/constructor.png | Bin 0 -> 584 bytes docs/images/pdoc/deprecated.png | Bin 0 -> 4695 bytes docs/images/pdoc/description.png | Bin 0 -> 786 bytes docs/images/pdoc/information.png | Bin 0 -> 778 bytes docs/images/pdoc/instance_method.png | Bin 0 -> 853 bytes docs/images/pdoc/instance_property.png | Bin 0 -> 613 bytes docs/images/pdoc/method.png | Bin 0 -> 1680 bytes docs/images/pdoc/method_deprecated.png | Bin 0 -> 1342 bytes docs/images/pdoc/mixin.png | Bin 0 -> 1130 bytes docs/images/pdoc/namespace.png | Bin 0 -> 755 bytes docs/images/pdoc/property.png | Bin 0 -> 599 bytes docs/images/pdoc/related_to.png | Bin 0 -> 343 bytes docs/images/pdoc/search-background.png | Bin 0 -> 295 bytes docs/images/pdoc/section-background.png | Bin 0 -> 296 bytes docs/images/pdoc/section.png | Bin 0 -> 946 bytes .../pdoc/selected-section-background.png | Bin 0 -> 169 bytes docs/images/pdoc/subclass.png | Bin 0 -> 759 bytes docs/images/pdoc/superclass.png | Bin 0 -> 759 bytes docs/images/pdoc/utility.png | Bin 0 -> 630 bytes docs/index.html | 86 + docs/javascripts/pdoc/application.js | 478 ++ docs/javascripts/pdoc/item_index.js | 12 + docs/javascripts/pdoc/prototype.js | 4874 +++++++++++++++++ docs/javascripts/pdoc/tabs.js | 506 ++ docs/pipeline/add/index.html | 125 + docs/pipeline/index.html | 136 + docs/pipeline/remove/index.html | 125 + docs/remove/index.html | 138 + docs/stylesheets/pdoc/api.css | 677 +++ docs/stylesheets/pdoc/pygments.css | 62 + src/aerogear.core.js | 7 +- src/pipeline/adapters/rest.js | 144 +- src/pipeline/aerogear.pipeline.js | 200 +- 61 files changed, 10859 insertions(+), 127 deletions(-) create mode 100644 Rakefile create mode 100644 docs/AeroGear/Pipeline/adapters/index.html create mode 100644 docs/AeroGear/Pipeline/adapters/read/index.html create mode 100644 docs/AeroGear/Pipeline/adapters/remove/index.html create mode 100644 docs/AeroGear/Pipeline/adapters/rest/index.html create mode 100644 docs/AeroGear/Pipeline/adapters/rest/prototype/read/index.html create mode 100644 docs/AeroGear/Pipeline/adapters/rest/prototype/remove/index.html create mode 100644 docs/AeroGear/Pipeline/adapters/rest/prototype/save/index.html create mode 100644 docs/AeroGear/Pipeline/adapters/rest/read/index.html create mode 100644 docs/AeroGear/Pipeline/adapters/rest/remove/index.html create mode 100644 docs/AeroGear/Pipeline/adapters/rest/save/index.html create mode 100644 docs/AeroGear/Pipeline/adapters/save/index.html create mode 100644 docs/AeroGear/Pipeline/add/index.html create mode 100644 docs/AeroGear/Pipeline/index.html create mode 100644 docs/AeroGear/Pipeline/prototype/adapters/index.html create mode 100644 docs/AeroGear/Pipeline/prototype/add/index.html create mode 100644 docs/AeroGear/Pipeline/prototype/remove/index.html create mode 100644 docs/AeroGear/Pipeline/remove/index.html create mode 100644 docs/AeroGear/index.html create mode 100644 docs/add/index.html create mode 100755 docs/images/pdoc/alias.png create mode 100755 docs/images/pdoc/class.png create mode 100755 docs/images/pdoc/class_deprecated.png create mode 100644 docs/images/pdoc/class_method.png create mode 100755 docs/images/pdoc/class_property.png create mode 100644 docs/images/pdoc/constant.png create mode 100755 docs/images/pdoc/constructor.png create mode 100644 docs/images/pdoc/deprecated.png create mode 100755 docs/images/pdoc/description.png create mode 100755 docs/images/pdoc/information.png create mode 100644 docs/images/pdoc/instance_method.png create mode 100755 docs/images/pdoc/instance_property.png create mode 100644 docs/images/pdoc/method.png create mode 100644 docs/images/pdoc/method_deprecated.png create mode 100644 docs/images/pdoc/mixin.png create mode 100644 docs/images/pdoc/namespace.png create mode 100755 docs/images/pdoc/property.png create mode 100755 docs/images/pdoc/related_to.png create mode 100644 docs/images/pdoc/search-background.png create mode 100644 docs/images/pdoc/section-background.png create mode 100644 docs/images/pdoc/section.png create mode 100644 docs/images/pdoc/selected-section-background.png create mode 100755 docs/images/pdoc/subclass.png create mode 100755 docs/images/pdoc/superclass.png create mode 100755 docs/images/pdoc/utility.png create mode 100644 docs/index.html create mode 100644 docs/javascripts/pdoc/application.js create mode 100644 docs/javascripts/pdoc/item_index.js create mode 100644 docs/javascripts/pdoc/prototype.js create mode 100644 docs/javascripts/pdoc/tabs.js create mode 100644 docs/pipeline/add/index.html create mode 100644 docs/pipeline/index.html create mode 100644 docs/pipeline/remove/index.html create mode 100644 docs/remove/index.html create mode 100644 docs/stylesheets/pdoc/api.css create mode 100644 docs/stylesheets/pdoc/pygments.css diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..0814b5b --- /dev/null +++ b/Rakefile @@ -0,0 +1,33 @@ +require 'rake' +require 'pdoc' + +desc "Builds the documentation" +task :build_doc do + hash = `git show-ref --hash HEAD`.chomp[0..6] + + PDoc.run({ + :source_files => Dir[File.join("src", "**", "*.js")], + :destination => "docs", + :syntax_highlighter => :none, + :markdown_parser => :bluecloth, + :src_code_href => proc { |obj| + "https://github.com/aerogear/aerogear-js/blob/#{hash}/#{obj.file}#L#{obj.line_number}" + }, + :pretty_urls => false, + :bust_cache => true, + :name => 'AeroGear JavaScript Library', + :short_name => 'AeroGear.js', + :home_url => 'http://aerogear.org', + :doc_url => 'http://aerogear.org/docs', + :version => "1.0.0.Alpha", + :copyright_notice => 'Add license info here' + }) +end + +desc "Empties output directory" +task :remove_doc do + rm_rf Dir.glob(File.join(docs, "*")) +end + +desc "Empties the output directory and builds the documentation." +task :doc => [:remove_doc, :build_doc] \ No newline at end of file diff --git a/dist/aerogear.js b/dist/aerogear.js index 9757127..98415a8 100644 --- a/dist/aerogear.js +++ b/dist/aerogear.js @@ -1,4 +1,4 @@ -/*! AeroGear JavaScript Library - v1.0.0.Alpha - 2012-08-20 +/*! AeroGear JavaScript Library - v1.0.0.Alpha - 2012-08-22 * https://github.com/aerogear/aerogear-js * JBoss, Home of Professional Open Source * Copyright 2012, Red Hat, Inc., and individual contributors @@ -15,94 +15,201 @@ */ (function( window, undefined ) { + /** + * aerogear + * + * The aerogear namespace provides a way to encapsulate the library's properties and methods away from the global namespace + **/ var aerogear = window.aerogear = {}; })( this ); -// AeroGear Pipeline (function( aerogear, undefined ) { function isArray( obj ) { return ({}).toString.call( obj ) === "[object Array]"; } + /** + * aerogear.pipeline + * + * The aerogear.pipeline namespace provides a persistence API that is protocol agnostic and does not depend on any certain data model. Through the use of adapters, both provided and custom, user supplied, this library provides common methods like read, save and delete that will just work. + * + * `aerogear.pipeline( pipe ) -> Object` + * - **pipe** (Mixed) When passing a pipeConfiguration object to `add`, the following items can be provided: + * - **name** - String (Required), the name that the pipe will later be referenced by + * - **type** - String (Optional, default - "rest"), the type of pipe as determined by the adapter used + * - **recordId** - String (Optional, default - "id"), the identifier used to denote the unique id for each record in the data associated with this pipe + * - **settings** - Object (Optional, default - {}), the settings to be passed to the adapter + * - Adapters may have a number of varying configuration settings. + * + * Returns an object representing a collection of server connections (pipes) and their corresponding data models. This object provides a standard way to communicate with the server no matter the data format or transport expected. + * + * ##### Example + * + * // Create a single pipe using the default adapter + * var pipeline = aerogear.pipeline( "tasks" ); + * + * // Create multiple pipes using the default adapter + * var myPipeline = aerogear.pipeline( [ "tasks", "projects" ] ); + **/ aerogear.pipeline = function( pipe ) { - var pipeline = {}; - - pipeline.add = function( pipe ) { - var i, - current, - // initialize pipes if not already - pipes = pipeline.pipes = pipeline.pipes || {}; - - if ( typeof pipe === "string" ) { - // pipe is a string so use - pipes[ pipe ] = aerogear.pipeline.adapters.rest( pipe, "id" ); - } else if ( isArray( pipe ) ) { - // pipe is an array so loop through each item in the array - for ( i = 0; i < pipe.length; i++ ) { - current = pipe[ i ]; - - if ( typeof current === "string" ) { - pipes[ current ] = aerogear.pipeline.adapters.rest( current ); + var pipeline = { + pipes: {}, + /** + * aerogear.pipeline#add( pipe ) -> Object + * - pipe (Mixed): This can be a variety of types specifying how to create the pipe as illustrated below + * + * When passing a pipeConfiguration object to `add`, the following items can be provided: + * - **name** - String (Required), the name that the pipe will later be referenced by + * - **type** - String (Optional, default - "rest"), the type of pipe as determined by the adapter used + * - **recordId** - String (Optional, default - "id"), the identifier used to denote the unique id for each record in the data associated with this pipe + * - **settings** - Object (Optional, default - {}), the settings to be passed to the adapter + * - Adapters may have a number of varying configuration settings. + * + * Returns the full pipeline object with the new pipe(s) added + * + * // Add a single pipe using the default configuration (rest). + * aerogear.pipeline.add( String pipeName ); + * + * // Add multiple pipes all using the default configuration (rest). + * aerogear.pipeline.add( Array[String] pipeNames ); + * + * // Add one or more pipe configuration objects. + * aerogear.pipeline.add( Object/Array[Object] pipeConfigurations ) + * + * The default pipe type is `rest`. You may also use one of the other provided types or create your own. + * + * ##### Example + * + * var pipeline = aerogear.pipeline(); + * + * // Add a single pipe using the default adapter + * pipeline = pipeline.add( "tasks" ); + * + * // Add multiple pipes using the default adapter + * pipeline = pipeline.add( [ "tags", "projects" ] ); + * + **/ + add: function( pipe ) { + var i, + current; + + if ( !pipe ) { + return this; + } else if ( typeof pipe === "string" ) { + // pipe is a string so use + this.pipes[ pipe ] = aerogear.pipeline.adapters.rest( pipe, "id" ); + } else if ( isArray( pipe ) ) { + // pipe is an array so loop through each item in the array + for ( i = 0; i < pipe.length; i++ ) { + current = pipe[ i ]; + + if ( typeof current === "string" ) { + this.pipes[ current ] = aerogear.pipeline.adapters.rest( current ); + } else { + this.pipes[ current.name ] = aerogear.pipeline.adapters[ current.type || "rest" ]( current.name, current.recordId || "id", current.settings || {} ); + } + } } else { - pipes[ current.name ] = aerogear.pipeline.adapters[ current.type || "rest" ]( current.name, current.recordId || "id", current.settings || {} ); + // pipe is an object so use that signature + this.pipes[ pipe.name ] = aerogear.pipeline.adapters[ pipe.type || "rest" ]( pipe.name, pipe.recordId || "id", pipe.settings || {} ); } - } - } else if ( pipe ) { - // pipe is an object so use that signature - pipes[ pipe.name ] = aerogear.pipeline.adapters[ pipe.type || "rest" ]( pipe.name, pipe.recordId || "id", pipe.settings || {} ); - } else { - // pipe is undefined so throw error - throw "aerogear.pipeline: pipe is undefined"; - } - - pipeline.pipes = pipes; - - return pipeline; - }; - pipeline.remove = function( pipe ) { - var i, - current, - // initialize pipes if not already - pipes = pipeline.pipes = pipeline.pipes || {}; - - if ( typeof pipe === "string" ) { - // pipe is a string so use - delete pipes[ pipe ]; - } else if ( isArray( pipe ) ) { - // pipe is an array so loop through each item in the array - for ( i = 0; i < pipe.length; i++ ) { - current = pipe[ i ]; - - if ( typeof current === "string" ) { - delete pipes[ current ]; - } else { - delete pipes[ current.name ]; + return this; + }, + /** + * aerogear.pipeline#remove( pipe ) -> Object + * - pipe (Mixed): This can be a variety of types specifying the pipe to remove as illustrated below + * + * When passing a pipeConfiguration object to `remove`, the following items can be provided: + * - **name** - String (Required), the name that the pipe will later be referenced by + * - **type** - String (Optional, default - "rest"), the type of pipe as determined by the adapter used + * - **recordId** - String (Optional, default - "id"), the identifier used to denote the unique id for each record in the data associated with this pipe + * - **settings** - Object (Optional, default - {}), the settings to be passed to the adapter + * - Adapters may have a number of varying configuration settings. + * + * Returns the full pipeline object with the specified pipe(s) removed + * + * // Remove a single pipe using the default configuration (rest). + * aerogear.pipeline.remove( String pipeName ); + * + * // Remove multiple pipes all using the default configuration (rest). + * aerogear.pipeline.remove( Array[String] pipeNames ); + * + * // Remove one or more pipe configuration objects. + * aerogear.pipeline.remove( Object/Array[Object] pipeConfigurations ) + * + * ##### Example + * + * var pipeline = aerogear.pipeline( [ "projects", "tags", "tasks" ] ); + * + * // Remove a single pipe + * pipeline.remove( "tasks" ); + * + * // Remove multiple pipes using the default adapter + * pipeline.remove( [ "tags", "projects" ] ); + * + **/ + remove: function( pipe ) { + var i, + current; + + if ( typeof pipe === "string" ) { + // pipe is a string so use + delete this.pipes[ pipe ]; + } else if ( isArray( pipe ) ) { + // pipe is an array so loop through each item in the array + for ( i = 0; i < pipe.length; i++ ) { + current = pipe[ i ]; + + if ( typeof current === "string" ) { + delete this.pipes[ current ]; + } else { + delete this.pipes[ current.name ]; + } + } + } else if ( pipe ) { + // pipe is an object so use that signature + delete this.pipes[ pipe.name ]; } - } - } else if ( pipe ) { - // pipe is an object so use that signature - delete pipes[ pipe.name ]; - } - - pipeline.pipes = pipes; - return pipeline; - }; + return this; + } + }; return pipeline.add( pipe ); }; + /** + * aerogear.pipeline.adapters + * + * The adapters object is provided so that adapters can be added to the aerogear.pipeline namespace dynamically and still be accessible to the add method + **/ aerogear.pipeline.adapters = {}; })( aerogear ); -// Rest Adapter (default) (function( aerogear, $, undefined ) { // TODO: Share this across entire lib function isArray( obj ) { return ({}).toString.call( obj ) === "[object Array]"; } + /** + * aerogear.pipeline.adapters.rest + * + * The REST adapter is the default type used when creating a new pipe. It uses jQuery.ajax to communicate with the server. By default, the RESTful endpoint used by this pipe is the app's current context, followed by the pipe name. For example, if the app is running on http://mysite.com/myApp, then a pipe named `tasks` would use http://mysite.com/myApp/tasks as its REST endpoint. + * + * `aerogear.pipeline.adapters.rest( pipeName [, recordId, ajaxSettings] ) -> Object` + * - pipeName (String): the name that will be used to reference this pipe + * - recordId (String): the record identifier specified when the pipe was created + * - ajaxSettings (Object) - an object used to pass additional parameters to jQuery.ajax + * + * When creating a new pipe using the REST adapter, the `settings` parameter to be supplied to pipeline is a hash of key/value pairs that will be supplied to the jQuery.ajax method. + * + * Once created, the new pipe will contain: + * - **recordId** - the record identifier specified when the pipe was created + * - **type** - the type specified when the pipe was created + * - **data** - an object used to store a client side copy of the data associated with this pipe + **/ aerogear.pipeline.adapters.rest = function( pipeName, recordId, ajaxSettings ) { ajaxSettings = $.extend({ // use the pipeName as the default rest endpoint @@ -116,6 +223,51 @@ recordId: recordId, type: "rest", data: null, + /** + * aerogear.pipeline.adapters.rest#read( [options] ) -> Object + * - options (Object): Additional options + * + * The options sent to read can include either of the following: + * - **data** - Object, a hash of key/value pairs that can be passed to the server as additional information for use when determining what data to return (Optional) + * - **ajax** - Object, a hash of key/value pairs that will be added to or override any AJAX settings set during creation of the pipe using this adapter (Optional) + * + * Returns a jqXHR which implements the Promise interface. See the [Defered Object](http://api.jquery.com/category/deferred-object/) reference on the jQuery site for more information. + * + * var myPipe = aerogear.pipeline( "tasks" ).pipes[ 0 ]; + * + * // Get a set of key/value pairs of all data on the server associated with this pipe + * var allData = myPipe.read(); + * + * // A data object can be passed to filter the data and in the case of REST, + * // this object is converted to query string parameters which the server can use. + * // The values would be determined by what the server is expecting + * var filteredData = myPipe.read({ + * data: { + * limit: 10, + * date: "2012-08-01" + * ... + * } + * }); + * + * Example returned data in allData: + * + * [ + * { + * id: 12345 + * title: "Do Something", + * date: "2012-08-01", + * ... + * }, + * { + * id: 67890 + * title: "Do Something Else", + * date: "2012-08-02", + * ... + * }, + * ... + * ] + * + **/ read: function( options ) { var that = this, data; @@ -145,6 +297,47 @@ return $.ajax( $.extend( {}, ajaxSettings, { type: "GET" }, options.ajax, { success: success } ) ); }, + /** + * aerogear.pipeline.adapters.rest#save( data[, options] ) -> Object + * - data (Object): For new data, this will be an object representing the data to be saved to the server. For updating data, a hash of key/value pairs one of which must be the `recordId` you set during creation of the pipe representing the identifier the server will use to update this record and then any other number of pairs representing the data. The data object is then stringified and passed to the server to be processed. + * - options (Object): An object with a single key/value pair, the key being `ajax`, that will be added to or override any ajax settings set during creation of the pipe using this adapter + * + * Save data asynchronously to the server. If this is a new object (doesn't have a record identifier provided by the server), the data is created on the server (POST) and then that record is sent back to the client including the new server-assigned id, otherwise, the data on the server is updated (PUT). + * + * Returns a jqXHR which implements the Promise interface. See the [Defered Object](http://api.jquery.com/category/deferred-object/) reference on the jQuery site for more information. + * + * var myPipe = aerogear.pipeline( "tasks" ).pipes[ 0 ]; + * + * // Store a new task + * myPipe.save({ + * title: "Created Task", + * date: "2012-07-13", + * ... + * }); + * + * // Pass a success and error callback, in this case using the REST pipe and jQuery.ajax so the functions take the same parameters. + * myPipe.save({ + * title: "Another Created Task", + * date: "2012-07-13", + * ... + * }, + * { + * ajax: { + * success: function( data, textStatus, jqXHR ) { + * console.log( "Success" ); + * }, + * error: function( jqXHR, textStatus, errorThrown ) { + * console.log( "Error" ); + * } + * } + * }); + * + * // Update an existing piece of data + * var toUpdate = myPipe.data[ 0 ]; + * toUpdate.data.title = "Updated Task"; + * myPipe.save( toUpdate ); + * + **/ save: function( data, options ) { var that = this, type, @@ -197,6 +390,44 @@ )); }, + /** + * aerogear.pipeline.adapters.rest#remove( toRemove [, options] ) -> Object + * - toRemove (Mixed): A variety of objects can be passed to remove to specify the item to remove as illustrated below + * - options (Object): An object with a single key/value pair, the key being `ajax`, that will be added to or override any ajax settings set during creation of the pipe using this adapter + * + * Remove data asynchronously from the server. Passing nothing will inform the server to remove all data at this pipe's rest endpoint. + * + * Returns a jqXHR which implements the Promise interface. See the [Defered Object](http://api.jquery.com/category/deferred-object/) reference on the jQuery site for more information. + * + * var myPipe = aerogear.pipeline( "tasks" ).pipes[ 0 ]; + * + * // Store a new task + * myPipe.save({ + * title: "Created Task" + * }); + * + * // Store another new task + * myPipe.save({ + * title: "Another Created Task" + * }); + * + * // Store one more new task + * myPipe.save({ + * title: "And Another Created Task" + * }); + * + * // Remove a particular item from the server by its id + * var toRemove = myPipe.data[ 0 ]; + * myPipe.remove( toRemove.id ); + * + * // Remove an item from the server using the data object + * toRemove = myPipe.data[ 0 ]; + * myPipe.remove( toRemove ); + * + * // Delete all remaining data from the server associated with this pipe + * myPipe.delete(); + * + **/ remove: function( toRemove, options ) { var that = this, delId = 0, diff --git a/dist/aerogear.min.js b/dist/aerogear.min.js index 46c0e3e..b78c5f0 100644 --- a/dist/aerogear.min.js +++ b/dist/aerogear.min.js @@ -1,4 +1,4 @@ -/*! AeroGear JavaScript Library - v1.0.0.Alpha - 2012-08-20 +/*! AeroGear JavaScript Library - v1.0.0.Alpha - 2012-08-22 * https://github.com/aerogear/aerogear-js * JBoss, Home of Professional Open Source * Copyright 2012, Red Hat, Inc., and individual contributors @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -(function(a,b){var c=a.aerogear={}})(this),function(a,b){function c(a){return{}.toString.call(a)==="[object Array]"}a.pipeline=function(b){var d={};return d.add=function(b){var e,f,g=d.pipes=d.pipes||{};if(typeof b=="string")g[b]=a.pipeline.adapters.rest(b,"id");else if(c(b))for(e=0;e + + + + AeroGear.js v1.0.0.Alpha API documentation | aerogear.pipeline.adapters + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ namespace aerogear.pipeline.adapters +

+ + + + +
+
+

Description

+
+
+ +

The adapters object is provided so that adapters can be added to the aerogear.pipeline namespace dynamically and still be accessible to the add method

+
+
+ + + + +
+
+

Namespaces

+
+
+ +
    +
  • +

    aerogear.pipeline.adapters.rest

    + + +

    The REST adapter is the default type used when creating a new pipe. It uses jQuery.ajax to communicate with the server. By default, the RESTful endpoint used by this pipe is the app's current context, followed by the pipe name. For example, if the app is running on http://mysite.com/myApp, then a pipe named tasks would use http://mysite.com/myApp/tasks as its REST endpoint.

    + +
  • +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + diff --git a/docs/AeroGear/Pipeline/adapters/read/index.html b/docs/AeroGear/Pipeline/adapters/read/index.html new file mode 100644 index 0000000..0d2e57c --- /dev/null +++ b/docs/AeroGear/Pipeline/adapters/read/index.html @@ -0,0 +1,164 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | aerogear.pipeline.adapters.read + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ class method aerogear.pipeline.adapters.read +

+ + + + +
+
+
+
+
+ +
aerogear.pipeline.adapters.read( [options] ) → Object
+ + + +

Retrieve data asynchronously from the server.

+ +
    +
  • options - Object (Optional) +
      +
    • data - Object, a hash of key/value pairs that can be passed to the server as additional information for use when determining what data to return (Optional)
    • +
    • ajax - Object, a hash of key/value pairs that will be added to or override any AJAX settings set during creation of the pipe using this adapter (Optional)
    • +
  • +
+ +

Returns a jqXHR which implements the Promise interface. See the Defered Object reference on the jQuery site for more information.

+ +
var myPipe = aerogear.pipeline( "tasks" ).pipes[ 0 ];
+ // Get a set of key/value pairs of all data on the server associated with this pipe
+var allData = myPipe.read();
+ // A data object can be passed to filter the data and in the case of REST,
+// this object is converted to query string parameters which the server can use.
+// The values would be determined by what the server is expecting
+var filteredData = myPipe.read({
+    data: {
+        limit: 10,
+        date: "2012-08-01"
+        ...
+    }
+});
+ +

Example returned data in allData:

+ +
[
+    {
+        id: 12345
+        title: "Do Something",
+        date: "2012-08-01",
+        ...
+    },
+    {
+        id: 67890
+        title: "Do Something Else",
+        date: "2012-08-02",
+        ...
+    },
+    ...
+]
+ + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/docs/AeroGear/Pipeline/adapters/remove/index.html b/docs/AeroGear/Pipeline/adapters/remove/index.html new file mode 100644 index 0000000..44738ef --- /dev/null +++ b/docs/AeroGear/Pipeline/adapters/remove/index.html @@ -0,0 +1,151 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | aerogear.pipeline.adapters.remove + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ class method aerogear.pipeline.adapters.remove +

+ + + + +
+
+
+
+
+ +
aerogear.pipeline.adapters.remove( toRemove [, options] ) → Object
+ + + +

Remove data asynchronously from the server. Passing nothing will inform the server to remove all data at this pipe's rest endpoint.

+ +
    +
  • data - Object (Required), For new data, this will be an object representing the data to be saved to the server. For updating data, a hash of key/value pairs one of which must be the recordId you set during creation of the pipe representing the identifier the server will use to update this record and then any other number of pairs representing the data. The data object is then stringified and passed to the server to be processed.
  • +
  • options - Object (Optional), for the rest adapter, an object with a single key/value pair, the key being ajax, that will be added to or override any ajax settings set during creation of the pipe using this adapter
  • +
+ +

Returns a jqXHR which implements the Promise interface. See the Defered Object reference on the jQuery site for more information.

+ +
var myPipe = aerogear.pipeline( "tasks" ).pipes[ 0 ];
+ // Store a new task
+myPipe.save({
+    title: "Created Task"
+});
+ // Store another new task
+myPipe.save({
+    title: "Another Created Task"
+});
+ // Store one more new task
+myPipe.save({
+    title: "And Another Created Task"
+});
+ // Remove a particular item from the server by its id
+var toRemove = myPipe.data[ 0 ];
+myPipe.remove( toRemove.id );
+ // Remove an item from the server using the data object
+toRemove = myPipe.data[ 0 ];
+myPipe.remove( toRemove );
+ // Delete all remaining data from the server associated with this pipe
+myPipe.delete();
+ + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/docs/AeroGear/Pipeline/adapters/rest/index.html b/docs/AeroGear/Pipeline/adapters/rest/index.html new file mode 100644 index 0000000..7413b9a --- /dev/null +++ b/docs/AeroGear/Pipeline/adapters/rest/index.html @@ -0,0 +1,179 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | aerogear.pipeline.adapters.rest + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ namespace aerogear.pipeline.adapters.rest +

+ + + + +
+
+

Description

+
+
+ +

The REST adapter is the default type used when creating a new pipe. It uses jQuery.ajax to communicate with the server. By default, the RESTful endpoint used by this pipe is the app's current context, followed by the pipe name. For example, if the app is running on http://mysite.com/myApp, then a pipe named tasks would use http://mysite.com/myApp/tasks as its REST endpoint.

+ +

aerogear.pipeline.adapters.rest( pipeName [, recordId, ajaxSettings] ) -> Object

+ +
    +
  • pipeName (String): the name that will be used to reference this pipe
  • +
  • recordId (String): the record identifier specified when the pipe was created
  • +
  • ajaxSettings (Object) - an object used to pass additional parameters to jQuery.ajax
  • +
+ +

When creating a new pipe using the REST adapter, the settings parameter to be supplied to pipeline is a hash of key/value pairs that will be supplied to the jQuery.ajax method.

+ +

Once created, the new pipe will contain:

+ +
    +
  • recordId - the record identifier specified when the pipe was created
  • +
  • type - the type specified when the pipe was created
  • +
  • data - an object used to store a client side copy of the data associated with this pipe
  • +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+

Instance methods

+
+
+ + +
+
+ + + + + + + + + + + +
+ + + +
+ + diff --git a/docs/AeroGear/Pipeline/adapters/rest/prototype/read/index.html b/docs/AeroGear/Pipeline/adapters/rest/prototype/read/index.html new file mode 100644 index 0000000..099c203 --- /dev/null +++ b/docs/AeroGear/Pipeline/adapters/rest/prototype/read/index.html @@ -0,0 +1,175 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | aerogear.pipeline.adapters.rest#read + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ instance method aerogear.pipeline.adapters.rest#read +

+ + + + +
+
+
+
+
+ +
aerogear.pipeline.adapters.rest#read( [options] ) → Object
+ +
    + +
  • + options + + (Object) + + – Additional options +
  • + +
+ + + +

The options sent to read can include either of the following:

+ +
    +
  • data - Object, a hash of key/value pairs that can be passed to the server as additional information for use when determining what data to return (Optional)
  • +
  • ajax - Object, a hash of key/value pairs that will be added to or override any AJAX settings set during creation of the pipe using this adapter (Optional)
  • +
+ +

Returns a jqXHR which implements the Promise interface. See the Defered Object reference on the jQuery site for more information.

+ +
var myPipe = aerogear.pipeline( "tasks" ).pipes[ 0 ];
+ // Get a set of key/value pairs of all data on the server associated with this pipe
+var allData = myPipe.read();
+ // A data object can be passed to filter the data and in the case of REST,
+// this object is converted to query string parameters which the server can use.
+// The values would be determined by what the server is expecting
+var filteredData = myPipe.read({
+    data: {
+        limit: 10,
+        date: "2012-08-01"
+        ...
+    }
+});
+ +

Example returned data in allData:

+ +
[
+    {
+        id: 12345
+        title: "Do Something",
+        date: "2012-08-01",
+        ...
+    },
+    {
+        id: 67890
+        title: "Do Something Else",
+        date: "2012-08-02",
+        ...
+    },
+    ...
+]
+ + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/docs/AeroGear/Pipeline/adapters/rest/prototype/remove/index.html b/docs/AeroGear/Pipeline/adapters/rest/prototype/remove/index.html new file mode 100644 index 0000000..e70fcb7 --- /dev/null +++ b/docs/AeroGear/Pipeline/adapters/rest/prototype/remove/index.html @@ -0,0 +1,168 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | aerogear.pipeline.adapters.rest#remove + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ instance method aerogear.pipeline.adapters.rest#remove +

+ + + + +
+
+
+
+
+ +
aerogear.pipeline.adapters.rest#remove( toRemove [, options] ) → Object
+ +
    + +
  • + toRemove + + (Mixed) + + – A variety of objects can be passed to remove to specify the item to remove as illustrated below +
  • + +
  • + options + + (Object) + + – An object with a single key/value pair, the key being ajax, that will be added to or override any ajax settings set during creation of the pipe using this adapter +
  • + +
+ + + +

Remove data asynchronously from the server. Passing nothing will inform the server to remove all data at this pipe's rest endpoint.

+ +

Returns a jqXHR which implements the Promise interface. See the Defered Object reference on the jQuery site for more information.

+ +
var myPipe = aerogear.pipeline( "tasks" ).pipes[ 0 ];
+ // Store a new task
+myPipe.save({
+    title: "Created Task"
+});
+ // Store another new task
+myPipe.save({
+    title: "Another Created Task"
+});
+ // Store one more new task
+myPipe.save({
+    title: "And Another Created Task"
+});
+ // Remove a particular item from the server by its id
+var toRemove = myPipe.data[ 0 ];
+myPipe.remove( toRemove.id );
+ // Remove an item from the server using the data object
+toRemove = myPipe.data[ 0 ];
+myPipe.remove( toRemove );
+ // Delete all remaining data from the server associated with this pipe
+myPipe.delete();
+ + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/docs/AeroGear/Pipeline/adapters/rest/prototype/save/index.html b/docs/AeroGear/Pipeline/adapters/rest/prototype/save/index.html new file mode 100644 index 0000000..f378ac1 --- /dev/null +++ b/docs/AeroGear/Pipeline/adapters/rest/prototype/save/index.html @@ -0,0 +1,174 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | aerogear.pipeline.adapters.rest#save + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ instance method aerogear.pipeline.adapters.rest#save +

+ + + + +
+
+
+
+
+ +
aerogear.pipeline.adapters.rest#save( data[, options] ) → Object
+ +
    + +
  • + data + + (Object) + + – For new data, this will be an object representing the data to be saved to the server. For updating data, a hash of key/value pairs one of which must be the recordId you set during creation of the pipe representing the identifier the server will use to update this record and then any other number of pairs representing the data. The data object is then stringified and passed to the server to be processed. +
  • + +
  • + options + + (Object) + + – An object with a single key/value pair, the key being ajax, that will be added to or override any ajax settings set during creation of the pipe using this adapter +
  • + +
+ + + +

Save data asynchronously to the server. If this is a new object (doesn't have a record identifier provided by the server), the data is created on the server (POST) and then that record is sent back to the client including the new server-assigned id, otherwise, the data on the server is updated (PUT).

+ +

Returns a jqXHR which implements the Promise interface. See the Defered Object reference on the jQuery site for more information.

+ +
var myPipe = aerogear.pipeline( "tasks" ).pipes[ 0 ];
+ // Store a new task
+myPipe.save({
+    title: "Created Task",
+    date: "2012-07-13",
+    ...
+});
+ // Pass a success and error callback, in this case using the REST pipe and jQuery.ajax so the functions take the same parameters.
+myPipe.save({
+    title: "Another Created Task",
+    date: "2012-07-13",
+    ...
+},
+{
+    ajax: {
+        success: function( data, textStatus, jqXHR ) {
+            console.log( "Success" );
+        },
+        error: function( jqXHR, textStatus, errorThrown ) {
+            console.log( "Error" );
+        }
+    }
+});
+ // Update an existing piece of data
+var toUpdate = myPipe.data[ 0 ];
+toUpdate.data.title = "Updated Task";
+myPipe.save( toUpdate );
+ + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/docs/AeroGear/Pipeline/adapters/rest/read/index.html b/docs/AeroGear/Pipeline/adapters/rest/read/index.html new file mode 100644 index 0000000..76b33b0 --- /dev/null +++ b/docs/AeroGear/Pipeline/adapters/rest/read/index.html @@ -0,0 +1,166 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | aerogear.pipeline.adapters.rest.read + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ class method aerogear.pipeline.adapters.rest.read +

+ + + + +
+
+
+
+
+ +
aerogear.pipeline.adapters.rest.read( [options] ) → Object
+ + + +

Retrieve data asynchronously from the server.

+ +
    +
  • options - Object (Optional) +
      +
    • data - Object, a hash of key/value pairs that can be passed to the server as additional information for use when determining what data to return (Optional)
    • +
    • ajax - Object, a hash of key/value pairs that will be added to or override any AJAX settings set during creation of the pipe using this adapter (Optional)
    • +
  • +
+ +

Returns a jqXHR which implements the Promise interface. See the Defered Object reference on the jQuery site for more information.

+ +
var myPipe = aerogear.pipeline( "tasks" ).pipes[ 0 ];
+ // Get a set of key/value pairs of all data on the server associated with this pipe
+var allData = myPipe.read();
+ // A data object can be passed to filter the data and in the case of REST,
+// this object is converted to query string parameters which the server can use.
+// The values would be determined by what the server is expecting
+var filteredData = myPipe.read({
+    data: {
+        limit: 10,
+        date: "2012-08-01"
+        ...
+    }
+});
+ +

Example returned data in allData:

+ +
[
+    {
+        id: 12345
+        title: "Do Something",
+        date: "2012-08-01",
+        ...
+    },
+    {
+        id: 67890
+        title: "Do Something Else",
+        date: "2012-08-02",
+        ...
+    },
+    ...
+]
+ + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/docs/AeroGear/Pipeline/adapters/rest/remove/index.html b/docs/AeroGear/Pipeline/adapters/rest/remove/index.html new file mode 100644 index 0000000..16e3a85 --- /dev/null +++ b/docs/AeroGear/Pipeline/adapters/rest/remove/index.html @@ -0,0 +1,153 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | aerogear.pipeline.adapters.rest.remove + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ class method aerogear.pipeline.adapters.rest.remove +

+ + + + +
+
+
+
+
+ +
aerogear.pipeline.adapters.rest.remove( toRemove [, options] ) → Object
+ + + +

Remove data asynchronously from the server. Passing nothing will inform the server to remove all data at this pipe's rest endpoint.

+ +
    +
  • data - Object (Required), For new data, this will be an object representing the data to be saved to the server. For updating data, a hash of key/value pairs one of which must be the recordId you set during creation of the pipe representing the identifier the server will use to update this record and then any other number of pairs representing the data. The data object is then stringified and passed to the server to be processed.
  • +
  • options - Object (Optional), for the rest adapter, an object with a single key/value pair, the key being ajax, that will be added to or override any ajax settings set during creation of the pipe using this adapter
  • +
+ +

Returns a jqXHR which implements the Promise interface. See the Defered Object reference on the jQuery site for more information.

+ +
var myPipe = aerogear.pipeline( "tasks" ).pipes[ 0 ];
+ // Store a new task
+myPipe.save({
+    title: "Created Task"
+});
+ // Store another new task
+myPipe.save({
+    title: "Another Created Task"
+});
+ // Store one more new task
+myPipe.save({
+    title: "And Another Created Task"
+});
+ // Remove a particular item from the server by its id
+var toRemove = myPipe.data[ 0 ];
+myPipe.remove( toRemove.id );
+ // Remove an item from the server using the data object
+toRemove = myPipe.data[ 0 ];
+myPipe.remove( toRemove );
+ // Delete all remaining data from the server associated with this pipe
+myPipe.delete();
+ + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/docs/AeroGear/Pipeline/adapters/rest/save/index.html b/docs/AeroGear/Pipeline/adapters/rest/save/index.html new file mode 100644 index 0000000..27df20b --- /dev/null +++ b/docs/AeroGear/Pipeline/adapters/rest/save/index.html @@ -0,0 +1,159 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | aerogear.pipeline.adapters.rest.save + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ class method aerogear.pipeline.adapters.rest.save +

+ + + + +
+
+
+
+
+ +
aerogear.pipeline.adapters.rest.save( data [, options] ) → Object
+ + + +

Save data asynchronously to the server. If this is a new object (doesn't have a record identifier provided by the server), the data is created on the server (POST) and then that record is sent back to the client including the new server-assigned id, otherwise, the data on the server is updated (PUT).

+ +
    +
  • data - Object (Required), For new data, this will be an object representing the data to be saved to the server. For updating data, a hash of key/value pairs one of which must be the recordId you set during creation of the pipe representing the identifier the server will use to update this record and then any other number of pairs representing the data. The data object is then stringified and passed to the server to be processed.
  • +
  • options - Object (Optional), for the rest adapter, an object with a single key/value pair, the key being ajax, that will be added to or override any ajax settings set during creation of the pipe using this adapter
  • +
+ +

Returns a jqXHR which implements the Promise interface. See the Defered Object reference on the jQuery site for more information.

+ +
var myPipe = aerogear.pipeline( "tasks" ).pipes[ 0 ];
+ // Store a new task
+myPipe.save({
+    title: "Created Task",
+    date: "2012-07-13",
+    ...
+});
+ // Pass a success and error callback, in this case using the REST pipe and jQuery.ajax so the functions take the same parameters.
+myPipe.save({
+    title: "Another Created Task",
+    date: "2012-07-13",
+    ...
+},
+{
+    ajax: {
+        success: function( data, textStatus, jqXHR ) {
+            console.log( "Success" );
+        },
+        error: function( jqXHR, textStatus, errorThrown ) {
+            console.log( "Error" );
+        }
+    }
+});
+ // Update an existing piece of data
+var toUpdate = myPipe.data[ 0 ];
+toUpdate.data.title = "Updated Task";
+myPipe.save( toUpdate );
+ + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/docs/AeroGear/Pipeline/adapters/save/index.html b/docs/AeroGear/Pipeline/adapters/save/index.html new file mode 100644 index 0000000..f947a38 --- /dev/null +++ b/docs/AeroGear/Pipeline/adapters/save/index.html @@ -0,0 +1,157 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | aerogear.pipeline.adapters.save + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ class method aerogear.pipeline.adapters.save +

+ + + + +
+
+
+
+
+ +
aerogear.pipeline.adapters.save( data [, options] ) → Object
+ + + +

Save data asynchronously to the server. If this is a new object (doesn't have a record identifier provided by the server), the data is created on the server (POST) and then that record is sent back to the client including the new server-assigned id, otherwise, the data on the server is updated (PUT).

+ +
    +
  • data - Object (Required), For new data, this will be an object representing the data to be saved to the server. For updating data, a hash of key/value pairs one of which must be the recordId you set during creation of the pipe representing the identifier the server will use to update this record and then any other number of pairs representing the data. The data object is then stringified and passed to the server to be processed.
  • +
  • options - Object (Optional), for the rest adapter, an object with a single key/value pair, the key being ajax, that will be added to or override any ajax settings set during creation of the pipe using this adapter
  • +
+ +

Returns a jqXHR which implements the Promise interface. See the Defered Object reference on the jQuery site for more information.

+ +
var myPipe = aerogear.pipeline( "tasks" ).pipes[ 0 ];
+ // Store a new task
+myPipe.save({
+    title: "Created Task",
+    date: "2012-07-13",
+    ...
+});
+ // Pass a success and error callback, in this case using the REST pipe and jQuery.ajax so the functions take the same parameters.
+myPipe.save({
+    title: "Another Created Task",
+    date: "2012-07-13",
+    ...
+},
+{
+    ajax: {
+        success: function( data, textStatus, jqXHR ) {
+            console.log( "Success" );
+        },
+        error: function( jqXHR, textStatus, errorThrown ) {
+            console.log( "Error" );
+        }
+    }
+});
+ // Update an existing piece of data
+var toUpdate = myPipe.data[ 0 ];
+toUpdate.data.title = "Updated Task";
+myPipe.save( toUpdate );
+ + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/docs/AeroGear/Pipeline/add/index.html b/docs/AeroGear/Pipeline/add/index.html new file mode 100644 index 0000000..66ef5ab --- /dev/null +++ b/docs/AeroGear/Pipeline/add/index.html @@ -0,0 +1,147 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | aerogear.pipeline.add + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ class method aerogear.pipeline.add +

+ + + + +
+
+
+
+
+ +
aerogear.pipeline.add( pipe ) → Object
+ + + +
    +
  • pipe (Mixed) When passing a pipeConfiguration object to add, the following items can be provided: +
      +
    • name - String (Required), the name that the pipe will later be referenced by
    • +
    • type - String (Optional, default - "rest"), the type of pipe as determined by the adapter used
    • +
    • recordId - String (Optional, default - "id"), the identifier used to denote the unique id for each record in the data associated with this pipe
    • +
    • settings - Object (Optional, default - {}), the settings to be passed to the adapter
    • +
    • Adapters may have a number of varying configuration settings.
    • +
  • +
+ +

Returns the full pipeline object with the new pipe(s) added

+ +
// Add a single pipe using the default configuration (rest).
+aerogear.pipeline.add( String pipeName );
+ // Add multiple pipes all using the default configuration (rest).
+aerogear.pipeline.add( Array[String] pipeNames );
+ // Add one or more pipe configuration objects.
+aerogear.pipeline.add( Object/Array[Object] pipeConfigurations )
+ +

The default pipe type is rest. You may also use one of the other provided types or create your own.

+ +
Example
+ +
// Create a single pipe using the default adapter
+var pipeline = aerogear.pipeline.add( "tasks" );
+ // Create multiple pipes using the default adapter
+var myPipeline = aerogear.pipeline.add( [ "tasks", "projects" ] );
+ + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/docs/AeroGear/Pipeline/index.html b/docs/AeroGear/Pipeline/index.html new file mode 100644 index 0000000..62415b0 --- /dev/null +++ b/docs/AeroGear/Pipeline/index.html @@ -0,0 +1,195 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | aerogear.pipeline + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ namespace aerogear.pipeline +

+ + + + +
+
+

Description

+
+
+ +

The aerogear.pipeline namespace provides a persistence API that is protocol agnostic and does not depend on any certain data model. Through the use of adapters, both provided and custom, user supplied, this library provides common methods like read, save and delete that will just work.

+ +

aerogear.pipeline( pipe ) -> Object

+ +
    +
  • pipe (Mixed) When passing a pipeConfiguration object to add, the following items can be provided: +
      +
    • name - String (Required), the name that the pipe will later be referenced by
    • +
    • type - String (Optional, default - "rest"), the type of pipe as determined by the adapter used
    • +
    • recordId - String (Optional, default - "id"), the identifier used to denote the unique id for each record in the data associated with this pipe
    • +
    • settings - Object (Optional, default - {}), the settings to be passed to the adapter
    • +
    • Adapters may have a number of varying configuration settings.
    • +
  • +
+ +

Returns an object representing a collection of server connections (pipes) and their corresponding data models. This object provides a standard way to communicate with the server no matter the data format or transport expected.

+ +
Example
+ +
// Create a single pipe using the default adapter
+var pipeline = aerogear.pipeline( "tasks" );
+ // Create multiple pipes using the default adapter
+var myPipeline = aerogear.pipeline( [ "tasks", "projects" ] );
+
+
+ + + + +
+
+

Namespaces

+
+
+ +
    +
  • +

    aerogear.pipeline.adapters

    + + +

    The adapters object is provided so that adapters can be added to the aerogear.pipeline namespace dynamically and still be accessible to the add method

    + +
  • +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +
+
+

Instance methods

+
+
+ + +
+
+ + + + + + + + + + + +
+ + + +
+ + diff --git a/docs/AeroGear/Pipeline/prototype/adapters/index.html b/docs/AeroGear/Pipeline/prototype/adapters/index.html new file mode 100644 index 0000000..a375b1d --- /dev/null +++ b/docs/AeroGear/Pipeline/prototype/adapters/index.html @@ -0,0 +1,120 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | aerogear.pipeline#adapters + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ instance property aerogear.pipeline#adapters +

+ + + + +
+
+
+
+
+ +
aerogear.pipeline#adapters → Object
+ + + + + + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/docs/AeroGear/Pipeline/prototype/add/index.html b/docs/AeroGear/Pipeline/prototype/add/index.html new file mode 100644 index 0000000..775418b --- /dev/null +++ b/docs/AeroGear/Pipeline/prototype/add/index.html @@ -0,0 +1,160 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | aerogear.pipeline#add + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ instance method aerogear.pipeline#add +

+ + + + +
+
+
+
+
+ +
aerogear.pipeline#add( pipe ) → Object
+ +
    + +
  • + pipe + + (Mixed) + + – This can be a variety of types specifying how to create the pipe as illustrated below +
  • + +
+ + + +

When passing a pipeConfiguration object to add, the following items can be provided:

+ +
    +
  • name - String (Required), the name that the pipe will later be referenced by
  • +
  • type - String (Optional, default - "rest"), the type of pipe as determined by the adapter used
  • +
  • recordId - String (Optional, default - "id"), the identifier used to denote the unique id for each record in the data associated with this pipe
  • +
  • settings - Object (Optional, default - {}), the settings to be passed to the adapter +
      +
    • Adapters may have a number of varying configuration settings.
    • +
  • +
+ +

Returns the full pipeline object with the new pipe(s) added

+ +
// Add a single pipe using the default configuration (rest).
+aerogear.pipeline.add( String pipeName );
+ // Add multiple pipes all using the default configuration (rest).
+aerogear.pipeline.add( Array[String] pipeNames );
+ // Add one or more pipe configuration objects.
+aerogear.pipeline.add( Object/Array[Object] pipeConfigurations )
+ +

The default pipe type is rest. You may also use one of the other provided types or create your own.

+ +
Example
+ +
var pipeline = aerogear.pipeline();
+ // Add a single pipe using the default adapter
+pipeline = pipeline.add( "tasks" );
+ // Add multiple pipes using the default adapter
+pipeline = pipeline.add( [ "tags", "projects" ] );
+ + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/docs/AeroGear/Pipeline/prototype/remove/index.html b/docs/AeroGear/Pipeline/prototype/remove/index.html new file mode 100644 index 0000000..487ac1b --- /dev/null +++ b/docs/AeroGear/Pipeline/prototype/remove/index.html @@ -0,0 +1,158 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | aerogear.pipeline#remove + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ instance method aerogear.pipeline#remove +

+ + + + +
+
+
+
+
+ +
aerogear.pipeline#remove( pipe ) → Object
+ +
    + +
  • + pipe + + (Mixed) + + – This can be a variety of types specifying the pipe to remove as illustrated below +
  • + +
+ + + +

When passing a pipeConfiguration object to remove, the following items can be provided:

+ +
    +
  • name - String (Required), the name that the pipe will later be referenced by
  • +
  • type - String (Optional, default - "rest"), the type of pipe as determined by the adapter used
  • +
  • recordId - String (Optional, default - "id"), the identifier used to denote the unique id for each record in the data associated with this pipe
  • +
  • settings - Object (Optional, default - {}), the settings to be passed to the adapter +
      +
    • Adapters may have a number of varying configuration settings.
    • +
  • +
+ +

Returns the full pipeline object with the specified pipe(s) removed

+ +
// Remove a single pipe using the default configuration (rest).
+aerogear.pipeline.remove( String pipeName );
+ // Remove multiple pipes all using the default configuration (rest).
+aerogear.pipeline.remove( Array[String] pipeNames );
+ // Remove one or more pipe configuration objects.
+aerogear.pipeline.remove( Object/Array[Object] pipeConfigurations )
+ +
Example
+ +
var pipeline = aerogear.pipeline( [ "projects", "tags", "tasks" ] );
+ // Remove a single pipe
+pipeline.remove( "tasks" );
+ // Remove multiple pipes using the default adapter
+pipeline.remove( [ "tags", "projects" ] );
+ + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/docs/AeroGear/Pipeline/remove/index.html b/docs/AeroGear/Pipeline/remove/index.html new file mode 100644 index 0000000..7b120f3 --- /dev/null +++ b/docs/AeroGear/Pipeline/remove/index.html @@ -0,0 +1,146 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | aerogear.pipeline.remove + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ class method aerogear.pipeline.remove +

+ + + + +
+
+
+
+
+ +
aerogear.pipeline.remove( pipe ) → Object
+ + + +
    +
  • pipe (Mixed) When passing a pipeConfiguration object to remove, the following items can be provided: +
      +
    • name - String (Required), the name that the pipe will later be referenced by
    • +
    • type - String (Optional, default - "rest"), the type of pipe as determined by the adapter used
    • +
    • recordId - String (Optional, default - "id"), the identifier used to denote the unique id for each record in the data associated with this pipe
    • +
    • settings - Object (Optional, default - {}), the settings to be passed to the adapter
    • +
    • Adapters may have a number of varying configuration settings.
    • +
  • +
+ +

Returns the full pipeline object with the specified pipe(s) removed

+ +
// Remove a single pipe using the default configuration (rest).
+aerogear.pipeline.remove( String pipeName );
+ // Remove multiple pipes all using the default configuration (rest).
+aerogear.pipeline.remove( Array[String] pipeNames );
+ // Remove one or more pipe configuration objects.
+aerogear.pipeline.remove( Object/Array[Object] pipeConfigurations )
+ +
Example
+ +
var pipeline = aerogear.pipeline.add( [ "projects", "tags", "tasks" ] );
+ // Remove a single pipe
+pipeline.remove( "tasks" );
+ // Remove multiple pipes using the default adapter
+pipeline().add( [ "tags", "projects" ] );
+ + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/docs/AeroGear/index.html b/docs/AeroGear/index.html new file mode 100644 index 0000000..905c42c --- /dev/null +++ b/docs/AeroGear/index.html @@ -0,0 +1,154 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | aerogear + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ namespace aerogear +

+ + + + +
+
+

Description

+
+
+ +

The aerogear namespace provides a way to encapsulate the library's properties and methods away from the global namespace

+
+
+ + + + +
+
+

Namespaces

+
+
+ +
    +
  • +

    aerogear.pipeline

    + + +

    The aerogear.pipeline namespace provides a persistence API that is protocol agnostic and does not depend on any certain data model. Through the use of adapters, both provided and custom, user supplied, this library provides common methods like read, save and delete that will just work.

    + +
  • +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + diff --git a/docs/add/index.html b/docs/add/index.html new file mode 100644 index 0000000..9680aed --- /dev/null +++ b/docs/add/index.html @@ -0,0 +1,139 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | add + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ class method add +

+ + + + +
+
+
+
+
+ +
.add( pipe ) → Object
+ + + +
    +
  • pipe (Mixed) When passing a pipeConfiguration object to add, the following items can be provided: +-- name - String (Required), the name that the pipe will later be referenced by +-- type - String (Optional, default - "rest"), the type of pipe as determined by the adapter used +-- recordId - String (Optional, default - "id"), the identifier used to denote the unique id for each record in the data associated with this pipe +-- settings - Object (Optional, default - {}), the settings to be passed to the adapter +-- Adapters may have a number of varying configuration settings.
  • +
+ +

Returns the full pipeline object with the new pipe(s) added

+ +
// Add a single pipe using the default configuration (rest).
+aerogear.pipeline.add( String pipeName );
+ // Add multiple pipes all using the default configuration (rest).
+aerogear.pipeline.add( Array[String] pipeNames );
+ // Add one or more pipe configuration objects.
+aerogear.pipeline.add( Object/Array[Object] pipeConfigurations )
+ +

The default pipe type is rest. You may also use one of the other provided types or create your own.

+ +
Example
+ +
// Create a single pipe using the default adapter
+var pipeline = aerogear.pipeline.add( "tasks" );
+ // Create multiple pipes using the default adapter
+var myPipeline = aerogear.pipeline.add( [ "tasks", "projects" ] );
+ + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/docs/images/pdoc/alias.png b/docs/images/pdoc/alias.png new file mode 100755 index 0000000000000000000000000000000000000000..6332fefea4be19eeadf211b0b202b272e8564898 GIT binary patch literal 733 zcmV<30wVp1P)9VHk(~TedF+gQSL8D5xnVSSWAVY>J9b+m>@{iq7_KE}go~11+5s4;8hc+i0Xa zI1j@EX5!S+Me6HNqKzU5YQwL;-W5$p%ZMKMeR<%zp69-~?<4?8|C8S?bklXr4v&Ov zb&06v2|-x?qB`90yn>Qi%Sh2^G4n)$ZdyvTPf9}1)_buUT7>`e2G&2VU@~Bb(o+Mz zi4)>IxlSY${Dj4k={-9RzU^W5g9|2V5RZ2ZulL9s2xQbZ@r6eP9Ra5u(s|C0Nj#&4>wTSkb?%#=9?@ z^oxDy-O@tyN{L@by(WWvQ3%CyEu8x{+#Jb4-h&K9Owi)2pgg+heWDyked|3R$$kL@A z#sp1v-r+=G4B8D6DqsDH0@7OztA7aT9qc1Py{()w`m``?Y0&gi2=ROcc-9+nU^I6< zT=e_Y=vSnG@?3Ue{BW5ONFttcE!R-R_W4O01|0-|K-YNXLo2`4Qv z`r1LxR6#yf3FB%T95gJnaKKivA~Z}S9A(ZxEDK}O3T04USJ P00000NkvXXu0mjf^IS-S literal 0 HcmV?d00001 diff --git a/docs/images/pdoc/class.png b/docs/images/pdoc/class.png new file mode 100755 index 0000000000000000000000000000000000000000..6187b15aec001b7080b51a5f944f07591f26cc15 GIT binary patch literal 591 zcmV-V0eEcNHZMNv|IbJ-M`( zKwWL~opzjJe^WpCmV9E;(0&ut2;4va_(#>M8)>9$R5viQnf(Nkh~VM$y>J(jqb$cj z+nL1Nm|mV)Gm|9MnHf*7Ja4OEAQz__^LRKOLEwqpiGV^^A*T=#&inGm-62Xs;dnSp zKj&H9T*boh2i)W+(n27l!C)>fq|L%VB1i ziC4p;NwV_}ZjW7$LRW#(_bKF#hp=!IqNO26Z*w2+LEwx{PVnZ&Sn}T;mtzb$;qA*nT@@+ zV5uQ@iXDTPoTbV#FRr~z04|PPh`wXTNoCm9*tG&?e3+fYl>K6+&3|Cc$KOpL`ER+_ dcRl5U#9zn6ZO}GF*+R*y?^}D#G^uK? zs!!WfH;*g^h|Dj(RDzL==f|my)dr%PT1vq@z?H_1k(}fvLJyh9O&}sYO929R=UVq= zH&av%{Tsc$cuOEAbbsynEuyNb5fS0`v3teyW}v3jt**t~Fn1ga)C_k>tW6ZEEAGat z{;q|GsH&(N=Em^&5TnzhhzsUUB#2UD!tNkSx9K7PQF=4I#FiIQwt53UCNrojYD(0z z>{MZM)o~6?bkcO^sEY_9%9G}2K?I;Zbu;MLdn-tfr%_Wv3kg*a6B;F?s`4CazKnWI2NNtV@9URch+SU-u9ZR}f7$*x!f z1;vwCb^zSa@z+%EzsM=%0Z41VipU4IWnn;Nmn9^9tb(GlR?HkUV zI(lc-(%oJ48&}Lfx@GOz*%S9p>)ttM(%$die(lsOvGpLZlXVdCCxm%HjVzJK>AKY8lUpTBQjed^~@aO29;DV;l3FFIb6 zzs%pY@b-=8=}8rnJ9o_N-xK0h`t|GgD;FOB|Nnp9?3IrnzHBO6bNAMZxS)=W>vmna zcz@Z#t(#Y$0m`1gu67If$1U-4_oM_M@5r%MujRcN@jX5OptS&wnfG*+OKp$!-`2J-HRqD zbSnuj?whUV;mycx-@c)mGh0-8xq3kNO3~eH%2z0d2J33qV-ek=W|G}pR;))>xBTrG_y3l&Wddk zwVd)3tb15RW=I~k-0@>(r9`k+BU93zO+l;T-mFop4Dv~JRVa5!`=zF0RAjl+;>Jv8 yoA5d3Wlt-=Kk;@U&sSXmiK_JJ&JhfZYz(UQj3X&*16m=d#Wzp$PzTO7m_2 literal 0 HcmV?d00001 diff --git a/docs/images/pdoc/class_property.png b/docs/images/pdoc/class_property.png new file mode 100755 index 0000000000000000000000000000000000000000..ebaf0e8743fc33cf152cb7694b865e8d8adbfa90 GIT binary patch literal 599 zcmV-d0;v6oP)GWQRM3$+Tx>2G~D3qqtDdzLJ$P+M| z%_5OV?1V_vbzR8Cf4JqIVHo)K^%pXcv3TotyGW%{h{xkw5Q#dkEiV=ekof!9z?%~d z=g(E7!z)Oq(;*j#L?RmyiObN>-n-ERY$OQs{fC-WE z`TR3JBO8xbMN0KSbiO^m!^f-pEr_bBgH6ZV(+;jrKl87%5H3QY5S&iu(~XVt z`Q%tE#s-6d3Aucs;QCb?w-;^voEneC7ITEh5sgOWa5&8962;=`54d^#1;35CDRwv< z7ITTajw2Wh%6`9}(Iu`wF^PG8L%bJ2;q&>deAA2$Oi`4b;)4JRkH=$mxm=9IcDvoO l^OXPhyYjA9E`GA_{V$1@FaBct0}KEF002ovPDHLkV1kGx8r%Q? literal 0 HcmV?d00001 diff --git a/docs/images/pdoc/constant.png b/docs/images/pdoc/constant.png new file mode 100644 index 0000000000000000000000000000000000000000..c4295ec0df9bb1921471c5f6625f77eb2084cea3 GIT binary patch literal 981 zcmV;`11kK9P)X+uL$Nkc;*P;zf(X>4Tx0C=30k-tkDVHn3h?`a7X&C=7>f^dVF3{iqv zA{4=7u%bg61d|NHzBK!xR*f>o*3ti&0;^aFtHL~^=Rn&-~=^Bn>3ZOoR^ zKWe3pe-FLg{jxN+dAf6Tes>)JePN|q17QMYLvtE1>zZEx=4&Mth!S8rE4B;51v246 zxd>t#NH#R@0?E4O10cEXG!%$7kPX~s0OA*rcfH5~BMm4=h6;@Lz(}Q9v-D_c4yJ~o z=cMb^BG~&3Pe;36`WXx?!eOrKbzUI=F?bR!=OzFUeFb=Q8ONPbNW6pV?KuAXF^;c4 zLC*!W17|H<|92N*Ou~Iy@20i>0qDNBv)&(oEPQwgi;rP$3wC}$Y9F3_g;GB(Ok(7J z{!e`?0G=0ZzgZ7$<+)aQreGCYek+Wm?RfV*`k|q`HwvKGk{e;Ov7)SLDSag{~ z6ul2f=m2>zm_P#JUodfUV{_B6b|Qu_bZY9*fs}!z1I2~MXh}#qt8q{k8Jl2YQW)w~ z6&ur}3B&;J-FxoG=Yqz@J_bGOIp4YWp6_0w|AZ4p42Q$##+WhyQq|*PvABDiE)r&- zs$~EN01iZ?9Hxtf5dg>-^Fvh$K$tAtfSIAH#{dYxb(rq23Ak+3cZFLn3l2BBZMCLT9-RCnqPi+wIy-n$Qf0h?sd} zfWHm;{r(O!?*TX}l}g?(Qbb5ZZak>fYC8b-035YiEibmN)ZU73k>f<#ys_qjxbpGj_f*`mavW#-^4lei$D>!)+Gjx! zTql!BpD5&*8jZ#y08d1uxIU)$0A6-Fowpmmg}f4o)2%U3C;eEDoiEh?94d(rV57VIF#8VqzW$HrDC|#U`x@QDbgi zVl)t9GGz&YY#D?gc%>hISA+_EBpnXt#pnC`p6@xw0$8TCbULjhlgVx(kuc)%xbgqq zR5+DNDFRN0!y)7Gm}oT0i39}h4h928qY?Rho^UvPGJ#kuW|-Amtrn`Pmd&+bFo@sp z$LI4IQw7BG?|#2ewOS<<3VjL$0=lMY^m;wqZujv5kx1l%Sl;V&Iy4#$ip3&@LV2!7vhhN=PCz%^9v24`qb(+m4W?!q-&~=?ssf5GfnAmJKV;3bvpDm0(NhahZ=&^sqo6Odj6>)Dq_3p~4~ zvb`d3Mydwjt&Df^hVmLtI2x=U&h9(JVYX-!y~z3zi;1>=LY;o(bL$(Yf$lf)dMf0-u^0HrpTG Wk@)HE*94aU0000WSdG9-O@2T(1x#!K?=SBwF)D)}~1Ox=sI*&9>0L=RLl92%4`-B0j1O#-P zI+|)`p@awd7a{c8bRYF94^8E66Oj<9V0&P43GiIkkeIK3bgs_27jFcvOuz2A=`7tv z!d>Z?!G-7Vv5|w7zI)6EZ8l7U=MPv@%UB+#7M2^2>5u9E-g;_jX=$$X_hjqC0P5NI z@m1&85}Q{tkNJ}O$&?uQ_m3SIcJdNVa+r*_{(FJHv7y>pWAj*+Z!q3DXPo{bX)qN$ z%Ad!$615J|3a6SqR^{5dT7^dY8+_z4=sO~tp7~-F5uvo$9g_az_lZ$pp!7wg3gR9+ z?tz?iR_xX0=O6i7$$kB*3@`(Mc4h|kjds{NaZs7Uqri?Komk44E(KYENtwL8vMTyY zUgc!NeJSmGsKDUSG%qoP5+Nk5^BjJk60sVtLMcCxONGv4j~&@?#(isMAT#p!7oQCA z2hILCmY5O`39+=C{KXE+&UB*1Wl-n^(+Cm%et8+L3l{U!kwNagD0!tZ#J{}BRgK@! zl-B}TBIbtv^6(eoSJyzZJmq(uO^P8y9FH&{%lQof2)hxe6Tccr+(4wOn=vJfRCYX? zzUpg9;S1nkIw3NWPWptg&{^1DkLp>KI=?Me>65T|t#^+XK9@pk_cnstD$iC5<|nB0 z97QZ<*YEoQeG806^ATn*s%F*%6A4;+#*I@*XQL1=LZ?u@CVY+n@F+_Ne|+|Ugc66(}@0I|wT z#J6;EZ_NIn8>eRS;DaBC>0g|_Czb-Cn`m)Mkc$0oab!x*Y8`RIZ?JI05uF6F$f)iz zU0H@6UII(puV+3s?Vm!bi$dM(ZqXiG@e*)Z%5rFq_Hx2*_ z;2XpMM8h|z0I-K|FaV$e-(UxT6TSgh*8W@>X0y6T7}-lRCZpl*`QAtxYTq+V3S;Li zs&BzqSQ5!d%4#rB=(zTX{KSM{5#*3nGZXEru-)x#BX<=V&ih3@@_iu7;y4T??we=z zXj_Z1-Y*3kYx|1!c7@C15!H;dQzBMYP9BP95*9_N3^M_bcSjnY3vlC|;|_qKzmzUq@ReaNPTUwHdquf9Aq)`o%$Uo-MN?u2{{fF^Q&XKBrY7J$AC4=hUyiv1p zaHw>Ys5-8$t1HXMpgZ+%+pyMObS~cflI1mWdOl>@fjYPM7?Uv$vu1hXPo#f)1<}59 z#l=~jRdckiLjj@^a6G=+5~7;!3PL|;eRQ)x=Xm4;u)m4E#u#v_8fa;0tsjN!pf$Z5 zJzvyJu-dmr=Ds#4ECE+>4-+hnWQ!MPZ1c&$L6(>L)ldwBS<$gm{r$k>c)|7aU4G9>VE`^SOp$#r_V zXF&9G`;V6ryi{trif=pm777>5N*|?vd`wTD$va;8C~N1`iYp>r{}dJ-lz950(kkgU zQ-qhVYf6^nwJG|?&mW6Qy3$<8qVEY_JTrkugD)*3Xq9JIWLt~A4*lE&wxkq~05 zKYqD*EvxY^f5!)+1*5;vZT?LiPN^tu?TPEhM#N~#&Z7FQnfk`Yr=D6nYw3|?3E+Ajdh<3V!1A4E7d4is*cs=rHaQtlF=0jOzfjY zqA8;b>wy9Ody3LhM~i>)&k4y;}3xu_|1rH#;jYu}djvRUvWRM=`k^etQ5JXjF1* zQr+>nUr>m#=(>cQhgfgkTEHjOhiZ&$)C2zsuiAkbT+x`&&gKp+7z34`pma`79~j5` zpRS3#2)Ft+>)h_E;+pFEisE8<897OCZtbhx$fsY%$73yg(q<$+2(n&=?m%R${v><# zl#A#|?$tT5dT1A=7s;9!*&SM-kbOV5b6@8cr=H5jHj}Wu_7D{+?BfddG+1N@7<&8)+XibCwM84SnG-j zrwZ$dO#`!R!96uQyIC`+oSX{b=Wd7UJBo^^c=jtMnNna{yj*yT?gXt#Uz1;-a|iJ*8*kp(NxE@}m~t{-QI0<4q? zYAp0!{r&u)q}1YFv9Hji5w?z+Uh+6!a=`PGXRRxd@5pBx*S@GqXijBLd0%chYj>KM zVzFasY|n*?A2{|~fTDVYAF&jqKiLsB&a@jDC!YAz3*tZyyl33}e4nwoweg|vS_}9| z_uGcFANb(EC)E!XpI$a2lH63aJ9EB$WfdV2r^hkN6sWoy7SfO7uOOR3xK=gobPlkY zycc*r^5#z$;uG#@=V^Jp1FV@8)_OpZX)C=b1<5m;n_n4f+A^~?MsCYO&0r?_i?a>F z+9}$qDk#!mvR%@*lL7DMq)G2MDP5^&w-eWK^ak~{loosBCY#gx-X3iImAPihfC{5- z^H%%nCkh6Ap*-YbI@8ll9=AhL*l375^2^%g_V$-*1&=RJaPM`&h_$J|2B;CK1$vgx zEJt(A-HGcu0vk$$Ag`P_DAvwdLH(d^M@Bm^pPSH4_8g0lNi83Sv$$rn3 zm6rJM_cznCllwLzGMQ|IKB|o`Dj;HM>V0R{^qHC749uFZ@WP>gz8$vL>gT>0D=2%+HaTZC9ChD1qHgLmcmnIAV&E4Lx0rc9fY&Z{iafckI{ znDbi8!*tGI-#Fw7?yJ!fG&f_DgbH=tyqgGZ#b$gIoUB535CX62pL+YfoNDh}7j(2p z)WhrE4jK%pfS=Ob63$V1rY}oMnIuf?idJXrsh=k6LMA8Q_Z}ao`aVFIvxRkLd`9cg z>ok{B1)AY`z|S>IELKqDUilSmg^RTnOAGBYc-s|9XsZG1MlhE4)9ofchOkk~$*{*a z?bno_!ax>M%3O1^)DW2y$$S0pLr-V~2=(#&43x~2*vfP7XPrY2$ zbT(!O<5a0Wh_L*5jK3t)=i;29o=y9N`H4euV&)yAc8SdBlQI?4hW7Bo!Wf3P(BIPX z?9K{#bV{C96Q8W{moM@dqCF@eKHGX|J#(x)Cwb%0XT|*uJxQs$*fn3D5e3{4q*j21 zlN0q#)>YwO(|{gb82b-c(EC0-sp4XbKx$ZBxtBdOCPlzsZzPRG zMG<9r1ATm5r6Vb7iVMHGG9L*#QYXDmX0C!PC{>j-sy`+deL(#V?|x6>?)|5`uXZ`J zvp`ud0UHJ$#qDPO<<*JRsjaagB7X0uj7-u$r^nZ{4VS^|Mo!Q<-4a&Cw`3i9el7QW z`7=bE5PXgtn)<9e9V^bK0uRv(WWo-po!6pYN1Db}P_(?YcWjFDL;5yS%xT!GG)2ea zP6QXey}7^K5Q`ys@GQRu_#I8GP9g}7xIjUKi@f4fQqr=uHr1JM$*YTONbIndz-~IU z$pf-l(O4q;ZV)*|sX!f=4kt5tGc{D8ne&7=A*r$EjDs1~vE0a%+OgK^)ZKlQnW++` zQrO{PlJUbXH(|yuC_?;;QUEojnpuqg-1w}ENyl~M8w%WBjFMrg)n!_}snYzyj-s=+ zglApFc+qPQg-@2Yq~%bihxjA}2Q689?Yii9`q@e6{=FXTn7)lz!RE!zj`VI9TrGDo zB`vMEDagch%BurWoyn;hMuL9M9k$5Xfu3+CpJ7?W$T9!-_WdOrt5B$CyhuWZk*$iY z7$MZ26cxRTqGSyhWvy_q?|MK<@{8rz{ZYpu0Gad(-}!cvLnf zpI`Q?rngRs})jb-+Q|Q z*K&EKdXpFn=Tq9W+06Y*i(P7RJTI`v(eb?MWmhL}l>ex*k#8d6ia&#OIg5yA{yy}7 zUu>K}v*qG$tEPdMVy|3eai_4nS$^T2@8`r5&tmmD%f+d>qGIZ#(Emd}uL=DTH~+Up z=i5n!e{wa(_#F>6xuGAVkZ4Sm>iuwij-NWNZ@q7sUi@4Mu@a1m(@^iSMKKSHn)dKJ zx`E5Pb9YfbAJ;dh{XYn)T|>5;2b>HK6QUwhw2_{rCEoi<5wFR_2z|tfto0^<<3)G6 z^Q(~OYf~qQ1~^9RB*r)h>7Jm6A7*`c<&h@@3lO3>W+<90a*~I_Kr??&3#ZML@IV~K z;&^HCARKXB{GQ65HU$e%{JnGb=y-Kt!YFnv1tOYnuh3x;aibsoO+4Y`R$Om?<>ebc z0wjgLyDe;t6u@xsKFyzMq96oJD+kM>rEB~69n0-!6;!8&|EYcC?`E@M1U9?FM@Qx? z{^dj|yz~8wH?X-g8?e-Xr2~8{Nlb*e)B+jp)PC=>cLM_%b@7(mY`QS%eEi}gCtgeY12yr$)cKpkY5?C8y z^hn%qA_UeFUyt=jvr=crV&Zk1hDB2V`i;8vTiXh$aX=xA6RmgT9s;bbs|Nzl>vDVf z9XGIzb-}gz%XHW}iv@*f`)(isg$6$R`O(|x58BixHu&nUdqUDm+;rTK7_*ME7O^zXum NKu60!vq9Z4?tjro(xLzW literal 0 HcmV?d00001 diff --git a/docs/images/pdoc/description.png b/docs/images/pdoc/description.png new file mode 100755 index 0000000000000000000000000000000000000000..5c870176d4dea68aab9e51166cc3d7a582f326d6 GIT binary patch literal 786 zcmV+t1MU2YP)$XgYMs^AIOw1Qr{*Wn)N-{9ma}x2(<~`9Go1=*>YR!KZvrBS zCd!u}@M0og%Ev@_;Z?Kk>Wwv=%h_57zmt2<_1msz_niYE=YRNPpd%02TK9oK1z z>ooPno}v^sikz_|1XHFx_L%~;ljh7i(jiay5F0x*+(9aXXFCl?AdQj5XlQ65%sEv+ ztfe?|YcjPN*@yYtE~ImQh{l|#A6Z8iu>pf43Rj52CzU_dMQm|S2xR62YjQOn+z8WH zaK=!}ggOZi{4pB7SQ=xC0n|vXP_Bkx_a)FeNd}w8U97BNbSWxa^QW-li9BZ#M1!_xE*?wzt^GcoeoL*JGLSe_+l-JT2#2tz!z&^ z_s5anq&^nBklIMwRvcoP3%qs%%Ea?1c{_*V*Xj&~uLu-2Dp1fUN4<0zMo$EH>*U83 zm_9;Vt%-bE{_J_!If!1y=c+`QVZ>0_BPy z+%^pgnv`f8H)Z%0&Tp8&u*MCIC4igNW5MeWM_DHpDNi)Zxz|9XboOnitwFq$ETN=X zj-tkCJnz**Y4k#6_Ty^B=hWo~L!47r`HoP=x&3T1)JLr2t2+#fHBVme|mWaqy4$_pJm?y9KM{-*hp?1+Ey3e-CEDooTa!B;e(Q>TSF?bj>5At13y1p zriN3w3x~5SfZj{@J4M{kp{?=M_Lh2bV+5LH)Q)5W!-ePA$RgE1@5f1cyHki0Y}JyVEYZF(LD$xXlt$7A5CgE@ zpV-&l%vf;=5kZ2-2gi@Y6J&=cuwt>!vJ^#(&n|LcZyUzi6Duj$$hJ1s*HD-#;k-w@ zpdrwAuoDG_N2bvb07G$Zk*?Hc)JLtW4yqOnic_$zO7NZ#l>Fm){;fE?b$IbOaX2fe z0la4g0Dfw2xk7Wi7NapVD8YMPCZu?A1QCK*67dgsvRKBLFtrM>?$%&_lD1882mzdO zWPdw5KWw6IT`m1b_8=lS5jt8D3=RDa=&jWzR-)S@56WMslZ~mKu1)-wpXB>rNBQ>N zU#K`#1B&v|_AQK;7I~B}OdGiUT9LX>f0xm6<;LeP!=vFjPsUQF*wCJ*dO)4YBypgdiuF!=i@6Zyi7F|q#K zz?tlSZULa@t1D?$e;f@b36&N!V2mjOHw|*E^hw!@87<2>-L;obMM);vo{ZJI5KzY`sxKcIW&aun)POdpPWBbWvcb;B3bMwHG-F<5h&Rn{u|HI*x5b=SFDhoTEzpTB*0;KHU0ca9#pylvUGsr%2b zU%hqV{pZ&s^PMNIDcgU1+m_>t!cyHr)7-jOub7zNn_zwP^7d&*w3rf;m@vTI#*p68;Kvx^(j z!gHKTCqx6a$IC6g28^NVk|4ieAa{TO!{oy&UICr)+0(@_q~cc63MOXdR5yQ)ZpMzK zO2NH{e}q>yeC+;b8?3}I4xMCr0w0YTAaCk7sL9M0fC`YOQhPh zW>>H_Zx&LP?)LKv6|LvdUap%g(;Pf4z(#ueEY`R>FVdQ&MBb@0OS$#WdHyG literal 0 HcmV?d00001 diff --git a/docs/images/pdoc/instance_property.png b/docs/images/pdoc/instance_property.png new file mode 100755 index 0000000000000000000000000000000000000000..83ec984bd73364134da0f98d27a800c5d3264180 GIT binary patch literal 613 zcmV-r0-F7aP)^5T)AZ%#@G{_P{NCN^P z(J0zvSn~SSm(Ur);-M~8^*;61*VRI`T1BN&LAhK;sZ>I-SVW;vfUfJv=ko^ugnc0x zhJodBxe>iyk3%w<%wC8holUJ4(iv>tL{`DQt zPOsyUbO_Cmc&*iHkqbm3ku`|GcC^OhF>jj9W*GkH;^g!iUVpib_h*=@udp4h(P+e*zL_~ZmJjh(y^BxULwq>9zXoYE8sq{#pN~U0C6!8vY)5N2 z9P*}mw}7X$O^qTtJef1ACWvJT9^wt-)Zh0r~j#0bT`f;-zv6 z^Tmw22!%rMcs!TaUX<-8s;X-B`+Xbo+_uWuFa z1yIPc?DTrQ7KvRhmt*TG|L=EYQ=LqFX;=Lp`4}jx6BE-@00000NkvXXu0mjf=s_29 literal 0 HcmV?d00001 diff --git a/docs/images/pdoc/method.png b/docs/images/pdoc/method.png new file mode 100644 index 0000000000000000000000000000000000000000..35efa75949d7c79947a61c38a1b54381b122fd90 GIT binary patch literal 1680 zcmV;B254Tx0C=2@luu|JRUF4ZZ#tnMi6E{u29$?~7$ga6 zE4oFf$tLMGZrCo@o7t@`MI<2JZ1pH!szp3h5f74sf+u?@5@@aM zAqe8Bicl={B4s_y{+SSq{$Swqe!t)Q{{9R+82G9j1lp3Y=|{%NW#!81nml-&0fra^ zD7#@WT`VpDl!HLC&+h+>0Jt$x4g#HDI(hxKm!A6K{jc-4hrcU{{rP)r$gHfcfsjC| z7W0chYCYx?K(8Mcq~ zefJy$AP((>)gy-i5QAA5_@&*xHwp(oga;qA+kb!3Za?@G4(!7B+HIOvXGcQ(2ywsh z8Md7+J&fa-0LZ|l6R`XUc)_ApgBoC+4 zFU#p5&`Qqx?&P>EYb}jet4E9*NVUh2xp^_cYs4+O`WSRF2^kNx%y0@!#|m(Qv#j^>vEur3vqAO53Hh5c=#xM zBn~;UOb}pbP{qSTz*qcC`cZ2W7crkG$!jyw3=!Qk;GO%xJ`C9(y!#(N4feJlNE z`eyo4`f~b@izCgkeq_tM?zuY`?ovcydb*uxr>9uorNJ~BO%26nZ>BKOX`;KTe{rO* z_hx@f|+S{jZ3|>9IXIG7V zQ>ormd(Zv6P(tg#RvX9xbcE*0iUg+H@;p1@zg(0Mj#^)?@&;RS@ z62C0~q;kqv#&e~U%gUl@R6VT{&)k26|EK)}0fiL}$-4Xb00009a7bBm000XU000XU z0RWnu7ytkR21!IgR5*=wQ%^`6c@+L86Z2=15F5pioy60mvJ_#nmqf&a7mtEhp_gqv z^x$nT?cyR7TF{g6n7EgE^d7=SMOU;0Z1qqVD<~)%ocM1blbPTAes3mwF;dy?JG}?* zfB zfdCqf27Er>T&Yy50l?zoA{vdxpQ@^&*=%Bbe7sjx)!zB}`5%0ob1=q0L~vafU6yz} z{_tML7=#e;JP$+!$8peVwP0Bmq++r7so87}Boc{8KA-QkEDOP45cPWfqYz^59`JT# zWTe13hwHjnU0pRy(`*YNnhzqD%jI{OOy)Ha!SDA&mSvosoq>ojI5-F*f@N7SO%v5> z_5Iq~+M5R-luD&J&iU`zY!;5=AQ%iH91bHEiy@InKv9&3b5vEu!NI}U(9n=~bab@s zzrWE-r_+c;BB8&guL6#Dx5aCms=J@Ucq>}>hw z=H{1nyWLDCleus>{CR3>DoI2r7K^&$I62SrK3kSGAcXj%Ua!A=l!fKx<(IN7KZ{1A zPgALs?s=YU7zQpcFX1?jTqqQDzu*7Vb=_xO@PE?yZB0*4zqq=(dd?VwBuO8(x3|9= a=YIhT7o_5%kakJ{0000P)X+uL$Nkc;*P;zf(X>4Tx0C=30k-tkDVHn3h?`a7X&C=7>f^dVF3{iqv zA{4=7u%bg61d|NHzBK!xR*f>o*3ti&0;^aFtHL~^=Rn&-~=^Bn>3ZOoR^ zKWe3pe-FLg{jxN+dAf6Tes>)JePN|q17QMYLvtE1>zZEx=4&Mth!S8rE4B;51v246 zxd>t#NH#R@0?E4O10cEXG!%$7kPX~s0OA*rcfH5~BMm4=h6;@Lz(}Q9v-D_c4yJ~o z=cMb^BG~&3Pe;36`WXx?!eOrKbzUI=F?bR!=OzFUeFb=Q8ONPbNW6pV?KuAXF^;c4 zLC*!W17|H<|92N*Ou~Iy@20i>0qDNBv)&(oEPQwgi;rP$3wC}$Y9F3_g;GB(Ok(7J z{!e`?0G=0ZzgZ7$<+)aQreGCYek+Wm?RfV*`k|q`HwvKGk{e;Ov7)SLDSaZ>YB5OSsFBQR_Ea)Xl5f82vEO=6odWrNP z!AcL7l?p9QOIE{fLeuVQR(DO8T2d0bF`b$G=J#hjxD8v-@A7>gy!YUHyidaaR6d`7 zgHrlB=Ny#MugAy7zxpqn^zc$DmCjj~wVzBTk8`XYg$37jcO^+GXR}#@QpyP-AcR0wRUVJW4a>61gpl2II=yhh^F1KH z9}0!ujYJ|60Ik_7P)Y#+!^6WMgme)?P^na~v9STiapY4TY;JB|(RDr5YPG;QN2Afe z-rgSkem_jpgrX>*l)|=c6pO`=Q>oN@03hXZxf_(yKF)bC5{c-RW#Q=P2wPiQ*Br;0 z?da%0{0aW~GXwThHQ!4JXuVilTf6VNuEiKTR2XB4SS%*h>vc354fy?jRI63UvOGIC zH}~W1mC0@nbUr$88KhD`wSEC(V`I8u82bGDd{kzPfe-@57&zzfJP(?tp{J+k!Ex@) z8S~|V?#KxI$3^()0bJLGWm&Lo8&W!*zEP{y`oiIGFp)^;j^jX8Rcvo>U+YuuESSNY zpPjulrGb`VJ2CuTSizT9o%??`EsHUB*fuef$y|v>qbbH16h(n7OAzx0ZhJ4l&KX4ZAxl&_?gR`Oft8Y(Febg2pgb2eh5C{ZNsZ{X8)fM}%oki%6Cm`%?c*4QxYcUA-Pjq&c z@$~3robSGUv7N-FrKPNCngi?W>m%iI`S2C9^y$#EFTN0tQi#@X06bh@`W4aPUO-p~ z_K(6Yt!Pu1dcQyQOfxex=Q!v4lTYSv#U~e|KKT!L>auQ__tsG2aYJBCdeIsMF0Q*07*qoM6N<$f~TEz AS^xk5 literal 0 HcmV?d00001 diff --git a/docs/images/pdoc/mixin.png b/docs/images/pdoc/mixin.png new file mode 100644 index 0000000000000000000000000000000000000000..11a7f8fed4227c4902f8acb9d3a1f4089d37ccbe GIT binary patch literal 1130 zcmV-w1eN=VP)X+uL$Nkc;*P;zf(X>4Tx0C=30k-tkDVHn3h?`a7X&C=7>f^dVF3{iqv zA{4=7u%bg61d|NHzBK!xR*f>o*3ti&0;^aFtHL~^=Rn&-~=^Bn>3ZOoR^ zKWe3pe-FLg{jxN+dAf6Tes>)JePN|q17QMYLvtE1>zZEx=4&Mth!S8rE4B;51v246 zxd>t#NH#R@0?E4O10cEXG!%$7kPX~s0OA*rcfH5~BMm4=h6;@Lz(}Q9v-D_c4yJ~o z=cMb^BG~&3Pe;36`WXx?!eOrKbzUI=F?bR!=OzFUeFb=Q8ONPbNW6pV?KuAXF^;c4 zLC*!W17|H<|92N*Ou~Iy@20i>0qDNBv)&(oEPQwgi;rP$3wC}$Y9F3_g;GB(Ok(7J z{!e`?0G=0ZzgZ7$<+)aQreGCYek+Wm?RfV*`k|q`HwvKGk{e;Ov7)SLDSawM1loO7=O*nQ&43XAEwK?B@I!!QHP$iXIDB@)Zw z_Yba~=>VtzXpDz(uCw0V&d|3Xn2jevhAE~n{Np!c-cYKGXG*WyU0=GU208CZUXij|ray9|S)-$fu9z z=~#Z7`t~7qovNSyy9G0nDA7lJl-!OOL6jtlj14e<-fPx$t!KfkW%Rwe!K0TC&#pV# zHnSL?K}t#t84!{(7KIQ6pOn#`_gLMz3MqtDZ95Sc*-+mEj$=hupoAnOpYTyBqY$HJ z`Ce%J`byPJXHVC008Z|>#FDu^IB1!efrueN@G*NC6W%K!DBnjKy!t%Ixw{7eICtkD z?}naZ;PX2$gQ8&V`X0n|iiz^F=Q;S7G4UeK0OMfUO5ETsAnA wf8IauAA{zZ*89-%6kNdI7iPVWd%v9e1Ax=SeX(cYBme*a07*qoM6N<$f*KS8aR2}S literal 0 HcmV?d00001 diff --git a/docs/images/pdoc/namespace.png b/docs/images/pdoc/namespace.png new file mode 100644 index 0000000000000000000000000000000000000000..bae615f6dfecb02f897a68dc460a3b627be326ce GIT binary patch literal 755 zcmVX zMX~t6uOQ;KpQB50p=9Aw5y6Uzpio!Yg;ZjiU}}<<<~5nQGyYDL4xG8?p7THd^SJlg zmSx!+8yl)nC^+akl}gEK4TnS1Znur-*=*Js3txz$R-z1=6cU-vLBT+W3xrg+%Aj-Db1t zOA8uSA(#;YstM79dcA%^07fMei2xk&p(L51!o=+Ctg9)e!^z<0;9*i>K zQvh_U)sm|_ImS#T<3OshXIL>?Ri)IJ;g2-|2Ide)2tWu@yaU?RdU0`4E>bKyeY;@N z5{)h=5*{5L8C9#*&|^bsf22H0y#&b|HkY@d$>NGm+#Iqb1bhcz|B-VYBW{{po(~ME zhg?K{aB<#{aZ}I~u#LWs>OeL?c9=m}E|()|NKvZG%ku!8p|>LIX+Xay@wE_e<8EWi lqjqTXBWs;U=2t3};4eH7Euk6;-W~t|002ovPDHLkV1kD&SUvy% literal 0 HcmV?d00001 diff --git a/docs/images/pdoc/property.png b/docs/images/pdoc/property.png new file mode 100755 index 0000000000000000000000000000000000000000..ebaf0e8743fc33cf152cb7694b865e8d8adbfa90 GIT binary patch literal 599 zcmV-d0;v6oP)GWQRM3$+Tx>2G~D3qqtDdzLJ$P+M| z%_5OV?1V_vbzR8Cf4JqIVHo)K^%pXcv3TotyGW%{h{xkw5Q#dkEiV=ekof!9z?%~d z=g(E7!z)Oq(;*j#L?RmyiObN>-n-ERY$OQs{fC-WE z`TR3JBO8xbMN0KSbiO^m!^f-pEr_bBgH6ZV(+;jrKl87%5H3QY5S&iu(~XVt z`Q%tE#s-6d3Aucs;QCb?w-;^voEneC7ITEh5sgOWa5&8962;=`54d^#1;35CDRwv< z7ITTajw2Wh%6`9}(Iu`wF^PG8L%bJ2;q&>deAA2$Oi`4b;)4JRkH=$mxm=9IcDvoO l^OXPhyYjA9E`GA_{V$1@FaBct0}KEF002ovPDHLkV1kGx8r%Q? literal 0 HcmV?d00001 diff --git a/docs/images/pdoc/related_to.png b/docs/images/pdoc/related_to.png new file mode 100755 index 0000000000000000000000000000000000000000..25eacb7c2524142262d68bf729c5e2b61adfd6d4 GIT binary patch literal 343 zcmV-d0jU0oP)$`dXYaZs9=SbAto%g@>T~?_bH&lTUn@`uo|1bXE{eSR(AO)ESb=V4`uk}mK|39Px&03WLbv~pzk+s7D@lK^ zn+aB+sp)&Y_x-B3>;6ywU--WQNUr<8>TU0P-|L#1U&;A)67w(+> pDf@fM7q9#F25QXo3rUI;002ro52U44e~JJA002ovPDHLkV1l;_q@Mr) literal 0 HcmV?d00001 diff --git a/docs/images/pdoc/search-background.png b/docs/images/pdoc/search-background.png new file mode 100644 index 0000000000000000000000000000000000000000..76295000a0361b4010af8ea71739bd62da70ea76 GIT binary patch literal 295 zcmV+?0oeYDP)I^@p_0n8MnOxY4cF?5x!5gRsf5+3&mI z_m8{Ow%zl9t;dzX*s9X$p2*+1;P#uw-HEl%v)b{e(C31%$b`*gkN^MxQAtEWRCwAX z!HE_^0002Njf9XpN1^!tfAsd5VHTG|^db8U}fi7AzZCsS=eY6E;iTp1V`^$d)GJPuAy9v)sT9X&aDMHUujYdc37Svhkn zTYE=WCs$8Zbxk%lb^$>lOB;Jrb1QXCZ6+orNhxV@2}xyTH9md;XLoM}MHLr!Zy{k3 zLt`^mR#saF7f~^B9X&%wXLn;$3odSMdxPs8K%0U*T^vIyZn+%1Ddq&^UhHg{VC%i` z$N%~-Cdc=(Ji62sq4P-9sjy?Wgo~zKlJMRaE?RO)LivFmZZ411^B!rJ1$HlA;i42a jv2*{4qZ(;*nRpn2%*52^9Plgy8pq)2>gTe~DWM4fif~Q} literal 0 HcmV?d00001 diff --git a/docs/images/pdoc/section.png b/docs/images/pdoc/section.png new file mode 100644 index 0000000000000000000000000000000000000000..d9d598569175e9d73005163366a19ab960f7d0b3 GIT binary patch literal 946 zcmV;j15NyiP)X+uL$Nkc;*P;zf(X>4Tx0C=30k-tkDVHn3h?`a7X&C=7>f^dVF3{iqv zA{4=7u%bg61d|NHzBK!xR*f>o*3ti&0;^aFtHL~^=Rn&-~=^Bn>3ZOoR^ zKWe3pe-FLg{jxN+dAf6Tes>)JePN|q17QMYLvtE1>zZEx=4&Mth!S8rE4B;51v246 zxd>t#NH#R@0?E4O10cEXG!%$7kPX~s0OA*rcfH5~BMm4=h6;@Lz(}Q9v-D_c4yJ~o z=cMb^BG~&3Pe;36`WXx?!eOrKbzUI=F?bR!=OzFUeFb=Q8ONPbNW6pV?KuAXF^;c4 zLC*!W17|H<|92N*Ou~Iy@20i>0qDNBv)&(oEPQwgi;rP$3wC}$Y9F3_g;GB(Ok(7J z{!e`?0G=0ZzgZ7$<+)aQreGCYek+Wm?RfV*`k|q`HwvKGk{e;Ov7)SLDSaF&>9#@#i!P_UA2s_XmJS4G2r9|rL8)wTC|cWcWmS$PuG;M1&07*qoM6N<$g085ny8r+H literal 0 HcmV?d00001 diff --git a/docs/images/pdoc/selected-section-background.png b/docs/images/pdoc/selected-section-background.png new file mode 100644 index 0000000000000000000000000000000000000000..35def47ce76a51e34610884d5943c2a669c779c0 GIT binary patch literal 169 zcmeAS@N?(olHy`uVBq!ia0vp^oItF?!3HFw7YqCVQU#tajv*F;Yp)#SJz&7$d~rrf zN8Sa~P5*;(ud-IOKj}){$D?w6@BE86!s%DnDyV_p!Vho;Y!CN@%k%++5#`AU` z7j5)lnIhb&B?tE;SITJw0xGxH8942>1F_9ZaThjjZ%s23?xQ-@r5kxkEa4j>7{{;BfdE8C6 zp)=Kr_7x|%4~~=ZYy@N51Gu$7A2z>jIV?4`^U?Mw=@$3+y z+k+V08o==9hZtOcfJd1g7-KpV1azcWJe7vY*83?Q?)MDX1Py20ES*+3mn{;Y7ls$t z3Iimk;ZEAowc?Sty5ck(%T2hsSPw?5gJs@;{)`{?Sqrq|6e`BbpdPt`Qzkk@3r05j zVP9%MvuMPPg<6>BYtZC@cyF=Ex0$sT7)uN=NgX2>bi{*xTDfJRXO~-;T~c z4|Z}pvX)FH&DbSxYH|dx8wmMk!n_RX`L)q|<365(&g&F(?#@@0FF6=LtX%gku@d z_{xC3wQkV84PfldAAnXnr&KC`s#GdeRaMDBa-xwM0a&fpybP#&S&f=WEh_r2qQam- zpf7MTH8piGJw1&`Bm$>X`kfpn=R_m5U@(~1Xf)ZsUZJ?S_?&dbOKP?Hi`i^Gve|6M pQvA^AbVeykrTiPwNR9N6-ro-@tE8r#i39)u002ovPDHLkV1nq!Tkrq? literal 0 HcmV?d00001 diff --git a/docs/images/pdoc/superclass.png b/docs/images/pdoc/superclass.png new file mode 100755 index 0000000000000000000000000000000000000000..445c18868e64b239f844c49c89ff8c9229235723 GIT binary patch literal 759 zcmV?tE;SITJw0xGxH8942>1F_9ZaThjjZ%s23?xQ-@r5kxkEa4j>7{{;BfdE8C6 zp)=Kr_7x|%4~~=ZYy@N51Gu$7A2z>jIV?4`^U?Mw=@$3+y z+k+V08o==9hZtOcfJd1g7-KpV1azcWJe7vY*83?Q?)MDX1Py20ES*+3mn{;Y7ls$t z3Iimk;ZEAowc?Sty5ck(%T2hsSPw?5gJs@;{)`{?Sqrq|6e`BbpdPt`Qzkk@3r05j zVP9%MvuMPPg<6>BYtZC@cyF=Ex0$sT7)uN=NgX2>bi{*xTDfJRXO~-;T~c z4|Z}pvX)FH&DbSxYH|dx8wmMk!n_RX`L)q|<365(&g&F(?#@@0FF6=LtX%gku@d z_{xC3wQkV84PfldAAnXnr&KC`s#GdeRaMDBa-xwM0a&fpybP#&S&f=WEh_r2qQam- zpf7MTH8piGJw1&`Bm$>X`kfpn=R_m5U@(~1Xf)ZsUZJ?S_?&dbOKP?Hi`i^Gve|6M pQvA^AbVeykrTiPwNR9N6-ro-@tE8r#i39)u002ovPDHLkV1nq!Tkrq? literal 0 HcmV?d00001 diff --git a/docs/images/pdoc/utility.png b/docs/images/pdoc/utility.png new file mode 100755 index 0000000000000000000000000000000000000000..59af163824c44be62dfbb06df9e71769563a33e1 GIT binary patch literal 630 zcmV-+0*U>JP)!DK;9Y=n` ztyZT|d*HtN4z^AtY@ehNsx1Av5@058(+4Yyzw@m$wtszqQ04yGbJhSW-PK+Sn9kpy z6c5&sKH5aCB||O zo)n!;Re(Lq>NlD(Y>~Mm^&rNjF{+zqQYLCFW%O8ObHbFoO{oHG8H;vpFN|zULKkF} znE;czLyw9^s&5nLicTfoh(h`)V!g47a4i6T`6XNhM{_uCpf3fOH)+aUm{Pd%0$HCQ zD`b=e=_a}-!2e?bhS(t8*Bx}jxG|(Bs-8zXGwpDVhfpKF$YwKX2WZW0hO6n{GpNkbaQ6*W`Eo;3}_R5=XK< z0YsI0n43^|QWPahLjCo*dA`zf@Kp|7fal9I=-yn{U+4i*ot*tN)m|#kBeuVS2r=(P z$&2x{rKt;Dqx=3$7Mb}P++9YHsIwW%;gx^mfN*2lS#X?@Zq5b--LhKUKO1nouBZGU QkpKVy07*qoM6N<$f-OlOxc~qF literal 0 HcmV?d00001 diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..bd3b83d --- /dev/null +++ b/docs/index.html @@ -0,0 +1,86 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | Home + + + + + + + + + + + + + + + + +
+ + +
+ + +
+ +
+ +
+
+

Sections

+
+
+ +
    + +
+
+
+ +
+ + + +
+ + diff --git a/docs/javascripts/pdoc/application.js b/docs/javascripts/pdoc/application.js new file mode 100644 index 0000000..a0303de --- /dev/null +++ b/docs/javascripts/pdoc/application.js @@ -0,0 +1,478 @@ +//= require + +if (!Prototype || Prototype.Version.indexOf('1.6') !== 0) { + throw "This script requires Prototype >= 1.6."; +} + +Object.isDate = function(object) { + return object instanceof Date; +}; + +/** + * class Cookie + * Creates a cookie. +**/ +var Cookie = Class.create({ + /** + * new Cookie(name, value[, expires]) + * + * - name (String): The name of the cookie. + * - value (String): The value of the cookie. + * - expires (Number | Date): Exact date (or number of days from now) that + * the cookie will expire. + **/ + initialize: function(name, value, expires) { + expires = expires || ""; + if (Object.isNumber(expires)) { + var days = expires; + expires = new Date(); + expires.setTime(expires.getTime() + (days * 24 * 60 * 60 * 1000)); + } + + if (Object.isDate(expires)) + expires = expires.toGMTString(); + + if (!Object.isUndefined(expires) && expires !== "") + expires = "; expires=" + expires; + + this.name = name; + this.value = value; + this.expires = expires; + + document.cookie = name + "=" + value + expires + "; path=/"; + }, + + toString: function() { + return this.value; + }, + + inspect: function() { + return "#".interpolate(this); + } +}); + +/** + * Cookie +**/ +Object.extend(Cookie, { + /** + * Cookie.set(name, value, expires) + * + * Alias of [[Cookie#initialize]]. + **/ + set: function(name, value, expires) { + return new Cookie(name, value, expires); + }, + + /** + * Cookie.get(name) + * + * Returns the value of the cookie with the given name. + * - name (String): The name of the cookie to retrieve. + **/ + get: function(name) { + var c = document.cookie.split(';'); + + for (var i = 0, cookie; i < c.length; i++) { + cookie = c[i].split('='); + if (cookie[0].strip() === name) + return cookie[1].strip(); + } + + return null; + }, + + /** + * Cookie.unset(name) + * + * Deletes a cookie. + * - name (String): The name of the cookie to delete. + * + **/ + unset: function(name) { + return Cookie.set(name, "", -1); + } +}); + +Cookie.erase = Cookie.unset; + + + +if (typeof PDoc === 'undefined') { + window.PDoc = { + Sidebar: {} + }; +} + +// HISTORY MANAGER (sort of) +// Polls for changes to the hash. + +(function() { + var PREVIOUS_HASH = null; + + function poll() { + var hash = window.location.hash; + if (hash && hash !== PREVIOUS_HASH) { + document.fire('hash:changed', { + previous: PREVIOUS_HASH, current: hash + }); + } + PREVIOUS_HASH = hash; + window.setTimeout(arguments.callee, 100); + } + + Event.observe(window, 'load', poll); +})(); + +Object.extend(PDoc.Sidebar, { + getActiveTab: function() { + var activeTab = $('sidebar_tabs').down('.active'); + if (!activeTab) return null; + + var href = activeTab.readAttribute('href'); + return href.endsWith('menu_pane') ? 'menu_pane' : 'search_pane'; + }, + + // Remember the state of the sidebar so it can be restored on the next page. + serialize: function() { + var state = $H({ + activeTab: PDoc.Sidebar.getActiveTab(), + menuScrollOffset: $('menu_pane').scrollTop, + searchScrollOffset: $('search_results').scrollTop, + searchValue: $('search').getValue() + }); + + return escape(state.toJSON()); + }, + + // Restore the tree to a certain point based on a cookie. + restore: function(state) { + try { + state = unescape(state).evalJSON(); + var filterer = $('search').retrieve('filterer'); + filterer.setSearchValue(state.searchValue); + + (function() { + $('menu_pane').scrollTop = state.menuScrollOffset; + $('search_results').scrollTop = state.searchScrollOffset; + }).defer(); + } catch(error) { + console.log(error); + if (!(error instanceof SyntaxError)) throw error; + } + } +}); + + + +// Live API search. +PDoc.Sidebar.Filterer = Class.create({ + initialize: function(element, options) { + this.element = $(element); + this.options = Object.extend( + Object.clone(PDoc.Sidebar.Filterer.DEFAULT_OPTIONS), + options || {} + ); + + // The browser's "helpful" auto-complete gets in the way. + this.element.writeAttribute("autocomplete", "off"); + this.element.setValue(''); + + // Hitting "enter" should do nothing. + this.element.up('form').observe("submit", Event.stop); + + this.menu = this.options.menu; + this.links = this.menu.select('a'); + + this.resultsElement = this.options.resultsElement; + + this.observers = { + filter: this.filter.bind(this), + keydown: this.keydown.bind(this), + keyup: this.keyup.bind(this) + }; + + this.menu.setStyle({ opacity: 0.9 }); + this.addObservers(); + }, + + addObservers: function() { + this.element.observe('keyup', this.observers.filter); + }, + + // Called whenever the list of results needs to update as a result of a + // changed search key. + filter: function(event) { + // Clear the text box on ESC. + if (event.keyCode && event.keyCode === Event.KEY_ESC) { + this.element.setValue(''); + } + + if (PDoc.Sidebar.Filterer.INTERCEPT_KEYS.include(event.keyCode)) + return; + + // If there's nothing in the text box, clear the results list. + var value = $F(this.element).strip().toLowerCase(); + if (value === '') { + this.emptyResults(); + this.hideResults(); + return; + } + + var urls = this.findURLs(value); + this.buildResults(urls); + }, + + setSearchValue: function(value) { + this.element.setValue(value); + if (value.strip() === "") { + PDoc.Sidebar.Tabs.setActiveTab(0); + return; + } + this.buildResults(this.findURLs(value)); + }, + + // Given a key, finds all the PDoc objects that match. + findURLs: function(str) { + var results = []; + for (var name in PDoc.elements) { + if (name.toLowerCase().include(str.toLowerCase())) + results.push(PDoc.elements[name]); + } + return results; + }, + + buildResults: function(results) { + this.emptyResults(); + + results.each( function(result) { + var li = this._buildResult(result); + this.resultsElement.appendChild(li); + }, this); + this.showResults(); + }, + + _buildResult: function(obj) { + var li = new Element('li', { 'class': 'menu-item' }); + var a = new Element('a', { + 'class': obj.type.gsub(/\s/, '-'), + 'href': PDoc.pathPrefix + obj.path + }).update(obj.name); + + li.appendChild(a); + return li; + }, + + emptyResults: function() { + this.resultsElement.update(); + }, + + hideResults: function() { + PDoc.Sidebar.Tabs.setActiveTab(0); + //this.resultsElement.hide(); + document.stopObserving('keydown', this.observers.keydown); + document.stopObserving('keyup', this.observers.keyup); + }, + + showResults: function() { + PDoc.Sidebar.Tabs.setActiveTab(1); + //this.resultsElement.show(); + document.stopObserving('keydown', this.observers.keydown); + this.element.stopObserving('keyup', this.observers.keyup); + this.element.observe('keydown', this.observers.keydown); + document.observe('keyup', this.observers.keyup); + }, + + keydown: function(event) { + if (!PDoc.Sidebar.Filterer.INTERCEPT_KEYS.include(event.keyCode)) + return; + + // Also ignore if any modifier keys are present. + if (event.shiftKey || event.ctrlKey || event.altKey || event.metaKey) + return; + + event.stop(); + + if (event.keyCode === Event.KEY_RETURN) { + // Follow the highlighted item, unless there is none. + if (!this.highlighted) return; + var a = this.highlighted.down('a'); + if (a) { + window.location.href = a.href; + } + } else if ([Event.KEY_UP, Event.KEY_DOWN].include(event.keyCode)) { + // Is an arrow key. + var direction = (Event.KEY_DOWN === event.keyCode) ? 1 : -1; + this.highlighted = this.moveHighlight(direction); + + if (!Prototype.Browser.WebKit) { + // If up/down key is held down, list should keep scrolling. + // WebKit does this automatically because it fires the keydown + // event over and over. + this._scrollTimer = window.setTimeout( + this.scrollList.bind(this, direction), 1000); + } + } + }, + + keyup: function(event) { + if (this._scrollTimer) { + window.clearTimeout(this._scrollTimer); + } + }, + + moveHighlight: function(direction) { + if (!this.highlighted) { + // If there is none, highlight the first result. + this.highlighted = + this.resultsElement.down('li').addClassName('highlighted'); + } else { + var method = (direction === 1) ? 'next' : 'previous'; + this.highlighted.removeClassName('highlighted'); + var adjacent = this.highlighted[method]('li'); + // If there isn't an adjacent one, we're at the top or bottom + // of the list. Flip it. + if (!adjacent) { + adjacent = method == 'next' ? this.resultsElement.down('li') : + this.resultsElement.down('li:last-of-type'); + } + adjacent.addClassName('highlighted'); + this.highlighted = adjacent; + } + + var h = this.highlighted, r = this.resultsElement; + + var distanceToBottom = h.offsetTop + h.offsetHeight; + if (distanceToBottom > (r.offsetHeight + r.scrollTop)) { + // Item is below the visible frame. + r.scrollTop = distanceToBottom - r.offsetHeight; + } else if (h.offsetTop < r.scrollTop) { + // Item is above the visible frame. + r.scrollTop = h.offsetTop; + } + + return this.highlighted; + }, + + scrollList: function(direction) { + this.moveHighlight(direction); + this._scrollTimer = window.setTimeout( + this.scrollList.bind(this, direction), 100); + } +}); + +Object.extend(PDoc.Sidebar.Filterer, { + INTERCEPT_KEYS: [Event.KEY_UP, Event.KEY_DOWN, Event.KEY_RETURN], + DEFAULT_OPTIONS: { + interval: 0.1, + resultsElement: '.search-results' + } +}); + + +Form.GhostedField = Class.create({ + initialize: function(element, title, options) { + options = options || {}; + + this.element = $(element); + this.title = title; + + this.isGhosted = true; + + if (options.cloak) { + + // Wrap the native getValue function so that it never returns the + // ghosted value. This is optional because it presumes the ghosted + // value isn't valid input for the field. + this.element.getValue = this.element.getValue.wrap(this.wrappedGetValue.bind(this)); + } + + this.addObservers(); + + this.onBlur(); + }, + + wrappedGetValue: function($proceed) { + var value = $proceed(); + return value === this.title ? "" : value; + }, + + addObservers: function() { + this.element.observe('focus', this.onFocus.bind(this)); + this.element.observe('blur', this.onBlur.bind(this)); + + var form = this.element.up('form'); + if (form) { + form.observe('submit', this.onSubmit.bind(this)); + } + + // Firefox's bfcache means that form fields need to be re-initialized + // when you hit the "back" button to return to the page. + if (Prototype.Browser.Gecko) { + window.addEventListener('pageshow', this.onBlur.bind(this), false); + } + }, + + onFocus: function() { + if (this.isGhosted) { + this.element.setValue(''); + this.setGhosted(false); + } + }, + + onBlur: function() { + var value = this.element.getValue(); + if (value.blank() || value == this.title) { + this.setGhosted(true); + } else { + this.setGhosted(false); + } + }, + + setGhosted: function(isGhosted) { + this.isGhosted = isGhosted; + this.element[isGhosted ? 'addClassName' : 'removeClassName']('ghosted'); + if (isGhosted) { + this.element.setValue(this.title); + } + }, + + // Hook into the enclosing form's `onsubmit` event so that we clear any + // ghosted text before the form is sent. + onSubmit: function() { + if (this.isGhosted) { + this.element.setValue(''); + } + } +}); + +document.observe('dom:loaded', function() { + PDoc.Sidebar.Tabs = new Control.Tabs($('sidebar_tabs')); + + var searchField = $('search'); + + if (searchField) { + var filterer = new PDoc.Sidebar.Filterer(searchField, { + menu: $('api_menu'), + resultsElement: $('search_results') + }); + searchField.store('filterer', filterer); + } + + // Prevent horizontal scrolling in scrollable sidebar areas. + $$('.scrollable').invoke('observe', 'scroll', function() { + this.scrollLeft = 0; + }); + + var sidebarState = Cookie.get('sidebar_state'); + if (sidebarState) { + PDoc.Sidebar.restore(sidebarState); + } + + new Form.GhostedField(searchField, searchField.getAttribute('title'), + { cloak: true }); +}); + +Event.observe(window, 'unload', function() { + Cookie.set('sidebar_state', PDoc.Sidebar.serialize()); +}); \ No newline at end of file diff --git a/docs/javascripts/pdoc/item_index.js b/docs/javascripts/pdoc/item_index.js new file mode 100644 index 0000000..95732e5 --- /dev/null +++ b/docs/javascripts/pdoc/item_index.js @@ -0,0 +1,12 @@ +if (!window.PDoc) window.PDoc = {}; +PDoc.elements = { + 'aerogear.pipeline.adapters.rest#remove': { 'name': 'aerogear.pipeline.adapters.rest#remove', 'type': 'instance method', 'path': 'aerogear/pipeline/adapters/rest/prototype/remove/index.html' }, +'aerogear': { 'name': 'aerogear', 'type': 'namespace', 'path': 'aerogear/index.html' }, +'aerogear.pipeline#add': { 'name': 'aerogear.pipeline#add', 'type': 'instance method', 'path': 'aerogear/pipeline/prototype/add/index.html' }, +'aerogear.pipeline': { 'name': 'aerogear.pipeline', 'type': 'namespace', 'path': 'aerogear/pipeline/index.html' }, +'aerogear.pipeline.adapters': { 'name': 'aerogear.pipeline.adapters', 'type': 'namespace', 'path': 'aerogear/pipeline/adapters/index.html' }, +'aerogear.pipeline#remove': { 'name': 'aerogear.pipeline#remove', 'type': 'instance method', 'path': 'aerogear/pipeline/prototype/remove/index.html' }, +'aerogear.pipeline.adapters.rest#save': { 'name': 'aerogear.pipeline.adapters.rest#save', 'type': 'instance method', 'path': 'aerogear/pipeline/adapters/rest/prototype/save/index.html' }, +'aerogear.pipeline.adapters.rest#read': { 'name': 'aerogear.pipeline.adapters.rest#read', 'type': 'instance method', 'path': 'aerogear/pipeline/adapters/rest/prototype/read/index.html' }, +'aerogear.pipeline.adapters.rest': { 'name': 'aerogear.pipeline.adapters.rest', 'type': 'namespace', 'path': 'aerogear/pipeline/adapters/rest/index.html' } +}; \ No newline at end of file diff --git a/docs/javascripts/pdoc/prototype.js b/docs/javascripts/pdoc/prototype.js new file mode 100644 index 0000000..9fe6e12 --- /dev/null +++ b/docs/javascripts/pdoc/prototype.js @@ -0,0 +1,4874 @@ +/* Prototype JavaScript framework, version 1.6.1 + * (c) 2005-2009 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * + *--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.6.1', + + Browser: (function(){ + var ua = navigator.userAgent; + var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; + return { + IE: !!window.attachEvent && !isOpera, + Opera: isOpera, + WebKit: ua.indexOf('AppleWebKit/') > -1, + Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, + MobileSafari: /Apple.*Mobile.*Safari/.test(ua) + } + })(), + + BrowserFeatures: { + XPath: !!document.evaluate, + SelectorsAPI: !!document.querySelector, + ElementExtensions: (function() { + var constructor = window.Element || window.HTMLElement; + return !!(constructor && constructor.prototype); + })(), + SpecificElementExtensions: (function() { + if (typeof window.HTMLDivElement !== 'undefined') + return true; + + var div = document.createElement('div'); + var form = document.createElement('form'); + var isSupported = false; + + if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) { + isSupported = true; + } + + div = form = null; + + return isSupported; + })() + }, + + ScriptFragment: ']*>([\\S\\s]*?)<\/script>', + JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +}; + +if (Prototype.Browser.MobileSafari) + Prototype.BrowserFeatures.SpecificElementExtensions = false; + + +var Abstract = { }; + + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) { } + } + + return returnValue; + } +}; + +/* Based on Alex Arnell's inheritance implementation. */ + +var Class = (function() { + function subclass() {}; + function create() { + var parent = null, properties = $A(arguments); + if (Object.isFunction(properties[0])) + parent = properties.shift(); + + function klass() { + this.initialize.apply(this, arguments); + } + + Object.extend(klass, Class.Methods); + klass.superclass = parent; + klass.subclasses = []; + + if (parent) { + subclass.prototype = parent.prototype; + klass.prototype = new subclass; + parent.subclasses.push(klass); + } + + for (var i = 0; i < properties.length; i++) + klass.addMethods(properties[i]); + + if (!klass.prototype.initialize) + klass.prototype.initialize = Prototype.emptyFunction; + + klass.prototype.constructor = klass; + return klass; + } + + function addMethods(source) { + var ancestor = this.superclass && this.superclass.prototype; + var properties = Object.keys(source); + + if (!Object.keys({ toString: true }).length) { + if (source.toString != Object.prototype.toString) + properties.push("toString"); + if (source.valueOf != Object.prototype.valueOf) + properties.push("valueOf"); + } + + for (var i = 0, length = properties.length; i < length; i++) { + var property = properties[i], value = source[property]; + if (ancestor && Object.isFunction(value) && + value.argumentNames().first() == "$super") { + var method = value; + value = (function(m) { + return function() { return ancestor[m].apply(this, arguments); }; + })(property).wrap(method); + + value.valueOf = method.valueOf.bind(method); + value.toString = method.toString.bind(method); + } + this.prototype[property] = value; + } + + return this; + } + + return { + create: create, + Methods: { + addMethods: addMethods + } + }; +})(); +(function() { + + var _toString = Object.prototype.toString; + + function extend(destination, source) { + for (var property in source) + destination[property] = source[property]; + return destination; + } + + function inspect(object) { + try { + if (isUndefined(object)) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : String(object); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + } + + function toJSON(object) { + var type = typeof object; + switch (type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (isElement(object)) return; + + var results = []; + for (var property in object) { + var value = toJSON(object[property]); + if (!isUndefined(value)) + results.push(property.toJSON() + ': ' + value); + } + + return '{' + results.join(', ') + '}'; + } + + function toQueryString(object) { + return $H(object).toQueryString(); + } + + function toHTML(object) { + return object && object.toHTML ? object.toHTML() : String.interpret(object); + } + + function keys(object) { + var results = []; + for (var property in object) + results.push(property); + return results; + } + + function values(object) { + var results = []; + for (var property in object) + results.push(object[property]); + return results; + } + + function clone(object) { + return extend({ }, object); + } + + function isElement(object) { + return !!(object && object.nodeType == 1); + } + + function isArray(object) { + return _toString.call(object) == "[object Array]"; + } + + + function isHash(object) { + return object instanceof Hash; + } + + function isFunction(object) { + return typeof object === "function"; + } + + function isString(object) { + return _toString.call(object) == "[object String]"; + } + + function isNumber(object) { + return _toString.call(object) == "[object Number]"; + } + + function isUndefined(object) { + return typeof object === "undefined"; + } + + extend(Object, { + extend: extend, + inspect: inspect, + toJSON: toJSON, + toQueryString: toQueryString, + toHTML: toHTML, + keys: keys, + values: values, + clone: clone, + isElement: isElement, + isArray: isArray, + isHash: isHash, + isFunction: isFunction, + isString: isString, + isNumber: isNumber, + isUndefined: isUndefined + }); +})(); +Object.extend(Function.prototype, (function() { + var slice = Array.prototype.slice; + + function update(array, args) { + var arrayLength = array.length, length = args.length; + while (length--) array[arrayLength + length] = args[length]; + return array; + } + + function merge(array, args) { + array = slice.call(array, 0); + return update(array, args); + } + + function argumentNames() { + var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] + .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') + .replace(/\s+/g, '').split(','); + return names.length == 1 && !names[0] ? [] : names; + } + + function bind(context) { + if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; + var __method = this, args = slice.call(arguments, 1); + return function() { + var a = merge(args, arguments); + return __method.apply(context, a); + } + } + + function bindAsEventListener(context) { + var __method = this, args = slice.call(arguments, 1); + return function(event) { + var a = update([event || window.event], args); + return __method.apply(context, a); + } + } + + function curry() { + if (!arguments.length) return this; + var __method = this, args = slice.call(arguments, 0); + return function() { + var a = merge(args, arguments); + return __method.apply(this, a); + } + } + + function delay(timeout) { + var __method = this, args = slice.call(arguments, 1); + timeout = timeout * 1000 + return window.setTimeout(function() { + return __method.apply(__method, args); + }, timeout); + } + + function defer() { + var args = update([0.01], arguments); + return this.delay.apply(this, args); + } + + function wrap(wrapper) { + var __method = this; + return function() { + var a = update([__method.bind(this)], arguments); + return wrapper.apply(this, a); + } + } + + function methodize() { + if (this._methodized) return this._methodized; + var __method = this; + return this._methodized = function() { + var a = update([this], arguments); + return __method.apply(null, a); + }; + } + + return { + argumentNames: argumentNames, + bind: bind, + bindAsEventListener: bindAsEventListener, + curry: curry, + delay: delay, + defer: defer, + wrap: wrap, + methodize: methodize + } +})()); + + +Date.prototype.toJSON = function() { + return '"' + this.getUTCFullYear() + '-' + + (this.getUTCMonth() + 1).toPaddedString(2) + '-' + + this.getUTCDate().toPaddedString(2) + 'T' + + this.getUTCHours().toPaddedString(2) + ':' + + this.getUTCMinutes().toPaddedString(2) + ':' + + this.getUTCSeconds().toPaddedString(2) + 'Z"'; +}; + + +RegExp.prototype.match = RegExp.prototype.test; + +RegExp.escape = function(str) { + return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); +}; +var PeriodicalExecuter = Class.create({ + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + execute: function() { + this.callback(this); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.execute(); + this.currentlyExecuting = false; + } catch(e) { + this.currentlyExecuting = false; + throw e; + } + } + } +}); +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, (function() { + + function prepareReplacement(replacement) { + if (Object.isFunction(replacement)) return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; + } + + function gsub(pattern, replacement) { + var result = '', source = this, match; + replacement = prepareReplacement(replacement); + + if (Object.isString(pattern)) + pattern = RegExp.escape(pattern); + + if (!(pattern.length || pattern.source)) { + replacement = replacement(''); + return replacement + source.split('').join(replacement) + replacement; + } + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + } + + function sub(pattern, replacement, count) { + replacement = prepareReplacement(replacement); + count = Object.isUndefined(count) ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + } + + function scan(pattern, iterator) { + this.gsub(pattern, iterator); + return String(this); + } + + function truncate(length, truncation) { + length = length || 30; + truncation = Object.isUndefined(truncation) ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : String(this); + } + + function strip() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + } + + function stripTags() { + return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, ''); + } + + function stripScripts() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + } + + function extractScripts() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + } + + function evalScripts() { + return this.extractScripts().map(function(script) { return eval(script) }); + } + + function escapeHTML() { + return this.replace(/&/g,'&').replace(//g,'>'); + } + + function unescapeHTML() { + return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&'); + } + + + function toQueryParams(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return { }; + + return match[1].split(separator || '&').inject({ }, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + } + + function toArray() { + return this.split(''); + } + + function succ() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + } + + function times(count) { + return count < 1 ? '' : new Array(count + 1).join(this); + } + + function camelize() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + } + + function capitalize() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + } + + function underscore() { + return this.replace(/::/g, '/') + .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') + .replace(/([a-z\d])([A-Z])/g, '$1_$2') + .replace(/-/g, '_') + .toLowerCase(); + } + + function dasherize() { + return this.replace(/_/g, '-'); + } + + function inspect(useDoubleQuotes) { + var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) { + if (character in String.specialChar) { + return String.specialChar[character]; + } + return '\\u00' + character.charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + } + + function toJSON() { + return this.inspect(true); + } + + function unfilterJSON(filter) { + return this.replace(filter || Prototype.JSONFilter, '$1'); + } + + function isJSON() { + var str = this; + if (str.blank()) return false; + str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); + return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); + } + + function evalJSON(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || json.isJSON()) return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + } + + function include(pattern) { + return this.indexOf(pattern) > -1; + } + + function startsWith(pattern) { + return this.indexOf(pattern) === 0; + } + + function endsWith(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + } + + function empty() { + return this == ''; + } + + function blank() { + return /^\s*$/.test(this); + } + + function interpolate(object, pattern) { + return new Template(this, pattern).evaluate(object); + } + + return { + gsub: gsub, + sub: sub, + scan: scan, + truncate: truncate, + strip: String.prototype.trim ? String.prototype.trim : strip, + stripTags: stripTags, + stripScripts: stripScripts, + extractScripts: extractScripts, + evalScripts: evalScripts, + escapeHTML: escapeHTML, + unescapeHTML: unescapeHTML, + toQueryParams: toQueryParams, + parseQuery: toQueryParams, + toArray: toArray, + succ: succ, + times: times, + camelize: camelize, + capitalize: capitalize, + underscore: underscore, + dasherize: dasherize, + inspect: inspect, + toJSON: toJSON, + unfilterJSON: unfilterJSON, + isJSON: isJSON, + evalJSON: evalJSON, + include: include, + startsWith: startsWith, + endsWith: endsWith, + empty: empty, + blank: blank, + interpolate: interpolate + }; +})()); + +var Template = Class.create({ + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + if (object && Object.isFunction(object.toTemplateReplacements)) + object = object.toTemplateReplacements(); + + return this.template.gsub(this.pattern, function(match) { + if (object == null) return (match[1] + ''); + + var before = match[1] || ''; + if (before == '\\') return match[2]; + + var ctx = object, expr = match[3]; + var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; + match = pattern.exec(expr); + if (match == null) return before; + + while (match != null) { + var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1]; + ctx = ctx[comp]; + if (null == ctx || '' == match[3]) break; + expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); + match = pattern.exec(expr); + } + + return before + String.interpret(ctx); + }); + } +}); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; + +var $break = { }; + +var Enumerable = (function() { + function each(iterator, context) { + var index = 0; + try { + this._each(function(value) { + iterator.call(context, value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + } + + function eachSlice(number, iterator, context) { + var index = -number, slices = [], array = this.toArray(); + if (number < 1) return array; + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.collect(iterator, context); + } + + function all(iterator, context) { + iterator = iterator || Prototype.K; + var result = true; + this.each(function(value, index) { + result = result && !!iterator.call(context, value, index); + if (!result) throw $break; + }); + return result; + } + + function any(iterator, context) { + iterator = iterator || Prototype.K; + var result = false; + this.each(function(value, index) { + if (result = !!iterator.call(context, value, index)) + throw $break; + }); + return result; + } + + function collect(iterator, context) { + iterator = iterator || Prototype.K; + var results = []; + this.each(function(value, index) { + results.push(iterator.call(context, value, index)); + }); + return results; + } + + function detect(iterator, context) { + var result; + this.each(function(value, index) { + if (iterator.call(context, value, index)) { + result = value; + throw $break; + } + }); + return result; + } + + function findAll(iterator, context) { + var results = []; + this.each(function(value, index) { + if (iterator.call(context, value, index)) + results.push(value); + }); + return results; + } + + function grep(filter, iterator, context) { + iterator = iterator || Prototype.K; + var results = []; + + if (Object.isString(filter)) + filter = new RegExp(RegExp.escape(filter)); + + this.each(function(value, index) { + if (filter.match(value)) + results.push(iterator.call(context, value, index)); + }); + return results; + } + + function include(object) { + if (Object.isFunction(this.indexOf)) + if (this.indexOf(object) != -1) return true; + + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + } + + function inGroupsOf(number, fillWith) { + fillWith = Object.isUndefined(fillWith) ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + } + + function inject(memo, iterator, context) { + this.each(function(value, index) { + memo = iterator.call(context, memo, value, index); + }); + return memo; + } + + function invoke(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + } + + function max(iterator, context) { + iterator = iterator || Prototype.K; + var result; + this.each(function(value, index) { + value = iterator.call(context, value, index); + if (result == null || value >= result) + result = value; + }); + return result; + } + + function min(iterator, context) { + iterator = iterator || Prototype.K; + var result; + this.each(function(value, index) { + value = iterator.call(context, value, index); + if (result == null || value < result) + result = value; + }); + return result; + } + + function partition(iterator, context) { + iterator = iterator || Prototype.K; + var trues = [], falses = []; + this.each(function(value, index) { + (iterator.call(context, value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + } + + function pluck(property) { + var results = []; + this.each(function(value) { + results.push(value[property]); + }); + return results; + } + + function reject(iterator, context) { + var results = []; + this.each(function(value, index) { + if (!iterator.call(context, value, index)) + results.push(value); + }); + return results; + } + + function sortBy(iterator, context) { + return this.map(function(value, index) { + return { + value: value, + criteria: iterator.call(context, value, index) + }; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + } + + function toArray() { + return this.map(); + } + + function zip() { + var iterator = Prototype.K, args = $A(arguments); + if (Object.isFunction(args.last())) + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + } + + function size() { + return this.toArray().length; + } + + function inspect() { + return '#'; + } + + + + + + + + + + return { + each: each, + eachSlice: eachSlice, + all: all, + every: all, + any: any, + some: any, + collect: collect, + map: collect, + detect: detect, + findAll: findAll, + select: findAll, + filter: findAll, + grep: grep, + include: include, + member: include, + inGroupsOf: inGroupsOf, + inject: inject, + invoke: invoke, + max: max, + min: min, + partition: partition, + pluck: pluck, + reject: reject, + sortBy: sortBy, + toArray: toArray, + entries: toArray, + zip: zip, + size: size, + inspect: inspect, + find: detect + }; +})(); +function $A(iterable) { + if (!iterable) return []; + if ('toArray' in Object(iterable)) return iterable.toArray(); + var length = iterable.length || 0, results = new Array(length); + while (length--) results[length] = iterable[length]; + return results; +} + +function $w(string) { + if (!Object.isString(string)) return []; + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +Array.from = $A; + + +(function() { + var arrayProto = Array.prototype, + slice = arrayProto.slice, + _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available + + function each(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + } + if (!_each) _each = each; + + function clear() { + this.length = 0; + return this; + } + + function first() { + return this[0]; + } + + function last() { + return this[this.length - 1]; + } + + function compact() { + return this.select(function(value) { + return value != null; + }); + } + + function flatten() { + return this.inject([], function(array, value) { + if (Object.isArray(value)) + return array.concat(value.flatten()); + array.push(value); + return array; + }); + } + + function without() { + var values = slice.call(arguments, 0); + return this.select(function(value) { + return !values.include(value); + }); + } + + function reverse(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + } + + function uniq(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + } + + function intersect(array) { + return this.uniq().findAll(function(item) { + return array.detect(function(value) { return item === value }); + }); + } + + + function clone() { + return slice.call(this, 0); + } + + function size() { + return this.length; + } + + function inspect() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + } + + function toJSON() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (!Object.isUndefined(value)) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } + + function indexOf(item, i) { + i || (i = 0); + var length = this.length; + if (i < 0) i = length + i; + for (; i < length; i++) + if (this[i] === item) return i; + return -1; + } + + function lastIndexOf(item, i) { + i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; + var n = this.slice(0, i).reverse().indexOf(item); + return (n < 0) ? n : i - n - 1; + } + + function concat() { + var array = slice.call(this, 0), item; + for (var i = 0, length = arguments.length; i < length; i++) { + item = arguments[i]; + if (Object.isArray(item) && !('callee' in item)) { + for (var j = 0, arrayLength = item.length; j < arrayLength; j++) + array.push(item[j]); + } else { + array.push(item); + } + } + return array; + } + + Object.extend(arrayProto, Enumerable); + + if (!arrayProto._reverse) + arrayProto._reverse = arrayProto.reverse; + + Object.extend(arrayProto, { + _each: _each, + clear: clear, + first: first, + last: last, + compact: compact, + flatten: flatten, + without: without, + reverse: reverse, + uniq: uniq, + intersect: intersect, + clone: clone, + toArray: clone, + size: size, + inspect: inspect, + toJSON: toJSON + }); + + var CONCAT_ARGUMENTS_BUGGY = (function() { + return [].concat(arguments)[0][0] !== 1; + })(1,2) + + if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat; + + if (!arrayProto.indexOf) arrayProto.indexOf = indexOf; + if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf; +})(); +function $H(object) { + return new Hash(object); +}; + +var Hash = Class.create(Enumerable, (function() { + function initialize(object) { + this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); + } + + function _each(iterator) { + for (var key in this._object) { + var value = this._object[key], pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + } + + function set(key, value) { + return this._object[key] = value; + } + + function get(key) { + if (this._object[key] !== Object.prototype[key]) + return this._object[key]; + } + + function unset(key) { + var value = this._object[key]; + delete this._object[key]; + return value; + } + + function toObject() { + return Object.clone(this._object); + } + + function keys() { + return this.pluck('key'); + } + + function values() { + return this.pluck('value'); + } + + function index(value) { + var match = this.detect(function(pair) { + return pair.value === value; + }); + return match && match.key; + } + + function merge(object) { + return this.clone().update(object); + } + + function update(object) { + return new Hash(object).inject(this, function(result, pair) { + result.set(pair.key, pair.value); + return result; + }); + } + + function toQueryPair(key, value) { + if (Object.isUndefined(value)) return key; + return key + '=' + encodeURIComponent(String.interpret(value)); + } + + function toQueryString() { + return this.inject([], function(results, pair) { + var key = encodeURIComponent(pair.key), values = pair.value; + + if (values && typeof values == 'object') { + if (Object.isArray(values)) + return results.concat(values.map(toQueryPair.curry(key))); + } else results.push(toQueryPair(key, values)); + return results; + }).join('&'); + } + + function inspect() { + return '#'; + } + + function toJSON() { + return Object.toJSON(this.toObject()); + } + + function clone() { + return new Hash(this); + } + + return { + initialize: initialize, + _each: _each, + set: set, + get: get, + unset: unset, + toObject: toObject, + toTemplateReplacements: toObject, + keys: keys, + values: values, + index: index, + merge: merge, + update: update, + toQueryString: toQueryString, + inspect: inspect, + toJSON: toJSON, + clone: clone + }; +})()); + +Hash.from = $H; +Object.extend(Number.prototype, (function() { + function toColorPart() { + return this.toPaddedString(2, 16); + } + + function succ() { + return this + 1; + } + + function times(iterator, context) { + $R(0, this, true).each(iterator, context); + return this; + } + + function toPaddedString(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + } + + function toJSON() { + return isFinite(this) ? this.toString() : 'null'; + } + + function abs() { + return Math.abs(this); + } + + function round() { + return Math.round(this); + } + + function ceil() { + return Math.ceil(this); + } + + function floor() { + return Math.floor(this); + } + + return { + toColorPart: toColorPart, + succ: succ, + times: times, + toPaddedString: toPaddedString, + toJSON: toJSON, + abs: abs, + round: round, + ceil: ceil, + floor: floor + }; +})()); + +function $R(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var ObjectRange = Class.create(Enumerable, (function() { + function initialize(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + } + + function _each(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + } + + function include(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } + + return { + initialize: initialize, + _each: _each, + include: include + }; +})()); + + + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +}; + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (Object.isFunction(responder[callback])) { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) { } + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { Ajax.activeRequestCount++ }, + onComplete: function() { Ajax.activeRequestCount-- } +}); +Ajax.Base = Class.create({ + initialize: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '', + evalJSON: true, + evalJS: true + }; + Object.extend(this.options, options || { }); + + this.options.method = this.options.method.toLowerCase(); + + if (Object.isString(this.options.parameters)) + this.options.parameters = this.options.parameters.toQueryParams(); + else if (Object.isHash(this.options.parameters)) + this.options.parameters = this.options.parameters.toObject(); + } +}); +Ajax.Request = Class.create(Ajax.Base, { + _complete: false, + + initialize: function($super, url, options) { + $super(options); + this.transport = Ajax.getTransport(); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Object.toQueryString(params)) { + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + var response = new Ajax.Response(this); + if (this.options.onCreate) this.options.onCreate(response); + Ajax.Responders.dispatch('onCreate', this, response); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + 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', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + 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 (Object.isFunction(extras.push)) + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + 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 = Ajax.Request.Events[readyState], response = new Ajax.Response(this); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + response.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + var contentType = response.getHeader('Content-type'); + if (this.options.evalJS == 'force' + || (this.options.evalJS && this.isSameOrigin() && contentType + && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); + Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + isSameOrigin: function() { + var m = this.url.match(/^\s*https?:\/\/[^\/]*/); + return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ + protocol: location.protocol, + domain: document.domain, + port: location.port ? ':' + location.port : '' + })); + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name) || null; + } catch (e) { return null; } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + + + + + + + + +Ajax.Response = Class.create({ + initialize: function(request){ + this.request = request; + var transport = this.transport = request.transport, + readyState = this.readyState = transport.readyState; + + if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { + this.status = this.getStatus(); + this.statusText = this.getStatusText(); + this.responseText = String.interpret(transport.responseText); + this.headerJSON = this._getHeaderJSON(); + } + + if(readyState == 4) { + var xml = transport.responseXML; + this.responseXML = Object.isUndefined(xml) ? null : xml; + this.responseJSON = this._getResponseJSON(); + } + }, + + status: 0, + + statusText: '', + + getStatus: Ajax.Request.prototype.getStatus, + + getStatusText: function() { + try { + return this.transport.statusText || ''; + } catch (e) { return '' } + }, + + getHeader: Ajax.Request.prototype.getHeader, + + getAllHeaders: function() { + try { + return this.getAllResponseHeaders(); + } catch (e) { return null } + }, + + getResponseHeader: function(name) { + return this.transport.getResponseHeader(name); + }, + + getAllResponseHeaders: function() { + return this.transport.getAllResponseHeaders(); + }, + + _getHeaderJSON: function() { + var json = this.getHeader('X-JSON'); + if (!json) return null; + json = decodeURIComponent(escape(json)); + try { + return json.evalJSON(this.request.options.sanitizeJSON || + !this.request.isSameOrigin()); + } catch (e) { + this.request.dispatchException(e); + } + }, + + _getResponseJSON: function() { + var options = this.request.options; + if (!options.evalJSON || (options.evalJSON != 'force' && + !(this.getHeader('Content-type') || '').include('application/json')) || + this.responseText.blank()) + return null; + try { + return this.responseText.evalJSON(options.sanitizeJSON || + !this.request.isSameOrigin()); + } catch (e) { + this.request.dispatchException(e); + } + } +}); + +Ajax.Updater = Class.create(Ajax.Request, { + initialize: function($super, container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + }; + + options = Object.clone(options); + var onComplete = options.onComplete; + options.onComplete = (function(response, json) { + this.updateContent(response.responseText); + if (Object.isFunction(onComplete)) onComplete(response, json); + }).bind(this); + + $super(url, options); + }, + + updateContent: function(responseText) { + var receiver = this.container[this.success() ? 'success' : 'failure'], + options = this.options; + + if (!options.evalScripts) responseText = responseText.stripScripts(); + + if (receiver = $(receiver)) { + if (options.insertion) { + if (Object.isString(options.insertion)) { + var insertion = { }; insertion[options.insertion] = responseText; + receiver.insert(insertion); + } + else options.insertion(receiver, responseText); + } + else receiver.update(responseText); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { + initialize: function($super, container, url, options) { + $super(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = { }; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(response) { + if (this.options.decay) { + this.decay = (response.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = response.responseText; + } + this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); + + + +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (Object.isString(element)) + element = document.getElementById(element); + return Element.extend(element); +} + +if (Prototype.BrowserFeatures.XPath) { + document._getElementsByXPath = function(expression, parentElement) { + var results = []; + var query = document.evaluate(expression, $(parentElement) || document, + null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + for (var i = 0, length = query.snapshotLength; i < length; i++) + results.push(Element.extend(query.snapshotItem(i))); + return results; + }; +} + +/*--------------------------------------------------------------------------*/ + +if (!window.Node) var Node = { }; + +if (!Node.ELEMENT_NODE) { + Object.extend(Node, { + ELEMENT_NODE: 1, + ATTRIBUTE_NODE: 2, + TEXT_NODE: 3, + CDATA_SECTION_NODE: 4, + ENTITY_REFERENCE_NODE: 5, + ENTITY_NODE: 6, + PROCESSING_INSTRUCTION_NODE: 7, + COMMENT_NODE: 8, + DOCUMENT_NODE: 9, + DOCUMENT_TYPE_NODE: 10, + DOCUMENT_FRAGMENT_NODE: 11, + NOTATION_NODE: 12 + }); +} + + +(function(global) { + + var SETATTRIBUTE_IGNORES_NAME = (function(){ + var elForm = document.createElement("form"); + var elInput = document.createElement("input"); + var root = document.documentElement; + elInput.setAttribute("name", "test"); + elForm.appendChild(elInput); + root.appendChild(elForm); + var isBuggy = elForm.elements + ? (typeof elForm.elements.test == "undefined") + : null; + root.removeChild(elForm); + elForm = elInput = null; + return isBuggy; + })(); + + var element = global.Element; + global.Element = function(tagName, attributes) { + attributes = attributes || { }; + tagName = tagName.toLowerCase(); + var cache = Element.cache; + if (SETATTRIBUTE_IGNORES_NAME && attributes.name) { + tagName = '<' + tagName + ' name="' + attributes.name + '">'; + delete attributes.name; + return Element.writeAttribute(document.createElement(tagName), attributes); + } + if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); + return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); + }; + Object.extend(global.Element, element || { }); + if (element) global.Element.prototype = element.prototype; +})(this); + +Element.cache = { }; +Element.idCounter = 1; + +Element.Methods = { + visible: function(element) { + return $(element).style.display != 'none'; + }, + + toggle: function(element) { + element = $(element); + Element[Element.visible(element) ? 'hide' : 'show'](element); + return element; + }, + + + hide: function(element) { + element = $(element); + element.style.display = 'none'; + return element; + }, + + show: function(element) { + element = $(element); + element.style.display = ''; + return element; + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + return element; + }, + + update: (function(){ + + var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){ + var el = document.createElement("select"), + isBuggy = true; + el.innerHTML = ""; + if (el.options && el.options[0]) { + isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION"; + } + el = null; + return isBuggy; + })(); + + var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){ + try { + var el = document.createElement("table"); + if (el && el.tBodies) { + el.innerHTML = "test"; + var isBuggy = typeof el.tBodies[0] == "undefined"; + el = null; + return isBuggy; + } + } catch (e) { + return true; + } + })(); + + var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () { + var s = document.createElement("script"), + isBuggy = false; + try { + s.appendChild(document.createTextNode("")); + isBuggy = !s.firstChild || + s.firstChild && s.firstChild.nodeType !== 3; + } catch (e) { + isBuggy = true; + } + s = null; + return isBuggy; + })(); + + function update(element, content) { + element = $(element); + + if (content && content.toElement) + content = content.toElement(); + + if (Object.isElement(content)) + return element.update().insert(content); + + content = Object.toHTML(content); + + var tagName = element.tagName.toUpperCase(); + + if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) { + element.text = content; + return element; + } + + if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) { + if (tagName in Element._insertionTranslations.tags) { + while (element.firstChild) { + element.removeChild(element.firstChild); + } + Element._getContentFromAnonymousElement(tagName, content.stripScripts()) + .each(function(node) { + element.appendChild(node) + }); + } + else { + element.innerHTML = content.stripScripts(); + } + } + else { + element.innerHTML = content.stripScripts(); + } + + content.evalScripts.bind(content).defer(); + return element; + } + + return update; + })(), + + replace: function(element, content) { + element = $(element); + if (content && content.toElement) content = content.toElement(); + else if (!Object.isElement(content)) { + content = Object.toHTML(content); + var range = element.ownerDocument.createRange(); + range.selectNode(element); + content.evalScripts.bind(content).defer(); + content = range.createContextualFragment(content.stripScripts()); + } + element.parentNode.replaceChild(content, element); + return element; + }, + + insert: function(element, insertions) { + element = $(element); + + if (Object.isString(insertions) || Object.isNumber(insertions) || + Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) + insertions = {bottom:insertions}; + + var content, insert, tagName, childNodes; + + for (var position in insertions) { + content = insertions[position]; + position = position.toLowerCase(); + insert = Element._insertionTranslations[position]; + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + insert(element, content); + continue; + } + + content = Object.toHTML(content); + + tagName = ((position == 'before' || position == 'after') + ? element.parentNode : element).tagName.toUpperCase(); + + childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + + if (position == 'top' || position == 'after') childNodes.reverse(); + childNodes.each(insert.curry(element)); + + content.evalScripts.bind(content).defer(); + } + + return element; + }, + + wrap: function(element, wrapper, attributes) { + element = $(element); + if (Object.isElement(wrapper)) + $(wrapper).writeAttribute(attributes || { }); + else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); + else wrapper = new Element('div', wrapper); + if (element.parentNode) + element.parentNode.replaceChild(wrapper, element); + wrapper.appendChild(element); + return wrapper; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return Element.recursivelyCollect(element, 'parentNode'); + }, + + descendants: function(element) { + return Element.select(element, "*"); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return Element.recursivelyCollect(element, 'previousSibling'); + }, + + nextSiblings: function(element) { + return Element.recursivelyCollect(element, 'nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return Element.previousSiblings(element).reverse() + .concat(Element.nextSiblings(element)); + }, + + match: function(element, selector) { + if (Object.isString(selector)) + selector = new Selector(selector); + return selector.match($(element)); + }, + + up: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(element.parentNode); + var ancestors = Element.ancestors(element); + return Object.isNumber(expression) ? ancestors[expression] : + Selector.findElement(ancestors, expression, index); + }, + + down: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return Element.firstDescendant(element); + return Object.isNumber(expression) ? Element.descendants(element)[expression] : + Element.select(element, expression)[index || 0]; + }, + + previous: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); + var previousSiblings = Element.previousSiblings(element); + return Object.isNumber(expression) ? previousSiblings[expression] : + Selector.findElement(previousSiblings, expression, index); + }, + + next: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); + var nextSiblings = Element.nextSiblings(element); + return Object.isNumber(expression) ? nextSiblings[expression] : + Selector.findElement(nextSiblings, expression, index); + }, + + + select: function(element) { + var args = Array.prototype.slice.call(arguments, 1); + return Selector.findChildElements(element, args); + }, + + adjacent: function(element) { + var args = Array.prototype.slice.call(arguments, 1); + return Selector.findChildElements(element.parentNode, args).without(element); + }, + + identify: function(element) { + element = $(element); + var id = Element.readAttribute(element, 'id'); + if (id) return id; + do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id)); + Element.writeAttribute(element, 'id', id); + return id; + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + var t = Element._attributeTranslations.read; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + if (name.include(':')) { + return (!element.attributes || !element.attributes[name]) ? null : + element.attributes[name].value; + } + } + return element.getAttribute(name); + }, + + writeAttribute: function(element, name, value) { + element = $(element); + var attributes = { }, t = Element._attributeTranslations.write; + + if (typeof name == 'object') attributes = name; + else attributes[name] = Object.isUndefined(value) ? true : value; + + for (var attr in attributes) { + name = t.names[attr] || attr; + value = attributes[attr]; + if (t.values[attr]) name = t.values[attr](element, value); + if (value === false || value === null) + element.removeAttribute(name); + else if (value === true) + element.setAttribute(name, name); + else element.setAttribute(name, value); + } + return element; + }, + + getHeight: function(element) { + return Element.getDimensions(element).height; + }, + + getWidth: function(element) { + return Element.getDimensions(element).width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + return (elementClassName.length > 0 && (elementClassName == className || + new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + if (!Element.hasClassName(element, className)) + element.className += (element.className ? ' ' : '') + className; + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + element.className = element.className.replace( + new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + return Element[Element.hasClassName(element, className) ? + 'removeClassName' : 'addClassName'](element, className); + }, + + cleanWhitespace: function(element) { + element = $(element); + var node = element.firstChild; + while (node) { + var nextNode = node.nextSibling; + if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) + element.removeChild(node); + node = nextNode; + } + return element; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + descendantOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + + if (element.compareDocumentPosition) + return (element.compareDocumentPosition(ancestor) & 8) === 8; + + if (ancestor.contains) + return ancestor.contains(element) && ancestor !== element; + + while (element = element.parentNode) + if (element == ancestor) return true; + + return false; + }, + + scrollTo: function(element) { + element = $(element); + var pos = Element.cumulativeOffset(element); + window.scrollTo(pos[0], pos[1]); + return element; + }, + + getStyle: function(element, style) { + element = $(element); + style = style == 'float' ? 'cssFloat' : style.camelize(); + var value = element.style[style]; + if (!value || value == 'auto') { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css[style] : null; + } + if (style == 'opacity') return value ? parseFloat(value) : 1.0; + return value == 'auto' ? null : value; + }, + + getOpacity: function(element) { + return $(element).getStyle('opacity'); + }, + + setStyle: function(element, styles) { + element = $(element); + var elementStyle = element.style, match; + if (Object.isString(styles)) { + element.style.cssText += ';' + styles; + return styles.include('opacity') ? + element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; + } + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]); + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : + property] = styles[property]; + + return element; + }, + + setOpacity: function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + return element; + }, + + getDimensions: function(element) { + element = $(element); + var display = Element.getStyle(element, 'display'); + if (display != 'none' && display != null) // Safari bug + 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'; + if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari + els.position = 'absolute'; + els.display = 'block'; + var originalWidth = element.clientWidth; + var originalHeight = element.clientHeight; + els.display = originalDisplay; + els.position = originalPosition; + els.visibility = originalVisibility; + return {width: originalWidth, height: originalHeight}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + if (Prototype.Browser.Opera) { + element.style.top = 0; + element.style.left = 0; + } + } + return element; + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return element; + element._overflow = Element.getStyle(element, 'overflow') || 'auto'; + if (element._overflow !== 'hidden') + element.style.overflow = 'hidden'; + return element; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if (element.tagName.toUpperCase() == 'BODY') break; + var p = Element.getStyle(element, 'position'); + if (p !== 'static') break; + } + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + absolutize: function(element) { + element = $(element); + if (Element.getStyle(element, 'position') == 'absolute') return element; + + var offsets = Element.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + return element; + }, + + relativize: function(element) { + element = $(element); + if (Element.getStyle(element, 'position') == 'relative') return element; + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + return element; + }, + + cumulativeScrollOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + getOffsetParent: function(element) { + if (element.offsetParent) return $(element.offsetParent); + if (element == document.body) return $(element); + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return $(element); + + return $(document.body); + }, + + viewportOffset: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + if (element.offsetParent == document.body && + Element.getStyle(element, 'position') == 'absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return Element._returnOffset(valueL, valueT); + }, + + clonePosition: function(element, source) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || { }); + + source = $(source); + var p = Element.viewportOffset(source); + + element = $(element); + var delta = [0, 0]; + var parent = null; + if (Element.getStyle(element, 'position') == 'absolute') { + parent = Element.getOffsetParent(element); + delta = Element.viewportOffset(parent); + } + + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if (options.setWidth) element.style.width = source.offsetWidth + 'px'; + if (options.setHeight) element.style.height = source.offsetHeight + 'px'; + return element; + } +}; + +Object.extend(Element.Methods, { + getElementsBySelector: Element.Methods.select, + + childElements: Element.Methods.immediateDescendants +}); + +Element._attributeTranslations = { + write: { + names: { + className: 'class', + htmlFor: 'for' + }, + values: { } + } +}; + +if (Prototype.Browser.Opera) { + Element.Methods.getStyle = Element.Methods.getStyle.wrap( + function(proceed, element, style) { + switch (style) { + case 'left': case 'top': case 'right': case 'bottom': + if (proceed(element, 'position') === 'static') return null; + case 'height': case 'width': + if (!Element.visible(element)) return null; + + var dim = parseInt(proceed(element, style), 10); + + if (dim !== element['offset' + style.capitalize()]) + return dim + 'px'; + + var properties; + if (style === 'height') { + properties = ['border-top-width', 'padding-top', + 'padding-bottom', 'border-bottom-width']; + } + else { + properties = ['border-left-width', 'padding-left', + 'padding-right', 'border-right-width']; + } + return properties.inject(dim, function(memo, property) { + var val = proceed(element, property); + return val === null ? memo : memo - parseInt(val, 10); + }) + 'px'; + default: return proceed(element, style); + } + } + ); + + Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( + function(proceed, element, attribute) { + if (attribute === 'title') return element.title; + return proceed(element, attribute); + } + ); +} + +else if (Prototype.Browser.IE) { + Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( + function(proceed, element) { + element = $(element); + try { element.offsetParent } + catch(e) { return $(document.body) } + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + + $w('positionedOffset viewportOffset').each(function(method) { + Element.Methods[method] = Element.Methods[method].wrap( + function(proceed, element) { + element = $(element); + try { element.offsetParent } + catch(e) { return Element._returnOffset(0,0) } + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + var offsetParent = element.getOffsetParent(); + if (offsetParent && offsetParent.getStyle('position') === 'fixed') + offsetParent.setStyle({ zoom: 1 }); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + }); + + Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap( + function(proceed, element) { + try { element.offsetParent } + catch(e) { return Element._returnOffset(0,0) } + return proceed(element); + } + ); + + Element.Methods.getStyle = function(element, style) { + element = $(element); + style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize(); + var value = element.style[style]; + if (!value && element.currentStyle) value = element.currentStyle[style]; + + if (style == 'opacity') { + if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) + if (value[1]) return parseFloat(value[1]) / 100; + return 1.0; + } + + if (value == 'auto') { + if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none')) + return element['offset' + style.capitalize()] + 'px'; + return null; + } + return value; + }; + + Element.Methods.setOpacity = function(element, value) { + function stripAlpha(filter){ + return filter.replace(/alpha\([^\)]*\)/gi,''); + } + element = $(element); + var currentStyle = element.currentStyle; + if ((currentStyle && !currentStyle.hasLayout) || + (!currentStyle && element.style.zoom == 'normal')) + element.style.zoom = 1; + + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + (filter = stripAlpha(filter)) ? + style.filter = filter : style.removeAttribute('filter'); + return element; + } else if (value < 0.00001) value = 0; + style.filter = stripAlpha(filter) + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; + + Element._attributeTranslations = (function(){ + + var classProp = 'className'; + var forProp = 'for'; + + var el = document.createElement('div'); + + el.setAttribute(classProp, 'x'); + + if (el.className !== 'x') { + el.setAttribute('class', 'x'); + if (el.className === 'x') { + classProp = 'class'; + } + } + el = null; + + el = document.createElement('label'); + el.setAttribute(forProp, 'x'); + if (el.htmlFor !== 'x') { + el.setAttribute('htmlFor', 'x'); + if (el.htmlFor === 'x') { + forProp = 'htmlFor'; + } + } + el = null; + + return { + read: { + names: { + 'class': classProp, + 'className': classProp, + 'for': forProp, + 'htmlFor': forProp + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute); + }, + _getAttr2: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _getAttrNode: function(element, attribute) { + var node = element.getAttributeNode(attribute); + return node ? node.value : ""; + }, + _getEv: (function(){ + + var el = document.createElement('div'); + el.onclick = Prototype.emptyFunction; + var value = el.getAttribute('onclick'); + var f; + + if (String(value).indexOf('{') > -1) { + f = function(element, attribute) { + attribute = element.getAttribute(attribute); + if (!attribute) return null; + attribute = attribute.toString(); + attribute = attribute.split('{')[1]; + attribute = attribute.split('}')[0]; + return attribute.strip(); + }; + } + else if (value === '') { + f = function(element, attribute) { + attribute = element.getAttribute(attribute); + if (!attribute) return null; + return attribute.strip(); + }; + } + el = null; + return f; + })(), + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + return element.title; + } + } + } + } + })(); + + Element._attributeTranslations.write = { + names: Object.extend({ + cellpadding: 'cellPadding', + cellspacing: 'cellSpacing' + }, Element._attributeTranslations.read.names), + values: { + checked: function(element, value) { + element.checked = !!value; + }, + + style: function(element, value) { + element.style.cssText = value ? value : ''; + } + } + }; + + Element._attributeTranslations.has = {}; + + $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + + 'encType maxLength readOnly longDesc frameBorder').each(function(attr) { + Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; + Element._attributeTranslations.has[attr.toLowerCase()] = attr; + }); + + (function(v) { + Object.extend(v, { + href: v._getAttr2, + src: v._getAttr2, + type: v._getAttr, + action: v._getAttrNode, + disabled: v._flag, + checked: v._flag, + readonly: v._flag, + multiple: v._flag, + onload: v._getEv, + onunload: v._getEv, + onclick: v._getEv, + ondblclick: v._getEv, + onmousedown: v._getEv, + onmouseup: v._getEv, + onmouseover: v._getEv, + onmousemove: v._getEv, + onmouseout: v._getEv, + onfocus: v._getEv, + onblur: v._getEv, + onkeypress: v._getEv, + onkeydown: v._getEv, + onkeyup: v._getEv, + onsubmit: v._getEv, + onreset: v._getEv, + onselect: v._getEv, + onchange: v._getEv + }); + })(Element._attributeTranslations.read.values); + + if (Prototype.BrowserFeatures.ElementExtensions) { + (function() { + function _descendants(element) { + var nodes = element.getElementsByTagName('*'), results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName !== "!") // Filter out comment nodes. + results.push(node); + return results; + } + + Element.Methods.down = function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + return Object.isNumber(expression) ? _descendants(element)[expression] : + Element.select(element, expression)[index || 0]; + } + })(); + } + +} + +else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1) ? 0.999999 : + (value === '') ? '' : (value < 0.00001) ? 0 : value; + return element; + }; +} + +else if (Prototype.Browser.WebKit) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + + if (value == 1) + if(element.tagName.toUpperCase() == 'IMG' && element.width) { + element.width++; element.width--; + } else try { + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch (e) { } + + return element; + }; + + Element.Methods.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return Element._returnOffset(valueL, valueT); + }; +} + +if ('outerHTML' in document.documentElement) { + Element.Methods.replace = function(element, content) { + element = $(element); + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + element.parentNode.replaceChild(content, element); + return element; + } + + content = Object.toHTML(content); + var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); + + if (Element._insertionTranslations.tags[tagName]) { + var nextSibling = element.next(); + var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + parent.removeChild(element); + if (nextSibling) + fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); + else + fragments.each(function(node) { parent.appendChild(node) }); + } + else element.outerHTML = content.stripScripts(); + + content.evalScripts.bind(content).defer(); + return element; + }; +} + +Element._returnOffset = function(l, t) { + var result = [l, t]; + result.left = l; + result.top = t; + return result; +}; + +Element._getContentFromAnonymousElement = function(tagName, html) { + var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; + if (t) { + div.innerHTML = t[0] + html + t[1]; + t[2].times(function() { div = div.firstChild }); + } else div.innerHTML = html; + return $A(div.childNodes); +}; + +Element._insertionTranslations = { + before: function(element, node) { + element.parentNode.insertBefore(node, element); + }, + top: function(element, node) { + element.insertBefore(node, element.firstChild); + }, + bottom: function(element, node) { + element.appendChild(node); + }, + after: function(element, node) { + element.parentNode.insertBefore(node, element.nextSibling); + }, + tags: { + TABLE: ['', '
', 1], + TBODY: ['', '
', 2], + TR: ['', '
', 3], + TD: ['
', '
', 4], + SELECT: ['', 1] + } +}; + +(function() { + var tags = Element._insertionTranslations.tags; + Object.extend(tags, { + THEAD: tags.TBODY, + TFOOT: tags.TBODY, + TH: tags.TD + }); +})(); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + attribute = Element._attributeTranslations.has[attribute] || attribute; + var node = $(element).getAttributeNode(attribute); + return !!(node && node.specified); + } +}; + +Element.Methods.ByTag = { }; + +Object.extend(Element, Element.Methods); + +(function(div) { + + if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) { + window.HTMLElement = { }; + window.HTMLElement.prototype = div['__proto__']; + Prototype.BrowserFeatures.ElementExtensions = true; + } + + div = null; + +})(document.createElement('div')) + +Element.extend = (function() { + + function checkDeficiency(tagName) { + if (typeof window.Element != 'undefined') { + var proto = window.Element.prototype; + if (proto) { + var id = '_' + (Math.random()+'').slice(2); + var el = document.createElement(tagName); + proto[id] = 'x'; + var isBuggy = (el[id] !== 'x'); + delete proto[id]; + el = null; + return isBuggy; + } + } + return false; + } + + function extendElementWith(element, methods) { + for (var property in methods) { + var value = methods[property]; + if (Object.isFunction(value) && !(property in element)) + element[property] = value.methodize(); + } + } + + var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object'); + + if (Prototype.BrowserFeatures.SpecificElementExtensions) { + if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) { + return function(element) { + if (element && typeof element._extendedByPrototype == 'undefined') { + var t = element.tagName; + if (t && (/^(?:object|applet|embed)$/i.test(t))) { + extendElementWith(element, Element.Methods); + extendElementWith(element, Element.Methods.Simulated); + extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]); + } + } + return element; + } + } + return Prototype.K; + } + + var Methods = { }, ByTag = Element.Methods.ByTag; + + var extend = Object.extend(function(element) { + if (!element || typeof element._extendedByPrototype != 'undefined' || + element.nodeType != 1 || element == window) return element; + + var methods = Object.clone(Methods), + tagName = element.tagName.toUpperCase(); + + if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); + + extendElementWith(element, methods); + + element._extendedByPrototype = Prototype.emptyFunction; + return element; + + }, { + refresh: function() { + if (!Prototype.BrowserFeatures.ElementExtensions) { + Object.extend(Methods, Element.Methods); + Object.extend(Methods, Element.Methods.Simulated); + } + } + }); + + extend.refresh(); + return extend; +})(); + +Element.hasAttribute = function(element, attribute) { + if (element.hasAttribute) return element.hasAttribute(attribute); + return Element.Methods.Simulated.hasAttribute(element, attribute); +}; + +Element.addMethods = function(methods) { + var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag; + + if (!methods) { + Object.extend(Form, Form.Methods); + Object.extend(Form.Element, Form.Element.Methods); + Object.extend(Element.Methods.ByTag, { + "FORM": Object.clone(Form.Methods), + "INPUT": Object.clone(Form.Element.Methods), + "SELECT": Object.clone(Form.Element.Methods), + "TEXTAREA": Object.clone(Form.Element.Methods) + }); + } + + if (arguments.length == 2) { + var tagName = methods; + methods = arguments[1]; + } + + if (!tagName) Object.extend(Element.Methods, methods || { }); + else { + if (Object.isArray(tagName)) tagName.each(extend); + else extend(tagName); + } + + function extend(tagName) { + tagName = tagName.toUpperCase(); + if (!Element.Methods.ByTag[tagName]) + Element.Methods.ByTag[tagName] = { }; + Object.extend(Element.Methods.ByTag[tagName], methods); + } + + function copy(methods, destination, onlyIfAbsent) { + onlyIfAbsent = onlyIfAbsent || false; + for (var property in methods) { + var value = methods[property]; + if (!Object.isFunction(value)) continue; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = value.methodize(); + } + } + + function findDOMClass(tagName) { + var klass; + var trans = { + "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph", + "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList", + "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading", + "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote", + "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION": + "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD": + "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR": + "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET": + "FrameSet", "IFRAME": "IFrame" + }; + if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName + 'Element'; + if (window[klass]) return window[klass]; + klass = 'HTML' + tagName.capitalize() + 'Element'; + if (window[klass]) return window[klass]; + + var element = document.createElement(tagName); + var proto = element['__proto__'] || element.constructor.prototype; + element = null; + return proto; + } + + var elementPrototype = window.HTMLElement ? HTMLElement.prototype : + Element.prototype; + + if (F.ElementExtensions) { + copy(Element.Methods, elementPrototype); + copy(Element.Methods.Simulated, elementPrototype, true); + } + + if (F.SpecificElementExtensions) { + for (var tag in Element.Methods.ByTag) { + var klass = findDOMClass(tag); + if (Object.isUndefined(klass)) continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; + + if (Element.extend.refresh) Element.extend.refresh(); + Element.cache = { }; +}; + + +document.viewport = { + + getDimensions: function() { + return { width: this.getWidth(), height: this.getHeight() }; + }, + + getScrollOffsets: function() { + return Element._returnOffset( + window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, + window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); + } +}; + +(function(viewport) { + var B = Prototype.Browser, doc = document, element, property = {}; + + function getRootElement() { + if (B.WebKit && !doc.evaluate) + return document; + + if (B.Opera && window.parseFloat(window.opera.version()) < 9.5) + return document.body; + + return document.documentElement; + } + + function define(D) { + if (!element) element = getRootElement(); + + property[D] = 'client' + D; + + viewport['get' + D] = function() { return element[property[D]] }; + return viewport['get' + D](); + } + + viewport.getWidth = define.curry('Width'); + + viewport.getHeight = define.curry('Height'); +})(document.viewport); + + +Element.Storage = { + UID: 1 +}; + +Element.addMethods({ + getStorage: function(element) { + if (!(element = $(element))) return; + + var uid; + if (element === window) { + uid = 0; + } else { + if (typeof element._prototypeUID === "undefined") + element._prototypeUID = [Element.Storage.UID++]; + uid = element._prototypeUID[0]; + } + + if (!Element.Storage[uid]) + Element.Storage[uid] = $H(); + + return Element.Storage[uid]; + }, + + store: function(element, key, value) { + if (!(element = $(element))) return; + + if (arguments.length === 2) { + Element.getStorage(element).update(key); + } else { + Element.getStorage(element).set(key, value); + } + + return element; + }, + + retrieve: function(element, key, defaultValue) { + if (!(element = $(element))) return; + var hash = Element.getStorage(element), value = hash.get(key); + + if (Object.isUndefined(value)) { + hash.set(key, defaultValue); + value = defaultValue; + } + + return value; + }, + + clone: function(element, deep) { + if (!(element = $(element))) return; + var clone = element.cloneNode(deep); + clone._prototypeUID = void 0; + if (deep) { + var descendants = Element.select(clone, '*'), + i = descendants.length; + while (i--) { + descendants[i]._prototypeUID = void 0; + } + } + return Element.extend(clone); + } +}); +/* Portions of the Selector class are derived from Jack Slocum's DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create({ + initialize: function(expression) { + this.expression = expression.strip(); + + if (this.shouldUseSelectorsAPI()) { + this.mode = 'selectorsAPI'; + } else if (this.shouldUseXPath()) { + this.mode = 'xpath'; + this.compileXPathMatcher(); + } else { + this.mode = "normal"; + this.compileMatcher(); + } + + }, + + shouldUseXPath: (function() { + + var IS_DESCENDANT_SELECTOR_BUGGY = (function(){ + var isBuggy = false; + if (document.evaluate && window.XPathResult) { + var el = document.createElement('div'); + el.innerHTML = '
'; + + var xpath = ".//*[local-name()='ul' or local-name()='UL']" + + "//*[local-name()='li' or local-name()='LI']"; + + var result = document.evaluate(xpath, el, null, + XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + + isBuggy = (result.snapshotLength !== 2); + el = null; + } + return isBuggy; + })(); + + return function() { + if (!Prototype.BrowserFeatures.XPath) return false; + + var e = this.expression; + + if (Prototype.Browser.WebKit && + (e.include("-of-type") || e.include(":empty"))) + return false; + + if ((/(\[[\w-]*?:|:checked)/).test(e)) + return false; + + if (IS_DESCENDANT_SELECTOR_BUGGY) return false; + + return true; + } + + })(), + + shouldUseSelectorsAPI: function() { + if (!Prototype.BrowserFeatures.SelectorsAPI) return false; + + if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false; + + if (!Selector._div) Selector._div = new Element('div'); + + try { + Selector._div.querySelector(this.expression); + } catch(e) { + return false; + } + + return true; + }, + + compileMatcher: function() { + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m, len = ps.length, name; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; + return; + } + + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i = 0; i"; + } +}); + +if (Prototype.BrowserFeatures.SelectorsAPI && + document.compatMode === 'BackCompat') { + Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){ + var div = document.createElement('div'), + span = document.createElement('span'); + + div.id = "prototype_test_id"; + span.className = 'Test'; + div.appendChild(span); + var isIgnored = (div.querySelector('#prototype_test_id .test') !== null); + div = span = null; + return isIgnored; + })(); +} + +Object.extend(Selector, { + _cache: { }, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: function(m) { + m[1] = m[1].toLowerCase(); + return new Template("[@#{1}]").evaluate(m); + }, + attr: function(m) { + m[1] = m[1].toLowerCase(); + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (Object.isFunction(h)) return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0)]", + 'checked': "[@checked]", + 'disabled': "[(@disabled) and (@type!='hidden')]", + 'enabled': "[not(@disabled) and (@type!='hidden')]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, v, len = p.length, name; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i = 0; i= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: [ + { name: 'laterSibling', re: /^\s*~\s*/ }, + { name: 'child', re: /^\s*>\s*/ }, + { name: 'adjacent', re: /^\s*\+\s*/ }, + { name: 'descendant', re: /^\s/ }, + + { name: 'tagName', re: /^\s*(\*|[\w\-]+)(\b|$)?/ }, + { name: 'id', re: /^#([\w\-\*]+)(\b|$)/ }, + { name: 'className', re: /^\.([\w\-\*]+)(\b|$)/ }, + { name: 'pseudo', re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ }, + { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ }, + { name: 'attr', re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ } + ], + + assertions: { + tagName: function(element, matches) { + return matches[1].toUpperCase() == element.tagName.toUpperCase(); + }, + + className: function(element, matches) { + return Element.hasClassName(element, matches[1]); + }, + + id: function(element, matches) { + return element.id === matches[1]; + }, + + attrPresence: function(element, matches) { + return Element.hasAttribute(element, matches[1]); + }, + + attr: function(element, matches) { + var nodeValue = Element.readAttribute(element, matches[1]); + return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); + } + }, + + handlers: { + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + mark: function(nodes) { + var _true = Prototype.emptyFunction; + for (var i = 0, node; node = nodes[i]; i++) + node._countedByPrototype = _true; + return nodes; + }, + + unmark: (function(){ + + var PROPERTIES_ATTRIBUTES_MAP = (function(){ + var el = document.createElement('div'), + isBuggy = false, + propName = '_countedByPrototype', + value = 'x' + el[propName] = value; + isBuggy = (el.getAttribute(propName) === value); + el = null; + return isBuggy; + })(); + + return PROPERTIES_ATTRIBUTES_MAP ? + function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node.removeAttribute('_countedByPrototype'); + return nodes; + } : + function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._countedByPrototype = void 0; + return nodes; + } + })(), + + index: function(parentNode, reverse, ofType) { + parentNode._countedByPrototype = Prototype.emptyFunction; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + var node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; + } + }, + + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (typeof (n = nodes[i])._countedByPrototype == 'undefined') { + n._countedByPrototype = Prototype.emptyFunction; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + tagName: function(nodes, root, tagName, combinator) { + var uTagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() === uTagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + + if (root == document) { + if (!targetNode) return []; + if (!nodes) return [targetNode]; + } else { + if (!root.sourceIndex || root.sourceIndex < 1) { + var nodes = root.getElementsByTagName('*'); + for (var j = 0, node; node = nodes[j]; j++) { + if (node.id === id) return [node]; + } + } + } + + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr, combinator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + if (nodes && combinator) nodes = this[combinator](nodes); + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator, combinator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + if (nodes && combinator) nodes = this[combinator](nodes); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._countedByPrototype) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (node.tagName == '!' || node.firstChild) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._countedByPrototype) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled && (!node.type || node.type !== 'hidden')) + results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); }, + '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); }, + '*=': function(nv, v) { return nv == v || nv && nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() + + '-').include('-' + (v || "").toUpperCase() + '-'); } + }, + + split: function(expression) { + var expressions = []; + expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + return expressions; + }, + + matchElements: function(elements, expression) { + var matches = $$(expression), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._countedByPrototype) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (Object.isNumber(expression)) { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + expressions = Selector.split(expressions.join(',')); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +if (Prototype.Browser.IE) { + Object.extend(Selector.handlers, { + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + if (node.tagName !== "!") a.push(node); + return a; + } + }); +} + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} + +var Form = { + reset: function(form) { + form = $(form); + form.reset(); + return form; + }, + + serializeElements: function(elements, options) { + if (typeof options != 'object') options = { hash: !!options }; + else if (Object.isUndefined(options.hash)) options.hash = true; + var key, value, submitted = false, submit = options.submit; + + var data = elements.inject({ }, function(result, element) { + if (!element.disabled && element.name) { + key = element.name; value = $(element).getValue(); + if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && + submit !== false && (!submit || key == submit) && (submitted = true)))) { + if (key in result) { + if (!Object.isArray(result[key])) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return options.hash ? data : Object.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, options) { + return Form.serializeElements(Form.getElements(form), options); + }, + + getElements: function(form) { + var elements = $(form).getElementsByTagName('*'), + element, + arr = [ ], + serializers = Form.Element.Serializers; + for (var i = 0; element = elements[i]; i++) { + arr.push(element); + } + return arr.inject([], function(elements, child) { + if (serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + }) + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + var elements = $(form).getElements().findAll(function(element) { + return 'hidden' != element.type && !element.disabled; + }); + var firstByIndex = elements.findAll(function(element) { + return element.hasAttribute('tabIndex') && element.tabIndex >= 0; + }).sortBy(function(element) { return element.tabIndex }).first(); + + return firstByIndex ? firstByIndex : elements.find(function(element) { + return /^(?:input|select|textarea)$/i.test(element.tagName); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || { }); + + var params = options.parameters, action = form.readAttribute('action') || ''; + if (action.blank()) action = window.location.href; + options.parameters = form.serialize(true); + + if (params) { + if (Object.isString(params)) params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(action, options); + } +}; + +/*--------------------------------------------------------------------------*/ + + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +}; + +Form.Element.Methods = { + + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = { }; + pair[element.name] = value; + return Object.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + setValue: function(element, value) { + element = $(element); + var method = element.tagName.toLowerCase(); + Form.Element.Serializers[method](element, value); + return element; + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + try { + element.focus(); + if (element.select && (element.tagName.toLowerCase() != 'input' || + !(/^(?:button|reset|submit)$/i.test(element.type)))) + element.select(); + } catch (e) { } + return element; + }, + + disable: function(element) { + element = $(element); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +}; + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; + +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element, value) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element, value); + default: + return Form.Element.Serializers.textarea(element, value); + } + }, + + inputSelector: function(element, value) { + if (Object.isUndefined(value)) return element.checked ? element.value : null; + else element.checked = !!value; + }, + + textarea: function(element, value) { + if (Object.isUndefined(value)) return element.value; + else element.value = value; + }, + + select: function(element, value) { + if (Object.isUndefined(value)) + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + else { + var opt, currentValue, single = !Object.isArray(value); + for (var i = 0, length = element.length; i < length; i++) { + opt = element.options[i]; + currentValue = this.optionValue(opt); + if (single) { + if (currentValue == value) { + opt.selected = true; + return; + } + } + else opt.selected = value.include(currentValue); + } + } + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +}; + +/*--------------------------------------------------------------------------*/ + + +Abstract.TimedObserver = Class.create(PeriodicalExecuter, { + initialize: function($super, element, frequency, callback) { + $super(callback, frequency); + this.element = $(element); + this.lastValue = this.getValue(); + }, + + execute: function() { + var value = this.getValue(); + if (Object.isString(this.lastValue) && Object.isString(value) ? + this.lastValue != value : String(this.lastValue) != String(value)) { + this.callback(this.element, value); + this.lastValue = value; + } + } +}); + +Form.Element.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = Class.create({ + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback, this); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +}); + +Form.Element.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); +(function() { + + var Event = { + 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, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + KEY_INSERT: 45, + + cache: {} + }; + + var docEl = document.documentElement; + var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl + && 'onmouseleave' in docEl; + + var _isButton; + if (Prototype.Browser.IE) { + var buttonMap = { 0: 1, 1: 4, 2: 2 }; + _isButton = function(event, code) { + return event.button === buttonMap[code]; + }; + } else if (Prototype.Browser.WebKit) { + _isButton = function(event, code) { + switch (code) { + case 0: return event.which == 1 && !event.metaKey; + case 1: return event.which == 1 && event.metaKey; + default: return false; + } + }; + } else { + _isButton = function(event, code) { + return event.which ? (event.which === code + 1) : (event.button === code); + }; + } + + function isLeftClick(event) { return _isButton(event, 0) } + + function isMiddleClick(event) { return _isButton(event, 1) } + + function isRightClick(event) { return _isButton(event, 2) } + + function element(event) { + event = Event.extend(event); + + var node = event.target, type = event.type, + currentTarget = event.currentTarget; + + if (currentTarget && currentTarget.tagName) { + if (type === 'load' || type === 'error' || + (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' + && currentTarget.type === 'radio')) + node = currentTarget; + } + + if (node.nodeType == Node.TEXT_NODE) + node = node.parentNode; + + return Element.extend(node); + } + + function findElement(event, expression) { + var element = Event.element(event); + if (!expression) return element; + var elements = [element].concat(element.ancestors()); + return Selector.findElement(elements, expression, 0); + } + + function pointer(event) { + return { x: pointerX(event), y: pointerY(event) }; + } + + function pointerX(event) { + var docElement = document.documentElement, + body = document.body || { scrollLeft: 0 }; + + return event.pageX || (event.clientX + + (docElement.scrollLeft || body.scrollLeft) - + (docElement.clientLeft || 0)); + } + + function pointerY(event) { + var docElement = document.documentElement, + body = document.body || { scrollTop: 0 }; + + return event.pageY || (event.clientY + + (docElement.scrollTop || body.scrollTop) - + (docElement.clientTop || 0)); + } + + + function stop(event) { + Event.extend(event); + event.preventDefault(); + event.stopPropagation(); + + event.stopped = true; + } + + Event.Methods = { + isLeftClick: isLeftClick, + isMiddleClick: isMiddleClick, + isRightClick: isRightClick, + + element: element, + findElement: findElement, + + pointer: pointer, + pointerX: pointerX, + pointerY: pointerY, + + stop: stop + }; + + + var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { + m[name] = Event.Methods[name].methodize(); + return m; + }); + + if (Prototype.Browser.IE) { + function _relatedTarget(event) { + var element; + switch (event.type) { + case 'mouseover': element = event.fromElement; break; + case 'mouseout': element = event.toElement; break; + default: return null; + } + return Element.extend(element); + } + + Object.extend(methods, { + stopPropagation: function() { this.cancelBubble = true }, + preventDefault: function() { this.returnValue = false }, + inspect: function() { return '[object Event]' } + }); + + Event.extend = function(event, element) { + if (!event) return false; + if (event._extendedByPrototype) return event; + + event._extendedByPrototype = Prototype.emptyFunction; + var pointer = Event.pointer(event); + + Object.extend(event, { + target: event.srcElement || element, + relatedTarget: _relatedTarget(event), + pageX: pointer.x, + pageY: pointer.y + }); + + return Object.extend(event, methods); + }; + } else { + Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__; + Object.extend(Event.prototype, methods); + Event.extend = Prototype.K; + } + + function _createResponder(element, eventName, handler) { + var registry = Element.retrieve(element, 'prototype_event_registry'); + + if (Object.isUndefined(registry)) { + CACHE.push(element); + registry = Element.retrieve(element, 'prototype_event_registry', $H()); + } + + var respondersForEvent = registry.get(eventName); + if (Object.isUndefined(respondersForEvent)) { + respondersForEvent = []; + registry.set(eventName, respondersForEvent); + } + + if (respondersForEvent.pluck('handler').include(handler)) return false; + + var responder; + if (eventName.include(":")) { + responder = function(event) { + if (Object.isUndefined(event.eventName)) + return false; + + if (event.eventName !== eventName) + return false; + + Event.extend(event, element); + handler.call(element, event); + }; + } else { + if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED && + (eventName === "mouseenter" || eventName === "mouseleave")) { + if (eventName === "mouseenter" || eventName === "mouseleave") { + responder = function(event) { + Event.extend(event, element); + + var parent = event.relatedTarget; + while (parent && parent !== element) { + try { parent = parent.parentNode; } + catch(e) { parent = element; } + } + + if (parent === element) return; + + handler.call(element, event); + }; + } + } else { + responder = function(event) { + Event.extend(event, element); + handler.call(element, event); + }; + } + } + + responder.handler = handler; + respondersForEvent.push(responder); + return responder; + } + + function _destroyCache() { + for (var i = 0, length = CACHE.length; i < length; i++) { + Event.stopObserving(CACHE[i]); + CACHE[i] = null; + } + } + + var CACHE = []; + + if (Prototype.Browser.IE) + window.attachEvent('onunload', _destroyCache); + + if (Prototype.Browser.WebKit) + window.addEventListener('unload', Prototype.emptyFunction, false); + + + var _getDOMEventName = Prototype.K; + + if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) { + _getDOMEventName = function(eventName) { + var translations = { mouseenter: "mouseover", mouseleave: "mouseout" }; + return eventName in translations ? translations[eventName] : eventName; + }; + } + + function observe(element, eventName, handler) { + element = $(element); + + var responder = _createResponder(element, eventName, handler); + + if (!responder) return element; + + if (eventName.include(':')) { + if (element.addEventListener) + element.addEventListener("dataavailable", responder, false); + else { + element.attachEvent("ondataavailable", responder); + element.attachEvent("onfilterchange", responder); + } + } else { + var actualEventName = _getDOMEventName(eventName); + + if (element.addEventListener) + element.addEventListener(actualEventName, responder, false); + else + element.attachEvent("on" + actualEventName, responder); + } + + return element; + } + + function stopObserving(element, eventName, handler) { + element = $(element); + + var registry = Element.retrieve(element, 'prototype_event_registry'); + + if (Object.isUndefined(registry)) return element; + + if (eventName && !handler) { + var responders = registry.get(eventName); + + if (Object.isUndefined(responders)) return element; + + responders.each( function(r) { + Element.stopObserving(element, eventName, r.handler); + }); + return element; + } else if (!eventName) { + registry.each( function(pair) { + var eventName = pair.key, responders = pair.value; + + responders.each( function(r) { + Element.stopObserving(element, eventName, r.handler); + }); + }); + return element; + } + + var responders = registry.get(eventName); + + if (!responders) return; + + var responder = responders.find( function(r) { return r.handler === handler; }); + if (!responder) return element; + + var actualEventName = _getDOMEventName(eventName); + + if (eventName.include(':')) { + if (element.removeEventListener) + element.removeEventListener("dataavailable", responder, false); + else { + element.detachEvent("ondataavailable", responder); + element.detachEvent("onfilterchange", responder); + } + } else { + if (element.removeEventListener) + element.removeEventListener(actualEventName, responder, false); + else + element.detachEvent('on' + actualEventName, responder); + } + + registry.set(eventName, responders.without(responder)); + + return element; + } + + function fire(element, eventName, memo, bubble) { + element = $(element); + + if (Object.isUndefined(bubble)) + bubble = true; + + if (element == document && document.createEvent && !element.dispatchEvent) + element = document.documentElement; + + var event; + if (document.createEvent) { + event = document.createEvent('HTMLEvents'); + event.initEvent('dataavailable', true, true); + } else { + event = document.createEventObject(); + event.eventType = bubble ? 'ondataavailable' : 'onfilterchange'; + } + + event.eventName = eventName; + event.memo = memo || { }; + + if (document.createEvent) + element.dispatchEvent(event); + else + element.fireEvent(event.eventType, event); + + return Event.extend(event); + } + + + Object.extend(Event, Event.Methods); + + Object.extend(Event, { + fire: fire, + observe: observe, + stopObserving: stopObserving + }); + + Element.addMethods({ + fire: fire, + + observe: observe, + + stopObserving: stopObserving + }); + + Object.extend(document, { + fire: fire.methodize(), + + observe: observe.methodize(), + + stopObserving: stopObserving.methodize(), + + loaded: false + }); + + if (window.Event) Object.extend(window.Event, Event); + else window.Event = Event; +})(); + +(function() { + /* Support for the DOMContentLoaded event is based on work by Dan Webb, + Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */ + + var timer; + + function fireContentLoadedEvent() { + if (document.loaded) return; + if (timer) window.clearTimeout(timer); + document.loaded = true; + document.fire('dom:loaded'); + } + + function checkReadyState() { + if (document.readyState === 'complete') { + document.stopObserving('readystatechange', checkReadyState); + fireContentLoadedEvent(); + } + } + + function pollDoScroll() { + try { document.documentElement.doScroll('left'); } + catch(e) { + timer = pollDoScroll.defer(); + return; + } + fireContentLoadedEvent(); + } + + if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false); + } else { + document.observe('readystatechange', checkReadyState); + if (window == top) + timer = pollDoScroll.defer(); + } + + Event.observe(window, 'load', fireContentLoadedEvent); +})(); + +Element.addMethods(); + +/*------------------------------- DEPRECATED -------------------------------*/ + +Hash.toQueryString = Object.toQueryString; + +var Toggle = { display: Element.toggle }; + +Element.Methods.childOf = Element.Methods.descendantOf; + +var Insertion = { + Before: function(element, content) { + return Element.insert(element, {before:content}); + }, + + Top: function(element, content) { + return Element.insert(element, {top:content}); + }, + + Bottom: function(element, content) { + return Element.insert(element, {bottom:content}); + }, + + After: function(element, content) { + return Element.insert(element, {after:content}); + } +}; + +var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +var Position = { + includeScrollOffsets: false, + + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = Element.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = Element.cumulativeScrollOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = Element.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + + cumulativeOffset: Element.Methods.cumulativeOffset, + + positionedOffset: Element.Methods.positionedOffset, + + absolutize: function(element) { + Position.prepare(); + return Element.absolutize(element); + }, + + relativize: function(element) { + Position.prepare(); + return Element.relativize(element); + }, + + realOffset: Element.Methods.cumulativeScrollOffset, + + offsetParent: Element.Methods.getOffsetParent, + + page: Element.Methods.viewportOffset, + + clone: function(source, target, options) { + options = options || { }; + return Element.clonePosition(target, source, options); + } +}; + +/*--------------------------------------------------------------------------*/ + +if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){ + function iter(name) { + return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]"; + } + + instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? + function(element, className) { + className = className.toString().strip(); + var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); + return cond ? document._getElementsByXPath('.//*' + cond, element) : []; + } : function(element, className) { + className = className.toString().strip(); + var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); + if (!classNames && !className) return elements; + + var nodes = $(element).getElementsByTagName('*'); + className = ' ' + className + ' '; + + for (var i = 0, child, cn; child = nodes[i]; i++) { + if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || + (classNames && classNames.all(function(name) { + return !name.toString().blank() && cn.include(' ' + name + ' '); + })))) + elements.push(Element.extend(child)); + } + return elements; + }; + + return function(className, parentElement) { + return $(parentElement || document.body).getElementsByClassName(className); + }; +}(Element.Methods); + +/*--------------------------------------------------------------------------*/ + +Element.ClassNames = Class.create(); +Element.ClassNames.prototype = { + initialize: function(element) { + this.element = $(element); + }, + + _each: function(iterator) { + this.element.className.split(/\s+/).select(function(name) { + return name.length > 0; + })._each(iterator); + }, + + set: function(className) { + this.element.className = className; + }, + + add: function(classNameToAdd) { + if (this.include(classNameToAdd)) return; + this.set($A(this).concat(classNameToAdd).join(' ')); + }, + + remove: function(classNameToRemove) { + if (!this.include(classNameToRemove)) return; + this.set($A(this).without(classNameToRemove).join(' ')); + }, + + toString: function() { + return $A(this).join(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); + +/*--------------------------------------------------------------------------*/ diff --git a/docs/javascripts/pdoc/tabs.js b/docs/javascripts/pdoc/tabs.js new file mode 100644 index 0000000..7c97420 --- /dev/null +++ b/docs/javascripts/pdoc/tabs.js @@ -0,0 +1,506 @@ +/** + * @author Ryan Johnson + * @copyright 2008 PersonalGrid Corporation + * @package LivePipe UI + * @license MIT + * @url http://livepipe.net/core + * @require prototype.js + */ + +if(typeof(Control) == 'undefined') + Control = {}; + +var $proc = function(proc){ + return typeof(proc) == 'function' ? proc : function(){return proc}; +}; + +var $value = function(value){ + return typeof(value) == 'function' ? value() : value; +}; + +Object.Event = { + extend: function(object){ + object._objectEventSetup = function(event_name){ + this._observers = this._observers || {}; + this._observers[event_name] = this._observers[event_name] || []; + }; + object.observe = function(event_name,observer){ + if(typeof(event_name) == 'string' && typeof(observer) != 'undefined'){ + this._objectEventSetup(event_name); + if(!this._observers[event_name].include(observer)) + this._observers[event_name].push(observer); + }else + for(var e in event_name) + this.observe(e,event_name[e]); + }; + object.stopObserving = function(event_name,observer){ + this._objectEventSetup(event_name); + if(event_name && observer) + this._observers[event_name] = this._observers[event_name].without(observer); + else if(event_name) + this._observers[event_name] = []; + else + this._observers = {}; + }; + object.observeOnce = function(event_name,outer_observer){ + var inner_observer = function(){ + outer_observer.apply(this,arguments); + this.stopObserving(event_name,inner_observer); + }.bind(this); + this._objectEventSetup(event_name); + this._observers[event_name].push(inner_observer); + }; + object.notify = function(event_name){ + this._objectEventSetup(event_name); + var collected_return_values = []; + var args = $A(arguments).slice(1); + try{ + for(var i = 0; i < this._observers[event_name].length; ++i) + collected_return_values.push(this._observers[event_name][i].apply(this._observers[event_name][i],args) || null); + }catch(e){ + if(e == $break) + return false; + else + throw e; + } + return collected_return_values; + }; + if(object.prototype){ + object.prototype._objectEventSetup = object._objectEventSetup; + object.prototype.observe = object.observe; + object.prototype.stopObserving = object.stopObserving; + object.prototype.observeOnce = object.observeOnce; + object.prototype.notify = function(event_name){ + if(object.notify){ + var args = $A(arguments).slice(1); + args.unshift(this); + args.unshift(event_name); + object.notify.apply(object,args); + } + this._objectEventSetup(event_name); + var args = $A(arguments).slice(1); + var collected_return_values = []; + try{ + if(this.options && this.options[event_name] && typeof(this.options[event_name]) == 'function') + collected_return_values.push(this.options[event_name].apply(this,args) || null); + for(var i = 0; i < this._observers[event_name].length; ++i) + collected_return_values.push(this._observers[event_name][i].apply(this._observers[event_name][i],args) || null); + }catch(e){ + if(e == $break) + return false; + else + throw e; + } + return collected_return_values; + }; + } + } +}; + +/* Begin Core Extensions */ + +//Element.observeOnce +Element.addMethods({ + observeOnce: function(element,event_name,outer_callback){ + var inner_callback = function(){ + outer_callback.apply(this,arguments); + Element.stopObserving(element,event_name,inner_callback); + }; + Element.observe(element,event_name,inner_callback); + } +}); + +//mouseenter, mouseleave +//from http://dev.rubyonrails.org/attachment/ticket/8354/event_mouseenter_106rc1.patch +Object.extend(Event, (function() { + var cache = Event.cache; + + function getEventID(element) { + if (element._prototypeEventID) return element._prototypeEventID[0]; + arguments.callee.id = arguments.callee.id || 1; + return element._prototypeEventID = [++arguments.callee.id]; + } + + function getDOMEventName(eventName) { + if (eventName && eventName.include(':')) return "dataavailable"; + //begin extension + if(!Prototype.Browser.IE){ + eventName = { + mouseenter: 'mouseover', + mouseleave: 'mouseout' + }[eventName] || eventName; + } + //end extension + return eventName; + } + + function getCacheForID(id) { + return cache[id] = cache[id] || { }; + } + + function getWrappersForEventName(id, eventName) { + var c = getCacheForID(id); + return c[eventName] = c[eventName] || []; + } + + function createWrapper(element, eventName, handler) { + var id = getEventID(element); + var c = getWrappersForEventName(id, eventName); + if (c.pluck("handler").include(handler)) return false; + + var wrapper = function(event) { + if (!Event || !Event.extend || + (event.eventName && event.eventName != eventName)) + return false; + + Event.extend(event); + handler.call(element, event); + }; + + //begin extension + if(!(Prototype.Browser.IE) && ['mouseenter','mouseleave'].include(eventName)){ + wrapper = wrapper.wrap(function(proceed,event) { + var rel = event.relatedTarget; + var cur = event.currentTarget; + if(rel && rel.nodeType == Node.TEXT_NODE) + rel = rel.parentNode; + if(rel && rel != cur && !rel.descendantOf(cur)) + return proceed(event); + }); + } + //end extension + + wrapper.handler = handler; + c.push(wrapper); + return wrapper; + } + + function findWrapper(id, eventName, handler) { + var c = getWrappersForEventName(id, eventName); + return c.find(function(wrapper) { return wrapper.handler == handler }); + } + + function destroyWrapper(id, eventName, handler) { + var c = getCacheForID(id); + if (!c[eventName]) return false; + c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); + } + + function destroyCache() { + for (var id in cache) + for (var eventName in cache[id]) + cache[id][eventName] = null; + } + + if (window.attachEvent) { + window.attachEvent("onunload", destroyCache); + } + + return { + observe: function(element, eventName, handler) { + element = $(element); + var name = getDOMEventName(eventName); + + var wrapper = createWrapper(element, eventName, handler); + if (!wrapper) return element; + + if (element.addEventListener) { + element.addEventListener(name, wrapper, false); + } else { + element.attachEvent("on" + name, wrapper); + } + + return element; + }, + + stopObserving: function(element, eventName, handler) { + element = $(element); + var id = getEventID(element), name = getDOMEventName(eventName); + + if (!handler && eventName) { + getWrappersForEventName(id, eventName).each(function(wrapper) { + element.stopObserving(eventName, wrapper.handler); + }); + return element; + + } else if (!eventName) { + Object.keys(getCacheForID(id)).each(function(eventName) { + element.stopObserving(eventName); + }); + return element; + } + + var wrapper = findWrapper(id, eventName, handler); + if (!wrapper) return element; + + if (element.removeEventListener) { + element.removeEventListener(name, wrapper, false); + } else { + element.detachEvent("on" + name, wrapper); + } + + destroyWrapper(id, eventName, handler); + + return element; + }, + + fire: function(element, eventName, memo) { + element = $(element); + if (element == document && document.createEvent && !element.dispatchEvent) + element = document.documentElement; + + var event; + if (document.createEvent) { + event = document.createEvent("HTMLEvents"); + event.initEvent("dataavailable", true, true); + } else { + event = document.createEventObject(); + event.eventType = "ondataavailable"; + } + + event.eventName = eventName; + event.memo = memo || { }; + + if (document.createEvent) { + element.dispatchEvent(event); + } else { + element.fireEvent(event.eventType, event); + } + + return Event.extend(event); + } + }; +})()); + +Object.extend(Event, Event.Methods); + +Element.addMethods({ + fire: Event.fire, + observe: Event.observe, + stopObserving: Event.stopObserving +}); + +Object.extend(document, { + fire: Element.Methods.fire.methodize(), + observe: Element.Methods.observe.methodize(), + stopObserving: Element.Methods.stopObserving.methodize() +}); + +//mouse:wheel +(function(){ + function wheel(event){ + var delta; + // normalize the delta + if(event.wheelDelta) // IE & Opera + delta = event.wheelDelta / 120; + else if (event.detail) // W3C + delta =- event.detail / 3; + if(!delta) + return; + var custom_event = Event.element(event).fire('mouse:wheel',{ + delta: delta + }); + if(custom_event.stopped){ + Event.stop(event); + return false; + } + } + document.observe('mousewheel',wheel); + document.observe('DOMMouseScroll',wheel); +})(); + +/* End Core Extensions */ + +//from PrototypeUI +var IframeShim = Class.create({ + initialize: function() { + this.element = new Element('iframe',{ + style: 'position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);display:none', + src: 'javascript:void(0);', + frameborder: 0 + }); + $(document.body).insert(this.element); + }, + hide: function() { + this.element.hide(); + return this; + }, + show: function() { + this.element.show(); + return this; + }, + positionUnder: function(element) { + var element = $(element); + var offset = element.cumulativeOffset(); + var dimensions = element.getDimensions(); + this.element.setStyle({ + left: offset[0] + 'px', + top: offset[1] + 'px', + width: dimensions.width + 'px', + height: dimensions.height + 'px', + zIndex: element.getStyle('zIndex') - 1 + }).show(); + return this; + }, + setBounds: function(bounds) { + for(prop in bounds) + bounds[prop] += 'px'; + this.element.setStyle(bounds); + return this; + }, + destroy: function() { + if(this.element) + this.element.remove(); + return this; + } +}); + +/** + * @author Ryan Johnson + * @copyright 2008 PersonalGrid Corporation + * @package LivePipe UI + * @license MIT + * @url http://livepipe.net/control/tabs + * @require prototype.js, livepipe.js + */ + +/*global window, document, Prototype, $, $A, $H, $break, Class, Element, Event, Control */ + +if(typeof(Prototype) == "undefined") { + throw "Control.Tabs requires Prototype to be loaded."; } +if(typeof(Object.Event) == "undefined") { + throw "Control.Tabs requires Object.Event to be loaded."; } + +Control.Tabs = Class.create({ + initialize: function(tab_list_container,options){ + if(!$(tab_list_container)) { + throw "Control.Tabs could not find the element: " + tab_list_container; } + this.activeContainer = false; + this.activeLink = false; + this.containers = $H({}); + this.links = []; + Control.Tabs.instances.push(this); + this.options = { + beforeChange: Prototype.emptyFunction, + afterChange: Prototype.emptyFunction, + hover: false, + linkSelector: 'li a', + setClassOnContainer: false, + activeClassName: 'active', + defaultTab: 'first', + autoLinkExternal: true, + targetRegExp: /#(.+)$/, + showFunction: Element.show, + hideFunction: Element.hide + }; + Object.extend(this.options,options || {}); + (typeof(this.options.linkSelector == 'string') ? + $(tab_list_container).select(this.options.linkSelector) : + this.options.linkSelector($(tab_list_container)) + ).findAll(function(link){ + return (/^#/).exec((Prototype.Browser.WebKit ? decodeURIComponent(link.href) : link.href).replace(window.location.href.split('#')[0],'')); + }).each(function(link){ + this.addTab(link); + }.bind(this)); + this.containers.values().each(Element.hide); + if(this.options.defaultTab == 'first') { + this.setActiveTab(this.links.first()); + } else if(this.options.defaultTab == 'last') { + this.setActiveTab(this.links.last()); + } else { + this.setActiveTab(this.options.defaultTab); } + var targets = this.options.targetRegExp.exec(window.location); + if(targets && targets[1]){ + targets[1].split(',').each(function(target){ + this.setActiveTab(this.links.find(function(link){ + return link.key == target; + })); + }.bind(this)); + } + if(this.options.autoLinkExternal){ + $A(document.getElementsByTagName('a')).each(function(a){ + if(!this.links.include(a)){ + var clean_href = a.href.replace(window.location.href.split('#')[0],''); + if(clean_href.substring(0,1) == '#'){ + if(this.containers.keys().include(clean_href.substring(1))){ + $(a).observe('click',function(event,clean_href){ + this.setActiveTab(clean_href.substring(1)); + }.bindAsEventListener(this,clean_href)); + } + } + } + }.bind(this)); + } + }, + addTab: function(link){ + this.links.push(link); + link.key = link.getAttribute('href').replace(window.location.href.split('#')[0],'').split('#').last().replace(/#/,''); + var container = $(link.key); + if(!container) { + throw "Control.Tabs: #" + link.key + " was not found on the page."; } + this.containers.set(link.key,container); + link[this.options.hover ? 'onmouseover' : 'onclick'] = function(link){ + if(window.event) { + Event.stop(window.event); } + this.setActiveTab(link); + return false; + }.bind(this,link); + }, + setActiveTab: function(link){ + if(!link && typeof(link) == 'undefined') { + return; } + if(typeof(link) == 'string'){ + this.setActiveTab(this.links.find(function(_link){ + return _link.key == link; + })); + }else if(typeof(link) == 'number'){ + this.setActiveTab(this.links[link]); + }else{ + if(this.notify('beforeChange',this.activeContainer,this.containers.get(link.key)) === false) { + return; } + if(this.activeContainer) { + this.options.hideFunction(this.activeContainer); } + this.links.each(function(item){ + (this.options.setClassOnContainer ? $(item.parentNode) : item).removeClassName(this.options.activeClassName); + }.bind(this)); + (this.options.setClassOnContainer ? $(link.parentNode) : link).addClassName(this.options.activeClassName); + this.activeContainer = this.containers.get(link.key); + this.activeLink = link; + this.options.showFunction(this.containers.get(link.key)); + this.notify('afterChange',this.containers.get(link.key)); + } + }, + next: function(){ + this.links.each(function(link,i){ + if(this.activeLink == link && this.links[i + 1]){ + this.setActiveTab(this.links[i + 1]); + throw $break; + } + }.bind(this)); + }, + previous: function(){ + this.links.each(function(link,i){ + if(this.activeLink == link && this.links[i - 1]){ + this.setActiveTab(this.links[i - 1]); + throw $break; + } + }.bind(this)); + }, + first: function(){ + this.setActiveTab(this.links.first()); + }, + last: function(){ + this.setActiveTab(this.links.last()); + } +}); +Object.extend(Control.Tabs,{ + instances: [], + findByTabId: function(id){ + return Control.Tabs.instances.find(function(tab){ + return tab.links.find(function(link){ + return link.key == id; + }); + }); + } +}); +Object.Event.extend(Control.Tabs); diff --git a/docs/pipeline/add/index.html b/docs/pipeline/add/index.html new file mode 100644 index 0000000..07e665b --- /dev/null +++ b/docs/pipeline/add/index.html @@ -0,0 +1,125 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | pipeline.add + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ class method pipeline.add +

+ + + + +
+
+
+
+
+ +
pipeline.add( pipe ) → Object
+ + + +
    +
  • pipe (Mixed) The same pipe configuration options that are used in AeroGear.pipeline are available here
  • +
+ +

Add one or more pipes to the pipeline. Add can add pipes using the same options as when the pipeline was created by passing either a single pipe name, an array of pipe names or an object with one or more pipe configurations.

+ +
// Add a pipe to the previous created pipeline
+myPipeline.add( "tags" );
+ + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/docs/pipeline/index.html b/docs/pipeline/index.html new file mode 100644 index 0000000..9561029 --- /dev/null +++ b/docs/pipeline/index.html @@ -0,0 +1,136 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | pipeline + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ namespace pipeline +

+ + + + +
+
+

Description

+
+
+ +

Pipeline is a JavaScript library that provides a persistence API that is protocol agnostic and does not depend on any certain data model. Through the use of adapters, both provided and custom, user supplied, this library provides common methods like read, save and delete that will just work.

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + diff --git a/docs/pipeline/remove/index.html b/docs/pipeline/remove/index.html new file mode 100644 index 0000000..347a5a2 --- /dev/null +++ b/docs/pipeline/remove/index.html @@ -0,0 +1,125 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | pipeline.remove + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ class method pipeline.remove +

+ + + + +
+
+
+
+
+ +
pipeline.remove( pipe ) → Object
+ + + +
    +
  • pipe (Mixed) The same pipe configuration options that are used in AeroGear.pipeline are available here
  • +
+ +

Remove one or more pipes from the pipeline. Remove can remove pipes using the same options as when the pipeline was created by passing either a single pipe name, an array of pipe names or an object containing one or more pipes.

+ +
// Remove a pipe from the previous created pipeline
+myPipeline.remove( "tags" );
+ + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/docs/remove/index.html b/docs/remove/index.html new file mode 100644 index 0000000..a70c448 --- /dev/null +++ b/docs/remove/index.html @@ -0,0 +1,138 @@ + + + + + AeroGear.js v1.0.0.Alpha API documentation | remove + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + +

src code

+ + +

+ class method remove +

+ + + + +
+
+
+
+
+ +
.remove( pipe ) → Object
+ + + +
    +
  • pipe (Mixed) When passing a pipeConfiguration object to remove, the following items can be provided: +-- name - String (Required), the name that the pipe will later be referenced by +-- type - String (Optional, default - "rest"), the type of pipe as determined by the adapter used +-- recordId - String (Optional, default - "id"), the identifier used to denote the unique id for each record in the data associated with this pipe +-- settings - Object (Optional, default - {}), the settings to be passed to the adapter +-- Adapters may have a number of varying configuration settings.
  • +
+ +

Returns the full pipeline object with the specified pipe(s) removed

+ +
// Remove a single pipe using the default configuration (rest).
+aerogear.pipeline.remove( String pipeName );
+ // Remove multiple pipes all using the default configuration (rest).
+aerogear.pipeline.remove( Array[String] pipeNames );
+ // Remove one or more pipe configuration objects.
+aerogear.pipeline.remove( Object/Array[Object] pipeConfigurations )
+ +
Example
+ +
var pipeline = aerogear.pipeline.add( [ "projects", "tags", "tasks" ] );
+ // Remove a single pipe
+pipeline.remove( "tasks" );
+ // Remove multiple pipes using the default adapter
+pipeline().add( [ "tags", "projects" ] );
+ + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/docs/stylesheets/pdoc/api.css b/docs/stylesheets/pdoc/api.css new file mode 100644 index 0000000..2ff481b --- /dev/null +++ b/docs/stylesheets/pdoc/api.css @@ -0,0 +1,677 @@ +/* The "section" class implicitly needs a clearfix; adding it here for convenience. */ + +.clearfix:after, +.section:after { + content: "."; + display: block; + clear: both; + visibility: hidden; + line-height: 0; + height: 0; +} + +.clearfix, .section { + display: inline-block; +} + +html[xmlns] .clearfix, +html[xmlns] .section { + display: block; +} + +* html .clearfix, +* html .section { + height: 1%; +} + +span.hidden { display: none; } + +body { + font-family: Verdana, sans-serif; + font-size: 82.5%; + line-height: 1.5em; + margin: 0; + padding: 0; +} + + body * { + margin: 0; + padding: 0; + } + +h1, h2, h3, h4, h5, h6 { + font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; +} + +pre { + white-space: pre-wrap; /* CSS 3 */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ +} + +a img { + border: 0; +} + +ul, li { + list-style-type: none; +} + +ol, ul { + margin: 0 0 15px; +} + +code, pre { + font-family: "Panic Sans", "Bitstream Vera Sans Mono", Monaco, Consolas, Andale Mono, monospace; + font-size: 12px; +} + +#page a.img, +#page a.img:link, +#page a.img:visited { + border: 0; +} + +.content { + padding-left: 120px; + margin: 0 auto; +} + +#page { + margin: 0; + position: fixed; + top: 0; + bottom: 0; + right: 0; + left: 241px; + overflow-y: scroll; + overflow-x: auto; +} + +/* BREADCRUMBS */ + +ul.breadcrumbs { + margin-left: 120px; + padding-left: 120px; + list-style-type: none; +} + + ul.breadcrumbs li { + float: left; + list-style-type: none; + margin-left: 0; + margin-right: 0.4em; + } + +/* DEPRECATION */ + +#deprecated { + position: absolute; + right: 0; + top: 0; +} + +#deprecated img { + display: block; + border: 0; +} + +.menu-item a.deprecated { + text-decoration: line-through; + color: #999; +} + +/* PAGE CONTENT */ + +.page-content { + width: 715px; + margin: 0 0 30px 0; +} + + .page-content h2.page-title { + margin: 0 0 15px 120px; + line-height: 100%; + font-size: 27px; + letter-spacing: -1px; + color: #444; + } + + .page-introduction { + margin-left: 120px; + margin-bottom: 25px; + } + + .page-content a, + .page-content a:link { + color: #036; + border-bottom: 1px solid #036; + text-decoration: none; + } + + .page-content a:visited { + border-bottom: 1px solid #bbb; + } + + .page-content ul, + .page-content ol { + margin: 10px 0; + } + + .page-content li { + margin: 5px 0 8px 20px; + list-style-type: disc; + } + + .page-content p { + margin: 0 0 0.8em; + } + + .page-content code { + background-color: #f0f0f0; + border: 1px solid #ccc; + border-radius: 3px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + padding: 0 3px; + } + + .page-content pre { + color: #333; + background-color: #f0f0ff; + border: 1px solid #dde; + padding: 3px 5px; + margin: 0 0 1em; + } + + .page-content pre code { + background-color: transparent; + border: 0; + padding: 0; + line-height: 100%; + } + + + .page-content code { + + } + + .page-content h1 { + font-size: 27px; + color: #000; + margin: 1.0em 0 0.6em; + } + + .page-content h2 { + font-size: 23px; + color: #000; + margin: 1.0em 0 0.6em; + } + + .page-content h3 { + font-size: 20px; + color: #000; + margin: 1.0em 0 0.6em; + } + + .page-content h4 { + font-size: 17px; + color: #555; + margin: 1.0em 0 0.6em; + } + + .page-content h5 { + font-size: 15px; + color: #2a2a2a; + margin: 1.0em 0 0.6em; + } + + .page-content h6 { + font-size: 14px; + color: #000; + margin: 1.0em 0 0.6em; + } + +/* PAGE SECTIONS */ + +.section { + margin: 10px 0 15px; +} + + .section-title { + width: 110px; + float: left; + margin-right: 10px; + padding-right: 0; + padding-bottom: 10px; + text-align: right; + overflow: hidden; + } + + .section-title h3 { + color: #999; + font-size: 14px; + line-height: 110%; + margin-top: 3px; + padding-right: 10px; + padding-bottom: 5px; + } + + .section-content { + width: 595px; + float: left; + } + + +/* API STYLES */ + +.page-title .type { + display: block; + text-transform: uppercase; + font-size: 14px; + color: #aaa; +} + + +ul.section-list { + list-style-type: none; + margin-top: 0; +} + + ul.section-list li { + list-style-type: none; + margin: 0 0 15px; + } + + ul.section-list li h4 { + margin-top: 0; + } + +ul.method-list { + margin-top: 0; +} + + ul.method-list li { + float: left; + margin: 0 5px 3px 0; + list-style-type: none; + padding-bottom: 0; + } + + ul.method-list li a, + ul.method-list li a:link { + text-decoration: none; + border: 0; + } + +ul.method-details-list { + margin-top: 0; +} + + li.method-description { + margin: 0 0 2.0em; + list-style-type: none; + } + + .method-description h4 { + margin: 0 0 0.6em; + line-height: 90%; + } + + .method-description p { + margin: 0.8em 0; + } + + + .method-description .method-permalink a { + color: #aaa; + text-decoration: none; + border-bottom: 0; + font-size: 14px; +} + +h4.inherited { + clear: left; + font-size: 15px; + font-style: italic; +} + +pre.syntax { + margin-bottom: 5px; +} + +ul.argument-list { + font-size: 12px; + padding: 0; + margin: 0; +} + + ul.argument-list li { + line-height: 140%; + margin-top: 0px; + margin-bottom: 5px; + } + + ul.argument-list li code { + font-size: 11px; + } + + ul.argument-list .argument-name { + background-color: #eeffee; + border-color: #6b6; + } + + +/* SECTION ICONS */ + +.page-content .section .section-title h3 { + padding-right: 24px; + background-position: right 0; + background-repeat: no-repeat; +} + +.section-constructor .section-title h3 { + background-image: url(../../images/pdoc/constructor.png); +} + +.section-method-list .section-title h3 { + background-image: url(../../images/pdoc/method.png); +} + +.section-class_methods .section-title h3 { + background-image: url(../../images/pdoc/class_method.png); +} + +.section-class_properties .section-title h3 { + background-image: url(../../images/pdoc/class_property.png); +} + +.section-instance_methods .section-title h3 { + background-image: url(../../images/pdoc/instance_method.png); +} + +.section-instance_properties .section-title h3 { + background-image: url(../../images/pdoc/instance_property.png); +} + +.section-mixins .section-title h3 { + background-image: url(../../images/pdoc/mixin.png); +} + +.section-classes .section-title h3 { + background-image: url(../../images/pdoc/class.png); +} + +.section-namespaces .section-title h3 { + background-image: url(../../images/pdoc/namespace.png); +} + +.section-sections .section-title h3 { + background-image: url(../../images/pdoc/section.png); +} + +.section-utilities .section-title h3 { + background-image: url(../../images/pdoc/utility.png); +} + +.section-description .section-title h3 { + background-image: url(../../images/pdoc/description.png); +} + +.section-subclasses .section-title h3 { + background-image: url(../../images/pdoc/subclass.png); +} + +.section-superclass .section-title h3 { + background-image: url(../../images/pdoc/superclass.png); +} + +/* notes */ + +p.note, +p.alias, +p.related-to { + font-size: 11px; + line-height: 14px; + padding: 5px 20px 5px 60px; + background-repeat: no-repeat; + background-position: 20px 50%; + border: 1px solid #000; +} + +p.note { + background-color: #f0f0f4; + background-image: url(../../images/pdoc/information.png); + border-color: #69c; +} + +p.alias { + background-color: #fff6de; + background-image: url(../../images/pdoc/alias.png); + border-color: #cc9; +} + +p.related-to { + background-color: #f4f0f4; + background-image: url(../../images/pdoc/related_to.png); + border-color: #c9c; +} + +/* SIDEBAR */ + +#sidebar { + position: fixed; + top: 0; + bottom: 0; + left: 0; + width: 240px; + background: #fff; + font-size: 13px; +} + +#sidebar form.search-ribbon { + margin: 0; + height: 24px; + border-right: 1px solid #636363; + padding: 4px 0 3px; + border-bottom: 1px solid #587e93; + background: url(../../images/pdoc/search-background.png) repeat-x 0 0; + text-align: center; +} + +/* Keep these around for `Control.Tabs`. */ +.sidebar-tabs { display: none; } + +.menu-items ul { + margin: 0; +} + + .menu-items ul li { + list-style-type: none; + padding-left: 0; + margin-left: 0; + } + + .menu-items ul .menu-item a { + padding-left: 38px; + background-position: 16px 50%; + } + + .menu-items ul ul .menu-item a { + padding-left: 48px; + background-position: 26px 50%; + } + + .menu-items ul ul ul .menu-item a { + padding-left: 58px; + background-position: 36px 50%; + } + + .menu-items ul ul ul ul .menu-item a { + padding-left: 68px; + background-position: 46px 50%; + } + + + + .menu-item a, + .menu-item a:link { + display: block; + padding: 3px 10px 3px 28px; + background-position: 6px 50%; + background-repeat: no-repeat; + text-align: left; + text-decoration: none; + color: #333; + border-top: 1px solid #fff; + border-bottom: 1px solid #fff; + white-space: nowrap; + } + + .menu-item a:hover, + .menu-item a.highlighted, + #sidebar .highlighted a { + border-top: 1px solid #69f; + border-bottom: 1px solid #69f; + background-color: #f0f0ff; + } + + .menu-item a.current, + #sidebar .current a { + border-top: 1px solid #f0f0ff; + border-bottom: 1px solid #f0f0ff; + background-color: #f0f0ff; + } + + .menu-item a.current-parent, + #sidebar .current-parent a { + border-top: 1px solid #f0f0ff; + border-bottom: 1px solid #f0f0ff; + background-color: #f0f0ff; + } + + .menu-item a.class-method { + background-image: url(../../images/pdoc/class_method.png); + } + + .menu-item a.instance-method { + background-image: url(../../images/pdoc/instance_method.png); + } + + .menu-item a.class { + background-image: url(../../images/pdoc/class.png); + } + + .menu-item a.constructor { + background-image: url(../../images/pdoc/constructor.png); + } + + .menu-item a.class-property { + background-image: url(../../images/pdoc/class_property.png); + } + + .menu-item a.instance-property { + background-image: url(../../images/pdoc/instance_property.png); + } + + .menu-item a.namespace { + background-image: url(../../images/pdoc/namespace.png); + } + + .menu-item a.mixin { + background-image: url(../../images/pdoc/mixin.png); + } + + .menu-item a.utility { + background-image: url(../../images/pdoc/utility.png); + } + + .menu-item a.section { + margin: 0; + background-image: url(../../images/pdoc/section.png); + } + + #api_menu .menu-item a.section { + height: 22px; + font-weight: normal; + color: #a5a5a5; + margin-top: 0; + margin-bottom: 0; + border-top: 1px solid #000; + border-bottom: 1px solid #000; + background: url(../../images/pdoc/section-background.png) repeat-x 0 0; + } + + #api_menu .menu-item a.section:hover { + border-color: #69f; + color: #D8D9EA; + background-image: url(../../images/pdoc/selected-section-background.png); + } + +.menu-section { + margin-bottom: 1.0em; +} + +#menu_pane { + position: absolute; + top: 32px; + bottom: 0; + left: 0; + width: 239px; + border-right: 1px solid #636363; + overflow-y: scroll; + overflow-x: hidden; +} + +#search_pane { + width: 239px; + border-right: 1px solid #636363; + position: absolute; + top: 32px; + bottom: 0; + left: 0; +} + + #search_results { + margin: 0; + padding: 0; + overflow-y: scroll; + overflow-x: hidden; + position: absolute; + top: 0; + bottom: 0; + width: 239px; + } + +#search { + width: 200px; + padding: 2px 3px; +} + +input.ghosted { + font-style: italic; + color: #aaa; +} + + +/* FOOTER */ + +#footer { + color: #bbb; + width: 595px; + margin-left: 120px; + margin-top: 30px; + border-top: 1px solid #ccc; + font-size: 10px; + padding: 1em 0; +} + + #footer a, + #footer a:link { + color: #999; + } + +#src_code_href { + float: right; +} diff --git a/docs/stylesheets/pdoc/pygments.css b/docs/stylesheets/pdoc/pygments.css new file mode 100644 index 0000000..56dee28 --- /dev/null +++ b/docs/stylesheets/pdoc/pygments.css @@ -0,0 +1,62 @@ +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f8f8f8; } +.highlight .c { color: #408080; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #008000; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #BC7A00 } /* Comment.Preproc */ +.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #808080 } /* Generic.Output */ +.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0040D0 } /* Generic.Traceback */ +.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #008000 } /* Keyword.Pseudo */ +.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #B00040 } /* Keyword.Type */ +.highlight .m { color: #666666 } /* Literal.Number */ +.highlight .s { color: #BA2121 } /* Literal.String */ +.highlight .na { color: #7D9029 } /* Name.Attribute */ +.highlight .nb { color: #008000 } /* Name.Builtin */ +.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +.highlight .no { color: #880000 } /* Name.Constant */ +.highlight .nd { color: #AA22FF } /* Name.Decorator */ +.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #0000FF } /* Name.Function */ +.highlight .nl { color: #A0A000 } /* Name.Label */ +.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #19177C } /* Name.Variable */ +.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mf { color: #666666 } /* Literal.Number.Float */ +.highlight .mh { color: #666666 } /* Literal.Number.Hex */ +.highlight .mi { color: #666666 } /* Literal.Number.Integer */ +.highlight .mo { color: #666666 } /* Literal.Number.Oct */ +.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */ +.highlight .sc { color: #BA2121 } /* Literal.String.Char */ +.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #BA2121 } /* Literal.String.Double */ +.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */ +.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +.highlight .sx { color: #008000 } /* Literal.String.Other */ +.highlight .sr { color: #BB6688 } /* Literal.String.Regex */ +.highlight .s1 { color: #BA2121 } /* Literal.String.Single */ +.highlight .ss { color: #19177C } /* Literal.String.Symbol */ +.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #19177C } /* Name.Variable.Class */ +.highlight .vg { color: #19177C } /* Name.Variable.Global */ +.highlight .vi { color: #19177C } /* Name.Variable.Instance */ +.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/src/aerogear.core.js b/src/aerogear.core.js index 4b66a3b..e2ed104 100644 --- a/src/aerogear.core.js +++ b/src/aerogear.core.js @@ -1,5 +1,8 @@ -/* Need to add license, description, etc. */ - (function( window, undefined ) { + /** + * aerogear + * + * The aerogear namespace provides a way to encapsulate the library's properties and methods away from the global namespace + **/ var aerogear = window.aerogear = {}; })( this ); diff --git a/src/pipeline/adapters/rest.js b/src/pipeline/adapters/rest.js index 91e805b..4929106 100644 --- a/src/pipeline/adapters/rest.js +++ b/src/pipeline/adapters/rest.js @@ -1,12 +1,26 @@ -/* Need to add license, description, etc. */ - -// Rest Adapter (default) (function( aerogear, $, undefined ) { // TODO: Share this across entire lib function isArray( obj ) { return ({}).toString.call( obj ) === "[object Array]"; } + /** + * aerogear.pipeline.adapters.rest + * + * The REST adapter is the default type used when creating a new pipe. It uses jQuery.ajax to communicate with the server. By default, the RESTful endpoint used by this pipe is the app's current context, followed by the pipe name. For example, if the app is running on http://mysite.com/myApp, then a pipe named `tasks` would use http://mysite.com/myApp/tasks as its REST endpoint. + * + * `aerogear.pipeline.adapters.rest( pipeName [, recordId, ajaxSettings] ) -> Object` + * - pipeName (String): the name that will be used to reference this pipe + * - recordId (String): the record identifier specified when the pipe was created + * - ajaxSettings (Object) - an object used to pass additional parameters to jQuery.ajax + * + * When creating a new pipe using the REST adapter, the `settings` parameter to be supplied to pipeline is a hash of key/value pairs that will be supplied to the jQuery.ajax method. + * + * Once created, the new pipe will contain: + * - **recordId** - the record identifier specified when the pipe was created + * - **type** - the type specified when the pipe was created + * - **data** - an object used to store a client side copy of the data associated with this pipe + **/ aerogear.pipeline.adapters.rest = function( pipeName, recordId, ajaxSettings ) { ajaxSettings = $.extend({ // use the pipeName as the default rest endpoint @@ -20,6 +34,51 @@ recordId: recordId, type: "rest", data: null, + /** + * aerogear.pipeline.adapters.rest#read( [options] ) -> Object + * - options (Object): Additional options + * + * The options sent to read can include either of the following: + * - **data** - Object, a hash of key/value pairs that can be passed to the server as additional information for use when determining what data to return (Optional) + * - **ajax** - Object, a hash of key/value pairs that will be added to or override any AJAX settings set during creation of the pipe using this adapter (Optional) + * + * Returns a jqXHR which implements the Promise interface. See the [Defered Object](http://api.jquery.com/category/deferred-object/) reference on the jQuery site for more information. + * + * var myPipe = aerogear.pipeline( "tasks" ).pipes[ 0 ]; + * + * // Get a set of key/value pairs of all data on the server associated with this pipe + * var allData = myPipe.read(); + * + * // A data object can be passed to filter the data and in the case of REST, + * // this object is converted to query string parameters which the server can use. + * // The values would be determined by what the server is expecting + * var filteredData = myPipe.read({ + * data: { + * limit: 10, + * date: "2012-08-01" + * ... + * } + * }); + * + * Example returned data in allData: + * + * [ + * { + * id: 12345 + * title: "Do Something", + * date: "2012-08-01", + * ... + * }, + * { + * id: 67890 + * title: "Do Something Else", + * date: "2012-08-02", + * ... + * }, + * ... + * ] + * + **/ read: function( options ) { var that = this, data; @@ -49,6 +108,47 @@ return $.ajax( $.extend( {}, ajaxSettings, { type: "GET" }, options.ajax, { success: success } ) ); }, + /** + * aerogear.pipeline.adapters.rest#save( data[, options] ) -> Object + * - data (Object): For new data, this will be an object representing the data to be saved to the server. For updating data, a hash of key/value pairs one of which must be the `recordId` you set during creation of the pipe representing the identifier the server will use to update this record and then any other number of pairs representing the data. The data object is then stringified and passed to the server to be processed. + * - options (Object): An object with a single key/value pair, the key being `ajax`, that will be added to or override any ajax settings set during creation of the pipe using this adapter + * + * Save data asynchronously to the server. If this is a new object (doesn't have a record identifier provided by the server), the data is created on the server (POST) and then that record is sent back to the client including the new server-assigned id, otherwise, the data on the server is updated (PUT). + * + * Returns a jqXHR which implements the Promise interface. See the [Defered Object](http://api.jquery.com/category/deferred-object/) reference on the jQuery site for more information. + * + * var myPipe = aerogear.pipeline( "tasks" ).pipes[ 0 ]; + * + * // Store a new task + * myPipe.save({ + * title: "Created Task", + * date: "2012-07-13", + * ... + * }); + * + * // Pass a success and error callback, in this case using the REST pipe and jQuery.ajax so the functions take the same parameters. + * myPipe.save({ + * title: "Another Created Task", + * date: "2012-07-13", + * ... + * }, + * { + * ajax: { + * success: function( data, textStatus, jqXHR ) { + * console.log( "Success" ); + * }, + * error: function( jqXHR, textStatus, errorThrown ) { + * console.log( "Error" ); + * } + * } + * }); + * + * // Update an existing piece of data + * var toUpdate = myPipe.data[ 0 ]; + * toUpdate.data.title = "Updated Task"; + * myPipe.save( toUpdate ); + * + **/ save: function( data, options ) { var that = this, type, @@ -101,6 +201,44 @@ )); }, + /** + * aerogear.pipeline.adapters.rest#remove( toRemove [, options] ) -> Object + * - toRemove (Mixed): A variety of objects can be passed to remove to specify the item to remove as illustrated below + * - options (Object): An object with a single key/value pair, the key being `ajax`, that will be added to or override any ajax settings set during creation of the pipe using this adapter + * + * Remove data asynchronously from the server. Passing nothing will inform the server to remove all data at this pipe's rest endpoint. + * + * Returns a jqXHR which implements the Promise interface. See the [Defered Object](http://api.jquery.com/category/deferred-object/) reference on the jQuery site for more information. + * + * var myPipe = aerogear.pipeline( "tasks" ).pipes[ 0 ]; + * + * // Store a new task + * myPipe.save({ + * title: "Created Task" + * }); + * + * // Store another new task + * myPipe.save({ + * title: "Another Created Task" + * }); + * + * // Store one more new task + * myPipe.save({ + * title: "And Another Created Task" + * }); + * + * // Remove a particular item from the server by its id + * var toRemove = myPipe.data[ 0 ]; + * myPipe.remove( toRemove.id ); + * + * // Remove an item from the server using the data object + * toRemove = myPipe.data[ 0 ]; + * myPipe.remove( toRemove ); + * + * // Delete all remaining data from the server associated with this pipe + * myPipe.delete(); + * + **/ remove: function( toRemove, options ) { var that = this, delId = 0, diff --git a/src/pipeline/aerogear.pipeline.js b/src/pipeline/aerogear.pipeline.js index 328cea8..9ba9306 100644 --- a/src/pipeline/aerogear.pipeline.js +++ b/src/pipeline/aerogear.pipeline.js @@ -1,79 +1,163 @@ -/* Need to add license, description, etc. */ - -// AeroGear Pipeline (function( aerogear, undefined ) { function isArray( obj ) { return ({}).toString.call( obj ) === "[object Array]"; } + /** + * aerogear.pipeline + * + * The aerogear.pipeline namespace provides a persistence API that is protocol agnostic and does not depend on any certain data model. Through the use of adapters, both provided and custom, user supplied, this library provides common methods like read, save and delete that will just work. + * + * `aerogear.pipeline( pipe ) -> Object` + * - **pipe** (Mixed) When passing a pipeConfiguration object to `add`, the following items can be provided: + * - **name** - String (Required), the name that the pipe will later be referenced by + * - **type** - String (Optional, default - "rest"), the type of pipe as determined by the adapter used + * - **recordId** - String (Optional, default - "id"), the identifier used to denote the unique id for each record in the data associated with this pipe + * - **settings** - Object (Optional, default - {}), the settings to be passed to the adapter + * - Adapters may have a number of varying configuration settings. + * + * Returns an object representing a collection of server connections (pipes) and their corresponding data models. This object provides a standard way to communicate with the server no matter the data format or transport expected. + * + * ##### Example + * + * // Create a single pipe using the default adapter + * var pipeline = aerogear.pipeline( "tasks" ); + * + * // Create multiple pipes using the default adapter + * var myPipeline = aerogear.pipeline( [ "tasks", "projects" ] ); + **/ aerogear.pipeline = function( pipe ) { - var pipeline = {}; - - pipeline.add = function( pipe ) { - var i, - current, - // initialize pipes if not already - pipes = pipeline.pipes = pipeline.pipes || {}; + var pipeline = { + pipes: {}, + /** + * aerogear.pipeline#add( pipe ) -> Object + * - pipe (Mixed): This can be a variety of types specifying how to create the pipe as illustrated below + * + * When passing a pipeConfiguration object to `add`, the following items can be provided: + * - **name** - String (Required), the name that the pipe will later be referenced by + * - **type** - String (Optional, default - "rest"), the type of pipe as determined by the adapter used + * - **recordId** - String (Optional, default - "id"), the identifier used to denote the unique id for each record in the data associated with this pipe + * - **settings** - Object (Optional, default - {}), the settings to be passed to the adapter + * - Adapters may have a number of varying configuration settings. + * + * Returns the full pipeline object with the new pipe(s) added + * + * // Add a single pipe using the default configuration (rest). + * aerogear.pipeline.add( String pipeName ); + * + * // Add multiple pipes all using the default configuration (rest). + * aerogear.pipeline.add( Array[String] pipeNames ); + * + * // Add one or more pipe configuration objects. + * aerogear.pipeline.add( Object/Array[Object] pipeConfigurations ) + * + * The default pipe type is `rest`. You may also use one of the other provided types or create your own. + * + * ##### Example + * + * var pipeline = aerogear.pipeline(); + * + * // Add a single pipe using the default adapter + * pipeline = pipeline.add( "tasks" ); + * + * // Add multiple pipes using the default adapter + * pipeline = pipeline.add( [ "tags", "projects" ] ); + * + **/ + add: function( pipe ) { + var i, + current; - if ( typeof pipe === "string" ) { - // pipe is a string so use - pipes[ pipe ] = aerogear.pipeline.adapters.rest( pipe, "id" ); - } else if ( isArray( pipe ) ) { - // pipe is an array so loop through each item in the array - for ( i = 0; i < pipe.length; i++ ) { - current = pipe[ i ]; + if ( !pipe ) { + return this; + } else if ( typeof pipe === "string" ) { + // pipe is a string so use + this.pipes[ pipe ] = aerogear.pipeline.adapters.rest( pipe, "id" ); + } else if ( isArray( pipe ) ) { + // pipe is an array so loop through each item in the array + for ( i = 0; i < pipe.length; i++ ) { + current = pipe[ i ]; - if ( typeof current === "string" ) { - pipes[ current ] = aerogear.pipeline.adapters.rest( current ); + if ( typeof current === "string" ) { + this.pipes[ current ] = aerogear.pipeline.adapters.rest( current ); + } else { + this.pipes[ current.name ] = aerogear.pipeline.adapters[ current.type || "rest" ]( current.name, current.recordId || "id", current.settings || {} ); + } + } } else { - pipes[ current.name ] = aerogear.pipeline.adapters[ current.type || "rest" ]( current.name, current.recordId || "id", current.settings || {} ); + // pipe is an object so use that signature + this.pipes[ pipe.name ] = aerogear.pipeline.adapters[ pipe.type || "rest" ]( pipe.name, pipe.recordId || "id", pipe.settings || {} ); } - } - } else if ( pipe ) { - // pipe is an object so use that signature - pipes[ pipe.name ] = aerogear.pipeline.adapters[ pipe.type || "rest" ]( pipe.name, pipe.recordId || "id", pipe.settings || {} ); - } else { - // pipe is undefined so throw error - throw "aerogear.pipeline: pipe is undefined"; - } - - pipeline.pipes = pipes; - - return pipeline; - }; - pipeline.remove = function( pipe ) { - var i, - current, - // initialize pipes if not already - pipes = pipeline.pipes = pipeline.pipes || {}; + return this; + }, + /** + * aerogear.pipeline#remove( pipe ) -> Object + * - pipe (Mixed): This can be a variety of types specifying the pipe to remove as illustrated below + * + * When passing a pipeConfiguration object to `remove`, the following items can be provided: + * - **name** - String (Required), the name that the pipe will later be referenced by + * - **type** - String (Optional, default - "rest"), the type of pipe as determined by the adapter used + * - **recordId** - String (Optional, default - "id"), the identifier used to denote the unique id for each record in the data associated with this pipe + * - **settings** - Object (Optional, default - {}), the settings to be passed to the adapter + * - Adapters may have a number of varying configuration settings. + * + * Returns the full pipeline object with the specified pipe(s) removed + * + * // Remove a single pipe using the default configuration (rest). + * aerogear.pipeline.remove( String pipeName ); + * + * // Remove multiple pipes all using the default configuration (rest). + * aerogear.pipeline.remove( Array[String] pipeNames ); + * + * // Remove one or more pipe configuration objects. + * aerogear.pipeline.remove( Object/Array[Object] pipeConfigurations ) + * + * ##### Example + * + * var pipeline = aerogear.pipeline( [ "projects", "tags", "tasks" ] ); + * + * // Remove a single pipe + * pipeline.remove( "tasks" ); + * + * // Remove multiple pipes using the default adapter + * pipeline.remove( [ "tags", "projects" ] ); + * + **/ + remove: function( pipe ) { + var i, + current; - if ( typeof pipe === "string" ) { - // pipe is a string so use - delete pipes[ pipe ]; - } else if ( isArray( pipe ) ) { - // pipe is an array so loop through each item in the array - for ( i = 0; i < pipe.length; i++ ) { - current = pipe[ i ]; + if ( typeof pipe === "string" ) { + // pipe is a string so use + delete this.pipes[ pipe ]; + } else if ( isArray( pipe ) ) { + // pipe is an array so loop through each item in the array + for ( i = 0; i < pipe.length; i++ ) { + current = pipe[ i ]; - if ( typeof current === "string" ) { - delete pipes[ current ]; - } else { - delete pipes[ current.name ]; + if ( typeof current === "string" ) { + delete this.pipes[ current ]; + } else { + delete this.pipes[ current.name ]; + } + } + } else if ( pipe ) { + // pipe is an object so use that signature + delete this.pipes[ pipe.name ]; } - } - } else if ( pipe ) { - // pipe is an object so use that signature - delete pipes[ pipe.name ]; - } - pipeline.pipes = pipes; - - return pipeline; - }; + return this; + } + }; return pipeline.add( pipe ); }; + /** + * aerogear.pipeline.adapters + * + * The adapters object is provided so that adapters can be added to the aerogear.pipeline namespace dynamically and still be accessible to the add method + **/ aerogear.pipeline.adapters = {}; })( aerogear );