/*
 Copyright 2013 Adobe Systems Incorporated.  All rights reserved.

Purpose-
This file has the implementation of Image Editing functionality in Live Edit view

AdobePatentID="4273US01"
*/

/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, maxerr: 50 */
/*global $, DwImageHud, AuxiliaryExtensionObject, liveViewObject, dwObject, liveExtensionsConfigPath,TAGS, dwExtensionController, KEYCODES,DWConstants, DW_EXTENSION_EVENT, DWLE_DIMENSIONS */

var CONSTANTS = {
    ExtensionID: "dwImageHud",
    none: "none",
    undef: "undefined",
    FILTER: "*.png|*.gif|*.jpg|*.jpeg|*.psd",
    ClipToShapeRadioGroup: "CTSRadioGroup",
    ImgCircleBootstrapClass: "img-circle",
    ImgRoundedBootstrapClass: "img-rounded",
    ImgThumbnailBootstrapClass: "img-thumbnail",
    ImgResponsiveBootstrapClass: "img-responsive",
    HTMLGroup: "HTML",
    BootstrapGroup: "BOOTSTRAP",
    ColorHudGrey: "#AAAAAA",
    ColorHudBlue: "#2D8CEB",
    DefaultImageDimension: 32,
    DWDiv: 'dw-div',
    ClassSeparator: '.',
    DefaultArrowPositon: 20,
    ImgDimensionThreshold: 1.5
};

var DWLE_IMG_IDS = {
    src: "dwLeImgSrc",
    imgSrc: "dwLeImgSrcBtn",
    link: "dwLeImgLink",
    imgLink: "dwLeImgLinkBtn",
    alt: "dwLeImgAlt",
    target: "dwLeImgTarget",
    width: "dwLeImgWidth",
    height: "dwLeImgHeight",
    hudEntryID: "dwLeImgHudEntry",
    clipToShape: "dwLeClipToShape",
    clipToShapeCircle: "dwLeCircleBtn",
    clipToShapeRounded: "dwLeRoundedBtn",
    clipToShapeThumbnail: "dwLeThumbnailBtn",
    imgResponsive: "dwLeResponsive",
    aspectRatio: "dwLeImgAspectRatio",
    targetDiv: "dwLeImgTargetDiv"
};

var DWLE_IMG_CLASS = {
    Seperator: " ",
    ImgHudEntry: "dw_imgPropHud",
    ImgSelection: "dw_imgSelection",
    ImgInput: "dw_liveedit_HTMLPI_inputClass",
    ImgInputWandH: "dw_liveedit_HTMLPI_input_Width_Height",
    ImgLabel: "dw_liveedit_HTMLPI_labelClass",
    ImgLabelHeight: "dw_liveedit_HTMLPI_labelForHeight",
    ImgHudGroup: "dw_liveedit_HTMLPI_group",
    ImgHudRow: "dw_liveedit_HTMLPI_row",
    ImgHudSubRow: "dw_liveedit_HTMLPI_subrow",
    ImgBtnClass: "dw_liveedit_HTMLPI_inputbtnClass",
    ImgContainer: "dw_liveedit_HTMLPIWrapper",
    ImgContainerRight: "dw_liveedit_HTMLPIWrapperRight",
    ImgContainerLeft: "dw_liveedit_HTMLPIWrapperLeft",
    ImgContainerTop: "dw_liveedit_HTMLPIWrapperTop",
    ImgContainerBottom: "dw_liveedit_HTMLPIWrapperBottom",
    ImgContainerGreyed: "dw_liveedit_grey_border",
    NonEditable: "dw_liveedit_HTMLPINonEditable",
    ImgDropDownNone: "dw_liveedit_HTMLPI_donotShow",
    ImgDropDown: "dw_liveedit_HTMLPI_dropdownClass",
    LesserTopMargin: "dwLeLessTopMargin",
    Unselectable: "dw_liveedit_HTMLPI_unselectable",
    ClipToShapeDiv: "dw_liveedit_HTMLPI_clipToShape",
    RadioLabel: "dw_livedit_HTMLPI_radioLabel",
    ImgCheckboxClass: "dw_liveedit_HTMLPI_inputcheckboxClass",
    ImgClipToShapeLabel: "dw_liveedit_HTMLPI_ClipToShapeLabel",
    ImgGroupHeaderLabel: "dw_liveedit_HTMLPI_GroupHeaderLabel",
    ImgWHGroup: "dw_liveedit_HTMLPI_WHGroup",
    ImgWidthandHeightAndAspectRatio: "dw_liveedit_HTMLPI_WH_Aspect",
    ImgAspectRatio: "dw_liveedit_HTMLPI_AspectRatio",
    ImgAspectRatioSize: "dw_liveedit_HTMLPI_AspectRatioImageSize",
    ImgAspectRatioTopLine: "dw_liveedit_HTMLPI_AspectRatioTopLine",
    ImgAspectRatioBottomLine: "dw_liveedit_HTMLPI_AspectRatioBottomLine",
    ImgSelected: "dw_liveedit_HMLPI_ImageSelected",
    ClipToShapeRadioImageButton: "dw_liveedit_HTMLPI_clipToShape_InputRadioBtn",
    ClipToShapeRadioImageButtonOutlineNone: "dw_liveedit_HTMLPI_ClipToShape_ClickOutlineNone",
    InputTypeNoUndo: "CantHandleUndo",
    BeforePseudoSelector: ":before",
    AfterPseudoSelector: ":after",
    AspectRatioLocked : "dw_liveeditLink",
    AspectRatioUnLocked : "dw_liveeditunlink",
    ClipToShapeImgWidth : "dw_liveeditShapeDiv",
    clipToShapeCircle_S: "dw_liveeditShapeCircle_s",
    clipToShapeRounded_S : "dw_liveeditShapeRounded_s",
    clipToShapeThumb_S : "dw_liveeditShapeThumb_s"
};

var DWLE_IMAGEHUD_HEADLIGHTS = {
    ELV_IH: "ELV IH",
    DW_SHORTCUT: "DWShortcuts",
    OTH_ELV: "OTH ELV",
    RWD: "RWD",
    RWD_BOOTSTRAP: "RWD_Bootstrap",
    THUMBNAIL: "Image_HUD_Clip_Thumbnail",
    CIRCLE: "Image_HUD_Clip_Circle",
    ROUNDED: "Image_HUD_Clip_Rounded ",
    IMAGE_RESPONSIVE: "Image_HUD_MakeResponsive",
    SRC: "IH Src",
    ALT: "IH Alt",
    LINK: "IH Link",
    TARGET: "IH Target",
    WIDTH: "IH Width",
    HEIGHT: "IH Height",
    LAUNCH: "IH Launch",
    BROWSE_SRC: "IH BrowseFile Src",
    BROWSE_LINK: "IH BrowseFile Link",
    CLOSE_SHORTCUT: "IH Closed via Shortcut",
    CLOSE_CLICK: "IH Closed via Click"
};

DwImageHud.prototype = new AuxiliaryExtensionObject();
DwImageHud.prototype.constructor = DwImageHud;
DwImageHud.prototype.baseClass = AuxiliaryExtensionObject.prototype.constructor;

function DwImageHud() {
    'use strict';
    
    //initialize variables

    this.callback_counter = 0; // this is to assign ID's for newly created nodes / modified nodes
    this.callback_map = {}; // map holds the mapping between temporary id's and nodes
    
    dwExtensionController.addListener(DW_EXTENSION_EVENT.ELEMENT_DIMENSION_CHANGED, this.repositionHUD, this);
    // before we disable the extensions we should be committing the HUDS
	dwExtensionController.addListener(parent.DW_EVENTS.DisableExtensions, this.commit, this);
}

DwImageHud.prototype.getHudTag = function () {
    'use strict';
    return "img";
};

DwImageHud.prototype.fileSave = function () {
    'use strict';
    if (this.getVisibility()) {
        this.fileSavePending = 1;
        this.commit();
    }
};

DwImageHud.prototype.fileSaveAs = function () {
    'use strict';
    if (this.getVisibility()) {
        this.fileSavePending = 0;
        this.commit();
    }
};

/**
 * @private createLabel
 * Create the label
 * @Param toDiv     :to which this created label should be made as child 
 * @Param labelText :actual label value
 * @Param labelClass:css for label
 * @Param forInputId:inputID corresponding to the label
 */
DwImageHud.prototype.createLabel = function (toDiv, labelText, labelClass, forInputId, tooltip) {
    'use strict';
    var labelElement = document.createElement("label");
    labelElement.innerHTML = labelText;
    labelElement.title = tooltip || "";
    labelElement.htmlFor = forInputId;
    labelClass.push(DWLE_IMG_CLASS.Reset);
    labelElement.classList.add.apply(labelElement.classList, labelClass);
    toDiv.appendChild(labelElement);
};
/**
 * @private createImgButton
 * Create input component with given values 
 * @Param toDiv     : to which this created label should be made as child
 * @Param idOfInput : id to be assigned
 * @Param inputClass: class to be applied
 * @Param placeholderText: placeholderText
 * @Param readOnlyFlag : whether the element is readOnly or writable
 * @Param addtabIndex : enable tabindex
 * @Return an InputElement created with given arguments as values
 * @Note DWLE_TEXT_CLASS.Reset 
 *         Needs to be applied on all text HUD elements
 *         In order to make sure that we are not hit by globally applied styles
 */
DwImageHud.prototype.createImgButton = function (toDiv, idOfInput, inputClass, readOnlyFlag, addtabIndex) {
    'use strict';
    var inputElement = document.createElement("img");
    inputElement.id = idOfInput;
    inputElement.classList.add.apply(inputElement.classList, inputClass);
    if (addtabIndex) {
        inputElement.tabIndex = "0";
    }
    if (readOnlyFlag === true) {
        inputElement.readonly = 'true';
    }
    //this is done to make sure that drag is differentiated from text selection inside input box    
    inputElement.onmousedown = function (e) {
        e.stopPropagation();
    };
    
    toDiv.appendChild(inputElement);
    inputElement.style.cursor = "pointer";
    return inputElement;
};
/**
 * @private createInput
 * Create input component with given values 
 * @Param toDiv     : to which this created label should be made as child
 * @Param ofType    : file/text/image
 * @Param idOfInput : id to be assigned
 * @Param inputClass: class to be applied
 * @Param placeholderText: placeholderText
 * @Param readOnlyFlag : whether the element is readOnly or writable
 * @Return an InputElement created with given arguments as values
 * @Note DWLE_IMG_CLASS.Reset 
 *         Needs to be applied on all image HUD elements 
 *          In order to make sure that we are not hit by globally applied styles
 */
DwImageHud.prototype.createInput = function (toDiv, ofType, idOfInput, inputClass, placeHolderText, readOnlyFlag, attr, isParent) {
    'use strict';
    var inputElement = document.createElement('input', 'coral-textfield');
    inputElement.id = idOfInput;
    inputElement.placeholder = placeHolderText;
    inputElement.setAttribute("type", ofType);
    inputElement.classList.add.apply(inputElement.classList, inputClass);
    if (readOnlyFlag === true) {
        inputElement.readOnly = true;
    }
    //this is done to make sure that drag is differentiated from text selection inside input box
    inputElement.onmousedown = function (e) {
        e.stopPropagation();
    };
    toDiv.appendChild(inputElement);
    
    var self = this;
    inputElement.onfocus = function () {
        if (attr) {
            var element = self.m_currentSelectedElement;
            if (element) {
                if (isParent) {
                    element = element.parent;
                }
                if (element && (element.getAttribute(attr) || inputElement.value) && (element.getAttribute(attr) !== inputElement.value)) {
                    self.commit();
                }
            }
        }
    };
     
    return inputElement;
};

DwImageHud.prototype.createCheckBox = function (toDiv, idOfInput, inputClass, placeHolderText, readOnlyFlag, attr, isParent) {
    'use strict';
    var inputElement = document.createElement('coral-checkbox');
    inputElement.id = idOfInput;
    inputElement.label.innerHTML = placeHolderText;
    inputElement.classList.add.apply(inputElement.classList, inputClass);
    if (readOnlyFlag === true) {
        inputElement.is_disabled = true;
    }
    //this is done to make sure that drag is differentiated from text selection inside input box
    inputElement.onmousedown = function (e) {
        e.stopPropagation();
    };
    toDiv.appendChild(inputElement);
    return inputElement;
};

DwImageHud.prototype.addItem = function (component, valueId, innerHTMLText, is_disabled, is_selected) {
    'use strict';
    var item = component.items.add({
        value : valueId,
        content : {
            innerHTML : innerHTMLText,
            innerText : innerHTMLText
        },
        disabled : is_disabled,
        selected : is_selected
    });

    return item;
};

/**
 * @private createDropDown
 * create DropDown with given values
 * @Param toDiv     : to which this created label should be made as child
 * @Param idApplied : id to be assigned
 * @Param classToBeApplied: class to be applied
 * @Param placeholderText: placeholderText
 * @Param values : values to be populated in dropdown
 * @Return an Dropdown Element created with given arguments as values
 */
DwImageHud.prototype.createDropDown = function (toDiv, idApplied, classToBeApplied, values) {
    'use strict';
    var selectElement = document.createElement("coral-select");
    selectElement.id = idApplied;
    selectElement.classList.add.apply(selectElement.classList, classToBeApplied);
    selectElement.setAttribute("disabled", 'true');
    var index, opt;
    
    this.addItem(selectElement, "none", "none", false, true);
    
    for (index = 0; index < values.length; ++index) {
        opt = this.addItem(selectElement, values[index], values[index], false, false);
    }
    toDiv.appendChild(selectElement);
    return selectElement;
};

/**
 * @private createGroupContainer
 * create a DW-DIV for a group with given class applied
 * @Param classToBeApplied:class to be applied on dw-div
 * @Return return dw-div with the class applied
 */
DwImageHud.prototype.createGroupContainer = function (classToBeApplied, groupLabel) {
    'use strict';
    var newContainerDiv = this.createContainer(classToBeApplied);
    var labelDiv = this.createContainer([DWLE_IMG_CLASS.ImgHudRow]);
    var labelClass = [DWLE_IMG_CLASS.ImgLabel, DWLE_IMG_CLASS.ImgGroupHeaderLabel];
    this.createLabel(labelDiv, groupLabel, labelClass);
    newContainerDiv.appendChild(labelDiv);
    return newContainerDiv;
};

/**
 * @private createContainer
 * create a DW-DIV with given class applied
 * @Param classToBeApplied:class to be applied on dw-div
 * @Return return dw-div with the class applied
 */
DwImageHud.prototype.createContainer = function (classToBeApplied) {
    'use strict';
    var newContainerDiv = document.createElement(TAGS.DwDiv);
    newContainerDiv.classList.add.apply(newContainerDiv.classList, classToBeApplied);
    return newContainerDiv;
};

/**
 * @private updateHudFields
 * Update HUD Fields with respect to the current element under edit
 * @Param elem : Current Element Under Edit.
*/
DwImageHud.prototype.updateHudFields = function (elem) {
    'use strict';
    if (!elem) {
        return;
    }
    if (elem.src) {
        var sourceElement = document.getElementById(DWLE_IMG_IDS.src);
        sourceElement.value = elem.getAttribute("src");
        sourceElement.title = elem.getAttribute("src");
    }
    if (elem.alt) {
        var altElement = document.getElementById(DWLE_IMG_IDS.alt);
        altElement.value = elem.alt;
        altElement.title = elem.alt;
    }
    // for Link tag and target
    var parent = elem.parentNode;
    var targetElement = document.getElementById(DWLE_IMG_IDS.target);
    if (parent && parent.tagName === "A") {
        var href = parent.getAttribute("href");
        if (href !== null) {

            var linkElement = document.getElementById(DWLE_IMG_IDS.link);
            linkElement.value = href;
            linkElement.title = href;
            var target = parent.getAttribute("target");

            if (this.getEditable() === true) {
                targetElement.removeAttribute("disabled");
                targetElement.classList.remove(DWLE_IMG_CLASS.ImgDropDownNone);
            }
            if (target !== null) {

                targetElement.value = target;
            } else {

                targetElement.value = "none";
            }
            document.getElementById(DWLE_IMG_IDS.targetDiv).style.display = 'block';
        } else {
            document.getElementById(DWLE_IMG_IDS.targetDiv).style.display = 'none';
            targetElement.setAttribute("disabled", 'true');
            targetElement.classList.add.apply(targetElement.classList, [DWLE_IMG_CLASS.ImgDropDown, DWLE_IMG_CLASS.ImgDropDownNone]);
            targetElement.value = "none";
        }
    } else {
        targetElement.value = "none";
        document.getElementById(DWLE_IMG_IDS.targetDiv).style.display = 'none';
    }
    var heightOfElement = elem.getAttribute("height");
    if (heightOfElement) {
        var heightElement = document.getElementById(DWLE_IMG_IDS.height);
        heightElement.value = heightOfElement;
        heightElement.title = heightOfElement;
        //check if number value is greater than 0
        if (Number(heightOfElement) > 0) {
            this.imgAttrSize.height = Number(heightOfElement);
        }
    }
    var widhtOfElement = elem.getAttribute("width");
    if (widhtOfElement) {
        var widthElement = document.getElementById(DWLE_IMG_IDS.width);
        widthElement.value = widhtOfElement;
        widthElement.title = widhtOfElement;
        //check if number value is greater than 0
        if (Number(widhtOfElement) > 0) {
            this.imgAttrSize.width = Number(widhtOfElement);
        }
    }
    //update the aspect ratio state after width and height has been fetched from attribute value
    var aspectRatioElem = document.getElementById(DWLE_IMG_IDS.aspectRatio);
    if (this.imgAttrSize.width !== -1 && this.imgAttrSize.height !== -1) {
        //calculate width and height percent wrt to original size
        var widthPercent = Math.round(((this.imgAttrSize.width * 100) / this.imageOrigSize.width));
        var heightPercent = Math.round(((this.imgAttrSize.height * 100) / this.imageOrigSize.height));
        if (widthPercent !== heightPercent) {
            this.imgAspectRatioLockOn = false;
            if (aspectRatioElem) {
                aspectRatioElem.parentElement.classList.remove(DWLE_IMG_CLASS.AspectRatioLocked);
                aspectRatioElem.parentElement.classList.add(DWLE_IMG_CLASS.AspectRatioUnLocked);
            }
        }
    } else if (this.imgAttrSize.width === -1 || this.imgAttrSize.height === -1) {
        this.imgAspectRatioLockOn = true;
        if (aspectRatioElem) {
            aspectRatioElem.parentElement.classList.add(DWLE_IMG_CLASS.AspectRatioLocked);
            aspectRatioElem.parentElement.classList.remove(DWLE_IMG_CLASS.AspectRatioUnLocked);
        }
    }
    
    this.updateBootstrapClassHudFields(elem);
};

/**
 * @private updateBootstrapClassHudFields
 * Update Bootstap HUD Fields with respect to the current element under edit
 * @Param elem : Current Element Under Edit.
*/
DwImageHud.prototype.updateBootstrapClassHudFields = function (elem) {
    'use strict';
    if (this.showBootstrapComponents) {
        if (!elem) {
            return;
        }
        //the first applied class in the class list is the one to be shown selected in Clip to shape category
        var i, clipToShapeRadioGroup = document.getElementsByName(CONSTANTS.ClipToShapeRadioGroup);
        var classValue = elem.getAttribute("class");
        if (classValue) {
            var indexOffirstClassInClassList = classValue.length;
            if (indexOffirstClassInClassList > 0) {
                var indexToSet = -1;
                for (i = 0; i < clipToShapeRadioGroup.length; ++i) {
                    
                    clipToShapeRadioGroup[i].classList.remove(DWLE_IMG_CLASS.ImgSelected);
                    clipToShapeRadioGroup[i].parentElement.classList.remove(clipToShapeRadioGroup[i].selectedclass);
                    if (elem.classList.contains(clipToShapeRadioGroup[i].value)) {
                        var indexInClasslist = classValue.indexOf(clipToShapeRadioGroup[i].value);
                        if (indexInClasslist !== -1 && indexInClasslist < indexOffirstClassInClassList) {
                            indexOffirstClassInClassList = indexInClasslist;
                            indexToSet = i;
                        }
                    }
                }
                if (indexToSet !== -1) {
                    clipToShapeRadioGroup[indexToSet].classList.add(DWLE_IMG_CLASS.ImgSelected);
                    clipToShapeRadioGroup[indexToSet].parentElement.classList.add(clipToShapeRadioGroup[indexToSet].selectedclass);
                }
            }
        } else { //no classvalue
            for (i = 0; i < clipToShapeRadioGroup.length; ++i) {
                clipToShapeRadioGroup[i].classList.remove(DWLE_IMG_CLASS.ImgSelected);
                clipToShapeRadioGroup[i].parentElement.classList.remove(clipToShapeRadioGroup[i].selectedclass);
            }
        }
        //responsive
        var responsiveElem = document.getElementById(DWLE_IMG_IDS.imgResponsive);
        if (responsiveElem) {
            if (elem.classList.contains(responsiveElem.value)) {
                responsiveElem.checked = true;
            } else {
                responsiveElem.checked = false;
            }
        }
    }
};


/**
* @private handleArrowKeys
* handles Right & Left Arrow keys for input elements
* If left arrow key is pressed and cursor is at the end of text, or
* Right arrow key is pressed and cursor is at the beginning of text,
* then nothing should occur
* @Param e:keypress event
* @Param elem:the HTML element on which key is pressed
*/
DwImageHud.prototype.handleArrowKeys = function (e, elem) {
    'use strict';
    if (e.keyCode === KEYCODES.Right) {
        var elemLen = elem.value.length;
        //check if cursor is at the end of elem text
        if (elem.selectionStart === elemLen) {
            e.stopPropagation();
            e.preventDefault();
        }
    } else if (e.keyCode ===  KEYCODES.Left) {
        //check if cursor is at the start of src text
        if (elem.selectionEnd === 0) {
            e.stopPropagation();
            e.preventDefault();
        }
    }
};

/**
* @private handleArrowKeysForButtons
* handles Right & Left Arrow keys for buttons
* If left or right arrow key is pressed, nothing should occur
* @Param e:keypress event
*/
DwImageHud.prototype.handleArrowKeysForButtons = function (e) {
    'use strict';
    if (e.keyCode === KEYCODES.Right || e.keyCode === KEYCODES.Left) {
        e.stopPropagation();
        e.preventDefault();
    }
};

DwImageHud.prototype.invokeSelectSoureDialogOnKeyUp = function (e) {
    'use strict';
    if (e.keyCode === KEYCODES.Space || e.keyCode === KEYCODES.Enter) {
        if (this.getVisibility()) {
            this.InputElementSrcBtn.blur();
            // this needs to be done because this element has focus after showing browse dialog and gets all key events(including enter)
            // and infinitely show up browse dialog
            this.launchFileSelection(this.locStrings.srcLabel);
            e.preventDefault();
            e.stopPropagation();
        }
    }
};

DwImageHud.prototype.invokeSelectLinkDialogOnKeyUp = function (e) {
    'use strict';
    if (e.keyCode === KEYCODES.Space || e.keyCode === KEYCODES.Enter) {

        if (this.getVisibility()) {
            this.InputElementLinkBtn.blur(); //same reason as link
            this.launchFileSelection(this.locStrings.linkLabel);
            e.preventDefault();
            e.stopPropagation();
        }
    }
};

DwImageHud.prototype.handleAspectRatioBtnOnKeyUp = function (e) {
    'use strict';
    if (e.keyCode === KEYCODES.Space) {
        if (this.getVisibility()) {
            this.handleAspectRatioBtnClick();
            this.focusHudField(DWLE_IMG_IDS.aspectRatio);
            e.preventDefault();
            e.stopPropagation();
        }
    }
};

DwImageHud.prototype.handleUpdateClipToShapeOnKeyUp = function (e) {
    'use strict';
    if (e.keyCode === KEYCODES.Space) {
        if (this.getVisibility()) {
            this.updateClipToShapeClass(e);
            e.preventDefault();
            e.stopPropagation();
        }
    }
};

DwImageHud.prototype.handleUpdateResponsiveClassOnKeyUp = function (e) {
    'use strict';
    if (e.keyCode === KEYCODES.Space) {
        if (this.getVisibility()) {
            e.target.checked = !e.target.checked;
            this.updateResponsiveClass(e.target.id);
            e.preventDefault();
            e.stopPropagation();
        }
    }
};

/**
 * @private populateContent
 * populate content inside the Image HUD container div.
 * this is responsible for both editable and non editable cases
 * creation of each of the component and also attaching event listeners and 
 * handling values should be done from this function
 */
DwImageHud.prototype.populateContent = function () {
    'use strict';
    this.showBootstrapComponents = liveViewObject.isBootstrapResponsiveFrameworkLoaded();
    
    //store the original size of the image
    this.imageOrigSize = {};
    if (this.m_currentSelectedElement.naturalWidth === 0) {
        this.imageOrigSize.width = CONSTANTS.DefaultImageDimension;
    } else {
        this.imageOrigSize.width = this.m_currentSelectedElement.naturalWidth;
    }
    if (this.m_currentSelectedElement.naturalHeight === 0) {
        this.imageOrigSize.height = CONSTANTS.DefaultImageDimension;
    } else {
        this.imageOrigSize.height = this.m_currentSelectedElement.naturalHeight;
    }
    
    //init the attr value of the image. we will update these when populating the attribute values
    this.imgAttrSize = {};
    this.imgAttrSize.width = -1;
    this.imgAttrSize.height = -1;
    
    this.imgAspectRatioLockOn = true;
    
    var container = this.getHudContainer();
    container.innerHTML = "";
    var containerClass = [DWLE_IMG_CLASS.ImgContainer, DWLE_IMG_CLASS.ImgContainerRight];
    /* create a container div to holds the content*/
    if (this.getEditable() === false) {
        containerClass.push(DWLE_IMG_CLASS.ImgContainerGreyed);
    }
    
    this.m_hudContentDiv = this.createContainer(containerClass);
    window.setCoralThemeForElement(this.m_hudContentDiv, this.m_currentTheme);
    AuxiliaryExtensionObject.prototype.EnableDragOnElement.call(this, this.m_hudContentDiv);

    //Create containers for each of the rows
    var imgHTMLContainerDiv = this.createGroupContainer([DWLE_IMG_CLASS.ImgHudGroup], CONSTANTS.HTMLGroup);
    var imgSrcDiv = this.createContainer([DWLE_IMG_CLASS.ImgHudRow]);
    var imgLinkDiv = this.createContainer([DWLE_IMG_CLASS.ImgHudRow]);
    var imgAltDiv = this.createContainer([DWLE_IMG_CLASS.ImgHudRow, DWLE_IMG_CLASS.LesserTopMargin]);
    var imgTargetDiv = this.createContainer([DWLE_IMG_CLASS.ImgHudRow, DWLE_IMG_CLASS.LesserTopMargin]);
    imgTargetDiv.id = DWLE_IMG_IDS.targetDiv;
    
    var containerForWHAspectRatio = this.createContainer([DWLE_IMG_CLASS.ImgHudRow, DWLE_IMG_CLASS.ImgWHGroup]);
    var containerForWandH = this.createContainer([DWLE_IMG_CLASS.ImgHudRow, DWLE_IMG_CLASS.ImgWidthandHeightAndAspectRatio]);
    var imgWidthDiv = this.createContainer([DWLE_IMG_CLASS.ImgAspectRatio]);
    var imgHeightDiv = this.createContainer([DWLE_IMG_CLASS.ImgAspectRatio]);
    var containerForAspectRatio = this.createContainer([DWLE_IMG_CLASS.ImgWidthandHeightAndAspectRatio]);

    var classToApplyOnInput = [DWLE_IMG_CLASS.ImgInput];
    var classToApplyOnInputForWH = [DWLE_IMG_CLASS.ImgInputWandH, DWLE_IMG_CLASS.ImgInput];
    var readOnly = false;
    if (this.getEditable() === false) {
        classToApplyOnInput.push(DWLE_IMG_CLASS.NonEditable);
        classToApplyOnInputForWH.push(DWLE_IMG_CLASS.NonEditable);
        readOnly = true;
    }

    //Image Source Div
    this.createLabel(imgSrcDiv, this.locStrings.srcLabel, [DWLE_IMG_CLASS.ImgLabel], DWLE_IMG_IDS.src, this.locStrings.srcTooltip);
    var inputElemSrc = this.createInput(imgSrcDiv, "text", DWLE_IMG_IDS.src, classToApplyOnInput, "", readOnly);
    var self = this;

    if (this.getEditable() === true) {
        // this is to achieve shift+tab should go back to last filed and should not navigate in the page.
        // it must be onkeydown as tab does not get captured using onkeyup
        inputElemSrc.onkeydown = function (e) {

            if (e.keyCode === KEYCODES.Tab) {
                if (e.shiftKey) {
                    //Focus previous input
                    if (this.showBootstrapComponents) {
                        this.focusHudField(DWLE_IMG_IDS.imgResponsive);
                        e.stopPropagation();
                    } else {
                        if (document.getElementById(DWLE_IMG_IDS.targetDiv).style.display !== 'none') {
                            this.focusHudField(DWLE_IMG_IDS.target);
                        } else {
                            this.focusHudField(DWLE_IMG_IDS.link);
                        }
                    }
                    e.preventDefault();
                }
                this.updateSrc(true);
                e.stopPropagation();
            } else if (e.keyCode === KEYCODES.Enter) {
                this.updateSrc(true);
                e.stopPropagation();
            } else {
                this.handleArrowKeys(e, inputElemSrc);
            }
        }.bind(this);

        this.InputElementSrcBtn = this.createImgButton(imgSrcDiv, DWLE_IMG_IDS.imgSrc, [DWLE_IMG_CLASS.ImgBtnClass], readOnly, true);
        this.InputElementSrcBtn.title = this.locStrings.browseTooltip;

        this.InputElementSrcBtn.onclick = function () {
            this.InputElementSrcBtn.blur();
            // this needs to be done because this element has focus after showing browse dialog and gets all key events(including enter)
            // and infinitely show up browse dialog
            this.launchFileSelection(this.locStrings.srcLabel);
        }.bind(this);
        
        
        
        
        
        // This is for Mac
        var invokeSelectSourceDialog = function (e) {
            if (self.getVisibility()) {
                self.InputElementSrcBtn.blur();
                // this needs to be done because this element has focus after showing browse dialog and gets all key events(including enter)
                // and infinitely show up browse dialog
                self.launchFileSelection(self.locStrings.srcLabel);
                e.preventDefault();
                e.stopPropagation();
            }
        };


        this.InputElementSrcBtn.onkeydown = function (e) {
            if (e.keyCode === KEYCODES.Enter) {
                invokeSelectSourceDialog(e);
            }
        }.bind(this);

        this.InputElementSrcBtn.onkeydown = function (e) {
            this.handleArrowKeysForButtons(e);
        }.bind(this);

        this.invokeSelectSoureDialogOnKeyUpBind = this.invokeSelectSoureDialogOnKeyUp.bind(this);
        this.InputElementSrcBtn.addEventListener("keyup", this.invokeSelectSoureDialogOnKeyUpBind, true);// enter/space bar should bring the file selection dialog
        
    }
    // Image Link Div
    this.createLabel(imgLinkDiv, this.locStrings.linkLabel, [DWLE_IMG_CLASS.ImgLabel], DWLE_IMG_IDS.link, this.locStrings.linkTooltip);
    var inputElemLink = this.createInput(imgLinkDiv, "text", DWLE_IMG_IDS.link, classToApplyOnInput, CONSTANTS.undef, readOnly, "href", true);
    if (this.getEditable() === true) {
        this.InputElementLinkBtn = this.createImgButton(imgLinkDiv, DWLE_IMG_IDS.imgLink, [DWLE_IMG_CLASS.ImgBtnClass], readOnly, true);
        this.InputElementLinkBtn.title = this.locStrings.browseTooltip;
        inputElemLink.onkeydown = function (e) {
            if (e.keyCode === KEYCODES.Tab) {
                if (e.shiftKey) {
                    this.focusHudField(DWLE_IMG_IDS.aspectRatio);
                    e.preventDefault();
                    e.stopPropagation();
                }
            } else {
                this.handleArrowKeys(e, inputElemLink);
            }
        }.bind(this);
        inputElemLink.onkeyup = function (e) {
            if (e.keyCode === KEYCODES.Enter) {
                this.updateLink();
                e.stopPropagation();
            } else {
                this.updateTargetDropdown();
            }
        }.bind(this);
        
        this.InputElementLinkBtn.onclick = function () {
            this.InputElementLinkBtn.blur(); //same reason as link
            this.launchFileSelection(this.locStrings.linkLabel);
        }.bind(this);
        
        
        
        var invokeSelectLinkDialog = function (e) {
            if (self.getVisibility()) {
                self.InputElementLinkBtn.blur(); //same reason as link
                self.launchFileSelection(self.locStrings.linkLabel);
                e.preventDefault();
                e.stopPropagation();
            }
        };
        // this is to make sure that tabbing is insiode the hud
        this.InputElementLinkBtn.onkeydown = function (e) {
            if (e.keyCode === KEYCODES.Enter) {
                invokeSelectLinkDialog(e);
            }
        }.bind(this);
        this.InputElementLinkBtn.onkeydown = function (e) {
            this.handleArrowKeysForButtons(e);
            if (e.keyCode === KEYCODES.Tab) {
                if (!e.shiftKey) {
                    if (document.getElementById(DWLE_IMG_IDS.targetDiv).style.display === 'none') {
                        if (this.showBootstrapComponents) {
                            this.focusHudField(DWLE_IMG_IDS.clipToShapeCircle);
                        } else {
                            this.focusHudField(DWLE_IMG_IDS.src);
                        }
                        e.preventDefault();
                    }
                } else {
                    this.focusHudField(DWLE_IMG_IDS.link);
                    e.preventDefault();
                }
            }
        }.bind(this);
        
        this.invokeSelectLinkDialogOnKeyUpBind = this.invokeSelectLinkDialogOnKeyUp.bind(this);
        this.InputElementLinkBtn.addEventListener("keyup", this.invokeSelectLinkDialogOnKeyUpBind, true);// enter/space bar should bring the file selection dialog
    }
    // img Alt Div
    this.createLabel(imgAltDiv, this.locStrings.altLabel, [DWLE_IMG_CLASS.ImgLabel], DWLE_IMG_IDS.alt, this.locStrings.altTooltip);
    var inputElemAlt = this.createInput(imgAltDiv, "text", DWLE_IMG_IDS.alt, classToApplyOnInput, CONSTANTS.none, readOnly, "alt");


    // image target div
    this.createLabel(imgTargetDiv, this.locStrings.targetLabel, [DWLE_IMG_CLASS.ImgLabel], DWLE_IMG_IDS.target, this.locStrings.targetTooltip);
    var inputElemTarget = this.createDropDown(imgTargetDiv, DWLE_IMG_IDS.target, [DWLE_IMG_CLASS.ImgDropDown, DWLE_IMG_CLASS.ImgDropDownNone], ["_blank", "_self", "_parent", "_top"]);

    // image width div
    this.createLabel(imgWidthDiv, this.locStrings.widthLabel, [DWLE_IMG_CLASS.ImgLabel], DWLE_IMG_IDS.width, this.locStrings.widthTooltip);
    var inputElemWidth = this.createInput(imgWidthDiv, "text", DWLE_IMG_IDS.width, classToApplyOnInputForWH, CONSTANTS.none, readOnly, "width");
    // image height div
    this.createLabel(imgHeightDiv, this.locStrings.heightLabel, [DWLE_IMG_CLASS.ImgLabel], DWLE_IMG_IDS.height, this.locStrings.HeightTooltip);
    var inputElemHeight = this.createInput(imgHeightDiv, "text", DWLE_IMG_IDS.height, classToApplyOnInputForWH, CONSTANTS.none, readOnly, "height");

    // container for both width and height
    containerForWandH.appendChild(imgWidthDiv);
    containerForWandH.appendChild(imgHeightDiv);

    if (this.getEditable() === true) {
        inputElemWidth.onkeypress = function (e) {
            // user must not be able to enter non numeric characters in this fields.
            this.validateInputText(e);
        }.bind(this);


        inputElemWidth.onkeydown = function (e) {
            if (e.keyCode === KEYCODES.Enter || e.keyCode === KEYCODES.Tab) {
                this.updateWidth(true, true);
                e.stopPropagation();
            } else {
                this.handleArrowKeys(e, inputElemWidth);
            }
        }.bind(this);
        
        inputElemWidth.onfocus = function (e) {
            this.validateElemValue(e.target);
        }.bind(this);
        
        inputElemWidth.onkeyup = function (e) {
            this.validateElemValue(e.target);
        }.bind(this);
        
        inputElemWidth.onblur = function (e) {
            this.updateWidth(false, true, false);
        }.bind(this);

        inputElemHeight.onkeypress = function (e) {
            // user must not be able to enter non numeric characters in this fields.
            this.validateInputText(e);

        }.bind(this);
        
        inputElemHeight.onblur = function (e) {
            this.updateHeight(false, true, false);
        }.bind(this);

        inputElemHeight.onkeydown = function (e) {

            if (e.keyCode === KEYCODES.Enter) {
                this.updateHeight(true, true);
                e.stopPropagation();
            } else if (e.keyCode === KEYCODES.Tab) {
                this.updateHeight(true, true);
                if (!e.shiftKey) {
                    this.focusHudField(DWLE_IMG_IDS.aspectRatio);
                } else {
                    this.focusHudField(DWLE_IMG_IDS.width);
                }
                e.stopPropagation();
                e.preventDefault();
            } else {
                this.handleArrowKeys(e, inputElemHeight);
            }

        }.bind(this);
        inputElemHeight.onkeyup = function (e) {
            this.validateElemValue(e.target);
        }.bind(this);
        
        inputElemHeight.onfocus = function (e) {
            this.validateElemValue(e.target);
        }.bind(this);
        
        inputElemAlt.onkeydown = function (e) {
            if (e.keyCode === KEYCODES.Enter || e.keyCode === KEYCODES.Tab) {
                this.updateAlt();
                e.stopPropagation();
            } else {
                this.handleArrowKeys(e, inputElemAlt);
            }
        }.bind(this);

        inputElemTarget.onkeydown = function (e) {
            if (e.keyCode === KEYCODES.Tab && e.shiftKey) {
                this.updateLink();
                this.focusHudField(DWLE_IMG_IDS.imgLink);
                e.preventDefault();
                e.stopPropagation();
            } else if (e.keyCode === KEYCODES.Escape) {
                this.escapeKeyPressed();
            }
        }.bind(this);

        inputElemTarget.addEventListener('change', function () {
            // On target change we need to update link because if link is modified and not committed we will not even have anchor tag in the page.
            this.updateLink();

        }.bind(this));

        inputElemTarget.onmousedown = function (e) {
            e.stopPropagation();
        };

    }
    
    var topLineDiv = this.createContainer([DWLE_IMG_CLASS.ImgAspectRatio]);
    var aspectRatioTopImageLine = this.createImgButton(topLineDiv, "", [DWLE_IMG_CLASS.ImgAspectRatioSize, DWLE_IMG_CLASS.ImgAspectRatioTopLine], readOnly, false);
    aspectRatioTopImageLine.disabled = true;

    var aspectRatioDiv = this.createContainer([DWLE_IMG_CLASS.ImgAspectRatio]);
    this.InputElementAspectRatioBtn = this.createImgButton(aspectRatioDiv, DWLE_IMG_IDS.aspectRatio, [DWLE_IMG_CLASS.ImgAspectRatioSize], readOnly, true);
    var bottomLineDiv = this.createContainer([DWLE_IMG_CLASS.ImgAspectRatio]);
    var aspectRatioBottomImageLine = this.createImgButton(bottomLineDiv, "", [DWLE_IMG_CLASS.ImgAspectRatioSize, DWLE_IMG_CLASS.ImgAspectRatioBottomLine], readOnly, false);
    aspectRatioBottomImageLine.disabled = true;
    
    containerForAspectRatio.appendChild(topLineDiv);
    containerForAspectRatio.appendChild(aspectRatioDiv);
    containerForAspectRatio.appendChild(bottomLineDiv);
    
    this.InputElementAspectRatioBtn.title = this.locStrings.AspectRatioTooltip;
    this.InputElementAspectRatioBtn.onkeydown = function (e) {
        if (e.keyCode === KEYCODES.Tab) {
            if (e.shiftKey) {
                this.focusHudField(DWLE_IMG_IDS.height);
            } else {
                this.focusHudField(DWLE_IMG_IDS.link);
            }
            e.stopPropagation();
            e.preventDefault();
        } else if (e.keyCode === KEYCODES.Enter) {
            this.handleAspectRatioBtnClick();
            this.focusHudField(DWLE_IMG_IDS.aspectRatio);
            e.preventDefault();
            e.stopPropagation();
        }
    }.bind(this);
    
    this.InputElementAspectRatioBtn.onclick = function () {
        this.handleAspectRatioBtnClick();
        this.focusHudField(DWLE_IMG_IDS.aspectRatio);
    }.bind(this);
    aspectRatioDiv.classList.add(DWLE_IMG_CLASS.AspectRatioLocked);
    aspectRatioDiv.classList.remove(DWLE_IMG_CLASS.AspectRatioUnLocked);
    this.handleAspectRatioBtnOnKeyUpBind = this.handleAspectRatioBtnOnKeyUp.bind(this);
    this.InputElementAspectRatioBtn.addEventListener("keyup", this.handleAspectRatioBtnOnKeyUpBind, true);
        
    
    containerForWHAspectRatio.appendChild(containerForWandH);
    containerForWHAspectRatio.appendChild(containerForAspectRatio);
        
    imgHTMLContainerDiv.appendChild(imgSrcDiv);
    imgHTMLContainerDiv.appendChild(imgAltDiv);
    imgHTMLContainerDiv.appendChild(containerForWHAspectRatio);
    imgHTMLContainerDiv.appendChild(imgLinkDiv);
    imgHTMLContainerDiv.appendChild(imgTargetDiv);
    this.m_hudContentDiv.appendChild(imgHTMLContainerDiv);
    
    //show the bootstrap components only if the TitanDoc is a bootstrap document
    if (this.showBootstrapComponents) {
        var htmlBootstrapDividerDiv = document.createElement("hr");//For Divider Line
        var imgBootstrapContainerDiv = this.createGroupContainer([DWLE_IMG_CLASS.ImgHudGroup], CONSTANTS.BootstrapGroup);
        //Clip to shape div
        var imgClipToShapeDiv = this.createContainer([DWLE_IMG_CLASS.ImgHudRow]);
        var imgResponsiveDiv = this.createContainer([DWLE_IMG_CLASS.ImgHudRow]);
        var clipToshapeLabelClasses = [DWLE_IMG_CLASS.ImgLabel, DWLE_IMG_CLASS.ImgClipToShapeLabel];
        this.createLabel(imgClipToShapeDiv, this.locStrings.clipToShapeLabel, clipToshapeLabelClasses, DWLE_IMG_IDS.clipToShape, this.locStrings.ClipToShapeTooltip);
        var clipToShapeInnerDiv = this.createContainer([DWLE_IMG_CLASS.ClipToShapeDiv]);
        imgClipToShapeDiv.appendChild(clipToShapeInnerDiv);

        this.RadioCircleBtn = this.createImgButton(clipToShapeInnerDiv, DWLE_IMG_IDS.clipToShapeCircle, [DWLE_IMG_CLASS.ImgBtnClass, DWLE_IMG_CLASS.ClipToShapeRadioImageButton, DWLE_IMG_CLASS.ClipToShapeImgWidth], readOnly, true);
        this.RadioCircleBtn.selectedclass = DWLE_IMG_CLASS.clipToShapeCircle_S;
        this.RadioCircleBtn.title = this.locStrings.ClipToShapeCircleTooltip;
        this.RadioCircleBtn.value = CONSTANTS.ImgCircleBootstrapClass;
        this.RadioCircleBtn.name = CONSTANTS.ClipToShapeRadioGroup;
        this.RadioCircleBtn.classList.add(DWLE_IMG_CLASS.InputTypeNoUndo);
        
        this.RadioCircleBtn.onmousedown = function (e) {
            e.target.classList.add(DWLE_IMG_CLASS.ClipToShapeRadioImageButtonOutlineNone);
        }.bind(this);
        this.RadioCircleBtn.onblur = function (e) {
            e.target.classList.remove(DWLE_IMG_CLASS.ClipToShapeRadioImageButtonOutlineNone);
        }.bind(this);
        this.RadioCircleBtn.onclick = function (e) {
            this.updateClipToShapeClass(e);
        }.bind(this);
        this.RadioCircleBtn.onkeydown = function (e) {
            this.handleArrowKeysForButtons(e);
            if (e.keyCode === KEYCODES.Tab) {
                if (!e.shiftKey) {
                    this.focusHudField(DWLE_IMG_IDS.clipToShapeRounded);
                } else {
                    if (document.getElementById(DWLE_IMG_IDS.targetDiv).style.display !== CONSTANTS.none) {
                        this.focusHudField(DWLE_IMG_IDS.target);
                    } else {
                        this.focusHudField(DWLE_IMG_IDS.imgLink);
                    }
                }
                e.preventDefault();
            } else if (e.keyCode === KEYCODES.Enter) {
                this.updateClipToShapeClass(e);
                e.preventDefault();
                e.stopPropagation();
            }
        }.bind(this);
		
        this.handleUpdateClipToShapeOnKeyUpBind = this.handleUpdateClipToShapeOnKeyUp.bind(this);
        this.RadioCircleBtn.addEventListener("keyup", this.handleUpdateClipToShapeOnKeyUpBind, true);

        this.RadioRoundedBtn = this.createImgButton(clipToShapeInnerDiv, DWLE_IMG_IDS.clipToShapeRounded, [DWLE_IMG_CLASS.ImgBtnClass, DWLE_IMG_CLASS.ClipToShapeRadioImageButton, DWLE_IMG_CLASS.ClipToShapeImgWidth], readOnly, true);
        this.RadioRoundedBtn.selectedclass = DWLE_IMG_CLASS.clipToShapeRounded_S;
        this.RadioRoundedBtn.title = this.locStrings.ClipToShapeRoundedTooltip;
        this.RadioRoundedBtn.value = CONSTANTS.ImgRoundedBootstrapClass;
        this.RadioRoundedBtn.name = CONSTANTS.ClipToShapeRadioGroup;
        this.RadioRoundedBtn.classList.add(DWLE_IMG_CLASS.InputTypeNoUndo);
        this.RadioRoundedBtn.onclick = function (e) {
            this.updateClipToShapeClass(e);
        }.bind(this);
        this.RadioRoundedBtn.onmousedown = function (e) {
            e.target.classList.add(DWLE_IMG_CLASS.ClipToShapeRadioImageButtonOutlineNone);
        }.bind(this);
        this.RadioRoundedBtn.onblur = function (e) {
            e.target.classList.remove(DWLE_IMG_CLASS.ClipToShapeRadioImageButtonOutlineNone);
        }.bind(this);
        this.RadioRoundedBtn.onkeydown = function (e) {
            this.handleArrowKeysForButtons(e);
            if (e.keyCode === KEYCODES.Tab) {
                if (!e.shiftKey) {
                    this.focusHudField(DWLE_IMG_IDS.clipToShapeThumbnail);
                } else {
                    this.focusHudField(DWLE_IMG_IDS.clipToShapeCircle);
                }
                e.preventDefault();
            } else if (e.keyCode === KEYCODES.Enter) {
                this.updateClipToShapeClass(e);
                e.preventDefault();
                e.stopPropagation();
            }
        }.bind(this);

        this.RadioRoundedBtn.addEventListener("keyup", this.handleUpdateClipToShapeOnKeyUpBind, true);

        this.RadioThumbnailBtn = this.createImgButton(clipToShapeInnerDiv, DWLE_IMG_IDS.clipToShapeThumbnail, [DWLE_IMG_CLASS.ImgBtnClass, DWLE_IMG_CLASS.ClipToShapeRadioImageButton], readOnly, true);
        this.RadioThumbnailBtn.selectedclass = DWLE_IMG_CLASS.clipToShapeThumb_S;
        this.RadioThumbnailBtn.title = this.locStrings.ClipToShapeThumbnailTooltip;
        this.RadioThumbnailBtn.value = CONSTANTS.ImgThumbnailBootstrapClass;
        this.RadioThumbnailBtn.name = CONSTANTS.ClipToShapeRadioGroup;
        this.RadioThumbnailBtn.classList.add(DWLE_IMG_CLASS.InputTypeNoUndo);
        this.RadioThumbnailBtn.onclick = function (e) {
            this.updateClipToShapeClass(e);
        }.bind(this);
        this.RadioThumbnailBtn.onblur = function (e) {
            e.target.classList.remove(DWLE_IMG_CLASS.ClipToShapeRadioImageButtonOutlineNone);
        }.bind(this);
        this.RadioThumbnailBtn.onmousedown = function (e) {
            e.target.classList.add(DWLE_IMG_CLASS.ClipToShapeRadioImageButtonOutlineNone);
        }.bind(this);
        this.RadioThumbnailBtn.onkeydown = function (e) {
            this.handleArrowKeysForButtons(e);
            if (e.keyCode === KEYCODES.Tab) {
                if (e.shiftKey) {
                    this.focusHudField(DWLE_IMG_IDS.clipToShapeRounded);
                    e.preventDefault();
                    e.stopPropagation();
                }
            } else if (e.keyCode === KEYCODES.Enter) {
                this.updateClipToShapeClass(e);
                e.preventDefault();
                e.stopPropagation();
            }
        }.bind(this);

        this.RadioThumbnailBtn.addEventListener("keyup", this.handleUpdateClipToShapeOnKeyUpBind, true);

        //Bootstrap Responsive div
        this.ResponsiveCBElement = this.createCheckBox(imgResponsiveDiv, DWLE_IMG_IDS.imgResponsive, [DWLE_IMG_CLASS.ImgCheckboxClass], this.locStrings.responsiveImgLabel, readOnly);
        this.ResponsiveCBElement.title = this.locStrings.MakeImageResponsiveTooltip;
        this.ResponsiveCBElement.setAttribute("value", CONSTANTS.ImgResponsiveBootstrapClass);
        this.ResponsiveCBElement.classList.add(DWLE_IMG_CLASS.InputTypeNoUndo);
        
        this.ResponsiveCBElement.onclick = function (e) {
            this.updateResponsiveClass(e.target.id);
        }.bind(this);
        this.ResponsiveCBElement.onkeydown = function (e) {
            if (e.keyCode === KEYCODES.Tab) {
                this.focusHudField(DWLE_IMG_IDS.src);
                e.preventDefault();
                e.stopPropagation();
            } else if (e.keyCode === KEYCODES.Enter) {
                this.ResponsiveCBElement.checked = !this.ResponsiveCBElement.checked;
                this.updateResponsiveClass(e.target.id);
                e.preventDefault();
                e.stopPropagation();
            }
        }.bind(this);

        this.handleUpdateResponsiveClassOnKeyUpBind = this.handleUpdateResponsiveClassOnKeyUp.bind(this);
        this.ResponsiveCBElement.addEventListener("keyup", this.handleUpdateResponsiveClassOnKeyUpBind, true);
        
        imgBootstrapContainerDiv.appendChild(imgClipToShapeDiv);
        imgBootstrapContainerDiv.appendChild(imgResponsiveDiv);
        this.m_hudContentDiv.appendChild(htmlBootstrapDividerDiv);
        this.m_hudContentDiv.appendChild(imgBootstrapContainerDiv);
    }
    
    
    //add actual hud content
    container.appendChild(this.m_hudContentDiv);
    
    this.m_initialized = true;
    
    this.updateHudFields(this.m_currentSelectedElement);

};

/**
 * @private updateTargetDropdown
 * update the target dropdown depending on the value in link. 
 * target does not make sense when we dont have a link associated.
 * @Param evt     : keystroke event that we received.
 */
DwImageHud.prototype.updateTargetDropdown = function () {
    'use strict';
    var value = document.getElementById(DWLE_IMG_IDS.link).value;
    var targetElement = document.getElementById(DWLE_IMG_IDS.target);
    if (value === "" || value === "undefined") {
        document.getElementById(DWLE_IMG_IDS.targetDiv).style.display = 'none';
        targetElement.setAttribute("disabled", 'true');
        targetElement.classList.add.apply(targetElement.classList, [DWLE_IMG_CLASS.ImgDropDown, DWLE_IMG_CLASS.ImgDropDownNone]);
        targetElement.value = "none";
    } else {
        document.getElementById(DWLE_IMG_IDS.targetDiv).style.display = 'block';
        targetElement.removeAttribute("disabled");
        targetElement.classList.remove(DWLE_IMG_CLASS.ImgDropDownNone);
    }
};

/**
 * @private handleAspectRatioBtnClick
 * handle click on the Aspect ratio button
 */
DwImageHud.prototype.handleAspectRatioBtnClick = function () {
    "use strict";
    var aspectRatioElem = document.getElementById(DWLE_IMG_IDS.aspectRatio);
    if (this.imgAspectRatioLockOn) {
        this.imgAspectRatioLockOn = !this.imgAspectRatioLockOn;
        if (aspectRatioElem) {
            aspectRatioElem.parentElement.classList.remove(DWLE_IMG_CLASS.AspectRatioLocked);
            aspectRatioElem.parentElement.classList.add(DWLE_IMG_CLASS.AspectRatioUnLocked);
        }
    } else {
        this.imgAspectRatioLockOn = !this.imgAspectRatioLockOn;
        if (aspectRatioElem) {
            aspectRatioElem.parentElement.classList.add(DWLE_IMG_CLASS.AspectRatioLocked);
            aspectRatioElem.parentElement.classList.remove(DWLE_IMG_CLASS.AspectRatioUnLocked);
        }
        if (this.imgAttrSize.width !== -1 && this.imgAttrSize.height !== -1) {
            this.updateWidth(true, true);
        }
    }
};

DwImageHud.prototype.launchFileSelection = function (type) {
    'use strict';
    var argObj = {};
    argObj.filter = "";
    if (type === this.locStrings.srcLabel) {
        argObj.operation = this.locStrings.fileDialogType;
        argObj.subOp = this.locStrings.fileTitleSrc;
        argObj.filter = CONSTANTS.FILTER;
        argObj.callback = function (value) {
            var srcElement = document.getElementById(DWLE_IMG_IDS.src);
            if (value && srcElement.value !== value) {
                srcElement.value = value;
                srcElement.title = value;
                this.updateSrc(true);
            }
            this.stopHide = false;
            this.focusHudField(DWLE_IMG_IDS.imgSrc);
        }.bind(this);
        dwObject.logHeadlightsData(DWLE_IMAGEHUD_HEADLIGHTS.ELV_IH, DWLE_IMAGEHUD_HEADLIGHTS.BROWSE_SRC);
    } else if (type === this.locStrings.linkLabel) {
        argObj.operation = this.locStrings.fileDialogType;
        argObj.subOp = this.locStrings.fileTitleLink;
        argObj.callback = function (value) {
            //In case the user presses Esc after clicking the launch file selection,
            //Do NOT consider the new link value as "" to go ahead to remove the link.
            if (value === "") {
                this.focusHudField(DWLE_IMG_IDS.imgLink);
                this.stopHide = false;
                return;
            }
            var linkElement = document.getElementById(DWLE_IMG_IDS.link);
            linkElement.value = value;
            this.updateLink();
            this.focusHudField(DWLE_IMG_IDS.imgLink);
            this.stopHide = false;
            this.updateTargetDropdown();
        }.bind(this);
        dwObject.logHeadlightsData(DWLE_IMAGEHUD_HEADLIGHTS.ELV_IH, DWLE_IMAGEHUD_HEADLIGHTS.BROWSE_LINK);
    } else {
        return;
    }
    this.stopHide = true;
    dwObject.dwBrowseForFileURL(argObj.operation, argObj.subOp, argObj.callback, argObj.filter, false);
};

/*
function : focusHudField
Arguments: current Image Element

give focus to hud field

*/
DwImageHud.prototype.focusHudField = function (id) {
    'use strict';

    var focusElement = document.getElementById(id);
    if (focusElement) {
        focusElement.focus();
    }
};

DwImageHud.prototype.toggleAuxHud = function (message) {
    'use strict';
    AuxiliaryExtensionObject.prototype.toggleAuxHud.call(this, message);
    var elem = this.getCurrentElement();
    if (this.getVisibility()) {
        var srcElement = document.getElementById(DWLE_IMG_IDS.src);
        if (this.getEditable() === true) {
            srcElement.focus();
        }
        // this is to compute natural height and width of an element after changing.
        elem.addEventListener("load", this.postImageLoad.bind(this), true);
    } else if (elem) {
        // this is to compute natural height and width of an element after changing.
        elem.removeEventListener("load", this.postImageLoad.bind(this), true);
    }
    if (message.shortcut) {
        if (this.getVisibility()) {
            dwObject.logHeadlightsData(DWLE_IMAGEHUD_HEADLIGHTS.DW_SHORTCUT, DWLE_IMAGEHUD_HEADLIGHTS.LAUNCH);
        } else {
            dwObject.logHeadlightsData(DWLE_IMAGEHUD_HEADLIGHTS.OTH_ELV, DWLE_IMAGEHUD_HEADLIGHTS.CLOSE_SHORTCUT);
        }
    } else {
        if (this.getVisibility()) {
            dwObject.logHeadlightsData(DWLE_IMAGEHUD_HEADLIGHTS.ELV_IH, DWLE_IMAGEHUD_HEADLIGHTS.LAUNCH);
        } else {
            dwObject.logHeadlightsData(DWLE_IMAGEHUD_HEADLIGHTS.OTH_ELV, DWLE_IMAGEHUD_HEADLIGHTS.CLOSE_CLICK);
        }
    }
};

DwImageHud.prototype.getExtensionId = function () {
    'use strict';
    return CONSTANTS.ExtensionID;
};

/**
 * @override commit
 * Commit the values of each of the attribute in Image Hud. 
 * @Param None
*/
DwImageHud.prototype.commit = function () {
    'use strict';

    if (this.getVisibility() === false) {
        return;
    }
    this.updateSrc(false);
    this.updateAlt();
    this.updateWidth(false, false);//false indicates that dont redraw the view
    this.updateHeight(false, false);
    // Link needs to be done at the end since it leads to creation of new elements. This will update the target as well.
    this.updateLink();

//	if (this.attributeChanged) {
//		this.m_liveEditEvent.fire({
//			type: DW_LIVEEDIT_EVENTS.ElementChanged
//		});
//		this.attributeChanged = false;
//	}
};

/**
 * @private isHudObstructingImage
 * if the Hud postioned at the given point will obstruct the image or not
 * DWLE_DIMENSIONS.AuxHudOffSet : 10px  --> for the arrow to come before the HUD
 */
DwImageHud.prototype.isHudObstructingImage = function (imgRect) {
    'use strict';
    
    if (imgRect) {
        var imgRight = imgRect.left + imgRect.width;
        var imgBottom = imgRect.top + imgRect.height;
        var imgLeft = imgRect.left <= window.parent.pageXOffset ? window.parent.pageXOffset : imgRect.left;
        var imgTop = imgRect.top <= window.parent.scrollY ? window.parent.scrollY : imgRect.top;
        
        imgRight = imgRight > (window.parent.innerWidth + window.parent.pageXOffset) ? (window.parent.innerWidth + window.parent.pageXOffset) : imgRight;
        imgBottom = imgBottom > (window.parent.innerHeight + window.parent.scrollY) ? (window.parent.innerHeight + window.parent.scrollY) : imgBottom;
        
        if (imgRight > imgLeft && imgBottom > imgTop) {
            var imgWidth = imgRight - imgLeft;
            var imgHeight = imgBottom - imgTop;
            
            if (this.m_currentHudWidth > 0 && this.m_currentHudHeight > 0) {
                var widthRatio = imgWidth / this.m_currentHudWidth;
                var heightRatio = imgHeight / this.m_currentHudHeight;

                if (widthRatio < CONSTANTS.ImgDimensionThreshold && heightRatio < CONSTANTS.ImgDimensionThreshold) {
                    return true;
                }
            }
        }
    }
    
    return false;
};

/**
 * @private positionHud
 * Position the HUD according to element's width, height and position
 * @Param elemRect : contains computed width,height,top,left 
 * @Note This positions the HUD with respect to the space available around the Image.
 * DWLE_DIMENSIONS.AuxHudOffSet : 10px  --> for the arrow to come before the HUD
 */
DwImageHud.prototype.positionHud = function () {
    'use strict';
    var elemRect = liveViewObject.getElementRect(this.getCurrentElement());
    if (elemRect.height <= 0 || elemRect.width <= 0) {
        return;
    }
    
    //cache position of hud because offsetwidth and offsetheight gives 0 when element display is made to none
    if (this.m_currentHudHeight === 0 && this.m_currentHudWidth === 0) {
        this.m_currentHudHeight = this.m_hudContentDiv.offsetHeight;
        this.m_currentHudWidth = this.m_hudContentDiv.offsetWidth;
    }
    
    //Hud should not obscure the esh Details 
    var widthOffset = (elemRect.width >= this.eshDetails.Width) ? elemRect.width : this.eshDetails.Width;
    
    // By default try to position on right
    var hudTop = -1;
    var hudLeft = -1;
    var styleToApply = "";
    
    // right Side Check contains max horizontal position needed to place the hud on right side
    var leftOfElem = elemRect.left >= window.parent.pageXOffset ? elemRect.left : window.parent.pageXOffset;
    var topOfElem = elemRect.top >= window.parent.scrollY ? elemRect.top : window.parent.scrollY;
    
    var rightSideCheck = (leftOfElem + widthOffset + this.m_currentHudWidth) - window.parent.pageXOffset;
    // height Check contains max vertical position takes to place the hud at same level
    var heightCheck = (topOfElem + this.m_currentHudHeight) - window.parent.scrollY;
    
    //Step 1: Lets try to fit it at the right/ left of the element entirely
    
    if (rightSideCheck < window.parent.innerWidth) {
        //Keeping hud at the right side will fit inside the live view width 
        hudLeft = (leftOfElem + widthOffset) + DWLE_DIMENSIONS.AuxHudOffSet;
        hudTop = topOfElem;
        styleToApply = DWLE_IMG_CLASS.ImgContainerRight;
    } else {
        //no fit on the right side , lets try on the left side
        var leftSideCheck = leftOfElem - (window.parent.pageXOffset + this.m_currentHudWidth + DWLE_DIMENSIONS.AuxHudOffSet);
        
        if (leftSideCheck > 0) {
            //fit on the left side 
            hudLeft = leftSideCheck + window.parent.pageXOffset;
            hudTop = topOfElem;
            styleToApply = DWLE_IMG_CLASS.ImgContainerLeft;
        } else {
            //No space on the left , only option is to allign it with the element itself 
            hudLeft = leftOfElem;
        }
    }
    
    
    //Step 2 : Not possible on the right / left of the element , try at top / bottom of the element
    
    if (hudTop === -1 || heightCheck > window.parent.innerHeight) {
        //we need to re-position the hud either on top of the element or at the bottom 
        
        //Try at the top of the element
        var topCorner = topOfElem - (this.m_currentHudHeight + DWLE_DIMENSIONS.AuxHudOffSet + this.eshDetails.Height);
        
        if (topCorner - window.parent.scrollY > 0) {
            //Hud can be placed at the top of the element , so align the hud vertically same as the element
            hudLeft = leftOfElem;
            hudTop = topCorner;
            styleToApply = DWLE_IMG_CLASS.ImgContainerTop;
        } else {
            //Can't be placed at the top , so lets try at the bottom of the element 
            var bottom = (topOfElem + elemRect.height + this.m_currentHudHeight + DWLE_DIMENSIONS.AuxHudOffSet + this.eshDetails.Height) - window.parent.scrollY;
            
            if (bottom < window.parent.innerHeight) { //bottom case
                //Fitted at the bottom of the element , so align the hud vertically same as the element
                var heightToPlace = topOfElem + elemRect.height + DWLE_DIMENSIONS.AuxHudOffSet;
                //if the editable selectors is on bottom add that height also
                if (this.eshDetails.Position === false) {
                    heightToPlace += this.eshDetails.Height;
                }
                hudLeft = leftOfElem;
                hudTop = heightToPlace;
                styleToApply = DWLE_IMG_CLASS.ImgContainerBottom;
            } else {
                //Step 3 : Not Possible on top / bottom of the element , now try somewhere in between 
                
                if (styleToApply !== DWLE_IMG_CLASS.ImgContainerRight && styleToApply !== DWLE_IMG_CLASS.ImgContainerLeft) {
                    //hud will be placed on top of the element
                    
                    if (!this.isHudObstructingImage(elemRect)) {
                        //Place the hud nearer to the ESH 
                        if (this.eshDetails.Position === true) {
                            //ESH on top, extend hud towards bottom of the element
                            hudTop = topOfElem + DWLE_DIMENSIONS.AuxHudOffSet;
                        } else {
                            //ESH on bottom, extend hud towards top of the element
                            hudTop = topOfElem + elemRect.height - (this.m_currentHudHeight + DWLE_DIMENSIONS.AuxHudOffSet);
                        }
                        //lets check if hud will get clipped some how by positoning it nearer to the ESH 
                        if ((hudTop < window.parent.scrollY) || (hudTop + this.m_currentHudHeight) > (window.parent.innerHeight + window.parent.scrollY)) {
                            
                            if ((hudLeft + this.eshDetails.Width + this.m_currentHudWidth + DWLE_DIMENSIONS.AuxHudOffSet) < (window.parent.innerWidth + window.parent.pageXOffset)) {
                                //Lets try to take the hud a little rightwards , so that hud doesn't cover the ESH at all 
                                hudLeft += (this.eshDetails.Width + DWLE_DIMENSIONS.AuxHudOffSet);
                                styleToApply = DWLE_IMG_CLASS.ImgContainerRight;
                            } else {
                                //Lets try to take the hud a little rightwards , just after the addbtn
                                var left = (window.parent.innerWidth + window.parent.pageXOffset) - (this.m_currentHudWidth + DWLE_DIMENSIONS.AuxHudOffSet);
                                hudLeft = left < 0 ? hudLeft : left;
                                styleToApply = DWLE_IMG_CLASS.ImgContainerRight;
                            }
                            
                            if (hudTop < window.parent.scrollY) {
                                //hud will get cliped at the top , so start at the top of the screen 
                                hudTop = window.parent.scrollY;
                            } else if ((hudTop + this.m_currentHudHeight) > (window.parent.innerHeight + window.parent.scrollY)) {
                                //Hud will get clipped at the bottom , take the hud a little upwards
                                var top = (window.parent.innerHeight + window.parent.scrollY) - (this.m_currentHudHeight + DWLE_DIMENSIONS.AuxHudOffSet);
                                hudTop = top < window.parent.scrollY ? window.parent.scrollY : top;
                            }
                        }
                    } else {
                        //Hud's left edge will be alligned with the element's left edge , so lets try to obscure the element as less as possible
                        var hudTopWhenHudFlowsUpwards = window.parent.scrollY;
                        var hudTopWhenHudFlowsDownwards = (window.parent.innerHeight - this.m_currentHudHeight) + window.parent.scrollY;

                        var elemHeightObstructedbyHudUpwards = (hudTopWhenHudFlowsUpwards + this.m_currentHudHeight) - topOfElem;
                        var elemHeightObstructedbyHudDownwards = topOfElem - hudTopWhenHudFlowsDownwards;

                        if (elemHeightObstructedbyHudDownwards < elemHeightObstructedbyHudUpwards) {
                            //Pick the one which obstructs the element least
                            hudTop = hudTopWhenHudFlowsDownwards;
                        } else {
                            hudTop = hudTopWhenHudFlowsUpwards;
                        }
                        
                        if ((hudLeft + this.eshDetails.Width + this.m_currentHudWidth + DWLE_DIMENSIONS.AuxHudOffSet) < (window.parent.innerWidth + window.parent.pageXOffset)) {
                            //Lets try to take the hud a little rightwards , just after the class 
                            hudLeft += (this.eshDetails.Width + DWLE_DIMENSIONS.AuxHudOffSet);
                            
                            if ((hudTop + CONSTANTS.DefaultArrowPositon) > topOfElem && (hudTop + CONSTANTS.DefaultArrowPositon) < (topOfElem + elemRect.height)) {
                                styleToApply = DWLE_IMG_CLASS.ImgContainerRight;
                            }
                        } else {
                            //Lets try to take the hud a little rightwards , just after the addbtn
                            var leftOfHud = (window.parent.innerWidth + window.parent.pageXOffset) - (this.m_currentHudWidth + DWLE_DIMENSIONS.AuxHudOffSet);
                            hudLeft = leftOfHud < 0 ? hudLeft : leftOfHud;
                            
                            if ((hudTop + CONSTANTS.DefaultArrowPositon) > topOfElem && (hudTop + CONSTANTS.DefaultArrowPositon) < (topOfElem + elemRect.height)) {
                                styleToApply = DWLE_IMG_CLASS.ImgContainerRight;
                            }
                        }
                    }
                    
                    //Check if Esh is totally covered by the hud
                    if (hudTop < this.eshDetails.addBtnTop && (hudTop + this.m_currentHudHeight) > this.eshDetails.addBtnBottom) {
                        //Take the hud a little upwards , so that arrow is clearly visible in this case 
                        if (hudTop > window.parent.scrollY + DWLE_DIMENSIONS.AuxHudOffSet) {
                            hudTop -= DWLE_DIMENSIONS.AuxHudOffSet;
                        } else {
                            hudTop = window.parent.scrollY;
                        }
                    }

                    //Lets check if the hud width will get clipped somehow 
                    if (this.m_currentHudWidth < window.parent.innerWidth) {
                        var wcheck = hudLeft + this.m_currentHudWidth;
                        //Only if the hud can be somehow fitted inside the live view , then try to re-position the same 
                        if (wcheck > (window.parent.scrollX + window.parent.innerWidth)) {
                            //Imagehud will overflow outside the liveview, try to re-position it properly
                            var wDiff = wcheck - (window.parent.scrollX + window.parent.innerWidth);
                            hudLeft -= wDiff;
                        }
                    }
                } else {
                    //Image hud will be a the right / left of the element , so it can't obstruct the image 
                    if (this.eshDetails.Position === true) {
                        //ESH on top , place hud on top of element and extend it to the bottom of the element
                        hudTop = topOfElem + DWLE_DIMENSIONS.AuxHudOffSet;
                        if ((hudTop + this.m_currentHudHeight) > (window.parent.scrollY + window.parent.innerHeight)) {
                            // imageHud will overflow outside the liveview , try to re-postion it properly                        
                            hudTop = hudTop - ((hudTop + this.m_currentHudHeight + DWLE_DIMENSIONS.AuxHudOffSet) - (window.parent.scrollY + window.parent.innerHeight));
                        }
                    } else {
                        //ESH on bottom, place hud on top of the element and extend it to the top of the element 
                        hudTop = topOfElem + elemRect.height - (this.m_currentHudHeight + DWLE_DIMENSIONS.AuxHudOffSet);

                        if (hudTop < 0) {
                            //hud will get cliped at the top , so start at the botom of the element & extend it towards the bottom 
                            hudTop = topOfElem + elemRect.height + this.eshDetails.Height + DWLE_DIMENSIONS.AuxHudOffSet;
                        }

                        if ((hudTop + this.m_currentHudHeight) > (window.parent.scrollY + window.parent.innerHeight)) {
                            // imageHud will overflow outside the liveview , try to re-postion it properly                            
                            hudTop = hudTop - ((hudTop + this.m_currentHudHeight + DWLE_DIMENSIONS.AuxHudOffSet) - (window.parent.scrollY + window.parent.innerHeight));
                        }
                    }
                }
                
                if (styleToApply !== DWLE_IMG_CLASS.ImgContainerRight && styleToApply !== DWLE_IMG_CLASS.ImgContainerLeft) {
                    
                    //Decide where the arrow points to
                    if (hudTop <= this.eshDetails.addBtnTop && (hudTop + this.m_currentHudHeight) >= this.eshDetails.addBtnBottom) {
                        //Esh is totally covered by the hud , so check what part of element is visible
                        if (hudTop >= topOfElem) {
                            //Element is visible at the top of the hud , so make the arrow point towards top
                            styleToApply = DWLE_IMG_CLASS.ImgContainerBottom;
                        } else if ((hudTop + this.m_currentHudHeight) <= (topOfElem + elemRect.height)) {
                            //Element is visible at the bottom of the hud , so let the arrow point at the bottom
                            styleToApply = DWLE_IMG_CLASS.ImgContainerTop;
                        } else if ((hudLeft + this.m_currentHudWidth) <= (leftOfElem + elemRect.width)) {
                            //Element is visible at the right of the hud
                            styleToApply = DWLE_IMG_CLASS.ImgContainerLeft;
                        } else if (hudLeft > leftOfElem) {
                            //Element is visible at the left of the hud
                            styleToApply = DWLE_IMG_CLASS.ImgContainerRight;
                        } /* else {
                            //Case where nothing is visible , lets not have any arrow pointed anywhere
                        }
                        */
                    } else if ((hudTop + this.m_currentHudHeight) <= this.eshDetails.addBtnBottom) {
                        //Esh is visible at the bottom of the hud , so arrow will point towards bottom 
                        styleToApply = DWLE_IMG_CLASS.ImgContainerTop;
                    } else {
                        //Esh is visible at the top of the hud  , so arrow should point towards top 
                        styleToApply = DWLE_IMG_CLASS.ImgContainerBottom;
                    }
                }
            }
        }
    }
    
    this.m_hudContentDiv.style.top = hudTop + 'px';
    this.m_hudContentDiv.style.left = hudLeft + 'px';
    this.m_hudContentDiv.removeAttribute("class");
    if (this.getEditable() === false) {
        styleToApply += " " + (DWLE_IMG_CLASS.ImgContainerGreyed);
    }
    this.m_hudContentDiv.setAttribute("class", DWLE_IMG_CLASS.ImgContainer + " " + styleToApply);
    window.setCoralThemeForElement(this.m_hudContentDiv, this.m_currentTheme);
    var styleSheet = document.styleSheets[1];
    var arrowColor = CONSTANTS.ColorHudBlue;
    if (this.getEditable() === false) {
        arrowColor = CONSTANTS.ColorHudGrey;
    }
    
    if (styleSheet && styleSheet.insertRule) {
        if (styleToApply.indexOf(DWLE_IMG_CLASS.ImgContainerRight) !== -1 || styleToApply.indexOf(DWLE_IMG_CLASS.ImgContainerLeft) !== -1) {
            //Set the posiiton of the arrow in case hud is on right or left of the element 
            var arrowTop = 0;
            if ((topOfElem - hudTop) > CONSTANTS.DefaultArrowPositon && (topOfElem - hudTop) < (this.m_currentHudHeight - CONSTANTS.DefaultArrowPositon)) {
                arrowTop = (topOfElem - hudTop);
            } else if ((topOfElem - hudTop) < CONSTANTS.DefaultArrowPositon) {
                arrowTop = CONSTANTS.DefaultArrowPositon;
            } else {
                arrowTop = (this.m_currentHudHeight - CONSTANTS.DefaultArrowPositon);
            }
            
            if (styleToApply.indexOf(DWLE_IMG_CLASS.ImgContainerRight) !== -1) {
                styleSheet.insertRule(CONSTANTS.DWDiv + CONSTANTS.ClassSeparator + DWLE_IMG_CLASS.ImgContainerRight + DWLE_IMG_CLASS.BeforePseudoSelector + "{ top:" + arrowTop + "px; border-right-color: " + arrowColor + ";}", styleSheet.cssRules.length);
                styleSheet.insertRule(CONSTANTS.DWDiv + CONSTANTS.ClassSeparator + DWLE_IMG_CLASS.ImgContainerRight + DWLE_IMG_CLASS.AfterPseudoSelector + "{ top:" + arrowTop + "px;} ", styleSheet.cssRules.length);
            } else {
                styleSheet.insertRule(CONSTANTS.DWDiv + CONSTANTS.ClassSeparator + DWLE_IMG_CLASS.ImgContainerLeft + DWLE_IMG_CLASS.BeforePseudoSelector + "{ top:" + arrowTop + "px; border-left-color: " + arrowColor + ";} ", styleSheet.cssRules.length);
                styleSheet.insertRule(CONSTANTS.DWDiv + CONSTANTS.ClassSeparator + DWLE_IMG_CLASS.ImgContainerLeft + DWLE_IMG_CLASS.AfterPseudoSelector + "{ top:" + arrowTop + "px;} ", styleSheet.cssRules.length);
            }
        } else {
            //For bottom and top case of Hud 
            var arrowLeft = CONSTANTS.DefaultArrowPositon;
            
            if (leftOfElem > hudLeft) {
                //element is at the right side of the hud 
                if ((hudLeft + this.m_currentHudWidth) < leftOfElem) {
                    //hud start croses the end of the element , so keep the arrow at the end of the hud 
                    arrowLeft = this.m_currentHudWidth - CONSTANTS.DefaultArrowPositon;
                } else if ((leftOfElem - hudLeft) > CONSTANTS.DefaultArrowPositon && (leftOfElem - hudLeft) < (this.m_currentHudWidth - CONSTANTS.DefaultArrowPositon)) {
                    arrowLeft = leftOfElem - hudLeft;
                } else if ((leftOfElem - hudLeft) > (this.m_currentHudWidth - CONSTANTS.DefaultArrowPositon)) {
                    arrowLeft = this.m_currentHudWidth - CONSTANTS.DefaultArrowPositon;
                }
            } //No need of adjustment if element is at the left side of the hud
            
            if (styleToApply.indexOf(DWLE_IMG_CLASS.ImgContainerTop) !== -1) {
                styleSheet.insertRule(CONSTANTS.DWDiv + CONSTANTS.ClassSeparator + DWLE_IMG_CLASS.ImgContainerTop + DWLE_IMG_CLASS.BeforePseudoSelector + "{ left:" + arrowLeft + "px; border-top-color: " + arrowColor + ";} ", styleSheet.cssRules.length);
                styleSheet.insertRule(CONSTANTS.DWDiv + CONSTANTS.ClassSeparator + DWLE_IMG_CLASS.ImgContainerTop + DWLE_IMG_CLASS.AfterPseudoSelector + "{ left:" + arrowLeft + "px;} ", styleSheet.cssRules.length);
            } else {
                styleSheet.insertRule(CONSTANTS.DWDiv + CONSTANTS.ClassSeparator + DWLE_IMG_CLASS.ImgContainerBottom + DWLE_IMG_CLASS.BeforePseudoSelector + "{ left:" + arrowLeft + "px; border-bottom-color: " + arrowColor + ";} ", styleSheet.cssRules.length);
                styleSheet.insertRule(CONSTANTS.DWDiv + CONSTANTS.ClassSeparator + DWLE_IMG_CLASS.ImgContainerBottom + DWLE_IMG_CLASS.AfterPseudoSelector + "{ left:" + arrowLeft + "px;} ", styleSheet.cssRules.length);
            }
        }
    }
     
    
    this.m_hudContentDiv.style.visibility = "visible";
	// explicitly set focus to imagehud because there are lot of scenarios of conflict between editable selectors and image hud.
    var imageHudInParent = parent.document.getElementById(CONSTANTS.ExtensionID);
    if (imageHudInParent) {
        imageHudInParent.focus();
    }
};

DwImageHud.prototype.getHudContainer = function () {
    'use strict';
    return this.m_hudContainer;
};

DwImageHud.prototype.initialize = function () {
    'use strict';
    AuxiliaryExtensionObject.prototype.initialize.call(this);
    
    this.globalController = window.parent.globalController;
    dwExtensionController.addListener(parent.DW_EVENTS.SelectionChanged, this.SelectionChangedMessageHandler, this);
    
    this.locStrings = {};

    this.locStrings.browseTooltip = this.globalController.getLocalizedString('Common_Browse_Tooltip');
    this.locStrings.fileDialogType = this.globalController.getLocalizedString('Common_DialogType');
	this.locStrings.fileTitleSrc = this.globalController.getLocalizedString('Common_FileTitleSrc');
	this.locStrings.fileTitleLink = this.globalController.getLocalizedString('Common_FileTitleLink');
    
    this.locStrings.srcLabel = this.globalController.getLocalizedString('Img_Hud_Src_Label');
    this.locStrings.linkLabel = this.globalController.getLocalizedString('Img_Hud_Link_Label');
    this.locStrings.titleLabel = this.globalController.getLocalizedString('Img_Hud_Title_Label');
    this.locStrings.altLabel = this.globalController.getLocalizedString('Img_Hud_Alt_Label');
    this.locStrings.targetLabel = this.globalController.getLocalizedString('Img_Hud_Target_Label');
    this.locStrings.widthLabel = this.globalController.getLocalizedString('Img_Hud_Width_Label');
    this.locStrings.heightLabel = this.globalController.getLocalizedString('Img_Hud_Height_Label');
    this.locStrings.clipToShapeLabel = this.globalController.getLocalizedString('Img_Hud_ClipToShape_Label');
    this.locStrings.responsiveImgLabel = this.globalController.getLocalizedString('Img_Hud_ResponsiveImage_Label');
    
    this.locStrings.srcTooltip = this.globalController.getLocalizedString('Img_Hud_Src_Tooltip');
    this.locStrings.linkTooltip = this.globalController.getLocalizedString('Common_Link_ToolTip');
    this.locStrings.titleTooltip = this.globalController.getLocalizedString('Img_Hud_Title_Tooltip');
    this.locStrings.altTooltip = this.globalController.getLocalizedString('Img_Hud_Alt_Tooltip');
    this.locStrings.targetTooltip = this.globalController.getLocalizedString('Img_Hud_Target_Tooltip');
    this.locStrings.widthTooltip = this.globalController.getLocalizedString('Img_Hud_W_Tooltip');
    this.locStrings.HeightTooltip = this.globalController.getLocalizedString('Img_Hud_H_Tooltip');
    this.locStrings.AspectRatioTooltip = this.globalController.getLocalizedString('Img_Hud_AspectRatio_Tooltip');
    this.locStrings.ClipToShapeTooltip = this.globalController.getLocalizedString('Img_Hud_ClipToShape_Tooltip');
    this.locStrings.ClipToShapeCircleTooltip = this.globalController.getLocalizedString('Img_Hud_ClipToShape_Circle_Tooltip');
    this.locStrings.ClipToShapeRoundedTooltip = this.globalController.getLocalizedString('Img_Hud_ClipToShape_Rounded_Tooltip');
    this.locStrings.ClipToShapeThumbnailTooltip = this.globalController.getLocalizedString('Img_Hud_ClipToShape_Thumbnail_Tooltip');
    this.locStrings.MakeImageResponsiveTooltip = this.globalController.getLocalizedString('Img_Hud_ClipToShape_Responsive_Tooltip');
    this.locStrings.NotAValidValue = this.globalController.getLocalizedString('Img_Hud_NotAValidValue_Tooltip');
    
    this.InputElementAspectRatioBtn = null;
    this.InputElementLinkBtn = null;
    this.InputElementSrcBtn = null;
    this.RadioCircleBtn = null;
    this.RadioRoundedBtn = null;
    this.RadioThumbnailBtn = null;
    this.ResponsiveCBElement = null;
    
    this.invokeSelectSoureDialogOnKeyUpBind = null;
    this.invokeSelectLinkDialogOnKeyUpBind = null;
    this.handleAspectRatioBtnOnKeyUpBind = null;
    this.handleUpdateClipToShapeOnKeyUpBind = null;
    this.handleUpdateResponsiveClassOnKeyUpBind = null;
    
    this.stopHide = false;
};

/*
function:SelectionChangedMessageHandler - Handler for selection changed messages from Live View. Currently needed for undo/redo for Bootstrap category
Arguments: none
Return : None
*/
DwImageHud.prototype.SelectionChangedMessageHandler = function () {
    'use strict';
    this.updateBootstrapClassHudFields(this.m_currentSelectedElement);
};

/**
 * @private repositionHUD
 * respotion the hud
 * @Param none
 */
DwImageHud.prototype.repositionHUD = function () {
    'use strict';
    
    // do not reposition if the hud has been dragged
	if (!this.getCurrentElement() || this.m_hudDragged === true || this.getVisibility() === false) {
        return;
    }
    
    liveViewObject.positionExtensionById(CONSTANTS.ExtensionID, 0, 0, window.parent.innerWidth + window.parent.scrollX, window.parent.innerHeight + window.parent.scrollY);
    this.positionHud();
};
/**
 * @private updateSrc
 * if we pass a string other than "" it will take that value otherwise it will read the value of the filed from hud.
 * @Param srcValue: "" if it is from file dialog and value in the input box if is from HUD Input Boxes
 */
DwImageHud.prototype.updateSrc = function (updateUI) {
    'use strict';

    this.updateElement("src", DWLE_IMG_IDS.src);
    // After the source has changed we need to redraw the whole stuff again
    if (updateUI === true) {
        AuxiliaryExtensionObject.prototype.elementDimensionChanged.call(this);
//        if (this.attributeChanged) {
//			this.m_liveEditEvent.fire({
//				type: DW_LIVEEDIT_EVENTS.ElementChanged
//			});
//			this.attributeChanged = false;
//		}
    }
};

/**
 * @private postImageLoad
 * After the image loading compute the width and height of the image 
 * this has to be done only when there is a width or height attribute present already.
 * Mocking design view behavior
 * @Param none
 */
DwImageHud.prototype.postImageLoad = function () {
    'use strict';
    var activeFocus = document.activeElement;
    var elem = this.getCurrentElement();
    if (!elem || (this.getVisibility() === false)) {
        return;
    }
    var heightElement = document.getElementById(DWLE_IMG_IDS.height);
    var widthElement = document.getElementById(DWLE_IMG_IDS.width);
    if (heightElement.value) {
        heightElement.value = elem.naturalHeight;
    }
    if (widthElement.value) {
        widthElement.value =  elem.naturalWidth;
    }
    this.updateWidth(false, false);//false indicates that dont redraw the view
    this.updateHeight(true, false);
    if (activeFocus.type && activeFocus.type === "image") {
        // browse button had focus. restore it.
        activeFocus.focus();
    } else {
        this.focusHudField(DWLE_IMG_IDS.src);
    }
};
/**
 * @private updateLink
 * Wraps the image tag with an anchor tag.
 * @Param linkValue: "" if it is from file dialog and value in the input box if is from HUD Input Boxes
 */
DwImageHud.prototype.updateLink = function () {
    'use strict';
    var linkElement = document.getElementById(DWLE_IMG_IDS.link);
    
    var linkValue = linkElement.value;
    linkElement.title = linkValue;
    
    // if link is deleted or empty --> target should also be empty
    if (linkValue === "" || linkValue === "undefined") {
        document.getElementById(DWLE_IMG_IDS.target).value = "none";
    }
    var elem = this.getCurrentElement();
    var parent = elem.parentNode;
    var target = null,
        linkNode;
    var imageId = elem.getAttribute(DWConstants.DWUniqueId);
    var newOuterHTML = "";
    var newCallbackObj = {};
    // if LinkValue is empty --> it is deleted or not there at all
    // else linkValue is non empty --> it is associated newly or existing link is modified.
    if (linkValue !== "") {
        //if link exists previously and we updated it -->get parent DWId and push the changes
        if (parent.tagName === "A") {
            var existingHref = parent.getAttribute("href");
            //if the value is not changed dont do anything
            if (existingHref && existingHref === linkValue) {
                this.updateTarget();
                return;
            }
            parent.setAttribute("href", linkValue);
            dwObject.updateDWDocumentElementAttr(parent, 'href', linkValue, null, imageId);
            dwObject.logHeadlightsData(DWLE_IMAGEHUD_HEADLIGHTS.ELV_IH, DWLE_IMAGEHUD_HEADLIGHTS.LINK);
            this.updateTarget();
            return;
        }
        // we are associating links newly.
        // add <a> tag in between image and its parent
        linkNode = document.createElement("a");
        linkNode.setAttribute("href", linkValue);
        elem.parentNode.replaceChild(linkNode, elem);
        linkNode.appendChild(elem);
        linkNode.setAttribute(DWConstants.DWTempId, this.callback_counter);
        // attach a temp ID and store them so that once we get correct dwid's we replace the values.
        this.callback_map[this.callback_counter] = linkNode;
        this.callback_counter++;
        elem.setAttribute(DWConstants.DWTempId, this.callback_counter);
        this.callback_map[this.callback_counter] = elem;
        newCallbackObj.node_callback_id = this.callback_counter;
        this.callback_counter++;
        target = linkNode;
    } else {
        linkNode = elem.parentNode;
        imageId = linkNode.getAttribute(DWConstants.DWUniqueId);
        // there is no anchor tag associated with this img --> just return
        if (linkNode.tagName !== "A") {
            return;
        }

        // there is an anchor tag associated we need to delete it.
        var parentNode = linkNode.parentNode;
        var childNodesOfA = linkNode.childNodes,
            length = childNodesOfA.length,
            i = length - 1, // length will atleast be 1 as we know there is a child img
            prevElem = null;
        for (i; i >= 0; i--) {
            var curElem = childNodesOfA[i];
            if (i === length - 1) {
                parentNode.replaceChild(curElem, linkNode);
            } else {
                parentNode.insertBefore(curElem, prevElem);
            }
            if (curElem.nodeType === 1) {
                // this is an element
                curElem.setAttribute(DWConstants.DWTempId, this.callback_counter);
                newCallbackObj.node_callback_id = this.callback_counter;
                this.callback_map[this.callback_counter] = curElem;
                this.callback_counter++;
            }
            if (curElem.nodeType === 1) {
                newOuterHTML = curElem.outerHTML + newOuterHTML;
            } else if (curElem.nodeType === 3) {
                newOuterHTML = curElem.data + newOuterHTML;
            }
            prevElem = curElem;
        }
        target = elem;
    }
    
    // get details of parent and push it to SM layer.
    var parentId = target.parentNode.getAttribute(DWConstants.DWUniqueId);
    var newText = target.outerHTML;
    if (newOuterHTML !== "") {
        newText = newOuterHTML;
    }
    newCallbackObj.parentId = parentId;
    newCallbackObj.nodeId = imageId;
    newCallbackObj.newText = newText;
    newCallbackObj.counter = this.callback_counter;
    newCallbackObj.callback = function (newObj) {
        this.updateDWIdsForAnchors(newObj);
    }.bind(this);

    if (this.fileSavePending >= 1) {
        this.fileSavePending++;
    }
    dwObject.DWSMGetDWIdsForUpdatedTags(newCallbackObj);
    dwObject.logHeadlightsData(DWLE_IMAGEHUD_HEADLIGHTS.ELV_IH, DWLE_IMAGEHUD_HEADLIGHTS.LINK);
    this.updateTargetDropdown();
};

DwImageHud.prototype.shouldHide = function () {
    'use strict';
    if ((this.fileSavePending > 1)  || this.stopHide) {
        return false;
    }
    
    return true;
};

/**
 * @private updateDWIdsForAnchors
 * will be called from sm layer with newObj containing tempId's and their corresponding dwid's
 * @Param newObj: contains a map of tempId,dwid
 */
DwImageHud.prototype.updateDWIdsForAnchors = function (newObj) {
    'use strict';
//    if (!newObj) {
//    }
        
    var i, elem;
    for (i = 0; i < this.callback_counter; i++) {
        elem = this.callback_map[i];
        elem.setAttribute(DWConstants.DWUniqueId, newObj[i]);
        elem.removeAttribute(DWConstants.DWTempId);
    }
    // update target always after updating the link
    this.updateTarget();
    this.callback_counter = 0;
    
    if (this.fileSavePending > 1) {
        this.fileSavePending--;
        if (this.fileSavePending === 1) {
            window.parent.DWSaveDocument();
            this.fileSavePending--;
        }
    }
};
/**
 * @private updateAlt
 * update Alt attribute of the image
 * @Param none
 */
DwImageHud.prototype.updateAlt = function () {
    'use strict';
    this.updateElement("alt", DWLE_IMG_IDS.alt);
};
/**
 * @private updateWidth
 * update width attribute of the image
 * @Param updateUI: update the UI now
 * @Param shouldAdjustHeight: bool to tell if height needs to be adjusted wrt width
 * @Param setFocus: bool to tell if focus should be set after the update
 */
DwImageHud.prototype.updateWidth = function (updateUI, shouldAdjustHeight, setFocus) {
    'use strict';
    this.updateElement("width", DWLE_IMG_IDS.width, setFocus);
    if (this.imgAspectRatioLockOn === true && shouldAdjustHeight === true) {
        //reset the aspect ratio of height as the width
        var widthVal = Number(document.getElementById(DWLE_IMG_IDS.width).value);
        var heightVal = Number(document.getElementById(DWLE_IMG_IDS.height).value);
        if ((widthVal !== isNaN) && (heightVal !== isNaN) && (widthVal > 0) && (heightVal > 0)) {
            var widthPercent = Math.round(((widthVal * 100) / this.imageOrigSize.width));
            var newHeight = Math.round(((this.imageOrigSize.height * widthPercent) / 100));
            document.getElementById(DWLE_IMG_IDS.height).value = newHeight;
            this.updateElement("height", DWLE_IMG_IDS.height, false);
        }
    }
    
    if (updateUI === true) {
        AuxiliaryExtensionObject.prototype.elementDimensionChanged.call(this);
        this.focusHudField(DWLE_IMG_IDS.width);
    }
};
/**
 * @private updateHeight
 * update height attribute of the image
 * @Param updateUI: update the UI now
 * @Param shouldAdjustWidth: bool to tell if width needs to be adjusted wrt height
 * @Param setFocus: bool to tell if focus should be set after the update
 */
DwImageHud.prototype.updateHeight = function (updateUI, shouldAdjustWidth, setFocus) {
    'use strict';
    this.updateElement("height", DWLE_IMG_IDS.height, setFocus);
    if (this.imgAspectRatioLockOn === true && shouldAdjustWidth === true) {
        //reset the aspect ratio of height as the width
        var widthVal = Number(document.getElementById(DWLE_IMG_IDS.width).value);
        var heightVal = Number(document.getElementById(DWLE_IMG_IDS.height).value);
        if ((widthVal !== isNaN) && (heightVal !== isNaN) && (widthVal > 0) && (heightVal > 0)) {
            var heightPercent = Math.round(((heightVal * 100) / this.imageOrigSize.height));
            var newWidth = Math.round(((this.imageOrigSize.width * heightPercent) / 100));
            document.getElementById(DWLE_IMG_IDS.width).value = newWidth;
            this.updateElement("width", DWLE_IMG_IDS.width, false);
        }
    }
    if (updateUI === true) {
        AuxiliaryExtensionObject.prototype.elementDimensionChanged.call(this);
        this.focusHudField(DWLE_IMG_IDS.height);
	}
};
/**
 * @private updateTarget
 * update target attribute of the image
 * @Param none
 */
DwImageHud.prototype.updateTarget = function () {
    'use strict';

    var elem = this.getCurrentElement();
    if (!elem) {
        return;
    }
    var parent = elem.parentNode;
    if (parent.tagName === "A") {
        var value = document.getElementById(DWLE_IMG_IDS.target).value;
        if (value !== "none") {
            parent.setAttribute("target", value);
        } else {
            value = "";
            parent.removeAttribute("target");
        }

        var self = this;
        var funcCallback = function () {
            if (self.fileSavePending > 1) {
                self.fileSavePending--;
                if (self.fileSavePending === 1) {
                    window.parent.DWSaveDocument();
                    self.fileSavePending--;
                }
            }
        };
        if (this.fileSavePending >= 1) {
            this.fileSavePending++;
        }
        var imageTagId = elem.getAttribute(DWConstants.DWUniqueId);
        if (imageTagId) {
            dwObject.updateDWDocumentElementAttr(parent, 'target', value, funcCallback, imageTagId);
        }
        dwObject.logHeadlightsData(DWLE_IMAGEHUD_HEADLIGHTS.ELV_IH, DWLE_IMAGEHUD_HEADLIGHTS.TARGET);
    } else {
        return;
    }
};
/**
 * @private updateResponsiveClass
 * update class attribute with img-responsive class
 * @Param none
 */
DwImageHud.prototype.updateResponsiveClass = function (checkboxId) {
    'use strict';
    var classNamesToSet = [],
        classNamesToRemove = [];
    
    var responsiveElem = document.getElementById(checkboxId);
    if (!responsiveElem) {
        return;
    }
        
    if (responsiveElem.checked === true) {
        classNamesToSet.push(responsiveElem.value);
        dwObject.logHeadlightsData(DWLE_IMAGEHUD_HEADLIGHTS.RWD_BOOTSTRAP, DWLE_IMAGEHUD_HEADLIGHTS.IMAGE_RESPONSIVE, DWLE_IMAGEHUD_HEADLIGHTS.RWD);
    } else {
        classNamesToRemove.push(responsiveElem.value);
    }
    
    this.updateClass(classNamesToSet, classNamesToRemove);
    AuxiliaryExtensionObject.prototype.elementDimensionChanged.call(this);
};
/**
 * @private updateClipToShapeClass
 * update class attribute with any of the 3 Bootstrap Clip to shape class
 * @Param none
 */
DwImageHud.prototype.updateClipToShapeClass = function (event) {
    'use strict';
    var classNamesToSet = [],
        classNamesToRemove = [];
    if (!event || !event.target) {
        return;
    }
    var clickedElem = document.getElementById(event.target.id);
     
    if (!clickedElem) {
        return;
    }
    clickedElem.classList.toggle(DWLE_IMG_CLASS.ImgSelected);
    clickedElem.parentElement.classList.toggle(clickedElem.selectedclass);
    if (clickedElem.classList.contains(DWLE_IMG_CLASS.ImgSelected)) {
        classNamesToSet.push(clickedElem.value);
        if (DWLE_IMG_IDS.clipToShapeCircle === clickedElem.id) {
            dwObject.logHeadlightsData(DWLE_IMAGEHUD_HEADLIGHTS.RWD_BOOTSTRAP, DWLE_IMAGEHUD_HEADLIGHTS.CIRCLE, DWLE_IMAGEHUD_HEADLIGHTS.RWD);
        } else if (DWLE_IMG_IDS.clipToShapeRounded === clickedElem.id) {
            dwObject.logHeadlightsData(DWLE_IMAGEHUD_HEADLIGHTS.RWD_BOOTSTRAP, DWLE_IMAGEHUD_HEADLIGHTS.ROUNDED, DWLE_IMAGEHUD_HEADLIGHTS.RWD);
        } else if (DWLE_IMG_IDS.clipToShapeThumbnail === clickedElem.id) {
            dwObject.logHeadlightsData(DWLE_IMAGEHUD_HEADLIGHTS.RWD_BOOTSTRAP, DWLE_IMAGEHUD_HEADLIGHTS.THUMBNAIL, DWLE_IMAGEHUD_HEADLIGHTS.RWD);
        }
    }
    
    var clipToShapeElements = document.getElementsByName(CONSTANTS.ClipToShapeRadioGroup);
    if (!clipToShapeElements || clipToShapeElements.length === 0) {
        return;
    }
    
    var i;
    for (i = 0; i < clipToShapeElements.length; ++i) {
        if (classNamesToSet.length === 0) {
            classNamesToRemove.push(clipToShapeElements[i].value);
            clipToShapeElements[i].classList.remove(DWLE_IMG_CLASS.ImgSelected);
            clipToShapeElements[i].parentElement.classList.remove(clipToShapeElements[i].selectedclass);
        } else {
            if (clipToShapeElements[i].id !== clickedElem.id) {
                classNamesToRemove.push(clipToShapeElements[i].value);
                clipToShapeElements[i].classList.remove(DWLE_IMG_CLASS.ImgSelected);
                clipToShapeElements[i].parentElement.classList.remove(clipToShapeElements[i].selectedclass);
            }
        }
    }
    
    
    this.updateClass(classNamesToSet, classNamesToRemove);
    AuxiliaryExtensionObject.prototype.elementDimensionChanged.call(this);
};
/**
 * @private updateClass
 * update class attribute with adding classes in classNamesToSet and removing classes in classNamesToRemove
 * @Param classNamesToSet class names to be added
 * @Param classNamesToRemove class names to be removed
 */
DwImageHud.prototype.updateClass = function (classNamesToSet, classNamesToRemove) {
    'use strict';
    var elem = this.getCurrentElement();
    
    var classListHasChanged  = false, hasClass = false;
    var i;
    for (i = 0; i < classNamesToSet.length; ++i) {
        hasClass = elem.classList.contains(classNamesToSet[i]);
        if (!hasClass) {
            elem.classList.add(classNamesToSet[i]);
            classListHasChanged = true;
        }
    }
    for (i = 0; i < classNamesToRemove.length; ++i) {
        hasClass = elem.classList.contains(classNamesToRemove[i]);
        if (hasClass) {
            elem.classList.remove(classNamesToRemove[i]);
            classListHasChanged = true;
        }
    }
    var updatedClassList = elem.getAttribute("class");
    
    if (classListHasChanged) {
        var self = this;
        var funcCallback = function () {
            if (self.fileSavePending > 1) {
                self.fileSavePending--;
                if (self.fileSavePending === 1) {
                    window.parent.DWSaveDocument();
                    self.fileSavePending--;
                }
            }
        };
        
        if (this.fileSavePending >= 1) {
            this.fileSavePending++;
        }
        dwObject.updateDWDocumentElementAttr(this.m_currentSelectedElement, "class", updatedClassList, funcCallback);
        
		this.attributeChanged  = true;
    }
};
/**
 * @private updateElement
 * update given attribute of the image with the value in the input field with id attrId
 * @Param attr image attribute under edit
 * @Param attrId the id of the input field in the HUD whose value corresponds to given attribute
 * @Param setFocus bool to say whether to set focus
 */
DwImageHud.prototype.updateElement = function (attr, attrId, setFocus) {
    'use strict';
    var elem = this.getCurrentElement();
    var targetElement = document.getElementById(attrId);
    var value = targetElement.value;
    targetElement.title = value;
    var curVal = elem.getAttribute(attr);
    if ((!value || typeof value === "undefined") && (!curVal || typeof curVal === "undefined")) {
        return;
    }
    if (value !== curVal) {
        if (value && value.length) {
            elem.setAttribute(attr, value);
        } else {
            if (attr === "src") {
                elem.setAttribute(attr, "temp value to clear cached drawing of image in CEF");
            }
            elem.removeAttribute(attr);
        }
        
        var self = this;
        var funcCallback = function () {
            if (self.fileSavePending > 1) {
                self.fileSavePending--;
                if (self.fileSavePending === 1) {
                    window.parent.DWSaveDocument();
                    self.fileSavePending--;
                }
            }
        };
        
        if (this.fileSavePending >= 1) {
            this.fileSavePending++;
        }
        dwObject.updateDWDocumentElementAttr(this.m_currentSelectedElement, attr, value, funcCallback);
        if (attr === "src") {
            dwObject.logHeadlightsData(DWLE_IMAGEHUD_HEADLIGHTS.ELV_IH, DWLE_IMAGEHUD_HEADLIGHTS.SRC);
        } else if (attr === "alt") {
            dwObject.logHeadlightsData(DWLE_IMAGEHUD_HEADLIGHTS.ELV_IH, DWLE_IMAGEHUD_HEADLIGHTS.ALT);
        } else if (attr === "height") {
            dwObject.logHeadlightsData(DWLE_IMAGEHUD_HEADLIGHTS.ELV_IH, DWLE_IMAGEHUD_HEADLIGHTS.HEIGHT);
            this.imgAttrSize.height = ((value >= 0) ? value : -1);
        } else if (attr === "width") {
            dwObject.logHeadlightsData(DWLE_IMAGEHUD_HEADLIGHTS.ELV_IH, DWLE_IMAGEHUD_HEADLIGHTS.WIDTH);
            this.imgAttrSize.width = ((value >= 0) ? value : -1);
        }
		this.attributeChanged  = true;
        if (setFocus !== false) {
            targetElement.focus();
        }
    }
};

/**
 * @private validateElemValue
 * input Text for width and height needs to be integers.
 * Also update the element tooltip if value is not valid.
 * @Param elem     : the element whose value to be validated
 */
DwImageHud.prototype.validateElemValue = function (elem) {
    'use strict';
    if (!elem || elem.value === undefined || elem.value.length === 0) {
        return;
    }
   
    var dotCharacter = ".";
    if (elem.value.indexOf(dotCharacter) !== -1) {
        elem.invalid = true;
        elem.title = this.locStrings.NotAValidValue;
    } else {
        elem.title = elem.value;
        elem.invalid = false;
    }
};

/**
 * @private validateInputText
 * input Text for width and height needs to be numeric.
 * @Param evt     : keystroke event that we received.
 */
DwImageHud.prototype.validateInputText = function (evt) {
    'use strict';
    var theEvent = evt || window.event;
    var key = theEvent.keyCode || theEvent.which;
    key = String.fromCharCode(key);
    var regex = /[0-9]/;
    if (!regex.test(key)) {
        theEvent.returnValue = false;
        if (theEvent.preventDefault) {
            theEvent.preventDefault();
        }
    }
};


var initDwImageHud = function () {
    'use strict';
    window.dwImageHudObj = new DwImageHud();
    window.dwImageHudObj.initialize();
};

var desposeDwImageHud = function () {
    'use strict';
    
    dwExtensionController.removeListener(DW_EXTENSION_EVENT.ELEMENT_DIMENSION_CHANGED, window.dwImageHudObj.repositionHUD);
    dwExtensionController.removeListener(parent.DW_EVENTS.DisableExtensions, window.dwImageHudObj.commit);
    dwExtensionController.removeListener(parent.DW_EVENTS.SelectionChanged, window.dwImageHudObj.SelectionChangedMessageHandler);
};

DwImageHud.prototype.removeHudListeners = function () {
    'use strict';
       
    this.InputElementSrcBtn.removeEventListener("keyup", this.invokeSelectSoureDialogOnKeyUpBind, true);
    this.InputElementLinkBtn.removeEventListener("keyup", this.invokeSelectLinkDialogOnKeyUpBind, true);
    this.InputElementAspectRatioBtn.removeEventListener("keyup", this.handleAspectRatioBtnOnKeyUpBind, true);
    if (this.showBootstrapComponents) {
        this.RadioCircleBtn.removeEventListener("keyup", this.handleUpdateClipToShapeOnKeyUpBind, true);
        this.RadioRoundedBtn.removeEventListener("keyup", this.handleUpdateClipToShapeOnKeyUpBind, true);
        this.RadioThumbnailBtn.removeEventListener("keyup", this.handleUpdateClipToShapeOnKeyUpBind, true);
        this.ResponsiveCBElement.removeEventListener("keyup", this.handleUpdateResponsiveClassOnKeyUpBind, true);
    }
};
