2009-09-22 15:26:41 +00:00
/// <reference path="/umbraco_client/Application/NamespaceManager.js" />
/// <reference path="/umbraco_client/Application/UmbracoUtils.js" />
2009-06-19 07:39:16 +00:00
/// <reference path="/umbraco_client/ui/jquery.js" />
/// <reference path="/umbraco_client/ui/jqueryui.js" />
/// <reference path="tree_component.js" />
/// <reference path="/umbraco_client/Application/UmbracoApplicationActions.js" />
/// <reference path="NodeDefinition.js" />
/// <reference name="MicrosoftAjax.js"/>
Umbraco . Sys . registerNamespace ( "Umbraco.Controls" );
( function ( $ ) {
2010-03-15 15:17:38 +00:00
2009-06-19 07:39:16 +00:00
$ . fn . UmbracoTree = function ( opts ) {
2010-03-15 15:17:38 +00:00
/// <summary>jQuery plugin to create an Umbraco tree. See option remarks below.</summary>
2009-06-19 07:39:16 +00:00
return this . each ( function () {
2010-03-15 15:17:38 +00:00
new Umbraco . Controls . UmbracoTree (). init ( $ ( this ), opts );
2009-06-19 07:39:16 +00:00
});
};
$ . fn . UmbracoTreeAPI = function () {
/// <summary>exposes the Umbraco Tree api for the selected object</summary>
2010-02-08 02:22:42 +00:00
if ( $ ( this ). length != 1 ) {
2010-03-03 15:19:51 +00:00
throw "UmbracoTreeAPI selector requires that there be exactly one control selected, this selector returns " + $ ( this ). length ;
2010-02-08 02:22:42 +00:00
};
// check if there's an api stored for the id of the object specified, if there's not
// check if the first child is a div and if that has the api specified
var api = Umbraco . Controls . UmbracoTree . inst [ $ ( this ). attr ( "id" )] || null ;
if ( api == null )
return Umbraco . Controls . UmbracoTree . inst [ $ ( this ). children ( "div" ). attr ( "id" )] || null ;
return api ;
2009-06-19 07:39:16 +00:00
};
2010-03-15 15:17:38 +00:00
Umbraco . Controls . TreeDefaultOptions = function () {
return {
doNotInit : false , //this is used for the main umbraco tree so that the tree doesn't fully initialize until rebuildTree is explicitly called
jsonFullMenu : {}, //The tree menu, by default is empty
appActions : null , //A reference to a MenuActions object
deletingText : "Deleting..." , //the txt to display when a node is deleting
treeMode : "standard" , //determines the type of tree: false/null = normal, 'checkbox' = checkboxes enabled, 'inheritedcheckbox' = parent nodes have checks inherited from children
recycleBinId : - 20 , //the id of the recycle bin for the current tree
serviceUrl : "" , //Url path for the tree client service
dataUrl : "" , //Url path for the tree data service
//These are all properties of the ITreeService and are
//used to pass the properties in to the InitAppTreeData service
app : "" , //the application name to render
treeType : "" , //the active tree application
showContext : true , //boolean indicating whether or not to show a context menu
isDialog : false ,
dialogMode : "none" , //boolean indicating whether or not the tree is in dialog mode
functionToCall : "" ,
nodeKey : ""
};
}
2009-06-19 07:39:16 +00:00
Umbraco . Controls . UmbracoTree = function () {
/// <summary>
/// The object that manages the Umbraco tree.
/// Has these events: syncNotFound, syncFound, rebuiltTree, newchildNodeFound, nodeMoved, nodeCopied, ajaxError, nodeClicked
/// </summary>
return {
2010-03-15 15:17:38 +00:00
_opts : {},
_cntr : ++ Umbraco . Controls . UmbracoTree . cntr , //increments the number of tree instances.
2010-02-08 02:22:42 +00:00
_containerId : null ,
_context : null , //the jquery context used to get the container
2009-06-19 07:39:16 +00:00
_actionNode : new Umbraco . Controls . NodeDefinition (), //the most recent node right clicked for context menu
_activeTreeType : "content" , //tracks which is the active tree type, this is used in searching and syncing.
_tree : null , //reference to the jsTree object
2010-03-15 15:17:38 +00:00
_isEditMode : false , //not really used YET
2010-06-23 15:24:39 +00:00
_isDebug : false , //set to true to enable alert debugging
2009-06-19 07:39:16 +00:00
_loadedApps : [], //stores the application names that have been loaded to track which JavaScript code has been inserted into the DOM
_treeClass : "umbTree" , //used for other libraries to detect which elements are an umbraco tree
2009-06-20 21:59:38 +00:00
_currenAJAXRequest : false , //used to determine if there is currently an ajax request being executed.
2010-06-07 10:49:52 +00:00
_isSyncing : false ,
2009-06-19 07:39:16 +00:00
addEventHandler : function ( fnName , fn ) {
/// <summary>Adds an event listener to the event name event</summary>
2010-04-08 13:27:33 +00:00
this . _getContainer (). bind ( fnName , fn );
2009-06-19 07:39:16 +00:00
},
removeEventHandler : function ( fnName , fn ) {
/// <summary>Removes an event listener to the event name event</summary>
2010-04-08 13:27:33 +00:00
this . _getContainer (). unbind ( fnName , fn );
},
_raiseEvent : function ( evName , args ) {
/// <summary>Raises an event and attaches it to the container</summary>
this . _getContainer (). trigger ( evName , args );
2009-06-19 07:39:16 +00:00
},
2010-03-15 15:17:38 +00:00
init : function ( jItem , opts ) {
2009-06-19 07:39:16 +00:00
/// <summary>Initializes the tree with the options and stores the tree API in the jQuery data object for the current element</summary>
2010-02-08 02:22:42 +00:00
this . _debug ( "init: creating new tree with class/id: " + jItem . attr ( "class" ) + " / " + jItem . attr ( "id" ));
2010-03-15 15:17:38 +00:00
this . _opts = $ . extend ( Umbraco . Controls . TreeDefaultOptions (), opts );
2010-02-08 02:22:42 +00:00
this . _context = jItem . get ( 0 ). ownerDocument ;
//wire up event handlers
2010-03-15 15:17:38 +00:00
if ( this . _opts . appActions != null ) {
2010-02-08 02:22:42 +00:00
var _this = this ;
//wrapped functions maintain scope
2010-03-15 15:17:38 +00:00
this . _opts . appActions . addEventHandler ( "nodeDeleting" , function ( E ) { _this . onNodeDeleting ( E ) });
this . _opts . appActions . addEventHandler ( "nodeDeleted" , function ( E ) { _this . onNodeDeleted ( E ) });
this . _opts . appActions . addEventHandler ( "nodeRefresh" , function ( E ) { _this . onNodeRefresh ( E ) });
2010-02-08 02:22:42 +00:00
}
this . _containerId = jItem . attr ( "id" );
2010-03-15 15:17:38 +00:00
if ( ! this . _opts . doNotInit ) {
//initializes the jsTree
this . _tree = $ . tree . create ();
this . _tree . init ( this . _getContainer (), this . _getInitOptions ());
}
2010-02-08 02:22:42 +00:00
2009-06-19 07:39:16 +00:00
jItem . addClass ( this . _treeClass );
2010-02-08 02:22:42 +00:00
//store a reference to this api by the id and the counter
Umbraco . Controls . UmbracoTree . inst [ this . _cntr ] = this ;
if ( ! this . _getContainer (). attr ( "id" )) this . _getContainer (). attr ( "id" , "UmbTree_" + this . _cntr );
Umbraco . Controls . UmbracoTree . inst [ this . _getContainer (). attr ( "id" )] = Umbraco . Controls . UmbracoTree . inst [ this . _cntr ];
2009-06-19 07:39:16 +00:00
},
2009-08-31 15:05:47 +00:00
setRecycleBinNodeId : function ( id ) {
2010-03-15 15:17:38 +00:00
this . _opts . recycleBinId = id ;
2009-08-31 15:05:47 +00:00
},
2009-08-12 16:53:24 +00:00
clearTreeCache : function () {
// <summary>This will remove all stored trees in client side cache so that the next time a tree needs loading it will be refreshed</summary>
this . _debug ( "clearTreeCache..." );
2010-04-15 13:28:45 +00:00
this . _loadedApps = [];
2009-08-12 16:53:24 +00:00
},
2009-09-21 15:39:59 +00:00
toggleEditMode : function ( enable ) {
this . _debug ( "Edit mode. Currently: " + this . _tree . settings . rules . draggable );
this . _isEditMode = enable ;
2009-10-19 13:35:14 +00:00
2010-03-15 15:17:38 +00:00
this . saveTreeState ( this . _opts . app );
2009-09-21 15:39:59 +00:00
//need to trick the system so it thinks it's a different app, then rebuild with new rules
2010-03-15 15:17:38 +00:00
var app = this . _opts . app ;
this . _opts . app = "temp" ;
2009-09-21 15:39:59 +00:00
this . rebuildTree ( app );
2009-10-19 13:35:14 +00:00
2009-09-21 15:39:59 +00:00
this . _debug ( "Edit mode. New Mode: " + this . _tree . settings . rules . draggable );
2010-03-15 15:17:38 +00:00
if ( this . _opts . appActions )
this . _opts . appActions . showSpeachBubble ( "info" , "Tree Edit Mode" , "The tree is now operating in edit mode" );
2009-09-21 15:39:59 +00:00
},
2010-04-27 14:17:15 +00:00
refreshTree : function ( treeType ) {
/// <summary>This wraps the standard jsTree functionality unless a treeType is specified. If one is, then it will just reload that nodes children</summary>
this . _debug ( "refreshTree: " + treeType );
if ( ! treeType ) {
2010-06-20 11:26:49 +00:00
this . rebuildTree ();
2010-04-27 14:17:15 +00:00
}
else {
var allRoots = this . _getContainer (). find ( "li[rel='rootNode']" );
var _this = this ;
var root = allRoots . filter ( function () {
return ( $ ( this ). attr ( "umb:type" ) == _this . _activeTreeType ); //filter based on custom namespace requires custom function
});
if ( root . length == 1 ) {
this . _debug ( "refreshTree: reloading tree type: " + treeType );
this . _loadChildNodes ( root );
}
else {
//couldn't find it, so refresh the whole tree
2010-06-20 11:26:49 +00:00
this . rebuildTree ();
2010-04-27 14:17:15 +00:00
}
}
2010-02-08 02:22:42 +00:00
},
2010-04-08 13:27:33 +00:00
rebuildTree : function ( app , callback ) {
2009-06-19 07:39:16 +00:00
/// <summary>This will rebuild the tree structure for the application specified</summary>
this . _debug ( "rebuildTree" );
2009-07-13 14:51:26 +00:00
2010-06-20 11:26:49 +00:00
//if app is null, then we will rebuild the current app which also means clearing the cache.
if ( ! app ) {
this . clearTreeCache ();
this . _opts . app = this . _opts . app ;
}
else if ( this . _tree && ( this . _opts . app . toLowerCase () == app . toLowerCase ())) {
2009-06-19 07:39:16 +00:00
this . _debug ( "not rebuilding" );
2010-06-20 11:26:49 +00:00
//don't rebuild if the tree object exists, the app that's being requested to be loaded is
//flagged as already loaded, and the tree actually has nodes in it
2009-06-19 07:39:16 +00:00
return ;
}
else {
2010-03-15 15:17:38 +00:00
this . _opts . app = app ;
2009-06-19 07:39:16 +00:00
}
//kill the tree
2010-04-08 13:27:33 +00:00
if ( this . _tree ) {
this . _tree . destroy ();
}
2009-10-19 13:35:14 +00:00
2009-06-19 07:39:16 +00:00
var _this = this ;
2009-07-13 14:51:26 +00:00
2009-06-20 13:17:06 +00:00
//check if we should rebuild from a saved tree
2010-02-08 02:22:42 +00:00
var saveData = this . _loadedApps [ "tree_" + app ];
2009-06-20 13:17:06 +00:00
if ( saveData != null ) {
2009-08-12 16:53:24 +00:00
this . _debug ( "rebuildTree: rebuilding from cache: app = " + app );
2009-07-13 14:51:26 +00:00
2009-06-20 13:17:06 +00:00
//create the tree from the saved data.
2009-10-11 12:23:27 +00:00
//this._initNode = saveData.d;
this . _tree = $ . tree . create ();
2010-02-08 02:22:42 +00:00
this . _tree . init ( this . _getContainer (), this . _getInitOptions ( saveData . d ));
2009-10-19 13:35:14 +00:00
//ensure the static data is gone
this . _tree . settings . data . opts . static = null ;
2010-02-08 02:22:42 +00:00
this . _configureNodes ( this . _getContainer (). find ( "li" ), true );
2009-06-20 21:59:38 +00:00
//select the last node
var lastSelected = saveData . selected != null ? $ ( saveData . selected [ 0 ]). attr ( "id" ) : null ;
2009-07-13 14:51:26 +00:00
if ( lastSelected != null ) {
2009-06-20 21:59:38 +00:00
//create an event handler for the tree sync
var _this = this ;
var foundHandler = function ( EV , node ) {
//remove the event handler from firing again
_this . removeEventHandler ( "syncFound" , foundHandler );
2010-04-08 13:27:33 +00:00
_this . _debug ( "rebuildTree: node synced, selecting node..." );
2009-06-20 21:59:38 +00:00
//ensure the node is selected, ensure the event is fired and reselect is true since jsTree thinks this node is already selected by id
_this . selectNode ( node , false , true );
};
this . _debug ( "rebuildTree: syncing to last selected: " + lastSelected );
//add the event handler for the tree sync and sync the tree
this . addEventHandler ( "syncFound" , foundHandler );
this . setActiveTreeType ( $ ( saveData . selected [ 0 ]). attr ( "umb:type" ));
2009-07-13 14:51:26 +00:00
this . syncTree ( lastSelected );
2009-06-20 21:59:38 +00:00
}
2009-07-13 14:51:26 +00:00
2010-04-08 13:27:33 +00:00
if ( typeof callback == "function" ) callback . apply ( this , [ lastSelected ]);
2009-06-20 13:17:06 +00:00
}
2009-10-19 13:35:14 +00:00
else {
this . _debug ( "rebuildTree: rebuilding from scratch: app = " + app );
2010-04-08 13:27:33 +00:00
this . _currentAJAXRequest = true ;
_this . _tree = $ . tree . create ();
_this . _tree . init ( _this . _getContainer (), _this . _getInitOptions ());
if ( typeof callback == "function" ) callback . apply ( this , []);
2009-10-19 13:35:14 +00:00
}
2009-06-19 07:39:16 +00:00
},
2009-07-13 14:51:26 +00:00
2009-06-20 13:17:06 +00:00
saveTreeState : function ( appAlias ) {
/// <summary>
/// Saves the state of the current application trees so we can restore it next time the user visits the app
/// </summary>
2009-07-13 14:51:26 +00:00
2009-06-20 21:59:38 +00:00
this . _debug ( "saveTreeState: " + appAlias + " : ajax request? " + this . _currentAJAXRequest );
2009-07-13 14:51:26 +00:00
2009-10-13 14:01:24 +00:00
//clear the saved data for the current app before saving
2010-02-08 02:22:42 +00:00
this . _loadedApps [ "tree_" + appAlias ] = null ;
2009-10-19 13:35:14 +00:00
2009-06-20 21:59:38 +00:00
//if an ajax request is currently in progress, abort saving the tree state and set the
//data object for the application to null.
2009-10-19 13:35:14 +00:00
if ( ! this . _currentAJAXRequest ) {
2009-10-13 14:01:24 +00:00
//only save the data if there are nodes
2010-02-08 02:22:42 +00:00
var nodeCount = this . _getContainer (). find ( "li[rel='dataNode']" ). length ;
2009-10-13 14:01:24 +00:00
if ( nodeCount > 0 ) {
this . _debug ( "saveTreeState: node count = " + nodeCount );
2009-10-19 13:35:14 +00:00
var treeData = this . _tree . get ();
2009-10-13 14:01:24 +00:00
//need to update the 'state' of the data. jsTree get doesn't return the state of nodes properly!
2009-10-19 13:35:14 +00:00
this . _updateJSONNodeState ( treeData );
2009-10-13 14:01:24 +00:00
this . _debug ( "saveTreeState: treeData = " + treeData );
2010-02-08 02:22:42 +00:00
this . _loadedApps [ "tree_" + appAlias ] = { selected : this . _tree . selected , d : treeData };
2009-10-13 14:01:24 +00:00
}
2009-06-20 21:59:38 +00:00
}
2009-06-20 13:17:06 +00:00
},
2009-07-13 14:51:26 +00:00
2009-06-20 13:17:06 +00:00
_updateJSONNodeState : function ( obj ) {
/// <summary>
/// A recursive function to store the state of the node for the JSON object when using saveTreeState.
/// This is required since jsTree doesn't output the state of the tree nodes with the request to getJSON method.
2009-10-11 12:23:27 +00:00
/// This is also required to save the correct title for each node since we store our title in a div tag, not just the a tag
2009-06-20 21:59:38 +00:00
/// </summary>
2009-07-13 14:51:26 +00:00
2009-06-20 21:59:38 +00:00
var node = $ ( "li[id='" + obj . attributes . id + "']" ). filter ( function () {
return ( $ ( this ). attr ( "umb:type" ) == obj . attributes [ "umb:type" ]); //filter based on custom namespace requires custom function
2009-07-13 14:51:26 +00:00
});
2009-10-19 13:35:14 +00:00
2009-10-11 12:23:27 +00:00
//saves the correct title
obj . data . title = $ . trim ( node . children ( "a" ). children ( "div" ). text ());
obj . state = obj . data . state ;
2010-03-15 15:17:38 +00:00
//ensures that the style property of the data contains only single quotes since jsTree puts double around the attr
for ( var i in obj . data . attributes ) {
if ( ! obj . data . attributes . hasOwnProperty ( i )) continue ;
2010-03-16 15:05:05 +00:00
if ( i == "style" || i == "class" ) {
obj . data . attributes [ i ] = obj . data . attributes [ i ]. replace ( /\"/g , "'" );
}
2010-03-15 15:17:38 +00:00
}
2009-10-19 13:35:14 +00:00
2009-10-11 12:23:27 +00:00
//recurse through children
2009-06-20 13:17:06 +00:00
if ( obj . children != null ) {
for ( var x in obj . children ) {
this . _updateJSONNodeState ( obj . children [ x ]);
}
}
},
2009-07-13 14:51:26 +00:00
2009-06-19 07:39:16 +00:00
syncTree : function ( path , forceReload ) {
/// <summary>
/// Syncronizes the tree with the path supplied and makes that node visible/selected.
/// </summary>
/// <param name="path">The path of the node</param>
/// <param name="forceReload">If true, will ensure that the node to be synced is synced with data from the server</param>
this . _debug ( "syncTree: " + path + ", " + forceReload );
2010-06-07 10:49:52 +00:00
//set the flag so that multiple synces aren't attempted
this . _isSyncing = true ;
2009-06-19 07:39:16 +00:00
this . _syncTree . call ( this , path , forceReload , null , null );
},
childNodeCreated : function () {
/// <summary>
/// Reloads the children of the current action node and selects the node that didn't exist there before.
/// If it cannot determine which node is new, then no node is selected. If the children are not already
/// loaded, then it is impossible for this method to determine which child is new.
/// </summary>
this . _debug ( "childNodeCreated" );
//store the current child ids so we can determine which one is the new one
var childrenIds = new Array ();
this . _actionNode . jsNode . find ( "ul > li" ). each ( function () {
childrenIds . push ( $ ( this ). attr ( "id" ));
});
var _this = this ;
var currId = this . _actionNode . nodeId ;
this . reloadActionNode ( true , false , function ( success ) {
if ( success && childrenIds . length > 0 ) {
var found = false ;
var actionNode = _this . findNode ( currId );
if ( actionNode ) {
actionNode . find ( "ul > li" ). each ( function () {
//if the id of the current child is not found in the original list, then this is the new one, store it
if ( $ . inArray ( $ ( this ). attr ( "id" ), childrenIds ) == - 1 ) {
found = $ ( this );
}
});
}
if ( found ) {
_this . _debug ( "childNodeCreated: selecting new child node: " + found . attr ( "id" ));
_this . selectNode ( found , true , true );
2010-04-08 13:27:33 +00:00
_this . _raiseEvent ( "newChildNodeFound" , [ found ]);
2009-06-19 07:39:16 +00:00
return ;
}
}
_this . _debug ( "childNodeCreated: could not select new child!" );
});
},
moveNode : function ( nodeId , parentPath ) {
/// <summary>Moves a node in the tree. This will remove the existing node by id and sync the tree to the new path</summary>
this . _debug ( "moveNode" );
//remove the old node
var old = this . findNode ( nodeId );
if ( old ) old . remove ();
//build the path to the new node
var newPath = parentPath + "," + nodeId ;
//create an event handler for the tree sync
var _this = this ;
var foundHandler = function ( EV , node ) {
//remove the event handler from firing again
_this . removeEventHandler ( "syncFound" , foundHandler );
//ensure the node is selected, ensure the event is fired and reselect is true since jsTree thinks this node is already selected by id
_this . selectNode ( node , false , true );
2010-04-08 13:27:33 +00:00
_this . _raiseEvent ( "nodeMoved" , [ node ]);
2009-06-19 07:39:16 +00:00
};
//add the event handler for the tree sync and sync the tree
this . addEventHandler ( "syncFound" , foundHandler );
this . syncTree ( newPath );
},
copyNode : function ( nodeId , parentPath ) {
/// <summary>Copies a node in the tree. This will keep the current node selected but will sync the tree to show the copied node too</summary>
this . _debug ( "copyNode" );
var originalNode = this . findNode ( nodeId );
//create an event handler for the tree sync
var _this = this ;
var foundHandler = function ( EV , node ) {
//remove the event handler from firing again
_this . removeEventHandler ( "syncFound" , foundHandler );
//now that the new parent node is found, expand it
_this . _loadChildNodes ( node , null );
//reselect the original node since sync will select the one that was copied
if ( originalNode ) _this . selectNode ( originalNode , true );
2010-04-08 13:27:33 +00:00
_this . _raiseEvent ( "nodeCopied" , [ node ]);
2009-06-19 07:39:16 +00:00
};
//add the event handler for the tree sync and sync the to the parent path
this . addEventHandler ( "syncFound" , foundHandler );
this . syncTree ( parentPath );
},
findNode : function ( nodeId , findGlobal ) {
/// <summary>Returns either the found branch or false if not found in the tree</summary>
/// <param name="findGlobal">Optional. If true, disregards the tree type and searches the entire tree for the id</param>
var _this = this ;
2010-02-08 02:22:42 +00:00
var branch = this . _getContainer (). find ( "li[id='" + nodeId + "']" );
2009-06-19 07:39:16 +00:00
if ( ! findGlobal ) branch = branch . filter ( function () {
return ( $ ( this ). attr ( "umb:type" ) == _this . _activeTreeType ); //filter based on custom namespace requires custom function
});
var found = branch . length > 0 ? branch : false ;
2010-04-27 14:17:15 +00:00
this . _debug ( "findNode: " + nodeId + " in '" + this . _activeTreeType + "' tree. Found? " + found );
2009-06-19 07:39:16 +00:00
return found ;
},
selectNode : function ( node , supressEvent , reselect ) {
2009-09-21 15:39:59 +00:00
/// <summary>
/// Makes the selected node the active node, but only if it is not already selected or if reselect is true.
/// </summary>
2009-06-19 07:39:16 +00:00
/// <param name="supressEvent">If set to true, will select the node but will supress the onSelected event</param>
/// <param name="reselect">If set to true, will call the select_branch method even if the node is already selected</param>
2009-10-19 13:35:14 +00:00
2010-04-08 13:27:33 +00:00
//this._debug("selectNode, edit mode? " + this._isEditMode);
2009-06-19 07:39:16 +00:00
var selectedId = this . _tree . selected != null ? $ ( this . _tree . selected [ 0 ]). attr ( "id" ) : null ;
2010-04-08 13:27:33 +00:00
this . _debug ( "selectNode (" + node . attr ( "id" ) + "). supressEvent? " + supressEvent + ", reselect? " + reselect );
2009-06-19 07:39:16 +00:00
if ( reselect || ( selectedId == null || selectedId != node . attr ( "id" ))) {
//if we don't wan the event to fire, we'll set the callback to a null method and set it back after we call the select_branch method
2009-09-21 15:39:59 +00:00
if ( supressEvent || this . _isEditMode ) {
2009-06-19 07:39:16 +00:00
this . _tree . settings . callback . onselect = function () { };
}
this . _tree . select_branch ( node );
//reset the method / maintain scope in callback
var _this = this ;
this . _tree . settings . callback . onselect = function ( N , T ) { _this . onSelect ( N , T ) };
}
2009-10-19 13:35:14 +00:00
2009-06-19 07:39:16 +00:00
},
reloadActionNode : function ( supressSelect , supressChildReload , callback ) {
/// <summary>
/// Gets the current action node's parent's data source url, then passes this url and the current action node's id
/// to a web service. The webservice will find the JSON data for the current action node and return it. This
/// will parse the returned JSON into html and replace the current action nodes' markup with the refreshed server data.
/// If by chance, the ajax call fails because of inconsistent data (a developer has implemented poor tree design), then
/// this use the build in jsTree reload which works ok.
/// </summary>
/// <param name="callback">
/// A callback function which will have a boolean parameter passed. True = the reload was succesful,
/// False = the reload failed and the generic _tree.refresh() method was used.
/// </param>
this . _debug ( "reloadActionNode: supressSelect = " + supressSelect + ", supressChildReload = " + supressChildReload );
if ( this . _actionNode != null && this . _actionNode . jsNode != null ) {
var nodeParent = this . _actionNode . jsNode . parents ( "li:first" );
this . _debug ( "reloadActionNode: found " + nodeParent . length + " parent nodes" );
if ( nodeParent . length == 1 ) {
2009-10-11 12:23:27 +00:00
var nodeDef = this . getNodeDef ( nodeParent );
2009-06-19 07:39:16 +00:00
this . _debug ( "reloadActionNode: loading ajax for node: " + nodeDef . nodeId );
var _this = this ;
//replace the node to refresh with loading and return the new loading element
2009-10-11 12:23:27 +00:00
var toReplace = $ ( "<li class='last'><a class='loading' href='#'><ins></ins><div>" + ( this . _tree . settings . lang . loading || "Loading ..." ) + "</div></a></li>" ). replaceAll ( this . _actionNode . jsNode );
2009-06-19 07:39:16 +00:00
$ . get ( this . _getUrl ( nodeDef . sourceUrl ), null ,
function ( msg ) {
if ( ! msg || msg . length == 0 ) {
_this . _debug ( "reloadActionNode: error loading ajax data, performing jsTree refresh" );
2010-06-20 11:26:49 +00:00
_this . rebuildTree (); /*try jsTree refresh as last resort */
2009-06-19 07:39:16 +00:00
if ( callback != null ) callback . call ( _this , false );
return ;
}
//filter the results to find the object corresponding to the one we want refreshed
var oFound = null ;
for ( var o in msg ) {
if ( msg [ o ]. attributes != null && msg [ o ]. attributes . id == _this . _actionNode . nodeId ) {
2009-10-11 12:23:27 +00:00
oFound = $ . tree . datastores . json (). parse ( msg [ o ], _this . _tree );
2009-06-19 07:39:16 +00:00
//ensure the tree type is the same too
if ( $ ( oFound ). attr ( "umb:type" ) == _this . _actionNode . treeType ) { break ; }
else { oFound = null ; }
}
}
if ( oFound != null ) {
2009-10-11 12:23:27 +00:00
_this . _debug ( "reloadActionNode: node is refreshed! : " + supressSelect );
2009-06-19 07:39:16 +00:00
var reloaded = $ ( oFound ). replaceAll ( toReplace );
_this . _configureNodes ( reloaded , true );
2009-10-11 12:23:27 +00:00
if ( ! supressSelect ) _this . selectNode ( reloaded , true , true );
2009-06-19 07:39:16 +00:00
if ( ! supressChildReload ) {
_this . _loadChildNodes ( reloaded , function () {
if ( callback != null ) callback . call ( _this , true );
});
}
else { if ( callback != null ) callback . call ( _this , true ); }
}
else {
_this . _debug ( "reloadActionNode: error finding child node in ajax data, performing jsTree refresh" );
2010-06-20 11:26:49 +00:00
_this . rebuildTree (); /*try jsTree refresh as last resort */
2009-06-19 07:39:16 +00:00
if ( callback != null ) callback . call ( _this , false );
}
}, "json" );
return ;
}
this . _debug ( "reloadActionNode: error finding parent node, performing jsTree refresh" );
2010-06-20 11:26:49 +00:00
this . rebuildTree (); /*try jsTree refresh as last resort */
2009-06-19 07:39:16 +00:00
if ( callback != null ) callback . call ( this , false );
}
},
getActionNode : function () {
/// <summary>Returns the latest node interacted with</summary>
2009-10-11 12:23:27 +00:00
this . _debug ( "getActionNode: " + this . _actionNode . nodeId );
2009-06-19 07:39:16 +00:00
return this . _actionNode ;
},
setActiveTreeType : function ( treeType ) {
/// <summary>
/// All interactions with the tree are done so based on the current tree type (i.e. content, media).
/// When sycning, or searching, the operations will be done on the current tree type so developers
/// can explicitly specify on with this method before performing the operations.
/// The active tree type is always updated any time a node interaction takes place.
/// </summary>
this . _activeTreeType = treeType ;
},
onNodeDeleting : function ( EV ) {
/// <summary>Event handler for when a tree node is about to be deleted</summary>
2009-06-20 13:17:06 +00:00
this . _debug ( "onNodeDeleting" )
2009-06-19 07:39:16 +00:00
//first, close the branch
this . _tree . close_branch ( this . _actionNode . jsNode );
2010-03-16 15:05:05 +00:00
//show the deleting text
this . _actionNode . jsNode . find ( "a div" )
. html ( this . _opts . deletingText )
. effect ( "highlight" , {}, 1000 );
2009-06-19 07:39:16 +00:00
},
onNodeDeleted : function ( EV ) {
/// <summary>Event handler for when a tree node is deleted after ajax call</summary>
2009-06-20 13:17:06 +00:00
this . _debug ( "onNodeDeleted" );
2010-03-01 12:55:01 +00:00
var nodeToDel = this . _actionNode . jsNode ;
2009-06-19 07:39:16 +00:00
//ensure the branch is closed
2010-03-01 12:55:01 +00:00
this . _tree . close_branch ( nodeToDel );
2009-06-19 07:39:16 +00:00
//make the node disapear
2010-03-01 12:55:01 +00:00
nodeToDel . hide ( "drop" , { direction : "down" }, 400 , function () {
2010-04-27 11:45:05 +00:00
//remove the node from the DOM, do this after 1 second as IE doesn't like it when you try this right away.
setTimeout ( function () { nodeToDel . remove (); }, 1000 );
2010-03-01 12:55:01 +00:00
});
2009-06-19 07:39:16 +00:00
this . _updateRecycleBin ();
},
onNodeRefresh : function ( EV ) {
/// <summary>Handles the nodeRefresh event of the context menu and does the refreshing</summary>
this . _debug ( "onNodeRefresh" );
this . _loadChildNodes ( this . _actionNode . jsNode , null );
},
onSelect : function ( NODE , TREE_OBJ ) {
2009-09-21 15:39:59 +00:00
/// <summary>Fires the JS associated with the node, if the tree is in edit mode, allows for rename instead</summary>
2010-04-08 13:27:33 +00:00
//this._debug("onSelect, edit mode? " + this._isEditMode);
this . _debug ( "onSelect" );
2009-10-19 13:35:14 +00:00
if ( this . _isEditMode ) {
2009-09-21 15:39:59 +00:00
this . _tree . rename ( NODE );
return false ;
}
else {
this . setActiveTreeType ( $ ( NODE ). attr ( "umb:type" ));
var js = $ ( NODE ). children ( "a" ). attr ( "href" ). replace ( "javascript:" , "" );
2009-06-19 07:39:16 +00:00
2009-09-21 15:39:59 +00:00
this . _debug ( "onSelect: js: " + js );
2009-06-19 07:39:16 +00:00
2009-09-21 15:39:59 +00:00
try {
var func = eval ( js );
if ( func != null ) {
func . call ();
}
} catch ( e ) { }
2009-06-19 07:39:16 +00:00
2009-09-21 15:39:59 +00:00
return true ;
}
2009-10-19 13:35:14 +00:00
2009-06-19 07:39:16 +00:00
},
onBeforeOpen : function ( NODE , TREE_OBJ ) {
2009-10-11 12:23:27 +00:00
/// <summary>Before opening child nodes, ensure that the data method and url are set properly</summary>
2009-10-19 13:35:14 +00:00
this . _currentAJAXRequest = true ;
2010-03-15 15:17:38 +00:00
TREE_OBJ . settings . data . opts . url = this . _opts . dataUrl ;
2009-10-11 12:23:27 +00:00
TREE_OBJ . settings . data . opts . method = "GET" ;
2009-06-19 07:39:16 +00:00
},
2009-07-13 14:51:26 +00:00
2009-06-20 21:59:38 +00:00
onJSONData : function ( DATA , TREE_OBJ ) {
this . _debug ( "onJSONData" );
2009-10-19 13:35:14 +00:00
2010-02-08 02:22:42 +00:00
this . _ensureContext ();
2009-06-20 21:59:38 +00:00
this . _currentAJAXRequest = false ;
2009-10-19 13:35:14 +00:00
2009-10-11 12:23:27 +00:00
if ( typeof DATA . d != "undefined" ) {
2009-10-19 13:35:14 +00:00
var msg = DATA . d ;
2009-10-11 12:23:27 +00:00
//recreates the tree
if ( $ . inArray ( msg . app , this . _loadedApps ) == - 1 ) {
this . _debug ( "loading js for app: " + msg . app );
this . _loadedApps . push ( msg . app );
//inject the scripts
2010-02-08 02:22:42 +00:00
this . _getContainer (). after ( "<script>" + msg . js + "</script>" );
2009-10-11 12:23:27 +00:00
}
return eval ( msg . json );
}
2009-10-19 13:35:14 +00:00
2009-06-20 21:59:38 +00:00
return DATA ;
},
2009-10-19 13:35:14 +00:00
2009-10-11 12:23:27 +00:00
onBeforeRequest : function ( NODE , TREE_OBJ ) {
2010-02-08 02:22:42 +00:00
this . _ensureContext ();
2009-10-11 12:23:27 +00:00
if ( TREE_OBJ . settings . data . opts . method == "POST" ) {
2010-03-15 15:17:38 +00:00
var parameters = "{'app':'" + this . _opts . app + "','showContextMenu':'" + this . _opts . showContext + "', 'isDialog':'" + this . _opts . isDialog + "', 'dialogMode':'" + this . _opts . dialogMode + "', 'treeType':'" + this . _opts . treeType + "', 'functionToCall':'" + this . _opts . functionToCall + "', 'nodeKey':'" + this . _opts . nodeKey + "'}"
2009-10-19 13:35:14 +00:00
return parameters ;
2009-10-11 12:23:27 +00:00
}
else {
var nodeDef = this . getNodeDef ( $ ( NODE ));
return this . _getUrlParams ( nodeDef . sourceUrl );
}
},
2009-10-19 13:35:14 +00:00
2009-06-19 07:39:16 +00:00
onChange : function ( NODE , TREE_OBJ ) {
//bubble an event!
2010-04-08 13:27:33 +00:00
this . _raiseEvent ( "nodeClicked" , [ NODE ]);
2009-06-19 07:39:16 +00:00
},
2009-10-11 12:23:27 +00:00
onBeforeContext : function ( NODE , TREE_OBJ , EV ) {
2009-10-19 13:35:14 +00:00
2009-06-19 07:39:16 +00:00
//update the action node's NodeDefinition and set the active tree type
2009-10-11 12:23:27 +00:00
this . _actionNode = this . getNodeDef ( $ ( NODE ));
2009-06-19 07:39:16 +00:00
this . setActiveTreeType ( $ ( NODE ). attr ( "umb:type" ));
2009-10-11 12:23:27 +00:00
this . _debug ( "onBeforeContext: " + this . _actionNode . menu );
2009-10-19 13:35:14 +00:00
return this . _actionNode . menu ;
2009-08-11 14:03:30 +00:00
},
2009-10-19 13:35:14 +00:00
2009-10-11 12:23:27 +00:00
onLoad : function ( TREE_OBJ ) {
/// <summary>When the application first loads, load the child nodes</summary>
2009-10-19 13:35:14 +00:00
2009-10-11 12:23:27 +00:00
this . _debug ( "onLoad" );
2009-10-19 13:35:14 +00:00
2009-10-11 12:23:27 +00:00
//ensure the static data is gone
this . _tree . settings . data . opts . static = null ;
var _this = this ;
2010-02-08 02:22:42 +00:00
_this . _loadChildNodes ( $ ( _this . _getContainer ()). find ( "li" ), null );
2009-10-11 12:23:27 +00:00
},
2009-10-19 13:35:14 +00:00
2009-10-11 12:23:27 +00:00
onParse : function ( STR , TREE_OBJ ) {
this . _debug ( "onParse" );
2009-10-19 13:35:14 +00:00
2010-02-08 02:22:42 +00:00
this . _ensureContext ();
2009-10-11 12:23:27 +00:00
var obj = $ ( STR );
this . _configureNodes ( obj );
//this will return the full html of the configured node
return $ ( '<div>' ). append ( $ ( obj ). clone ()). remove (). html ();
2009-06-19 07:39:16 +00:00
},
2009-10-19 13:35:14 +00:00
2010-04-08 13:27:33 +00:00
onDestroy : function ( TREE_OBJ ) {
/// <summary>
/// When the tree is destroyed we need to ensure that all of the events both
/// live and bind are gone. For some reason the jstree unbinding doesn't seem to do it's job
/// so instead we need to clear all of the events ourselves
/// </summary>
this . _debug ( "onDestroy: " + TREE_OBJ . container . attr ( "id" ));
TREE_OBJ . container
. unbind ( "contextmenu" )
. unbind ( "click" )
. unbind ( "dblclick" )
. unbind ( "mouseover" )
. unbind ( "mousedown" )
. unbind ( "mouseup" );
$ ( "a" , TREE_OBJ . container . get ( 0 ))
. die ( "contextmenu" )
. die ( "click" )
. die ( "dblclick" )
. die ( "mouseover" )
. die ( "mousedown" );
2010-06-23 23:19:49 +00:00
//also need to kill the custom selector we've fixed in jstree source
$ ( "#" + TREE_OBJ . container . attr ( "id" ) + " li" ). die ( "click" );
2010-04-08 13:27:33 +00:00
$ ( "li" , TREE_OBJ . container . get ( 0 ))
. die ( "click" );
},
2010-02-08 02:22:42 +00:00
onError : function ( ERR , TREE_OBJ ) {
this . _debug ( "ERROR!!!!! " + ERR );
},
2009-06-19 07:39:16 +00:00
_debug : function ( strMsg ) {
2010-03-01 12:55:01 +00:00
if ( this . _isDebug && Sys && Sys . Debug ) {
2009-06-19 07:39:16 +00:00
Sys . Debug . trace ( "UmbracoTree: " + strMsg );
}
},
_configureNodes : function ( nodes , reconfigure ) {
/// <summary>
/// Ensures the node is configured properly after it's loaded via ajax.
/// This includes setting overlays and ensuring the correct icon paths are used.
/// This also ensures that the correct markup is rendered for the tree (i.e. inserts html nodes for text, etc...)
/// </summary>
var _this = this ;
//don't process the nodes that have already been loaded, unless reconfigure is true
if ( ! reconfigure ) {
nodes = nodes . not ( "li[class*='loaded']" );
}
this . _debug ( "_configureNodes: " + nodes . length );
var rxInput = new RegExp ( "\\boverlay-\\w+\\b" , "gi" );
nodes . each ( function () {
//if it is checkbox tree (not standard), don't worry about overlays and remove the default icon.
2010-03-15 15:17:38 +00:00
if ( _this . _opts . treeMode != "standard" ) {
2009-06-19 07:39:16 +00:00
$ ( this ). children ( "a:first" ). css ( "background" , "" );
return ;
}
//remove all overlays if reconfiguring
$ ( this ). children ( "div" ). remove ();
var m = $ ( this ). attr ( "class" ). match ( rxInput );
if ( m != null ) {
for ( i = 0 ; i < m . length ; i ++ ) {
_this . _debug ( "_configureNodes: adding overlay: " + m [ i ] + " for node: " + $ ( this ). attr ( "id" ));
$ ( this ). children ( "a:first" ). before ( "<div class='overlay " + m [ i ] + "'></div>" );
}
}
2009-10-11 12:23:27 +00:00
//create a div for the text
var a = $ ( this ). children ( "a" );
var ins = a . children ( "ins" );
2009-11-02 21:58:02 +00:00
ins . remove (); //need to remove before you do a .text() otherwise whitespace is included
2009-10-11 12:23:27 +00:00
var txt = $ ( "<div>" + a . text () + "</div>" );
//check if it's not a sprite, if not then move the ins node just after the anchor, otherwise remove
if ( a . hasClass ( "noSpr" )) {
a . attr ( "style" , ins . attr ( "style" ));
}
2009-10-19 13:35:14 +00:00
else {
2009-10-11 12:23:27 +00:00
}
a . html ( txt );
2009-06-19 07:39:16 +00:00
//add the loaded class to each element so we know not to process it again
$ ( this ). addClass ( "loaded" );
});
},
2009-10-11 12:23:27 +00:00
getNodeDef : function ( NODE ) {
2009-06-19 07:39:16 +00:00
/// <summary>Converts a jquery node with metadata to a NodeDefinition</summary>
//get our meta data stored with our node
var nodedata = $ ( NODE ). children ( "a" ). metadata ({ type : 'attr' , name : 'umb:nodedata' });
2009-10-11 12:23:27 +00:00
this . _debug ( "getNodeDef: " + $ ( NODE ). attr ( "id" ) + ", " + nodedata . nodeType + ", " + nodedata . source );
2009-06-19 07:39:16 +00:00
var def = new Umbraco . Controls . NodeDefinition ();
def . updateDefinition ( this . _tree , $ ( NODE ), $ ( NODE ). attr ( "id" ), $ ( NODE ). find ( "a > div" ). html (), nodedata . nodeType , nodedata . source , nodedata . menu , $ ( NODE ). attr ( "umb:type" ));
return def ;
},
_updateRecycleBin : function () {
2010-03-01 12:55:01 +00:00
/// <summary>Generally used for when a node is deleted. This will set the actionNode to the recycle bin node and force a refresh of it's children</summary>
2010-03-15 15:17:38 +00:00
this . _debug ( "_updateRecycleBin BinId: " + this . _opts . recycleBinId );
2009-06-19 07:39:16 +00:00
2010-03-15 15:17:38 +00:00
var rNode = this . findNode ( this . _opts . recycleBinId , true );
2009-06-19 07:39:16 +00:00
if ( rNode ) {
2009-10-11 12:23:27 +00:00
this . _actionNode = this . getNodeDef ( rNode );
2009-06-19 07:39:16 +00:00
var _this = this ;
this . reloadActionNode ( true , true , function ( success ) {
if ( success ) {
2010-03-15 15:17:38 +00:00
_this . findNode ( _this . _opts . recycleBinId , true ). effect ( "highlight" , {}, 1000 );
2009-06-19 07:39:16 +00:00
}
});
}
},
2010-02-08 02:22:42 +00:00
_ensureContext : function () {
/// <summary>
/// ensure that the tree object always has the correct context.
/// this is a fix for the TinyMCE dialog window, as it tends to lose object context for some wacky reason
/// when ajax calls are made. Works fine in all other instances.
/// </summary>
this . _tree . container = this . _getContainer ();
},
2009-06-19 07:39:16 +00:00
_loadChildNodes : function ( liNode , callback ) {
/// <summary>jsTree won't allow you to open a node that doesn't explitly have childen, this will force it to try</summary>
/// <param name="node">a jquery object for the current li node</param>
2009-10-19 13:35:14 +00:00
this . _debug ( "_loadChildNodes: " + liNode . attr ( "id" ));
2009-06-19 07:39:16 +00:00
liNode . removeClass ( "leaf" );
2010-06-21 22:26:14 +00:00
var _this = this ;
//close branch will actually cause a select to happen so we'll intercept the select callback and then reset it once complete
//if we don't wan the event to fire, we'll set the callback to a null method and set it back after we call the select_branch method
this . _tree . settings . callback . onselect = function () { };
this . _tree . close_branch ( liNode , true );
this . _tree . settings . callback . onselect = function ( N , T ) { _this . onSelect ( N , T ) };
2009-10-19 13:35:14 +00:00
liNode . children ( "ul:eq(0)" ). remove ();
2009-06-19 07:39:16 +00:00
this . _tree . open_branch ( liNode , false , callback );
},
_syncTree : function ( path , forceReload , numPaths , numAsync ) {
/// <summary>
/// This is the internal method that will recursively search for the nodes to sync. If an invalid path is
/// passed to this method, it will raise an event which can be handled.
/// </summary>
/// <param name="path">The path of the node to find</param>
/// <param name="forceReload">If true, will ensure that the node to be synced is synced with data from the server</param>
/// <param name="numPaths">the number of id's deep to search starting from the end of the path. Used in recursion.</param>
/// <param name="numAsync">the number of async calls made so far to sync. Used in recursion and used to determine if the found node has been loaded by ajax.</param>
this . _debug ( "_syncTree" );
var paths = path . split ( "," );
var found = null ;
var foundIndex = null ;
if ( numPaths == null ) numPaths = ( paths . length - 0 );
for ( var i = 0 ; i < numPaths ; i ++ ) {
foundIndex = paths . length - ( 1 + i );
found = this . findNode ( paths [ foundIndex ]);
this . _debug ( "_syncTree: finding... " + paths [ foundIndex ] + " found? " + found );
if ( found ) break ;
}
//if no node has been found at all in the entire path, then bubble an error event
if ( ! found ) {
this . _debug ( "no node found in path: " + path + " : " + numPaths );
2010-06-07 10:49:52 +00:00
this . _isSyncing = false ; //reset flag
2010-04-08 13:27:33 +00:00
this . _raiseEvent ( "syncNotFound" , [ path ]);
2009-06-19 07:39:16 +00:00
return ;
}
//if the found node was not the end of the path, we need to load them in recursively.
if ( found . attr ( "id" ) != paths [ paths . length - 1 ]) {
var _this = this ;
this . _loadChildNodes ( found , function ( NODE , TREE_OBJ ) {
//check if the next node to be found is in the children, if it is not, there's a problem bubble an event!
var pathsToSearch = paths . length - ( Number ( foundIndex ) + 1 );
if ( _this . findNode ( paths [ foundIndex + 1 ])) {
_this . _syncTree ( path , forceReload , pathsToSearch , ( numAsync == null ? numAsync == 1 : ++ numAsync ));
}
else {
_this . _debug ( "node not found in children: " + path + " : " + numPaths );
2010-06-07 10:49:52 +00:00
this . _isSyncing = false ; //reset flag
2010-04-08 13:27:33 +00:00
_this . _raiseEvent ( "syncNotFound" , [ path ]);
2009-06-19 07:39:16 +00:00
}
});
}
else {
//only force the reload of this nodes data if forceReload is specified and the node has not already come from the server
var doReload = ( forceReload && ( numAsync == null || numAsync < 1 ));
2010-06-07 10:49:52 +00:00
this . _debug ( "_syncTree: found! numAsync: " + numAsync + ", forceReload: " + forceReload + ", doReload: " + doReload );
2009-06-19 07:39:16 +00:00
if ( doReload ) {
2009-10-11 12:23:27 +00:00
this . _actionNode = this . getNodeDef ( found );
this . reloadActionNode ( false , true , null );
2009-06-19 07:39:16 +00:00
}
else {
//we have found our node, select it but supress the selecting event
if ( found . attr ( "id" ) != "-1" ) this . selectNode ( found , true );
this . _configureNodes ( found , doReload );
}
2010-06-07 10:49:52 +00:00
this . _isSyncing = false ; //reset flag
2009-06-19 07:39:16 +00:00
//bubble event
2010-04-08 13:27:33 +00:00
this . _raiseEvent ( "syncFound" , [ found ]);
2009-06-19 07:39:16 +00:00
}
},
2009-10-11 12:23:27 +00:00
_getUrlParams : function ( nodeSource ) {
/// <summary>This converts Url query string params to json</summary>
var p = {};
2010-06-21 14:55:18 +00:00
if ( nodeSource ) {
var urlSplit = nodeSource . split ( "?" );
if ( urlSplit . length > 1 ) {
var sp = urlSplit [ 1 ]. split ( "&" );
for ( var i = 0 ; i < sp . length ; i ++ ) {
var e = sp [ i ]. split ( "=" );
p [ e [ 0 ]] = e [ 1 ];
}
p [ "rnd2" ] = Umbraco . Utils . generateRandom ();
2010-06-21 14:52:22 +00:00
}
2010-06-21 14:55:18 +00:00
}
2009-10-11 12:23:27 +00:00
return p ;
},
2009-10-19 13:35:14 +00:00
2009-06-19 07:39:16 +00:00
_getUrl : function ( nodeSource ) {
/// <summary>Returns the json service url</summary>
if ( nodeSource == null || nodeSource == "" ) {
2010-03-15 15:17:38 +00:00
return this . _opts . dataUrl ;
2009-06-19 07:39:16 +00:00
}
var params = nodeSource . split ( "?" )[ 1 ];
2010-03-15 15:17:38 +00:00
return this . _opts . dataUrl + "?" + params + "&rnd2=" + Umbraco . Utils . generateRandom ();
2009-06-19 07:39:16 +00:00
},
2010-02-08 02:22:42 +00:00
_getContainer : function () {
return $ ( "#" + this . _containerId , this . _context );
},
2009-10-11 12:23:27 +00:00
_getInitOptions : function ( initData ) {
2009-06-19 07:39:16 +00:00
/// <summary>return the initialization objects for the tree</summary>
2009-06-20 13:17:06 +00:00
this . _debug ( "_getInitOptions" );
2009-07-13 14:51:26 +00:00
2009-06-19 07:39:16 +00:00
var _this = this ;
var options = {
data : {
type : "json" ,
async : true ,
2009-10-19 13:35:14 +00:00
opts : {
static : initData == null ? null : initData ,
2009-10-11 12:23:27 +00:00
method : "POST" ,
2010-03-15 15:17:38 +00:00
url : _this . _opts . serviceUrl ,
2009-10-11 12:23:27 +00:00
outer_attrib : [ "id" , "umb:type" , "class" , "rel" ],
inner_attrib : [ "umb:nodedata" , "href" , "class" , "style" ]
}
2009-06-19 07:39:16 +00:00
},
ui : {
dots : false ,
rtl : false ,
animation : false ,
hover_mode : true ,
2010-03-09 13:52:11 +00:00
theme_path : false ,
2009-10-11 12:23:27 +00:00
theme_name : "umbraco"
2009-06-19 07:39:16 +00:00
},
2009-10-11 12:23:27 +00:00
langs : {
2009-06-20 14:23:15 +00:00
new_node : "New folder" ,
loading : "<div>" + ( this . _tree . settings . lang . loading || "Loading ..." ) + "</div>"
2009-06-19 09:32:18 +00:00
},
2009-06-19 07:39:16 +00:00
callback : {
2009-10-11 12:23:27 +00:00
//ensures that the node id isn't appended to the async url
2009-10-19 13:35:14 +00:00
beforedata : function ( N , T ) { return _this . onBeforeRequest ( N , T ); },
2009-06-19 07:39:16 +00:00
//wrapped functions maintain scope in callback
2009-10-11 12:23:27 +00:00
beforeopen : function ( N , T ) { _this . onBeforeOpen ( N , T ); },
onselect : function ( N , T ) { _this . onSelect ( N , T ); },
onchange : function ( N , T ) { _this . onChange ( N , T ); },
ondata : function ( D , T ) { return _this . onJSONData ( D , T ); },
onload : function ( T ) { if ( initData == null ) _this . onLoad ( T ); },
2010-02-08 02:22:42 +00:00
onparse : function ( S , T ) { return _this . onParse ( S , T ); },
2010-04-08 13:27:33 +00:00
error : function ( E , T ) { _this . onError ( E , T ); },
ondestroy : function ( T ) { _this . onDestroy ( T ); }
2009-10-11 12:23:27 +00:00
},
plugins : {
//UmbracoContext comes before context menu so that the events fire first
UmbracoContext : {
2010-03-15 15:17:38 +00:00
fullMenu : _this . _opts . jsonFullMenu ,
2009-10-19 13:35:14 +00:00
onBeforeContext : function ( N , T , E ) { return _this . onBeforeContext ( N , T , E ); }
2009-10-11 12:23:27 +00:00
},
contextmenu : {}
2009-06-19 07:39:16 +00:00
}
};
2010-03-15 15:17:38 +00:00
if ( this . _opts . treeMode != "standard" ) {
2009-10-19 13:35:14 +00:00
options . plugins . checkbox = { three_state : false }
2009-10-11 12:23:27 +00:00
}
2009-10-19 13:35:14 +00:00
2010-03-01 12:55:01 +00:00
//if there's no service URL, then disable ajax requests
2010-03-15 15:17:38 +00:00
if ( this . _opts . serviceUrl == "" || this . _opts . dataUrl == "" ) {
2010-03-01 12:55:01 +00:00
options . data . async = false ;
options . data . opts . static = {};
}
2009-10-11 12:23:27 +00:00
//set global ajax settings:
$ . ajaxSetup ({
2009-10-19 13:35:14 +00:00
contentType : "application/json; charset=utf-8"
2009-10-11 12:23:27 +00:00
});
2009-06-19 07:39:16 +00:00
2010-03-01 12:55:01 +00:00
this . _debug ( "_getInitOptions. Async enabled = " + options . data . async );
2009-10-19 13:35:14 +00:00
2009-06-19 07:39:16 +00:00
return options ;
}
};
}
2010-02-08 02:22:42 +00:00
// instance manager
Umbraco . Controls . UmbracoTree . cntr = 0 ;
Umbraco . Controls . UmbracoTree . inst = {};
2010-04-08 13:27:33 +00:00
})( jQuery );