diff --git a/umbraco/businesslogic/BasePages/ClientTools.cs b/umbraco/businesslogic/BasePages/ClientTools.cs
index 83faa5e584..f2af5c90b8 100644
--- a/umbraco/businesslogic/BasePages/ClientTools.cs
+++ b/umbraco/businesslogic/BasePages/ClientTools.cs
@@ -47,6 +47,7 @@ namespace umbraco.BasePages
}
public static string ChildNodeCreated = GetMainTree + ".childNodeCreated();";
public static string SyncTree { get { return GetMainTree + ".syncTree('{0}', {1});"; } }
+ public static string ClearTreeCache { get { return GetMainTree + ".clearTreeCache();"; } }
public static string CopyNode { get { return GetMainTree + ".copyNode('{0}', '{1}');"; } }
public static string MoveNode { get { return GetMainTree + ".moveNode('{0}', '{1}');"; } }
public static string ReloadActionNode { get { return GetMainTree + ".reloadActionNode({0}, {1}, null);"; } }
@@ -59,7 +60,18 @@ namespace umbraco.BasePages
}
private Page m_page;
-
+
+ ///
+ /// This removes all tree JSON data cached in the client browser.
+ /// Useful when you want to ensure that the tree is reloaded from live data.
+ ///
+ ///
+ public ClientTools ClearClientTreeCache()
+ {
+ RegisterClientScript(Scripts.ClearTreeCache);
+ return this;
+ }
+
///
/// Change applications
///
diff --git a/umbraco/presentation/umbraco.presentation.csproj b/umbraco/presentation/umbraco.presentation.csproj
index 26df62b9bc..880d6a066a 100644
--- a/umbraco/presentation/umbraco.presentation.csproj
+++ b/umbraco/presentation/umbraco.presentation.csproj
@@ -3420,6 +3420,7 @@
+
diff --git a/umbraco/presentation/umbraco/developer/Packages/installedPackage.aspx.cs b/umbraco/presentation/umbraco/developer/Packages/installedPackage.aspx.cs
index f276268f8f..c2a7e2a864 100644
--- a/umbraco/presentation/umbraco/developer/Packages/installedPackage.aspx.cs
+++ b/umbraco/presentation/umbraco/developer/Packages/installedPackage.aspx.cs
@@ -375,6 +375,9 @@ namespace umbraco.presentation.developer.packages
protected void confirmUnInstall(object sender, EventArgs e)
{
+ //ensure that all tree's are refreshed after uninstall
+ ClientTools.ClearClientTreeCache();
+
bool refreshCache = false;
diff --git a/umbraco/presentation/umbraco/developer/Packages/installer.aspx.cs b/umbraco/presentation/umbraco/developer/Packages/installer.aspx.cs
index 40483d28e8..43e6b22d73 100644
--- a/umbraco/presentation/umbraco/developer/Packages/installer.aspx.cs
+++ b/umbraco/presentation/umbraco/developer/Packages/installer.aspx.cs
@@ -261,6 +261,10 @@ namespace umbraco.presentation.developer.packages
//we will now create the installer manifest, which means that umbraco can register everything that gets added to the system
//this returns an id of the manifest.
+ //ensure that all tree's are refreshed after uninstall
+ ClientTools.ClearClientTreeCache();
+
+
p.LoadConfig(tempFile.Value);
int pId = p.CreateManifest(tempFile.Value, helper.Request("guid"), helper.Request("repoGuid"));
diff --git a/umbraco/presentation/umbraco_client/Tree/UmbracoTree.js b/umbraco/presentation/umbraco_client/Tree/UmbracoTree.js
index afe803bb01..00689c449f 100644
--- a/umbraco/presentation/umbraco_client/Tree/UmbracoTree.js
+++ b/umbraco/presentation/umbraco_client/Tree/UmbracoTree.js
@@ -50,7 +50,7 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls");
_app: null, //the reference to the current app
_showContext: true,
_isDialog: false,
- _isDebug: false, //set to true to enable alert debugging
+ _isDebug: true, //set to true to enable alert debugging
_loadedApps: [], //stores the application names that have been loaded to track which JavaScript code has been inserted into the DOM
_serviceUrl: "", //a path to the tree client service url
_dataUrl: "", //a path to the tree data service url
@@ -76,11 +76,22 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls");
jItem.data("UmbracoTree", this);
},
+ clearTreeCache: function() {
+ // This will remove all stored trees in client side cache so that the next time a tree needs loading it will be refreshed
+ this._debug("clearTreeCache...");
+
+ for (var a in this._loadedApps) {
+ this._debug("clearTreeCache: " + this._loadedApps[a]);
+ this._container.data("tree_" + this._loadedApps[a], null);
+ }
+ },
+
rebuildTree: function(app) {
/// This will rebuild the tree structure for the application specified
this._debug("rebuildTree");
+ //are we already on the app being requested to load?
if (this._app == null || (this._app.toLowerCase() == app.toLowerCase())) {
this._debug("not rebuilding");
return;
@@ -99,7 +110,7 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls");
//check if we should rebuild from a saved tree
var saveData = this._container.data("tree_" + app);
if (saveData != null) {
- this._debug("rebuildTree: rebuilding from cache!");
+ this._debug("rebuildTree: rebuilding from cache: app = " + app);
//create the tree from the saved data.
this._initNode = saveData.d;
@@ -830,6 +841,11 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls");
this._tree = $.tree_create();
this._tree.init(this._container, this._getInitOptions());
+ //add this app to the loaded apps array
+ if ($.inArray(app, this._loadedApps) == -1) {
+ this._loadedApps.push(app);
+ }
+
//load child nodes of the init node
this._loadChildNodes(this._container.find("li:first"), null);
},
diff --git a/umbraco/presentation/umbraco_client/Tree/UmbracoTree.min.js b/umbraco/presentation/umbraco_client/Tree/UmbracoTree.min.js
index f6292e6d7a..bc7d240bc1 100644
--- a/umbraco/presentation/umbraco_client/Tree/UmbracoTree.min.js
+++ b/umbraco/presentation/umbraco_client/Tree/UmbracoTree.min.js
@@ -1,10 +1,10 @@
Umbraco.Sys.registerNamespace("Umbraco.Controls"); (function($) {
$.fn.UmbracoTree = function(opts) { return this.each(function() { var conf = $.extend({ jsonFullMenu: null, jsonInitNode: null, appActions: null, uiKeys: null, app: "", showContext: true, isDialog: false, treeType: "standard", umb_clientFolderRoot: "/umbraco_client" }, opts); new Umbraco.Controls.UmbracoTree().init($(this), conf); }); }; $.fn.UmbracoTreeAPI = function() { return $(this).data("UmbracoTree") == null ? null : $(this).data("UmbracoTree"); }; Umbraco.Controls.UmbracoTree = function() {
- return { _actionNode: new Umbraco.Controls.NodeDefinition(), _activeTreeType: "content", _recycleBinId: -20, _umb_clientFolderRoot: "/umbraco_client", _fullMenu: null, _initNode: null, _menuActions: null, _tree: null, _uiKeys: null, _container: null, _app: null, _showContext: true, _isDialog: false, _isDebug: false, _loadedApps: [], _serviceUrl: "", _dataUrl: "", _treeType: "standard", _treeClass: "umbTree", _currenAJAXRequest: false, addEventHandler: function(fnName, fn) { $(this).bind(fnName, fn); }, removeEventHandler: function(fnName, fn) { $(this).unbind(fnName, fn); }, init: function(jItem, opts) { this._init(opts.jsonFullMenu, opts.jsonInitNode, jItem, opts.appActions, opts.uiKeys, opts.app, opts.showContext, opts.isDialog, opts.treeType, opts.serviceUrl, opts.dataUrl, opts.umb_clientFolderRoot); jItem.addClass(this._treeClass); jItem.data("UmbracoTree", this); }, rebuildTree: function(app) {
+ return { _actionNode: new Umbraco.Controls.NodeDefinition(), _activeTreeType: "content", _recycleBinId: -20, _umb_clientFolderRoot: "/umbraco_client", _fullMenu: null, _initNode: null, _menuActions: null, _tree: null, _uiKeys: null, _container: null, _app: null, _showContext: true, _isDialog: false, _isDebug: true, _loadedApps: [], _serviceUrl: "", _dataUrl: "", _treeType: "standard", _treeClass: "umbTree", _currenAJAXRequest: false, addEventHandler: function(fnName, fn) { $(this).bind(fnName, fn); }, removeEventHandler: function(fnName, fn) { $(this).unbind(fnName, fn); }, init: function(jItem, opts) { this._init(opts.jsonFullMenu, opts.jsonInitNode, jItem, opts.appActions, opts.uiKeys, opts.app, opts.showContext, opts.isDialog, opts.treeType, opts.serviceUrl, opts.dataUrl, opts.umb_clientFolderRoot); jItem.addClass(this._treeClass); jItem.data("UmbracoTree", this); }, clearTreeCache: function() { this._debug("clearTreeCache..."); for (var a in this._loadedApps) { this._debug("clearTreeCache: " + this._loadedApps[a]); this._container.data("tree_" + this._loadedApps[a], null); } }, rebuildTree: function(app) {
this._debug("rebuildTree"); if (this._app == null || (this._app.toLowerCase() == app.toLowerCase())) { this._debug("not rebuilding"); return; }
else { this._app = app; }
$("div").remove(".tree-default-context"); this._tree.destroy(); this._container.hide(); var _this = this; var saveData = this._container.data("tree_" + app); if (saveData != null) {
- this._debug("rebuildTree: rebuilding from cache!"); this._initNode = saveData.d; this._tree = $.tree_create(); this._tree.init(this._container, this._getInitOptions()); this._configureNodes(this._container.find("li"), true); var lastSelected = saveData.selected != null ? $(saveData.selected[0]).attr("id") : null; if (lastSelected != null) { var _this = this; var foundHandler = function(EV, node) { _this.removeEventHandler("syncFound", foundHandler); this._debug("rebuildTree: node synced, selecting node..."); _this.selectNode(node, false, true); this._container.show(); }; this._debug("rebuildTree: syncing to last selected: " + lastSelected); this.addEventHandler("syncFound", foundHandler); this.setActiveTreeType($(saveData.selected[0]).attr("umb:type")); this.syncTree(lastSelected); }
+ this._debug("rebuildTree: rebuilding from cache: app = " + app); this._initNode = saveData.d; this._tree = $.tree_create(); this._tree.init(this._container, this._getInitOptions()); this._configureNodes(this._container.find("li"), true); var lastSelected = saveData.selected != null ? $(saveData.selected[0]).attr("id") : null; if (lastSelected != null) { var _this = this; var foundHandler = function(EV, node) { _this.removeEventHandler("syncFound", foundHandler); this._debug("rebuildTree: node synced, selecting node..."); _this.selectNode(node, false, true); this._container.show(); }; this._debug("rebuildTree: syncing to last selected: " + lastSelected); this.addEventHandler("syncFound", foundHandler); this.setActiveTreeType($(saveData.selected[0]).attr("umb:type")); this.syncTree(lastSelected); }
else { this._container.show(); }
return;
}
@@ -112,7 +112,8 @@
return null;
}, _init: function(jFullMenu, jInitNode, treeContainer, appActions, uiKeys, app, showContext, isDialog, treeType, serviceUrl, dataUrl, umbClientFolder) {
this._debug("_init: creating new tree with class/id: " + treeContainer.attr("class") + " / " + treeContainer.attr("id")); this._fullMenu = jFullMenu; this._initNode = jInitNode; this._menuActions = appActions; this._uiKeys = uiKeys; this._app = app; this._showContext = showContext; this._isDialog = isDialog; this._treeType = treeType; this._serviceUrl = serviceUrl; this._dataUrl = dataUrl; this._umb_clientFolderRoot = umbClientFolder; if (this._menuActions != null) { var _this = this; this._menuActions.addEventHandler("nodeDeleting", function(E) { _this.onNodeDeleting(E) }); this._menuActions.addEventHandler("nodeDeleted", function(E) { _this.onNodeDeleted(E) }); this._menuActions.addEventHandler("nodeRefresh", function(E) { _this.onNodeRefresh(E) }); }
- this._container = treeContainer; this._tree = $.tree_create(); this._tree.init(this._container, this._getInitOptions()); this._loadChildNodes(this._container.find("li:first"), null);
+ this._container = treeContainer; this._tree = $.tree_create(); this._tree.init(this._container, this._getInitOptions()); if ($.inArray(app, this._loadedApps) == -1) { this._loadedApps.push(app); }
+ this._loadChildNodes(this._container.find("li:first"), null);
}, _getUrl: function(nodeSource) {
if (nodeSource == null || nodeSource == "") { return this._dataUrl; }
var params = nodeSource.split("?")[1]; return this._dataUrl + "?" + params + "&rnd2=" + Umbraco.Utils.generateRandom();