You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xap-commits@incubator.apache.org by jm...@apache.org on 2006/06/27 22:49:06 UTC
svn commit: r417618 [6/19] - in /incubator/xap/trunk/src/dojo/src: ./ lfx/
logging/ rpc/ selection/ storage/ string/ text/ undo/ uri/ uuid/ widget/
widget/html/ widget/svg/ widget/templates/ widget/templates/buttons/
widget/templates/images/ widget/tem...
Added: incubator/xap/trunk/src/dojo/src/rpc/RpcService.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/rpc/RpcService.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/rpc/RpcService.js (added)
+++ incubator/xap/trunk/src/dojo/src/rpc/RpcService.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,116 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.rpc.RpcService");
+dojo.require("dojo.io.*");
+dojo.require("dojo.json");
+dojo.require("dojo.lang.func");
+dojo.require("dojo.rpc.Deferred");
+
+dojo.rpc.RpcService = function(url){
+ // summary
+ // constructor for rpc base class
+ if(url){
+ this.connect(url);
+ }
+}
+
+dojo.lang.extend(dojo.rpc.RpcService, {
+
+ strictArgChecks: true,
+ serviceUrl: "",
+
+ parseResults: function(obj){
+ // summary
+ // parse the results coming back from an rpc request.
+ // this base implementation, just returns the full object
+ // subclasses should parse and only return the actual results
+ return obj;
+ },
+
+ errorCallback: function(/* dojo.rpc.Deferred */ deferredRequestHandler){
+ // summary
+ // create callback that calls the Deferres errback method
+ return function(type, obj, e){
+ deferredRequestHandler.errback(e);
+ }
+ },
+
+ resultCallback: function(/* dojo.rpc.Deferred */ deferredRequestHandler){
+ // summary
+ // create callback that calls the Deferred's callback method
+ var tf = dojo.lang.hitch(this,
+ function(type, obj, e){
+ var results = this.parseResults(obj||e);
+ deferredRequestHandler.callback(results);
+ }
+ );
+ return tf;
+ },
+
+
+ generateMethod: function(/*string*/ method, /*array*/ parameters, /*string*/ url){
+ // summary
+ // generate the local bind methods for the remote object
+ return dojo.lang.hitch(this, function(){
+ var deferredRequestHandler = new dojo.rpc.Deferred();
+
+ // if params weren't specified, then we can assume it's varargs
+ if( (this.strictArgChecks) &&
+ (parameters != null) &&
+ (arguments.length != parameters.length)
+ ){
+ // put error stuff here, no enough params
+ dojo.raise("Invalid number of parameters for remote method.");
+ } else {
+ this.bind(method, arguments, deferredRequestHandler, url);
+ }
+
+ return deferredRequestHandler;
+ });
+ },
+
+ processSmd: function(/*json*/ object){
+ // summary
+ // callback method for reciept of a smd object. Parse the smd and
+ // generate functions based on the description
+ dojo.debug("RpcService: Processing returned SMD.");
+ if(object.methods){
+ dojo.lang.forEach(object.methods, function(m){
+ if(m && m["name"]){
+ dojo.debug("RpcService: Creating Method: this.", m.name, "()");
+ this[m.name] = this.generateMethod( m.name,
+ m.parameters,
+ m["url"]||m["serviceUrl"]||m["serviceURL"]);
+ if(dojo.lang.isFunction(this[m.name])){
+ dojo.debug("RpcService: Successfully created", m.name, "()");
+ }else{
+ dojo.debug("RpcService: Failed to create", m.name, "()");
+ }
+ }
+ }, this);
+ }
+
+ this.serviceUrl = object.serviceUrl||object.serviceURL;
+ dojo.debug("RpcService: Dojo RpcService is ready for use.");
+ },
+
+ connect: function(/*String*/ smdUrl){
+ // summary
+ // connect to a remote url and retrieve a smd object
+ dojo.debug("RpcService: Attempting to load SMD document from:", smdUrl);
+ dojo.io.bind({
+ url: smdUrl,
+ mimetype: "text/json",
+ load: dojo.lang.hitch(this, function(type, object, e){ return this.processSmd(object); }),
+ sync: true
+ });
+ }
+});
Propchange: incubator/xap/trunk/src/dojo/src/rpc/RpcService.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/xap/trunk/src/dojo/src/rpc/YahooService.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/rpc/YahooService.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/rpc/YahooService.js (added)
+++ incubator/xap/trunk/src/dojo/src/rpc/YahooService.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,55 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.rpc.YahooService");
+dojo.require("dojo.rpc.RpcService");
+dojo.require("dojo.rpc.JsonService");
+dojo.require("dojo.json");
+dojo.require("dojo.uri.*");
+dojo.require("dojo.io.ScriptSrcIO");
+
+dojo.rpc.YahooService = function(appId){
+ this.appId = appId;
+ if(!appId){
+ this.appId = "dojotoolkit";
+ dojo.debug( "please initializae the YahooService class with your own",
+ "application ID. Using the default may cause problems during",
+ "deployment of your application");
+ }
+ this.connect(dojo.uri.dojoUri("src/rpc/yahoo.smd"));
+ this.scrictArgChecks = false;
+}
+
+dojo.inherits(dojo.rpc.YahooService, dojo.rpc.JsonService);
+
+dojo.lang.extend(dojo.rpc.YahooService, {
+ strictArgChecks: false,
+
+ bind: function(method, parameters, deferredRequestHandler, url){
+ var params = parameters;
+ if( (dojo.lang.isArrayLike(parameters))&&
+ (parameters.length == 1)){
+ params = parameters[0];
+ }
+ params.output = "json";
+ params.appid= this.appId;
+ dojo.io.bind({
+ url: url||this.serviceUrl,
+ transport: "ScriptSrcTransport",
+ // FIXME: need to get content interpolation fixed
+ content: params,
+ jsonParamName: "callback",
+ mimetype: "text/json",
+ load: this.resultCallback(deferredRequestHandler),
+ error: this.errorCallback(deferredRequestHandler),
+ preventCache: true
+ });
+ }
+});
Propchange: incubator/xap/trunk/src/dojo/src/rpc/YahooService.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/xap/trunk/src/dojo/src/rpc/__package__.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/rpc/__package__.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/rpc/__package__.js (added)
+++ incubator/xap/trunk/src/dojo/src/rpc/__package__.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,14 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.kwCompoundRequire({
+ common: ["dojo.rpc.JsonService", false, false]
+});
+dojo.provide("dojo.rpc.*");
Propchange: incubator/xap/trunk/src/dojo/src/rpc/__package__.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/xap/trunk/src/dojo/src/rpc/yahoo.smd
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/rpc/yahoo.smd?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/rpc/yahoo.smd (added)
+++ incubator/xap/trunk/src/dojo/src/rpc/yahoo.smd Tue Jun 27 15:48:54 2006
@@ -0,0 +1,263 @@
+{
+ "SMDVersion":".1",
+ "objectName":"yahoo",
+ "serviceType":"JSON-P",
+ "methods":[
+ //
+ // MAPS
+ //
+ {
+ // http://developer.yahoo.com/maps/rest/V1/mapImage.html
+ "name":"mapImage",
+ "serviceURL": "http://api.local.yahoo.com/MapsService/V1/mapImage",
+ "parameters":[
+ { "name":"street", "type":"STRING" },
+ { "name":"city", "type":"STRING" },
+ { "name":"zip", "type":"INTEGER" },
+ { "name":"location", "type":"STRING" },
+ { "name":"longitude", "type":"FLOAT" },
+ { "name":"latitude", "type":"FLOAT" },
+ { "name":"image_type", "type":"STRING" },
+ { "name":"image_width", "type":"INTEGER" },
+ { "name":"image_height", "type":"INTEGER" },
+ { "name":"zoom", "type":"INTEGER" },
+ { "name":"radius", "type":"INTEGER" }
+ ]
+ },
+ {
+ // http://developer.yahoo.com/traffic/rest/V1/index.html
+ "name":"trafficData",
+ "serviceURL": "http://api.local.yahoo.com/MapsService/V1/trafficData",
+ "parameters":[
+ { "name":"street", "type":"STRING" },
+ { "name":"city", "type":"STRING" },
+ { "name":"zip", "type":"INTEGER" },
+ { "name":"location", "type":"STRING" },
+ { "name":"longitude", "type":"FLOAT" },
+ { "name":"latitude", "type":"FLOAT" },
+ { "name":"severity", "type":"INTEGER" },
+ { "name":"include_map", "type":"INTEGER" },
+ { "name":"image_type", "type":"STRING" },
+ { "name":"image_width", "type":"INTEGER" },
+ { "name":"image_height", "type":"INTEGER" },
+ { "name":"zoom", "type":"INTEGER" },
+ { "name":"radius", "type":"INTEGER" }
+ ]
+ },
+ /*
+ // Yahoo's geocoding service is f'd for JSON and Y! advises that it
+ // may not be returning
+ {
+ // http://developer.yahoo.com/maps/rest/V1/geocode.html
+ "name":"geocode",
+ "serviceURL": "http://api.local.yahoo.com/MapsService/V1/geocode",
+ "parameters":[
+ { "name":"street", "type":"STRING" },
+ { "name":"city", "type":"STRING" },
+ { "name":"zip", "type":"INTEGER" },
+ { "name":"location", "type":"STRING" }
+ ]
+ },
+ */
+ //
+ // LOCAL SEARCH
+ //
+ {
+ // http://developer.yahoo.com/search/local/V3/localSearch.html
+ "name":"localSearch",
+ "serviceURL": "http://api.local.yahoo.com/LocalSearchService/V3/localSearch",
+ "parameters":[
+ { "name":"street", "type":"STRING" },
+ { "name":"city", "type":"STRING" },
+ { "name":"zip", "type":"INTEGER" },
+ { "name":"location", "type":"STRING" },
+ { "name":"listing_id", "type":"STRING" },
+ { "name":"sort", "type":"STRING" }, // "relevence", "title", "distance", or "rating"
+ { "name":"start", "type":"INTEGER" },
+ { "name":"radius", "type":"FLOAT" },
+ { "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+ { "name":"longitude", "type":"FLOAT" },
+ { "name":"latitude", "type":"FLOAT" },
+ { "name":"category", "type":"INTEGER" },
+ { "name":"omit_category", "type":"INTEGER" },
+ { "name":"minimum_rating", "type":"INTEGER" }
+ ]
+ },
+ //
+ // WEB SEARCH
+ //
+
+ // NOTE: contextual search and term extraction are not stubbed out
+ // becaues I'm not sure if we can POST via script src inclusion method
+ {
+ // http://developer.yahoo.com/search/web/V1/webSearch.html
+ "name":"webSearch",
+ "serviceURL": "http://api.search.yahoo.com/WebSearchService/V1/webSearch",
+ "parameters":[
+ { "name":"query", "type":"STRING" },
+ { "name":"type", "type":"STRING" }, // defaults to "all"
+ { "name":"region", "type":"STRING" }, // defaults to "us"
+ { "name":"results", "type":"INTEGER" }, // defaults to 10
+ { "name":"start", "type":"INTEGER" }, // defaults to 1
+ { "name":"format", "type":"STRING" }, // defaults to "any", can be "html", "msword", "pdf", "ppt", "rst", "txt", or "xls"
+ { "name":"adult_ok", "type":"INTEGER" }, // defaults to null
+ { "name":"similar_ok", "type":"INTEGER" }, // defaults to null
+ { "name":"language", "type":"STRING" }, // defaults to null
+ { "name":"country", "type":"STRING" }, // defaults to null
+ { "name":"site", "type":"STRING" }, // defaults to null
+ { "name":"subscription", "type":"STRING" }, // defaults to null
+ { "name":"license", "type":"STRING" } // defaults to "any"
+ ]
+ },
+ {
+ // http://developer.yahoo.com/search/web/V1/spellingSuggestion.html
+ "name":"spellingSuggestion",
+ "serviceURL": "http://api.search.yahoo.com/WebSearchService/V1/spellingSuggestion",
+ "parameters":[ { "name":"query", "type":"STRING" } ]
+ },
+ {
+ // http://developer.yahoo.com/search/web/V1/relatedSuggestion.html
+ "name":"spellingSuggestion",
+ "serviceURL": "http://api.search.yahoo.com/WebSearchService/V1/relatedSuggestion",
+ "parameters":[
+ { "name":"query", "type":"STRING" },
+ { "name":"results", "type":"INTEGER" } // 1-50, defaults to 10
+ ]
+ },
+ //
+ // IMAGE SEARCH
+ //
+ {
+ // http://developer.yahoo.com/search/image/V1/imageSearch.html
+ "name":"imageSearch",
+ "serviceURL": "http://api.search.yahoo.com/ImageSearchService/V1/imageSearch",
+ "parameters":[
+ { "name":"query", "type":"STRING" },
+ { "name":"type", "type":"STRING" }, // defaults to "all", can by "any" or "phrase"
+ { "name":"results", "type":"INTEGER" }, // defaults to 10
+ { "name":"start", "type":"INTEGER" }, // defaults to 1
+ { "name":"format", "type":"STRING" }, // defaults to "any", can be "bmp", "gif", "jpeg", or "png"
+ { "name":"adult_ok", "type":"INTEGER" }, // defaults to null
+ { "name":"coloration", "type":"STRING" }, // "any", "color", or "bw"
+ { "name":"site", "type":"STRING" } // defaults to null
+ ]
+ },
+ //
+ // SITE EXPLORER
+ //
+ {
+ // http://developer.yahoo.com/search/siteexplorer/V1/inlinkData.html
+ "name":"inlinkData",
+ "serviceURL": "http://api.search.yahoo.com/SiteExplorerService/V1/inlinkData",
+ "parameters":[
+ { "name":"query", "type":"STRING" },
+ { "name":"type", "type":"STRING" }, // defaults to "all", can by "any" or "phrase"
+ { "name":"entire_site", "type":"INTEGER" }, // defaults to null
+ { "name":"omit_inlinks", "type":"STRING" }, // "domain" or "subdomain", defaults to null
+ { "name":"results", "type":"INTEGER" }, // defaults to 50
+ { "name":"start", "type":"INTEGER" }, // defaults to 1
+ { "name":"site", "type":"STRING" } // defaults to null
+ ]
+ },
+ {
+ // http://developer.yahoo.com/search/siteexplorer/V1/pageData.html
+ "name":"pageData",
+ "serviceURL": "http://api.search.yahoo.com/SiteExplorerService/V1/pageData",
+ "parameters":[
+ { "name":"query", "type":"STRING" },
+ { "name":"type", "type":"STRING" }, // defaults to "all", can by "any" or "phrase"
+ { "name":"domain_only", "type":"INTEGER" }, // defaults to null
+ { "name":"results", "type":"INTEGER" }, // defaults to 50
+ { "name":"start", "type":"INTEGER" }, // defaults to 1
+ { "name":"site", "type":"STRING" } // defaults to null
+ ]
+ },
+ //
+ // MUSIC SEARCH
+ //
+ {
+ // http://developer.yahoo.com/search/audio/V1/artistSearch.html
+ "name":"artistSearch",
+ "serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/artistSearch",
+ "parameters":[
+ { "name":"artist", "type":"STRING" },
+ { "name":"artistid", "type":"STRING" },
+ { "name":"type", "type":"STRING" }, // "all", "any", or "phrase"
+ { "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+ { "name":"start", "type":"INTEGER" } // defaults to 1
+ ]
+ },
+ {
+ // http://developer.yahoo.com/search/audio/V1/albumSearch.html
+ "name":"albumSearch",
+ "serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/albumSearch",
+ "parameters":[
+ { "name":"artist", "type":"STRING" },
+ { "name":"artistid", "type":"STRING" },
+ { "name":"album", "type":"STRING" },
+ { "name":"type", "type":"STRING" }, // "all", "any", or "phrase"
+ { "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+ { "name":"start", "type":"INTEGER" } // defaults to 1
+ ]
+ },
+ {
+ // http://developer.yahoo.com/search/audio/V1/songSearch.html
+ "name":"songSearch",
+ "serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/songSearch",
+ "parameters":[
+ { "name":"artist", "type":"STRING" },
+ { "name":"artistid", "type":"STRING" },
+ { "name":"album", "type":"STRING" },
+ { "name":"albumid", "type":"STRING" },
+ { "name":"song", "type":"STRING" },
+ { "name":"songid", "type":"STRING" },
+ { "name":"type", "type":"STRING" }, // "all", "any", or "phrase"
+ { "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+ { "name":"start", "type":"INTEGER" } // defaults to 1
+ ]
+ },
+ {
+ // http://developer.yahoo.com/search/audio/V1/songDownloadLocation.html
+ "name":"songDownloadLocation",
+ "serviceURL": "http://api.search.yahoo.com/AudioSearchService/V1/songDownloadLocation",
+ "parameters":[
+ { "name":"songid", "type":"STRING" },
+ // "source" can contain:
+ // audiolunchbox artistdirect buymusic dmusic
+ // emusic epitonic garageband itunes yahoo
+ // livedownloads mp34u msn musicmatch mapster passalong
+ // rhapsody soundclick theweb
+ { "name":"source", "type":"STRING" },
+ { "name":"results", "type":"INTEGER" }, // 1-50, defaults to 10
+ { "name":"start", "type":"INTEGER" } // defaults to 1
+ ]
+ },
+ //
+ // NEWS SEARCH
+ //
+ {
+ // http://developer.yahoo.com/search/news/V1/newsSearch.html
+ "name":"newsSearch",
+ "serviceURL": "http://api.search.yahoo.com/NewsSearchService/V1/newsSearch",
+ "parameters":[
+ { "name":"query", "type":"STRING" },
+ { "name":"type", "type":"STRING" }, // defaults to "all"
+ { "name":"results", "type":"INTEGER" }, // defaults to 10
+ { "name":"start", "type":"INTEGER" }, // defaults to 1
+ { "name":"sort", "type":"STRING" }, // "rank" or "date"
+ { "name":"language", "type":"STRING" }, // defaults to null
+ { "name":"site", "type":"STRING" } // defaults to null
+ ]
+ }
+ /*
+ {
+ //
+ "name":"",
+ "serviceURL": "",
+ "parameters":[
+ { "name":"street", "type":"STRING" },
+ ]
+ }
+ */
+ ]
+}
Added: incubator/xap/trunk/src/dojo/src/selection/Selection.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/selection/Selection.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/selection/Selection.js (added)
+++ incubator/xap/trunk/src/dojo/src/selection/Selection.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,425 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.selection.Selection");
+dojo.require("dojo.lang.array");
+dojo.require("dojo.lang.func");
+dojo.require("dojo.math");
+
+dojo.selection.Selection = function(items, isCollection) {
+ this.items = [];
+ this.selection = [];
+ this._pivotItems = [];
+ this.clearItems();
+
+ if(items) {
+ if(isCollection) {
+ this.setItemsCollection(items);
+ } else {
+ this.setItems(items);
+ }
+ }
+}
+dojo.lang.extend(dojo.selection.Selection, {
+ items: null, // items to select from, order matters for growable selections
+
+ selection: null, // items selected, aren't stored in order (see sorted())
+ lastSelected: null, // last item selected
+
+ allowImplicit: true, // if true, grow selection will start from 0th item when nothing is selected
+ length: 0, // number of *selected* items
+
+ // if true, the selection is treated as an in-order and can grow by ranges, not just by single item
+ isGrowable: true,
+
+ _pivotItems: null, // stack of pivot items
+ _pivotItem: null, // item we grow selections from, top of stack
+
+ // event handlers
+ onSelect: function(item) {},
+ onDeselect: function(item) {},
+ onSelectChange: function(item, selected) {},
+
+ _find: function(item, inSelection) {
+ if(inSelection) {
+ return dojo.lang.find(item, this.selection);
+ } else {
+ return dojo.lang.find(item, this.items);
+ }
+ },
+
+ isSelectable: function(item) {
+ // user-customizable, will filter items through this
+ return true;
+ },
+
+ setItems: function(/* ... */) {
+ this.clearItems();
+ this.addItems.call(this, arguments);
+ },
+
+ // this is in case you have an active collection array-like object
+ // (i.e. getElementsByTagName collection) that manages its own order
+ // and item list
+ setItemsCollection: function(collection) {
+ this.items = collection;
+ },
+
+ addItems: function(/* ... */) {
+ var args = dojo.lang.unnest(arguments);
+ for(var i = 0; i < args.length; i++) {
+ this.items.push(args[i]);
+ }
+ },
+
+ addItemsAt: function(item, before /* ... */) {
+ if(this.items.length == 0) { // work for empy case
+ return this.addItems(dojo.lang.toArray(arguments, 2));
+ }
+
+ if(!this.isItem(item)) {
+ item = this.items[item];
+ }
+ if(!item) { throw new Error("addItemsAt: item doesn't exist"); }
+ var idx = this._find(item);
+ if(idx > 0 && before) { idx--; }
+ for(var i = 2; i < arguments.length; i++) {
+ if(!this.isItem(arguments[i])) {
+ this.items.splice(idx++, 0, arguments[i]);
+ }
+ }
+ },
+
+ removeItem: function(item) {
+ // remove item
+ var idx = this._find(item);
+ if(idx > -1) {
+ this.items.splice(i, 1);
+ }
+ // remove from selection
+ // FIXME: do we call deselect? I don't think so because this isn't how
+ // you usually want to deselect an item. For example, if you deleted an
+ // item, you don't really want to deselect it -- you want it gone. -DS
+ id = this._find(item, true);
+ if(idx > -1) {
+ this.selection.splice(i, 1);
+ }
+ },
+
+ clearItems: function() {
+ this.items = [];
+ this.deselectAll();
+ },
+
+ isItem: function(item) {
+ return this._find(item) > -1;
+ },
+
+ isSelected: function(item) {
+ return this._find(item, true) > -1;
+ },
+
+ /**
+ * allows you to filter item in or out of the selection
+ * depending on the current selection and action to be taken
+ **/
+ selectFilter: function(item, selection, add, grow) {
+ return true;
+ },
+
+ /**
+ * update -- manages selections, most selecting should be done here
+ * item => item which may be added/grown to/only selected/deselected
+ * add => behaves like ctrl in windows selection world
+ * grow => behaves like shift
+ * noToggle => if true, don't toggle selection on item
+ **/
+ update: function(item, add, grow, noToggle) {
+ if(!this.isItem(item)) { return false; }
+
+ if(this.isGrowable && grow) {
+ if(!this.isSelected(item)
+ && this.selectFilter(item, this.selection, false, true)) {
+ this.grow(item);
+ this.lastSelected = item;
+ }
+ } else if(add) {
+ if(this.selectFilter(item, this.selection, true, false)) {
+ if(noToggle) {
+ if(this.select(item)) {
+ this.lastSelected = item;
+ }
+ } else if(this.toggleSelected(item)) {
+ this.lastSelected = item;
+ }
+ }
+ } else {
+ this.deselectAll();
+ this.select(item);
+ }
+
+ this.length = this.selection.length;
+ },
+
+ /**
+ * Grow a selection.
+ * toItem => which item to grow selection to
+ * fromItem => which item to start the growth from (it won't be selected)
+ *
+ * Any items in (fromItem, lastSelected] that aren't part of
+ * (fromItem, toItem] will be deselected
+ **/
+ grow: function(toItem, fromItem) {
+ if(!this.isGrowable) { return; }
+
+ if(arguments.length == 1) {
+ fromItem = this._pivotItem;
+ if(!fromItem && this.allowImplicit) {
+ fromItem = this.items[0];
+ }
+ }
+ if(!toItem || !fromItem) { return false; }
+
+ var fromIdx = this._find(fromItem);
+
+ // get items to deselect (fromItem, lastSelected]
+ var toDeselect = {};
+ var lastIdx = -1;
+ if(this.lastSelected) {
+ lastIdx = this._find(this.lastSelected);
+ var step = fromIdx < lastIdx ? -1 : 1;
+ var range = dojo.math.range(lastIdx, fromIdx, step);
+ for(var i = 0; i < range.length; i++) {
+ toDeselect[range[i]] = true;
+ }
+ }
+
+ // add selection (fromItem, toItem]
+ var toIdx = this._find(toItem);
+ var step = fromIdx < toIdx ? -1 : 1;
+ var shrink = lastIdx >= 0 && step == 1 ? lastIdx < toIdx : lastIdx > toIdx;
+ var range = dojo.math.range(toIdx, fromIdx, step);
+ if(range.length) {
+ for(var i = range.length-1; i >= 0; i--) {
+ var item = this.items[range[i]];
+ if(this.selectFilter(item, this.selection, false, true)) {
+ if(this.select(item, true) || shrink) {
+ this.lastSelected = item;
+ }
+ if(range[i] in toDeselect) {
+ delete toDeselect[range[i]];
+ }
+ }
+ }
+ } else {
+ this.lastSelected = fromItem;
+ }
+
+ // now deselect...
+ for(var i in toDeselect) {
+ if(this.items[i] == this.lastSelected) {
+ dbg("oops!");
+ }
+ this.deselect(this.items[i]);
+ }
+
+ // make sure everything is all kosher after selections+deselections
+ this._updatePivot();
+ },
+
+ /**
+ * Grow selection upwards one item from lastSelected
+ **/
+ growUp: function() {
+ if(!this.isGrowable) { return; }
+
+ var idx = this._find(this.lastSelected) - 1;
+ while(idx >= 0) {
+ if(this.selectFilter(this.items[idx], this.selection, false, true)) {
+ this.grow(this.items[idx]);
+ break;
+ }
+ idx--;
+ }
+ },
+
+ /**
+ * Grow selection downwards one item from lastSelected
+ **/
+ growDown: function() {
+ if(!this.isGrowable) { return; }
+
+ var idx = this._find(this.lastSelected);
+ if(idx < 0 && this.allowImplicit) {
+ this.select(this.items[0]);
+ idx = 0;
+ }
+ idx++;
+ while(idx > 0 && idx < this.items.length) {
+ if(this.selectFilter(this.items[idx], this.selection, false, true)) {
+ this.grow(this.items[idx]);
+ break;
+ }
+ idx++;
+ }
+ },
+
+ toggleSelected: function(item, noPivot) {
+ if(this.isItem(item)) {
+ if(this.select(item, noPivot)) { return 1; }
+ if(this.deselect(item)) { return -1; }
+ }
+ return 0;
+ },
+
+ select: function(item, noPivot) {
+ if(this.isItem(item) && !this.isSelected(item)
+ && this.isSelectable(item)) {
+ this.selection.push(item);
+ this.lastSelected = item;
+ this.onSelect(item);
+ this.onSelectChange(item, true);
+ if(!noPivot) {
+ this._addPivot(item);
+ }
+ return true;
+ }
+ return false;
+ },
+
+ deselect: function(item) {
+ var idx = this._find(item, true);
+ if(idx > -1) {
+ this.selection.splice(idx, 1);
+ this.onDeselect(item);
+ this.onSelectChange(item, false);
+ if(item == this.lastSelected) {
+ this.lastSelected = null;
+ }
+
+ this._removePivot(item);
+
+ return true;
+ }
+ return false;
+ },
+
+ selectAll: function() {
+ for(var i = 0; i < this.items.length; i++) {
+ this.select(this.items[i]);
+ }
+ },
+
+ deselectAll: function() {
+ while(this.selection && this.selection.length) {
+ this.deselect(this.selection[0]);
+ }
+ },
+
+ selectNext: function() {
+ var idx = this._find(this.lastSelected);
+ while(idx > -1 && ++idx < this.items.length) {
+ if(this.isSelectable(this.items[idx])) {
+ this.deselectAll();
+ this.select(this.items[idx]);
+ return true;
+ }
+ }
+ return false;
+ },
+
+ selectPrevious: function() {
+ //debugger;
+ var idx = this._find(this.lastSelected);
+ while(idx-- > 0) {
+ if(this.isSelectable(this.items[idx])) {
+ this.deselectAll();
+ this.select(this.items[idx]);
+ return true;
+ }
+ }
+ return false;
+ },
+
+ // select first selectable item
+ selectFirst: function() {
+ this.deselectAll();
+ var idx = 0;
+ while(this.items[idx] && !this.select(this.items[idx])) {
+ idx++;
+ }
+ return this.items[idx] ? true : false;
+ },
+
+ // select last selectable item
+ selectLast: function() {
+ this.deselectAll();
+ var idx = this.items.length-1;
+ while(this.items[idx] && !this.select(this.items[idx])) {
+ idx--;
+ }
+ return this.items[idx] ? true : false;
+ },
+
+ _addPivot: function(item, andClear) {
+ this._pivotItem = item;
+ if(andClear) {
+ this._pivotItems = [item];
+ } else {
+ this._pivotItems.push(item);
+ }
+ },
+
+ _removePivot: function(item) {
+ var i = dojo.lang.find(item, this._pivotItems);
+ if(i > -1) {
+ this._pivotItems.splice(i, 1);
+ this._pivotItem = this._pivotItems[this._pivotItems.length-1];
+ }
+
+ this._updatePivot();
+ },
+
+ _updatePivot: function() {
+ if(this._pivotItems.length == 0) {
+ if(this.lastSelected) {
+ this._addPivot(this.lastSelected);
+ }
+ }
+ },
+
+ sorted: function() {
+ return dojo.lang.toArray(this.selection).sort(
+ dojo.lang.hitch(this, function(a, b) {
+ var A = this._find(a), B = this._find(b);
+ if(A > B) {
+ return 1;
+ } else if(A < B) {
+ return -1;
+ } else {
+ return 0;
+ }
+ })
+ );
+ },
+
+ // remove any items from the selection that are no longer in this.items
+ updateSelected: function() {
+ for(var i = 0; i < this.selection.length; i++) {
+ if(this._find(this.selection[i]) < 0) {
+ var removed = this.selection.splice(i, 1);
+
+ this._removePivot(removed[0]);
+ }
+ }
+
+ this.length = this.selection.length;
+ }
+});
Propchange: incubator/xap/trunk/src/dojo/src/selection/Selection.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/xap/trunk/src/dojo/src/storage.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/storage.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/storage.js (added)
+++ incubator/xap/trunk/src/dojo/src/storage.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,418 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+/**
+ FIXME: Write better docs.
+
+ @author Alex Russel, alex@dojotoolkit.org
+ @author Brad Neuberg, bkn3@columbia.edu
+*/
+dojo.provide("dojo.storage");
+dojo.provide("dojo.storage.StorageProvider");
+
+dojo.require("dojo.lang.*");
+dojo.require("dojo.event.*");
+
+
+/** The base class for all storage providers. */
+
+/**
+ The constructor for a storage provider. You should avoid initialization
+ in the constructor; instead, define initialization in your initialize()
+ method.
+*/
+dojo.storage = function(){
+}
+
+dojo.lang.extend(dojo.storage, {
+ /** A put() call to a storage provider was succesful. */
+ SUCCESS: "success",
+
+ /** A put() call to a storage provider failed. */
+ FAILED: "failed",
+
+ /** A put() call to a storage provider is pending user approval. */
+ PENDING: "pending",
+
+ /**
+ Returned by getMaximumSize() if this storage provider can not determine
+ the maximum amount of data it can support.
+ */
+ SIZE_NOT_AVAILABLE: "Size not available",
+
+ /**
+ Returned by getMaximumSize() if this storage provider has no theoretical
+ limit on the amount of data it can store.
+ */
+ SIZE_NO_LIMIT: "No size limit",
+
+ /**
+ The namespace for all storage operations. This is useful if
+ several applications want access to the storage system from the same
+ domain but want different storage silos.
+ */
+ namespace: "dojoStorage",
+
+ /**
+ If a function is assigned to this property, then
+ when the settings provider's UI is closed this
+ function is called. Useful, for example, if the
+ user has just cleared out all storage for this
+ provider using the settings UI, and you want to
+ update your UI.
+ */
+ onHideSettingsUI: null,
+
+ /**
+ Allows this storage provider to initialize itself. This is called
+ after the page has finished loading, so you can not do document.writes().
+ */
+ initialize: function(){
+ dojo.unimplemented("dojo.storage.initialize");
+ },
+
+ /**
+ Returns whether this storage provider is
+ available on this platform.
+
+ @returns True or false if this storage
+ provider is supported.
+ */
+ isAvailable: function(){
+ dojo.unimplemented("dojo.storage.isAvailable");
+ },
+
+ /**
+ Puts a key and value into this storage system.
+
+ @param key A string key to use when retrieving
+ this value in the future.
+ @param value A value to store; this can be
+ any JavaScript type.
+ @param resultsHandler A callback function
+ that will receive three arguments.
+ The first argument is one of three
+ values: dojo.storage.SUCCESS,
+ dojo.storage.FAILED, or
+ dojo.storage.PENDING; these values
+ determine how the put request went.
+ In some storage systems users can deny
+ a storage request, resulting in a
+ dojo.storage.FAILED, while in
+ other storage systems a storage
+ request must wait for user approval,
+ resulting in a dojo.storage.PENDING
+ status until the request
+ is either approved or denied,
+ resulting in another call back
+ with dojo.storage.SUCCESS.
+
+ The second argument in the call back is the key name
+ that was being stored.
+
+ The third argument in the call back is an
+ optional message that details possible error
+ messages that might have occurred during
+ the storage process.
+
+ Example:
+ var resultsHandler = function(status, key, message){
+ alert("status="+status+", key="+key+", message="+message);
+ };
+ dojo.storage.put("test", "hello world",
+ resultsHandler);
+ */
+ put: function(key, value, resultsHandler){
+ dojo.unimplemented("dojo.storage.put");
+ },
+
+ /**
+ Gets the value with the given key. Returns null
+ if this key is not in the storage system.
+
+ @param key A string key to get the value of.
+ @returns Returns any JavaScript object type;
+ null if the key is not
+ present.
+ */
+ get: function(key){
+ dojo.unimplemented("dojo.storage.get");
+ },
+
+ /**
+ Determines whether the storage has the given
+ key.
+
+ @returns Whether this key is
+ present or not.
+ */
+ hasKey: function(key){
+ if (this.get(key) != null)
+ return true;
+ else
+ return false;
+ },
+
+ /**
+ Enumerates all of the available keys in
+ this storage system.
+
+ @returns Array of string keys in this
+ storage system.
+ */
+ getKeys: function(){
+ dojo.unimplemented("dojo.storage.getKeys");
+ },
+
+ /**
+ Completely clears this storage system of all
+ of it's values and keys.
+ */
+ clear: function(){
+ dojo.unimplemented("dojo.storage.clear");
+ },
+
+ /** Removes the given key from the storage system. */
+ remove: function(key){
+ dojo.unimplemented("dojo.storage.remove");
+ },
+
+ /**
+ Returns whether this storage provider's
+ values are persisted when this platform
+ is shutdown.
+
+ @returns True or false whether this
+ storage is permanent.
+ */
+ isPermanent: function(){
+ dojo.unimplemented("dojo.storage.isPermanent");
+ },
+
+ /**
+ The maximum storage allowed by this provider.
+
+ @returns Returns the maximum storage size
+ supported by this provider, in
+ thousands of bytes (i.e., if it
+ returns 60 then this means that 60K
+ of storage is supported).
+
+ If this provider can not determine
+ it's maximum size, then
+ dojo.storage.SIZE_NOT_AVAILABLE is
+ returned; if there is no theoretical
+ limit on the amount of storage
+ this provider can return, then
+ dojo.storage.SIZE_NO_LIMIT is
+ returned
+ */
+ getMaximumSize: function(){
+ dojo.unimplemented("dojo.storage.getMaximumSize");
+ },
+
+ /**
+ Determines whether this provider has a
+ settings UI.
+
+ @returns True or false if this provider has
+ the ability to show a
+ a settings UI to change it's
+ values, change the amount of storage
+ available, etc.
+ */
+ hasSettingsUI: function(){
+ return false;
+ },
+
+ /**
+ If this provider has a settings UI, it is
+ shown.
+ */
+ showSettingsUI: function(){
+ dojo.unimplemented("dojo.storage.showSettingsUI");
+ },
+
+ /**
+ If this provider has a settings UI, hides
+ it.
+ */
+ hideSettingsUI: function(){
+ dojo.unimplemented("dojo.storage.hideSettingsUI");
+ },
+
+ /**
+ The provider name as a string, such as
+ "dojo.storage.FlashStorageProvider".
+ */
+ getType: function(){
+ dojo.unimplemented("dojo.storage.getType");
+ },
+
+ /**
+ Subclasses can call this to ensure that the key given is valid in a
+ consistent way across different storage providers. We use the lowest
+ common denominator for key values allowed: only letters, numbers, and
+ underscores are allowed. No spaces.
+ */
+ isValidKey: function(keyName){
+ if (keyName == null || typeof keyName == "undefined")
+ return false;
+
+ return /^[0-9A-Za-z_]*$/.test(keyName);
+ }
+});
+
+
+
+
+/**
+ Initializes the storage systems and figures out the best available
+ storage options on this platform.
+*/
+dojo.storage.manager = new function(){
+ this.currentProvider = null;
+ this.available = false;
+ this.initialized = false;
+ this.providers = new Array();
+
+ // TODO: Provide a way for applications to override the default namespace
+ this.namespace = "dojo.storage";
+
+ /** Initializes the storage system. */
+ this.initialize = function(){
+ // autodetect the best storage provider we can provide on this platform
+ this.autodetect();
+ }
+
+ /**
+ Registers the existence of a new storage provider; used by subclasses
+ to inform the manager of their existence.
+
+ @param name The full class name of this provider, such as
+ "dojo.storage.browser.Flash6StorageProvider".
+ @param instance An instance of this provider, which we will use to
+ call isAvailable() on.
+ */
+ this.register = function(name, instance) {
+ this.providers[this.providers.length] = instance;
+ this.providers[name] = instance;
+ }
+
+ /**
+ Instructs the storageManager to use
+ the given storage class for all storage requests.
+
+ Example:
+
+ dojo.storage.setProvider(
+ dojo.storage.browser.IEStorageProvider)
+ */
+ this.setProvider = function(storageClass){
+
+ }
+
+ /**
+ Autodetects the best possible persistent
+ storage provider available on this platform.
+ */
+ this.autodetect = function(){
+ if(this.initialized == true) // already finished
+ return;
+
+ // go through each provider, seeing if it can be used
+ var providerToUse = null;
+ for(var i = 0; i < this.providers.length; i++) {
+ providerToUse = this.providers[i];
+ if(providerToUse.isAvailable()){
+ break;
+ }
+ }
+
+ if(providerToUse == null){ // no provider available
+ this.initialized = true;
+ this.available = false;
+ this.currentProvider = null;
+ dojo.raise("No storage provider found for this platform");
+ }
+
+ // create this provider and copy over it's properties
+ this.currentProvider = providerToUse;
+ for(var i in providerToUse){
+ dojo.storage[i] = providerToUse[i];
+ }
+ dojo.storage.manager = this;
+
+ // have the provider initialize itself
+ dojo.storage.initialize();
+
+ this.initialized = true;
+ this.available = true;
+ }
+
+ /** Returns whether any storage options are available. */
+ this.isAvailable = function(){
+ return this.available;
+ }
+
+ /**
+ Returns whether the storage system is initialized and
+ ready to be used.
+ */
+ this.isInitialized = function(){
+ // FIXME: This should _really_ not be in here, but it fixes a bug
+ if(dojo.flash.ready == false){
+ return false;
+ }else{
+ return this.initialized;
+ }
+ }
+
+ /**
+ Determines if this platform supports
+ the given storage provider.
+
+ Example:
+
+ dojo.storage.manager.supportsProvider(
+ "dojo.storage.browser.InternetExplorerStorageProvider");
+ */
+ this.supportsProvider = function(storageClass){
+ // construct this class dynamically
+ try{
+ // dynamically call the given providers class level isAvailable()
+ // method
+ var provider = eval("new " + storageClass + "()");
+ var results = provider.isAvailable();
+ if(results == null || typeof results == "undefined")
+ return false;
+ return results;
+ }catch (exception){
+ dojo.debug("exception="+exception);
+ return false;
+ }
+ }
+
+ /** Gets the current provider. */
+ this.getProvider = function(){
+ return this.currentProvider;
+ }
+
+ /**
+ The storage provider should call this method when it is loaded and
+ ready to be used. Clients who will use the provider will connect
+ to this method to know when they can use the storage system:
+
+ dojo.connect(dojo.storage.manager, "loaded", someInstance,
+ someInstance.someMethod);
+ */
+ this.loaded = function(){
+ }
+}
Added: incubator/xap/trunk/src/dojo/src/storage/Storage.as
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/storage/Storage.as?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/storage/Storage.as (added)
+++ incubator/xap/trunk/src/dojo/src/storage/Storage.as Tue Jun 27 15:48:54 2006
@@ -0,0 +1,144 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+import DojoExternalInterface;
+
+class Storage {
+ public static var SUCCESS = "success";
+ public static var FAILED = "failed";
+ public static var PENDING = "pending";
+
+ public var so;
+
+ public function Storage(){
+ DojoExternalInterface.initialize();
+ DojoExternalInterface.addCallback("put", this, put);
+ DojoExternalInterface.addCallback("get", this, get);
+ DojoExternalInterface.addCallback("showSettings", this, showSettings);
+ DojoExternalInterface.addCallback("clear", this, clear);
+ DojoExternalInterface.addCallback("getKeys", this, getKeys);
+ DojoExternalInterface.addCallback("remove", this, remove);
+ DojoExternalInterface.loaded();
+
+ // preload the System Settings finished button movie for offline
+ // access so it is in the cache
+ _root.createEmptyMovieClip("_settingsBackground", 1);
+ _root._settingsBackground.loadMovie("../../storage_dialog.swf");
+ }
+
+ public function put(keyName, keyValue, namespace){
+ // Get the SharedObject for these values and save it
+ so = SharedObject.getLocal(namespace);
+
+ // prepare a storage status handler
+ var self = this;
+ so.onStatus = function(infoObject:Object){
+ //getURL("javascript:dojo.debug('FLASH: onStatus, infoObject="+infoObject.code+"')");
+
+ // delete the data value if the request was denied
+ if (infoObject.code == "SharedObject.Flush.Failed"){
+ delete self.so.data[keyName];
+ }
+
+ var statusResults;
+ if(infoObject.code == "SharedObject.Flush.Failed"){
+ statusResults = Storage.FAILED;
+ }else if(infoObject.code == "SharedObject.Flush.Pending"){
+ statusResults = Storage.PENDING;
+ }else if(infoObject.code == "SharedObject.Flush.Success"){
+ statusResults = Storage.SUCCESS;
+ }
+ //getURL("javascript:dojo.debug('FLASH: onStatus, statusResults="+statusResults+"')");
+
+ // give the status results to JavaScript
+ DojoExternalInterface.call("dojo.storage._onStatus", null, statusResults,
+ keyName);
+ }
+
+ // save the key and value
+ so.data[keyName] = keyValue;
+ var flushResults = so.flush();
+
+ // return results of this command to JavaScript
+ var statusResults;
+ if(flushResults == true){
+ statusResults = Storage.SUCCESS;
+ }else if(flushResults == "pending"){
+ statusResults = Storage.PENDING;
+ }else{
+ statusResults = Storage.FAILED;
+ }
+
+ DojoExternalInterface.call("dojo.storage._onStatus", null, statusResults,
+ keyName);
+ }
+
+ public function get(keyName, namespace){
+ // Get the SharedObject for these values and save it
+ so = SharedObject.getLocal(namespace);
+ var results = so.data[keyName];
+
+ return results;
+ }
+
+ public function showSettings(){
+ // Show the configuration options for the Flash player, opened to the
+ // section for local storage controls (pane 1)
+ System.showSettings(1);
+
+ // there is no way we can intercept when the Close button is pressed, allowing us
+ // to hide the Flash dialog. Instead, we need to load a movie in the
+ // background that we can show a close button on.
+ _root.createEmptyMovieClip("_settingsBackground", 1);
+ _root._settingsBackground.loadMovie("../../storage_dialog.swf");
+ }
+
+ public function clear(namespace){
+ so = SharedObject.getLocal(namespace);
+ so.clear();
+ so.flush();
+ }
+
+ public function getKeys(namespace){
+ // Returns a list of the available keys in this namespace
+
+ // get the storage object
+ so = SharedObject.getLocal(namespace);
+
+ // get all of the keys
+ var results = new Array();
+ for(var i in so.data)
+ results.push(i);
+
+ // join the keys together in a comma seperate string
+ results = results.join(",");
+
+ return results;
+ }
+
+ public function remove(keyName, namespace){
+ // Removes a key
+
+ // get the storage object
+ so = SharedObject.getLocal(namespace);
+
+ // delete this value
+ delete so.data[keyName];
+
+ // save the changes
+ so.flush();
+ }
+
+ static function main(mc){
+ //getURL("javascript:dojo.debug('FLASH: storage loaded')");
+ _root.app = new Storage();
+ }
+}
+
Added: incubator/xap/trunk/src/dojo/src/storage/__package__.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/storage/__package__.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/storage/__package__.js (added)
+++ incubator/xap/trunk/src/dojo/src/storage/__package__.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,17 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.kwCompoundRequire({
+ common: ["dojo.storage"],
+ browser: ["dojo.storage.browser"],
+ dashboard: ["dojo.storage.dashboard"]
+});
+dojo.provide("dojo.storage.*");
+
Propchange: incubator/xap/trunk/src/dojo/src/storage/__package__.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/xap/trunk/src/dojo/src/storage/browser.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/storage/browser.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/storage/browser.js (added)
+++ incubator/xap/trunk/src/dojo/src/storage/browser.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,195 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.storage.browser");
+dojo.provide("dojo.storage.browser.FlashStorageProvider");
+
+dojo.require("dojo.storage");
+dojo.require("dojo.flash");
+dojo.require("dojo.json");
+dojo.require("dojo.uri.*");
+
+/**
+ Storage provider that uses features in Flash to achieve permanent storage.
+
+ @author Alex Russel, alex@dojotoolkit.org
+ @author Brad Neuberg, bkn3@columbia.edu
+*/
+dojo.storage.browser.FlashStorageProvider = function(){
+}
+
+dojo.inherits(dojo.storage.browser.FlashStorageProvider, dojo.storage);
+
+// instance methods and properties
+dojo.lang.extend(dojo.storage.browser.FlashStorageProvider, {
+ namespace: "default",
+ initialized: false,
+ _available: null,
+ _statusHandler: null,
+
+ initialize: function(){
+ // initialize our Flash
+ var loadedListener = function(){
+ dojo.storage._flashLoaded();
+ }
+ dojo.flash.addLoadedListener(loadedListener);
+ var swfloc6 = dojo.uri.dojoUri("Storage_version6.swf").toString();
+ var swfloc8 = dojo.uri.dojoUri("Storage_version8.swf").toString();
+ dojo.flash.setSwf({flash6: swfloc6, flash8: swfloc8, visible: false});
+ },
+
+ isAvailable: function(){
+ if(djConfig["disableFlashStorage"] == true){
+ this._available = false;
+ }
+
+ return this._available;
+ },
+
+ setNamespace: function(namespace){
+ this.namespace = namespace;
+ },
+
+ put: function(key, value, resultsHandler){
+ if(this.isValidKey(key) == false){
+ dojo.raise("Invalid key given: " + key);
+ }
+
+ this._statusHandler = resultsHandler;
+
+ // serialize the value
+ // Handle strings differently so they have better performance
+ if(dojo.lang.isString(value)){
+ value = "string:" + value;
+ }else{
+ value = dojo.json.serialize(value);
+ }
+
+ dojo.flash.comm.put(key, value, this.namespace);
+ },
+
+ get: function(key){
+ if(this.isValidKey(key) == false){
+ dojo.raise("Invalid key given: " + key);
+ }
+
+ var results = dojo.flash.comm.get(key, this.namespace);
+
+ if(results == ""){
+ return null;
+ }
+
+ // destringify the content back into a
+ // real JavaScript object
+ // Handle strings differently so they have better performance
+ if(!dojo.lang.isUndefined(results) && results != null
+ && /^string:/.test(results)){
+ results = results.substring("string:".length);
+ }else{
+ results = dojo.json.evalJson(results);
+ }
+
+ return results;
+ },
+
+ getKeys: function(){
+ var results = dojo.flash.comm.getKeys(this.namespace);
+
+ if(results == ""){
+ return new Array();
+ }
+
+ // the results are returned comma seperated; split them
+ results = results.split(",");
+
+ return results;
+ },
+
+ clear: function(){
+ dojo.flash.comm.clear(this.namespace);
+ },
+
+ remove: function(key){
+ },
+
+ isPermanent: function(){
+ return true;
+ },
+
+ getMaximumSize: function(){
+ return dojo.storage.SIZE_NO_LIMIT;
+ },
+
+ hasSettingsUI: function(){
+ return true;
+ },
+
+ showSettingsUI: function(){
+ dojo.flash.comm.showSettings();
+ dojo.flash.obj.setVisible(true);
+ dojo.flash.obj.center();
+ },
+
+ hideSettingsUI: function(){
+ // hide the dialog
+ dojo.flash.obj.setVisible(false);
+
+ // call anyone who wants to know the dialog is
+ // now hidden
+ if(dojo.storage.onHideSettingsUI != null &&
+ !dojo.lang.isUndefined(dojo.storage.onHideSettingsUI)){
+ dojo.storage.onHideSettingsUI.call(null);
+ }
+ },
+
+ /**
+ The provider name as a string, such as
+ "dojo.storage.FlashStorageProvider".
+ */
+ getType: function(){
+ return "dojo.storage.FlashStorageProvider";
+ },
+
+ /** Called when the Flash is finished loading. */
+ _flashLoaded: function(){
+ this.initialized = true;
+
+ // indicate that this storage provider is now loaded
+ dojo.storage.manager.loaded();
+ },
+
+ /**
+ Called if the storage system needs to tell us about the status
+ of a put() request.
+ */
+ _onStatus: function(statusResult, key){
+ //dojo.debug("_onStatus, statusResult="+statusResult+", key="+key);
+ if(statusResult == dojo.storage.PENDING){
+ dojo.flash.obj.center();
+ dojo.flash.obj.setVisible(true);
+ }else{
+ dojo.flash.obj.setVisible(false);
+ }
+
+ if(!dojo.lang.isUndefined(dojo.storage._statusHandler)
+ && dojo.storage._statusHandler != null){
+ dojo.storage._statusHandler.call(null, statusResult, key);
+ }
+ }
+});
+
+// register the existence of our storage providers
+dojo.storage.manager.register("dojo.storage.browser.FlashStorageProvider",
+ new dojo.storage.browser.FlashStorageProvider());
+
+// now that we are loaded and registered tell the storage manager to initialize
+// itself
+dojo.storage.manager.initialize();
+
Propchange: incubator/xap/trunk/src/dojo/src/storage/browser.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/xap/trunk/src/dojo/src/storage/dashboard.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/storage/dashboard.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/storage/dashboard.js (added)
+++ incubator/xap/trunk/src/dojo/src/storage/dashboard.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,52 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.require("dojo.storage");
+dojo.require("dojo.json");
+dojo.provide("dojo.storage.dashboard");
+
+dojo.storage.dashboard.StorageProvider = function(){
+ this.initialized = false;
+}
+
+dojo.inherits(dojo.storage.dashboard.StorageProvider, dojo.storage.StorageProvider);
+
+dojo.lang.extend(dojo.storage.dashboard.StorageProvider, {
+ storageOnLoad: function(){
+ this.initialized = true;
+ },
+
+ set: function(key, value, ns){
+ if (ns && widget.system){
+ widget.system("/bin/mkdir " + ns);
+ var system = widget.system("/bin/echo " + value + " >" + ns + "/" + key);
+ if(system.errorString){
+ return false;
+ }
+ return true;
+ }
+
+ return widget.setPreferenceForKey(dojo.json.serialize(value), key);
+ },
+
+ get: function(key, ns){
+ if (ns && widget.system) {
+ var system = widget.system("/bin/cat " + ns + "/" + key);
+ if(system.errorString){
+ return "";
+ }
+ return system.outputString;
+ }
+
+ return dojo.json.evalJson(widget.preferenceForKey(key));
+ }
+});
+
+dojo.storage.setProvider(new dojo.storage.dashboard.StorageProvider());
Propchange: incubator/xap/trunk/src/dojo/src/storage/dashboard.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/xap/trunk/src/dojo/src/storage/storage_dialog.fla
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/storage/storage_dialog.fla?rev=417618&view=auto
==============================================================================
Binary file - no diff available.
Propchange: incubator/xap/trunk/src/dojo/src/storage/storage_dialog.fla
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: incubator/xap/trunk/src/dojo/src/string.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/string.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/string.js (added)
+++ incubator/xap/trunk/src/dojo/src/string.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,12 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.string");
+dojo.require("dojo.string.common");
Added: incubator/xap/trunk/src/dojo/src/string/Builder.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/string/Builder.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/string/Builder.js (added)
+++ incubator/xap/trunk/src/dojo/src/string/Builder.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,105 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.string.Builder");
+dojo.require("dojo.string");
+
+// NOTE: testing shows that direct "+=" concatenation is *much* faster on
+// Spidermoneky and Rhino, while arr.push()/arr.join() style concatenation is
+// significantly quicker on IE (Jscript/wsh/etc.).
+
+dojo.string.Builder = function(str){
+ this.arrConcat = (dojo.render.html.capable && dojo.render.html["ie"]);
+
+ var a = [];
+ var b = str || "";
+ var length = this.length = b.length;
+
+ if(this.arrConcat){
+ if(b.length > 0){
+ a.push(b);
+ }
+ b = "";
+ }
+
+ this.toString = this.valueOf = function(){
+ return (this.arrConcat) ? a.join("") : b;
+ };
+
+ this.append = function(s){
+ if(this.arrConcat){
+ a.push(s);
+ }else{
+ b+=s;
+ }
+ length += s.length;
+ this.length = length;
+ return this;
+ };
+
+ this.clear = function(){
+ a = [];
+ b = "";
+ length = this.length = 0;
+ return this;
+ };
+
+ this.remove = function(f,l){
+ var s = "";
+ if(this.arrConcat){
+ b = a.join("");
+ }
+ a=[];
+ if(f>0){
+ s = b.substring(0, (f-1));
+ }
+ b = s + b.substring(f + l);
+ length = this.length = b.length;
+ if(this.arrConcat){
+ a.push(b);
+ b="";
+ }
+ return this;
+ };
+
+ this.replace = function(o,n){
+ if(this.arrConcat){
+ b = a.join("");
+ }
+ a = [];
+ b = b.replace(o,n);
+ length = this.length = b.length;
+ if(this.arrConcat){
+ a.push(b);
+ b="";
+ }
+ return this;
+ };
+
+ this.insert = function(idx,s){
+ if(this.arrConcat){
+ b = a.join("");
+ }
+ a=[];
+ if(idx == 0){
+ b = s + b;
+ }else{
+ var t = b.split("");
+ t.splice(idx,0,s);
+ b = t.join("")
+ }
+ length = this.length = b.length;
+ if(this.arrConcat){
+ a.push(b);
+ b="";
+ }
+ return this;
+ };
+};
Propchange: incubator/xap/trunk/src/dojo/src/string/Builder.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/xap/trunk/src/dojo/src/string/__package__.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/string/__package__.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/string/__package__.js (added)
+++ incubator/xap/trunk/src/dojo/src/string/__package__.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,19 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.kwCompoundRequire({
+ common: [
+ "dojo.string",
+ "dojo.string.common",
+ "dojo.string.extras",
+ "dojo.string.Builder"
+ ]
+});
+dojo.provide("dojo.string.*");
Propchange: incubator/xap/trunk/src/dojo/src/string/__package__.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/xap/trunk/src/dojo/src/string/common.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/string/common.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/string/common.js (added)
+++ incubator/xap/trunk/src/dojo/src/string/common.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,87 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.string.common");
+
+dojo.require("dojo.string");
+
+/**
+ * Trim whitespace from 'str'. If 'wh' > 0,
+ * only trim from start, if 'wh' < 0, only trim
+ * from end, otherwise trim both ends
+ */
+dojo.string.trim = function(str, wh){
+ if(!str.replace){ return str; }
+ if(!str.length){ return str; }
+ var re = (wh > 0) ? (/^\s+/) : (wh < 0) ? (/\s+$/) : (/^\s+|\s+$/g);
+ return str.replace(re, "");
+}
+
+/**
+ * Trim whitespace at the beginning of 'str'
+ */
+dojo.string.trimStart = function(str) {
+ return dojo.string.trim(str, 1);
+}
+
+/**
+ * Trim whitespace at the end of 'str'
+ */
+dojo.string.trimEnd = function(str) {
+ return dojo.string.trim(str, -1);
+}
+
+/**
+ * Return 'str' repeated 'count' times, optionally
+ * placing 'separator' between each rep
+ */
+dojo.string.repeat = function(str, count, separator) {
+ var out = "";
+ for(var i = 0; i < count; i++) {
+ out += str;
+ if(separator && i < count - 1) {
+ out += separator;
+ }
+ }
+ return out;
+}
+
+/**
+ * Pad 'str' to guarantee that it is at least 'len' length
+ * with the character 'c' at either the start (dir=1) or
+ * end (dir=-1) of the string
+ */
+dojo.string.pad = function(str, len/*=2*/, c/*='0'*/, dir/*=1*/) {
+ var out = String(str);
+ if(!c) {
+ c = '0';
+ }
+ if(!dir) {
+ dir = 1;
+ }
+ while(out.length < len) {
+ if(dir > 0) {
+ out = c + out;
+ } else {
+ out += c;
+ }
+ }
+ return out;
+}
+
+/** same as dojo.string.pad(str, len, c, 1) */
+dojo.string.padLeft = function(str, len, c) {
+ return dojo.string.pad(str, len, c, 1);
+}
+
+/** same as dojo.string.pad(str, len, c, -1) */
+dojo.string.padRight = function(str, len, c) {
+ return dojo.string.pad(str, len, c, -1);
+}
Propchange: incubator/xap/trunk/src/dojo/src/string/common.js
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/xap/trunk/src/dojo/src/string/extras.js
URL: http://svn.apache.org/viewvc/incubator/xap/trunk/src/dojo/src/string/extras.js?rev=417618&view=auto
==============================================================================
--- incubator/xap/trunk/src/dojo/src/string/extras.js (added)
+++ incubator/xap/trunk/src/dojo/src/string/extras.js Tue Jun 27 15:48:54 2006
@@ -0,0 +1,221 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.string.extras");
+
+dojo.require("dojo.string.common");
+dojo.require("dojo.lang");
+
+/**
+ * Parameterized string function
+ * str - formatted string with %{values} to be replaces
+ * pairs - object of name: "value" value pairs
+ * killExtra - remove all remaining %{values} after pairs are inserted
+ */
+dojo.string.paramString = function(str, pairs, killExtra) {
+ for(var name in pairs) {
+ var re = new RegExp("\\%\\{" + name + "\\}", "g");
+ str = str.replace(re, pairs[name]);
+ }
+
+ if(killExtra) { str = str.replace(/%\{([^\}\s]+)\}/g, ""); }
+ return str;
+}
+
+/** Uppercases the first letter of each word */
+dojo.string.capitalize = function (str) {
+ if (!dojo.lang.isString(str)) { return ""; }
+ if (arguments.length == 0) { str = this; }
+ var words = str.split(' ');
+ var retval = "";
+ var len = words.length;
+ for (var i=0; i<len; i++) {
+ var word = words[i];
+ word = word.charAt(0).toUpperCase() + word.substring(1, word.length);
+ retval += word;
+ if (i < len-1)
+ retval += " ";
+ }
+
+ return new String(retval);
+}
+
+/**
+ * Return true if the entire string is whitespace characters
+ */
+dojo.string.isBlank = function (str) {
+ if(!dojo.lang.isString(str)) { return true; }
+ return (dojo.string.trim(str).length == 0);
+}
+
+dojo.string.encodeAscii = function(str) {
+ if(!dojo.lang.isString(str)) { return str; }
+ var ret = "";
+ var value = escape(str);
+ var match, re = /%u([0-9A-F]{4})/i;
+ while((match = value.match(re))) {
+ var num = Number("0x"+match[1]);
+ var newVal = escape("&#" + num + ";");
+ ret += value.substring(0, match.index) + newVal;
+ value = value.substring(match.index+match[0].length);
+ }
+ ret += value.replace(/\+/g, "%2B");
+ return ret;
+}
+
+dojo.string.escape = function(type, str) {
+ var args = [];
+ for(var i = 1; i < arguments.length; i++) { args.push(arguments[i]); }
+ switch(type.toLowerCase()) {
+ case "xml":
+ case "html":
+ case "xhtml":
+ return dojo.string.escapeXml.apply(this, args);
+ case "sql":
+ return dojo.string.escapeSql.apply(this, args);
+ case "regexp":
+ case "regex":
+ return dojo.string.escapeRegExp.apply(this, args);
+ case "javascript":
+ case "jscript":
+ case "js":
+ return dojo.string.escapeJavaScript.apply(this, args);
+ case "ascii":
+ // so it's encode, but it seems useful
+ return dojo.string.encodeAscii.apply(this, args);
+ default:
+ return str;
+ }
+}
+
+dojo.string.escapeXml = function(str, noSingleQuotes) {
+ str = str.replace(/&/gm, "&").replace(/</gm, "<")
+ .replace(/>/gm, ">").replace(/"/gm, """);
+ if(!noSingleQuotes) { str = str.replace(/'/gm, "'"); }
+ return str;
+}
+
+dojo.string.escapeSql = function(str) {
+ return str.replace(/'/gm, "''");
+}
+
+dojo.string.escapeRegExp = function(str) {
+ return str.replace(/\\/gm, "\\\\").replace(/([\f\b\n\t\r[\^$|?*+(){}])/gm, "\\$1");
+}
+
+dojo.string.escapeJavaScript = function(str) {
+ return str.replace(/(["'\f\b\n\t\r])/gm, "\\$1");
+}
+
+dojo.string.escapeString = function(str){
+ return ('"' + str.replace(/(["\\])/g, '\\$1') + '"'
+ ).replace(/[\f]/g, "\\f"
+ ).replace(/[\b]/g, "\\b"
+ ).replace(/[\n]/g, "\\n"
+ ).replace(/[\t]/g, "\\t"
+ ).replace(/[\r]/g, "\\r");
+}
+
+// TODO: make an HTML version
+dojo.string.summary = function(str, len) {
+ if(!len || str.length <= len) {
+ return str;
+ } else {
+ return str.substring(0, len).replace(/\.+$/, "") + "...";
+ }
+}
+
+/**
+ * Returns true if 'str' ends with 'end'
+ */
+dojo.string.endsWith = function(str, end, ignoreCase) {
+ if(ignoreCase) {
+ str = str.toLowerCase();
+ end = end.toLowerCase();
+ }
+ if((str.length - end.length) < 0){
+ return false;
+ }
+ return str.lastIndexOf(end) == str.length - end.length;
+}
+
+/**
+ * Returns true if 'str' ends with any of the arguments[2 -> n]
+ */
+dojo.string.endsWithAny = function(str /* , ... */) {
+ for(var i = 1; i < arguments.length; i++) {
+ if(dojo.string.endsWith(str, arguments[i])) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Returns true if 'str' starts with 'start'
+ */
+dojo.string.startsWith = function(str, start, ignoreCase) {
+ if(ignoreCase) {
+ str = str.toLowerCase();
+ start = start.toLowerCase();
+ }
+ return str.indexOf(start) == 0;
+}
+
+/**
+ * Returns true if 'str' starts with any of the arguments[2 -> n]
+ */
+dojo.string.startsWithAny = function(str /* , ... */) {
+ for(var i = 1; i < arguments.length; i++) {
+ if(dojo.string.startsWith(str, arguments[i])) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * Returns true if 'str' starts with any of the arguments 2 -> n
+ */
+dojo.string.has = function(str /* , ... */) {
+ for(var i = 1; i < arguments.length; i++) {
+ if(str.indexOf(arguments[i]) > -1){
+ return true;
+ }
+ }
+ return false;
+}
+
+dojo.string.normalizeNewlines = function (text,newlineChar) {
+ if (newlineChar == "\n") {
+ text = text.replace(/\r\n/g, "\n");
+ text = text.replace(/\r/g, "\n");
+ } else if (newlineChar == "\r") {
+ text = text.replace(/\r\n/g, "\r");
+ text = text.replace(/\n/g, "\r");
+ } else {
+ text = text.replace(/([^\r])\n/g, "$1\r\n");
+ text = text.replace(/\r([^\n])/g, "\r\n$1");
+ }
+ return text;
+}
+
+dojo.string.splitEscaped = function (str,charac) {
+ var components = [];
+ for (var i = 0, prevcomma = 0; i < str.length; i++) {
+ if (str.charAt(i) == '\\') { i++; continue; }
+ if (str.charAt(i) == charac) {
+ components.push(str.substring(prevcomma, i));
+ prevcomma = i + 1;
+ }
+ }
+ components.push(str.substr(prevcomma));
+ return components;
+}