aboutsummaryrefslogtreecommitdiff
path: root/includes/js/dijit/layout/ContentPane.js
diff options
context:
space:
mode:
Diffstat (limited to 'includes/js/dijit/layout/ContentPane.js')
-rw-r--r--includes/js/dijit/layout/ContentPane.js445
1 files changed, 445 insertions, 0 deletions
diff --git a/includes/js/dijit/layout/ContentPane.js b/includes/js/dijit/layout/ContentPane.js
new file mode 100644
index 0000000..c3a4ca4
--- /dev/null
+++ b/includes/js/dijit/layout/ContentPane.js
@@ -0,0 +1,445 @@
+if(!dojo._hasResource["dijit.layout.ContentPane"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit.layout.ContentPane"] = true;
+dojo.provide("dijit.layout.ContentPane");
+
+dojo.require("dijit._Widget");
+dojo.require("dijit.layout._LayoutWidget");
+
+dojo.require("dojo.parser");
+dojo.require("dojo.string");
+dojo.requireLocalization("dijit", "loading", null, "zh,pt,da,tr,ru,ROOT,de,sv,ja,he,fi,nb,el,ar,pt-pt,cs,fr,es,ko,nl,zh-tw,pl,it,hu");
+
+dojo.declare(
+ "dijit.layout.ContentPane",
+ dijit._Widget,
+{
+ // summary:
+ // A widget that acts as a Container for other widgets, and includes a ajax interface
+ // description:
+ // A widget that can be used as a standalone widget
+ // or as a baseclass for other widgets
+ // Handles replacement of document fragment using either external uri or javascript
+ // generated markup or DOM content, instantiating widgets within that content.
+ // Don't confuse it with an iframe, it only needs/wants document fragments.
+ // It's useful as a child of LayoutContainer, SplitContainer, or TabContainer.
+ // But note that those classes can contain any widget as a child.
+ // example:
+ // Some quick samples:
+ // To change the innerHTML use .setContent('<b>new content</b>')
+ //
+ // Or you can send it a NodeList, .setContent(dojo.query('div [class=selected]', userSelection))
+ // please note that the nodes in NodeList will copied, not moved
+ //
+ // To do a ajax update use .setHref('url')
+ //
+ // href: String
+ // The href of the content that displays now.
+ // Set this at construction if you want to load data externally when the
+ // pane is shown. (Set preload=true to load it immediately.)
+ // Changing href after creation doesn't have any effect; see setHref();
+ href: "",
+
+ // extractContent: Boolean
+ // Extract visible content from inside of <body> .... </body>
+ extractContent: false,
+
+ // parseOnLoad: Boolean
+ // parse content and create the widgets, if any
+ parseOnLoad: true,
+
+ // preventCache: Boolean
+ // Cache content retreived externally
+ preventCache: false,
+
+ // preload: Boolean
+ // Force load of data even if pane is hidden.
+ preload: false,
+
+ // refreshOnShow: Boolean
+ // Refresh (re-download) content when pane goes from hidden to shown
+ refreshOnShow: false,
+
+ // loadingMessage: String
+ // Message that shows while downloading
+ loadingMessage: "<span class='dijitContentPaneLoading'>${loadingState}</span>",
+
+ // errorMessage: String
+ // Message that shows if an error occurs
+ errorMessage: "<span class='dijitContentPaneError'>${errorState}</span>",
+
+ // isLoaded: Boolean
+ // Tells loading status see onLoad|onUnload for event hooks
+ isLoaded: false,
+
+ // class: String
+ // Class name to apply to ContentPane dom nodes
+ // TODO: this should be called "baseClass" like in the other widgets
+ "class": "dijitContentPane",
+
+ // doLayout: String/Boolean
+ // false - don't adjust size of children
+ // true - looks for the first sizable child widget (ie, having resize() method) and sets it's size to
+ // however big the ContentPane is (TODO: implement)
+ // auto - if there is a single sizable child widget (ie, having resize() method), set it's size to
+ // however big the ContentPane is
+ doLayout: "auto",
+
+ postCreate: function(){
+ // remove the title attribute so it doesn't show up when i hover
+ // over a node
+ this.domNode.title = "";
+
+ if(!this.containerNode){
+ // make getDescendants() work
+ this.containerNode = this.domNode;
+ }
+
+ if(this.preload){
+ this._loadCheck();
+ }
+
+ var messages = dojo.i18n.getLocalization("dijit", "loading", this.lang);
+ this.loadingMessage = dojo.string.substitute(this.loadingMessage, messages);
+ this.errorMessage = dojo.string.substitute(this.errorMessage, messages);
+ var curRole = dijit.getWaiRole(this.domNode);
+ if (!curRole){
+ dijit.setWaiRole(this.domNode, "group");
+ }
+
+ // for programatically created ContentPane (with <span> tag), need to muck w/CSS
+ // or it's as though overflow:visible is set
+ dojo.addClass(this.domNode, this["class"]);
+ },
+
+ startup: function(){
+ if(this._started){ return; }
+ if(this.doLayout != "false" && this.doLayout !== false){
+ this._checkIfSingleChild();
+ if(this._singleChild){
+ this._singleChild.startup();
+ }
+ }
+ this._loadCheck();
+ this.inherited(arguments);
+ },
+
+ _checkIfSingleChild: function(){
+ // summary:
+ // Test if we have exactly one widget as a child, and if so assume that we are a container for that widget,
+ // and should propogate startup() and resize() calls to it.
+
+ // TODO: if there are two child widgets (a data store and a TabContainer, for example),
+ // should still find the TabContainer
+ var childNodes = dojo.query(">", this.containerNode || this.domNode),
+ childWidgets = childNodes.filter("[widgetId]");
+
+ if(childNodes.length == 1 && childWidgets.length == 1){
+ this.isContainer = true;
+ this._singleChild = dijit.byNode(childWidgets[0]);
+ }else{
+ delete this.isContainer;
+ delete this._singleChild;
+ }
+ },
+
+ refresh: function(){
+ // summary:
+ // Force a refresh (re-download) of content, be sure to turn off cache
+
+ // we return result of _prepareLoad here to avoid code dup. in dojox.layout.ContentPane
+ return this._prepareLoad(true);
+ },
+
+ setHref: function(/*String|Uri*/ href){
+ // summary:
+ // Reset the (external defined) content of this pane and replace with new url
+ // Note: It delays the download until widget is shown if preload is false
+ // href:
+ // url to the page you want to get, must be within the same domain as your mainpage
+ this.href = href;
+
+ // we return result of _prepareLoad here to avoid code dup. in dojox.layout.ContentPane
+ return this._prepareLoad();
+ },
+
+ setContent: function(/*String|DomNode|Nodelist*/data){
+ // summary:
+ // Replaces old content with data content, include style classes from old content
+ // data:
+ // the new Content may be String, DomNode or NodeList
+ //
+ // if data is a NodeList (or an array of nodes) nodes are copied
+ // so you can import nodes from another document implicitly
+
+ // clear href so we cant run refresh and clear content
+ // refresh should only work if we downloaded the content
+ if(!this._isDownloaded){
+ this.href = "";
+ this._onUnloadHandler();
+ }
+
+ this._setContent(data || "");
+
+ this._isDownloaded = false; // must be set after _setContent(..), pathadjust in dojox.layout.ContentPane
+
+ if(this.parseOnLoad){
+ this._createSubWidgets();
+ }
+
+ if(this.doLayout != "false" && this.doLayout !== false){
+ this._checkIfSingleChild();
+ if(this._singleChild && this._singleChild.resize){
+ this._singleChild.startup();
+ this._singleChild.resize(this._contentBox || dojo.contentBox(this.containerNode || this.domNode));
+ }
+ }
+
+ this._onLoadHandler();
+ },
+
+ cancel: function(){
+ // summary:
+ // Cancels a inflight download of content
+ if(this._xhrDfd && (this._xhrDfd.fired == -1)){
+ this._xhrDfd.cancel();
+ }
+ delete this._xhrDfd; // garbage collect
+ },
+
+ destroy: function(){
+ // if we have multiple controllers destroying us, bail after the first
+ if(this._beingDestroyed){
+ return;
+ }
+ // make sure we call onUnload
+ this._onUnloadHandler();
+ this._beingDestroyed = true;
+ this.inherited("destroy",arguments);
+ },
+
+ resize: function(size){
+ dojo.marginBox(this.domNode, size);
+
+ // Compute content box size in case we [later] need to size child
+ // If either height or width wasn't specified by the user, then query node for it.
+ // But note that setting the margin box and then immediately querying dimensions may return
+ // inaccurate results, so try not to depend on it.
+ var node = this.containerNode || this.domNode,
+ mb = dojo.mixin(dojo.marginBox(node), size||{});
+
+ this._contentBox = dijit.layout.marginBox2contentBox(node, mb);
+
+ // If we have a single widget child then size it to fit snugly within my borders
+ if(this._singleChild && this._singleChild.resize){
+ this._singleChild.resize(this._contentBox);
+ }
+ },
+
+ _prepareLoad: function(forceLoad){
+ // sets up for a xhrLoad, load is deferred until widget onShow
+ // cancels a inflight download
+ this.cancel();
+ this.isLoaded = false;
+ this._loadCheck(forceLoad);
+ },
+
+ _isShown: function(){
+ // summary: returns true if the content is currently shown
+ if("open" in this){
+ return this.open; // for TitlePane, etc.
+ }else{
+ var node = this.domNode;
+ return (node.style.display != 'none') && (node.style.visibility != 'hidden');
+ }
+ },
+
+ _loadCheck: function(/*Boolean*/ forceLoad){
+ // call this when you change onShow (onSelected) status when selected in parent container
+ // it's used as a trigger for href download when this.domNode.display != 'none'
+
+ // sequence:
+ // if no href -> bail
+ // forceLoad -> always load
+ // this.preload -> load when download not in progress, domNode display doesn't matter
+ // this.refreshOnShow -> load when download in progress bails, domNode display !='none' AND
+ // this.open !== false (undefined is ok), isLoaded doesn't matter
+ // else -> load when download not in progress, if this.open !== false (undefined is ok) AND
+ // domNode display != 'none', isLoaded must be false
+
+ var displayState = this._isShown();
+
+ if(this.href &&
+ (forceLoad ||
+ (this.preload && !this._xhrDfd) ||
+ (this.refreshOnShow && displayState && !this._xhrDfd) ||
+ (!this.isLoaded && displayState && !this._xhrDfd)
+ )
+ ){
+ this._downloadExternalContent();
+ }
+ },
+
+ _downloadExternalContent: function(){
+ this._onUnloadHandler();
+
+ // display loading message
+ this._setContent(
+ this.onDownloadStart.call(this)
+ );
+
+ var self = this;
+ var getArgs = {
+ preventCache: (this.preventCache || this.refreshOnShow),
+ url: this.href,
+ handleAs: "text"
+ };
+ if(dojo.isObject(this.ioArgs)){
+ dojo.mixin(getArgs, this.ioArgs);
+ }
+
+ var hand = this._xhrDfd = (this.ioMethod || dojo.xhrGet)(getArgs);
+
+ hand.addCallback(function(html){
+ try{
+ self.onDownloadEnd.call(self);
+ self._isDownloaded = true;
+ self.setContent.call(self, html); // onload event is called from here
+ }catch(err){
+ self._onError.call(self, 'Content', err); // onContentError
+ }
+ delete self._xhrDfd;
+ return html;
+ });
+
+ hand.addErrback(function(err){
+ if(!hand.cancelled){
+ // show error message in the pane
+ self._onError.call(self, 'Download', err); // onDownloadError
+ }
+ delete self._xhrDfd;
+ return err;
+ });
+ },
+
+ _onLoadHandler: function(){
+ this.isLoaded = true;
+ try{
+ this.onLoad.call(this);
+ }catch(e){
+ console.error('Error '+this.widgetId+' running custom onLoad code');
+ }
+ },
+
+ _onUnloadHandler: function(){
+ this.isLoaded = false;
+ this.cancel();
+ try{
+ this.onUnload.call(this);
+ }catch(e){
+ console.error('Error '+this.widgetId+' running custom onUnload code');
+ }
+ },
+
+ _setContent: function(cont){
+ this.destroyDescendants();
+
+ try{
+ var node = this.containerNode || this.domNode;
+ while(node.firstChild){
+ dojo._destroyElement(node.firstChild);
+ }
+ if(typeof cont == "string"){
+ // dijit.ContentPane does only minimal fixes,
+ // No pathAdjustments, script retrieval, style clean etc
+ // some of these should be available in the dojox.layout.ContentPane
+ if(this.extractContent){
+ match = cont.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
+ if(match){ cont = match[1]; }
+ }
+ node.innerHTML = cont;
+ }else{
+ // domNode or NodeList
+ if(cont.nodeType){ // domNode (htmlNode 1 or textNode 3)
+ node.appendChild(cont);
+ }else{// nodelist or array such as dojo.Nodelist
+ dojo.forEach(cont, function(n){
+ node.appendChild(n.cloneNode(true));
+ });
+ }
+ }
+ }catch(e){
+ // check if a domfault occurs when we are appending this.errorMessage
+ // like for instance if domNode is a UL and we try append a DIV
+ var errMess = this.onContentError(e);
+ try{
+ node.innerHTML = errMess;
+ }catch(e){
+ console.error('Fatal '+this.id+' could not change content due to '+e.message, e);
+ }
+ }
+ },
+
+ _onError: function(type, err, consoleText){
+ // shows user the string that is returned by on[type]Error
+ // overide on[type]Error and return your own string to customize
+ var errText = this['on' + type + 'Error'].call(this, err);
+ if(consoleText){
+ console.error(consoleText, err);
+ }else if(errText){// a empty string won't change current content
+ this._setContent.call(this, errText);
+ }
+ },
+
+ _createSubWidgets: function(){
+ // summary: scan my contents and create subwidgets
+ var rootNode = this.containerNode || this.domNode;
+ try{
+ dojo.parser.parse(rootNode, true);
+ }catch(e){
+ this._onError('Content', e, "Couldn't create widgets in "+this.id
+ +(this.href ? " from "+this.href : ""));
+ }
+ },
+
+ // EVENT's, should be overide-able
+ onLoad: function(e){
+ // summary:
+ // Event hook, is called after everything is loaded and widgetified
+ },
+
+ onUnload: function(e){
+ // summary:
+ // Event hook, is called before old content is cleared
+ },
+
+ onDownloadStart: function(){
+ // summary:
+ // called before download starts
+ // the string returned by this function will be the html
+ // that tells the user we are loading something
+ // override with your own function if you want to change text
+ return this.loadingMessage;
+ },
+
+ onContentError: function(/*Error*/ error){
+ // summary:
+ // called on DOM faults, require fault etc in content
+ // default is to display errormessage inside pane
+ },
+
+ onDownloadError: function(/*Error*/ error){
+ // summary:
+ // Called when download error occurs, default is to display
+ // errormessage inside pane. Overide function to change that.
+ // The string returned by this function will be the html
+ // that tells the user a error happend
+ return this.errorMessage;
+ },
+
+ onDownloadEnd: function(){
+ // summary:
+ // called when download is finished
+ }
+});
+
+}