﻿var DynamicsCommon = {};

// Returns true if the object is null, unknown or undefined; false otherwise.
DynamicsCommon.IsNull = function(o)
{
    return ("undefined" == typeof(o) || "unknown" == typeof(o) || null == o);
};


// Gets the target of the current event
DynamicsCommon.GetEventTarget = function(ev) 
{
    // How you get the event target varies between IE and FireFox
    return ( !DynamicsCommon.IsNull(ev) && !DynamicsCommon.IsNull(ev.target) ) ? ev.target : event.srcElement;
};

DynamicsCommon.StopPropogation = function(ev)
{
    if( !DynamicsCommon.IsNull(ev) && !DynamicsCommon.IsNull(ev.stopPropagation) )
        ev.stopPropagation();
    else if(event)
        event.cancelBubble = true;
};

// Gets the display name for the specified value in a select
DynamicsCommon.GetDisplayNameForSelect = function(select, value)
{
    if (DynamicsCommon.IsNull(select) || DynamicsCommon.IsNull(value)) 
    {
        return null;
    }
    
    var firstOption = select.firstChild;
    while (!DynamicsCommon.IsNull(firstOption)) 
    {
        if (firstOption.value == value)
        {
            return firstOption.innerHTML;
        }
        firstOption = firstOption.nextSibling;
    }

    return null;
};

// Trims the specified string
DynamicsCommon.Trim = function(str)
{
    return str.replace(/^\s+|\s+$/g, "");
}

// Applies the specified class to the object
DynamicsCommon.ApplyStyle = function(o, sClass, append)
{
    if (append)
        o.className = o.className + ' ' + sClass;
    else
        o.className = sClass;
}

// Returns the maximum of the two values
DynamicsCommon.Max = function(one, two)
{
   return Math.max(one,two);
}

// Adds an event handler
DynamicsCommon.AddEvent = function(eventSource, eventName, callbackFunction)
{
    if(typeof eventSource.addEventListener != 'undefined')
    { /*W3C compliant*/
        eventSource.addEventListener(eventName, callbackFunction, false);
    }
    else if(typeof window.attachEvent != 'undefined')
    { /*IE Method*/
        eventSource.attachEvent('on' + eventName, callbackFunction);
    
    }
    else
    {
        alert('dynamic eventing not supported');
    }
};

// Removes an event handler
DynamicsCommon.RemoveEvent = function(eventSource, eventName, callbackFunction)
{
    if(typeof eventSource.removeEventListener != 'undefined')
    { /*W3C compliant*/
        eventSource.removeEventListener(eventName, callbackFunction, false);
    }
    else if(typeof window.detachEvent != 'undefined')
    { /*IE Method*/
        eventSource.detachEvent('on' + eventName, callbackFunction);
    }
    else
    {
        alert('dynamic eventing not supported');
    }
};

// Finds a node within the specified element with a given node name
DynamicsCommon.FindNode = function(el, nodeName, onlyVisible)
{
    function isVisible(o)
    {
        if (!onlyVisible)
            return true;
        return (o && o.style && o.style.display != 'none' && o.style.visibility != 'hidden')
    }
    
    var o = el;
    if (o.nodeName.toLowerCase() == nodeName.toLowerCase() && isVisible(o)) 
    {
        return o;
    }
    
    var child = o.firstChild;
    while (!DynamicsCommon.IsNull(child)) 
    {
        if (isVisible(child))
        {
            var foundInstance = DynamicsCommon.FindNode(child, nodeName, onlyVisible);
            if (!DynamicsCommon.IsNull(foundInstance)) 
            {
                return foundInstance;
            }
        }
        child = child.nextSibling;
    }
    
    return null;
};

// Removes the specified element from the array
DynamicsCommon.RemoveElement = function(arr, el) 
{
    if (DynamicsCommon.IsNull(arr) || DynamicsCommon.IsNull(el) || DynamicsCommon.IsNull(arr.length)) 
    {
        return false;
    }

    var removed = false;
    var i;
    var iLen = arr.length;
    for (i = 0; i < iLen; i++) 
    {
        if (arr[i] == el) 
        {
            removed = true;
            arr.splice(i, 1);
            i--;
            iLen--;
        }
    }
    return removed;
}

DynamicsCommon.CompareClass = function(o, className)
{
    if(!DynamicsCommon.IsNull(o.className))
    {
        var classArray = o.className.split(' ');
        for (var i = 0; i < classArray.length; i++)
        {
            if (classArray[i] == className) 
            {
                return true;
            }
        }
    }
    return false;
}

DynamicsCommon.CompareAxCtrlType = function(o, axCtrlType)
{
	if(DynamicsCommon.IsNull(o))
		return false;
		
	return !DynamicsCommon.IsNull(o.getAttribute) && o.getAttribute("AxCtrlType") == axCtrlType;
}


// Finds an object with the specified class name or AxCtrlType attribute as a child of the current object
DynamicsCommon.FindInstance = function(o, className, onlyVisible)
{
    function isVisible(o)
    {
        if (!onlyVisible)
            return true;
        return (o && o.style && o.style.display != 'none' && o.style.visibility != 'hidden')
    }

	if(DynamicsCommon.IsNull(o))
		return null;
	
	if(isVisible(o) && (DynamicsCommon.CompareClass(o, className) || DynamicsCommon.CompareAxCtrlType(o,className)))
	{
	    return o;
	}
    
    var child = o.firstChild;
    while (!DynamicsCommon.IsNull(child)) 
    {
        if (isVisible(child))
        {
            var foundInstance = DynamicsCommon.FindInstance(child, className, onlyVisible);
            if (!DynamicsCommon.IsNull(foundInstance)) 
            {
                return foundInstance;
            }
        }
        child = child.nextSibling;
    }
    
    return null;
};

// Finds the position of the specified element on the screen
DynamicsCommon.FindPosition = function(obj, /*optional*/ relToAbsoluteParent) 
{
    if (!relToAbsoluteParent)
        relToAbsoluteParent = false;

	var curleft = curtop = 0;
	if (obj.style.pixelTop)
	{
		return [obj.style.pixelLeft, obj.style.pixelTop];
	}
 	
	if (obj.offsetParent)
    {	        
	    curleft = obj.offsetLeft;
	    curtop = obj.offsetTop;
	    if (!relToAbsoluteParent || obj.style.position != 'absolute')       //Position of object will be relative to parent who is absolute positioned
	    {		    
	        while ((obj = obj.offsetParent) && (obj.nodeName != 'BODY')) 
	        {
		        if (relToAbsoluteParent && obj.style.position == 'absolute')
		            break;		        
		        
		        curleft += obj.offsetLeft + Math.floor((obj.offsetWidth - obj.clientWidth)/2);  //Take into account border widths
		        curtop += obj.offsetTop + Math.floor((obj.offsetHeight - obj.clientHeight)/2);
	        }
	    }
    }
	return [curleft,curtop];
};

// Finds the relative position of the specified element on the screen
DynamicsCommon.FindRelativePosition = function(obj) 
{
    var coords = DynamicsCommon.FindPosition(obj);
    if (obj.offsetParent) 
    {
        var parentCoords = DynamicsCommon.FindPosition(obj.offsetParent);
        return [coords[0] - parentCoords[0], coords[1] - parentCoords[1]];
    }
    return coords;
};

// Gets the parent with the specified tagname
DynamicsCommon.GetParentElement = function(el, tagName)
{
    var o = el;
    tagName = tagName.toLowerCase();
    while (!DynamicsCommon.IsNull(o) && !DynamicsCommon.IsNull(o.tagName) && o.tagName.toLowerCase() != tagName )
    {
        o = DynamicsCommon.GetParent(o);
    }
    return o;
};

// Gets the parent of the specified object
DynamicsCommon.GetParent = function(obj, className) 
{
    // Check for null argument
    if (DynamicsCommon.IsNull(obj))
    {
        return null; 
    }

    // Get immediate parent
    var parent;
    if (!DynamicsCommon.IsNull(obj.parentElement)) 
    {
        // IE support
        parent = obj.parentElement;
    }
    else 
    {
        // W3C support
        parent = obj.parentNode;
    }
    
    // If we couldn't find a parent or aren't looking for a anything or this is the class we're looking for or the AxCtrlType we are looking for
    if (DynamicsCommon.IsNull(className) || 
		DynamicsCommon.IsNull(parent) || 
		DynamicsCommon.CompareClass(parent, className) ||
		DynamicsCommon.CompareAxCtrlType(parent,className))
    {
        return parent;
    }
    
    // Recurse
    return DynamicsCommon.GetParent(parent, className);
};

// Gets whether we are running on the client context
DynamicsCommon.IsRunningOnDesktop = function()
{
    var queryStr = unescape(location.search);
    if (queryStr.length > 1)
	    queryStr = queryStr.substr(1);

    var regEx = /^runonclient\s*=\s*1\s*/i;
    var queryArray = queryStr.split('&');
    for (var i = 0; i < queryArray.length; i++)
        if (queryArray[i].match(regEx))
	        return true;
    return false;  
}

DynamicsCommon.GetElementWithClientID = function(clientID, elementID)
{
    return $get(clientID + '_' + elementID);
}

DynamicsCommon.GetFirstChildElement = function(e)
{
    for (var i = 0; i < e.childNodes.length; i++)
    {
        if (e.childNodes[i].nodeType == 1)
            return e.childNodes[i];
    }

    return null;
}

DynamicsCommon.GetLastChildElement = function(e)
{
    for (var i = e.childNodes.length-1; i >= 0; i--)
    {
        if (e.childNodes[i].nodeType == 1)
            return e.childNodes[i];
    }

    return null;
}

DynamicsCommon.GetNthChildElement = function(e, n)
{
    var numFound = -1;
    for (var i = 0; i < e.childNodes.length; i++)
    {
        if (e.childNodes[i].nodeType == 1)
        {
            numFound++;
            if(numFound == n)
                return e.childNodes[i];
        }
    }

    return null;
}

DynamicsCommon.GetChildElementCount = function(e)
{
    var numFound = 0;
    for (var i = 0; i < e.childNodes.length; i++)
    {
        if (e.childNodes[i].nodeType == 1)
            numFound++;
    }

    return numFound;
}

DynamicsCommon.GetChildElementArray = function(e)
{
    if(DynamicsCommon.IsNull(e))
        return null;
        
    var retArray = new Array();
    var arrIndex = 0;
    
    for (var i = 0; i < e.childNodes.length; i++)
    {
        if (e.childNodes[i].nodeType == 1)
        {
            retArray[arrIndex] = e.childNodes[i];
            arrIndex++;
        }
    }

    return retArray;
}

DynamicsCommon.contains = function(container, containee) 
{
  while (containee) 
  {
    if (container == containee) 
    {
      return true;
    }
    containee = containee.parentNode;
  }
  return false;
}

DynamicsCommon.InnerText = function(elem)
{
	return (!DynamicsCommon.IsNull(elem.innerText) ? elem.innerText : elem.textContent);
}

DynamicsCommon.htmlEncode = function(str)
{
    var newstr;
    newstr = str.replace(/&/g,"&amp;");
    newstr = newstr.replace(/</g,"&lt;");
    newstr = newstr.replace(/>/g,"&gt;");
    newstr = newstr.replace(/  /g," &nbsp;");
    return newstr;
}

DynamicsCommon.isUserLanguageRTL = function()
{
    return (document.documentElement.dir == 'rtl');
}

DynamicsCommon.CanReceiveFocus = function(tagName)
{
    //According to http://www.w3.org/TR/html4/interact/forms.html#h-17.11.1    
    switch(tagName.toUpperCase())
    {
        case 'A':
        case 'AREA':
        case 'BUTTON':
        case 'INPUT':
        case 'OBJECT':
        case 'SELECT':
        case 'TEXTAREA':
            return true;    
    }
    return false;
}

// Returns size of the full client area 
DynamicsCommon.GetClientSize = function() {
  var width = 0, height = 0;
  if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    width = window.innerWidth;
    height = window.innerHeight;
  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
    //IE 6+ in 'standards compliant mode'
    width = document.documentElement.clientWidth;
    height = document.documentElement.clientHeight;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
    //IE 4 compatible and backCompat mode
    width = document.body.clientWidth;
    height = document.body.clientHeight;
  }

  return [height, width];
}

//Updates the tab index for all focusable elements.
//The index is set to the same. The browser will tab according to rendered order.
//
//Used by lookups to help remedy an IE bug where the focus isn't properly set after the lookup's update panel is refreshed.
//In this scenario, the update panel in the lookup is refreshed (ex. you sort the grid), and when you reopen
//the lookup, it looks like the focus is set on the lookup but when you move the mouse or press a key, the 
//focus moves to the body. Setting the tabindex will help put focus back on the lookup if the user's first
//keystroke after this issue occurs is the TAB key.
DynamicsCommon.RearrangeTabOrder = function(node, tabIndex)
{   
    if (!node)
        return;
        
    if (!tabIndex)
        tabIndex = 3200;    //Give it a high number so it doesn't hopefully interfere with other explicitly set tab indices 
           
    if (DynamicsCommon.CanReceiveFocus(node.nodeName))
        node.tabIndex = tabIndex;
        
    for (var i=0; i < node.childNodes.length; i++)    
        DynamicsCommon.RearrangeTabOrder(node.childNodes[i], tabIndex);        
}

//NOTE: When calling this method, pass in the active lookup panel as the initial node
DynamicsCommon.GetFirstFocusableElement = function(node)
{
    if (!node)
        return null;
        
    if (DynamicsCommon.CanReceiveFocus(node.nodeName))
        return node;

    for (var i=0; i < node.childNodes.length; i++)
    {
        var result = DynamicsCommon.GetFirstFocusableElement(node.childNodes[i]);
        if (result)
            return result;
    }
   
    return null;
}

//Sets focus to the given element.
//If it is a textbox ro textarea & you set moveToEnd = true, the cursor will be placed at the end of the string.
DynamicsCommon.SetFocusToTextbox = function(elem, moveToEnd)
{
    if (DynamicsCommon.IsNull(elem))
        return;
        
    if (elem.style.display == 'none' || elem.style.visibility == 'hidden' || elem.disabled)
        return;
        
    try
    {
        if (elem.createTextRange && ((elem.nodeName=='INPUT' && (elem.type == 'text' || elem.type == 'password' || elem.type == 'file')) || elem.nodeName == 'TEXTAREA'))
        {
            //The way we put focus on a textbox in IE
            var r = (elem.createTextRange());
            if (moveToEnd)
                r.moveStart('character', (elem.value.length));
            r.collapse();
            r.select();    
        }
        else		    
            elem.focus();  
    }
    catch (err) {}
}