diff --git a/components/umbraco.controls/TreePicker/BaseTreePicker.js b/components/umbraco.controls/TreePicker/BaseTreePicker.js index 2992bfe471..ff474a3b03 100644 --- a/components/umbraco.controls/TreePicker/BaseTreePicker.js +++ b/components/umbraco.controls/TreePicker/BaseTreePicker.js @@ -21,7 +21,7 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); LaunchPicker: function() { var _this = this; - UmbClientMgr.openModalWindow(this._itemPickerUrl, this._label, this._showHeader, this._width, this._height, 30, 0, ['#cancelbutton'], function(e) { _this.SaveSelection(e); }); + UmbClientMgr.openModalWindow(this._itemPickerUrl, this._label, this._showHeader, this._width, this._height, 60, 0, ['#cancelbutton'], function(e) { _this.SaveSelection(e); }); }, SaveSelection: function(e) { diff --git a/foreign dlls/ClientDependency.Core.dll b/foreign dlls/ClientDependency.Core.dll index c3d9245952..3820c459ce 100644 Binary files a/foreign dlls/ClientDependency.Core.dll and b/foreign dlls/ClientDependency.Core.dll differ diff --git a/foreign dlls/UmbracoExamine.Providers.dll b/foreign dlls/UmbracoExamine.Providers.dll index 889eaaceea..1b357ae795 100644 Binary files a/foreign dlls/UmbracoExamine.Providers.dll and b/foreign dlls/UmbracoExamine.Providers.dll differ diff --git a/umbraco/presentation/config/ClientDependency.config b/umbraco/presentation/config/ClientDependency.config index e4a2a54a90..0f42f1dd2c 100644 --- a/umbraco/presentation/config/ClientDependency.config +++ b/umbraco/presentation/config/ClientDependency.config @@ -1,4 +1,4 @@ - + diff --git a/umbraco/presentation/umbraco_client/Application/UmbracoClientManager.js b/umbraco/presentation/umbraco_client/Application/UmbracoClientManager.js index e46e188c4d..ddc95d1834 100644 --- a/umbraco/presentation/umbraco_client/Application/UmbracoClientManager.js +++ b/umbraco/presentation/umbraco_client/Application/UmbracoClientManager.js @@ -18,7 +18,7 @@ Umbraco.Sys.registerNamespace("Umbraco.Application"); _mainTree: null, _appActions: null, _rootPath: "/umbraco", //this is the default - _modal: null, + _modal: new Array(), //track all modal window objects (they get stacked) setUmbracoPath: function(strPath) { /// @@ -107,31 +107,49 @@ Umbraco.Sys.registerNamespace("Umbraco.Application"); } }, openModalWindow: function(url, name, showHeader, width, height, top, leftOffset, closeTriggers, onCloseCallback) { - if (this._modal == null) { - this._modal = new Umbraco.Controls.ModalWindow(); + //need to create the modal on the top window if the top window has a client manager, if not, create it on the current window + + //if this is the top window, or if the top window doesn't have a client manager, create the modal in this manager + if (window == this.mainWindow() || !this.mainWindow().UmbClientMgr) { + var m = new Umbraco.Controls.ModalWindow(); + this._modal.push(m); + m.open(url, name, showHeader, width, height, top, leftOffset, closeTriggers, onCloseCallback); + } + else { + //if the main window has a client manager, then call the main window's open modal method whilst keeping the context of it's manager. + if (this.mainWindow().UmbClientMgr) { + this.mainWindow().UmbClientMgr.openModalWindow.apply(this.mainWindow().UmbClientMgr, + [url, name, showHeader, width, height, top, leftOffset, closeTriggers, onCloseCallback]); + } + else { + return; //exit recurse. + } } - this._modal.open(url, name, showHeader, width, height, top, leftOffset, closeTriggers, onCloseCallback); }, closeModalWindow: function(rVal) { /// - /// will close the latest open modal window, otherwise - /// if the modal object is null and the mainWindow is not null, this generally means this is - /// being called inside a modal window, so we'll check to see if we can get the parent modal - /// object and close it instead. + /// will close the latest open modal window. /// if an rVal is passed in, then this will be sent to the onCloseCallback method if it was specified. /// - if (this._modal != null) { - this._modal.close(rVal); + if (this._modal != null && this._modal.length > 0) { + this._modal.pop().close(rVal); } else { - //this will recursively try to close a modal window until window.parent or - //window.parent.UmbClientMgr doesn't exist. + //this will recursively try to close a modal window until the parent window has a modal object or the window is the top and has the modal object + var mgr = null; if (window.parent == null || window.parent == window) { - return; //don't recurse, exit + //we are at the root window, check if we can close the modal window from here + if (window.UmbClientMgr != null && window.UmbClientMgr._modal != null && window.UmbClientMgr._modal.length > 0) { + mgr = window.UmbClientMgr; + } + else { + return; //exit recursion. + } } else if (typeof window.parent.UmbClientMgr != "undefined") { - window.parent.UmbClientMgr.closeModalWindow(rVal); + mgr = window.parent.UmbClientMgr; } + mgr.closeModalWindow.call(mgr, rVal); } }, _debug: function(strMsg) { diff --git a/umbraco/presentation/umbraco_client/modal/modal.js b/umbraco/presentation/umbraco_client/modal/modal.js index 06e4f30831..9c823cb217 100644 --- a/umbraco/presentation/umbraco_client/modal/modal.js +++ b/umbraco/presentation/umbraco_client/modal/modal.js @@ -14,44 +14,58 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); }; $.fn.ModalWindowShow = function(name, showHeader, width, height, top, leftOffset, closeTriggers, onCloseCallback) { + /// Shows a modal window based on existing content in the DOM return $(this).each(function() { //check if the modal exists already - if ($(this).closest(".umbModalBox").length) { + if ($(this).closest(".umbModalBox").length > 0) { var api = $(this).closest(".umbModalBox").ModalWindowAPI(); api._obj.jqmShow(); //since it exist, just re-show it } else { var modal = Umbraco.Controls.ModalWindow(); modal.show(this, name, showHeader, width, height, top, leftOffset, closeTriggers, onCloseCallback); - } + } }); }; Umbraco.Controls.ModalWindow = function() { - /// Modal window class, when open is called, it will create a temporary html element to attach the window to - return { + /// + /// Modal window class, when open is called, it will create a temporary html element to attach the window to. + /// The modal will attempt to be created in the top most frame if all of the libraries are found there, if not, + /// it uses the current frame's document/jquery objects. + /// + + var m = { _wId: Umbraco.Utils.generateRandom().toString().replace(".", ""), //the modal window ID that will be assigned _obj: null, //the jquery element for the modal window _rVal: null, //a return value specified when closing that gets passed to the onCloseCallback method + _cntr: ++Umbraco.Controls.ModalWindow.cntr, //counts instances + //get a reference to the topmost jquery object if there is a modal framework there, otherwise use current + _$: (window.top.jQuery && window.top.jQuery.jqm) ? window.top.jQuery : $, + //get a reference to the topmost document if we're selecting the topmost jquery, otherwise use the current + _document: (window.top.jQuery && window.top.jQuery.jqm) ? window.top.document : document, show: function(selector, name, showHeader, width, height, top, leftOffset, closeTriggers, onCloseCallback) { + /// Shows a modal window based on existing content in the DOM //check if the modal elems exist if (!this._modalElemsExist()) { this._createModalElems(false, selector); } + var _this = this; this._open(name, showHeader, width, height, top, leftOffset, closeTriggers, onCloseCallback, function(h) { //insert the content - var umbModal = $(h.w); - var umbModalContent = $(".umbModalBoxContent", umbModal); - umbModalContent.append($(selector)); - $(selector).show(); + var umbModal = _this._$(h.w); + var umbModalContent = _this._$(".umbModalBoxContent", umbModal); + umbModalContent.append(_this._$(selector)); + _this._$(selector).show(); }); }, open: function(url, name, showHeader, width, height, top, leftOffset, closeTriggers, onCloseCallback) { + /// Shows a modal window with content specified in the url in an iframe //check if the modal elems exist if (!this._modalElemsExist()) { this._createModalElems(true); @@ -62,8 +76,8 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); closeTriggers, onCloseCallback, function(h) { //get the iframe, and set the url - var umbModal = $(h.w); - var umbModalContent = $("iframe", umbModal); + var umbModal = _this._$(h.w); + var umbModalContent = _this._$("iframe", umbModal); umbModalContent.html('').attr('src', _this._getUniqueUrl(url)); umbModalContent.width(width); umbModalContent.height(showHeader ? height - 30 : height); @@ -91,7 +105,7 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); this._obj.jqm({ onShow: function(h) { - var umbModal = $(h.w); + var umbModal = _this._$(h.w); //remove the header if it shouldn't be shown if (!showHeader) { @@ -107,15 +121,18 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); if (height > 0) { umbModal.height(height); } + //if the width is set, then set it in the center if (width > 0) { umbModal.width(width); - umbModal.css("left", (($(document).width() - width) / 2) + "px"); + umbModal.css("left", ((_this._$(_this._document).width() - width) / 2) + "px"); } + //if the top is set if (top > 0) { umbModal.css("top", top + "px"); } + //if the leftOffset is set if (leftOffset > 0) { var newLeft = parseInt(umbModal.css("left").replace("px", "")) + leftOffset; @@ -128,21 +145,39 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); onCreate.call(_this, h) } - $(document).keyup(function(event) { + _this._$(_this._document).keyup(function(event) { if (event.keyCode == 27 && umbModal.css("display") == "block") { _this.close(); } }); + if (closeTriggers) { for (var x in closeTriggers) { - _this._obj.jqmAddClose(closeTriggers[x]); + //Ok, this is a bit weird, but it makes sense. Since the selector passed in might be a selector + //that exists in the root jquery obj, the current jquery object, or an item in the iframe if there is one + //we'll try to find them all. + var trigger = closeTriggers[x]; + //first check if the object passed in is already a jquery object + if (!trigger.jquery) { + trigger = _this._$(closeTriggers[x]); //find object in the doc that owns the modal container + if (trigger.length == 0) { + trigger = $(closeTriggers[x]); //find object in the doc that owns the curr jquery object + } + if (trigger.length == 0) { + try { + trigger = h.w.find("iframe").contents().find(closeTriggers[x]); + } + catch (err) {} //IE throws an exception when navigating iframes, but it stil works... + } + } + _this._obj.jqmAddClose(trigger); } } }, onHide: function(h) { - var umbModal = $(h.w); - var umbModalContent = $(".umbModalBoxContent", umbModal); + var umbModal = _this._$(h.w); + var umbModalContent = _this._$(".umbModalBoxContent", umbModal); var iframe = umbModalContent.find("iframe"); if (typeof onCloseCallback == "function") { //call the callback if specified, pass the jquery content object as a param and the output value array @@ -156,8 +191,9 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); if (iframe.length > 0) { umbModalContent.hide(); umbModalContent.html('').attr('src', ''); - _this.close(); + _this._obj.remove(); } + _this._close(); } }); @@ -167,35 +203,42 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); return this._obj; }, close: function(rVal) { - /// Closes the modal window, Removes the object from the DOM + /// Closes the modal window /// if specified, will add this parameter to the onCloseCallback method's outVal parameter so it may be used in the closing callback method this._rVal = rVal; top.focus(); - this._obj.jqmHide(); - this._obj.remove(); - return false; + this._obj.jqmHide(); //do the hiding, this will call the onHide handler + }, + _close: function() { + /// Finalizes the objects counter and instance manager + + //remove the instance from the instance manager + Umbraco.Controls.ModalWindow.inst[this._cntr] = null; + Umbraco.Controls.ModalWindow.inst[this._wId] = null; + Umbraco.Controls.ModalWindow.cntr--; //reduce the counter }, _createModalElems: function(withIFrame, selector) { /// This will create the html elements required for the modal overlay if they do not already exist in the DOM var overlayHtml = this._getOverlayHtml(withIFrame); - //create the modal dialog in the root if no selector, otherwise create at parent - //of selector + if (!selector) { - this._obj = $(overlayHtml).appendTo("body"); + this._obj = this._$(overlayHtml).appendTo(this._$("body")); } else { - this._obj = $(overlayHtml).appendTo($(selector).parent()); + this._obj = this._$(overlayHtml).appendTo(this._$(selector).parent()); } + //update the z-index so it stacks + this._obj.css("z-index", 10000 + (this._cntr * 10)); var _this = this; - if ($.fn.draggable) { + if (this._$.fn.draggable) { this._obj.draggable({ cursor: 'move', distance: 5, iframeFix: withIFrame, helper: function(event) { - var o = $(this).clone(); + var o = _this._$(this).clone(); o.children().remove(); o.css("border-width", "1px"); return o; @@ -224,7 +267,7 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); return overlayHtml; }, _modalElemsExist: function() { - return ($("#" + this._wId + "_modal").length > 0); + return (this._$("#" + this._wId + "_modal").length > 0); }, _getUniqueUrl: function(url) { var r = Umbraco.Utils.generateRandom(); @@ -234,8 +277,18 @@ Umbraco.Sys.registerNamespace("Umbraco.Controls"); return url += "?rndo=" + r; } }; + + //store a reference to this api by the id and the counter + Umbraco.Controls.ModalWindow.inst[m._cntr] = m; + Umbraco.Controls.ModalWindow.inst[m._wId] = Umbraco.Controls.ModalWindow.inst[m._cntr]; + + return m; }; + // instance manager + Umbraco.Controls.ModalWindow.cntr = 0; + Umbraco.Controls.ModalWindow.inst = {}; + })(jQuery);