Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Kim Andersen 1447 posts 2197 karma points MVP
    Jan 30, 2013 @ 19:57
    Kim Andersen
    0

    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

  • Bo Damgaard Mortensen 719 posts 1207 karma points
    Feb 03, 2013 @ 13:06
    Bo Damgaard Mortensen
    0

    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:

    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; } }
    }  

    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>

    And the .ascx.cs file:
     
    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

  • Bo Damgaard Mortensen 719 posts 1207 karma points
    Feb 03, 2013 @ 13:23
    Bo Damgaard Mortensen
    0

    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);

     

  • 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.

Please Sign in or register to post replies