uComponents: MNTP - Resolved various ClientDependency concerns.

Removed the Extension class, as wasn't needed.
Included MNTP's CSS/JS as embedded resources.
Added icons (for delete & info) to '/umbraco/images' and 'jquery.tooltip' script to 'umbraco_client/ui'
This commit is contained in:
leekelleher
2012-04-29 20:16:31 -01:00
parent f20712209d
commit 44b45d797d
10 changed files with 680 additions and 179 deletions

View File

@@ -14,17 +14,16 @@ using umbraco.IO;
namespace umbraco.editorControls.MultiNodeTreePicker
{
/// <summary>
/// The user interface to display to the content editor
/// </summary>
[ClientDependency( ClientDependencyType.Javascript, "ui/jqueryui.js", "UmbracoClient")]
/// <summary>
/// The user interface to display to the content editor
/// </summary>
[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
/// <summary>
/// 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
/// <summary>
/// Initializes a new instance of the <see cref="MNTP_DataEditor"/> class.
/// </summary>
/// <summary>
/// Initializes a new instance of the <see cref="MNTP_DataEditor"/> class.
/// </summary>
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
/// <summary>
/// Used for locking code blocks
/// </summary>
private static readonly object m_Locker = new object();
private static readonly object m_Locker = new object();
#endregion
#region Protected members
/// <summary>
///
/// </summary>
/// <summary>
///
/// </summary>
protected CustomValidator MinItemsValidator;
/// <summary>
///
/// </summary>
/// <summary>
///
/// </summary>
protected CustomTreeControl TreePickerControl;
/// <summary>
///
/// </summary>
protected Repeater SelectedValues;
/// <summary>
///
/// </summary>
protected Repeater SelectedValues;
/// <summary>
///
/// </summary>
protected HiddenField PickedValue;
/// <summary>
///
/// </summary>
protected HiddenField PickedValue;
/// <summary>
///
/// </summary>
protected HtmlGenericControl RightColumn;
/// <summary>
///
/// </summary>
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
/// </summary>
public string StartNodeXPathExpression { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [show tool tips].
/// </summary>
/// <value><c>true</c> if [show tool tips]; otherwise, <c>false</c>.</value>
/// <remarks>Shows/Hides the tooltip info bubble.</remarks>
/// <summary>
/// Gets or sets a value indicating whether [show tool tips].
/// </summary>
/// <value><c>true</c> if [show tool tips]; otherwise, <c>false</c>.</value>
/// <remarks>Shows/Hides the tooltip info bubble.</remarks>
public bool ShowToolTips { get; set; }
/// <summary>
@@ -252,13 +251,13 @@ namespace umbraco.editorControls.MultiNodeTreePicker
/// </summary>
public XPathFilterType XPathFilterMatchType { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [show thumbnails for media].
/// </summary>
/// <value>
/// <c>true</c> if [show thumbnails for media]; otherwise, <c>false</c>.
/// </value>
/// <remarks>Whether or not to show thumbnails for media</remarks>
/// <summary>
/// Gets or sets a value indicating whether [show thumbnails for media].
/// </summary>
/// <value>
/// <c>true</c> if [show thumbnails for media]; otherwise, <c>false</c>.
/// </value>
/// <remarks>Whether or not to show thumbnails for media</remarks>
public bool ShowThumbnailsForMedia { get; set; }
/// <summary>
@@ -279,10 +278,10 @@ namespace umbraco.editorControls.MultiNodeTreePicker
#endregion
/// <summary>
/// Initialize the control, make sure children are created
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs"/> object that contains the event data.</param>
/// <summary>
/// Initialize the control, make sure children are created
/// </summary>
/// <param name="e">An <see cref="T:System.EventArgs"/> object that contains the event data.</param>
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();
}
}
/// <summary>
@@ -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);
}
/// <summary>
/// Ensure the repeater is data bound
/// </summary>
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 = "<i>NODE NO LONGER EXISTS</i>";
}
}
}
}
}
/// <summary>
@@ -511,13 +511,13 @@ namespace umbraco.editorControls.MultiNodeTreePicker
SavePersistentValuesForTree(XPathFilter);
}
/// <summary>
/// Override render to control the exact output of what is rendered this includes instantiating the jquery plugin
/// </summary>
/// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param>
/// <remarks>
/// Generally i don't like to do this but there's a few div's, etc... to render so this makes more sense.
/// </remarks>
/// <summary>
/// Override render to control the exact output of what is rendered this includes instantiating the jquery plugin
/// </summary>
/// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> object that receives the server control content.</param>
/// <remarks>
/// Generally i don't like to do this but there's a few div's, etc... to render so this makes more sense.
/// </remarks>
protected override void Render(HtmlTextWriter writer)
{
//<div class="multiTreePicker">
@@ -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("<script type='text/javascript'>" + js + "</script>");
}
/// <summary>
/// converts a list of Ids to the XDocument structure
/// </summary>
/// <param name="val">The value.</param>
/// <returns></returns>
/// <summary>
/// converts a list of Ids to the XDocument structure
/// </summary>
/// <param name="val">The value.</param>
/// <returns></returns>
private XDocument ConvertToXDocument(IEnumerable<string> 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);
}
/// <summary>
/// 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.
/// </summary>
/// <param name="xpath">The xpath.</param>
/// <remarks>
/// 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.
/// </remarks>
/// <summary>
/// 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.
/// </summary>
/// <param name="xpath">The xpath.</param>
/// <remarks>
/// 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.
/// </remarks>
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);
}
/// <summary>

View File

@@ -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);
}
/// <summary>
@@ -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)

View File

@@ -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 = $("<a href='" + newLocation + "'>[edit]</a><h5>ID: " + data.d.Id + "</h5><p><b>Path:</b> " + data.d.Path + "</p><p><i>" + data.d.PathAsNames + "</i></p>");
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 = "<html><head><script type='text/javascript'>"
+ "this.window.top.delayedNavigate = function(url, app) { "
+ " if (UmbClientMgr.historyManager().getCurrent() == app) {"
+ " UmbClientMgr.contentFrame(url);"
+ " }"
+ " else {"
+ " var origContentFrameFunc = UmbClientMgr.contentFrame;"
+ " var newContentFrameFunc = function (location) {"
+ " UmbClientMgr.contentFrame = origContentFrameFunc;"
+ " origContentFrameFunc.call(this, url);"
+ " };"
+ " UmbClientMgr.contentFrame = newContentFrameFunc;"
+ " UmbClientMgr.mainTree()._loadedApps['tree_' + app] = null;"
+ " UmbClientMgr.mainTree().setActiveTreeType(app);"
+ " UmbClientMgr.mainWindow().location.hash = '#' + app ; "
+ " }"
+ "};"
+ "</script></head><body></body></html>";
iframe = UmbClientMgr.mainWindow().jQuery("<iframe id='deepLinkScriptFrame'>")
.append(html)
.hide()
.css("width", "0px")
.css("height", "0px");
UmbClientMgr.mainWindow().jQuery("body").append(iframe);
}
UmbClientMgr.mainWindow().delayedNavigate(newLocation, treeType);
return false;
});
throbber.hide().next().html("").append(h).show();
},
error: function (data) {
alert("Error!" + data.d.Message);
}
});
},
onBeforeShow: function (ev, pos) {
tooltip = this.getTip();
//move the tooltip just before the trigger so that it's relatively placed
this.getTrigger().before(tooltip);
throbber = tooltip.find(".throbber");
throbber.show().next().hide();
},
events: {
def: 'click, mouseleave'
}
};
function StorePickedNodes(hiddenField, rightCol) {
if (!hiddenField || !rightCol)
return;
var val = "";
rightCol.find(".item ul.rightNode li").each(function () {
val += $(this).attr("rel") + ",";
});
if (val != "") val = val.substr(0, val.length - 1);
hiddenField.val(val);
};
function doHighlight(node) {
var div = node.find('a').find("div:first");
var origBorder = div.css("border");
div.css("border", "1px solid #FBC2C4").css("background-color", "#FBE3E4").css("color", "#8a1f11");
setTimeout(function () { div.attr("style", ""); }, 500);
}
//handler for the node clicking event
function nodeClickHandler(e, node) {
//this is a dodgy hack due to a bug in the umb tree that fires the click event
//twice: http://umbraco.codeplex.com/workitem/29194
if ($(node).is(":hidden")) {
collapseNode = node;
return;
}
else {
//if the collapseNode flag is null, then we're ok
if (!collapseNode) {
if (!$(node).hasClass("uc-treenode-noclick")) {
AddToRight(node);
}
else {
doHighlight($(node));
}
}
else {
//reset the flag but still do nothing
collapseNode = null;
}
}
}
//handler for when the tree is synced
function treeSyncEventHandler() {
//re-add a handler to the tree's nodeClicked event
$tree.UmbracoTreeAPI().addEventHandler("nodeClicked", nodeClickHandler);
}
//syncs the tree with the item selected on the right
function SyncItems(node) {
//first remove the nodeClick event handler as this will fire when the tree is synced
$tree.UmbracoTreeAPI().removeEventHandler("nodeClicked", nodeClickHandler);
//for some reason node syncing doesn't work until a node is selected, so lets just
//select the root node, then continue to sync the tree.
$tree.UmbracoTreeAPI().selectNode($tree.find("li:first"));
//the path will be available to nodes rendered when the page is rendered so we can do a full sync tree.
//only the node id will be available for nodes that have been newly selected but this is ok since the
//nodes are already loaded so the system will be able to sync them.
var nodeId = node.attr("rel");
var path = node.attr("umb:nodedata");
if (!path) path = nodeId;
$tree.UmbracoTreeAPI()
.syncTree(path.toString());
}
//does the adding of a node to the right hand column
//If "test" is true the node is not added. Instead true is returned if it could have been added
function AddToRight(node, test) {
var $node = $(node);
if ($node.hasClass("uc-treenode-noclick")) {
doHighlight($node);
return "Item not allowed here";
}
//get the node id of the node selected
var nodeId = $node.attr("id");
//first, check if we've reached the max
if (maxItems >= 0 && rightCol.find("li").length >= maxItems) {
doHighlight($node);
return "No more items can be added";
}
//check if node id already exists in the right panel, also check if it the root node
//since this should not be selectable
if (nodeId <= 0 || $tree.find("li:first").attr("id") == nodeId || (rightCol.find("li[rel='" + nodeId + "']").length > 0)) {
doHighlight($node);
return nodeId < 0 ? "Item not allowed here" : "Item already added";
}
if (test) {
return true;
}
//create a copy of the node clicked on the tree
var jNode = $node.clone().find("a:first")
//remove un-needed attributes
jNode.removeAttr("href")
.removeAttr("umb:nodedata")
.attr("href", "#")
.attr("title", "Sync tree");
//build a DOM object to put in the right panel
var inserted = $("<div class='item'><a href='javascript:void(0);' class='info'></a>" +
"<div class='inner'><ul class='rightNode'>" +
"<li rel='" + nodeId + "' class='closed'>" +
"</li></ul><a class='close' title='Remove' href='javascript:void(0);'></a></div></div>")
.hide()
.appendTo(rightCol) //add the full div to the right col
.find(".closed") //get the li element
.append(jNode) //append the anchor link
.closest(".item"); //get the item div
if (showTooltip) {
inserted.find(".info").tooltip(tooltipOptions) //add the tooltop
}
else {
//remove the tooltip
inserted.find(".info").remove();
}
//add the image preview if we need to
if (showThumbnail) {
//set the item height to 50px and the width of the inner to 224px
inserted.css("height", "50px").find(".inner").css("width", "224px");
var imgViewer = $("<div class='imageViewer'></div>").prependTo(inserted);
//create the image viewer object, get the API of it and update the image
imgViewer.UmbracoImageViewer({
umbPath: umbPath,
style: "Basic",
linkTarget: "_blank"
})
.UmbracoImageViewerAPI()
.updateImage(nodeId, function (args) {
if (imgViewer.find("a").attr("href") == "#") {
imgViewer.find("img").attr("src", umbPath + "/images/blank.png");
}
});
}
inserted.show();
//now update the hidden field with the
//node selection
StorePickedNodes(hiddenField, rightCol);
}
//remove all trashed nodes
rightCol.find("li[rel='trashed']").closest(".item").remove();
//live click handlers for the removal of items
$(".item a.close", rightCol).live("click", function () {
$(this).closest(".item").remove();
StorePickedNodes(hiddenField, rightCol);
});
//create live click handlers to the right hand items
$(".item ul li a", rightCol).live("click", function () {
SyncItems($(this).parent());
});
//add a handler to the tree's nodeClicked event
$tree.UmbracoTreeAPI().addEventHandler("nodeClicked", nodeClickHandler);
$tree.UmbracoTreeAPI().addEventHandler("syncNotFound", treeSyncEventHandler);
$tree.UmbracoTreeAPI().addEventHandler("syncFound", treeSyncEventHandler);
//create a sortable, drag/drop list and
//initialize the right panel with previously
//saved data.
rightCol.sortable({
stop: function (event, ui) { StorePickedNodes($(this).data("hiddenField"), $(this)); },
start: function (event, ui) { if (tooltip) tooltip.hide(); }, //hide the tooltip when sorting
handle: '.inner'
});
//add the tooltips
rightCol.find("a.info").tooltip(tooltipOptions);
//Register drag and drop action
//PROOF OF CONCEPT: The user can probably also drop stuff that shouldn't be dropped (e.g., StartNodeID is not considered). The filter function can take care of that
if (typeof (UmbDragDrop) != "undefined") {
UmbDragDrop.register(
//Container to highlight
rightCol,
//Drop action
function (info) {
AddToRight(info.drag_node);
},
//Filter
function (info) {
var dropMessage = AddToRight(info.drag_node, true);
return { canDrop: dropMessage === true, message: dropMessage === true ? "" : dropMessage };
});
}
}
})(jQuery);

View File

@@ -0,0 +1,210 @@
/* Standard clearfix */
.clearfix:after
{
content: ".";
display: block;
clear: both;
visibility: hidden;
line-height: 0;
height: 0;
}
.clearfix
{
display: inline-block;
}
.multiNodePicker .item ul.rightNode
{
float: left;
margin: 0;
padding: 0;
width: inherit !important;
}
.multiNodePicker .item ul.rightNode li
{
margin: 0;
padding: 0;
list-style: none;
font: icon;
font-family: Arial,Lucida Grande;
font-size: 12px;
min-height: 20px;
}
.multiNodePicker .item ul.rightNode li a
{
background-repeat: no-repeat !important;
border: 0 none;
color: #2F2F2F;
height: 18px;
line-height: 18px;
padding: 0 0 0 18px;
text-decoration: none;
}
.multiNodePicker .item ul.rightNode li a div
{
cursor: move;
overflow: hidden;
height: 20px;
width: 240px;
}
.multiNodePicker .item.thumb-item ul.rightNode li a div
{
height: 40px;
width: 190px;
}
.multiNodePicker .item a
{
float: left;
}
.multiNodePicker .item a.close
{
color: red;
margin: 0;
padding: 0px;
background: transparent url('/umbraco/images/delete.gif') no-repeat 0px 3px;
width: 15px;
height: 15px;
position: absolute;
right: 0px;
top: 2px;
z-index: 200;
}
.multiNodePicker .item
{
width: 298px;
height: 21px;
border: 1px dotted #DCD;
overflow: hidden;
background-color: #FFF;
margin-bottom: 3px;
}
.multiNodePicker .item.thumb-item
{
height: 50px;
}
.multiNodePicker .item:hover
{
background-color: #F6F6FA;
}
.multiNodePicker .item .inner
{
float: left;
padding: 2px 0px 0px 2px;
width: 278px;
cursor: move;
height: 100%;
position: relative;
overflow: hidden;
}
.multiNodePicker .item.thumb-item .inner
{
width: 224px;
}
.multiNodePicker a.info
{
width: 18px;
height: 18px;
background: transparent url('/umbraco/images/information.png') no-repeat 1px 2px;
float: left;
}
/* tooltip */
#MNTPTooltip, .tooltip
{
background: url('/umbraco_client/propertypane/images/propertyBackground.gif') repeat-x scroll center top #FFFFFF;
display: none;
border: 2px solid #999;
width: 200px;
height: 70px;
padding: 5px;
-moz-border-radius: 5px;
-webkit-border-radius: 5px;
border-radius: 5px;
position: absolute;
z-index: 5000;
-moz-box-shadow: 2px 2px 11px #999;
-webkit-box-shadow: 2px 2px 11px #999;
}
#MNTPTooltip div.throbber, .tooltip div.throbber
{
width: 16px;
height: 16px;
background: transparent url('/umbraco/images/throbber.gif') no-repeat top left;
display: none;
}
#MNTPTooltip div.tooltipInfo, .tooltip div.tooltipInfo
{
font-family: Trebuchet MS,Lucida Grande,verdana,arial;
font-size: 11px;
overflow: hidden;
}
#MNTPTooltip div.tooltipInfo p, .tooltip div.tooltipInfo p
{
margin: 3px 0px 3px 0px;
}
#MNTPTooltip div.tooltipInfo h5, .tooltip div.tooltipInfo h5
{
font-size: 16px;
margin: 0;
padding: 0;
}
#MNTPTooltip div.tooltipInfo a, .tooltip div.tooltipInfo a
{
float: right;
font-size: 10px;
display: block;
}
.multiNodePicker .left.propertypane
{
width: 300px;
float: left;
clear: none;
margin-right: 10px;
height: 210px;
}
.multiNodePicker .right.propertypane
{
width: 300px;
float: left;
clear: right;
padding: 3px;
}
.multiNodePicker .header
{
width: 622px;
}
.uc-treenode-noclick > a > div
{
color: #CC8888;
}
.tree.tree-umbraco li.uc-treenode-noclick > a:hover
{
text-decoration: none;
}
.multiNodePicker .treeContainer
{
overflow: auto;
height: 200px;
position: relative;
}
.multiNodePicker .imageViewer
{
width: 50px;
height: 50px;
border-right: 1px dotted #DCD;
margin-right: 2px;
float: left;
}
.multiNodePicker .imageViewer img
{
width: 50px;
height: 50px;
}

View File

@@ -1,45 +0,0 @@
using System.Web.UI;
using umbraco.cms.businesslogic.datatype;
[assembly: WebResource("umbraco.editorControls.MultiNodeTreePicker.jquery.tooltip.min.js", "application/x-javascript")]
[assembly: WebResource("umbraco.editorControls.MultiNodeTreePicker.MultiNodePickerScripts.js", "application/x-javascript")]
[assembly: WebResource("umbraco.editorControls.MultiNodeTreePicker.MultiNodePickerStyles.css", "text/css", PerformSubstitution = true)]
namespace umbraco.editorControls.MultiNodeTreePicker
{
/// <summary>
/// Extension methods for this namespace
/// </summary>
public static class MultiNodeTreePickerExtensions
{
/// <summary>
/// Adds the JS/CSS required for the MultiNodeTreePicker
/// </summary>
/// <param name="ctl"></param>
public static void AddAllMNTPClientDependencies(this Control ctl)
{
//get the urls for the embedded resources
AddCssMNTPClientDependencies(ctl);
AddJsMNTPClientDependencies(ctl);
}
/// <summary>
/// Adds the CSS required for the MultiNodeTreePicker
/// </summary>
/// <param name="ctl"></param>
public static void AddCssMNTPClientDependencies(this Control ctl)
{
ctl.AddResourceToClientDependency("umbraco.editorControls.MultiNodeTreePicker.MultiNodePickerStyles.css", ClientDependencyType.Css);
}
/// <summary>
/// Adds the JS required for the MultiNodeTreePicker
/// </summary>
/// <param name="ctl"></param>
public static void AddJsMNTPClientDependencies(this Control ctl)
{
ctl.AddResourceToClientDependency("umbraco.editorControls.MultiNodeTreePicker.MultiNodePickerScripts.js", ClientDependencyType.Javascript);
ctl.AddResourceToClientDependency("umbraco.editorControls.MultiNodeTreePicker.jquery.tooltip.min.js", ClientDependencyType.Javascript);
}
}
}