Snarl = function() {
    var SNARL_WEB_BRIDGE = "http://127.0.0.1:9889/?d={0}&u={1}";
    var REGISTRATION = 0;
    var NOTIFICATION = 1;
    var iframe = null;
    var form = null;
    var field = null;
    var isInitialized = false;
    var isRegistered = false;
    var snarlsRunning = true; //TODO:
    var appName = null;

    function send(data) {
        if (!data) data = "";
        var u = new Date().getTime();
        var url = SNARL_WEB_BRIDGE.replace(/\{0\}/, data).replace(/\{1\}/, u);
        //window.prompt("url", url);
        iframe.contentWindow.location.replace(url);
    }

    return {
        init: function() {
            if (!isInitialized) {
                // set up iframe for communication
                iframe = document.createElement("iframe");
                iframe.id = "SnarlCommunicator";
                iframe.name = iframe.id;
                iframe.src = "about:blank";
                iframe.style.border = "0px";
                iframe.style.width = "0px";
                iframe.style.height = "0px";
                document.body.appendChild(iframe);
                if (!iframe.contentWindow)
                    iframe.document = iframe.contentDocument;

                isInitialized = true;
            }
        },

        register: function(applicationName, notificationTypes) {
            Snarl.init();
            //	if(snarlIsRunning){
            appName = applicationName;
            var data = { "action": REGISTRATION,
                "applicationName": applicationName,
                "notificationTypes": notificationTypes
            };
            var json = Snarl.utils.json.stringify(data);
            send(json);
            isRegistered = true;
            //	}
        },

        notify: function(notificationType, title, description, priority, sticky) {
            Snarl.init();
            if (isRegistered) {
                var data = { "action": NOTIFICATION,
                    "applicationName": appName,
                    "notificationType": notificationType,
                    "title": title,
                    "description": description,
                    "priority": priority,
                    "sticky": sticky
                };
                var json = Snarl.utils.json.stringify(data);
                send(json);
            }
        }
    }
} ();

Snarl.Priority = function() {
    return {
        Emergency: 2,
        High: 1,
        Normal: 0,
        Moderate: -1,
        VeryLow: -2
    }
} ();

Snarl.NotificationType = function(name, enabled) {
    this.name = name;
    this.enabled = enabled;
}

/* *************************************************
Snarl.utils.json

- the json module includes some regexs that look like unterminated strings, so some minification tools might choke on it

- if you would prefer to use another json library, you can override the following methods:
Snarl.utils.json.stringify(obj) - where obj is the object to convert. returns a json-formatted string
Snarl.utils.json.parse(json) - where json is the json-formatted string to parse. returns a javascript object

************************************************* */
Snarl.utils = function() {
    return {
        json: function() {
            // Test for modern browser (any except IE5).
            var JS13 = ('1'.replace(/1/, function() { return ''; }) == '');

            // CHARS array stores special strings for encodeString() function.
            var CHARS = {
                '\b': '\\b',
                '\t': '\\t',
                '\n': '\\n',
                '\f': '\\f',
                '\r': '\\r',
                '\\': '\\\\',
                '"': '\\"'
            };

            for (var i = 0; i < 32; i++) {
                var c = String.fromCharCode(i);
                if (!CHARS[c]) CHARS[c] = ((i < 16) ? '\\u000' : '\\u00') + i.toString(16);
            };

            function encodeString(str) {
                if (!/[\x00-\x1f\\"]/.test(str)) {
                    return str;
                } else if (JS13) {
                    return str.replace(/([\x00-\x1f\\"])/g, function($0, $1) {
                        return CHARS[$1];
                    });
                } else {
                    var out = new Array(str.length);
                    for (var i = 0; i < str.length; i++) {
                        var c = str.charAt(i);
                        out[i] = CHARS[c] || c;
                    }
                    return out.join('');
                }
            };

            return {
                stringify: function(arg) {
                    switch (typeof arg) {
                        //case 'string'   : return '"' + encodeString(arg) + '"'; // break command is redundant here and below. 
                        case 'string': return '"' + arg + '"'; // break command is redundant here and below.
                        case 'number': return String(arg);
                        case 'object':
                            if (arg) {
                                var out = [];
                                if (arg instanceof Array) {
                                    for (var i = 0; i < arg.length; i++) {
                                        var json = this.stringify(arg[i]);
                                        if (json != null) out[out.length] = json;
                                    }
                                    return '[' + out.join(',') + ']';
                                } else {
                                    for (var p in arg) {
                                        var json = this.stringify(arg[p]);
                                        if (json != null) out[out.length] = '"' + encodeString(p) + '":' + json;
                                    }
                                    return '{' + out.join(',') + '}';
                                }
                            }
                            return 'null'; // if execution reaches here, arg is null.
                        case 'boolean': return String(arg);
                            // cases function & undefined return null implicitly.
                    }
                },

                parse: function(text) {
                    try {
                        return !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(text.replace(/"(\\.|[^"\\])*"/g, ''))) && eval('(' + text + ')');
                    } catch (e) {
                        return false;
                    }
                }
            }
        } ()
    }
} ();

// Methods for master pages //

function setDateTimeInputs() {
	$('.dateInput').each(function () {
		if (this.value == '') {
			this.value = 'DDMMYYYY';
			$(this).css('color', '#c3c3c3');
		}
	});

	$('.timeInput').each(function () {
		if (this.value == '') {
			this.value = 'HHmm';
			$(this).css('color', '#c3c3c3');
		}
	});

  $('.dateInput').blur(function () {
    if (this.value == '') {
      this.value = 'DDMMYYYY';
      $(this).css('color', '#c3c3c3');
    }
  });

  $('.dateInput').focus(function () {
    if (this.value == 'DDMMYYYY') {
      this.value = '';
      $(this).css('color', '#000000');
    }
  });

  $('.timeInput').blur(function () {
    if (this.value == '') {
      this.value = 'HHmm';
      $(this).css('color', '#c3c3c3');
    }
  });

  $('.timeInput').focus(function () {
    if (this.value == 'HHmm') {
      this.value = '';
      $(this).css('color', '#000000');
    }
  });
}

function checkEnterKeyDown(e) {
  if (e.which == '13') {
    var type = e.srcElement.type;
    var name = e.srcElement.id;

    if (type == 'submit' || type == 'button' || type == 'textarea') {
    }
    else {
      e.preventDefault();

      if (name != "") {
        var control = $('#' + name);
        if (control.attr('cancelenter') == 'true') {
          return false;
        }
        var inputs = $('form').find(':input:visible:enabled');
        inputs.eq(inputs.index(control) + 1).focus();
      }
    }
  }
}

/* --- Ajax Script Service Methods --- */

function postAction(method, data, callBack) {
	$.ajax({
		type: "POST",
		url: "/webmethods/ajaxscriptservice.asmx/" + method,
		data: data,
		contentType: "application/json; charset=utf-8",
		dataType: "json",
		success: function (msg) {
			if (typeof callBack == "function") {
				callBack(msg.d);
			}
		},
		error: function (jqXHR, textStatus, errorThrown) {
			processError(jqXHR);
		}
	});
}

function processError(jqXHR) {
	alert(jqXHR.responseText);
}

/* --- General JS Methods --- */

function show(divobject) { 
  $("#" + divobject).show()
}

function hide(divobject) {
  $("#" + divobject).hide()
}

function GetHtmlElement(elementID)
{
	if (document.all)	
		return document.all[elementID];
	else if (document.getElementById)
		return document.getElementById(elementID);
	else if(document.layers)
		return document.layers[elementID];
}

function GetParentHtmlElement(elementID, doc)
{
	if (doc.all)	
		return doc.all[elementID];
	else if (doc.getElementById)
		return doc.getElementById(elementID);
	else if(doc.layers)
		return doc.layers[elementID];
}

function ClearControlAndFocus(id) {
	var txt = $('#' +id);
	txt.val('');
	txt.focus();
}

function PerformClose()
{
	if(window.opener != null)
		window.opener.location.reload();		
	window.close();
}

function GetRadWindow()
{
	var rdWindow = null;	
	if (window.radWindow) 
		rdWindow = window.radWindow;
	else if (window.frameElement.radWindow) 
		rdWindow = window.frameElement.radWindow;
	return rdWindow;
}

function CloseRadWindow() {
	var rdWindow = GetRadWindow();
	rdWindow.Close(null);		
}

function Redirect(url) {
	window.location = url;
}

function reloadWindow() {
	location.reload();
}

function HandleAJAXError(e, clientID)
{
	var result = confirm("You have been logged out due to a period of inactivity. You are required to login to continue using the application. Would you like to login?");
	
	if(result)
		location.reload(true);
}

function SelectAll(input)
{	
	// Russell Olivier: Create a range for the text
	var range = input.createTextRange();	
	// Russell Olivier: Do not collapse the text
	range.collapse(false);
	// Russell Olivier: Move to the end
	range.select();
}

function isNumber(n) { 
	return !isNaN(parseFloat(n)) && isFinite(n);    
}

function clearRBL(c) {
  var elementRef = document.getElementById(c);
  var inputElementArray = elementRef.getElementsByTagName('input');

  for (var i = 0; i < inputElementArray.length; i++) {
  	var inputElement = inputElementArray[i];
  	inputElement.checked = false;
  }
 }
