I have a question regarding extending or customizing the Tags data type to use tags form a JSON file.
What I want to achieve:
I want to use the Tags data type on some of my pages. But instead of this Tags data type using tags that have been inserted on other pages, I want the data type to find tags from a JSON file.
So when an editor starts writing a word, I want the Tags data type to look in my JSON instead of looking at tags on other pages when autocompleting the words/phrases.
Is this possible any way? And if yes, how?
It would be even more nice if it was possible to only save tags, that was found in the JSON, so that the editors can't come up with their own homemade tags by just writing them, but this is just a nice-to-have feature :D
I think your best bet would be to create a new datatype for this instead of trying to modify the current Tags datatype as this does db lookups in the tags table. Creating a new datatype based on the jQuery plugin tagIt (http://aehlke.github.com/tag-it/ i.e.) that does lookups in a JSON file shouldn't be that complicated with a little C# under your fingernails (actually, most of the development should be done in javascript)
All you need for the C# part is: a new custom control, a usercontrol (for using with the usercontrolwrapper in Umbraco) that makes use of the custom control, a javascript file and the tagIt JS references.
So to begin with, our custom control could look something like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Script.Serialization;
using System.Web.UI;
using System.Web.UI.WebControls;
[assembly: System.Web.UI.WebResource("yoursite.Umbraco.DataTypes.JsonTags.tagIt.css", "text/css")] [assembly: System.Web.UI.WebResource("yoursite.Umbraco.DataTypes.JsonTags.tagIt.js", "application/javascript")] [assembly: System.Web.UI.WebResource("yoursite.Umbraco.DataTypes.JsonTags.jsonTags.js", "application/javascript")]
namespace yoursite.Umbraco.DataTypes.JsonTags
{
public class JsonTags : Panel
{ // List of our tags private List _values = new List();
// An ASP.NET TextBox control to tie the frontend to the backend private readonly TextBox _data = new TextBox();
// JSON serializer for serializing
private readonly JavaScriptSerializer _jsonSerializer = new JavaScriptSerializer();
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
EnsureChildControls();
// Set the current tags in the textbox on page load
if (!Page.IsPostBack)
{
if (_values != null && _values.Count > 0)
{
string jsonArray = _jsonSerializer.Serialize(_values);
_data.Text = jsonArray;
}
}
}
protected override void CreateChildControls()
{ // Set css etc on the TextBox. CssClass is used for referencing it on the client
_data.CssClass = "data";
_data.TextMode = TextBoxMode.MultiLine;
_data.Attributes.Add("style", "display:none;");
// For debugging
//_data.Attributes.Add("style", "width:800px;height:800px;");
_data.ID = Parent.ID + "_dataTextBox";
// Add the javascript file as embedded resource
Page.ClientScript.RegisterClientScriptInclude(
"yoursite.Umbraco.DataTypes.JsonTags.jsonTags.js",
Page.ClientScript.GetWebResourceUrl(typeof(JsonTags), "yourSite.Umbraco.DataTypes.JsonTags.jsonTags.js"));
// Add tagIt javascript file as embedded resource
Page.ClientScript.RegisterClientScriptInclude(
"yoursite.Umbraco.DataTypes.JsonTags.tagIt.js",
Page.ClientScript.GetWebResourceUrl(typeof(JsonTags), "yourSite.Umbraco.DataTypes.JsonTags.tagIt.js"));
// Add tagIt css file HtmlLink link = new HtmlLink();
link.Attributes.Add("href", Page.ClientScript.GetWebResourceUrl(typeof(JsonTags), "yourSite.Umbraco.DataTypes.JsonTags.tagIt.css"));
link.Attributes.Add("type", "text/css");
link.Attributes.Add("rel", "stylesheet");
Page.Header.Controls.Add(link);
Controls.Add(new LiteralControl(markup.ToString()));
Controls.Add(_data);
}
// Property for getting and setting the tags public List Values
{
get
{
var result = new List(); if (!string.IsNullOrEmpty(_data.Text))
{
result = _jsonSerializer.Deserialize>(_data.Text); }
return result;
}
set
{
_values = value;
}
} }
using umbraco.editorControls.userControlGrapper;
namespace yoursite.Umbraco.DataTypes.JsonTags
{
public partial class TagsControl : System.Web.UI.UserControl, umbraco.editorControls.userControlGrapper.IUsercontrolDataEditor
{ // A list of the tags
List values;
protected void Page_Load(object sender, EventArgs e)
{ // Set the current tags on page load
if (!Page.IsPostBack)
{
jsonTagsControl.Values = values;
}
}
// This property handles get and set from/to the umbraco XML cache
public object value
{
get
{ // Save tags as XML
return SerializationHelper.ValueToXmlString(jsonTagsControl.Values);
}
set
{ // Check if the values are not null or empty.
if (value != null && string.IsNullOrEmpty(value.ToString())) // Return an empty list og tags
values = new List();
else
{ // Deserialize the XML and return the tags
values = (List)SerializationHelper.ValueFromXmlString(value, typeof(List));
}
}
}
}
}
Before going further, remember to set all .js and .css files as "Embedded Resource" (right click them in Visual Studio -> Properties -> Build action (I think it is) -> Embedded Resource) ! Very important ;-)
So, with these two classes we are now able to transfer XML values to and from the Umbraco XML cache. All values are stored as JSON in the _data TextBox in the custom control and can be accessed in the jsonTags.js file as follows (here comes the .NET'y javascript.. bear with me ;-))
$().ready(function() { // Reference to the tags input var tags = $('.tags');
// Array of tags var jsonArray = [];
// Reference to the data textbox var data = $('.data');
// Parse the JSON string var json = $.parseJSON(data.val());
// Loop through tags JSON $.each(json, function(i, v) { // Push to array jsonArray.push(v);
// Set tag value (should maybe be appended, just can't remember how ;-) tags.val(v); }); });
So basically, all user-interaction "logic" happens in your jsonTags.js file. Key-thing here is to always update the JSON string in the data Textbox to ensure the correct XML you get back. I find that a helper function is useful for that:
function updateData(dataTextBox, jsonArray) { dataTextbox.empty().append(JSON.stringify(jsonArray)); }
This should be called whenever the user adds a new tag and/or removes a tag after the jsonArray has been modified (i.e., when a user removes a tag, the value should be removed from the jsonArray aswell)
I will leave all javascript event handling and JSON lookup (in the json file) to a better frontend developer than me ;-)
Note to self: never edit a post that contains code :-( The editor stripped off a lot of "<" and ">". So all "List" should of course be: List<string> and "result = _jsonSerializer.Deserialize>(_data.Text);" should be:
result = _jsonSerializer.Deserialize<List<string>>(_data.Text);
How to only use tags from JSON in Tags data type
Hi guys
I have a question regarding extending or customizing the Tags data type to use tags form a JSON file.
What I want to achieve:
I want to use the Tags data type on some of my pages. But instead of this Tags data type using tags that have been inserted on other pages, I want the data type to find tags from a JSON file.
So when an editor starts writing a word, I want the Tags data type to look in my JSON instead of looking at tags on other pages when autocompleting the words/phrases.
Is this possible any way? And if yes, how?
It would be even more nice if it was possible to only save tags, that was found in the JSON, so that the editors can't come up with their own homemade tags by just writing them, but this is just a nice-to-have feature :D
Thank you very much in advance!
/Kim A
Hi Kim,
I think your best bet would be to create a new datatype for this instead of trying to modify the current Tags datatype as this does db lookups in the tags table. Creating a new datatype based on the jQuery plugin tagIt (http://aehlke.github.com/tag-it/ i.e.) that does lookups in a JSON file shouldn't be that complicated with a little C# under your fingernails (actually, most of the development should be done in javascript)
All you need for the C# part is: a new custom control, a usercontrol (for using with the usercontrolwrapper in Umbraco) that makes use of the custom control, a javascript file and the tagIt JS references.
So to begin with, our custom control could look something like this:
The UserControl looks like this:
.ascx file:
<%@ Register Assembly="yoursite.Umbraco.DataTypes" Namespace="yoursite.Umbraco.DataTypes.JsonTags" TagPrefix="custom" %>
<custom:JsonTags ID="jsonTagsControl" runat="server"></custom:JsonTags>
using umbraco.editorControls.userControlGrapper; namespace yoursite.Umbraco.DataTypes.JsonTags { public partial class TagsControl : System.Web.UI.UserControl, umbraco.editorControls.userControlGrapper.IUsercontrolDataEditor {// A list of the tags List values; protected void Page_Load(object sender, EventArgs e) {
// Set the current tags on page load if (!Page.IsPostBack) { jsonTagsControl.Values = values; } }
// This property handles get and set from/to the umbraco XML cache public object value { get {
// Save tags as XML return SerializationHelper.ValueToXmlString(jsonTagsControl.Values); } set {
// Check if the values are not null or empty. if (value != null && string.IsNullOrEmpty(value.ToString()))
// Return an empty list og tags values = new List(); else {
// Deserialize the XML and return the tags values = (List)SerializationHelper.ValueFromXmlString(value, typeof(List)); } } } } }
Before going further, remember to set all .js and .css files as "Embedded Resource" (right click them in Visual Studio -> Properties -> Build action (I think it is) -> Embedded Resource) ! Very important ;-)
So, with these two classes we are now able to transfer XML values to and from the Umbraco XML cache. All values are stored as JSON in the _data TextBox in the custom control and can be accessed in the jsonTags.js file as follows (here comes the .NET'y javascript.. bear with me ;-))
$().ready(function() {
// Reference to the tags input
var tags = $('.tags');
// Array of tags
var jsonArray = [];
// Reference to the data textbox
var data = $('.data');
// Parse the JSON string
var json = $.parseJSON(data.val());
// Loop through tags JSON
$.each(json, function(i, v) {
// Push to array
jsonArray.push(v);
// Set tag value (should maybe be appended, just can't remember how ;-)
tags.val(v);
});
});
So basically, all user-interaction "logic" happens in your jsonTags.js file. Key-thing here is to always update the JSON string in the data Textbox to ensure the correct XML you get back. I find that a helper function is useful for that:
function updateData(dataTextBox, jsonArray) {dataTextbox.empty().append(JSON.stringify(jsonArray));
}
This should be called whenever the user adds a new tag and/or removes a tag after the jsonArray has been modified (i.e., when a user removes a tag, the value should be removed from the jsonArray aswell)
I will leave all javascript event handling and JSON lookup (in the json file) to a better frontend developer than me ;-)
The output you get is:My tagAnother tag
Let me know if the above is totally nonsense!
All the best,
Bo
Note to self: never edit a post that contains code :-( The editor stripped off a lot of "<" and ">". So all "List" should of course be: List<string> and "result = _jsonSerializer.Deserialize>(_data.Text);" should be:
result = _jsonSerializer.Deserialize<List<string>>(_data.Text);
is working on a reply...
This forum is in read-only mode while we transition to the new forum.
You can continue this topic on the new forum by tapping the "Continue discussion" link below.