Implementing reusable MediaLibraryPicker shape.

This commit is contained in:
Sipke Schoorstra
2014-07-28 15:39:56 -07:00
parent 688b355ba4
commit 3d284eece8
4 changed files with 180 additions and 155 deletions

View File

@@ -76,6 +76,7 @@
</ItemGroup>
<ItemGroup>
<Content Include="Scripts\knockout-2.3.0.js" />
<Content Include="Scripts\media-library-picker.js" />
<Content Include="Scripts\media-library.js" />
<Content Include="Scripts\modal-window.js" />
<Content Include="Scripts\history.js" />
@@ -346,6 +347,9 @@
<ItemGroup>
<Content Include="Views\Admin\ChildFolders.cshtml" />
</ItemGroup>
<ItemGroup>
<Content Include="Views\MediaLibraryPicker.cshtml" />
</ItemGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>

View File

@@ -0,0 +1,110 @@
(function($) {
$(".media-library-picker-field").each(function() {
var element = $(this);
var multiple = element.data("multiple");
var removeText = element.data("remove-text");
var removePrompt = element.data("remove-prompt");
var editText = element.data("edit-text");
var dirtyText = element.data("dirty-text");
var pipe = element.data("pipe");
var returnUrl = element.data("return-url");
var addUrl = element.data("add-url");
var addButton = element.find(".button.add");
var template =
'<li><div data-id="{contentItemId}" class="media-library-picker-item"><div class="thumbnail">{thumbnail}<div class="overlay"><h3>{title}</h3></div></div></div><a href="#" data-id="{contentItemId}" class="media-library-picker-remove">' + removeText + '</a>' + pipe + '<a href="{editLink}?ReturnUrl=' + returnUrl + '">' + editText + '</a></li>';
var refreshIds = function() {
var id = element.find('.selected-ids');
id.val('');
element.find(".media-library-picker-item").each(function() {
id.val(id.val() + "," + $(this).attr("data-id"));
});
var itemsCount = element.find(".media-library-picker-item").length;
if(!multiple && itemsCount > 0) {
addButton.hide();
}
else {
addButton.show();
}
};
window.mediaLibraryDirty = false;
var showSaveMsg = function() {
element.find('.media-library-picker-message').show();
window.mediaLibraryDirty = true;
};
if (!window.mediaLibraryNavigateAway) {
$(window).on("beforeunload", window.mediaLibraryNavigateAway = function() {
if (window.mediaLibraryDirty) {
return dirtyText;
}
});
element.closest("form").on("submit", function() {
window.mediaLibraryDirty = false;
});
}
refreshIds();
addButton.click(function () {
var url = addUrl;
$.colorbox({
href: url,
iframe: true,
reposition: true,
width: "100%",
height: "100%",
onLoad: function() { // hide the scrollbars from the main window
$('html, body').css('overflow', 'hidden');
$('#cboxClose').remove();
},
onClosed: function() {
$('html, body').css('overflow', '');
var selectedData = $.colorbox.selectedData;
if (selectedData == null) // Dialog cancelled, do nothing
return;
var selectionLength = multiple ? selectedData.length : Math.min(selectedData.length, 1);
for (var i = 0; i < selectionLength ; i++) {
var tmpl = template
.replace(/\{contentItemId\}/g, selectedData[i].id)
.replace(/\{thumbnail\}/g, selectedData[i].thumbnail)
.replace(/\{title\}/g, selectedData[i].title)
.replace(/\{editLink\}/g, selectedData[i].editLink);
var content = $(tmpl);
element.find('.media-library-picker.items ul').append(content);
}
refreshIds();
if (selectedData.length) {
showSaveMsg();
}
}
});
});
element.on("click",'.media-library-picker-remove', function(e) {
e.preventDefault();
if (!confirm(removePrompt)) return false;
$(this).closest('li').remove();
refreshIds();
showSaveMsg();
return false;
});
element.find(".media-library-picker.items ul").sortable({
handle: '.thumbnail',
stop: function() {
refreshIds();
showSaveMsg();
}
}).disableSelection();
});
})(jQuery);

View File

@@ -1,160 +1,12 @@
@model Orchard.MediaLibrary.ViewModels.MediaLibraryPickerFieldViewModel
@using Orchard.ContentManagement
@using Orchard.Utility.Extensions;
@using Orchard.MediaLibrary.Settings;
@{
Script.Require("jQueryUI_Sortable").AtFoot();
Style.Include("media-library-picker-admin.css");
Script.Require("jQueryColorBox").AtFoot();
Style.Require("jQueryColorBox");
var settings = Model.Field.PartFieldDefinition.Settings.GetModel<MediaLibraryPickerFieldSettings>();
var contentManager = WorkContext.Resolve<IContentManager>();
var fieldIdForSelectedIds = Html.FieldIdFor(m => m.SelectedIds);
var fieldIdForIds = Html.FieldIdFor(m => m.Field.Ids);
}
<fieldset>
<label @if(settings.Required) { <text>class="required"</text> }>@Model.Field.DisplayName</label>
<div id="save-message-@fieldIdForIds" class="message message-Warning media-library-picker-message">@T("You need to save your changes.")</div>
<div id="media-library-picker-@fieldIdForIds" class="items media-library-picker" summary="@Model.Field.DisplayName">
<ul>
@foreach (var contentItem in Model.ContentItems) {
var editRouteValues = contentManager.GetItemMetadata(contentItem).EditorRouteValues;
var editUrl = Url.Action(
Convert.ToString(editRouteValues["action"]),
editRouteValues.Merge(new RouteValueDictionary { { "ReturnUrl", Request.RawUrl } }));
<li>
<div data-id="@contentItem.Id" data-fieldid="@fieldIdForIds" class="media-library-picker-item">
<div class="thumbnail">
@Display(contentManager.BuildDisplay(contentItem, "Thumbnail"))
<div class="overlay">
<h3>@Html.ItemDisplayText(contentItem)</h3>
</div>
</div>
</div>
<a href="#" data-id="@contentItem.Id" class="media-library-picker-remove">@T("Remove")</a>@T(" | ")
<a href="@editUrl">@T("Edit")</a>
</li>
}
</ul>
</div>
<div>
<span id="btn-@fieldIdForIds" class="button">@T("Add")</span>
</div>
@Html.HiddenFor(m => m.SelectedIds)
<span class="hint">@settings.Hint</span>
</fieldset>
@using (Script.Foot()) {
<script type="text/javascript">
//<![CDATA[
(function($) {
var multiple = @(settings.Multiple ? "true" : "false");
var addButton = $('#btn-@fieldIdForIds');
var @(fieldIdForIds)_Template =
'<li><div data-id="{contentItemId}" data-fieldid="@fieldIdForIds" class="media-library-picker-item"><div class="thumbnail">{thumbnail}<div class="overlay"><h3>{title}</h3></div></div></div><a href="#" data-id="{contentItemId}" class="media-library-picker-remove">@T("Remove")</a>@T(" | ")<a href="{editLink}?ReturnUrl=@Request.RawUrl">@T("Edit")</a></li>';
var refreshIds = function() {
var id = $('#@fieldIdForSelectedIds');
id.val('');
$("div[data-fieldid = @fieldIdForIds]").each(function() {
id.val(id.val() + "," + $(this).attr("data-id"));
});
var itemsCount = $("div[data-fieldid = @fieldIdForIds]").length;
if(!multiple && itemsCount > 0) {
addButton.hide();
}
else {
addButton.show();
}
};
window.mediaLibraryDirty = false;
var showSaveMsg = function() {
$('#save-message-@fieldIdForIds').show();
window.mediaLibraryDirty = true;
};
if (!window.mediaLibraryNavigateAway) {
$(window).on("beforeunload", window.mediaLibraryNavigateAway = function() {
if (window.mediaLibraryDirty) {
return "@HttpUtility.JavaScriptStringEncode(T("You have unsaved changes. Please only accept to leave if you don't mind losing those changes.").Text)";
}
});
$("#@(fieldIdForSelectedIds)").closest("form").on("submit", function() {
window.mediaLibraryDirty = false;
});
}
refreshIds();
addButton.click(function() {
var url = '@HttpUtility.JavaScriptStringEncode(Url.Action("Index", "Admin", new {area = "Orchard.MediaLibrary", dialog = true}))';
$.colorbox({
href: url,
iframe: true,
reposition: true,
width: "100%",
height: "100%",
onLoad: function() { // hide the scrollbars from the main window
$('html, body').css('overflow', 'hidden');
$('#cboxClose').remove();
},
onClosed: function() {
$('html, body').css('overflow', '');
var selectedData = $.colorbox.selectedData;
if (selectedData == null) // Dialog cancelled, do nothing
return;
var selectionLength = multiple ? selectedData.length : Math.min(selectedData.length, 1);
for (var i = 0; i < selectionLength ; i++) {
var template = @(fieldIdForIds)_Template
.replace(/\{contentItemId\}/g, selectedData[i].id)
.replace(/\{thumbnail\}/g, selectedData[i].thumbnail)
.replace(/\{title\}/g, selectedData[i].title)
.replace(/\{editLink\}/g, selectedData[i].editLink);
var content = $(template);
$('#media-library-picker-@fieldIdForIds ul').append(content);
}
refreshIds();
if (selectedData.length) {
showSaveMsg();
}
}
});
});
$(document).on("click",'#media-library-picker-@fieldIdForIds .media-library-picker-remove', function(e) {
e.preventDefault();
if (!confirm("@HttpUtility.JavaScriptStringEncode(T("Do you really want to remove that media?").Text)")) return false;
$(this).closest('li').remove();
refreshIds();
showSaveMsg();
return false;
});
$("#media-library-picker-@fieldIdForIds ul").sortable({
handle: '.thumbnail',
stop: function() {
refreshIds();
showSaveMsg();
}
}).disableSelection();
})(jQuery);
//]]>
</script>
}
@Display.MediaLibraryPicker(
FieldName: Html.FieldNameFor(m => m.SelectedIds),
DisplayName: Model.Field.DisplayName,
Multiple: settings.Multiple,
Required: settings.Required,
Hint: settings.Hint,
ContentItems: Model.ContentItems)

View File

@@ -0,0 +1,59 @@
@using Orchard.ContentManagement
@using Orchard.Utility.Extensions;
@{
Style.Include("media-library-picker-admin.css");
Style.Require("jQueryColorBox");
Script.Require("jQueryUI_Sortable").AtFoot();
Script.Require("jQueryColorBox").AtFoot();
Script.Include("media-library-picker.js").AtFoot();
var fieldName = (string) Model.FieldName;
var displayName = (string) Model.DisplayName;
var multiple = (bool)(Model.Multiple ?? false);
var required = (bool)(Model.Required ?? false);
var hint = (string) Model.Hint;
var contentItems = (IEnumerable<ContentItem>)Model.ContentItems ?? Enumerable.Empty<ContentItem>();
var contentManager = WorkContext.Resolve<IContentManager>();
}
<fieldset class="media-library-picker-field"
data-multiple="@multiple.ToString().ToLower()"
data-remove-text="@T("Remove")"
data-remove-prompt="@T("Do you really want to remove that media?")"
data-edit-text="@T("Edit")"
data-dirty-text="@T("You have unsaved changes. Please only accept to leave if you don't mind losing those changes.")"
data-pipe="@T(" | ")"
data-add-url="@HttpUtility.JavaScriptStringEncode(Url.Action("Index", "Admin", new { area = "Orchard.MediaLibrary", dialog = true }))"
data-return-url="@HttpUtility.JavaScriptStringEncode(Request.RawUrl)">
<label @if (required) { <text> class="required" </text> }>@displayName</label>
<div class="message message-Warning media-library-picker-message">@T("You need to save your changes.")</div>
<div class="items media-library-picker" summary="@displayName">
<ul>
@foreach (var contentItem in contentItems) {
var editRouteValues = contentManager.GetItemMetadata(contentItem).EditorRouteValues;
var editUrl = Url.Action(
Convert.ToString(editRouteValues["action"]),
editRouteValues.Merge(new RouteValueDictionary { { "ReturnUrl", Request.RawUrl } }));
<li>
<div data-id="@contentItem.Id" class="media-library-picker-item">
<div class="thumbnail">
@Display(BuildDisplay(contentItem, "Thumbnail"))
<div class="overlay">
<h3>@Html.ItemDisplayText(contentItem)</h3>
</div>
</div>
</div>
<a href="#" data-id="@contentItem.Id" class="media-library-picker-remove">@T("Remove")</a>@T(" | ")
<a href="@editUrl">@T("Edit")</a>
</li>
}
</ul>
</div>
<div>
<span class="button add">@T("Add")</span>
</div>
<input type="hidden" name="@fieldName" value="@String.Join(",", contentItems.Select(x => x.Id))" class="selected-ids" />
<span class="hint">@hint</span>
</fieldset>