diff --git a/components/editorControls/MultiNodeTreePicker/MNTP_DataEditor.cs b/components/editorControls/MultiNodeTreePicker/MNTP_DataEditor.cs index 8de3df8cb3..601ec12ae7 100644 --- a/components/editorControls/MultiNodeTreePicker/MNTP_DataEditor.cs +++ b/components/editorControls/MultiNodeTreePicker/MNTP_DataEditor.cs @@ -14,17 +14,16 @@ using umbraco.IO; namespace umbraco.editorControls.MultiNodeTreePicker { - - /// - /// The user interface to display to the content editor - /// - [ClientDependency( ClientDependencyType.Javascript, "ui/jqueryui.js", "UmbracoClient")] + /// + /// The user interface to display to the content editor + /// + [ClientDependency(ClientDependencyType.Javascript, "ui/jqueryui.js", "UmbracoClient")] + [ClientDependency(ClientDependencyType.Javascript, "ui/jquery.tooltip.min.js", "UmbracoClient")] [ClientDependency(ClientDependencyType.Javascript, "controls/Images/ImageViewer.js", "UmbracoRoot")] public class MNTP_DataEditor : Control, INamingContainer { - #region Static Constructor - + /// /// This adds our filtered tree definition to the TreeDefinitionCollection at runtime /// instead of having to declare it in the database @@ -79,13 +78,13 @@ namespace umbraco.editorControls.MultiNodeTreePicker } } } - } + } #endregion - /// - /// Initializes a new instance of the class. - /// + /// + /// Initializes a new instance of the class. + /// public MNTP_DataEditor() { this.MediaTypesWithThumbnails = new string[] { "image" }; @@ -93,7 +92,7 @@ namespace umbraco.editorControls.MultiNodeTreePicker TreeToRender = "content"; MaxNodeCount = -1; MinNodeCount = 0; - StartNodeId = uQuery.RootNodeId; + StartNodeId = uQuery.RootNodeId; ShowToolTips = true; ControlHeight = 200; } @@ -102,35 +101,35 @@ namespace umbraco.editorControls.MultiNodeTreePicker /// /// Used for locking code blocks /// - private static readonly object m_Locker = new object(); + private static readonly object m_Locker = new object(); #endregion #region Protected members - /// - /// - /// + /// + /// + /// protected CustomValidator MinItemsValidator; - /// - /// - /// + /// + /// + /// protected CustomTreeControl TreePickerControl; - /// - /// - /// - protected Repeater SelectedValues; + /// + /// + /// + protected Repeater SelectedValues; - /// - /// - /// - protected HiddenField PickedValue; + /// + /// + /// + protected HiddenField PickedValue; - /// - /// - /// - protected HtmlGenericControl RightColumn; + /// + /// + /// + protected HtmlGenericControl RightColumn; #endregion #region public Properties @@ -191,7 +190,7 @@ namespace umbraco.editorControls.MultiNodeTreePicker var nodes = value.Descendants("nodeId"); SelectedValues.DataSource = nodes; PickedValue.Value = string.Join(",", nodes.Select(x => x.Value).ToArray()); - } + } } } @@ -240,11 +239,11 @@ namespace umbraco.editorControls.MultiNodeTreePicker /// public string StartNodeXPathExpression { get; set; } - /// - /// Gets or sets a value indicating whether [show tool tips]. - /// - /// true if [show tool tips]; otherwise, false. - /// Shows/Hides the tooltip info bubble. + /// + /// Gets or sets a value indicating whether [show tool tips]. + /// + /// true if [show tool tips]; otherwise, false. + /// Shows/Hides the tooltip info bubble. public bool ShowToolTips { get; set; } /// @@ -252,13 +251,13 @@ namespace umbraco.editorControls.MultiNodeTreePicker /// public XPathFilterType XPathFilterMatchType { get; set; } - /// - /// Gets or sets a value indicating whether [show thumbnails for media]. - /// - /// - /// true if [show thumbnails for media]; otherwise, false. - /// - /// Whether or not to show thumbnails for media + /// + /// Gets or sets a value indicating whether [show thumbnails for media]. + /// + /// + /// true if [show thumbnails for media]; otherwise, false. + /// + /// Whether or not to show thumbnails for media public bool ShowThumbnailsForMedia { get; set; } /// @@ -279,10 +278,10 @@ namespace umbraco.editorControls.MultiNodeTreePicker #endregion - /// - /// Initialize the control, make sure children are created - /// - /// An object that contains the event data. + /// + /// Initialize the control, make sure children are created + /// + /// An object that contains the event data. protected override void OnInit(EventArgs e) { base.OnInit(e); @@ -299,7 +298,8 @@ namespace umbraco.editorControls.MultiNodeTreePicker base.OnLoad(e); //add the js/css required - this.AddAllMNTPClientDependencies(); + this.RegisterEmbeddedClientResource("umbraco.editorControls.MultiNodeTreePicker.MultiNodePickerStyles.css", umbraco.cms.businesslogic.datatype.ClientDependencyType.Css); + this.RegisterEmbeddedClientResource("umbraco.editorControls.MultiNodeTreePicker.MultiNodePickerScripts.js", umbraco.cms.businesslogic.datatype.ClientDependencyType.Javascript); //update the tree type (we need to do this each time because i don't think view state works with these controls) switch (TreeToRender) @@ -320,13 +320,13 @@ namespace umbraco.editorControls.MultiNodeTreePicker //since it is a post back, bind the data source to the view state values XmlValue = ConvertToXDocument(SelectedIds); } - + //bind the repeater if theres a data source, or if there's no datasource but this is a postback (i.e. nodes deleted) if (SelectedValues.DataSource != null || Page.IsPostBack) { SelectedValues.DataBind(); } - + } /// @@ -355,7 +355,7 @@ namespace umbraco.editorControls.MultiNodeTreePicker //create the right column RightColumn = new HtmlGenericControl("div") { ID = "RightColumn" }; RightColumn.Attributes.Add("class", "right propertypane"); - + //create the repeater SelectedValues = new Repeater { @@ -384,13 +384,13 @@ namespace umbraco.editorControls.MultiNodeTreePicker this.Controls.Add(RightColumn); } - - + + /// /// Ensure the repeater is data bound /// public override void DataBind() - { + { base.DataBind(); SelectedValues.DataBind(); } @@ -428,7 +428,7 @@ namespace umbraco.editorControls.MultiNodeTreePicker if (int.TryParse(thisNode.Value, out thisNodeId)) { umbraco.cms.businesslogic.Content loadedNode; - + try { loadedNode = new umbraco.cms.businesslogic.Content(thisNodeId); @@ -465,7 +465,7 @@ namespace umbraco.editorControls.MultiNodeTreePicker var imgPreview = (ImageViewer)e.Item.FindControl("ImgPreview"); //show the thubmnail controls imgPreview.Visible = true; - + //add the item class var item = (HtmlGenericControl)e.Item.FindControl("Item"); item.Attributes["class"] += " thumb-item"; @@ -482,7 +482,7 @@ namespace umbraco.editorControls.MultiNodeTreePicker imgPreview.MediaId = thisNodeId; imgPreview.DataBind(); } - } + } } } @@ -490,8 +490,8 @@ namespace umbraco.editorControls.MultiNodeTreePicker { //the node no longer exists, so we display a msg litSelectNodeName.Text = "NODE NO LONGER EXISTS"; - } - } + } + } } /// @@ -511,13 +511,13 @@ namespace umbraco.editorControls.MultiNodeTreePicker SavePersistentValuesForTree(XPathFilter); } - /// - /// Override render to control the exact output of what is rendered this includes instantiating the jquery plugin - /// - /// The object that receives the server control content. - /// - /// Generally i don't like to do this but there's a few div's, etc... to render so this makes more sense. - /// + /// + /// Override render to control the exact output of what is rendered this includes instantiating the jquery plugin + /// + /// The object that receives the server control content. + /// + /// Generally i don't like to do this but there's a few div's, etc... to render so this makes more sense. + /// protected override void Render(HtmlTextWriter writer) { //
@@ -536,7 +536,7 @@ namespace umbraco.editorControls.MultiNodeTreePicker RenderTooltip(writer); - writer.AddAttribute("class", (!MinItemsValidator.IsValid ? "error " : "") + "multiNodePicker clearfix"); + writer.AddAttribute("class", (!MinItemsValidator.IsValid ? "error " : "") + "multiNodePicker clearfix"); writer.AddAttribute("id", this.ClientID); writer.RenderBeginTag(HtmlTextWriterTag.Div); @@ -548,20 +548,20 @@ namespace umbraco.editorControls.MultiNodeTreePicker writer.RenderEndTag(); writer.AddAttribute("class", "left propertypane"); - writer.AddStyleAttribute( HtmlTextWriterStyle.Height, ((ControlHeight + 10).ToString() + "px")); + writer.AddStyleAttribute(HtmlTextWriterStyle.Height, ((ControlHeight + 10).ToString() + "px")); writer.RenderBeginTag(HtmlTextWriterTag.Div); //add the tree control here TreePickerControl.RenderControl(writer); writer.RenderEndTag(); - RightColumn.RenderControl(writer); + RightColumn.RenderControl(writer); //render the hidden field PickedValue.RenderControl(writer); writer.RenderEndTag(); //end multiNodePicker div - var tooltipAjaxUrl = IOHelper.ResolveUrl(SystemDirectories.Umbraco) + @"/plugins/MultiNodePicker/CustomTreeService.asmx/GetNodeInfo"; + var tooltipAjaxUrl = IOHelper.ResolveUrl(SystemDirectories.Umbraco) + @"/plugins/MultiNodePicker/CustomTreeService.asmx/GetNodeInfo"; //add jquery window load event to create the js tree picker var jsMethod = string.Format("jQuery('#{0}').MultiNodeTreePicker('{1}', {2}, '{3}', {4}, {5}, '{6}', '{7}');", @@ -574,23 +574,23 @@ namespace umbraco.editorControls.MultiNodeTreePicker IOHelper.ResolveUrl(SystemDirectories.Umbraco), TreeToRender); var js = "jQuery(window).load(function() { " + jsMethod + " });"; - + writer.WriteLine(""); } - /// - /// converts a list of Ids to the XDocument structure - /// - /// The value. - /// + /// + /// converts a list of Ids to the XDocument structure + /// + /// The value. + /// private XDocument ConvertToXDocument(IEnumerable val) { if (val.Count() > 0) { return new XDocument(new XElement("MultiNodePicker", new XAttribute("type", TreeToRender), - val.Select(x => new XElement("nodeId", x.ToString())))); + val.Select(x => new XElement("nodeId", x.ToString())))); } else { @@ -633,18 +633,18 @@ namespace umbraco.editorControls.MultiNodeTreePicker this.Page.Items.Add("MNTPTooltip", true); } - /// - /// This will update the multi-node tree picker data which is used to store - /// the xpath data and xpath match type for this control id. - /// - /// The xpath. - /// - /// This will save the data into a cookie and also into the request cookie. It must save - /// it to both locations in case the request cookie has been changed and the request cookie - /// is different than the response cookie. - /// + /// + /// This will update the multi-node tree picker data which is used to store + /// the xpath data and xpath match type for this control id. + /// + /// The xpath. + /// + /// This will save the data into a cookie and also into the request cookie. It must save + /// it to both locations in case the request cookie has been changed and the request cookie + /// is different than the response cookie. + /// private void SavePersistentValuesForTree(string xpath) - { + { //create the output cookie with all of the values of the request cookie @@ -668,7 +668,7 @@ namespace umbraco.editorControls.MultiNodeTreePicker var id = 0; if (int.TryParse(HttpContext.Current.Request["id"], out id)) { - newCookie.MntpAddCurrentEditingNode(this.DataTypeDefinitionId, id); + newCookie.MntpAddCurrentEditingNode(this.DataTypeDefinitionId, id); } } @@ -681,7 +681,7 @@ namespace umbraco.editorControls.MultiNodeTreePicker HttpContext.Current.Request.Cookies.Remove(MNTP_DataType.PersistenceCookieName); } HttpContext.Current.Request.Cookies.Add(newCookie); - + } /// diff --git a/components/editorControls/MultiNodeTreePicker/MNTP_PrevalueEditor.cs b/components/editorControls/MultiNodeTreePicker/MNTP_PrevalueEditor.cs index 2cb57f40cf..f1b2700166 100644 --- a/components/editorControls/MultiNodeTreePicker/MNTP_PrevalueEditor.cs +++ b/components/editorControls/MultiNodeTreePicker/MNTP_PrevalueEditor.cs @@ -316,7 +316,7 @@ namespace umbraco.editorControls.MultiNodeTreePicker base.OnInit(e); this.EnsureChildControls(); - this.AddResourceToClientDependency("uComponents.DataTypes.Shared.Resources.Styles.PrevalueEditor.css", ClientDependency.Core.ClientDependencyType.Css); + this.RegisterEmbeddedClientResource("umbraco.editorControls.PrevalueEditor.css", ClientDependencyType.Css); } /// @@ -329,7 +329,7 @@ namespace umbraco.editorControls.MultiNodeTreePicker base.OnLoad(e); //add the css required - this.AddCssMNTPClientDependencies(); + //// this.AddCssMNTPClientDependencies(); //let view state handle the rest if (!Page.IsPostBack) diff --git a/components/editorControls/MultiNodeTreePicker/MultiNodePickerScripts.js b/components/editorControls/MultiNodeTreePicker/MultiNodePickerScripts.js new file mode 100644 index 0000000000..9b548f142d --- /dev/null +++ b/components/editorControls/MultiNodeTreePicker/MultiNodePickerScripts.js @@ -0,0 +1,322 @@ +(function ($) { + + //jquery plugin for our tree picker + $.fn.MultiNodeTreePicker = function (ctlId, maxItems, tooltipAjaxUrl, showTooltip, showThumbnail, umbPath, treeType) { + + /* internal properties */ + var $tree = $(this); + var ctl = $("#" + ctlId); + var hiddenField = ctl.find("input[type='hidden']"); + var rightCol = ctl.find(".right"); + var tooltip = null; //the tooltip object (will be defined when it is shown) + var throbber = null; + var collapseNode = null; //this is used to track collapsing of tree nodes due to the issue of the nodeClicked event being fired on tree collapse + + //store a reference to the hidden field in the right columns data collection + rightCol.data("hiddenField", hiddenField); + + function getPosition(trigger, tip, conf) { + // get origin top/left position + var top = trigger.offset().top, + left = trigger.offset().left, + pos = conf.position[0]; + + top -= tip.outerHeight() - conf.offset[0]; + left += trigger.outerWidth() + conf.offset[1]; + + // adjust Y + var height = tip.outerHeight() + trigger.outerHeight(); + if (pos == 'center') { top += height / 2; } + if (pos == 'bottom') { top += height; } + + + // adjust X + pos = conf.position[1]; + var width = tip.outerWidth() + trigger.outerWidth(); + if (pos == 'center') { left -= width / 2; } + if (pos == 'left') { left -= width; } + + return { top: top, left: left }; + } + + //used to create the tooltip + var tooltipOptions = { + tip: "#MNTPTooltip", + effect: "fade", + predelay: 0, + position: 'center left', + relative: true, + offset: [30, 0], + onShow: function () { + //get the id of the item being queried + var id = this.getTrigger().next().find("li").attr("rel"); + $.ajax({ + type: "POST", + data: "{\"id\": " + id + "}", + dataType: "json", + url: tooltipAjaxUrl, + contentType: "application/json; charset=UTF-8", + success: function (data) { + var newLocation = (treeType == "content" ? umbPath + "/editContent.aspx?id=" : umbPath + "/editMedia.aspx?id=") + data.d.Id; + var h = $("[edit]
ID: " + data.d.Id + "

Path: " + data.d.Path + "

" + data.d.PathAsNames + "

"); + h.click(function () { + + if (!confirm("Are you sure you want to navigate away from this page?\n\nYou may have unsaved changes.\n\nPress OK to continue or Cancel to stay on the current page.")) { + return false; + } + + //this is a VERY dodgy work around for deep linking between sections and pages + var iframe = UmbClientMgr.mainWindow().jQuery("#deepLinkScriptFrame"); + if (iframe.length == 0) { + var html = ""; + iframe = UmbClientMgr.mainWindow().jQuery("