﻿/*****************************************************************************************
   
Copyright (c) Microsoft Corporation. All rights reserved.

****************************************************************************************/

//  --------------------------------------------------------------------------------------
//  LiveClipboardHelpers.js
//
//  NOTE: You MUST include MiscellaneousHelpers.js before including this file
//  --------------------------------------------------------------------------------------

var g_LiveClipboardNamespaceURI = "http://www.microsoft.com/schemas/liveclipboard";

var g_LiveClipboardTextID = "urn:microsoft.com:csa.liveclipboard.text";
var g_ElementToGiveFocusBackTo = null;

var g_CharCount = 0;

function InitializeLiveClipboardStyles()
    {
    if (document.createStyleSheet)
        {
        //  IE method
        var ss = document.createStyleSheet();
        ss.addRule(".webClipControl", "background: url('LiveClipboard/liveClipIcon.png') left top no-repeat;position: static;width:32px;height:32px;z-index:99;");
        ss.addRule(".CopyPasteInput", "position: relative;overflow:hidden;width:32px;height:32px;padding:0px;z-index:100;cursor:pointer;filter:alpha(opacity=0);KHTMLOpacity:0;MozOpacity:0;opacity:0;");
        }
    else
        {
        var LiveClipboardStyleText = ".webClipControl {background: url('LiveClipboard/liveClipIcon.png') left top no-repeat;position: static;width:32px;height:32px;z-index:99;}\n"
        LiveClipboardStyleText += ".CopyPasteInput {position: relative;overflow:hidden;width:32px;height:32px;padding:0px;z-index:100;cursor:pointer;filter:alpha(opacity=0);KHTMLOpacity:0;MozOpacity:0;opacity:0;}\n";

        var LiveClipboardStyleElement = document.createElement("style");
        LiveClipboardStyleElement.setAttribute("type", "text/css");

        //  W3C method
        var LiveClipboardStyleTextNode = document.createTextNode(LiveClipboardStyleText);
        LiveClipboardStyleElement.appendChild(LiveClipboardStyleTextNode);
        document.getElementsByTagName("head")[0].appendChild(LiveClipboardStyleElement);
        }
    }

function InsertLiveClipboardIcon(i_ParentElement, i_AllowCopy, i_AllowPaste)
    {
    if ((i_AllowCopy != true) && (i_AllowPaste != true))
        throw "Must specify true for allowing copy and/or paste";
        
	var TextAreaElement = document.createElement("textarea");
	TextAreaElement.rows = "1";
	TextAreaElement.className = "CopyPasteInput";
	TextAreaElement.setAttribute("autocomplete", "off");  
	TextAreaElement.value = "";
	TextAreaElement.AllowCopy = i_AllowCopy;
	TextAreaElement.AllowPaste = i_AllowPaste;
	
	if (i_AllowCopy && i_AllowPaste)
	    {
    	TextAreaElement.alt = "Right-click to copy/paste this content";
    	TextAreaElement.title = "Right-click to copy/paste this content";
        }
    else if (i_AllowCopy)
        {
	    TextAreaElement.alt = "Right-click to copy this content";
	    TextAreaElement.title = "Right-click to copy this content";
	    }
	else if (i_AllowPaste)
	    {
        TextAreaElement.alt = "Right-click to paste content";
        TextAreaElement.title = "Right-click to paste content";
        }

    if (i_AllowCopy && !i_AllowPaste)
        TextAreaElement.readOnly = true;
            
    if (i_AllowPaste)
        {
        if (IsFirefox())
            {
            g_CharCount = TextAreaElement.value.length;

	        AttachEvent
	            (
	            TextAreaElement,
	            "input", 
	            OnLiveClipboardInput
	            );
	        }
        else
            {
	        AttachEvent
	            (
	            TextAreaElement,
	            "paste", 
	            OnLiveClipboardPaste
	            );
	        }
	    }
        
	AttachEvent
	    (
	    TextAreaElement,
	    "contextmenu", 
	    OnLiveClipboardContextMenu
	    );

	var LiveClipboardElement = document.createElement("span");
	LiveClipboardElement.className = "webClipControl";
	LiveClipboardElement.appendChild(TextAreaElement);
	
	AttachEvent
	    (
	    LiveClipboardElement,
	    "mousedown", 
	    OnLiveClipboardMouseDown
	    );

	AttachEvent
	    (
	    LiveClipboardElement,
	    "mouseup", 
	    OnLiveClipboardMouseUp
	    );

	i_ParentElement.appendChild(LiveClipboardElement);
	}

function OnLiveClipboardMouseDown(i_Event)
    {
    if (i_Event == null)
        i_Event = window.event;

    var TextAreaElement = GetSourceElementFromEvent(i_Event);
    if (TextAreaElement.className != "CopyPasteInput")
        throw "OnLiveClipboardMouseDown - Unexpected element!";

    if (i_Event.button == 2)
        int_OnLiveClipboardCopy(TextAreaElement);

    StopEventBubbling(i_Event);
    }

function OnLiveClipboardMouseUp(i_Event)
    {
    if (i_Event == null)
        i_Event = window.event;

    var TextAreaElement = GetSourceElementFromEvent(i_Event);
    if (TextAreaElement.className != "CopyPasteInput")
        throw "OnLiveClipboardMouseUp - Unexpected element!";

    if (i_Event.button != 2)
        TextAreaElement.blur();

    StopEventBubbling(i_Event);
    }

function OnLiveClipboardInput(i_Event)
    {
    var TextAreaElement = GetSourceElementFromEvent(i_Event);
    if (TextAreaElement.className != "CopyPasteInput")
        throw "OnLiveClipboardPaste - Unexpected element!";

    //  Simulate paste detection by seeing if more than one
    //  character was added since we last checked
    var NewCharCount = TextAreaElement.value.length;
    var OldCharCount = g_CharCount;
    g_CharCount = NewCharCount;
    
    if (NewCharCount - OldCharCount > 1)
    	{       
        TextAreaElement.Operation = "paste";        
        setTimeout(function(){OnLiveClipboardPasteDelay(TextAreaElement);}, 1);
	    }
    }
    
function OnLiveClipboardPaste(i_Event)
    {
    var TextAreaElement = GetSourceElementFromEvent(i_Event);
    if (TextAreaElement.className != "CopyPasteInput")
        throw "OnLiveClipboardPaste - Unexpected element!";

    TextAreaElement.Operation = "paste";        
    setTimeout(function(){OnLiveClipboardPasteDelay(TextAreaElement);}, 1);
    }
    
function OnLiveClipboardPasteDelay(i_TextAreaElement)
    {
    int_OnLiveClipboardPaste(i_TextAreaElement);
    }

function int_OnLiveClipboardCopy(i_TextAreaElement)
    {
    i_TextAreaElement.value = "";

    if (i_TextAreaElement.AllowCopy == true)
        {        
        try
            {
            var LiveClipboardData = OnGetLiveClipboardData(i_TextAreaElement.parentNode.parentNode);
            if (LiveClipboardData == null)
                return;
                
            i_TextAreaElement.value = LiveClipboardData;
            i_TextAreaElement.select();
            }
        finally
            {
            if ((i_TextAreaElement.value == "") && (i_TextAreaElement.AllowPaste != true))
            alert ("Must implement OnLiveClipboardGetData and return valid Live Clipboard data!");
            }
        }
    }
    
function int_OnLiveClipboardPaste(i_TextAreaElement)
    {
    if ((i_TextAreaElement.value == null) || (i_TextAreaElement.value == ""))
        return;
        
    try
        {
        var DOMDocument = ParseXML
            (
            i_TextAreaElement.value, 
            false
            );
            
        if (DOMDocument == null)
            throw "No Live Clipboard data to paste!";

        var LiveClipboard = new LiveClipboardClass(DOMDocument);

        i_TextAreaElement.value = "";

        try
            {
            OnHandleLiveClipboardData(LiveClipboard,i_TextAreaElement.parentNode.parentNode);
            }
        catch (e)
            {
            throw "Must implement OnHandleLiveClipboardData and handle valid Live Clipboard data!";
            }
        }
    catch (e)
        {
        if (e.message != null)
            alert(e.message);
        else
            alert(e);
        }
    finally
        {
        i_TextAreaElement.blur();
        if (g_ElementToGiveFocusBackTo != null)
            {
            g_ElementToGiveFocusBackTo.focus();
            g_ElementToGiveFocusBackTo = null;
            }
        }
    }
    
function OnLiveClipboardContextMenu(i_Event)
    {
    if (i_Event == null)
        i_Event = window.event;

    //StopEventBubbling(i_Event);
    }

function InitiateKeyboardCopyToLiveClipboard(i_ParentElement, i_ElementToGiveFocusBackTo)
    {
    var TextAreaElement = GetTextAreaElementFromParentElement(i_ParentElement);
    if (TextAreaElement == null)
        throw "Invalid parent element!";

    int_OnLiveClipboardCopy(TextAreaElement)        

	AttachEvent
	    (
	    TextAreaElement,
	    "keyup", 
	    OnTextAreaElementKeyUp
	    );

    g_ElementToGiveFocusBackTo = i_ElementToGiveFocusBackTo;
            
    TextAreaElement.select();
    TextAreaElement.focus();
    TextAreaElement.Operation = "copy";
    }

function InitiateKeyboardPasteFromLiveClipboard(i_ParentElement, i_ElementToGiveFocusBackTo)
    {
    var TextAreaElement = GetTextAreaElementFromParentElement(i_ParentElement);
    if (TextAreaElement == null)
        throw "Invalid parent element!";
    
	AttachEvent
	    (
	    TextAreaElement,
	    "keyup", 
	    OnTextAreaElementKeyUp
	    );

    g_ElementToGiveFocusBackTo = i_ElementToGiveFocusBackTo;
            
    TextAreaElement.select();
    TextAreaElement.focus();
    TextAreaElement.Operation = "paste";
    }

function GetTextAreaElementFromParentElement(i_ParentElement)
    {
    var TextAreaElement = null;

    for (var Index = 0; Index < i_ParentElement.childNodes.length; ++Index)
        {
        if (i_ParentElement.childNodes[Index].className == "webClipControl")
            {
            if (i_ParentElement.childNodes[Index].childNodes[0].className == "CopyPasteInput")
                {
                TextAreaElement = i_ParentElement.childNodes[Index].childNodes[0];
                break;
                }
            }
        }

    return TextAreaElement;    
    }

function OnTextAreaElementKeyUp(i_Event)
    {
    var TextAreaElement = GetSourceElementFromEvent(i_Event);
    if (TextAreaElement.className != "CopyPasteInput")
        throw "OnTextAreaElementKeyUp - Unexpected element!";

    DetachEvent
        (
        TextAreaElement,
        "keyup", 
        OnTextAreaElementKeyUp
        );

    TextAreaElement.blur();

    if (g_ElementToGiveFocusBackTo != null)
        {
        g_ElementToGiveFocusBackTo.focus();
        g_ElementToGiveFocusBackTo = null;
        }
    
    if (TextAreaElement.Operation == "paste")
        OnLiveClipboardPaste(i_Event);
        
    TextAreaElement.Operation = null;
    }

function LiveClipboardClass(i_LiveClipboardXmlDocument)
    {
    this.m_XmlElement = i_LiveClipboardXmlDocument.documentElement;
    
    this.m_Version = this.m_XmlElement.getAttribute("version");
    if (this.m_Version != "0.93")
        throw "Incompatible version!";

    this.m_Source = this.m_XmlElement.getAttribute("source");
    this.m_Description = this.m_XmlElement.getAttribute("description");

    var Namespaces = new Array();
    Namespaces[0] = "xmlns:lc='" + g_LiveClipboardNamespaceURI + "'";
    
    //  -----------------------------------------------------------------------------
    //  NOTE - This is NOT a complete implementation for Live Clipboard
    //         because we only handle <lc:data>, <lc:presentations> and
    //         <lc:schemas> sections

        var DataSectionElement = SelectSingleNode
            (
            this.m_XmlElement,
            "lc:data",
            Namespaces,
            false
            );
        
        if (DataSectionElement != null)
            this.m_DataSection = new LCDataSectionClass(this, DataSectionElement);

        var SchemasSectionElement = SelectSingleNode
            (
            this.m_XmlElement,
            "lc:schemas",
            Namespaces,
            false
            );

        if (SchemasSectionElement != null)
            this.m_SchemasSection = new LCSchemasSectionClass(this, SchemasSectionElement);

        var PresentationsSectionElement = SelectSingleNode
            (
            this.m_XmlElement,
            "lc:presentations",
            Namespaces,
            false
            );

        if (PresentationsSectionElement != null)
            this.m_PresentationsSection = new LCPresentationsSectionClass(this, PresentationsSectionElement);
        
    //  -----------------------------------------------------------------------------
    }

function LCDataSectionClass(i_LiveClipboard, i_LCDataSectionXmlElement)
    {
    this.m_LiveClipboard = i_LiveClipboard;
    this.m_XmlElement = i_LCDataSectionXmlElement;
    
    this.m_Formats = new Array();
    
    var Namespaces = new Array();
    Namespaces[0] = "xmlns:lc='" + g_LiveClipboardNamespaceURI + "'";
    
    var FormatXmlElements = SelectNodes
        (
        this.m_XmlElement,
        "lc:format",
        Namespaces,
        false
        );
    
    for (var Index = 0; Index < FormatXmlElements.length; ++Index)
        {
        var FormatXmlElement = FormatXmlElements[Index];
        var Format = new LCDataFormatClass(this, FormatXmlElement);
        
        this.m_Formats.push(Format);
        }
        
    if (this.m_Formats.length == 0)
        throw "No data formats found!";
    }

function LCDataFormatClass(i_LCDataSection, i_LCFormatXmlElement)
    {
    this.m_DataSection = i_LCDataSection;
    this.m_XmlElement = i_LCFormatXmlElement;

    this.m_ContentType = this.m_XmlElement.getAttribute("contenttype");
    this.m_Type = this.m_XmlElement.getAttribute("type");
    this.m_Encoding = this.m_XmlElement.getAttribute("encoding");
    this.m_SchemaID = this.m_XmlElement.getAttribute("schemaid");

    this.m_Items = new Array();
    
    var Namespaces = new Array();
    Namespaces[0] = "xmlns:lc='" + g_LiveClipboardNamespaceURI + "'";
    
    var ItemXmlElements = SelectNodes
        (
        this.m_XmlElement,
        "lc:item",
        Namespaces,
        false
        );
    
    for (var Index = 0; Index < ItemXmlElements.length; ++Index)
        {
        var ItemXmlElement = ItemXmlElements[Index];
        var Item = new LCItemClass(this, ItemXmlElement);
        
        this.m_Items.push(Item);
        }
        
    if (this.m_Items.length == 0)
        throw "No items found!";
    }

function LCItemClass(i_LCFormat, i_LCItemXmlElement)
    {
    this.m_Format = i_LCFormat;
    this.m_XmlElement = i_LCItemXmlElement;
    
    this.m_Description = this.m_XmlElement.getAttribute("description");
    this.m_Ref = this.m_XmlElement.getAttribute("ref");
    }

function LCSchemasSectionClass(i_LiveClipboard, i_LCSchemasSectionXmlElement)
    {
    this.m_LiveClipboard = i_LiveClipboard;
    this.m_XmlElement = i_LCSchemasSectionXmlElement;
    
    this.m_Schemas = new Array();
    
    var Namespaces = new Array();
    Namespaces[0] = "xmlns:lc='" + g_LiveClipboardNamespaceURI + "'";
    
    var SchemaXmlElements = SelectNodes
        (
        this.m_XmlElement,
        "lc:schema",
        Namespaces,
        false
        );

    for (var Index = 0; Index < SchemaXmlElements.length; ++Index)
        {
        var SchemaXmlElement = SchemaXmlElements[Index];
        var Schema = new LCSchemaClass(this, SchemaXmlElement);
        
        this.m_Schemas.push(Schema);
        }
        
    if (this.m_Schemas.length == 0)
        throw "No schemas found!";
    }

function LCSchemaClass(i_SchemasSection, i_LCSchemaXmlElement)
    {
    this.m_SchemaSection = i_SchemasSection;
    this.m_XmlElement = i_LCSchemaXmlElement;
    
    this.m_ID = this.m_XmlElement.getAttribute("id");
    this.m_Type = this.m_XmlElement.getAttribute("type");
    this.m_Ref = this.m_XmlElement.getAttribute("ref");
    }

function LCPresentationsSectionClass(i_LiveClipboard, i_LCPresentationsSectionXmlElement)
    {
    this.m_LiveClipboard = i_LiveClipboard;
    this.m_XmlElement = i_LCPresentationsSectionXmlElement;
    
    this.m_Formats = new Array();
    
    var Namespaces = new Array();
    Namespaces[0] = "xmlns:lc='" + g_LiveClipboardNamespaceURI + "'";
    
    var FormatXmlElements = SelectNodes
        (
        this.m_XmlElement,
        "lc:format",
        Namespaces,
        false
        );

    for (var Index = 0; Index < FormatXmlElements.length; ++Index)
        {
        var FormatXmlElement = FormatXmlElements[Index];
        var Format = new LCPresentationFormatClass(this, FormatXmlElement);
        
        this.m_Formats.push(Format);
        }
        
    if (this.m_Formats.length == 0)
        throw "No presentation formats found!";
    }

function LCPresentationFormatClass(i_LCPresentationsSection, i_LCFormatXmlElement)
    {
    this.m_PresentationsSection = i_LCPresentationsSection;
    this.m_XmlElement = i_LCFormatXmlElement;

    this.m_ContentType = this.m_XmlElement.getAttribute("contenttype");
    this.m_Type = this.m_XmlElement.getAttribute("type");
    this.m_Encoding = this.m_XmlElement.getAttribute("encoding");
    this.m_Description = this.m_XmlElement.getAttribute("description");
    this.m_Ref = this.m_XmlElement.getAttribute("ref");
    }
