Client-side scripting for Taxonomy/Term Set Fields

    I haven’t found any way of how to attach to onchange event of term store fields for the edit/new forms, so I had to spend a couple of hours on reverse engineering of WebTaggingDialog.js and ScriptForWebTaggingUI.js and in piece of HTML which represents SharePoint FormField for Taxonomy field. 
    So, in HTML this field is bound as a set of spans, divs, hidden field and image to open WebTaggingDialog.aspx: 


<SPAN id=ctl00_MyTaxonomyFieldID_ctl00_ctl00>

    <INPUT id=ctl00_MyTaxonomyFieldID_ctl00_ctl01 class="ms-taxonomy ms-taxonomy-height ms-long" value=MyTaxonomyFieldValue|f0d123d1-ac8c-4a18-bccb-65c9b5ea83af type=hidden>

    <DIV id=ctl00_MyTaxonomyFieldID_ctl00_ctl02 class="ms-taxonomy ms-taxonomy-height ms-long" InputFieldId="ctl00_MyTaxonomyFieldID_ctl00_ctl01" SspId="68e138c4-5729-4ddd-ab0d-95c688c6c8eb" GroupId="00000000-0000-0000-0000-000000000000" TermSetId="14d6d1a1-0536-4fa3-977e-ecb2c764c061" AnchorId="00000000-0000-0000-0000-000000000000" IsMulti="true" AllowFillIn="false" WidthCSS="ms-long" Lcid="1033" IsSpanTermSets="false" IsSpanTermStores="false" IsIgnoreFormatting="false" IsIncludeDeprecated="false" IsIncludeUnavailable="false" IsIncludeTermSetName="false" IsAddTerms="false" IsIncludePathData="false" IsUseCommaAsDelimiter="true" Disable="false" ExcludeKeyword="false" WebServiceUrl="https://mysp2010server.com.au/_vti_bin/TaxonomyInternalService.json" FieldName="MyTaxonomyField" FieldId="8ebb773d-19e4-4132-a1eb-ee2686a3bed0" DisplayPickerButton="true" MinimumHeight="15" IsPercentWidth="false" IsUnvalidated="false" AdjustingHeight="false" Validating="false">

                <DIV id=ctl00_MyTaxonomyFieldID_ctl00_ctl02controlHolder class="ms-taxonomy-control-holder ms-long">

                        <IMG class=ms-taxonomy-browser-button title="Browse for a valid choice" tabIndex=0 alt="Browse for a valid choice" src="/_layouts/images/EMMCopyTerm.png" width=16 height=16>

                        <DIV style="WIDTH: 256px" class=ms-taxonomy-fieldeditor title=Location RteRedirect="ctl00_MyTaxonomyFieldID_ctl00_ctl02editableRegion">

                                <DIV aria-haspopup=true id=ctl00_MyTaxonomyFieldID_ctl00_ctl02editableRegion class="ms-taxonomy-writeableregion  ms-rtestate-write" role=textbox contentEditable=true aria-multiline="true" aria-autocomplete="both" DisableRibbonCommands="True" AllowMultiLines="false" RestrictPasteToText="True" alltermsvalid="true">

                                        <SPAN class=valid-text title="">MyTaxonomyFieldValue</SPAN>; 

                                </DIV>

                        </DIV>

                </DIV>

                <DIV id=ctl00_MyTaxonomyFieldID_ctl00_ctl02suggestionsContainer class="ms-taxonomy-suggestion-container ms-rtefocus-invalid ms-taxonomy-hidden" unselectable="on" RteRedirect="ctl00_MyTaxonomyFieldID_ctl00_ctl02editableRegion">

                        <DIV class=ms-taxonomy-suggestion-holder unselectable="on" needsNewRequest="false" addCreateNewWhileTrimming="false" isSpanTermSets="false">

                        </DIV>

                        <IMG class=ms-taxonomy-panel-resizer src="/_layouts/images/CornerGrip.gif" width=15 height=15 unselectable="on">

                </DIV>

        </DIV>
</SPAN>


    The first thought was to create a timer function checking if the value of hidden field has changed. This solution is quick but not smart enough :), so I decided to keep on digging the code. 
    After some hours of debugging I found a solution! They use a little piece of code which is a back door into their library:
 setRawText:function(text){ULSX8o:;var $0=this.$2_51();$0.value=text;eval(this.$2_64());}
Well, eval(this.$2_64()) looks very good for injecting our script!
So, here setRawText is a function which sets the text of the hidden field carrying taxonomy field value, this.$2_64() is a function:
 $2_64:function(){ULSX8o:;return this.$2_5.JavascriptOnValidation;}
Where $2_5 is a main div (containing css class “ms-taxonomy”) which carries configuration values of the Taxonomy field! Gotcha! What we need to do is just assign our function to the attribute JavascriptOnValidation of the div:
 $(' div.ms-taxonomy[id*="<%=MyTaxonomyField.ClientID%>"]').attr('JavascriptOnValidation', 'alert(text);');  

Here:
 - text – is a field which will contain selected taxonomy field value, 
 - ms-taxonomy is a css class of required div and
 - MyTaxonomyField.ClientID is a client ID of required Taxonomy field. As I have my custom form for editing and creating List items I can retrieve taxonomy field id and use it in the selector. If you’re using standard edit/new form you need to find an appropriate JQuery selector for the div field. 
    And finally, replace alert(text) with a function you need...

Comments

  1. Anonymous9/5/13 16:30

    Hi Maksym, I have been trying to get this working but my function never gets called in JavascriptOnValidation...my scenario is that I am trying to implement this on a custom page with a TaxonomyWebTaggingControl instance within a Visual Web Part (SharePoint 2010). I don't think this is too different as the same control is used on the SharePoint forms.

    I have tried every which way but can't seem to get this working. Any ideas gratefully received..Thanks Sean

    ReplyDelete
    Replies
    1. Hi Sean,

      Sorry, for some reason I wasn't alerted that I got a new comment in my blog. If you still have that problem I will try to help you.

      To begin with, can you please provide:
      1) html part of the TaxonomyWebTaggingControl which is rendered on the client
      2) your javascript that adds JavascriptOnValidation attribute?

      Delete
    2. Hi Sean,

      there is a better (and right) way to handle such events, please see my question in this blog post http://blog.vgrem.com/2013/01/23/using-sharepoint-taxonomywebtaggingcontrol-control-access-and-manipulate-from-client-side/#comment-2029

      Delete

Post a Comment

Popular posts from this blog

SharePoint delegate control is rendered twice

Some thoughts on using Sitecore Habitat for Production codebase