Return-Path: Delivered-To: apmail-jackrabbit-commits-archive@www.apache.org Received: (qmail 10676 invoked from network); 11 Nov 2006 16:47:06 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 11 Nov 2006 16:47:06 -0000 Received: (qmail 31283 invoked by uid 500); 11 Nov 2006 16:47:16 -0000 Delivered-To: apmail-jackrabbit-commits-archive@jackrabbit.apache.org Received: (qmail 31258 invoked by uid 500); 11 Nov 2006 16:47:16 -0000 Mailing-List: contact commits-help@jackrabbit.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@jackrabbit.apache.org Delivered-To: mailing list commits@jackrabbit.apache.org Received: (qmail 31249 invoked by uid 99); 11 Nov 2006 16:47:16 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 11 Nov 2006 08:47:16 -0800 X-ASF-Spam-Status: No, hits=-9.4 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Sat, 11 Nov 2006 08:46:40 -0800 Received: by eris.apache.org (Postfix, from userid 65534) id E316F1A9888; Sat, 11 Nov 2006 08:45:11 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r473755 [24/43] - in /jackrabbit/trunk/contrib/jcr-browser: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/jackrabbit/ src/main/java/org/apache/jackrabbit/browser/ src/main/resources/ ... Date: Sat, 11 Nov 2006 16:44:48 -0000 To: commits@jackrabbit.apache.org From: edgarpoce@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20061111164511.E316F1A9888@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/selection/Selection.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/selection/Selection.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/selection/Selection.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/selection/Selection.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,415 @@ +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(this.selection, item); + } else { + return dojo.lang.find(this.items, item); + } + }, + + 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(idx, 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 + idx = this._find(item, true); + if(idx > -1) { + this.selection.splice(idx, 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) { + //dojo.debug("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); + } + this.length = this.selection.length; + 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); + this.length = this.selection.length; + 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(this._pivotItems, item); + 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: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/selection/Selection.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,354 @@ +/** + FIXME: Write better docs. + + @author Brad Neuberg, bkn3@columbia.edu +*/ +dojo.provide("dojo.storage"); + +dojo.require("dojo.lang.*"); +dojo.require("dojo.event.*"); + +// create an empty "StorageProvider", which was being created as a side-effect +// of the erroneous dojo.provide("dojo.storage.StorageProvider") +dojo.storage.StorageProvider = {} + + +/** 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.declare("dojo.storage", null, { + /** 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, + + initialize: function(){ + // summary: + // Allows this storage provider to initialize itself. This is + // called after the page has finished loading, so you can not do + // document.writes(). + dojo.unimplemented("dojo.storage.initialize"); + }, + + isAvailable: function(){ /*Boolean*/ + // summary: + // Returns whether this storage provider is available on this + // platform. + dojo.unimplemented("dojo.storage.isAvailable"); + }, + + /** + + */ + put: function( /*string*/ key, + /*object*/ value, + /*function*/ resultsHandler){ + // summary: + // Puts a key and value into this storage system. + // key: + // A string key to use when retrieving this value in the future. + // value: + // A value to store; this can be any JavaScript type. + // 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); + dojo.unimplemented("dojo.storage.put"); + }, + + get: function(/*string*/ key){ /*Object*/ + // summary: + // Gets the value with the given key. Returns null if this key is + // not in the storage system. + // key: + // A string key to get the value of. + // return: Returns any JavaScript object type; null if the key is not present + dojo.unimplemented("dojo.storage.get"); + }, + + hasKey: function(/*string*/ key){ /*Boolean*/ + // summary: Determines whether the storage has the given key. + return (this.get(key) != null); + }, + + /** + + getKeys: function(){ //Array + // summary: Enumerates all of the available keys in this storage system. + dojo.unimplemented("dojo.storage.getKeys"); + }, + + */ + clear: function(){ + // summary: + // Completely clears this storage system of all of it's values and + // keys. + dojo.unimplemented("dojo.storage.clear"); + }, + + /** Removes the given key from the storage system. */ + remove: function(key){ + dojo.unimplemented("dojo.storage.remove"); + }, + + isPermanent: function(){ /*Boolean*/ + // summary: + // Returns whether this storage provider's values are persisted + // when this platform is shutdown. + 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"); + }, + + hasSettingsUI: function(){ /*Boolean*/ + // summary: Determines whether this provider has a settings UI. + return false; + }, + + showSettingsUI: function(){ + // summary: If this provider has a settings UI, it is shown. + dojo.unimplemented("dojo.storage.showSettingsUI"); + }, + + hideSettingsUI: function(){ + // summary: If this provider has a settings UI, hides it. + dojo.unimplemented("dojo.storage.hideSettingsUI"); + }, + + getType: function(){ /*String*/ + // summary: + // The provider name as a string, such as + // "dojo.storage.FlashStorageProvider". + dojo.unimplemented("dojo.storage.getType"); + }, + + isValidKey: function(/*string*/ keyName){ /*Boolean*/ + // summary: + // 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. + 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 = []; + + // TODO: Provide a way for applications to override the default namespace + this["namespace"] = "dojo.storage"; + + this.initialize = function(){ + // summary: + // Initializes the storage system and autodetects the best storage + // provider we can provide on this platform + this.autodetect(); + }; + + /** + + */ + this.register = function(/*string*/ name, /*Object*/ instance) { + // summary: + // Registers the existence of a new storage provider; used by + // subclasses to inform the manager of their existence. + // name: + // The full class name of this provider, such as + // "dojo.storage.browser.Flash6StorageProvider". + // instance: + // An instance of this provider, which we will use to call + // isAvailable() on. + this.providers[this.providers.length] = instance; + this.providers[name] = instance; + }; + + /** + + */ + this.setProvider = function(storageClass){ + // summary: + // Instructs the storageManager to use the given storage class for + // all storage requests. + // description: + // Example: + // dojo.storage.setProvider( + // dojo.storage.browser.IEStorageProvider) + + }; + + this.autodetect = function(){ + // summary: + // Autodetects the best possible persistent storage provider + // available on this platform. + 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; + }; + + this.isAvailable = function(){ /*Boolean*/ + // summary: Returns whether any storage options are available. + return this.available; + }; + + this.isInitialized = function(){ /*Boolean*/ + // summary: + // Returns whether the storage system is initialized and ready to + // be used. + + // FIXME: This should _really_ not be in here, but it fixes a bug + if(dojo.flash.ready == false){ + return false; + }else{ + return this.initialized; + } + }; + + this.supportsProvider = function(/*string*/ storageClass){ + // summary: Determines if this platform supports the given storage provider. + // description: + // Example: + // dojo.storage.manager.supportsProvider( + // "dojo.storage.browser.InternetExplorerStorageProvider"); + + // 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; + }; + + this.loaded = function(){ + // summary: + // 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: + }; +}; Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/Storage.as URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/Storage.as?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/Storage.as (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/Storage.as Sat Nov 11 08:44:22 2006 @@ -0,0 +1,136 @@ +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(){ + //getURL("javascript:dojo.debug('FLASH:Storage constructor')"); + 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); + // getURL("javascript:alert('"+DojoExternalInterface.dojoPath+"');"); + _root._settingsBackground.loadMovie(DojoExternalInterface.dojoPath + "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(DojoExternalInterface.dojoPath + "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 seperated 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: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/__package__.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/__package__.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/__package__.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/__package__.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,7 @@ +dojo.kwCompoundRequire({ + common: ["dojo.storage"], + browser: ["dojo.storage.browser"], + dashboard: ["dojo.storage.dashboard"] +}); +dojo.provide("dojo.storage.*"); + Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/__package__.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/browser.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/browser.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/browser.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/browser.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,185 @@ +dojo.provide("dojo.storage.browser"); + +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 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(){ + if(djConfig["disableFlashStorage"] == true){ + return; + } + + // 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(ns){ + this["namespace"] = ns; + }, + + 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 []; + } + + // the results are returned comma seperated; split them + return results.split(","); + }, + + 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){ + var ds = dojo.storage; + var dfo = dojo.flash.obj; + //dojo.debug("_onStatus, statusResult="+statusResult+", key="+key); + if(statusResult == ds.PENDING){ + dfo.center(); + dfo.setVisible(true); + }else{ + dfo.setVisible(false); + } + + if((!dj_undef("_statusHandler", ds))&&(ds._statusHandler != null)){ + ds._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: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/browser.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/dashboard.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/dashboard.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/dashboard.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/dashboard.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,42 @@ +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: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/dashboard.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/storage_dialog.fla URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/storage_dialog.fla?view=auto&rev=473755 ============================================================================== Binary file - no diff available. Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/storage/storage_dialog.fla ------------------------------------------------------------------------------ svn:mime-type = application/octet-stream Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,2 @@ +dojo.provide("dojo.string"); +dojo.require("dojo.string.common"); Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/Builder.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/Builder.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/Builder.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/Builder.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,118 @@ +dojo.provide("dojo.string.Builder"); +dojo.require("dojo.string"); +dojo.require("dojo.lang.common"); + +// 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(/* string? */str){ + // summary + this.arrConcat = (dojo.render.html.capable && dojo.render.html["ie"]); + + var a = []; + var b = ""; + var length = this.length = b.length; + + if(this.arrConcat){ + if(b.length > 0){ + a.push(b); + } + b = ""; + } + + this.toString = this.valueOf = function(){ + // summary + // Concatenate internal buffer and return as a string + return (this.arrConcat) ? a.join("") : b; // string + }; + + this.append = function(){ + // summary + // Append all arguments to the end of the internal buffer + for(var x=0; x0){ + 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; // dojo.string.Builder + }; + + this.replace = function(/* string */o, /* string */n){ + // summary + // replace phrase *o* with phrase *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; // dojo.string.Builder + }; + + this.insert = function(/* integer */idx, /* string */s){ + // summary + // Insert string s at index idx. + 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; // dojo.string.Builder + }; + + this.append.apply(this, arguments); +}; Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/Builder.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/__package__.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/__package__.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/__package__.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/__package__.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,9 @@ +dojo.kwCompoundRequire({ + common: [ + "dojo.string", + "dojo.string.common", + "dojo.string.extras", + "dojo.string.Builder" + ] +}); +dojo.provide("dojo.string.*"); Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/__package__.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/common.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/common.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/common.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/common.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,68 @@ +dojo.provide("dojo.string.common"); + +dojo.string.trim = function(/* string */str, /* integer? */wh){ + // summary + // Trim whitespace from str. If wh > 0, trim from start, if wh < 0, trim from end, else both + 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, ""); // string +} + +dojo.string.trimStart = function(/* string */str) { + // summary + // Trim whitespace at the beginning of 'str' + return dojo.string.trim(str, 1); // string +} + +dojo.string.trimEnd = function(/* string */str) { + // summary + // Trim whitespace at the end of 'str' + return dojo.string.trim(str, -1); +} + +dojo.string.repeat = function(/* string */str, /* integer */count, /* string? */separator) { + // summary + // Return 'str' repeated 'count' times, optionally placing 'separator' between each rep + var out = ""; + for(var i = 0; i < count; i++) { + out += str; + if(separator && i < count - 1) { + out += separator; + } + } + return out; // string +} + +dojo.string.pad = function(/* string */str, /* integer */len/*=2*/, /* string */ c/*='0'*/, /* integer */dir/*=1*/) { + // summary + // 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 + 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; // string +} + +dojo.string.padLeft = function(/* string */str, /* integer */len, /* string */c) { + // summary + // same as dojo.string.pad(str, len, c, 1) + return dojo.string.pad(str, len, c, 1); // string +} + +dojo.string.padRight = function(/* string */str, /* integer */len, /* string */c) { + // summary + // same as dojo.string.pad(str, len, c, -1) + return dojo.string.pad(str, len, c, -1); // string +} Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/common.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/extras.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/extras.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/extras.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/extras.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,251 @@ +dojo.provide("dojo.string.extras"); + +dojo.require("dojo.string.common"); +dojo.require("dojo.lang.common"); +dojo.require("dojo.lang.array"); + +//TODO: should we use ${} substitution syntax instead, like widgets do? +dojo.string.substituteParams = function(/*string*/template, /* object - optional or ... */hash){ +// summary: +// Performs parameterized substitutions on a string. Throws an exception if any parameter is unmatched. +// +// description: +// For example, +// dojo.string.substituteParams("File '%{0}' is not found in directory '%{1}'.","foo.html","/temp"); +// returns +// "File 'foo.html' is not found in directory '/temp'." +// +// template: the original string template with %{values} to be replaced +// hash: name/value pairs (type object) to provide substitutions. Alternatively, substitutions may be +// included as arguments 1..n to this function, corresponding to template parameters 0..n-1 + + var map = (typeof hash == 'object') ? hash : dojo.lang.toArray(arguments, 1); + + return template.replace(/\%\{(\w+)\}/g, function(match, key){ + if(typeof(map[key]) != "undefined" && map[key] != null){ + return map[key]; + } + dojo.raise("Substitution not found: " + key); + }); // string +}; + +dojo.string.capitalize = function(/*string*/str){ +// summary: +// Uppercases the first letter of each word + + if(!dojo.lang.isString(str)){ return ""; } + if(arguments.length == 0){ str = this; } + + var words = str.split(' '); + for(var i=0; i"' +// Optionally skips escapes for single quotes + + str = str.replace(/&/gm, "&").replace(//gm, ">").replace(/"/gm, """); + if(!noSingleQuotes){ str = str.replace(/'/gm, "'"); } + return str; // string +} + +dojo.string.escapeSql = function(/*string*/str){ +//summary: +// Adds escape sequences for single quotes in SQL expressions + + return str.replace(/'/gm, "''"); //string +} + +dojo.string.escapeRegExp = function(/*string*/str){ +//summary: +// Adds escape sequences for special characters in regular expressions + + return str.replace(/\\/gm, "\\\\").replace(/([\f\b\n\t\r[\^$|?*+(){}])/gm, "\\$1"); // string +} + +//FIXME: should this one also escape backslash? +dojo.string.escapeJavaScript = function(/*string*/str){ +//summary: +// Adds escape sequences for single and double quotes as well +// as non-visible characters in JavaScript string literal expressions + + return str.replace(/(["'\f\b\n\t\r])/gm, "\\$1"); // string +} + +//FIXME: looks a lot like escapeJavaScript, just adds quotes? deprecate one? +dojo.string.escapeString = function(/*string*/str){ +//summary: +// Adds escape sequences for non-visual characters, double quote and backslash +// and surrounds with double quotes to form a valid string literal. + 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"); // string +} + +// TODO: make an HTML version +dojo.string.summary = function(/*string*/str, /*number*/len){ +// summary: +// Truncates 'str' after 'len' characters and appends periods as necessary so that it ends with "..." + + if(!len || str.length <= len){ + return str; // string + } + + return str.substring(0, len).replace(/\.+$/, "") + "..."; // string +} + +dojo.string.endsWith = function(/*string*/str, /*string*/end, /*boolean*/ignoreCase){ +// summary: +// Returns true if 'str' ends with 'end' + + if(ignoreCase){ + str = str.toLowerCase(); + end = end.toLowerCase(); + } + if((str.length - end.length) < 0){ + return false; // boolean + } + return str.lastIndexOf(end) == str.length - end.length; // boolean +} + +dojo.string.endsWithAny = function(/*string*/str /* , ... */){ +// summary: +// Returns true if 'str' ends with any of the arguments[2 -> n] + + for(var i = 1; i < arguments.length; i++) { + if(dojo.string.endsWith(str, arguments[i])) { + return true; // boolean + } + } + return false; // boolean +} + +dojo.string.startsWith = function(/*string*/str, /*string*/start, /*boolean*/ignoreCase){ +// summary: +// Returns true if 'str' starts with 'start' + + if(ignoreCase) { + str = str.toLowerCase(); + start = start.toLowerCase(); + } + return str.indexOf(start) == 0; // boolean +} + +dojo.string.startsWithAny = function(/*string*/str /* , ... */){ +// summary: +// Returns true if 'str' starts with any of the arguments[2 -> n] + + for(var i = 1; i < arguments.length; i++) { + if(dojo.string.startsWith(str, arguments[i])) { + return true; // boolean + } + } + return false; // boolean +} + +dojo.string.has = function(/*string*/str /* , ... */) { +// summary: +// Returns true if 'str' contains any of the arguments 2 -> n + + for(var i = 1; i < arguments.length; i++) { + if(str.indexOf(arguments[i]) > -1){ + return true; // boolean + } + } + return false; // boolean +} + +dojo.string.normalizeNewlines = function(/*string*/text, /*string? (\n or \r)*/newlineChar){ +// summary: +// Changes occurences of CR and LF in text to CRLF, or if newlineChar is provided as '\n' or '\r', +// substitutes newlineChar for occurrences of CR/LF and CRLF + + 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").replace(/\r([^\n])/g, "\r\n$1"); + } + return text; // string +} + +dojo.string.splitEscaped = function(/*string*/str, /*string of length=1*/charac){ +// summary: +// Splits 'str' into an array separated by 'charac', but skips characters escaped with a backslash + + 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; // array +} Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/string/extras.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/style.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/style.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/style.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/style.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,5 @@ +dojo.provide("dojo.style"); +dojo.kwCompoundRequire({ + browser: ["dojo.html.style"] +}); +dojo.deprecated("dojo.style", "replaced by dojo.html.style", "0.5"); Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/style.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/svg.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/svg.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/svg.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/svg.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,310 @@ +dojo.provide("dojo.svg"); +dojo.require("dojo.lang.common"); +dojo.require("dojo.dom"); + +dojo.mixin(dojo.svg, dojo.dom); + +dojo.svg.graphics=dojo.svg.g=new function(/* DOMDocument */ d){ + // summary + // Singleton to encapsulate SVG rendering functions. + this.suspend=function(){ + // summary + // Suspend the rendering engine + try { d.documentElement.suspendRedraw(0); } catch(e){ } + }; + this.resume=function(){ + // summary + // Resume the rendering engine + try { d.documentElement.unsuspendRedraw(0); } catch(e){ } + }; + this.force=function(){ + // summary + // Force the render engine to redraw + try { d.documentElement.forceRedraw(); } catch(e){ } + }; +}(document); + +dojo.svg.animations=dojo.svg.anim=new function(/* DOMDocument */ d){ + // summary + // Singleton to encapsulate SVG animation functionality. + this.arePaused=function(){ + // summary + // check to see if all animations are paused + try { + return d.documentElement.animationsPaused(); // bool + } catch(e){ + return false; // bool + } + } ; + this.pause=function(){ + // summary + // pause all animations + try { d.documentElement.pauseAnimations(); } catch(e){ } + }; + this.resume=function(){ + // summary + // resume all animations + try { d.documentElement.unpauseAnimations(); } catch(e){ } + }; +}(document); + +// fixme: these functions should be mixed in from dojo.style, but dojo.style is HTML-centric and needs to change. +dojo.svg.toCamelCase=function(/* string */ selector){ + // summary + // converts a CSS-style selector to a camelCased one + var arr=selector.split('-'), cc=arr[0]; + for(var i=1; i < arr.length; i++) { + cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1); + } + return cc; // string +}; +dojo.svg.toSelectorCase=function(/* string */ selector) { + // summary + // converts a camelCased selector to a CSS style one + return selector.replace(/([A-Z])/g, "-$1" ).toLowerCase(); // string +}; +dojo.svg.getStyle=function(/* SVGElement */ node, /* string */ cssSelector){ + // summary + // get the computed style of selector for node. + return document.defaultView.getComputedStyle(node, cssSelector); // object +}; +dojo.svg.getNumericStyle=function(/* SVGElement */ node, /* string */ cssSelector){ + // summary + // return the numeric version of the computed style of selector on node. + return parseFloat(dojo.svg.getStyle(node, cssSelector)); +}; + +// fixme: there are different ways of doing the following, need to take into account +dojo.svg.getOpacity=function(/* SVGElement */node){ + // summary + // Return the opacity of the passed element + return Math.min(1.0, dojo.svg.getNumericStyle(node, "fill-opacity")); // float +}; +dojo.svg.setOpacity=function(/* SVGElement */ node, /* float */ opacity){ + // summary + // set the opacity of node using attributes. + node.setAttributeNS(this.xmlns.svg, "fill-opacity", opacity); + node.setAttributeNS(this.xmlns.svg, "stroke-opacity", opacity); +}; +dojo.svg.clearOpacity=function(/* SVGElement */ node){ + // summary + // Set any attributes setting opacity to opaque (1.0) + node.setAttributeNS(this.xmlns.svg, "fill-opacity", "1.0"); + node.setAttributeNS(this.xmlns.svg, "stroke-opacity", "1.0"); +}; + +/** + * Coordinates and dimensions. + */ + +// TODO ////////////////////////////////////////////////////////// TODO +dojo.svg.getCoords=function(/* SVGElement */ node){ + // summary + // Returns the x/y coordinates of the passed node, if available. + if (node.getBBox) { + var box=node.getBBox(); + return { x: box.x, y: box.y }; // object + } + return null; // object +}; +dojo.svg.setCoords=function(/* SVGElement */node, /* object */coords){ + // summary + // Set the x/y coordinates of the passed node + var p=dojo.svg.getCoords(); + if (!p) return; + var dx=p.x - coords.x; + var dy=p.y - coords.y; + dojo.svg.translate(node, dx, dy); +}; +dojo.svg.getDimensions=function(/* SVGElement */node){ + // summary + // Get the height and width of the passed node. + if (node.getBBox){ + var box=node.getBBox(); + return { width: box.width, height : box.height }; // object + } + return null; // object +}; +dojo.svg.setDimensions=function(/* SVGElement */node, /* object */dim){ + // summary + // Set the dimensions of the passed element if possible. + // will only support shape-based and container elements; path-based elements are ignored. + if (node.width){ + node.width.baseVal.value=dim.width; + node.height.baseVal.value=dim.height; + } + else if (node.r){ + node.r.baseVal.value=Math.min(dim.width, dim.height)/2; + } + else if (node.rx){ + node.rx.baseVal.value=dim.width/2; + node.ry.baseVal.value=dim.height/2; + } +}; + +/** + * Transformations. + */ +dojo.svg.translate=function(/* SVGElement */node, /* int */dx, /* int */dy){ + // summary + // Translates the passed node by dx and dy + if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){ + var t=node.ownerSVGElement.createSVGTransform(); + t.setTranslate(dx, dy); + node.transform.baseVal.appendItem(t); + } +}; +dojo.svg.scale=function(/* SVGElement */node, /* float */scaleX, /* float? */scaleY){ + // summary + // Scales the passed element by factor scaleX and scaleY. If scaleY not passed, scaleX is used. + if (!scaleY) var scaleY=scaleX; + if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){ + var t=node.ownerSVGElement.createSVGTransform(); + t.setScale(scaleX, scaleY); + node.transform.baseVal.appendItem(t); + } +}; +dojo.svg.rotate=function(/* SVGElement */node, /* float */ang, /* int? */cx, /* int? */cy){ + // summary + // rotate the passed node by ang, with optional cx/cy as the rotation point. + if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){ + var t=node.ownerSVGElement.createSVGTransform(); + if (cx == null) t.setMatrix(t.matrix.rotate(ang)); + else t.setRotate(ang, cx, cy); + node.transform.baseVal.appendItem(t); + } +}; +dojo.svg.skew=function(/* SVGElement */node, /* float */ang, /* string? */axis){ + // summary + // skew the passed node by ang over axis. + var dir=axis || "x"; + if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){ + var t=node.ownerSVGElement.createSVGTransform(); + if (dir != "x") t.setSkewY(ang); + else t.setSkewX(ang); + node.transform.baseVal.appendItem(t); + } +}; +dojo.svg.flip=function(/* SVGElement */node, /* string? */axis){ + // summary + // flip the passed element over axis + var dir=axis || "x"; + if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){ + var t=node.ownerSVGElement.createSVGTransform(); + t.setMatrix((dir != "x") ? t.matrix.flipY() : t.matrix.flipX()); + node.transform.baseVal.appendItem(t); + } +}; +dojo.svg.invert=function(/* SVGElement */node){ + // summary + // transform the passed node by the inverse of the current matrix + if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){ + var t=node.ownerSVGElement.createSVGTransform(); + t.setMatrix(t.matrix.inverse()); + node.transform.baseVal.appendItem(t); + } +}; +dojo.svg.applyMatrix=function( + /* SVGElement */node, + /* int || SVGMatrix */a, + /* int? */b, + /* int? */c, + /* int? */d, + /* int? */e, + /* int? */f +){ + // summary + // apply the passed matrix to node. If params b - f are passed, a matrix will be created. + if (node.transform && node.ownerSVGElement && node.ownerSVGElement.createSVGTransform){ + var m; + if (b){ + var m=node.ownerSVGElement.createSVGMatrix(); + m.a=a; + m.b=b; + m.c=c; + m.d=d; + m.e=e; + m.f=f; + } else m=a; + var t=node.ownerSVGElement.createSVGTransform(); + t.setMatrix(m); + node.transform.baseVal.appendItem(t); + } +}; + +/** + * Grouping and z-index operations. + */ +dojo.svg.group=function(/* Nodelist || array */nodes){ + // summary + // expect an array of nodes, attaches the group to the parent of the first node. + var p=nodes.item(0).parentNode; + var g=document.createElementNS(this.xmlns.svg, "g"); + for (var i=0; i < nodes.length; i++) g.appendChild(nodes.item(i)); + p.appendChild(g); + return g; +}; +dojo.svg.ungroup=function(/* SVGGElement */g){ + // summary + // puts the children of the group on the same level as group was. + var p=g.parentNode; + while (g.childNodes.length > 0) p.appendChild(g.childNodes.item(0)); + p.removeChild(g); +}; +// if the node is part of a group, return the group, else return null. +dojo.svg.getGroup=function(/* SVGElement */node){ + // summary + // if the node is part of a group, return the group, else return null. + var a=this.getAncestors(node); + for (var i=0; i < a.length; i++){ + if (a[i].nodeType == this.ELEMENT_NODE && a[i].nodeName.toLowerCase() == "g") + return a[i]; + } + return null; +}; +dojo.svg.bringToFront=function(/* SVGElement */node){ + // summary + // move the passed node the to top of the group (i.e. last child) + var n=this.getGroup(node) || node; + n.ownerSVGElement.appendChild(n); +}; +dojo.svg.sendToBack=function(/* SVGElement */node){ + // summary + // move the passed node to the bottom of the group (i.e. first child) + var n=this.getGroup(node) || node; + n.ownerSVGElement.insertBefore(n, n.ownerSVGElement.firstChild); +}; + +// TODO: possibly push node up a level in the DOM if it's at the beginning or end of the childNodes list. +dojo.svg.bringForward=function(/* SVGElement */node){ + // summary + // move the passed node up one in the child node chain + var n=this.getGroup(node) || node; + if (this.getLastChildElement(n.parentNode) != n){ + this.insertAfter(n, this.getNextSiblingElement(n), true); + } +}; +dojo.svg.sendBackward=function(/* SVGElement */node){ + // summary + // move the passed node down one in the child node chain + var n=this.getGroup(node) || node; + if (this.getFirstChildElement(n.parentNode) != n){ + this.insertBefore(n, this.getPreviousSiblingElement(n), true); + } +}; +// END TODO ////////////////////////////////////////////////////// TODO + +dojo.svg.createNodesFromText=function(/* string */ txt, /* bool? */ wrap){ + // summary + // Create a list of nodes from text + var docFrag=(new DOMParser()).parseFromString(txt, "text/xml").normalize(); + if(wrap){ + return [docFrag.firstChild.cloneNode(true)]; // array + } + var nodes=[]; + for(var x=0; x 0; + this.canRedo = this._redoStack.length > 0; + }, + + clear: function() { + this._undoStack = []; + this._redoStack = []; + this._currentManager = this; + + this.isUndoing = false; + this.isRedoing = false; + + this._updateStatus(); + }, + + undo: function() { + if(!this.canUndo) { return false; } + + this.endAllTransactions(); + + this.isUndoing = true; + var top = this._undoStack.pop(); + if(top instanceof dojo.undo.Manager){ + top.undoAll(); + }else{ + top.undo(); + } + if(top.redo){ + this._redoStack.push(top); + } + this.isUndoing = false; + + this._updateStatus(); + this.onUndo(this, top); + if(!(top instanceof dojo.undo.Manager)) { + this.getTop().onUndoAny(this, top); + } + return true; + }, + + redo: function() { + if(!this.canRedo){ return false; } + + this.isRedoing = true; + var top = this._redoStack.pop(); + if(top instanceof dojo.undo.Manager) { + top.redoAll(); + }else{ + top.redo(); + } + this._undoStack.push(top); + this.isRedoing = false; + + this._updateStatus(); + this.onRedo(this, top); + if(!(top instanceof dojo.undo.Manager)){ + this.getTop().onRedoAny(this, top); + } + return true; + }, + + undoAll: function() { + while(this._undoStack.length > 0) { + this.undo(); + } + }, + + redoAll: function() { + while(this._redoStack.length > 0) { + this.redo(); + } + }, + + push: function(undo, redo /* optional */, description /* optional */) { + if(!undo) { return; } + + if(this._currentManager == this) { + this._undoStack.push({ + undo: undo, + redo: redo, + description: description + }); + } else { + this._currentManager.push.apply(this._currentManager, arguments); + } + // adding a new undo-able item clears out the redo stack + this._redoStack = []; + this._updateStatus(); + }, + + concat: function(manager) { + if ( !manager ) { return; } + + if (this._currentManager == this ) { + for(var x=0; x < manager._undoStack.length; x++) { + this._undoStack.push(manager._undoStack[x]); + } + // adding a new undo-able item clears out the redo stack + if (manager._undoStack.length > 0) { + this._redoStack = []; + } + this._updateStatus(); + } else { + this._currentManager.concat.apply(this._currentManager, arguments); + } + }, + + beginTransaction: function(description /* optional */) { + if(this._currentManager == this) { + var mgr = new dojo.undo.Manager(this); + mgr.description = description ? description : ""; + this._undoStack.push(mgr); + this._currentManager = mgr; + return mgr; + } else { + //for nested transactions need to make sure the top level _currentManager is set + this._currentManager = this._currentManager.beginTransaction.apply(this._currentManager, arguments); + } + }, + + endTransaction: function(flatten /* optional */) { + if(this._currentManager == this) { + if(this._parent) { + this._parent._currentManager = this._parent; + // don't leave empty transactions hangin' around + if(this._undoStack.length == 0 || flatten) { + var idx = dojo.lang.find(this._parent._undoStack, this); + if (idx >= 0) { + this._parent._undoStack.splice(idx, 1); + //add the current transaction to parents undo stack + if (flatten) { + for(var x=0; x < this._undoStack.length; x++){ + this._parent._undoStack.splice(idx++, 0, this._undoStack[x]); + } + this._updateStatus(); + } + } + } + return this._parent; + } + } else { + //for nested transactions need to make sure the top level _currentManager is set + this._currentManager = this._currentManager.endTransaction.apply(this._currentManager, arguments); + } + }, + + endAllTransactions: function() { + while(this._currentManager != this) { + this.endTransaction(); + } + }, + + // find the top parent of an undo manager + getTop: function() { + if(this._parent) { + return this._parent.getTop(); + } else { + return this; + } + } +}); Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/undo/Manager.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/undo/__package__.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/undo/__package__.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/undo/__package__.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/undo/__package__.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,2 @@ +dojo.require("dojo.undo.Manager"); +dojo.provide("dojo.undo.*"); Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/undo/__package__.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/undo/browser.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/undo/browser.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/undo/browser.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/undo/browser.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,299 @@ +dojo.provide("dojo.undo.browser"); +dojo.require("dojo.io.common"); + +try{ + if((!djConfig["preventBackButtonFix"])&&(!dojo.hostenv.post_load_)){ + document.write(""); + } +}catch(e){/* squelch */} + +if(dojo.render.html.opera){ + dojo.debug("Opera is not supported with dojo.undo.browser, so back/forward detection will not work."); +} + +/* NOTES: + * Safari 1.2: + * back button "works" fine, however it's not possible to actually + * DETECT that you've moved backwards by inspecting window.location. + * Unless there is some other means of locating. + * FIXME: perhaps we can poll on history.length? + * Safari 2.0.3+ (and probably 1.3.2+): + * works fine, except when changeUrl is used. When changeUrl is used, + * Safari jumps all the way back to whatever page was shown before + * the page that uses dojo.undo.browser support. + * IE 5.5 SP2: + * back button behavior is macro. It does not move back to the + * previous hash value, but to the last full page load. This suggests + * that the iframe is the correct way to capture the back button in + * these cases. + * Don't test this page using local disk for MSIE. MSIE will not create + * a history list for iframe_history.html if served from a file: URL. + * The XML served back from the XHR tests will also not be properly + * created if served from local disk. Serve the test pages from a web + * server to test in that browser. + * IE 6.0: + * same behavior as IE 5.5 SP2 + * Firefox 1.0+: + * the back button will return us to the previous hash on the same + * page, thereby not requiring an iframe hack, although we do then + * need to run a timer to detect inter-page movement. + */ + +dojo.undo.browser = { + initialHref: window.location.href, + initialHash: window.location.hash, + + moveForward: false, + historyStack: [], + forwardStack: [], + historyIframe: null, + bookmarkAnchor: null, + locationTimer: null, + + /** + * setInitialState sets the state object and back callback for the very first page that is loaded. + * It is recommended that you call this method as part of an event listener that is registered via + * dojo.addOnLoad(). + */ + setInitialState: function(args){ + this.initialState = this._createState(this.initialHref, args, this.initialHash); + }, + + //FIXME: Would like to support arbitrary back/forward jumps. Have to rework iframeLoaded among other things. + //FIXME: is there a slight race condition in moz using change URL with the timer check and when + // the hash gets set? I think I have seen a back/forward call in quick succession, but not consistent. + /** + * addToHistory takes one argument, and it is an object that defines the following functions: + * - To support getting back button notifications, the object argument should implement a + * function called either "back", "backButton", or "handle". The string "back" will be + * passed as the first and only argument to this callback. + * - To support getting forward button notifications, the object argument should implement a + * function called either "forward", "forwardButton", or "handle". The string "forward" will be + * passed as the first and only argument to this callback. + * - If you want the browser location string to change, define "changeUrl" on the object. If the + * value of "changeUrl" is true, then a unique number will be appended to the URL as a fragment + * identifier (http://some.domain.com/path#uniquenumber). If it is any other value that does + * not evaluate to false, that value will be used as the fragment identifier. For example, + * if changeUrl: 'page1', then the URL will look like: http://some.domain.com/path#page1 + * + * Full example: + * + * dojo.undo.browser.addToHistory({ + * back: function() { alert('back pressed'); }, + * forward: function() { alert('forward pressed'); }, + * changeUrl: true + * }); + */ + addToHistory: function(args){ + //If addToHistory is called, then that means we prune the + //forward stack -- the user went back, then wanted to + //start a new forward path. + this.forwardStack = []; + + var hash = null; + var url = null; + if(!this.historyIframe){ + this.historyIframe = window.frames["djhistory"]; + } + if(!this.bookmarkAnchor){ + this.bookmarkAnchor = document.createElement("a"); + dojo.body().appendChild(this.bookmarkAnchor); + this.bookmarkAnchor.style.display = "none"; + } + if(args["changeUrl"]){ + hash = "#"+ ((args["changeUrl"]!==true) ? args["changeUrl"] : (new Date()).getTime()); + + //If the current hash matches the new one, just replace the history object with + //this new one. It doesn't make sense to track different state objects for the same + //logical URL. This matches the browser behavior of only putting in one history + //item no matter how many times you click on the same #hash link, at least in Firefox + //and Safari, and there is no reliable way in those browsers to know if a #hash link + //has been clicked on multiple times. So making this the standard behavior in all browsers + //so that dojo.undo.browser's behavior is the same in all browsers. + if(this.historyStack.length == 0 && this.initialState.urlHash == hash){ + this.initialState = this._createState(url, args, hash); + return; + }else if(this.historyStack.length > 0 && this.historyStack[this.historyStack.length - 1].urlHash == hash){ + this.historyStack[this.historyStack.length - 1] = this._createState(url, args, hash); + return; + } + + this.changingUrl = true; + setTimeout("window.location.href = '"+hash+"'; dojo.undo.browser.changingUrl = false;", 1); + this.bookmarkAnchor.href = hash; + + if(dojo.render.html.ie){ + url = this._loadIframeHistory(); + + var oldCB = args["back"]||args["backButton"]||args["handle"]; + + //The function takes handleName as a parameter, in case the + //callback we are overriding was "handle". In that case, + //we will need to pass the handle name to handle. + var tcb = function(handleName){ + if(window.location.hash != ""){ + setTimeout("window.location.href = '"+hash+"';", 1); + } + //Use apply to set "this" to args, and to try to avoid memory leaks. + oldCB.apply(this, [handleName]); + } + + //Set interceptor function in the right place. + if(args["back"]){ + args.back = tcb; + }else if(args["backButton"]){ + args.backButton = tcb; + }else if(args["handle"]){ + args.handle = tcb; + } + + var oldFW = args["forward"]||args["forwardButton"]||args["handle"]; + + //The function takes handleName as a parameter, in case the + //callback we are overriding was "handle". In that case, + //we will need to pass the handle name to handle. + var tfw = function(handleName){ + if(window.location.hash != ""){ + window.location.href = hash; + } + if(oldFW){ // we might not actually have one + //Use apply to set "this" to args, and to try to avoid memory leaks. + oldFW.apply(this, [handleName]); + } + } + + //Set interceptor function in the right place. + if(args["forward"]){ + args.forward = tfw; + }else if(args["forwardButton"]){ + args.forwardButton = tfw; + }else if(args["handle"]){ + args.handle = tfw; + } + + }else if(dojo.render.html.moz){ + // start the timer + if(!this.locationTimer){ + this.locationTimer = setInterval("dojo.undo.browser.checkLocation();", 200); + } + } + }else{ + url = this._loadIframeHistory(); + } + + this.historyStack.push(this._createState(url, args, hash)); + }, + + checkLocation: function(){ + if (!this.changingUrl){ + var hsl = this.historyStack.length; + + if((window.location.hash == this.initialHash||window.location.href == this.initialHref)&&(hsl == 1)){ + // FIXME: could this ever be a forward button? + // we can't clear it because we still need to check for forwards. Ugg. + // clearInterval(this.locationTimer); + this.handleBackButton(); + return; + } + + // first check to see if we could have gone forward. We always halt on + // a no-hash item. + if(this.forwardStack.length > 0){ + if(this.forwardStack[this.forwardStack.length-1].urlHash == window.location.hash){ + this.handleForwardButton(); + return; + } + } + + // ok, that didn't work, try someplace back in the history stack + if((hsl >= 2)&&(this.historyStack[hsl-2])){ + if(this.historyStack[hsl-2].urlHash==window.location.hash){ + this.handleBackButton(); + return; + } + } + } + }, + + iframeLoaded: function(evt, ifrLoc){ + if(!dojo.render.html.opera){ + var query = this._getUrlQuery(ifrLoc.href); + if(query == null){ + // alert("iframeLoaded"); + // we hit the end of the history, so we should go back + if(this.historyStack.length == 1){ + this.handleBackButton(); + } + return; + } + if(this.moveForward){ + // we were expecting it, so it's not either a forward or backward movement + this.moveForward = false; + return; + } + + //Check the back stack first, since it is more likely. + //Note that only one step back or forward is supported. + if(this.historyStack.length >= 2 && query == this._getUrlQuery(this.historyStack[this.historyStack.length-2].url)){ + this.handleBackButton(); + } + else if(this.forwardStack.length > 0 && query == this._getUrlQuery(this.forwardStack[this.forwardStack.length-1].url)){ + this.handleForwardButton(); + } + } + }, + + handleBackButton: function(){ + //The "current" page is always at the top of the history stack. + var current = this.historyStack.pop(); + if(!current){ return; } + var last = this.historyStack[this.historyStack.length-1]; + if(!last && this.historyStack.length == 0){ + last = this.initialState; + } + if (last){ + if(last.kwArgs["back"]){ + last.kwArgs["back"](); + }else if(last.kwArgs["backButton"]){ + last.kwArgs["backButton"](); + }else if(last.kwArgs["handle"]){ + last.kwArgs.handle("back"); + } + } + this.forwardStack.push(current); + }, + + handleForwardButton: function(){ + var last = this.forwardStack.pop(); + if(!last){ return; } + if(last.kwArgs["forward"]){ + last.kwArgs.forward(); + }else if(last.kwArgs["forwardButton"]){ + last.kwArgs.forwardButton(); + }else if(last.kwArgs["handle"]){ + last.kwArgs.handle("forward"); + } + this.historyStack.push(last); + }, + + _createState: function(url, args, hash){ + return {"url": url, "kwArgs": args, "urlHash": hash}; + }, + + _getUrlQuery: function(url){ + var segments = url.split("?"); + if (segments.length < 2){ + return null; + } + else{ + return segments[1]; + } + }, + + _loadIframeHistory: function(){ + var url = dojo.hostenv.getBaseScriptUri()+"iframe_history.html?"+(new Date()).getTime(); + this.moveForward = true; + dojo.io.setIFrameSrc(this.historyIframe, url, false); + return url; + } +} Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/undo/browser.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/uri/Uri.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/uri/Uri.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/uri/Uri.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/uri/Uri.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,100 @@ +dojo.provide("dojo.uri.Uri"); + +dojo.uri = new function() { + this.dojoUri = function (/*dojo.uri.Uri||String*/uri) { + // summary: returns a Uri object resolved relative to the dojo root + return new dojo.uri.Uri(dojo.hostenv.getBaseScriptUri(), uri); + } + + this.moduleUri = function(/*String*/module, /*dojo.uri.Uri||String*/uri){ + // summary: returns a Uri object relative to a (top-level) module + // description: Examples: dojo.uri.moduleUri("dojo","Editor"), or dojo.uri.moduleUri("acme","someWidget") + var loc = dojo.hostenv.getModulePrefix(module); + if(!loc){return null;} + if(loc.lastIndexOf("/") != loc.length-1){loc += "/";} + return new dojo.uri.Uri(dojo.hostenv.getBaseScriptUri()+loc,uri); + } + + this.Uri = function (/*dojo.uri.Uri||String...*/) { + // summary: Constructor to create an object representing a URI. + // description: + // Each argument is evaluated in order relative to the next until + // a canonical uri is produced. To get an absolute Uri relative + // to the current document use + // new dojo.uri.Uri(document.baseURI, uri) + + // TODO: support for IPv6, see RFC 2732 + + // resolve uri components relative to each other + var uri = arguments[0]; + for (var i = 1; i < arguments.length; i++) { + if(!arguments[i]) { continue; } + + // Safari doesn't support this.constructor so we have to be explicit + var relobj = new dojo.uri.Uri(arguments[i].toString()); + var uriobj = new dojo.uri.Uri(uri.toString()); + + if ((relobj.path=="")&&(relobj.scheme==null)&&(relobj.authority==null)&&(relobj.query==null)) { + if (relobj.fragment != null) { uriobj.fragment = relobj.fragment; } + relobj = uriobj; + } else if (relobj.scheme == null) { + relobj.scheme = uriobj.scheme; + + if (relobj.authority == null) { + relobj.authority = uriobj.authority; + + if (relobj.path.charAt(0) != "/") { + var path = uriobj.path.substring(0, + uriobj.path.lastIndexOf("/") + 1) + relobj.path; + + var segs = path.split("/"); + for (var j = 0; j < segs.length; j++) { + if (segs[j] == ".") { + if (j == segs.length - 1) { segs[j] = ""; } + else { segs.splice(j, 1); j--; } + } else if (j > 0 && !(j == 1 && segs[0] == "") && + segs[j] == ".." && segs[j-1] != "..") { + + if (j == segs.length - 1) { segs.splice(j, 1); segs[j - 1] = ""; } + else { segs.splice(j - 1, 2); j -= 2; } + } + } + relobj.path = segs.join("/"); + } + } + } + + uri = ""; + if (relobj.scheme != null) { uri += relobj.scheme + ":"; } + if (relobj.authority != null) { uri += "//" + relobj.authority; } + uri += relobj.path; + if (relobj.query != null) { uri += "?" + relobj.query; } + if (relobj.fragment != null) { uri += "#" + relobj.fragment; } + } + + this.uri = uri.toString(); + + // break the uri into its main components + var regexp = "^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"; + var r = this.uri.match(new RegExp(regexp)); + + this.scheme = r[2] || (r[1] ? "" : null); + this.authority = r[4] || (r[3] ? "" : null); + this.path = r[5]; // can never be undefined + this.query = r[7] || (r[6] ? "" : null); + this.fragment = r[9] || (r[8] ? "" : null); + + if (this.authority != null) { + // server based naming authority + regexp = "^((([^:]+:)?([^@]+))@)?([^:]*)(:([0-9]+))?$"; + r = this.authority.match(new RegExp(regexp)); + + this.user = r[3] || null; + this.password = r[4] || null; + this.host = r[5]; + this.port = r[7] || null; + } + + this.toString = function(){ return this.uri; } + } +}; Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/uri/Uri.js ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/uri/__package__.js URL: http://svn.apache.org/viewvc/jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/uri/__package__.js?view=auto&rev=473755 ============================================================================== --- jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/uri/__package__.js (added) +++ jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/uri/__package__.js Sat Nov 11 08:44:22 2006 @@ -0,0 +1,4 @@ +dojo.kwCompoundRequire({ + common: [["dojo.uri.Uri", false, false]] +}); +dojo.provide("dojo.uri.*"); Propchange: jackrabbit/trunk/contrib/jcr-browser/src/main/webapp/dojo/src/uri/__package__.js ------------------------------------------------------------------------------ svn:eol-style = native