Approaching Dialog Messages

Published in Front-end Development On Jun 9th 2015

Mixing logic is a dirty business. Filling your JavaScript with hard coded HTML is very rarely a good idea that can potentially diminish a project's extendibility. Luckily I had the opportunity to face this problem head on and arrive with an amicable solution.

Whilst building my University Major Project I came across the issue of managing various user prompted dialogue messages—you know, those alerts that notify the user; "Sorry, the username JonSnowRulez777 has already been taken!". After scouring stack overflow and devote:ee for advice or a plugin I fell short and was unsuccessful. I decided to embark on creating my own solution specifically for this project.

The Issue

My project had many interactions via prompted dialogue encounters, alerting the user of the following; errors, warnings, information and successful actions. These messages are called when the user needed to be notified by the system. Initially I had the idea of creating a function where callback data would be passed through and then a relevant message was to be appended to the DOM. All examples are written in jQuery.

function dialogueMessages(messageType, messageContent){
    //Lets ensure something is called back, no empty boxes will be left on screen
    if (messageType && messageContent){
        //Setup Variables
        var content = messageContent;
        var type = messageType;
        //Lets construct how the message works and add the dynamic variables 
        var message = '<div class="message '+type+'"><p>'+content+'</p> <a class="close-message">Dismiss</a></div>'
        //And finally lets append the constructed message into the DOM via the body
        $('body').append(message);
    }//conditonal ends
}//dialogueMessages
//The function can then be called like this
dialogueMessages("error", "<strong>Oops! :</strong> Please enter a valid Email Address.")

Whilst this is a perfectly working solution I feel it isn't the correct one as it requires maintenance and can be broken easily by someone who isn't familiar with JavaScript. In addition to this the messages aren't indexed at all and it specifically doesn't adhere to DRY(don't repeat yourself) coding standards. If this error was to appear on another page, the same call would presumably have to be input over and over.

The Proposed Solution

First and foremost I wanted to tackle indexing messages. I felt that if the very foundations from where each of the messages receive their content was responsibly constructed that everything else would flow in the same manner. Which in turn is why I decided to opt for a RESTful service; for those that aren't familiar, APIs that adhere to the REST (Representational State Transfer) architectural constraints are called RESTful—Ryan Tomayko's article on explaining REST to his wife is excellent for further reading. In turn our message content is retrieved via a HTTP request based on a URI, such as "example.com/message/12".

I won't go into the dirty details regarding the implementation of a RESTful service into your own system, besides Mark Kirby has done a stellar job on that already. On this project I used Expression Engine as a base system for the entire site. Expression Engine is an incredibly powerful content management system that can be extended far past it's intended use. As such Expression Engine is built with a RESTful approach and allows for it's data to be output in many forms, namely JSON. In addition anyone who has access to the control panel can add and edit any message entries as they see fit.

My solution would be simple, fetch a message based on ID via a URI that returns JSON then construct a message in JavaScript to be appended to the DOM.

function dialogueMessages(messageID){
    //Lets ensure something is called back, no empty boxes will be left on screen
    if (messageID){
        //Setup our catch variables
        msgId = messageID;
        //GET Message Information via AJAX
        $.ajax({
            //Set the type of to GET a response
            type: "GET",
            //Construct the URL in which message to retrieve
            url: "http://www.example.com/message?="+msgId,
            //Let the call know it is getting back JSON
            dataType: "json",
            //On Success
            success: function(data){
                //Loop through object
                $.each(data.message, function(i, item){
                    //Catch variables
                    var msgName = item.MessageNameURI; //Will return something like "wrong-password"
                    //Lets stop duplicate messages from forming before we even get started
                    if ($("ul.messages li#"+msgName).length == 0){
                        //Catch variables
                        var msgType = item.messageType;
                        var msgContent = item.messageContent;
                        //Construct our dynamic message
                        var message = "<li id='"+msgName+"' class='message "+msgType+"'><p>"+msgContent+"</p></li>";
                        //To allow for multiple messages we want to construct a list, lets conditonally add it
                        if ($("ul.messages").length == 0){
                            $('body').append("<ul class='messages'>"+message+"</ul>");
                        }else{
                            //If the UL Element does exist lets just append the message to it
                            $('ul.messages').append(message);
                        }//Else
                    }//end if conditional
                });//each
            },
            //Otherwise
            error: function(){
                //alert the user that no message was returned
                alert('Error Status 301: Could not retrieve message data');
            }//Response Handling
        });//Ajax Call Ends
    }//if messageID Exists
}//dialogueMessages ends
//The function can then be called like this
dialogueMessages(12);

To sum up this function allows the user to call a specific message object from a URI and append it to the DOM with the addition of some basic error handling.

Ways to Improve

In the spirit of learning I feel there are a few ways to improve this solution—firstly limiting requests. A restful API without any sort of request protection leaves it open to DDoS attacks. Thankfully Expression Engine comes equipped with Throttling Control, allowing the site admin to limit requests.

Conclusion

I feel this solution was the correct one for my University Major Project as it made the handling of dialogue messages simple to use and manage. Whilst it may be looked at as overkill for websites that have few user dialogue messages it is certainly an improvement upon the initial function. Perhaps a plugin of some description could be on it's way in the near future.