Saturday, December 19, 2015

scanning for keywords as you type

If you need to detect the presence of keywords as you type, you can add a small amount of javascript to your client. This may be useful to detect the typing of tags and to populate your data model with structured data.
For example, if you want to detect football teams while you type, you could do something like this. You'll want to ensure your data model has been updated to have two-value Yes/No fields indicated by the uitests_ prefix.
// Provide a handler that can find hashtag keywords in a text box and update a data model. The keywords 
// are mapped to field names using a simple data structure. Everything here is hard-coded
// to help demonstrate the basic idea.

// We use methods that are easy to program for the POC but are not supported on all devices
// however, this is a way to do this for all devices, but let's be lazy this time.

// Mapping between hashtags (starting with #) and field names.
// Normally this is stored in a custom entity or uses some other scheme...
var mappings = {
"Ravens" : "uitests_Ravens",
"Patriots" : "uitests_Patriots",
"SF" : "uitests_SF"
};

// This could also be a call out to a web service but additional
// logic to make the call out efficient would be needed.
function attachChangeHandlers(controlName) {
    controlName = "description"
    var controlNameDOM = "description_i"

    // Process content scanning for hashtags.
    function processContent(content) { 
        for(hashtag in mappings) {
                if(!mappings.hasOwnProperty(hashtag)) { continue; }
                var attributeToSet = mappings[hashtag];            
                if(attributeToSet && content) {
                    if(~content.toLowerCase().indexOf("#" + hashtag.toLowerCase())) {                
                        Xrm.Page.getAttribute(attributeToSet.toLowerCase()).setValue(true);
                    }
                }
            }
    }


    // Normally we would define a namespace for our customizations...
    // This checks the map on every keystroke which is inefficient
    // but this can easily be optimized.
    // For 2016, can have the context passed in ;-)
    var keywordHandler = function() {
        try { 
            // CRM 2016 only! If you use 2015, you don't need domControl passed in.
            //var userInput = Xrm.Page.ui.controls.get(controlName).getValue();
            var userInput = this.value
            processContent(userInput)
        } catch(ex) {
            console.log(ex);
        }
        }


    // CRM 2016 has an API for key presses and getting the value of a control
    // as you type...use that after you upgrade because its more portable.
    //Xrm.Page.getControl(name).addOnKeyPress(keywordHandler)

    // The hard way...get the doc inside the MS CRM Dynamics IFrame.
    // parent.parent.document gets us to the topmost level.
    var doc = parent.parent.document.getElementById("contentIFrame0").contentWindow.document
    var inputControl = doc.getElementById(controlNameDOM);
    inputControl.addEventListener("keyup", keywordHandler);

    // Attach to the rich text editor as well
    window.setTimeout(function() { 
    var CKE = parent.parent.document.getElementById("contentIFrame0").contentWindow.CKEDITOR;
    if(CKE) {
        var richEditor = CKE.instances["new_richdescription_i"];
        if(richEditor) { 
            console.log("Found rich editor");
            richEditor.on('key', function() {
                processContent(richEditor.getData());
            });
        } else { 
            console.log("Did not find rich text editor!");
        }
    } else { 
        console.log("No CKEDITOR object found");
    }}, 2000);
}
Now in your form load event, call the setup function. As you type, the keywords are detected and the data model changed. Of course, you would usually hookup the keyword to field name mapping as an entity and pull it into the form when it loads, but that's an exercise for the reader.
The handler is attached to both a standard description box as well as a rich text description box (see my otehr blog). The delay is there with an overly generous delay to allow the CKEDITOR to load before the handler is attached. There's probably another way to do it, but most people will attach to the standard description box anyway so ignore that part of teh code.
MS CRM 2016 has API to allow attached key press handlers to controls, so some of the shanigans in this code are not needed in 2016 (yeah!).
With this setup, you can now detect twitter like hashtag words in text and change your data model e.g. "John mentioned that he likes #SF and the #Patriots" sets these attributes to true in the data model in real-time. This is convenient if someone is taking notes but they do not want to move their hands or finds tagging the record too burdonsome. There are "tag" oriented solutions you can add that add a nice tag model to your data model so you may want to look into those as well.

No comments:

Post a Comment