mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2026-02-09 09:16:41 +08:00
#18182: Implementing Autocompleted on Tags
Work Item: 18182 --HG-- branch : 1.x
This commit is contained in:
@@ -63,5 +63,12 @@ namespace Orchard.Tags.Controllers {
|
||||
|
||||
return View(viewModel);
|
||||
}
|
||||
|
||||
public JsonResult FetchSimilarTags(string snippet) {
|
||||
return Json(
|
||||
_tagService.GetTagsByNameSnippet(snippet).Select(tag => tag.TagName).ToList(),
|
||||
JsonRequestBehavior.AllowGet
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ Features:
|
||||
Orchard.Tags:
|
||||
Name: Tags
|
||||
Description: The tags module is providing basic tagging for arbitrary content types.
|
||||
Dependencies: Settings
|
||||
Dependencies: Settings, Orchard.jQuery
|
||||
Category: Navigation
|
||||
Orchard.Tags.Projections:
|
||||
Name: Tags Projections
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Module.txt" />
|
||||
<Content Include="Scripts\orchard-tags-autocomplete.js" />
|
||||
<Content Include="Styles\images\menu.tags.png" />
|
||||
<Content Include="Styles\menu.tags-admin.css" />
|
||||
<Content Include="Styles\orchard-tags-admin.css" />
|
||||
@@ -117,6 +118,9 @@
|
||||
<ItemGroup>
|
||||
<Content Include="web.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="Scripts\Web.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
|
||||
@@ -3,7 +3,11 @@ using Orchard.UI.Resources;
|
||||
namespace Orchard.Tags {
|
||||
public class ResourceManifest : IResourceManifestProvider {
|
||||
public void BuildManifests(ResourceManifestBuilder builder) {
|
||||
builder.Add().DefineStyle("TagsAdmin").SetUrl("orchard-tags-admin.css");
|
||||
var manifest = builder.Add();
|
||||
|
||||
manifest.DefineScript("TagsAutocomplete").SetUrl("orchard-tags-autocomplete.js").SetDependencies("jQueryUI_Autocomplete");
|
||||
|
||||
manifest.DefineStyle("TagsAdmin").SetUrl("orchard-tags-admin.css");
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/Orchard.Web/Modules/Orchard.Tags/Scripts/Web.config
Normal file
21
src/Orchard.Web/Modules/Orchard.Tags/Scripts/Web.config
Normal file
@@ -0,0 +1,21 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appSettings>
|
||||
<add key="webpages:Enabled" value="false" />
|
||||
</appSettings>
|
||||
<system.web>
|
||||
<httpHandlers>
|
||||
<!-- iis6 - for any request in this location, return via managed static file handler -->
|
||||
<add path="*" verb="*" type="System.Web.StaticFileHandler" />
|
||||
</httpHandlers>
|
||||
</system.web>
|
||||
<system.webServer>
|
||||
<handlers accessPolicy="Script,Read">
|
||||
<!--
|
||||
iis7 - for any request to a file exists on disk, return it via native http module.
|
||||
accessPolicy 'Script' is to allow for a managed 404 page.
|
||||
-->
|
||||
<add name="StaticFile" path="*" verb="*" modules="StaticFileModule" preCondition="integratedMode" resourceType="File" requireAccess="Read" />
|
||||
</handlers>
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
@@ -0,0 +1,57 @@
|
||||
(function ($) {
|
||||
$.extend({
|
||||
tagsAutocomplete: {
|
||||
minSnippetLength: 3,
|
||||
|
||||
autocomplete: function (textboxId, fetchUrl, minSnippetLength) {
|
||||
if (minSnippetLength != null) this.minSnippetLength = minSnippetLength;
|
||||
|
||||
function split(val) {
|
||||
return val.split(/,\s*/);
|
||||
}
|
||||
function extractLast(snippet) {
|
||||
return split(snippet).pop();
|
||||
}
|
||||
|
||||
var that = this;
|
||||
var textBox = $('#' + textboxId);
|
||||
|
||||
textBox.bind('keydown', function (event) {
|
||||
// don't navigate away from the field on tab when selecting an item
|
||||
if (event.keyCode === $.ui.keyCode.TAB && $(this).data('autocomplete').menu.active) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}).autocomplete({
|
||||
source: function (request, response) {
|
||||
$.getJSON(fetchUrl, {
|
||||
snippet: extractLast(request.term)
|
||||
}, response);
|
||||
},
|
||||
appendTo: textBox.parent(),
|
||||
search: function () {
|
||||
// custom minLength
|
||||
var snippet = extractLast(this.value);
|
||||
if (snippet.length < that.minSnippetLength) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
focus: function () {
|
||||
// prevent value inserted on focus
|
||||
return false;
|
||||
},
|
||||
select: function (event, ui) {
|
||||
var snippets = split(this.value);
|
||||
// remove the current input
|
||||
snippets.pop();
|
||||
// add the selected item
|
||||
snippets.push(ui.item.value);
|
||||
// add placeholder to get the comma-and-space at the end
|
||||
snippets.push('');
|
||||
this.value = snippets.join(', ');
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
@@ -5,6 +5,14 @@ using Orchard.Tags.Models;
|
||||
namespace Orchard.Tags.Services {
|
||||
public interface ITagService : IDependency {
|
||||
IEnumerable<TagRecord> GetTags();
|
||||
|
||||
/// <summary>
|
||||
/// Returns tags whose name start with snippet
|
||||
/// </summary>
|
||||
/// <param name="snippet">The starting snippet</param>
|
||||
/// <param name="maxCount">Maximum number of tags returned</param>
|
||||
/// <returns>Tags found</returns>
|
||||
IEnumerable<TagRecord> GetTagsByNameSnippet(string snippet, int maxCount = 10);
|
||||
TagRecord GetTag(int tagId);
|
||||
TagRecord GetTagByName(string tagName);
|
||||
IEnumerable<IContent> GetTaggedContentItems(int tagId);
|
||||
|
||||
@@ -41,6 +41,11 @@ namespace Orchard.Tags.Services {
|
||||
return _tagRepository.Table.ToList();
|
||||
}
|
||||
|
||||
public IEnumerable<TagRecord> GetTagsByNameSnippet(string snippet, int maxCount = 10) {
|
||||
if (String.IsNullOrEmpty(snippet)) return null; // Otherwise would return the whole dataset
|
||||
return _tagRepository.Fetch(tag => tag.TagName.StartsWith(snippet)).Take(maxCount);
|
||||
}
|
||||
|
||||
public TagRecord GetTag(int tagId) {
|
||||
return _tagRepository.Get(x => x.Id == tagId);
|
||||
}
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
}
|
||||
.orchard-tags .manage label[for=TagName] {
|
||||
display:none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,23 @@
|
||||
@model Orchard.Tags.ViewModels.EditTagsViewModel
|
||||
|
||||
@{
|
||||
Style.Require("jQueryUI_Orchard");
|
||||
Script.Require("TagsAutocomplete");
|
||||
}
|
||||
|
||||
<fieldset>
|
||||
@Html.LabelFor(m => m.Tags, T("Tags"))
|
||||
@Html.TextBoxFor(m => m.Tags, new { @class = "large text" })
|
||||
</fieldset>
|
||||
</fieldset>
|
||||
|
||||
@using (Script.Foot()) {
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
$(function () {
|
||||
$.tagsAutocomplete.autocomplete(
|
||||
'@Html.FieldIdFor(m => m.Tags)',
|
||||
'@Url.Action("FetchSimilarTags", new { Controller = "Home", Area = "Orchard.Tags" })', 1);
|
||||
});
|
||||
//]]>
|
||||
</script>
|
||||
}
|
||||
Reference in New Issue
Block a user