/**
 * Import content box as a dependency
 */
import ContentBuilder from "./contentbuilder";

/**
 * Function to get the current script path
 *
 * source: https: //stackoverflow.com/questions/2255689/how-to-get-the-file-path-of-the-currently-executing-javascript-code
 */
function currentScriptPath() {
    var scripts = document.querySelectorAll('script[src]');
    var currentScript = scripts[scripts.length - 1].src;
    var currentScriptChunks = currentScript.split('/');
    var currentScriptFile = currentScriptChunks[currentScriptChunks.length - 1];

    return currentScript.replace(currentScriptFile, '');
}

/**
 * Handle the language file output
 */
function out(s) {

    // Language variables
    var bLangFile = false;
    if (typeof _txt !== 'undefined') {
        bLangFile = true;
    }

    if (bLangFile) {
        var result = _txt[s];
        if (result) return result;
        else return s;
    } else {
        return s;
    }
}

/**
 * Make id
 *
 * source: http://stackoverflow.com/questions/1349404/generate-a-string-of-5-random-characters-in-javascript
 */
function makeid() {
    var text = "";
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    for (var i = 0; i < 2; i++)
        text += possible.charAt(Math.floor(Math.random() * possible.length));

    var text2 = "";
    var possible2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    for (var i = 0; i < 5; i++)
        text2 += possible2.charAt(Math.floor(Math.random() * possible2.length));

    return text + text2;
};

/**
 * Apply box image
 *
 * @param s
 */
function applyBoxImage(s) {
    jQuery(".is-wrapper").data("contentbox").boxImage(s);
}

/**
 * Apply typography
 *
 * @param className
 * @param contentCss
 * @param pageCss
 */
function applyTypography(className, contentCss, pageCss) {
    jQuery(".is-wrapper").data("contentbox").boxTypography(className, contentCss, pageCss);
}

/**
 * Cleanup unused
 */
function cleanupUnused() {

    var links = document.getElementsByTagName("link");
    for (var i = 0; i < links.length; i++) {

        //Remove unused google font links
        var src = jQuery(links[i]).attr('href');
        if (src.indexOf('googleapis') != -1) {

            //get fontname
            src = src.replace(/\+/g, ' ').replace(/%20/g, ' ');
            var fontname = src.substr(src.indexOf('family=') + 7);
            if (fontname.indexOf(':') != -1) {
                fontname = fontname.split(':')[0];
            }
            fontname = fontname.toLowerCase();

            //check if fontname used in content
            var exist = false;
            var tmp = jQuery(".is-wrapper").html().toLowerCase();
            var count = tmp.split(fontname).length;
            if (count >= 3) exist = true;

            if (! exist) {
                //jQuery(links[i]).attr('data-rel', '_del');
                var attr = jQuery(links[i]).attr('data-protect');
                if (typeof attr !== typeof undefined && attr !== false) {
                    //do not delete
                } else {
                    jQuery(links[i]).attr('data-rel', '_del');
                }
            }
        }
    }

    //Cleanup unused contentstyles
    var links = document.getElementsByTagName("link");
    for (var i = 0; i < links.length; i++) {

        if (jQuery(links[i]).attr('data-name') == 'contentstyle') {

            var classname = jQuery(links[i]).attr('data-class');

            //check if classname used in content
            if (classname == '') {//prevent problem if classname is empty (incorrect json data)
                jQuery(links[i]).attr('data-rel', '_del');
            }
            if (classname != '') {
                if (jQuery(".is-wrapper").find('.' + classname).length == 0) {
                    jQuery(links[i]).attr('data-rel', '_del');
                }
            }
        }
    }

    jQuery('[data-rel="_del"]').remove();

    /*Cleanup duplicate contentstyles.
    Possible duplicates can happen when adding new section with embedded contentstyles.
    If .sectionCss() is used (which in app/example will be added in <head>) then there will be duplicates (because it reads all contentstyles (type-*.css) and returned in .sectionCss().
    If .sectionCss() is NOT used, then there will be no duplicates.

    This cleanup is applicable when there is actual duplication found. All duplicates within .is-wrapper will be removed to make the .html() clean.
    If .sectionCss() is NOT used, all contentstyles embedded in .is-wrapper will stay.
    So there will be no problem whether .sectionCss() is used or not and no change needed on section templates(can still use embedded contentstyles)!

    How about basetype-*.css? basetype-*.css always included once (by cleanup previous basetype-*.css include). It only used if enableContentStyle is set true. And for this (enableContentStyle=true), .mainCss() method MUST BE USED.
    */
    jQuery("head").children('link').each(function () {

        var src = jQuery(this).attr('href');

        jQuery(".is-wrapper").children('link').each(function () {
            if (src == jQuery(this).attr('href')) {
                jQuery(this).attr('data-rel', '_del');
            }
        });

    });

    jQuery('[data-rel="_del"]').remove();
}

/**
 * Define the svg icons used in the sidebar
 *
 * @returns {string}
 */
function getSidebarSvgDefinitions() {
    return `
        <svg width="0" height="0" style="position:absolute">
            <defs>
                <symbol viewBox="0 0 512 512" id="ion-android-add">
                    <path d="M416 277.333H277.333V416h-42.666V277.333H96v-42.666h138.667V96h42.666v138.667H416v42.666z"></path>
                </symbol>
                <symbol viewBox="0 0 512 512" id="cb-android-list">
                    <path d="M408 64H104c-22.091 0-40 17.908-40 40v304c0 22.092 17.909 40 40 40h304c22.092 0 40-17.908 40-40V104c0-22.092-17.908-40-40-40zM304 368H144v-48h160v48zm64-88H144v-48h224v48zm0-88H144v-48h224v48z"></path>
                </symbol>
                <symbol viewBox="0 0 512 512" id="ion-code">
                    <path d="M168 392a23.929 23.929 0 0 1-16.971-7.029l-112-112c-9.373-9.373-9.373-24.569 0-33.941l112-112c9.373-9.372 24.568-9.372 33.941 0 9.371 9.372 9.371 24.568 0 33.941L89.941 256l95.029 95.029c9.371 9.373 9.371 24.568 0 33.941A23.925 23.925 0 0 1 168 392zM344 392a23.929 23.929 0 0 0 16.971-7.029l112-112c9.373-9.373 9.373-24.569 0-33.941l-112-112c-9.373-9.372-24.568-9.372-33.941 0-9.371 9.372-9.371 24.568 0 33.941L422.059 256l-95.029 95.029c-9.371 9.373-9.371 24.568 0 33.941A23.925 23.925 0 0 0 344 392z"></path>
                </symbol>
                <symbol viewBox="0 0 512 512" id="ion-edit">
                    <path d="M163 439.573l-90.569-90.569L322.78 98.656l90.57 90.569zM471.723 88.393l-48.115-48.114c-11.723-11.724-31.558-10.896-44.304 1.85l-45.202 45.203 90.569 90.568 45.202-45.202c12.743-12.746 13.572-32.582 1.85-44.305zM64.021 363.252L32 480l116.737-32.021z"></path>
                </symbol>
                <symbol viewBox="0 0 512 512" id="ion-ios-browsers-outline">
                    <path d="M64 144v304h303.9V144H64zm287.9 288H80V160h271.9v272z"></path>
                    <path d="M448 64H144v64h16V80h272v272h-48v16h64z"></path>
                </symbol>
                <symbol viewBox="0 0 2048.0 2048.0" id="icon-snippets">
                    <g id="document" transform="matrix(1,0,0,1,1024.0,1024.0)">\t\t\t
                        <path d="M-727.581,329.502 L318.058,329.502 L318.058,-527.853 L-727.581,-527.853 L-727.581,329.502 Z " fill="#aaaaaa" fill-opacity="1.00" stroke-width="85.63" stroke="#000000" stroke-linecap="square" stroke-linejoin="miter" />\t\t\t
                        <path d="M-347.749,652.594 L697.89,652.594 L697.89,-204.761 L-347.749,-204.761 L-347.749,652.594 Z " fill="#aaaaaa" fill-opacity="1.00" stroke-width="85.63" stroke="#000000" stroke-linecap="square" stroke-linejoin="miter" />\t\t
                    </g>
                </symbol>
            </defs>
        </svg>
    `;
}

/**
 * Sidebar Design panel
 *
 * @returns {string}
 */
function getSidebarDesignPanel() {
    return `
        <div id="divSidebarSections" class="is-sidebar-content" style="-webkit-transition-duration:0.2s;transition-duration:0.2s;">
            <div>
                <iframe id="ifrIdeasPanel" src="about:blank" style="width:100%;height:100%;box-sizing:border-box;border:none;"></iframe>
            </div>
        </div>
    `;
}

/**
 * Sidebar snippets panel
 *
 * @returns {string}
 */
function getSidebarSnippetsPanel() {
    return `
        <div id="divSidebarSnippets" class="is-sidebar-content" style="max-width:275px; border-left: transparent 50px solid; box-sizing: border-box;"></div>
    `;
}

/**
 * Sidebar source code panel
 *
 * @returns {string}
 */
function getSidebarSourceCodePanel() {
    return '<div id="divSidebarSource" class="is-sidebar-content" style="-webkit-transition-duration:0.2s;transition-duration:0.2s;">'
        + '<div>'
        + '<div style="position:absolute;width:240px;height:35px;right:10px;top:7px;z-index:1;">'
        + '<button title="' + out('Cancel') + '" id="btnViewHtmlCancel" class="secondary"> ' + out('Cancel') + ' </button>'
        + '<button title="' + out('Ok') + '" id="btnViewHtmlOk" class="primary"> ' + out('Ok') + ' </button>'
        + '</div>'
        + '<div style="height:100%;box-sizing:border-box;border-top:#f3f3f3 50px solid;position:relative">'
        + '<textarea id="inpViewHtml" style="width:100%;height:100%;resize: none;"></textarea>'
        + '<button title="' + out('Enlarge') + '" class="edit-html-larger" style="width:40px;height:40px;position:absolute;right:20px;top:0;background:#fff;padding: 0;"><svg class="is-icon-flex" style="width:22px;height:22px;fill:rgb(170, 170, 170);"><use xlink:href="#ion-arrow-expand"></use></svg></button>'
        + '</div>'
        + '</div>'
        + '</div>';
}

/**
 * Sidebar styles panel
 *
 * @returns {string}
 */
function getSidebarStylesPanel() {
    return `
        <div id="divSidebarTypography" class="is-sidebar-content" style="-webkit-transition-duration:0.2s;transition-duration:0.2s;">
            <div>
                <iframe id="ifrTypographyPanel" src="about:blank" style="width:100%;height:100%;box-sizing:border-box;border:none;"></iframe>
            </div>
        </div>
    `;
}

/**
 * Sidebar custom panel 1
 *
 * @returns {string}
 */
function getSidebarCustomPanel1() {
    return `
        <div id="divCustomSidebarArea1" class="is-sidebar-content" style="max-width:500px;">
            <div style="padding:0 0 0 50px;box-sizing:border-box;">
                <iframe id="ifrCustomSidebarArea1" src="about:blank" style="width:100%;height:100%;box-sizing:border-box;border:none;"></iframe>
            </div>
        </div>
    `;
}

/**
 * Sidebar custom panel 2
 *
 * @returns {string}
 */
function getSidebarCustomPanel2() {
    return `
        <div id="divCustomSidebarArea2" class="is-sidebar-content" style="max-width:500px;">
            <div style="padding:0 0 0 50px;box-sizing:border-box;">
            <iframe id="ifrCustomSidebarArea2" src="about:blank" style="width:100%;height:100%;box-sizing:border-box;border:none;"></iframe>
            </div>
        </div>
    `;
}

/**
 * Delete section modal
 *
 * @returns {string}
 */
function getDeleteSectionModal() {
    return '<div class="is-modal delsectionconfirm">'
        + '<div style="max-width: 400px;">'
        + '<p style="margin-bottom: 25px;text-align:center;">' + out('Are you sure you want to delete this section?') + '</p>'
        + '<button title="' + out('Delete') + '" class="input-ok classic">' + out('Delete') + '</button>'
        + '</div>'
        + '</div>';
}

/**
 * Edit section modal
 *
 * @returns {string}
 */
function getEditSectionModal() {
    return `
        <div class="is-modal editsection">

            <div style="max-width:526px;">

                <div class="is-modal-bar is-draggable" style="padding: 1rem;">
                    Section Settings
                </div>

                <div class="is-modal-body" style="padding: 1rem;">

                    <div class="form-group is-settings">
                        <label>Move Section</label>
                        <div style="display: flex;">
                            <button class="cmd-section-up" title="Move Up" style="">
                                &#8593;
                            </button>
                            <button class="cmd-section-down" title="Move Down" style="border-left:none;">
                                &#8595;
                            </button>
                            <button class="cmd-section-top" title="Move to Top" style="border-left:none;">
                                <span style="transform:rotate(90deg); position:absolute; top:13px; left:15px;">&#8676;</span>
                            </button>
                            <button class="cmd-section-bottom" title="Move to Bottom" style="border-left:none;">
                                <span style="transform:rotate(90deg); position:absolute; top:13px; left:15px;">&#8677;</span>
                            </button>
                        </div>
                    </div>

                    <div class="form-group is-settings">
                        <div>Section Height</div>
                        <div>
                            <input class="section-height-fixed" type="text" style="width:33.33%; height:45px; text-align:center; font-size:12px;" />
                            <button class="section-height-auto" style="width:33.33%;">Auto</button>
                            <button class="section-height-full" style="width:33.33%;">Full</button>
                            <br style="clear:both">
                        </div>
                    </div>

                    <div class="form-group is-settings">
                        <div>Scroll Icon</div>
                        <div style="display: flex; align-items: center;">
                            <label for="chkScrollIcon" style="margin:0 1rem 0 0;">
                                <input id="chkScrollIcon" type="checkbox" />
                                Show
                            </label>
                            <button
                                title="Light Icon"
                                class="cmd-section-scroll"
                                data-value="light"
                            >
                                Light
                            </button>
                            <button
                                title="Dark Icon"
                                class="cmd-section-scroll"
                                data-value="dark"
                                style="border-left:none;"
                            >
                                Dark
                            </button>
                        </div>
                    </div>

                    <hr style="margin-top: 2rem;"/>

                    <div class="form-group">
                        <label for="separator-style">Separator Style</label>
                        <select id="separator-style" class="form-control custom-select" style="min-height: 45px;">
                            <option value="">-- Please Select --</option>
                            <option value="separator-chevron">Chevron</option>
                            <option value="separator-chevron-up">Chevron Up</option>
                            <option value="separator-chevron-down">Chevron Down</option>
                            <option value="separator-chevron-inverted">Chevron Inverted</option>
                            <option value="separator-points">Points</option>
                            <option value="separator-spikes">Spikes</option>
                            <option value="separator-slant-left">Slant Left</option>
                            <option value="separator-slant-right">Slant Right</option>
                            <option value="separator-skew-left">Skew Left</option>
                            <option value="separator-skew-right">Skew Right</option>
                            <option value="separator-zigzags">Zig Zags</option>
                        </select>
                    </div>

                    <div class="form-group">
                        <label for="separator-direction">Separator Direction</label>
                        <select id="separator-direction" class="form-control custom-select" style="min-height: 45px;">
                            <option value="">-- Please Select --</option>
                            <option value="separator-top">Top</option>
                            <option value="separator-bottom">Bottom</option>
                            <option value="separator-both">Both</option>
                        </select>
                    </div>

                    <div class="form-group">
                        <label for="separator-size">Separator Size</label>
                        <select id="separator-size" class="form-control custom-select" style="min-height: 45px;">
                            <option value="">-- Please Select --</option>
                            <option value="separator-xs">Extra Small</option>
                            <option value="separator-sm">Small</option>
                            <option value="separator-md">Medium</option>
                            <option value="separator-lg">Large</option>
                        </select>
                    </div>

                    <div class="form-group">
                        <label for="separator-colour">Separator Colour</label>
                        <select id="separator-colour" class="form-control custom-select" style="min-height: 45px;">
                            <option value="">-- Please Select --</option>
                            <option value="separator-primary">Primary</option>
                            <option value="separator-secondary">Secondary</option>
                            <option value="separator-tertiary">Tertiary</option>
                            <option value="separator-quaternary">Quaternary</option>
                            <option value="separator-color-5">Color 5</option>
                            <option value="separator-color-6">Color 6</option>
                            <option value="separator-color-7">Color 7</option>
                            <option value="separator-color-8">Color 8</option>
                            <option value="separator-success">Success</option>
                            <option value="separator-danger">Danger</option>
                            <option value="separator-warning">Warning</option>
                            <option value="separator-info">Info</option>
                            <option value="separator-white">White</option>
                            <option value="separator-light">Light</option>
                            <option value="separator-dark">Dark</option>
                        </select>
                    </div>

                    <hr style="margin-top: 2rem;"/>

                    <div class="form-group">
                        <label for="section-class-list">Section Classes</label>
                        <textarea id="section-class-list" class="form-control" rows="2"></textarea>
                    </div>

                </div>

            </div>
        </div>
    `;
}

/**
 * Get edit module modal
 *
 * @returns {string}
 */
function getEditModuleModal() {
    return '<div class="is-modal editmodule">'
        + '<div style="max-width:900px;height:570px;padding:0;box-sizing:border-box;position:relative;">'
        + '<div class="is-modal-bar is-draggable" style="position: absolute;top: 0;left: 0;width: 100%;z-index:1;">' + out('Module Settings') + '</div>'

        + '<iframe style="position: absolute;top: 0;left: 0;width:100%;height:100%;border:none;border-bottom:60px solid transparent;border-top:40px solid transparent;margin:0;box-sizing:border-box;" src="about:blank"></iframe>'
        + '<input id="hidModuleCode" type="hidden" />'
        + '<input id="hidModuleSettings" type="hidden" />'

        + '<button class="input-ok classic" style="height:60px;position:absolute;left:0;bottom:0;">' + out('Ok') + '</button>'
        + '</div>'
        + '</div>';
}

/**
 * Get edit custom code modal
 *
 * @returns {string}
 */
function getEditCustomCodeModal() {
    return '<div class="is-modal editcustomcode">'
        + '<div style="max-width:900px;height:570px;padding:0;box-sizing:border-box;position:relative;">'
        + '<div class="is-modal-bar is-draggable" style="position: absolute;top: 0;left: 0;width: 100%;z-index:1;">' + out('Custom Code (Javascript Allowed)') + '</div>'

        + '<textarea id="txtBoxCustomCode" class="inptxt" style="background: #fff;position: absolute;top: 0;left: 0;width:100%;height:100%;border:none;border-bottom:60px solid transparent;border-top:40px solid transparent;box-sizing:border-box;"></textarea>'
        + '<input id="hidBoxCustomCode" type="hidden" />'
        + '<button class="cell-html-larger" style="width:35px;height:35px;position:absolute;right:0;top:0;background:transparent;z-index:2;">'
        + '<svg class="is-icon-flex" style="width:19px;height:19px;fill:rgb(170, 170, 170);"><use xlink:href="#ion-arrow-expand"></use></svg>'
        + '</button>'
        + '<button class="input-ok classic" style="height:60px;position:absolute;left:0;bottom:0;">' + out('Ok') + '</button>'

        + '</div>'
        + '</div>';
}

/**
 * Get the edit box tabs
 *
 * @returns {string}
 */
function getEditBoxTabs() {
    return `
        <div class="is-tabs clearfix">
            <a id="tabBoxGeneral" href="" data-content="divBoxGeneral" class="active">
                ${out('General')}
            </a>
            <a id="tabBoxContentContainer" href="" data-content="divBoxContentContainer">
                ${out('Content')}
            </a>
            <a id="tabBoxContentText" href="" data-content="divBoxContentText">
                ${out('Text')}
            </a>
            <a id="tabBoxImage" href="" data-content="divBoxImage">
                ${out('Image')}
            </a>
            <a id="tabBoxModule" href="" data-content="divBoxPlaceModule">
                ${out('Module')}
            </a>
            <a id="tabBoxCustomHtml" href="" data-content="divBoxCustomHtml" style="display:none">
                ${out('HTML')}
            </a>
        </div>
    `;
}

/**
 * Get the edit box general tab
 *
 * @returns {string}
 */
function getEditBoxGeneralTab() {
    return `
        <div id="divBoxGeneral" class="is-tab-content" data-group="boxsettings" style="display:block">

            <div id="divBoxSize" class="is-settings">
                <div>${out('Box Size')}:</div>
                <div>
                    <button title="${out('Decrease')}" class="cmd-box-smaller">-</button>
                    <button title="${out('Increase')}" class="cmd-box-larger" style="border-left:none">+</button>
                    <br style="clear:both">
                </div>
            </div>

            <div id="divContentWidth" class="is-settings">
                <div>${out('Content Width')}:</div>
                <div>
                    <input class="inp-box-width" type="text" style="width:50%; height:45px; text-align:center; font-size:12px;" />
                    <button class="cmd-box-width" style="width:50%; border-top:none">Full Width</button>
                    <br style="clear:both">
                </div>
            </div>

            <div id="divBoxContainer" class="is-settings">
                <div>${out('Content Padding')}:</div>
                <div>
                    <button title="${out('Default')}" class="cmd-box-default-padding" style="width: 33.33%;">Default</button>
                    <button title="${out('Custom')}" class="cmd-box-custom-padding" style="width: 33.33%;">Custom</button>
                    <button title="${out('None')}" class="cmd-box-no-padding" style="width: 33.33%; border-left:none">None</button>
                    <br style="clear:both">
                </div>
            </div>
            <div id="divBoxCustomPadding" style="display: none; align-items: center; min-height: 45px; margin-bottom: 20px;">
                <div style="margin-right: 2px;">
                    <label>Top</label>
                    <input class="input-padding-top" type="text" placeholder="0" style="width:100%;"/>
                </div>
                <div style="margin-right: 2px;">
                    <label>Right</label>
                    <input class="input-padding-right" type="text" placeholder="0" style="width:100%;"/>
                </div>
                <div style="margin-right: 2px;">
                    <label>Bottom</label>
                    <input class="input-padding-bottom" type="text" placeholder="0" style="width:100%;"/>
                </div>
                <div style="margin-right: 2px;">
                    <label>Left</label>
                    <input class="input-padding-left" type="text" placeholder="0" style="width:100%;"/>
                </div>
            </div>

            <div id="divBoxBackgroundColor" class="is-settings clearfix" style="margin-bottom:2px;">
                <div>${out('Background Color')}:</div>

                <div>
                    <button title="${out('Light')}" class="cmd-box-bgcolor" data-value="light"></button>
                    <button title="${out('Grey')}" class="cmd-box-bgcolor" data-value="grey" style="border-left:none; background:#eee;"></button>
                    <button title="${out('Dark')}" class="cmd-box-bgcolor" data-value="dark" style="border:transparent 1px solid; background:#333; color:#fff"></button>

                    <input type="hidden" id="inpBoxBgColor" value=""/>
                    <button class="cmd-box-pickbgcolor" data-value="dark" style="border-left:none;">
                        <span style="display:block; margin-top:-2px;">&#9681;</span>
                    </button>
                    <button title="${out('Clear')}" class="cmd-box-bgcolor" style="border-left:none;" data-value="">
                        &#10005;
                    </button>
                </div>

                <div style="margin-top:20px;">
                    <button title="${out('Primary')}" class="cmd-box-bgcolor bg-primary" data-value="primary">P</button>
                    <button title="${out('Secondary')}" class="cmd-box-bgcolor bg-secondary" data-value="secondary">S</button>
                    <button title="${out('Tertiary')}" class="cmd-box-bgcolor bg-tertiary" data-value="tertiary">T</button>
                    <button title="${out('Quaternary')}" class="cmd-box-bgcolor bg-quaternary" data-value="quaternary">Q</button>
                </div>

                <div style="margin-top:20px;">
                    <button title="${out('Gradient')}" class="cmd-box-gradient" data-value="+" style="width:100%; font-size: 14px;">
                    ${out('Gradient')}
                </button>
                </div>
            </div>

            <div id="divBoxPickPhoto" class="is-settings" style="margin-bottom:0;">
                <button class="cmd-box-pickphoto" data-value="" style="width:100%">
                    <svg class="is-icon-flex" style="">
                        <use xlink:href="#ion-image"></use>
                    </svg>
                </button>
                <br style="clear:both">
            </div>

            <p id="divNoBoxSettings" style="text-align: center; display:none;">
                ${out('This box has no available settings.')}
            </p>
        </div>
    `;
}

/**
 * Get the edit box content tab
 *
 * @returns {string}
 */
function getEditBoxContentTab() {
    return `
        <div id="divBoxContentContainer" class="is-tab-content" data-group="boxsettings">

            <div class="is-settings">
                <div>${out('Position')}:</div>
                <div style="margin-bottom:0">
                    <button title="${out('Top Left')}" class="cmd-box-content-pos" data-value="topleft">&#8598;</button>
                    <button title="${out('Top Center')}" class="cmd-box-content-pos" data-value="topcenter" style="border-left:none;">&#8593;</button>
                    <button title="${out('Top Right')}" class="cmd-box-content-pos" data-value="topright" style="border-left:none;">&#8599;</button>
                </div>
                <div style="margin-bottom:0">
                    <button title="${out('Middle Left')}" class="cmd-box-content-pos" data-value="middleleft" style="border-top:none;">&#8592;</button>
                    <button title="${out('Middle Center')}" class="cmd-box-content-pos" data-value="middlecenter" style="border-left:none; border-top:none;">&#9737;</button>
                    <button title="${out('Middle Right')}" class="cmd-box-content-pos" data-value="middleright" style="border-left:none; border-top:none;">&#8594;</button>
                </div>
                <div>
                    <button title="${out('Bottom Left')}" class="cmd-box-content-pos" data-value="bottomleft" style="border-top:none;">&#8601;</button>
                    <button title="${out('Bottom Center')}" class="cmd-box-content-pos" data-value="bottomcenter" style="border-left:none; border-top:none;">&#8595;</button>
                    <button title="${out('Bottom Right')}" class="cmd-box-content-pos" data-value="bottomright" style="border-left:none; border-top:none;">&#8600;</button>
                </div>
            </div>

            <div class="is-settings">
                <div>${out('Top/Bottom Adjustment')}:</div>
                <div>
                    <button title="${out('Decrease')}" class="cmd-box-content-edge-y" data-value="-">-</button>
                    <button title="${out('Increase')}" class="cmd-box-content-edge-y" data-value="+" style="border-left:none;">+</button>
                    <button title="${out('Not Set')}" class="cmd-box-content-edge-y" data-value="" style="border-left:none; width: 75px;">
                        ${out('Not Set')}
                    </button>
                </div>
            </div>

            <div class="is-settings" style="margin-bottom:0">
                <div>${out('Left/Right Adjustment')}:</div>
                <div>
                    <button title="${out('Decrease')}" class="cmd-box-content-edge-x" data-value="-">-</button>
                    <button title="${out('Increase')}" class="cmd-box-content-edge-x" data-value="+" style="border-left:none;">+</button>
                    <button title="${out('Not Set')}" class="cmd-box-content-edge-x" data-value="" style="border-left:none; width: 75px;">
                        ${out('Not Set')}
                    </button>
                </div>
            </div>

        </div>
    `;
}

/**
 * Get the edit box text tab
 *
 * @returns {string}
 */
function getEditBoxTextTab(object) {
    let html = `
        <div id="divBoxContentText" class="is-tab-content" data-group="boxsettings">

            <div class="is-settings">
                <div>${out('Text Style')}:</div>
                <div>
                    <button title="${out('Light')}" class="cmd-box-textcolor" data-value="light">${out('Light')}</button>
                    <button title="${out('Dark')}" class="cmd-box-textcolor" data-value="dark" style="border-left:none;">${out('Dark')}</button>
                    <button title="${out('Not Set')}" class="cmd-box-textcolor" data-value="" style="border-left:none;">${out('Not Set')}</button>
                    <br style="clear:both">
                </div>
            </div>

            <div class="is-settings">
                <div>${out('Transparency')}:</div>
                <div>
                    <button title="${out('Increase')}" class="cmd-box-textopacity" data-value="+"> + </button>
                    <button title="${out('Decrease')}" class="cmd-box-textopacity" data-value="-" style="border-left:none;"> - </button>
                    <button title="${out('Not Set')}" class="cmd-box-textopacity" data-value="" style="border-left:none;">${out('Not Set')}</button>
                    <br style="clear:both">
                </div>
            </div>

            <div class="is-settings">
                <div>Align:</div>
                <div>
                    <button title="${out('Align Left')}" class="cmd-box-textalign" data-value="left">
                        <svg class="is-icon-flex" style="fill:rgba(0, 0, 0, 0.8); margin-top:3px; width:14px; height:14px;">
                            <use xlink:href="#icon-align-left"></use>
                        </svg>
                    </button>
                    <button title="${out('Align Center')}" class="cmd-box-textalign" data-value="center" style="border-left:none;">
                        <svg class="is-icon-flex" style="fill:rgba(0, 0, 0, 0.8); margin-top:3px; width:14px; height:14px;">
                            <use xlink:href="#icon-align-center"></use>
                        </svg>
                    </button>
                    <button title="${out('Align Right')}" class="cmd-box-textalign" data-value="right" style="border-left:none;">
                        <svg class="is-icon-flex" style="fill:rgba(0, 0, 0, 0.8); margin-top:3px; width:14px; height:14px;">
                            <use xlink:href="#icon-align-right"></use>
                        </svg>
                    </button>
                    <button title="${out('Align Full')}" class="cmd-box-textalign" data-value="justify" style="border-left:none;">
                        <svg class="is-icon-flex" style="fill:rgba(0, 0, 0, 0.8); margin-top:3px; width:14px; height:14px;">
                            <use xlink:href="#icon-align-full"></use>
                        </svg>
                    </button>
                    <br style="clear:both">
                </div>
            </div>
        `;

    if (object.settings.enableContentStyle) {
        html += `
            <div class="is-settings" style="margin-bottom:0">
                <div>${out('Typography')}:</div>
                <div>
                    <button title="${out('Change Style')}" class="cmd-box-typography" data-value="+" style="width:100%; font-size: 14px;">
                        ${out('Change Style')}
                    </button>
                    <br style="clear:both">
                </div>
            </div>
        `;
    }

    html += `</div>`;

    return html;
}

/**
 * Get the edit box image tab
 *
 * @returns {string}
 */
function getEditBoxImageTab(object) {
    let html = `<div id="divBoxImage" class="is-tab-content" data-group="boxsettings">`;

    html += `
        <div class="form-group type">
           <div>
                <label>Image Type</label>
           </div>
           <div style="display: flex; align-items: center;">
                <div style="margin-right: 1rem; width: 100%">
                    <button class="cmd-box-repeat" style="width:100%;">Repeat</button>
                </div>
                <div style="width: 100%">
                    <button class="cmd-box-no-repeat active" style="width:100%;">No Repeat</button>
                </div>
           </div>
        </div>
    `;

    html += `
        <div class="form-group manipulation" style="display: flex; align-items: center;">
           <div class="image-mode-block" style="margin-right: 1rem; width: 100%">
                <label>Mode</label>
                <select class="input-image-mode form-control custom-select" style="min-height: 48px; border-radius: 0;">
                    <option value="original">Use Original</option>
                    <option value="resizeFit">Resize</option>
                </select>
            </div>
            <div class="image-quality-block" style="width: 100%">
                <label>Quality</label>
                <input class="input-image-quality" type="text" placeholder="80" style="width:100%;" />
            </div>
        </div>
    `;

    html += `
        <div class="form-group dimensions" style="display: flex; align-items: center; margin-bottom: 2rem;">
            <div class="image-width-block" style="margin-right: 1rem; width: 100%">
                <label>Width</label>
                <input class="input-image-width" type="text" placeholder="150" style="width:100%;"/>
            </div>
            <div class="image-height-block" style="width: 100%">
                <label>Height</label>
                <input class="input-image-height" type="text" placeholder="150" style="width:100%;"/>
            </div>
        </div>
    `;

    html += `
        <div class="form-group" style="display: flex; align-items: center; margin-bottom: 2rem;">
            <div id="lazy-block" style="margin-right: 1rem">
                <label for="chkLazyBg" style="margin:0;">
                    <input id="chkLazyBg" type="checkbox" />
                    ${out('Lazy Load')}
                </label>
            </div>
            <div id="lightbox-block" style="margin-right: 1rem">
                <label for="chkAnimateBg" style="margin:0;">
                    <input id="chkAnimateBg" type="checkbox" />
                    ${out('Ken Burns Effect')}
                </label>
            </div>
            <div id="parallax-block">
                <label for="chkParallaxBg" style="margin:0;">
                    <input id="chkParallaxBg" type="checkbox" />
                    ${out('Parallax')}
                </label>
            </div>
        </div>
    `;

    html += `
        <div class="form-group" style="display: flex; align-items: center;">
            <div style="margin-right: 1rem; width: 100%">
                <label>Overlay Color</label>
                <div class="is-settings">
                    <button title="${out('White')}" class="cmd-box-overlaycolor" data-value="#ffffff">
                        ${out('White')}
                    </button>
                    <button title="${out('Black')}" class="cmd-box-overlaycolor" data-value="#000000" style="border-left:none;">
                        ${out('Black')}
                    </button>
                    <button class="cmd-box-pickoverlaycolor" style="border-left:none;">
                        <span style="display:block; margin-top:-2px;">&#9681;</span>
                    </button>
                    <button title="${out('None')}" class="cmd-box-overlaycolor" data-value="" style="border-left:none;">
                        ${out('None')}
                    </button>
                    <br style="clear:both">
                </div>
            </div>
            <div style="width: 100%">
                <label>Overlay Transparency</label>
                <div class="is-settings">
                    <button title="${out('Increase')}" class="cmd-box-overlayopacity" data-value="+">+</button>
                    <button title="${out('Decrease')}" class="cmd-box-overlayopacity" data-value="-" style="border-left:none;">-</button>
                    <button title="${out('None')}" class="cmd-box-overlayopacity" data-value="0" style="border-left:none;">${out('None')}</button>
                    <br style="clear:both">
                </div>
            </div>
        </div>
    `;

    html += `
        <div class="form-group" style="display: flex; align-items: center; margin-bottom:0">
            <div style="margin-right: 1rem; width: 100%">
                <label>Horizontal Position</label>
                <div class="is-settings">
                    <button title="${out('Left')}" class="cmd-bg-img-x" data-value="-">&#8592;</button>
                    <button title="${out('Right')}" class="cmd-bg-img-x" data-value="+" style="border-left:none;">&#8594;</button>
                    <button title="${out('Default')}" class="cmd-bg-img-x" data-value="" style="width:60px; border-left:none;">
                        ${out('Default')}
                    </button>
                    <br style="clear:both">
                </div>
            </div>
            <div style="width: 100%">
                <label>Vertical Position</label>
                <div class="is-settings">
                    <button title="${out('Top')}" class="cmd-bg-img-y" data-value="-">&#8595;</button>
                    <button title="${out('Bottom')}" class="cmd-bg-img-y" data-value="+" style="border-left:none;">&#8593;</button>
                    <button title="${out('Default')}" class="cmd-bg-img-y" data-value="" style="width:60px; border-left:none;">
                        ${out('Default')}
                    </button>
                    <br style="clear:both">
                </div>
            </div>
        </div>
    `;

    html += `</div>`;

    return html;
}

/**
 * Get the edit box module tab
 *
 * @returns {string}
 */
function getEditBoxModuleTab() {
    return `
        <div id="divBoxPlaceModule" class="is-tab-content" data-group="boxsettings">
            <div class="is-settings" style="margin-bottom:0">
                <div>
                    <label for="chkBgModule" style="margin:0;">
                        <input id="chkBgModule" type="checkbox" />
                        ${out('Module Placement')}
                    </label>
                </div>
            </div>
        </div>
    `;
}

/**
 * Get the edit box animate tab
 *
 * @returns {string}
 */
function getEditBoxAnimateTab() {
    return `
        <div id="divBoxAnimate" class="is-tab-content" data-group="boxsettings">
            <div class="is-settings">
                <div class="clearfix">
                    <h5>${out('Effect')}</h5>
                    <select class="cmd-box-animate" style="margin-right:12px; float:left">
                        <option value="">${out('None')}</option>
                        <option value="is-pulse">pulse</option>
                        <option value="is-bounceIn">bounceIn</option>
                        <option value="is-fadeIn">fadeIn</option>
                        <option value="is-fadeInDown">fadeInDown</option>
                        <option value="is-fadeInLeft">fadeInLeft</option>
                        <option value="is-fadeInRight">fadeInRight</option>
                        <option value="is-fadeInUp">fadeInUp</option>
                        <option value="is-flipInX">flipInX</option>
                        <option value="is-flipInY">flipInY</option>
                        <option value="is-slideInUp">slideInUp</option>
                        <option value="is-slideInDown">slideInDown</option>
                        <option value="is-slideInLeft">slideInLeft</option>
                        <option value="is-slideInRight">slideInRight</option>
                        <option value="is-zoomIn">zoomIn</option>
                    </select>
                    <label for="chkAnimOnce" style="margin:10px 0 0;">
                        <input id="chkAnimOnce" type="checkbox" />
                        ${out('Once')}
                    </label>
                </div>

                <br style="clear:both"/>

                <div class="clearfix" style="margin:10px 0 0;">
                    <h5>${out('Delay')}</h5>
                    <select class="cmd-box-animatedelay" style="margin-right:12px;">
                        <option value="">${out('None')}</option>
                        <option value="delay-0ms">0s</option>
                        <option value="delay-100ms">100ms</option>
                        <option value="delay-200ms">200ms</option>
                        <option value="delay-300ms">300ms</option>
                        <option value="delay-400ms">400ms</option>
                        <option value="delay-500ms">500ms</option>
                        <option value="delay-600ms">600ms</option>
                        <option value="delay-700ms">700ms</option>
                        <option value="delay-800ms">800ms</option>
                        <option value="delay-900ms">900ms</option>
                        <option value="delay-1000ms">1000ms</option>
                        <option value="delay-1100ms">1100ms</option>
                        <option value="delay-1200ms">1200ms</option>
                        <option value="delay-1300ms">1300ms</option>
                        <option value="delay-1400ms">1400ms</option>
                        <option value="delay-1500ms">1500ms</option>
                        <option value="delay-1600ms">1600ms</option>
                        <option value="delay-1700ms">1700ms</option>
                        <option value="delay-1800ms">1800ms</option>
                        <option value="delay-1900ms">1900ms</option>
                        <option value="delay-2000ms">2000ms</option>
                        <option value="delay-2100ms">2100ms</option>
                        <option value="delay-2200ms">2200ms</option>
                        <option value="delay-2300ms">2300ms</option>
                        <option value="delay-2400ms">2400ms</option>
                        <option value="delay-2500ms">2500ms</option>
                        <option value="delay-2600ms">2600ms</option>
                        <option value="delay-2700ms">2700ms</option>
                        <option value="delay-2800ms">2800ms</option>
                        <option value="delay-2900ms">2900ms</option>
                        <option value="delay-3000ms">3000ms</option>
                    </select>
                </div>
            </div>

            <div class="is-settings" style="margin-bottom:0">
                <div>
                    <button class="cmd-box-animate-test" style="width:100%">${out('Test')}</button>
                    <br style="clear:both">
                </div>
            </div>
        </div>
    `;
}

/**
 * Get the edit box html tab
 *
 * @returns {string}
 */
function getEditBoxHtmlTab() {
    return `
        <div id="divBoxCustomHtml" class="is-tab-content" data-group="boxsettings">
            <div class="is-settings" style="margin-bottom:0">
                <div>
                    <textarea id="inpBoxHtml" style="width:100%; height:220px; min-height:200px; border:#eee 1px solid;"></textarea>
                    <button class="cmd-box-html">${out('Apply')}</button>
                </div>
            </div>
        </div>
    `;
}

/**
 * Get edit box modal
 *
 * @returns {string}
 */
function getEditBoxModal(object) {

    // Header
    let html = `
        <div class="is-modal editbox">
            <div style="max-width:526px; padding:0">
                <div class="is-modal-bar is-draggable">${out('Box Settings')}</div>
    `;

    // Tab navigation
    html += getEditBoxTabs();

    // Tab panes
    html += getEditBoxGeneralTab();
    html += getEditBoxContentTab();
    html += getEditBoxTextTab(object);
    html += getEditBoxImageTab(object);
    html += getEditBoxModuleTab();
    html += getEditBoxHtmlTab();

    // Footer
    html += `
            </div>
        </div>
    `;

    return html;
}

/**
 * Get pick photo modal
 *
 * @returns {string}
 */
function getPickPhotoModal() {
    return '<div class="is-modal pickphoto">'
        + '<div style="max-width:1000px;height:570px;padding:0;box-sizing:border-box;position:relative;">'
        + '<div class="is-modal-bar is-draggable" style="position: absolute;top: 0;left: 0;width: 100%;z-index:1;">' + out('Photos') + '</div>'
        + '<iframe style="position: absolute;top: 0;left: 0;width:100%;height:100%;border:none;border-top:40px solid transparent;margin:0;box-sizing:border-box;" src="about:blank"></iframe>'
        + '</div>'
        + '</div>';
}

/**
 * Get apply styles modal
 *
 * @returns {string}
 */
function getApplyStylesModal() {
    return '<div class="is-modal applytypography">'
        + '<div style="max-width: 400px;text-align:center;">'
        + '<p>' + out('This page has one or more sections that have their own typography style.') + '</p>'
        + '<label><input name="rdoApplyTypoStyle" type="radio" value="1">' + out('Replace all sections\' typography style.') + '</label><br>'
        + '<label><input name="rdoApplyTypoStyle" type="radio" value="0">' + out('Keep sections\' specific typography style.') + '</label>'
        + '<p style="font-size:1rem"><i>' + out('To apply typography style on a specific section, goto \'Content Style\' tab in Box Settings') + '</i></p>'
        + '<button class="input-ok classic">' + out('Ok') + '</button>'
        + '</div>'
        + '</div>';
}

/**
 * Get the edit box tool
 *
 * @param object
 * @returns {string}
 */
function getBoxTool(object) {
    return `
        <div id="divboxtool">

            <form id="form-upload-cover"
                  data-tooltip-top
                  data-title="${out('Add Background Image')}"
                  target="frame-upload-cover"
                  method="post"
                  action="${object.settings.coverImageHandler}"
                  enctype="multipart/form-data"
                  style="position:relative; width:40px; height:40px; display:inline-block; float:left; background: #7f8c8d;"
            >
                <div style="width:40px; height:40px; overflow:hidden;">

                    <div style="position:absolute; width:100%; height:100%;">
                        <svg class="is-icon-flex" style="position: absolute; top: 12px; left: 12px; fill:rgb(255,255,255);">
                            <use xlink:href="#ion-image"></use>
                        </svg>
                    </div>

                    <input type="file"
                           title="${out('Add Background Image')}"
                           id="fileCover"
                           name="fileCover"
                           accept="image/*"
                           style="position:absolute; top:-30px; left:0; width:100%; height:80px; opacity: 0; cursor: pointer;"
                    />
                </div>

                <input id="hidcustomval" name="hidcustomval" type="hidden" value="" />
                <input class="validation" name="_token" type="hidden" value="">

                <iframe id="frame-upload-cover"
                        name="frame-upload-cover"
                        src="about:blank"
                        style="width:1px; height:1px; position:absolute; top:0; right:-100000px"
                ></iframe>
            </form>

            <div id="lnkremovecover"
                 data-tooltip-top
                 data-title="${out('Remove Background Image')}"
                 title="${out('Remove Background Image')}"
                 style="display:inline-block; width:40px; height:40px; background: #ffc048;"
            >
                <svg class="is-icon-flex" style="margin-right:-2px; margin-top:9px; fill:rgba(255,255,255,1);">
                    <use xlink:href="#ion-image"></use>
                </svg>
            </div>

            <div id="lnkeditbox"
                 data-tooltip-top
                 data-title="${out('Box Settings')}"
                 title="${out('Box Settings')}"
                 style="display:inline-block; width:40px; height:40px; background: #9b59b6;"
            >
                <svg class="is-icon-flex" style="margin-right:-2px; margin-top:9px; fill:rgba(255,255,255,1);">
                    <use xlink:href="#ion-wrench"></use>
                </svg>
            </div>

            <div id="lnkeditmodule"
                 data-tooltip-top
                 data-title="${out('Module Settings')}"
                 title="${out('Module Settings')}"
                 style="display:inline-block; width:40px; height:40px; background: #FF9800;"
            >
                <svg class="is-icon-flex" style="margin-right:-2px; margin-top:9px; fill:rgba(255,255,255,1);">
                    <use xlink:href="#ion-ios-gear"></use>
                </svg>
            </div>

        </div>
    `;
}

/**
 * Global variables used externally
 */
window.applyBoxImage = applyBoxImage;
window.applyTypography = applyTypography;

/**
 * ContentBox.js ver.4.1
 */
(function (jQuery) {

    // variables
    var $activeSection;
    var $activeBox;
    var scriptPath = currentScriptPath();
    var _fb;

    // Side snippet panel
    var bSideSnippets = false;

    /**
     * Content box object
     *
     * @param element
     * @param opts
     */
    jQuery.contentbox = function (element, opts) {

        // variables
        var hash = {};
        var hashAttr = {};
        var hashSettings = {};
        var customgradcolors = [];
        var colorpicker;

        // Main settings
        this.settings = {};

        // The element we are attached to
        var $element = jQuery(element);

        // Make sure the paths are setup
        if (! opts.apiPath || ! opts.frontendAssetPath || ! opts.backendAssetPath) {
            console.log(opts);
            alert('Box API or Asset Path not setup correctly');
        }

        // Default options
        var defaults = {

            // Grid settings
            framework: 'bootstrap',
            cellFormat: '',
            rowFormat: '',
            row: '',
            cols: [],
            colequal: [],
            colsizes: [],

            // API Paths
            apiPath: opts.apiPath,
            modulePath: opts.apiPath + '/modules/',
            designSelect: opts.apiPath + '/designs/',
            styleSelect: opts.apiPath + '/styles/',
            snippetData: opts.apiPath + '/snippets/',
            fileSelect: opts.apiPath + '/files/',
            imageSelect: opts.apiPath + '/images/',
            iconSelect: opts.apiPath + '/icons/',
            buttonSelect: opts.apiPath + '/buttons/',
            symbolSelect: opts.apiPath + '/symbols/',
            photoselect: '',

            // Asset paths
            frontendAssetPath: opts.frontendAssetPath,
            backendAssetPath: opts.backendAssetPath,
            assetPath: opts.backendAssetPath + '/',
            scriptPath: opts.backendAssetPath + '/',
            designPath: opts.frontendAssetPath + "/designs/images/",
            snippetPath: opts.frontendAssetPath + "/snippets/",
            snippetImagePath: opts.frontendAssetPath + "/snippets/images/",
            stylePath: opts.frontendAssetPath + "/styles/images/",
            styleCssPath: opts.frontendAssetPath + '/styles/css/',
            iconCssPath: opts.frontendAssetPath + '/icons/css/',
            iconFontPath: opts.frontendAssetPath + '/icons/fonts/',
            fontAssetPath: opts.backendAssetPath + '/fonts/previews/',
            pluginPath: opts.backendAssetPath + '/plugins/',
            contentStylePath: opts.frontendAssetPath + '/styles/',

            // Image settings
            imageEmbed: false,
            imageCrop: false,
            imageQuality: 0.80,
            coverImageHandler: '',
            largerImageHandler: '',

            // Style panel settings
            enableContentStyle: false,

            // Snippet category settings
            snippetCategories: [
                [120, "Basic"],
                [118, "Article"],
                [101, "Headline"],
                [119, "Buttons"],
                [102, "Photos"],
                [103, "Profile"],
                [116, "Contact"],
                [104, "Products"],
                [105, "Features"],
                [106, "Process"],
                [107, "Pricing"],
                [108, "Skills"],
                [109, "Achievements"],
                [110, "Quotes"],
                [111, "Partners"],
                [112, "As Featured On"],
                [113, "Page Not Found"],
                [114, "Coming Soon"],
                [115, "Help, FAQ"]
            ],
            defaultSnippetCategory: 'basic',

            // Plugins
            plugins: [],

            // UI settings
            absolutePath: false,
            addButtonPlacement: 'between-blocks-center',
            animateModal: false,
            animatedSorting: false,
            builderMode: 'default',
            clearPreferences: true,
            columnHtmlEditor: true,
            columnTool: true,
            dragWithoutHandle: false,
            elementAnimate: true,
            elementEditor: true,
            elementHighlight: true,
            elementSelection: true,
            elementTool: true,
            htmlSyntaxHighlighting: true,
            mobileSimpleEdit: false,
            outlineMode: true,
            outlineStyle: '',
            paste: 'html-without-styles',
            rowHtmlEditor: true,
            rowMoveButtons: true,
            rowTool: 'right',
            rowcolOutline: true,
            scrollableEditingToolbar: true,
            snippetAddTool: true,
            snippetOpen: false,
            toolStyle: '',
            toolbar: 'top',
            toolbarAddSnippetButton: false,
            toolbarDisplay: 'auto',
            undoContainerOnly: false,
            undoRedoStyles: true,
            useSidebar: true,

            // UI > Button settings
            buttons: [
                'bold',
                'italic',
                'underline',
                'formatPara',
                'textsettings',
                '|',
                'color',
                'align',
                'list',
                '|',
                'createLink',
                'tags',
                'more',
                '|',
                'undo',
                'redo'
            ],
            buttonsMore: [
                'icon',
                'image',
                '|',
                'font',
                'formatting',
                '|',
                'html'
            ],
            elementButtons: [
                'left',
                'center',
                'right',
                'full',
                'more',
                '|',
                'undo',
                'redo',
                '|',
                'gridtool'
            ],
            elementButtonsMore: ['|', 'html'],

            // UI > Sidebar settings
            sidebarData: {
                "buttons": [
                    {"name": "section", "title": out("Sections")},
                    {"name": "snippet", "title": out("Content Blocks")},
                    {"name": "typography", "title": out("Typography")},
                    /*
                    To add custom panel, add record  with name: "custom1" or "custom2", and specify title, your custom panel file, and icon:

                    { "name": "custom1", "title": "Custom Panel", "src": "assets/modules/panel-example.html", "html": "<i class=\"icon ion-android-bicycle\"></i>" },
                    { "name": "custom2", "title": "Custom Panel 2", "src": "assets/modules/panel-example.html", "html": "<i class=\"icon ion-android-bicycle\"></i>" }

                    Or use custom div (instead of file). In the following example we use div with id=mypanel for our custom panel:

                    { "name": "panelname", "title": "Title here", "content": "#mypanel", "html": "<i class=\"icon ion-android-bicycle\"></i>" },

                    Then, add a div anywhere in the body:

                    <div id="mypanel" class="is-sidebar-content" style="background:#ddd;max-width:500px;">
                    ...Sidebar content here...
                    </div>
                    */
                    {"name": "code", "title": "HTML"}
                ]
            },

            // Colour settings
            colors: [
                "#ff8f00", "#ef6c00", "#d84315", "#c62828", "#58362f", "#37474f", "#353535",
                "#f9a825", "#9e9d24", "#558b2f", "#ad1457", "#6a1b9a", "#4527a0", "#616161",
                "#00b8c9", "#009666", "#2e7d32", "#0277bd", "#1565c0", "#283593", "#9e9e9e"
            ],
            gradientcolors: [
                ["linear-gradient(0deg, rgb(255, 57, 25), rgb(249, 168, 37))", "light"],
                ["linear-gradient(0deg, rgb(255, 57, 25), rgb(255, 104, 15))", "light"],
                ["linear-gradient(0deg, #FF5722, #FF9800)", "light"],
                ["linear-gradient(0deg, #613ca2, rgb(110, 123, 217))", "light"],
                ["linear-gradient(0deg, rgb(65, 70, 206), rgb(236, 78, 130))", "light"],
                ["linear-gradient(0deg, rgb(0, 150, 102), rgb(90, 103, 197))", "light"],
                ["linear-gradient(30deg, rgb(249, 119, 148), rgb(98, 58, 162))", "light"],
                ["linear-gradient(0deg, rgb(223, 70, 137), rgb(90, 103, 197))", "light"],
                ["linear-gradient(0deg, rgb(40, 53, 147), rgb(90, 103, 197))", "light"],
                ["linear-gradient(0deg, rgb(21, 101, 192), rgb(52, 169, 239))", "light"],
                ["linear-gradient(0deg, rgb(32, 149, 219), rgb(139, 109, 230))", "light"],
                ["linear-gradient(0deg, rgb(90, 103, 197), rgb(0, 184, 201))", "light"],
                ["linear-gradient(0deg, rgb(0, 184, 201), rgb(253, 187, 45))", "light"],
                ["linear-gradient(0deg, rgb(255, 208, 100), rgb(239, 98, 159))", "light"],
                ["linear-gradient(0deg, rgb(0, 214, 223), rgb(130, 162, 253))", "light"],
                ["linear-gradient(0deg, rgb(50, 234, 251), rgb(248, 247, 126))", "dark"],
                ["linear-gradient(0deg, rgb(141, 221, 255), rgb(255, 227, 255))", "dark"],
                ["linear-gradient(0deg, rgb(255, 170, 170), rgb(255, 255, 200))", "dark"],
                ["linear-gradient(0deg, rgb(239, 239, 239), rgb(252, 252, 252))", "dark"]
            ],

            // Misc settings
            customval: '',
            enableModule: false,
            enableAnimation: true,
            moduleConfig: [],
            disableStaticSection: false,
            classReplace: [],
            snippetPathReplace: ['', ''],
            customTags: [],
            /*
            emailMode: false,
            sidePanel: 'right',
            snippetHandle: true,
            snippetOpen: false,
            snippetPageSliding: false,
            */
            contentHtmlStart: '<div class="is-container is-builder container"><div class="row clearfix"><div class="column full">',
            contentHtmlEnd: '</div></div></div>',

            // Event handlers
            onRender: function () {},
            onChange: function () {},
            onCoverImageSelectClick: function () {},
            // onImageBrowseClick: function () { },
            // onImageSettingClick: function () { },
            // onImageSelectClick: function () { },
            // onFileSelectClick: function () { },
            onContentClick: function () {},
            // onPluginsLoaded: function () { },
            onAddSectionOpen: function () {}, /* Old Version (backward compatible) */
        };

        /**
         * Initialise the object
         *
         * @public
         */
        this.init = function () {

            // Override any default options with any passed in by the user
            this.settings = jQuery.extend({}, defaults, opts);

            // Add the wrapper class to the element we are attached to
            $element.addClass('is-wrapper');

            // If we have a valid snippet path then show the snippets panel
            if (typeof _snippets_path !== 'undefined') {
                bSideSnippets = true;
            }

            // Extend onRender with built-in plugins
            var old = this.settings.onRender;
            this.settings.onRender = function () {
                old.call(this);
            };

            // Append the content builder overlay to the body tag
            if (jQuery('#_cbhtml').length === 0) {
                jQuery('body').append('<div id="_cbhtml"></div>');
            }

            // Doe we have any custom side buttons
            if (this.settings.sideButtons) {
                var sideButtons = this.settings.sideButtons;
            }

            // html for the sidebar
            var html_sidebar = '';
            if (this.settings.useSidebar) {

                // Svg icon definitions
                html_sidebar += getSidebarSvgDefinitions();

                // Sidebar opening tag
                html_sidebar += `
                    <div class="is-sidebar" style="transform: translate3d(0,0,0);display: flex;flex-direction: column;">
                `;

                var enableSidebarSnippets = false;
                var enableContentStyle = this.settings.enableContentStyle;
                var htmlSyntaxHighlighting = this.settings.htmlSyntaxHighlighting;
                var sideIndex = 0;

                // Loop through all the sidebar data options and build the links
                $.each(this.settings.sidebarData.buttons, function () {

                    if (this.name == 'section') {
                        html_sidebar += '<div class="is-sidebar-button" data-content="divSidebarSections" data-command="section" data-title="' + this.title + '" title="' + this.title + '">' + '<svg class="svg-icon"><use xlink:href="#ion-android-add"></use></svg>' + '</div>';

                    } else if (this.name == 'snippet') {
                        if (enableSidebarSnippets && bSideSnippets) { // if snippets are enabled
                            html_sidebar += '<div class="is-sidebar-button" data-content="divSidebarSnippets" data-title="' + this.title + '" title="' + this.title + '">' +
                                '<svg class="svg-icon"><use xlink:href="#icon-snippets"></use></svg>' +
                                '</div>';
                        }

                    } else if (this.name == 'typography') {
                        if (enableContentStyle) { // if styles are enabled
                            html_sidebar += '<div class="is-sidebar-button" data-content="divSidebarTypography" data-command="typography" data-title="' + this.title + '" title="' + this.title + '">' +
                                '<span style="font-family:serif;font-size:21px;display: inline-block;position:absolute;left:0;width:50px;">a</span>' +
                                '</div>';
                        }

                    } else if (this.name == 'code') {
                        if (htmlSyntaxHighlighting) { // if the html code preview is enabled
                            html_sidebar += '<div class="is-sidebar-button" data-command="code" data-title="' + this.title + '" title="' + this.title + '">' +
                                '<svg class="svg-icon" style="width:13px;height:13px;"><use xlink:href="#ion-code"></use></svg>' +
                                '</div>';
                        } else {
                            html_sidebar += '<div class="is-sidebar-button" data-content="divSidebarSource" data-command="code" data-title="' + this.title + '" title="' + this.title + '">' +
                                '<svg class="svg-icon" style="width:13px;height:13px;"><use xlink:href="#ion-code"></use></svg>' +
                                '</div>';
                        }

                    } else if (this.name == 'custom1') {
                        html_sidebar += '<div class="is-sidebar-button" data-content="divCustomSidebarArea1" data-title="' + this.title + '" title="' + this.title + '" data-src="' + this.src + '">' + this.html + '</div>';

                    } else if (this.name == 'custom2') {
                        html_sidebar += '<div class="is-sidebar-button" data-content="divCustomSidebarArea2" data-title="' + this.title + '" title="' + this.title + '" data-src="' + this.src + '">' + this.html + '</div>';

                    } else { //custom buttons
                        html_sidebar += '<div class="is-sidebar-button" data-content="' + this.content.substr(1) + '" data-title="' + this.title + '" title="' + this.title + '">' + this.html + '</div>';
                    }

                    // if we have any custom sidebar buttons then add them
                    if (sideButtons) {
                        /*
                        Alternative way to add sidebar button:

                        $(".is-wrapper").contentbox({
                            sideButtons:[{
                                    'pos': 0,
                                    'title': 'Writing Set',
                                    'src': 'assets/modules/panel-example.html',
                                    'html': '<svg class="svg-icon"><use xlink:href="#ion-edit"></use></svg>',
                                    'class': 'sidebar-sections'
                                }
                            ]
                        });
                        */
                        $.each(sideButtons, function () {
                            var btn = this;

                            if (sideIndex == btn.pos) {
                                var panelId = makeid();
                                html_sidebar += '<div class="is-sidebar-button" data-content="' + panelId + '" data-src="' + btn.src + '" data-title="' + out(btn.title) + '" title="' + out(btn.title) + '">' +
                                    btn.html +
                                    '</div>';

                                var panelHtml =
                                    '<div id="' + panelId + '" class="is-sidebar-content ' + btn.class + '" style="-webkit-transition-duration:0.2s;transition-duration:0.2s;">' +
                                    '<div>' +
                                    '<iframe src="about:blank" style="width:100%;height:100%;box-sizing:border-box;border:none;">' +
                                    '</iframe>' +
                                    '</div>' +
                                    '</div>';
                                jQuery('#_cbhtml').append(panelHtml);

                            }

                        });
                    }

                    sideIndex++;
                });

                // Sidebar closing tag
                html_sidebar += `
                    </div>
                `;

                // Sidebar > Design panel
                html_sidebar += getSidebarDesignPanel();

                // Sidebar > Snippet panel
                html_sidebar += getSidebarSnippetsPanel();

                // Sidebar > Html source panel
                html_sidebar += getSidebarSourceCodePanel();

                // Sidebar > Html typography panel
                html_sidebar += getSidebarStylesPanel();

                // Sidebar > Custom panel 1
                html_sidebar += getSidebarCustomPanel1();

                // Sidebar > Custom panel 2
                html_sidebar += getSidebarCustomPanel2();

                // Append to the cb editor
                jQuery('#_cbhtml').append(html_sidebar);

            } else {
                var html_normal = `
                    <div id="divSections" style="display:none"></div>
                    <div class="is-modal addsection">
                        <div style="max-width: 900px;">
                            <div id="divSectionList" class="is-section-list"></div>
                        </div>
                    </div>
                `;
                jQuery('#_cbhtml').append(html_normal);
            }

            // Create anew instance of the content builder
            _fb = new ContentBuilder({
                container: '.is-container',
                page: '.is-wrapper',
                snippetPath: this.settings.snippetPath,
                snippetImagePath: this.settings.snippetImagePath,
                snippetJSON: data_basic,
                onChange: this.settings.onChange,
                onRender: this.settings.onRender,
                moduleConfig: this.settings.moduleConfig,
                modulePath: this.settings.modulePath,
                onImageSelectClick: this.settings.onImageSelectClick,
                onFileSelectClick: this.settings.onFileSelectClick,
                onImageBrowseClick: this.settings.onImageBrowseClick,
                onImageSettingClick: this.settings.onImageSettingClick,
                onContentClick: this.settings.onContentClick,
                onPluginsLoaded: this.settings.onPluginsLoaded,
                imageselect: this.settings.imageselect,
                fileselect: this.settings.fileselect,
                iconSelect: this.settings.iconSelect,
                buttonSelect: this.settings.buttonSelect,
                symbolSelect: this.settings.symbolSelect,
                imageEmbed: this.settings.imageEmbed,
                sourceEditor: this.settings.sourceEditor,
                customval: this.settings.customval,
                snippetData: this.settings.snippetData,
                colors: this.settings.colors,
                gradientcolors: this.settings.gradientcolors,
                buttons: this.settings.buttons,
                buttonsMore: this.settings.buttonsMore,
                customTags: this.settings.customTags,
                largerImageHandler: this.settings.largerImageHandler,
                framework: this.settings.framework,
                cellFormat: this.settings.cellFormat,
                rowFormat: this.settings.rowFormat,
                row: this.settings.row,
                cols: this.settings.cols,
                colequal: this.settings.colequal,
                colsizes: this.settings.colsizes,
                classReplace: this.settings.classReplace,
                columnTool: this.settings.columnTool,
                elementTool: this.settings.elementTool,
                snippetPathReplace: this.settings.snippetPathReplace,
                animateModal: this.settings.animateModal,
                elementAnimate: this.settings.elementAnimate,
                snippetList: '#divSidebarSnippets',
                elementEditor: this.settings.elementEditor,
                onAdd: this.settings.onAdd,
                imageQuality: this.settings.imageQuality,
                columnHtmlEditor: this.settings.columnHtmlEditor,
                rowHtmlEditor: this.settings.rowHtmlEditor,
                rowMoveButtons: this.settings.rowMoveButtons,
                htmlSyntaxHighlighting: this.settings.htmlSyntaxHighlighting,
                scrollableEditingToolbar: this.settings.scrollableEditingToolbar,
                toolbar: this.settings.toolbar,
                toolbarDisplay: this.settings.toolbarDisplay,
                toolbarAddSnippetButton: this.settings.toolbarAddSnippetButton,
                paste: this.settings.paste,
                builderMode: this.settings.builderMode,
                rowcolOutline: this.settings.rowcolOutline,
                elementSelection: this.settings.elementSelection,
                animatedSorting: this.settings.animatedSorting,
                dragWithoutHandle: this.settings.dragWithoutHandle,
                addButtonPlacement: this.settings.addButtonPlacement,
                outlineMode: this.settings.outlineMode,
                elementHighlight: this.settings.elementHighlight,
                rowTool: this.settings.rowTool,
                toolStyle: this.settings.toolStyle,
                outlineStyle: this.settings.outlineStyle,
                snippetAddTool: this.settings.snippetAddTool,
                plugins: this.settings.plugins,
                mobileSimpleEdit: this.settings.mobileSimpleEdit,
                clearPreferences: this.settings.clearPreferences,
                snippetCategories: this.settings.snippetCategories,
                defaultSnippetCategory: this.settings.defaultSnippetCategory,
                scriptPath: this.settings.scriptPath,

                apiPath: this.settings.apiPath,
                backendAssetPath: this.settings.backendAssetPath,
                frontendAssetPath: this.settings.frontendAssetPath,
                assetPath: this.settings.assetPath,
                pluginPath: this.settings.pluginPath,
                iconCssPath: this.settings.iconCssPath,
                iconFontPath: this.settings.iconFontPath,
                fontAssetPath: this.settings.fontAssetPath,
                undoRedoStyles: this.settings.undoRedoStyles,
                onUndo: function () {
                    $element.data("contentbox").setup();
                },
                onRedo: function () {
                    $element.data("contentbox").setup();
                },
                undoContainerOnly: this.settings.undoContainerOnly,
                absolutePath: this.settings.absolutePath
            });

            // Html for the editor
            var htmlEditor = getDeleteSectionModal();
            htmlEditor += getEditSectionModal();
            htmlEditor += getEditModuleModal();
            htmlEditor += getEditCustomCodeModal();
            htmlEditor += getEditBoxModal(this);
            htmlEditor += getPickPhotoModal();
            htmlEditor += getApplyStylesModal();

            // Add the html to the editor
            jQuery('#_cbhtml').append(htmlEditor);

            // If use sidebar option is enabled
            if (this.settings.useSidebar) {
                jQuery('body').addClass('sidebar-active');
                jQuery('.is-sidebar > div').on('click', function () {

                    if (jQuery(this).hasClass('active')) { // toggle
                        jQuery('.is-sidebar-overlay').remove();
                        jQuery('.is-sidebar > div').removeClass('active');
                        jQuery('.is-sidebar-content').removeClass('active');
                        jQuery('body').css('overflow-y', '');
                        return;
                    }

                    if (jQuery(this).attr('data-content')) {

                        jQuery('#_cbhtml').append('<div class="is-sidebar-overlay" style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(255,255,255,0.000001);z-index: 1000;"></div>');

                        jQuery('.is-sidebar-overlay').off('click');
                        jQuery('.is-sidebar-overlay').on('click', function (e) {
                            jQuery('.is-sidebar-overlay').remove();
                            jQuery('.is-sidebar > div').removeClass('active');
                            jQuery('.is-sidebar-content').removeClass('active');
                            jQuery('body').css('overflow-y', '');
                        });

                        jQuery('.is-sidebar > div').removeClass('active');
                        jQuery('.is-sidebar-content').removeClass('active');
                        jQuery('body').css('overflow-y', '');

                        jQuery(this).addClass('active');
                        var id = jQuery(this).attr('data-content');
                        jQuery('#' + id).addClass('active');
                    }

                    if (jQuery(this).attr('data-command')) {
                        var cmd = jQuery(this).attr('data-command');
                        if (cmd == 'section') {
                            jQuery('.is-wrapper').data('contentbox').viewIdeas();
                        }
                        if (cmd == 'code') {
                            if ($element.data("contentbox").settings.htmlSyntaxHighlighting) {
                                jQuery('.is-wrapper').data('contentbox').viewHtml();
                            } else {
                                jQuery('.is-wrapper').data('contentbox').viewHtml2();
                            }
                        }
                        if (cmd == 'typography') {
                            jQuery(this).attr('data-applyto', 'page');
                            jQuery('.is-wrapper').data('contentbox').viewTypography();
                        }
                    }

                    if (jQuery(this).attr('data-src')) {
                        var id = jQuery(this).attr('data-content');
                        if (id == 'divCustomSidebarArea1') {
                            if (jQuery('#ifrCustomSidebarArea1').attr('src').indexOf('blank') != -1) {
                                var src = jQuery(this).attr('data-src');
                                jQuery('#ifrCustomSidebarArea1').attr('src', src);
                            }
                        } else if (id == 'divCustomSidebarArea2') {
                            if (jQuery('#ifrCustomSidebarArea2').attr('src').indexOf('blank') != -1) {
                                var src = jQuery(this).attr('data-src');
                                jQuery('#ifrCustomSidebarArea2').attr('src', src);
                            }
                        } else {
                            var src = jQuery(this).attr('data-src');

                            var id = jQuery(this).attr('data-content');
                            var $iframe = jQuery('#' + id).find('iframe');

                            if ($iframe.attr('src').indexOf('blank') != -1) {
                                $iframe.attr('src', src);
                            }
                        }
                    }

                });
            }

            // else do this
            if (! this.settings.useSidebar) {
                jQuery.get(scriptPath + 'contentbox.html', function (data) {
                    var htmlData = '';
                    var htmlThumbs = '';
                    var i = 1;
                    jQuery('<div/>').html(data).children('div').each(function () {

                        var block = jQuery(this).html();

                        var sfind = jQuery(this).attr('data-find');
                        var sreplace = jQuery(this).attr('data-replace');
                        var sfind2 = jQuery(this).attr('data-find2');
                        var sreplace2 = jQuery(this).attr('data-replace2');
                        var sfind3 = jQuery(this).attr('data-find2');
                        var sreplace3 = jQuery(this).attr('data-replace2');

                        var thumb = jQuery(this).attr('data-thumb');

                        if (sfind) {
                            block = block.replace('[%CONTAINER_START%]', $element.data("contentbox").settings.contentHtmlStart.replace(sfind, sreplace));
                            block = block.replace('[%CONTAINER_END%]', $element.data("contentbox").settings.contentHtmlEnd);
                        }
                        if (sfind2) {
                            block = block.replace('[%CONTAINER_START%]', $element.data("contentbox").settings.contentHtmlStart.replace(sfind2, sreplace2));
                            block = block.replace('[%CONTAINER_END%]', $element.data("contentbox").settings.contentHtmlEnd);
                        }
                        if (sfind3) {
                            block = block.replace('[%CONTAINER_START%]', $element.data("contentbox").settings.contentHtmlStart.replace(sfind3, sreplace3));
                            block = block.replace('[%CONTAINER_END%]', $element.data("contentbox").settings.contentHtmlEnd);
                        }
                        block = block.replace('[%CONTAINER_START%]', $element.data("contentbox").settings.contentHtmlStart);
                        block = block.replace('[%CONTAINER_END%]', $element.data("contentbox").settings.contentHtmlEnd);
                        block = block.replace(/\[%IMAGE_PATH%\]/g, scriptPath + 'images/');

                        //Enclode each block. Source: http://stackoverflow.com/questions/1219860/html-encoding-in-javascript-jquery
                        var blockEncoded = jQuery('<div/>').text(block).html(); //Encoded html prevents loading many images

                        if (! $element.data("contentbox").settings.enableModule) {
                            if (jQuery(this).find(".is-module").length == 0 && jQuery(this).find(".is-placeholder").length == 0) {
                                htmlData += '<div id="sect' + i + '">' + blockEncoded + '</div>';
                                htmlThumbs += '<div data-sect="' + i + '"><img src="' + scriptPath + 'images/' + thumb + '"></div>';
                            } else {

                            }
                        } else {
                            htmlData += '<div id="sect' + i + '">' + blockEncoded + '</div>';
                            htmlThumbs += '<div data-sect="' + i + '"><img src="' + scriptPath + 'images/' + thumb + '"></div>';
                        }

                        i++;

                    });

                    jQuery('#divSectionList').html(htmlThumbs);
                    jQuery('#divSections').html(htmlData);

                    jQuery('#divSectionList > *').on('click', function (e) {
                        var newArea = '';
                        newArea = jQuery('#sect' + jQuery(this).attr('data-sect')).text().replace('&lt;', '<').replace('&gt;', '>');

                        //*********** CUSTOMCODE ***********
                        newArea = newArea.replace(/{id}/g, makeid());
                        //*********** /CUSTOMCODE ***********

                        var $newSection;

                        if ($element.children('.is-section').last().hasClass('is-static')) {

                            $element.children('.is-section').last().before(newArea);

                            $newSection = $element.children('.is-section').last().prev();

                        } else {

                            if ($element.children('.is-section').length > 0) {
                                if (! $element.children('.is-section').last().hasClass("is-bg-grey")) {
                                    //$element.append(newArea);
                                    $element.children('.is-section').last().after(newArea);
                                    $element.children('.is-section').last().addClass("is-bg-grey");
                                } else {
                                    //$element.append(newArea);
                                    $element.children('.is-section').last().after(newArea);
                                }
                            } else {
                                $element.prepend(newArea);
                            }
                            $newSection = $element.children('.is-section').last();

                        }

                        //*********** CUSTOMCODE ***********
                        $newSection.find(".is-overlay-content[data-module]").each(function () {//Mode: code
                            var html = (decodeURIComponent(jQuery(this).attr("data-html")));
                            //Fill the block with original code (when adding section)
                            jQuery(this).html(html);
                        });
                        //*********** /CUSTOMCODE ***********

                        _fb.applyBehavior();

                        initSectionToolbar($newSection);

                        var $modal = jQuery('.is-modal.addsection');
                        $element.data("contentbox").hideModal($modal);

                        $element.data("contentbox").applyBoxBehavior();

                        jQuery('body, html').animate({
                            scrollTop: $newSection.offset().top
                        }, 1000);

                        //Trigger Change event
                        $element.data("contentbox").settings.onChange();

                        //Close sidebar
                        //jQuery('.is-sidebar > div').removeClass('active');
                        //jQuery('.is-sidebar-content').removeClass('active');

                        e.preventDefault();
                        e.stopImmediatePropagation();
                        return false;
                    });
                });
            }

            // Call the setup method
            this.setup();

            // Add the box tool to the editor
            if (jQuery("#divboxtool").length === 0) {
                var s = getBoxTool(this);
                jQuery('#_cbhtml').append(s);
            }

            jQuery('#hidcustomval').val(this.settings.customval);

            // Get the colour pickers
            colorpicker = _fb.colorpicker();

            // Sidebar mouse over
            jQuery('.is-sidebar').on('mouseover', function () {
                jQuery("#divboxtool").css("display", "none");
                jQuery('.is-section-tool').css('display', 'none');
            });
        };

        /**
         * Add sidebar button
         *
         * @param btn
         * @public
         */
        this.addButton = function (btn) {
            var btnId = makeid();
            var panelId = makeid();
            var btnHtml;
            if (btn.src) {

                btnHtml = '<div id="' + btnId + '" class="is-sidebar-button" data-content="' + panelId + '" data-src="' + btn.src + '" data-title="' + out(btn.title) + '" title="' + out(btn.title) + '">' +
                    btn.html +
                    '</div>';

                var panelHtml =
                    '<div id="' + panelId + '" class="is-sidebar-content ' + btn.class + '" style="-webkit-transition-duration:0.2s;transition-duration:0.2s;">' +
                    '<div>' +
                    '<iframe src="about:blank" style="width:100%;height:100%;box-sizing:border-box;border:none;">' +
                    '</iframe>' +
                    '</div>' +
                    '</div>';
                jQuery('#_cbhtml').append(panelHtml);

            } else {
                btnHtml = '<div id="' + btnId + '" class="is-sidebar-button" data-title="' + out(btn.title) + '" title="' + out(btn.title) + '">' +
                    btn.html +
                    '</div>';
            }

            jQuery('.is-sidebar > *:eq(' + btn.pos + ')').after(btnHtml);

            jQuery('#' + btnId).on('click', function (e) {

                if (btn.src) {

                    if (! jQuery(this).hasClass('active')) {

                        jQuery('.is-sidebar > div').removeClass('active');
                        jQuery('.is-sidebar-content').removeClass('active');
                        jQuery('body').css('overflow-y', '');

                        jQuery(this).addClass('active');
                        var id = jQuery(this).attr('data-content');
                        jQuery('#' + id).addClass('active');

                        var $iframe = jQuery('#' + id + ' iframe');
                        if ($iframe.attr('src') == 'about:blank') {
                            $iframe.attr('src', btn.src);
                        }

                        jQuery('#_cbhtml').append('<div class="is-sidebar-overlay" style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(255,255,255,0.000001);z-index: 1000;;"></div>');

                        jQuery('.is-sidebar-overlay').off('click');
                        jQuery('.is-sidebar-overlay').on('click', function (e) {
                            jQuery('.is-sidebar-overlay').remove();
                            jQuery('.is-sidebar > div').removeClass('active');
                            jQuery('.is-sidebar-content').removeClass('active');
                            jQuery('body').css('overflow-y', '');
                        });

                    } else {
                        jQuery('.is-sidebar-overlay').remove();
                        jQuery('.is-sidebar > div').removeClass('active');
                        jQuery('.is-sidebar-content').removeClass('active');
                        jQuery('body').css('overflow-y', '');
                        return;
                    }

                } else {

                    btn.onClick();

                }

            });
        };

        /**
         * Undo change
         *
         * @public
         */
        this.undo = function () {
            _fb.undo();
        };

        /**
         * Redo change
         *
         * @public
         */
        this.redo = function () {
            _fb.redo();
        };

        /**
         * Save the images
         *
         * @param handler
         * @param onComplete
         * @public
         */
        this.saveImages = function (handler, onComplete) {
            _fb.saveImages(handler, onComplete);
        };

        /**
         * Show modal
         *
         * @param $modal
         * @public
         */
        this.showModal = function ($modal) {
            $modal.addClass('active');
        };

        /**
         * Hide modal
         *
         * @param $modal
         * @public
         */
        this.hideModal = function ($modal) {
            $modal.removeClass('active');
        };

        /**
         * Add design
         *
         * @param newArea
         * @public
         */
        this.addIdea = function (newArea) {

            // Save for undo
            _fb.saveForUndo();

            // When adding a design replace the image path
            var designPath = $element.data("contentbox").settings.designPath;
            newArea = newArea.replace(/\[%IMAGE_PATH%\]/g, designPath);
            newArea = newArea.replace(/%5B%25IMAGE_PATH%25%5D/g, designPath); //If [%IMAGE_PATH%] is encoded (inside data-html)

            var $newSection;

            // If the new section is not static then add a grey background
            if (newArea.indexOf('is-static') == -1 && $element.children('.is-section').last().hasClass('is-static')) {
                $element.children('.is-section').last().before(newArea);
                $newSection = $element.children('.is-section').last().prev();
                if ($newSection.prev()) {
                    if (! $newSection.prev().hasClass("is-bg-grey")) {
                        $newSection.addClass("is-bg-grey");
                    }
                }

            } else {
                if ($element.children('.is-section').length > 0) {
                    $element.children('.is-section').last().after(newArea);
                } else {
                    $element.prepend(newArea);
                }
                $newSection = $element.children('.is-section').last();
                if ($newSection.prev()) {
                    if (! $newSection.prev().hasClass("is-bg-grey")) {
                        $newSection.addClass("is-bg-grey");
                    }
                }
            }

            // If the new section has any snippets with custom code, then get and apply their html
            $newSection
                .find(".is-overlay-content[data-module]")
                .each(function () {//Mode: code
                    var html = (decodeURIComponent(jQuery(this).attr("data-html")));
                    html = html.replace(/{id}/g, makeid());
                    //Fill the block with original code (when adding section)
                    jQuery(this).html(html);
                });

            // Apply the change
            _fb.applyBehavior();

            // Add the editor functionality to the new section
            initSectionToolbar($newSection);

            $element.data("contentbox").applyBoxBehavior();

            // Focus the page on the new section
            //$('body, html').scrollTop($newSection.offset().top);
            jQuery('body, html').animate({
                scrollTop: $newSection.offset().top
            }, 1000);

            // Trigger Change event
            $element.data("contentbox").settings.onChange();

            // Close sidebar
            jQuery('.is-sidebar-overlay').remove();
            jQuery('.is-sidebar > div').removeClass('active');
            jQuery('.is-sidebar-content').removeClass('active');
            jQuery('body').css('overflow-y', '');
        };

        /**
         * Get the html for the section toolbar (edit/duplicate/remove buttons)
         * @returns {string}
         */
        let getSectionToolHtml = function () {
            return `
                <div class="is-section-tool">
                    <div class="is-section-edit" data-title="Section Settings" title="Section Settings">
                        <svg class="is-icon-flex" style="margin-right:-2px;fill:rgba(255,255,255,1);">
                            <use xlink:href="#ion-wrench"></use>
                        </svg>
                    </div>
                    <div class="is-section-duplicate" data-title="Duplicate" title="Duplicate">
                        <svg class="is-icon-flex" style="margin-right:-2px;fill:rgba(255,255,255,1);">
                            <use xlink:href="#ion-grid"></use>
                        </svg>
                    </div>
                    <div class="is-section-remove" data-title="Remove" title="Remove">&#10005;</div>
                </div>
            `;
        }

        /**
         * Duplicate a section
         *
         * @param {jQuery} $section - The section to duplicate
         */
        let duplicateSection = function ($section) {

            // If the section has a custom module then bail
            if (sectionHasCustomModule($section)) {
                alert('Sections containing custom modules cannot be duplicated.');

                return;
            }

            _fb.saveForUndo();

            // Clone DOM without events (events capture wrong closure vars)
            let $clone = $section.clone(false);

            // Remove toolbar from clone (will be re-added via initSectionToolbar)
            $clone.find('.is-section-tool').remove();

            // Re-decode custom code modules with fresh IDs
            $clone.find('.is-overlay-content[data-module]').each(function () {
                var html = decodeURIComponent(jQuery(this).attr('data-html'));
                html = html.replace(/{id}/g, makeid());
                jQuery(this).html(html);
            });

            // Insert clone after original
            $section.after($clone);

            // Rebind ContentBuilder behaviours
            _fb.applyBehavior();

            // Add toolbar + events to clone
            initSectionToolbar($clone);

            // Rebind box interactions
            $element.data('contentbox').applyBoxBehavior();

            // Scroll to clone
            jQuery('body, html').animate({
                scrollTop: $clone.offset().top
            }, 1000);

            // Trigger callbacks
            $element.data('contentbox').settings.onRender();
            $element.data('contentbox').settings.onChange();
        };

        /**
         * Initialise section toolbar (edit/duplicate/remove buttons)
         *
         * @param {jQuery} $section - The section element
         */
        let initSectionToolbar = function ($section) {

            // Remove any existing toolbar (idempotent)
            $section.find('.is-section-tool').remove();

            // Append the html
            $section.append(getSectionToolHtml());

            _fb.setTooltip($element.get(0));

            // Edit handler
            $section.find('.is-section-edit')
                .off('click')
                .on('click', function (e) {
                    $activeSection = jQuery(this).parent().parent();
                    $element.data('contentbox').editSection();
                });

            // Duplicate handler - disable if section contains a custom module
            sectionHasCustomModule($section)
                ? disableDuplicateSectionBtn($section)
                : enableDuplicateSectionBtn($section);

            // Remove handler
            $section.find('.is-section-remove')
                .off('click')
                .on('click', function (e) {
                    jQuery('body, html').animate({scrollTop: $section.offset().top}, 1000);

                    var $modal = jQuery('.is-modal.delsectionconfirm');
                    $element.data('contentbox').showModal($modal);

                    $modal.not('.is-modal *').off('click');
                    $modal.not('.is-modal *').on('click', function (e) {
                        if (jQuery(e.target).hasClass('is-modal')) {
                            $element.data('contentbox').hideModal($modal);
                        }
                    });

                    $modal.find('.input-ok').off('click');
                    $modal.find('.input-ok').on('click', function (e) {
                        $section.fadeOut(400, function () {
                            _fb.saveForUndo();
                            $section.remove();

                            $element.data('contentbox').settings.onRender();
                            $element.data('contentbox').hideModal($modal);
                            $element.data('contentbox').settings.onChange();

                            jQuery('#divboxtool').css('display', 'none');
                        });
                        return false;
                    });
                });
        };

        /**
         * Get the duplicate button for a section
         * @param $section
         * @returns {*}
         */
        let getDuplicateSectionBtn = function ($section) {
            return $section.find('.is-section-duplicate');
        }

        /**
         * Enables the duplicate section button for a given section element.
         * @param $section
         */
        let enableDuplicateSectionBtn = function ($section) {
            let $duplicateBtn = getDuplicateSectionBtn($section);

            $duplicateBtn
                .off('click')
                .on('click', function (e) {
                    duplicateSection($section);
                });
        };

        /**
         * Disables the duplicate section button for a given section element.
         * @param $section
         */
        let disableDuplicateSectionBtn = function ($section) {
            let $duplicateBtn = getDuplicateSectionBtn($section);

            $duplicateBtn
                .off('click')
                .addClass('disabled')
                .attr('title', 'Cannot duplicate sections containing custom modules');
        }

        /**
         * Checks if a section contains any custom modules
         * (identified by the presence of a data-module attribute on an is-overlay-content element).
         * @param $section
         * @returns {boolean}
         */
        let sectionHasCustomModule = function ($section) {
            return $section.find('[data-module]').length > 0;
        };

        /**
         * Setup
         *
         * @public
         */
        this.setup = function () {

            $element.children('.is-section').each(function () {

                var $currentSection = jQuery(this);

                // Quick fix to make sure both the section and its children don't both have the is-box class
                if ($currentSection.hasClass('is-box') && $currentSection.find('.is-box').length) {
                    $currentSection.removeClass('is-box')
                }

                initSectionToolbar($currentSection);
            });

            this.applyBoxBehavior();

            _fb.applyBehavior();
        };

        /**
         * Load the html
         *
         * @param html
         * @public
         */
        this.loadHtml = function (html) {
            $element.html(html);
            this.setup();
        };

        /**
         * Added section
         *
         * @public
         */
        this.addSection = function () {

            //Trigger onAddSectionOpen event
            this.settings.onAddSectionOpen();

            var $modal = jQuery('.is-modal.addsection');
            $element.data("contentbox").showModal($modal);
        };

        /**
         * Edit section
         *
         * @public
         */
        this.editSection = function () {

            jQuery('body, html').animate({
                scrollTop: $activeSection.offset().top
            }, 1000);

            // section modal
            var $modal = jQuery('.is-modal.editsection');
            $element.data("contentbox").showModal($modal);

            // if the user clicks off the modal
            $modal.not('.is-modal *').off('click');
            $modal.not('.is-modal *').on('click', function (e) {
                if (jQuery(e.target).hasClass('is-modal')) {
                    $element.data("contentbox").hideModal($modal);
                }
            });

            // Restore the modal settings
            this.restoreEditSectionSettings();

            // Handle the events
            this.handleEditSectionEvents();
        };

        /**
         * Restore the selected options for the edit section modal window
         */
        this.restoreEditSectionSettings = function () {

            // does this section have a static class
            if ($activeSection.hasClass('is-static')) {
                jQuery('.move-section').css('display', 'none');
                jQuery('.add-scroll-section').css('display', 'none');
            } else {
                jQuery('.move-section').css('display', 'table');
                jQuery('.add-scroll-section').css('display', 'table');
            }

            // Set the initial section height input
            if ($activeSection.hasClass("is-section-fixed")) {
                jQuery(".section-height-fixed").val(
                    parseInt($activeSection.css("height") || 0)
                );
            }

            // Set the section scroll icon state
            if ($activeSection.find(".is-arrow-down").length > 0) {
                jQuery("#chkScrollIcon").prop("checked", true);
            } else {
                jQuery("#chkScrollIcon").prop("checked", false);
            }

            // Set the separator dropdowns
            this.updateSeparatorStyle();
            this.updateSeparatorDirection();
            this.updateSeparatorSize();
            this.updateSeparatorColour();

            // Set the section class list
            this.updateSectionClassList();
        }

        /**
         * Get the separator styles
         *
         * @returns {*[]}
         */
        this.getSeparatorStyles = function () {
            return [
                'separator-chevron',
                'separator-chevron-up',
                'separator-chevron-down',
                'separator-chevron-inverted',
                'separator-points',
                'separator-spikes',
                'separator-slant-left',
                'separator-slant-right',
                'separator-skew-left',
                'separator-skew-right',
                'separator-zigzags',
            ];
        }

        /**
         * Get the separator directions
         *
         * @returns {*[]}
         */
        this.getSeparatorDirections = function () {
            return [
                'separator-top',
                'separator-bottom',
                'separator-both',
            ];
        }

        /**
         * Get the separator sizes
         *
         * @returns {*[]}
         */
        this.getSeparatorSizes = function () {
            return [
                'separator-xs',
                'separator-sm',
                'separator-md',
                'separator-lg',
            ];
        }

        /**
         * Get the separator colours
         *
         * @returns {*[]}
         */
        this.getSeparatorColours = function () {
            return [
                'separator-primary',
                'separator-secondary',
                'separator-tertiary',
                'separator-quaternary',
                'separator-color-5',
                'separator-color-6',
                'separator-color-7',
                'separator-color-8',
                'separator-success',
                'separator-danger',
                'separator-warning',
                'separator-info',
                'separator-white',
                'separator-light',
                'separator-dark',
            ];
        }

        /**
         * Get the classes from the active section
         *
         * @returns {null|*}
         */
        this.getSectionClasses = function () {

            let classList = $activeSection.attr('class');

            if (classList && classList.length > 0) {
                classList = classList.replace('is-section ', '');

                return classList;
            }

            return null;
        }

        /**
         * Update the separator style dropdown
         */
        this.updateSeparatorStyle = function () {

            // Get and reset the dropdown
            let dropdown = jQuery('#separator-style');
            dropdown.val('');

            // If the section has the class then update the dropdown
            this.getSeparatorStyles().forEach(function (value) {
                if ($activeSection.hasClass(value)) {
                    return dropdown.val(value).change();
                }
            });
        }

        /**
         * Update the separator direction dropdown
         */
        this.updateSeparatorDirection = function () {

            // Get and reset the dropdown
            let dropdown = jQuery('#separator-direction');
            dropdown.val('');

            this.getSeparatorDirections().forEach(function (value) {
                if ($activeSection.hasClass(value)) {
                    return dropdown.val(value).change();
                }
            });
        }

        /**
         * Update the separator size dropdown
         */
        this.updateSeparatorSize = function () {

            // Get and reset the dropdown
            let dropdown = jQuery('#separator-size');
            dropdown.val('');

            this.getSeparatorSizes().forEach(function (value) {
                if ($activeSection.hasClass(value)) {
                    return dropdown.val(value).change();
                }
            });
        }

        /**
         * Update the separator colour dropdown
         */
        this.updateSeparatorColour = function () {

            // Get and reset the dropdown
            let dropdown = jQuery('#separator-colour');
            dropdown.val('');

            this.getSeparatorColours().forEach(function (value) {
                if ($activeSection.hasClass(value)) {
                    return dropdown.val(value).change();
                }
            });
        }

        /**
         * Update the section class list textarea
         */
        this.updateSectionClassList = function () {
            document.querySelector('#section-class-list').value = this.getSectionClasses();
        }

        /**
         * Handle the events fired from the edit section
         *
         * @private
         */
        this.handleEditSectionEvents = function () {
            this.handleEditSectionMoveEvents();
            this.handleEditSectionHeightEvents();
            this.handleEditSectionScrollEvents();
            this.handleEditSectionSeparatorEvents();
            this.handleEditSectionClassListEvent();
        };

        /**
         * Handle edit section move events
         *
         * @private
         */
        this.handleEditSectionMoveEvents = function () {

            // Handle moving the section up and down
            jQuery(".cmd-section-up")
                .unbind('click')
                .on('click', function (e) {
                    _fb.saveForUndo();

                    $element.data("contentbox").sectionUp();

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });

            jQuery(".cmd-section-down")
                .unbind('click')
                .on('click', function (e) {
                    _fb.saveForUndo();

                    $element.data("contentbox").sectionDown();

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });

            // Handle moving the section to the very top or the bottom
            jQuery(".cmd-section-top")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();

                    $element.data("contentbox").sectionTop();

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });

            jQuery(".cmd-section-bottom")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();

                    $element.data("contentbox").sectionBottom();

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });
        }

        /**
         * Handle edit section height events
         *
         * @private
         */
        this.handleEditSectionHeightEvents = function () {

            // Handle the fixed section height
            jQuery(".section-height-fixed")
                .unbind("keyup")
                .on("keyup", function (e) {

                    // Swap the full height class with fixed height
                    $activeSection.removeClass("is-section-100");
                    $activeSection.addClass("is-section-fixed");

                    // As long as the value is a number and above 100px then add it
                    var val = jQuery(".section-height-fixed").val();
                    if (! isNaN(val) && val >= 100) {
                        $activeSection.css("height", val + "px");
                    }

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });

            // Handle the auto section height
            jQuery(".section-height-auto")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();

                    // Remove the full height class and reset the fixed height
                    jQuery(".section-height-fixed").val(null);
                    $activeSection.css("height", "");
                    $activeSection.removeClass("is-section-100");
                    $activeSection.removeClass("is-section-fixed");

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });

            // Handle the full section height
            jQuery(".section-height-full")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();

                    // Remove the fixed height
                    jQuery(".section-height-fixed").val(null);
                    $activeSection.css("height", "");

                    // Swap the fixed height class with full height
                    $activeSection.removeClass("is-section-fixed");
                    $activeSection.addClass("is-section-100");

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });
        }

        /**
         * Handle edit section scroll events
         *
         * @private
         */
        this.handleEditSectionScrollEvents = function () {

            // Handle the show/hide
            jQuery("#chkScrollIcon")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();

                    $element.data("contentbox").sectionUseScroll();

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();
                });

            // Handle the icon colour
            jQuery(".cmd-section-scroll")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();

                    $element.data("contentbox").sectionScrollIcon(jQuery(this).data("value"));

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });
        }

        /**
         * Handle edit section separator events
         *
         * @private
         */
        this.handleEditSectionSeparatorEvents = function () {

            let _this = this;

            jQuery("#separator-style")
                .off("change")
                .on('change', function (e) {
                    _fb.saveForUndo();

                    // Remove existing class
                    let separatorStyles = _this.getSeparatorStyles();
                    separatorStyles.forEach(function (value) {
                        $activeSection.removeClass(value);
                    });

                    // Add the new class
                    $activeSection.addClass(e.target.value);
                    _this.updateSectionClassList();

                    // Trigger Change event
                    $element.data("contentbox").settings.onChange();
                });

            jQuery("#separator-direction")
                .off("change")
                .on('change', function (e) {
                    _fb.saveForUndo();

                    // Remove existing class
                    let separatorDirections = _this.getSeparatorDirections();
                    separatorDirections.forEach(function (value) {
                        $activeSection.removeClass(value);
                    });

                    // Add the new class
                    $activeSection.addClass(e.target.value);
                    _this.updateSectionClassList();

                    // Trigger Change event
                    $element.data("contentbox").settings.onChange();
                });

            jQuery("#separator-size")
                .off("change")
                .on('change', function (e) {
                    _fb.saveForUndo();

                    // Remove existing class
                    let separatorSizes = _this.getSeparatorSizes();
                    separatorSizes.forEach(function (value) {
                        $activeSection.removeClass(value);
                    });

                    // Add the new class
                    $activeSection.addClass(e.target.value);
                    _this.updateSectionClassList();

                    // Trigger Change event
                    $element.data("contentbox").settings.onChange();
                });

            jQuery("#separator-colour")
                .off("change")
                .on('change', function (e) {
                    _fb.saveForUndo();

                    // Remove existing class
                    let separatorColours = _this.getSeparatorColours();
                    separatorColours.forEach(function (value) {
                        $activeSection.removeClass(value);
                    });

                    // Add the new class
                    $activeSection.addClass(e.target.value);
                    _this.updateSectionClassList();

                    // Trigger Change event
                    $element.data("contentbox").settings.onChange();
                });
        }

        /**
         * Handle edit section class event
         *
         * @private
         */
        this.handleEditSectionClassListEvent = function () {

            let _this = this;

            jQuery("#section-class-list")
                .unbind("blur")
                .on('blur', function (e) {
                    _fb.saveForUndo();

                    // Update the actual css classes
                    $activeSection.attr('class', 'is-section ' + e.target.value);

                    // Refresh the dropdowns
                    _this.updateSeparatorStyle();
                    _this.updateSeparatorDirection();
                    _this.updateSeparatorSize();
                    _this.updateSeparatorColour();

                    // Trigger Change event
                    $element.data("contentbox").settings.onChange();
                });
        }

        /**
         * Apply box behaviour
         *
         * @public
         */
        this.applyBoxBehavior = function () {

            // Handle the box mouse over
            jQuery(document)
                .off('mouseenter', '.is-box')
                .on('mouseenter', '.is-box', function (e) {
                    var $box = jQuery(this);
                    var leftadj;

                    // Is this a module box or a normal box
                    if ($box.find('.is-overlay-content[data-module]').length > 0) {
                        jQuery("#form-upload-cover").css("display", "none");
                        jQuery("#lnkremovecover").css('display', 'none');
                        jQuery("#lnkeditmodule").css("display", "inline-block");
                        jQuery("#divboxtool").css("width", "80px");
                        leftadj = 55;

                    } else {
                        jQuery("#form-upload-cover").css("display", "block");
                        jQuery("#lnkeditmodule").css("display", "none");
                        jQuery("#divboxtool").css("width", "120px");
                        leftadj = 40;
                    }

                    // Handle the buttons position
                    var scrolltop = jQuery(window).scrollTop();
                    var offsettop = $box.offset().top;
                    var offsetleft = $box.offset().left;
                    var top = offsettop + parseInt($box.css('height')) - 40;
                    var left = offsetleft + parseInt($box.css('width')) / 2;

                    // Center the buttons in the middle of the box
                    var boxToolButtons = jQuery("#divboxtool");
                    boxToolButtons.css("top", top + "px");
                    boxToolButtons.css("left", (left - leftadj) + "px");
                    boxToolButtons.css("display", "flex");

                    // Hide all section tools
                    jQuery('.is-section-tool').css('display', 'none');

                    // If this box has a section then show the section tool but only for this box
                    if ($box.hasClass('is-section')) {
                        $box.find('.is-section-tool').css('display', 'block');

                    } else { // Otherwise find the closest section tool and display that
                        $box.parents('.is-section').first().find('.is-section-tool').css('display', 'block');
                    }

                    // Does this box have a background image
                    if ($box.find(".is-overlay-bg").length > 0) {
                        jQuery("#lnkremovecover").css('display', 'block');
                    } else {
                        jQuery("#lnkremovecover").css('display', 'none');
                    }

                    // Handle the add background image button click
                    jQuery(document)
                        .off('click', '#fileCover')
                        .on('click', '#fileCover', function (e) {
                            $activeBox = $box;
                            $activeSection = $box.parents('is-section');
                        });

                    // Handle the remove background button click
                    jQuery(document)
                        .off('click', '#lnkremovecover')
                        .on('click', '#lnkremovecover', function (e) {
                            $box.find(".is-overlay").remove();
                            jQuery(this).css('display', 'none');
                        });

                    // Handle the edit box button click
                    jQuery(document)
                        .off('click', '#lnkeditbox')
                        .on('click', '#lnkeditbox', function (e) {
                            $activeBox = $box;
                            $activeSection = $box.parents('is-section');
                            $element.data("contentbox").editBox();
                        });

                    // Handle the edit module settings button click
                    jQuery(document)
                        .off('click', '#lnkeditmodule')
                        .on('click', '#lnkeditmodule', function (e) {
                            $activeBox = $box;
                            $activeSection = $box.parents('is-section');
                            $element.data("contentbox").editModule();
                        });

                    // Handle the add background image form event
                    jQuery(document)
                        .off('change', '#fileCover')
                        .on('change', '#fileCover', function (e) {

                            if (jQuery(this).val() === '') return;

                            _fb.saveForUndo();

                            jQuery("#lblWait").css("display", "block");

                            let token = parent.document.head.querySelector('meta[name="csrf-token"]');
                            if (token) {
                                jQuery("#form-upload-cover").find('input[name="_token"]').val(token.content);
                            }

                            jQuery("#form-upload-cover").submit();
                            jQuery(this).clearInputs();

                            e.preventDefault();
                            e.stopImmediatePropagation();
                        });
                });

            /*
            Add dummy DIV after the last section (for the ability to adjust last section according bottom bar).
            In FF, needed only when adding new section.
            In IE, needed on normal.
            */
            if ($element.children('div.is-dummy').length > 0) {
                $element.children('div.is-dummy').remove();
            }
            $element.append('<div class="is-dummy" style="height:0px;"></div>'); //always on the last

            //Safari doesn't need the DIV
            if (navigator.userAgent.indexOf('Safari') != -1
                && navigator.userAgent.indexOf('Chrome') == -1
            ) {
                jQuery('div.is-dummy').remove();
            }

            //Trigger Render event
            this.settings.onRender();
        };

        /**
         * Edit Module
         *
         * @public
         */
        this.editModule = function () {

            jQuery('body, html').animate({
                scrollTop: $activeBox.offset().top
            }, 1000);

            var $activeModule = $activeBox.find(".is-overlay-content[data-module]");

            jQuery("[data-module-active]").removeAttr('data-module-active');
            $activeModule.attr('data-module-active', '1');

            var moduleName = $activeModule.attr('data-module');

            if (moduleName == 'code') {

                if ($element.data("contentbox").settings.htmlSyntaxHighlighting) {

                    $activeBox.addClass('box-active');

                    var html = decodeURIComponent($activeModule.attr("data-html"));

                    jQuery('#txtBoxCustomCode').val(html);

                    jQuery('textarea').removeAttr('data-source-active');
                    jQuery('textarea').removeAttr('data-source-ok');
                    jQuery('textarea').removeAttr('data-source-cancel');
                    jQuery('.editcustomcode textarea').attr('data-source-active', '1');
                    jQuery('.editcustomcode textarea').attr('data-source-ok', '.editcustomcode .input-ok');
                    jQuery('.editcustomcode textarea').attr('data-source-cancel', '.editcustomcode');

                    _fb.viewHtmlNormal();

                    var $modal = jQuery('.is-modal.editcustomcode');
                    $modal.find('.input-ok').off('click');
                    $modal.find('.input-ok').on('click', function (e) {

                        _fb.saveForUndo();

                        jQuery('#hidBoxCustomCode').val(jQuery('#txtBoxCustomCode').val());

                        //Save Html (original)
                        $activeModule.attr('data-html', encodeURIComponent(jQuery('#hidBoxCustomCode').val()));

                        //Render (programmatically)
                        $activeModule.html(jQuery('#hidBoxCustomCode').val());

                        //Trigger Change event
                        $element.data("contentbox").settings.onChange();

                        $element.data("contentbox").hideModal($modal);
                        jQuery('.box-active').removeClass('box-active');

                    });

                } else {

                    $activeBox.addClass('box-active');

                    var $modal = jQuery('.is-modal.editcustomcode');
                    $element.data("contentbox").showModal($modal);

                    $modal.not('.is-modal *').off('click');
                    $modal.not('.is-modal *').on('click', function (e) {
                        if (jQuery(e.target).hasClass('is-modal')) {
                            $element.data("contentbox").hideModal($modal);
                            jQuery('.box-active').removeClass('box-active');
                        }
                    });

                    var html = decodeURIComponent($activeModule.attr("data-html"));
                    jQuery('#txtBoxCustomCode').val(html);
                    jQuery('#txtBoxCustomCode').trigger('focus');

                    jQuery('.editcustomcode .cell-html-larger').off('click');
                    jQuery('.editcustomcode .cell-html-larger').on('click', function (e) {

                        //used  by larger editor dialog (html.html)
                        jQuery('textarea').removeAttr('data-source-active');
                        jQuery('textarea').removeAttr('data-source-ok');
                        jQuery('textarea').removeAttr('data-source-cancel');
                        jQuery('.editcustomcode textarea').attr('data-source-active', '1');
                        jQuery('.editcustomcode textarea').attr('data-source-ok', '.editcustomcode .input-ok');
                        jQuery('.editcustomcode textarea').attr('data-source-cancel', '.editcustomcode');

                        _fb.viewHtmlLarger();

                    });

                    $modal.find('.input-ok').off('click');
                    $modal.find('.input-ok').on('click', function (e) {

                        _fb.saveForUndo();

                        jQuery('#hidBoxCustomCode').val(jQuery('#txtBoxCustomCode').val());

                        //Save Html (original)
                        $activeModule.attr('data-html', encodeURIComponent(jQuery('#hidBoxCustomCode').val()));

                        //Render (programmatically)
                        $activeModule.html(jQuery('#hidBoxCustomCode').val());

                        //Trigger Change event
                        $element.data("contentbox").settings.onChange();

                        $element.data("contentbox").hideModal($modal);
                        jQuery('.box-active').removeClass('box-active');

                    });
                }

            } else {
                $activeBox.addClass('box-active');

                var $modal = jQuery('.is-modal.editmodule');
                $element.data("contentbox").showModal($modal);

                $modal.not('.is-modal *').off('click');
                $modal.not('.is-modal *').on('click', function (e) {
                    if (jQuery(e.target).hasClass('is-modal')) {
                        $element.data("contentbox").hideModal($modal);
                        jQuery('.box-active').removeClass('box-active');
                    }
                });

                $modal.find('iframe').attr('src', $element.data('contentbox').settings.modulePath + moduleName + '.html'); //load module panel on iframe

                var moduleDesc = $activeModule.attr('data-module-desc');
                if (moduleDesc) {
                    $modal.find('.is-modal-bar').html(moduleDesc);
                } else {
                    $modal.find('.is-modal-bar').html('Module Settings');
                }

                var w = $activeModule.attr('data-dialog-width');
                if (! w || w == '') {
                    w = '900px';
                }

                var h = $activeModule.attr('data-dialog-height');
                if (! h || h == '') {
                    h = '570px';
                }

                $modal.children('div').first().css('max-width', w);
                $modal.children('div').first().css('height', h);

                $modal.find('.input-ok').off('click');
                $modal.find('.input-ok').on('click', function (e) {

                    _fb.saveForUndo();

                    if (moduleName == 'code') {
                        var $codeEditor = jQuery('#txtBoxCustomCode').data('CodeMirrorInstance');
                        jQuery('#hidBoxCustomCode').val($codeEditor.getValue());
                    }

                    //Save Html (original)
                    $activeModule.attr('data-html', encodeURIComponent(jQuery('#hidModuleCode').val()));

                    //Save Settings (original)
                    $activeModule.attr('data-settings', encodeURIComponent(jQuery('#hidModuleSettings').val()));

                    //Render (programmatically)
                    $activeModule.html(jQuery('#hidModuleCode').val());

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    $element.data("contentbox").hideModal($modal);

                    jQuery('.box-active').removeClass('box-active');
                });

            }

        };

        /**
         * Edit box
         *
         * @public
         */
        this.editBox = function () {

            jQuery('body, html').animate({
                scrollTop: $activeBox.offset().top
            }, 1000);

            // Does this box have an overlay image
            if ($activeBox.find(".is-overlay-bg").length == 0) {
                this.hideEditBoxImageTab();
                this.hidePickPhotoField();
                this.hideEditBoxModuleTab();
            } else {
                this.showEditBoxImageTab();
                this.handlePickPhotoField();
                this.handleEditBoxModuleTab();
                this.handleImageEffectFields();
            }

            // Handle the remaining tabs
            this.handleEditBoxAnimationTab();

            // Content text tab
            if ($activeBox.find(".is-container").length == 0) { //no content
                this.hideEditBoxTextTab();
                this.hideEditBoxContentTab();
                this.hideContentWidthField();
                this.hideContentHeightField();

            } else {

                // Does this box have a container with a module inside
                if ($activeBox.find(".is-container .is-module").length > 0) {
                    this.hideEditBoxTextTab();
                } else {
                    this.showEditBoxTextTab();
                }

                // Is the current box display table or flex
                if ($activeBox.css("display") == "table"
                    || $activeBox.css("display") == "table-cell"
                    || $activeBox.css("display") == "flex"
                ) {
                    this.showEditBoxContentTab();
                    this.showContentWidthField();
                    this.showContentHeightField();
                } else {
                    this.hideEditBoxContentTab();
                    this.hideContentWidthField();
                    this.hideContentHeightField();
                }
            }

            // Is this box a module
            if ($activeBox.find(".is-module").length > 0) { //If is module
                jQuery("#chkBgModule").prop("checked", true);
            } else {
                jQuery("#chkBgModule").prop("checked", false);
            }

            // Does the overlay contain a module
            if ($activeBox.find(".is-overlay-content[data-module]").length != 0) {
                this.hideBackgroundColorField();
                this.hideEditBoxImageTab();
            } else {
                this.showBackgroundColorField();
            }

            // Does the overlay contain content
            if (jQuery("#divBoxBackgroundColor").css("display") == "block"
                && $activeBox.find(".is-overlay-bg").children().not('.is-overlay-color').length > 0
            ) {
                this.hideBackgroundColorField();
            }

            // Does the element have a background overlay
            if ($activeBox.find(".is-overlay-bg").length > 0) {
                let overlayBg = $activeBox.find(".is-overlay-bg");

                // Does this bg have the lazy load effect
                if (overlayBg.hasClass("lazyload")) {
                    jQuery("#chkLazyBg").prop("checked", true);
                } else {
                    jQuery("#chkLazyBg").prop("checked", false);
                }

                // Does this bg have the ken burns effect
                if (overlayBg.hasClass("is-scale-animated")) {
                    jQuery("#chkAnimateBg").prop("checked", true);
                } else {
                    jQuery("#chkAnimateBg").prop("checked", false);
                }

                // Does this box have the parallax effect
                if (overlayBg.attr("style") && overlayBg.attr("style").indexOf("scale(1.05)") !== -1) {
                    jQuery("#chkParallaxBg").prop("checked", true);
                } else {
                    jQuery("#chkParallaxBg").prop("checked", false);
                }

                // Does this box have a mode setting
                if (overlayBg.attr("data-mode")) {
                    jQuery(".input-image-mode").val(overlayBg.attr("data-mode"));
                } else {
                    overlayBg.attr("data-mode", 'resizeFit');
                    jQuery(".input-image-mode").val('resizeFit');
                }

                // Does this box have a quality setting
                if (overlayBg.attr("data-quality")) {
                    jQuery(".input-image-quality").val(overlayBg.attr("data-quality"));
                } else {
                    let defaultQuality = 80;
                    overlayBg.attr("data-quality", defaultQuality);
                    jQuery(".input-image-quality").val(defaultQuality);
                }

                // Does this box have a width setting
                if (overlayBg.attr("data-width")) {
                    jQuery(".input-image-width").val(overlayBg.attr("data-width"));
                } else {
                    jQuery(".input-image-width").val(null);
                }

                // Does this box have a height setting
                if (overlayBg.attr("data-height")) {
                    jQuery(".input-image-height").val(overlayBg.attr("data-height"));
                } else {
                    jQuery(".input-image-height").val(null);
                }
            }

            // Is the element a section
            if ($activeBox.hasClass("is-section")) {
                this.hideBoxSizeField();
            } else {
                this.showBoxSizeField();
            }

            // does the box have no settings
            if (this.editBoxHasNoSettings()) {
                jQuery("#divNoBoxSettings").css("display", "block"); //Show info: This box has no available settings
            } else {
                jQuery("#divNoBoxSettings").css("display", "none"); //Hide info
            }

            //$activeBox.prepend('<div class="box-active"></div>')
            $activeBox.addClass('box-active');

            // get the modal
            var $modal = jQuery('.is-modal.editbox');
            $element.data("contentbox").showModal($modal);

            // if we click off the modal
            $modal.not('.is-modal *').off('click');
            $modal.not('.is-modal *').on('click', function (e) {
                if (jQuery(e.target).hasClass('is-modal')) {
                    $element.data("contentbox").hideModal($modal);
                    jQuery('.box-active').removeClass('box-active');
                }
            });

            // if we click on a tab
            $modal.find('.is-tabs a').off('click');
            $modal.find('.is-tabs a').on('click', function () {

                if (jQuery(this).hasClass('active')) return false;

                $modal.find('.is-tabs > a').removeClass('active');
                jQuery(this).addClass('active');

                var id = jQuery(this).attr('data-content');

                $modal.find('.is-tab-content ').css('display', 'none');
                jQuery('#' + id).css('display', 'block');

                return false;
            });

            // to begin with show the general tab
            $modal.find('#tabBoxGeneral').trigger('click');

            // Handle the initial value for the fields
            jQuery(".inp-box-width").val(parseInt($activeBox.find(".is-container").css("max-width")));
            jQuery('#inpBoxBgColor').val($activeBox.get(0).style.backgroundColor);

            // Handle the initial padding if any
            jQuery("#divBoxContainer button").removeClass('active');
            let container = $activeBox.find(".is-container");
            if (container.hasClass('is-custom')) {
                this.showBoxCustomPaddingFields();
                jQuery(".cmd-box-custom-padding").addClass('active');
                jQuery(".input-padding-top").val(parseInt(container.css("padding-top")));
                jQuery(".input-padding-left").val(parseInt(container.css("padding-left")));
                jQuery(".input-padding-right").val(parseInt(container.css("padding-right")));
                jQuery(".input-padding-bottom").val(parseInt(container.css("padding-bottom")));

            } else if (container.hasClass('is-stretch-h') || container.hasClass('is-stretch-w')) {
                jQuery(".cmd-box-no-padding").addClass('active');
                this.hideBoxCustomPaddingFields();
            } else {
                jQuery(".cmd-box-default-padding").addClass('active');
                this.hideBoxCustomPaddingFields();
            }

            // Handle the events
            this.handleEditBoxEvents();

            // animation delay
            jQuery('.cmd-box-animatedelay')
                .unbind('change')
                .change(function (e) {

                    _fb.saveForUndo();

                    $activeBox.removeClass('delay-0ms');
                    $activeBox.removeClass('delay-100ms');
                    $activeBox.removeClass('delay-200ms');
                    $activeBox.removeClass('delay-300ms');
                    $activeBox.removeClass('delay-400ms');
                    $activeBox.removeClass('delay-500ms');
                    $activeBox.removeClass('delay-600ms');
                    $activeBox.removeClass('delay-700ms');
                    $activeBox.removeClass('delay-800ms');
                    $activeBox.removeClass('delay-900ms');
                    $activeBox.removeClass('delay-1000ms');
                    $activeBox.removeClass('delay-1100ms');
                    $activeBox.removeClass('delay-1200ms');
                    $activeBox.removeClass('delay-1300ms');
                    $activeBox.removeClass('delay-1400ms');
                    $activeBox.removeClass('delay-1500ms');
                    $activeBox.removeClass('delay-1600ms');
                    $activeBox.removeClass('delay-1700ms');
                    $activeBox.removeClass('delay-1800ms');
                    $activeBox.removeClass('delay-1900ms');
                    $activeBox.removeClass('delay-2000ms');
                    $activeBox.removeClass('delay-2100ms');
                    $activeBox.removeClass('delay-2200ms');
                    $activeBox.removeClass('delay-2300ms');
                    $activeBox.removeClass('delay-2400ms');
                    $activeBox.removeClass('delay-2500ms');
                    $activeBox.removeClass('delay-2600ms');
                    $activeBox.removeClass('delay-2700ms');
                    $activeBox.removeClass('delay-2800ms');
                    $activeBox.removeClass('delay-2900ms');
                    $activeBox.removeClass('delay-3000ms');

                    if (jQuery(this).val() != '') {
                        $activeBox.addClass(jQuery(this).val());
                    }

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    e.preventDefault();
                    e.stopImmediatePropagation();
                });

            jQuery("#inpBoxHtml").val(jQuery.trim($activeBox.html()));

            jQuery(".cmd-box-html")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();
                    $activeBox.html(jQuery("#inpBoxHtml").val());
                    $element.data("contentbox").settings.onChange();
                    return false;
                });
        };

        /**
         * Show image tab
         *
         * @private
         */
        this.showEditBoxImageTab = function () {
            jQuery("#tabBoxImage").css("display", "inline-block");
        }

        /**
         * Hide image tab
         *
         * @private
         */
        this.hideEditBoxImageTab = function () {
            jQuery("#tabBoxImage").css("display", "none");
        }

        /**
         * Show module tab
         *
         * @private
         */
        this.showEditBoxModuleTab = function () {
            jQuery("#tabBoxModule").css("display", "inline-block");
        }

        /**
         * Hide module tab
         *
         * @private
         */
        this.hideEditBoxModuleTab = function () {
            jQuery("#tabBoxModule").css("display", "none");
        }

        /**
         * Handle module tab
         *
         * @private
         */
        this.handleEditBoxModuleTab = function () {

            // is module setting enabled
            if (! $element.data("contentbox").settings.enableModule) {
                this.hideEditBoxModuleTab();
            } else {
                this.showEditBoxModuleTab();
            }
        }

        /**
         * Show pick photo field
         *
         * @private
         */
        this.showPickPhotoField = function () {
            jQuery("#divBoxPickPhoto").css("display", "block");
        }

        /**
         * Hide pick photo field
         */
        this.hidePickPhotoField = function () {
            jQuery("#divBoxPickPhoto").css("display", "none");
        }

        /**
         * Handle pick photo field
         *
         * @private
         */
        this.handlePickPhotoField = function () {

            // Is photoselect enabled
            if ($element.data("contentbox").settings.photoselect == '') {
                this.hidePickPhotoField();
            } else {
                this.showPickPhotoField();
            }
        }

        /**
         * Handle image effect fields
         *
         * @private
         */
        this.handleImageEffectFields = function () {

            // If the overlay bg does not have color
            if ($activeBox.find(".is-overlay-bg").children().not('.is-overlay-color').length > 0) { //There is content within background overlay
                jQuery("#chkLazyBg").parents(".is-settings").css("display", "none");
                jQuery("#chkAnimateBg").parents(".is-settings").css("display", "none");
                jQuery("#chkParallaxBg").parents(".is-settings").css("display", "none");
            } else {
                jQuery("#chkLazyBg").parents(".is-settings").css("display", "inline-block");
                jQuery("#chkAnimateBg").parents(".is-settings").css("display", "inline-block");
                jQuery("#chkParallaxBg").parents(".is-settings").css("display", "inline-block");
            }
        }

        /**
         * Show animation tab
         *
         * @private
         */
        this.showEditBoxAnimationTab = function () {
            jQuery("#tabBoxAnimate").css("display", "inline-block");
        }

        /**
         * Hide animation tab
         *
         * @private
         */
        this.hideEditBoxAnimationTab = function () {
            jQuery("#tabBoxAnimate").css("display", "none");
        }

        /**
         * Handle animation tab
         *
         * @private
         */
        this.handleEditBoxAnimationTab = function () {

            // Handle animation tab
            if (! $element.data("contentbox").settings.enableAnimation) {
                this.hideEditBoxAnimationTab();
            } else {
                this.showEditBoxAnimationTab();
            }
        }

        /**
         * Show text tab
         *
         * @private
         */
        this.showEditBoxTextTab = function () {
            jQuery("#tabBoxContentText").css("display", "inline-block");
        }

        /**
         * Hide text tab
         *
         * @private
         */
        this.hideEditBoxTextTab = function () {
            jQuery("#tabBoxContentText").css("display", "none");
        }

        /**
         * Show content tab
         *
         * @private
         */
        this.showEditBoxContentTab = function () {
            jQuery("#tabBoxContentContainer").css("display", "inline-block");
        }

        /**
         * Hide content tab
         *
         * @private
         */
        this.hideEditBoxContentTab = function () {
            jQuery("#tabBoxContentContainer").css("display", "none");
        }

        /**
         * Show content width field
         *
         * @private
         */
        this.showContentWidthField = function () {
            jQuery("#divContentWidth").css("display", "inline-block");
        }

        /**
         * Hide content width field
         *
         * @private
         */
        this.hideContentWidthField = function () {
            jQuery("#divContentWidth").css("display", "none");
        }

        /**
         * Show content height field
         *
         * @private
         */
        this.showContentHeightField = function () {
            jQuery("#divContentHeight").css("display", "inline-block");
        }

        /**
         * Hide content height field
         *
         * @private
         */
        this.hideContentHeightField = function () {
            jQuery("#divContentHeight").css("display", "none");
        }

        /**
         * Show background color field
         *
         * @private
         */
        this.showBackgroundColorField = function () {
            jQuery("#divBoxBackgroundColor").css("display", "block");
        }

        /**
         * Hide background color field
         *
         * @private
         */
        this.hideBackgroundColorField = function () {
            jQuery("#divBoxBackgroundColor").css("display", "none");
        }

        /**
         * Show box size field
         *
         * @private
         */
        this.showBoxSizeField = function () {
            jQuery("#divBoxSize").css("display", "block");
        }

        /**
         * Hide box size field
         *
         * @private
         */
        this.hideBoxSizeField = function () {
            jQuery("#divBoxSize").css("display", "none");
        }

        /**
         * Show box padding field
         *
         * @private
         */
        this.showBoxCustomPaddingFields = function () {
            jQuery("#divBoxCustomPadding").css("display", "flex");
        }

        /**
         * Hide box padding field
         *
         * @private
         */
        this.hideBoxCustomPaddingFields = function () {
            jQuery("#divBoxCustomPadding").css("display", "none");
        }

        /**
         * Does this edit box have no settings
         *
         * @private
         * @returns {boolean}
         */
        this.editBoxHasNoSettings = function () {
            return jQuery("#divBoxSize").css("display") == "none"
                && jQuery("#divBoxBackgroundColor").css("display") == "none"
                && jQuery("#tabBoxContentText").css("display") == "none"
                && jQuery("#tabBoxContentContainer").css("display") == "none"
                && jQuery("#tabBoxImage").css("display") == "none"
                && jQuery("#tabBoxModule").css("display") == "none"
                && jQuery("#tabBoxAnimate").css("display") == "none"
                && jQuery("#tabBoxCustomHtml").css("display") == "none";
        }

        /**
         * Handle edit box size events
         *
         * @private
         */
        this.handleEditBoxSizeEvents = function () {

            jQuery(".cmd-box-smaller")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();
                    $element.data("contentbox").boxWidthSmaller(jQuery(this).data("value"));
                    $element.data("contentbox").settings.onChange();
                    return false;
                });

            jQuery(".cmd-box-larger")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();
                    $element.data("contentbox").boxWidthLarger(jQuery(this).data("value"));
                    $element.data("contentbox").settings.onChange();
                    return false;
                });
        }

        /**
         * @private
         */
        this.resetBoxCustomPadding = function () {

            $activeBox.find(".is-container")
                .removeClass("is-custom")
                .css("padding-top", '')
                .css("padding-right", '')
                .css("padding-bottom", '')
                .css("padding-left", '');

            jQuery(".input-padding-top").val(null);
            jQuery(".input-padding-right").val(null);
            jQuery(".input-padding-bottom").val(null);
            jQuery(".input-padding-left").val(null);
        }

        /**
         * @private
         */
        this.resetBoxNoPadding = function () {

            $activeBox.find(".is-container")
                .removeClass("is-stretch-h")
                .removeClass("is-stretch-w");
        }

        /**
         * Handle edit box padding events
         *
         * @private
         */
        this.handleEditBoxPaddingEvents = function () {
            let _this = this;

            jQuery(".cmd-box-default-padding")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();

                    jQuery("#divBoxContainer button").removeClass('active');
                    jQuery(this).addClass('active');

                    _this.hideBoxCustomPaddingFields();
                    _this.resetBoxCustomPadding();
                    _this.resetBoxNoPadding();

                    $element.data("contentbox").settings.onChange();

                    return false;
                });

            jQuery(".cmd-box-custom-padding")
                .unbind("click")
                .on('click', function (e) {
                    jQuery("#divBoxContainer button").removeClass('active');
                    jQuery(this).addClass('active');

                    _this.showBoxCustomPaddingFields();

                    return false;
                });

            jQuery(".cmd-box-no-padding")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();

                    jQuery("#divBoxContainer button").removeClass('active');
                    jQuery(this).addClass('active');

                    _this.hideBoxCustomPaddingFields();
                    _this.resetBoxCustomPadding();

                    $activeBox.find(".is-container")
                        .addClass("is-stretch-h")
                        .addClass("is-stretch-w");

                    $element.data("contentbox").settings.onChange();

                    return false;
                });

            jQuery(".input-padding-top")
                .unbind("keyup")
                .on("keyup", function (e) {

                    _this.resetBoxNoPadding();
                    $activeBox.find(".is-container").addClass("is-custom");

                    var val = jQuery(".input-padding-top").val();
                    if (! isNaN(val) && val <= 999) {
                        $activeBox.find(".is-container").css("padding-top", val + "px");
                    }

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });

            jQuery(".input-padding-right")
                .unbind("keyup")
                .on("keyup", function (e) {

                    _this.resetBoxNoPadding();
                    $activeBox.find(".is-container").addClass("is-custom");

                    var val = jQuery(".input-padding-right").val();
                    if (! isNaN(val) && val <= 999) {
                        $activeBox.find(".is-container").css("padding-right", val + "px");
                    }

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });

            jQuery(".input-padding-bottom")
                .unbind("keyup")
                .on("keyup", function (e) {

                    _this.resetBoxNoPadding();
                    $activeBox.find(".is-container").addClass("is-custom");

                    var val = jQuery(".input-padding-bottom").val();
                    if (! isNaN(val) && val <= 999) {
                        $activeBox.find(".is-container").css("padding-bottom", val + "px");
                    }

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });

            jQuery(".input-padding-left")
                .unbind("keyup")
                .on("keyup", function (e) {

                    _this.resetBoxNoPadding();
                    $activeBox.find(".is-container").addClass("is-custom");

                    var val = jQuery(".input-padding-left").val();
                    if (! isNaN(val) && val <= 999) {
                        $activeBox.find(".is-container").css("padding-left", val + "px");
                    }

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });
        }

        /**
         * Reset the edit box widths
         *
         * @private
         */
        this.resetBoxWidths = function () {
            let container = $activeBox.find(".is-container");
            let classesToRemove = [
                "is-content-380",
                "is-content-500",
                "is-content-640",
                "is-content-800",
                "is-content-970",
                "is-content-980",
                "is-content-1050",
                "is-content-1100",
                "is-content-1200",
                "is-content-full"
            ];

            // Loop through the classes and remove them
            for (let i = 0; i < classesToRemove.length; i++) {
                if (container.hasClass(classesToRemove[i])) {
                    container.removeClass(classesToRemove[i]);
                }
            }
        }

        /**
         * Handle edit box width events
         *
         * @private
         */
        this.handleEditBoxWidthEvents = function () {

            let _this = this;

            jQuery(".cmd-box-width")
                .unbind("click")
                .on('click', function (e) {

                    _fb.saveForUndo();

                    //$element.data("contentbox").boxWidth(jQuery(this).data("value"));

                    //backward
                    _this.resetBoxWidths()

                    // Set the nax width to 100%
                    $activeBox.find(".is-container")
                        .addClass("is-content-full")
                        .css("max-width", "100%");

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });

            jQuery(".inp-box-width")
                .unbind("keyup")
                .on("keyup", function (e) {

                    //backward
                    _this.resetBoxWidths()

                    var val = jQuery(".inp-box-width").val();
                    if (! isNaN(val) && val >= 250) {
                        $activeBox.find(".is-container")
                            .css("max-width", val + "px");
                    }

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });
        }

        /**
         * Handle edit box position events
         *
         * @private
         */
        this.handleEditBoxPositionEvents = function () {

            jQuery(".cmd-box-content-pos")
                .unbind("click")
                .on('click', function (e) {

                    _fb.saveForUndo();

                    $activeBox.find(".edge-y--5").removeClass("edge-y--5");
                    $activeBox.find(".edge-y--4").removeClass("edge-y--4");
                    $activeBox.find(".edge-y--3").removeClass("edge-y--3");
                    $activeBox.find(".edge-y--2").removeClass("edge-y--2");
                    $activeBox.find(".edge-y--1").removeClass("edge-y--1");
                    $activeBox.find(".edge-y-0").removeClass("edge-y-0");
                    $activeBox.find(".edge-y-1").removeClass("edge-y-1");
                    $activeBox.find(".edge-y-2").removeClass("edge-y-2");
                    $activeBox.find(".edge-y-3").removeClass("edge-y-3");
                    $activeBox.find(".edge-y-4").removeClass("edge-y-4");
                    $activeBox.find(".edge-y-5").removeClass("edge-y-5");

                    $activeBox.find(".edge-x-0").removeClass("edge-x-0");
                    $activeBox.find(".edge-x-1").removeClass("edge-x-1");
                    $activeBox.find(".edge-x-2").removeClass("edge-x-2");
                    $activeBox.find(".edge-x-3").removeClass("edge-x-3");
                    $activeBox.find(".edge-x-4").removeClass("edge-x-4");
                    $activeBox.find(".edge-x-5").removeClass("edge-x-5");

                    $activeBox.find(".is-box-centered").removeClass("is-content-top");
                    $activeBox.find(".is-box-centered").removeClass("is-content-bottom");
                    $activeBox.removeClass("is-content-top"); //simplified
                    $activeBox.removeClass("is-content-bottom"); //simplified

                    $activeBox.find(".is-container").removeClass("is-content-left");
                    $activeBox.find(".is-container").removeClass("is-content-right");

                    var s = jQuery(this).data("value");
                    if (s == "topleft") {
                        $activeBox.find(".is-box-centered").addClass("is-content-top");
                        $activeBox.addClass("is-content-top"); //simplified

                        $activeBox.find(".is-container").addClass("is-content-left");
                    }
                    if (s == "topcenter") {
                        $activeBox.find(".is-box-centered").addClass("is-content-top");
                        $activeBox.addClass("is-content-top"); //simplified

                        $activeBox.find(".is-container").removeClass("is-content-left");
                    }
                    if (s == "topright") {
                        $activeBox.find(".is-box-centered").addClass("is-content-top");
                        $activeBox.addClass("is-content-top"); //simplified

                        $activeBox.find(".is-container").addClass("is-content-right");
                    }
                    if (s == "middleleft") {
                        $activeBox.find(".is-container").addClass("is-content-left");
                    }
                    if (s == "middlecenter") {

                    }
                    if (s == "middleright") {
                        $activeBox.find(".is-container").addClass("is-content-right");
                    }
                    if (s == "bottomleft") {
                        $activeBox.find(".is-box-centered").addClass("is-content-bottom");
                        $activeBox.addClass("is-content-bottom"); //simplified

                        $activeBox.find(".is-container").addClass("is-content-left");
                    }
                    if (s == "bottomcenter") {
                        $activeBox.find(".is-box-centered").addClass("is-content-bottom");
                        $activeBox.addClass("is-content-bottom"); //simplified
                    }
                    if (s == "bottomright") {
                        $activeBox.find(".is-box-centered").addClass("is-content-bottom");
                        $activeBox.addClass("is-content-bottom"); //simplified

                        $activeBox.find(".is-container").addClass("is-content-right");
                    }

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });

            jQuery(".cmd-box-content-edge-x")
                .unbind("click")
                .on('click', function (e) {

                    _fb.saveForUndo();

                    var s = jQuery(this).data("value");
                    if (s == "-") {
                        if ($activeBox.find(".is-container").hasClass("edge-x-0")) {
                            return false;
                        } else if ($activeBox.find(".is-container").hasClass("edge-x-1")) {
                            $activeBox.find(".is-container").removeClass("edge-x-1");
                            $activeBox.find(".is-container").addClass("edge-x-0");
                        } else if ($activeBox.find(".is-container").hasClass("edge-x-2")) {
                            $activeBox.find(".is-container").removeClass("edge-x-2");
                            $activeBox.find(".is-container").addClass("edge-x-1")
                        } else if ($activeBox.find(".is-container").hasClass("edge-x-3")) {
                            $activeBox.find(".is-container").removeClass("edge-x-3");
                            $activeBox.find(".is-container").addClass("edge-x-2")
                        } else if ($activeBox.find(".is-container").hasClass("edge-x-4")) {
                            $activeBox.find(".is-container").removeClass("edge-x-4");
                            $activeBox.find(".is-container").addClass("edge-x-3")
                        } else if ($activeBox.find(".is-container").hasClass("edge-x-5")) {
                            $activeBox.find(".is-container").removeClass("edge-x-5");
                            $activeBox.find(".is-container").addClass("edge-x-4")
                        } else {
                            $activeBox.find(".is-container").addClass("edge-x-0");
                        }
                    }

                    if (s == "+") {
                        if ($activeBox.find(".is-container").hasClass("edge-x-0")) {
                            $activeBox.find(".is-container").removeClass("edge-x-0");
                            $activeBox.find(".is-container").addClass("edge-x-1")
                        } else if ($activeBox.find(".is-container").hasClass("edge-x-1")) {
                            $activeBox.find(".is-container").removeClass("edge-x-1");
                            $activeBox.find(".is-container").addClass("edge-x-2")
                        } else if ($activeBox.find(".is-container").hasClass("edge-x-2")) {
                            $activeBox.find(".is-container").removeClass("edge-x-2");
                            $activeBox.find(".is-container").addClass("edge-x-3")
                        } else if ($activeBox.find(".is-container").hasClass("edge-x-3")) {
                            $activeBox.find(".is-container").removeClass("edge-x-3");
                            $activeBox.find(".is-container").addClass("edge-x-4")
                        } else if ($activeBox.find(".is-container").hasClass("edge-x-4")) {
                            $activeBox.find(".is-container").removeClass("edge-x-4");
                            $activeBox.find(".is-container").addClass("edge-x-5")
                        } else if ($activeBox.find(".is-container").hasClass("edge-x-5")) {
                            return false;
                        } else {
                            $activeBox.find(".is-container").addClass("edge-x-0")
                        }
                    }

                    if (s == "") {
                        $activeBox.find(".is-container").removeClass("edge-x-0");
                        $activeBox.find(".is-container").removeClass("edge-x-1");
                        $activeBox.find(".is-container").removeClass("edge-x-2");
                        $activeBox.find(".is-container").removeClass("edge-x-3");
                        $activeBox.find(".is-container").removeClass("edge-x-4");
                        $activeBox.find(".is-container").removeClass("edge-x-5");
                    }

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });

            jQuery(".cmd-box-content-edge-y")
                .unbind("click")
                .on('click', function (e) {

                    _fb.saveForUndo();

                    var s = jQuery(this).data("value");
                    if (s == "-") {
                        if ($activeBox.find(".is-box-centered").hasClass("edge-y--5")) {
                            return false;
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y--4")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y--4");
                            $activeBox.find(".is-box-centered").addClass("edge-y--5")
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y--3")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y--3");
                            $activeBox.find(".is-box-centered").addClass("edge-y--4")
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y--2")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y--2");
                            $activeBox.find(".is-box-centered").addClass("edge-y--3")
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y--1")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y--1");
                            $activeBox.find(".is-box-centered").addClass("edge-y--2")
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y-0")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y-0");
                            $activeBox.find(".is-box-centered").addClass("edge-y--1");
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y-1")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y-1");
                            $activeBox.find(".is-box-centered").addClass("edge-y-0");
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y-2")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y-2");
                            $activeBox.find(".is-box-centered").addClass("edge-y-1")
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y-3")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y-3");
                            $activeBox.find(".is-box-centered").addClass("edge-y-2")
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y-4")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y-4");
                            $activeBox.find(".is-box-centered").addClass("edge-y-3")
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y-5")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y-5");
                            $activeBox.find(".is-box-centered").addClass("edge-y-4")
                        } else {
                            $activeBox.find(".is-box-centered").addClass("edge-y-0");
                        }
                    }

                    if (s == "+") {
                        if ($activeBox.find(".is-box-centered").hasClass("edge-y--5")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y--5");
                            $activeBox.find(".is-box-centered").addClass("edge-y--4")
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y--4")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y--4");
                            $activeBox.find(".is-box-centered").addClass("edge-y--3")
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y--3")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y--3");
                            $activeBox.find(".is-box-centered").addClass("edge-y--2")
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y--2")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y--2");
                            $activeBox.find(".is-box-centered").addClass("edge-y--1")
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y--1")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y--1");
                            $activeBox.find(".is-box-centered").addClass("edge-y-0")
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y-0")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y-0");
                            $activeBox.find(".is-box-centered").addClass("edge-y-1")
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y-1")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y-1");
                            $activeBox.find(".is-box-centered").addClass("edge-y-2")
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y-2")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y-2");
                            $activeBox.find(".is-box-centered").addClass("edge-y-3")
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y-3")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y-3");
                            $activeBox.find(".is-box-centered").addClass("edge-y-4")
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y-4")) {
                            $activeBox.find(".is-box-centered").removeClass("edge-y-4");
                            $activeBox.find(".is-box-centered").addClass("edge-y-5")
                        } else if ($activeBox.find(".is-box-centered").hasClass("edge-y-5")) {
                            return false;
                        } else {
                            $activeBox.find(".is-box-centered").addClass("edge-y-0")
                        }
                    }

                    if (s == "") {
                        $activeBox.find(".is-box-centered").removeClass("edge-y--5");
                        $activeBox.find(".is-box-centered").removeClass("edge-y--4");
                        $activeBox.find(".is-box-centered").removeClass("edge-y--3");
                        $activeBox.find(".is-box-centered").removeClass("edge-y--2");
                        $activeBox.find(".is-box-centered").removeClass("edge-y--1");
                        $activeBox.find(".is-box-centered").removeClass("edge-y-0");
                        $activeBox.find(".is-box-centered").removeClass("edge-y-1");
                        $activeBox.find(".is-box-centered").removeClass("edge-y-2");
                        $activeBox.find(".is-box-centered").removeClass("edge-y-3");
                        $activeBox.find(".is-box-centered").removeClass("edge-y-4");
                        $activeBox.find(".is-box-centered").removeClass("edge-y-5");
                    }

                    //simplified
                    if (s == "-") {
                        if ($activeBox.hasClass("edge-y--5")) {
                            return false;
                        } else if ($activeBox.hasClass("edge-y--4")) {
                            $activeBox.removeClass("edge-y--4");
                            $activeBox.addClass("edge-y--5")
                        } else if ($activeBox.hasClass("edge-y--3")) {
                            $activeBox.removeClass("edge-y--3");
                            $activeBox.addClass("edge-y--4")
                        } else if ($activeBox.hasClass("edge-y--2")) {
                            $activeBox.removeClass("edge-y--2");
                            $activeBox.addClass("edge-y--3")
                        } else if ($activeBox.hasClass("edge-y--1")) {
                            $activeBox.removeClass("edge-y--1");
                            $activeBox.addClass("edge-y--2")
                        } else if ($activeBox.hasClass("edge-y-0")) {
                            $activeBox.removeClass("edge-y-0");
                            $activeBox.addClass("edge-y--1");
                        } else if ($activeBox.hasClass("edge-y-1")) {
                            $activeBox.removeClass("edge-y-1");
                            $activeBox.addClass("edge-y-0");
                        } else if ($activeBox.hasClass("edge-y-2")) {
                            $activeBox.removeClass("edge-y-2");
                            $activeBox.addClass("edge-y-1")
                        } else if ($activeBox.hasClass("edge-y-3")) {
                            $activeBox.removeClass("edge-y-3");
                            $activeBox.addClass("edge-y-2")
                        } else if ($activeBox.hasClass("edge-y-4")) {
                            $activeBox.removeClass("edge-y-4");
                            $activeBox.addClass("edge-y-3")
                        } else if ($activeBox.hasClass("edge-y-5")) {
                            $activeBox.removeClass("edge-y-5");
                            $activeBox.addClass("edge-y-4")
                        } else {
                            $activeBox.addClass("edge-y-0");
                        }
                    }

                    if (s == "+") {
                        if ($activeBox.hasClass("edge-y--5")) {
                            $activeBox.removeClass("edge-y--5");
                            $activeBox.addClass("edge-y--4")
                        } else if ($activeBox.hasClass("edge-y--4")) {
                            $activeBox.removeClass("edge-y--4");
                            $activeBox.addClass("edge-y--3")
                        } else if ($activeBox.hasClass("edge-y--3")) {
                            $activeBox.removeClass("edge-y--3");
                            $activeBox.addClass("edge-y--2")
                        } else if ($activeBox.hasClass("edge-y--2")) {
                            $activeBox.removeClass("edge-y--2");
                            $activeBox.addClass("edge-y--1")
                        } else if ($activeBox.hasClass("edge-y--1")) {
                            $activeBox.removeClass("edge-y--1");
                            $activeBox.addClass("edge-y-0")
                        } else if ($activeBox.hasClass("edge-y-0")) {
                            $activeBox.removeClass("edge-y-0");
                            $activeBox.addClass("edge-y-1")
                        } else if ($activeBox.hasClass("edge-y-1")) {
                            $activeBox.removeClass("edge-y-1");
                            $activeBox.addClass("edge-y-2")
                        } else if ($activeBox.hasClass("edge-y-2")) {
                            $activeBox.removeClass("edge-y-2");
                            $activeBox.addClass("edge-y-3")
                        } else if ($activeBox.hasClass("edge-y-3")) {
                            $activeBox.removeClass("edge-y-3");
                            $activeBox.addClass("edge-y-4")
                        } else if ($activeBox.hasClass("edge-y-4")) {
                            $activeBox.removeClass("edge-y-4");
                            $activeBox.addClass("edge-y-5")
                        } else if ($activeBox.hasClass("edge-y-5")) {
                            return false;
                        } else {
                            $activeBox.addClass("edge-y-0")
                        }
                    }

                    if (s == "") {
                        $activeBox.removeClass("edge-y--5");
                        $activeBox.removeClass("edge-y--4");
                        $activeBox.removeClass("edge-y--3");
                        $activeBox.removeClass("edge-y--2");
                        $activeBox.removeClass("edge-y--1");
                        $activeBox.removeClass("edge-y-0");
                        $activeBox.removeClass("edge-y-1");
                        $activeBox.removeClass("edge-y-2");
                        $activeBox.removeClass("edge-y-3");
                        $activeBox.removeClass("edge-y-4");
                        $activeBox.removeClass("edge-y-5");
                    }

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });
        }

        /**
         * Handle edit box text color events
         *
         * @private
         */
        this.handleEditBoxTextColorEvents = function () {

            jQuery(".cmd-box-textcolor")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();
                    $element.data("contentbox").boxTextColor(jQuery(this).data("value"));
                    $element.data("contentbox").settings.onChange();
                    return false;
                });
        }

        /**
         * Handle edit box text align events
         *
         * @private
         */
        this.handleEditBoxTextAlignEvents = function () {

            jQuery(".cmd-box-textalign")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();
                    $element.data("contentbox").boxTextAlign(jQuery(this).data("value"));
                    $element.data("contentbox").settings.onChange();
                    return false;
                });
        }

        /**
         * Handle edit box text opacity events
         *
         * @private
         */
        this.handleEditBoxTextOpacityEvents = function () {

            jQuery(".cmd-box-textopacity")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();
                    $element.data("contentbox").boxTextOpacity(jQuery(this).data("value"));
                    $element.data("contentbox").settings.onChange();
                    return false;
                });
        }

        /**
         * Handle edit box text typography events
         *
         * @private
         */
        this.handleEditBoxTextTypographyEvents = function () {

            jQuery(".cmd-box-typography")
                .unbind("click")
                .on('click', function (e) {
                    $element.data("contentbox").hideModal($modal);

                    // Open divSidebarTypography
                    jQuery('.is-sidebar > div[data-command=typography]').click();
                    jQuery('.is-sidebar > div[data-command=typography]').attr('data-applyto', 'box');

                    return false;
                });
        }

        /**
         * Handle edit box background color events
         *
         * @private
         */
        this.handleEditBoxBackgroundColorEvents = function () {

            let _this = this;

            jQuery(".cmd-box-bgcolor")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();
                    _this.boxBgColor(jQuery(this).data("value"));
                    $element.data("contentbox").settings.onChange();
                    return false;
                });

            jQuery(".cmd-box-pickbgcolor")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo(true); // checkLater = true
                    colorpicker.open(function (s) {

                        $activeBox.css("background-image", "");
                        _this.removeBoxBgColors();

                        jQuery('#inpBoxBgColor').val(s);

                        if ($activeBox.find(".is-overlay").length > 0) {
                            var $overlay = $activeBox.find(".is-overlay");
                            if ($overlay.find(".is-overlay-bg").length > 0) {
                                $overlay.data("bg-url", $overlay.find(".is-overlay-bg").css("background-image")); //Save bg image so that it can be restored using "Default" button.
                                $overlay.find(".is-overlay-bg").remove(); //Remove bg image
                                $overlay.find(".is-overlay-color").remove(); //Remove overlay color
                            }
                        }

                        $activeBox.css("background-color", s);

                    }, jQuery('#inpBoxBgColor').val());
                });
        }

        /**
         * Handle edit box gradient events
         *
         * @private
         */
        this.handleEditBoxGradientEvents = function () {

            let _this = this;

            jQuery(".cmd-box-gradient")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo(true); // checkLater = true

                    var gradientPicker = _fb.gradientpicker();
                    gradientPicker.open($activeBox.get(0), function (gradient, textcolor) {

                        _this.removeBoxBgColors();

                        // If a gradient was selected
                        if (gradient !== '') {
                            if ($activeBox.find(".is-overlay").length > 0) {
                                var $overlay = $activeBox.find(".is-overlay");
                                if ($overlay.find(".is-overlay-bg").length > 0) {
                                    $overlay.data("bg-url", $overlay.find(".is-overlay-bg").css("background-image")); //Save bg image so that it can be restored using "Default" button.
                                    $overlay.find(".is-overlay-bg").remove(); //Remove bg image
                                    $overlay.find(".is-overlay-color").remove(); //Remove overlay color
                                }
                            }
                            $activeBox.css("background-color", '');
                            if (textcolor) {
                                $element.data("contentbox").boxTextColor(textcolor);
                            }

                        } else { // return to bg image (if any)
                            var $overlay = $activeBox.find(".is-overlay");
                            if ($activeBox.find(".is-overlay-content .is-module").length == 0) {//If not is module
                                if ($overlay.data("bg-url")) {
                                    $overlay.find(".is-overlay-bg").remove(); //cleanup from old version (there can be is-overlay-bg with display:none)
                                    $overlay.find(".is-overlay-color").remove(); //cleanup from old version (there can be is-overlay-color with display:none)
                                    //$overlay.prepend('<div class="is-overlay-color" style="opacity:0.1"></div>');
                                    //$overlay.prepend('<div class="is-overlay-bg"></div>');
                                    $overlay.prepend('<div class="is-overlay-bg" style="transform:scale(1.05)" data-bottom-top="transform:translateY(-120px) scale(1.05);" data-top-bottom="transform:translateY(120px) scale(1.05)"></div>');
                                    $overlay.find(".is-overlay-bg").prepend('<div class="is-overlay-color" style="opacity:0.1"></div>');
                                    $overlay.find(".is-overlay-bg").css("background-image", $overlay.data("bg-url"));
                                    //$overlay.removeAttr("data-bg-url");
                                    $overlay.removeData("bg-url");
                                }
                            }

                            $activeBox.css("background-image", "");
                            $element.data("contentbox").boxTextColor('');
                        }

                    });
                });
        }

        /**
         * Handle edit box overlay color events
         *
         * @private
         */
        this.handleEditBoxOverlayColorEvents = function () {

            jQuery(".cmd-box-overlaycolor")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();

                    $element.data("contentbox").boxOverlayColor(jQuery(this).data("value"));
                    $element.data("contentbox").settings.onChange();

                    return false;
                });

            jQuery(".cmd-box-pickoverlaycolor")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo(true); // checkLater = true

                    colorpicker.open(function (s) {
                        $element.data("contentbox").boxOverlayColor(s);
                    }, '');
                });
        }

        /**
         * Handle edit box overlay opacity events
         *
         * @private
         */
        this.handleEditBoxOverlayOpacityEvents = function () {

            jQuery(".cmd-box-overlayopacity")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();

                    $element.data("contentbox").boxOverlayOpacity(jQuery(this).data("value"));
                    $element.data("contentbox").settings.onChange();

                    return false;
                });
        }

        /**
         * Handle edit box image type events
         *
         * @private
         */
        this.handleEditBoxImageTypeEvents = function () {

            jQuery(".cmd-box-repeat")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();

                    $activeBox.find(".is-overlay-bg")
                        .css("background-repeat", 'repeat')
                        .css("background-size", 'auto');

                    $element.data("contentbox").settings.onChange();
                    return false;
                });

            jQuery(".cmd-box-no-repeat")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();

                    $activeBox.find(".is-overlay-bg")
                        .css("background-repeat", '')
                        .css("background-size", '');

                    $element.data("contentbox").settings.onChange();
                    return false;
                });
        }

        /**
         * Handle edit box image mode events
         *
         * @private
         */
        this.handleEditBoxImageModeEvents = function () {

            let _this = this;

            jQuery(".input-image-mode")
                .unbind("change")
                .on('change', function (e) {
                    _fb.saveForUndo();

                    let mode = jQuery(this).val();
                    if (mode === 'original') {
                        _this.hideImageQualityField();
                        _this.hideImageWidthField();
                        _this.hideImageHeightField();

                    } else {
                        _this.showImageQualityField();
                        _this.showImageWidthField();
                        _this.showImageHeightField();
                    }

                    _this.updateBackgroundImageSize();
                    $element.data("contentbox").settings.onChange();

                    return false;
                });
        }

        /**
         * Show image quality field
         *
         * @private
         */
        this.showImageQualityField = function () {
            jQuery(".image-quality-block").css("display", "inline-block");
        }

        /**
         * Hide image quality field
         *
         * @private
         */
        this.hideImageQualityField = function () {
            jQuery(".image-quality-block").css("display", "none");
        }

        /**
         * Show image width field
         *
         * @private
         */
        this.showImageWidthField = function () {
            jQuery(".image-width-block").css("display", "inline-block");
        }

        /**
         * Hide image width field
         *
         * @private
         */
        this.hideImageWidthField = function () {
            jQuery(".image-width-block").css("display", "none");
        }

        /**
         * Show image height field
         *
         * @private
         */
        this.showImageHeightField = function () {
            jQuery(".image-height-block").css("display", "inline-block");
        }

        /**
         * Hide image height field
         *
         * @private
         */
        this.hideImageHeightField = function () {
            jQuery(".image-height-block").css("display", "none");
        }

        /**
         * Update the background image size
         */
        this.updateBackgroundImageSize = function () {

            this.removeLazyLoadEffect();
            this.untickLazyLoadCheckbox();

            let defaultQuality = 80;
            let overlayBg = $activeBox.find(".is-overlay-bg");

            // Get the input values
            let mode = jQuery(".input-image-mode").val() || 'resizeFit';
            let quality = jQuery(".input-image-quality").val() || defaultQuality;
            let width = jQuery(".input-image-width").val();
            let height = jQuery(".input-image-height").val();

            // Get the original image url
            let imageUrl = overlayBg.css('background-image');

            // Remove the url text
            imageUrl = imageUrl
                .replace('url(', '')
                .replace(')', '')
                .replace(/\"/gi, "");

            // Update the url
            let backgroundImage = imageUrl;
            if (imageUrl.includes('/photos/')) {
                const regex = /(\/photos\/[0-9a-zA-z-_.]+)/g;
                let matches = imageUrl.match(regex);
                let cleanSrc = matches[0];

                // Set the dimensions
                let dimensions = '';
                if (width && height) {
                    dimensions += `w=${width}&h=${height}`;
                } else if (width) {
                    dimensions += `w=${width}`;
                } else if (height) {
                    dimensions += `h=${height}`;
                }

                // Update the url
                backgroundImage = `${cleanSrc}?mode=${mode}`;
                if (mode !== 'original' && dimensions !== '') {
                    backgroundImage = `${cleanSrc}?mode=${mode}&${dimensions}`;
                }

                // If this is not a lazy loaded image, add the quality parameter
                if (! overlayBg.hasClass("lazyload")) {
                    backgroundImage.replace(/(q=\d+)/g, '');
                    backgroundImage += `&q=${quality}`;
                }
            }

            // Replace the background image with the new dimensions
            overlayBg.css('background-image', 'url("' + backgroundImage + '")');
            overlayBg.attr("data-mode", mode);
            overlayBg.attr("data-quality", quality);

            if (width) {
                overlayBg.attr("data-width", width);
            } else {
                overlayBg.removeAttr("data-width");
            }
            if (height) {
                overlayBg.attr("data-height", height);
            } else {
                overlayBg.removeAttr("data-height");
            }
        }

        /**
         * Handle edit box image size events
         *
         * @private
         */
        this.handleEditBoxImageSizeEvents = function () {
            let _this = this;

            jQuery(".input-image-quality")
                .unbind("blur")
                .on('blur', function (e) {
                    _fb.saveForUndo();
                    _this.updateBackgroundImageSize();
                    $element.data("contentbox").settings.onChange();
                    return false;
                });

            jQuery(".input-image-width")
                .unbind("blur")
                .on('blur', function (e) {
                    _fb.saveForUndo();
                    _this.updateBackgroundImageSize();
                    $element.data("contentbox").settings.onChange();
                    return false;
                });

            jQuery(".input-image-height")
                .unbind("blur")
                .on('blur', function (e) {
                    _fb.saveForUndo();
                    _this.updateBackgroundImageSize();
                    $element.data("contentbox").settings.onChange();
                    return false;
                });
        }

        /**
         * Handle edit box image position events
         *
         * @private
         */
        this.handleEditBoxImagePositionEvents = function () {

            jQuery(".cmd-bg-img-x")
                .unbind("click")
                .on('click', function (e) {

                    _fb.saveForUndo();

                    var s = jQuery(this).data("value");
                    var bgpos = $activeBox.find(".is-overlay-bg").css("background-position").split(" ");

                    if (s == "-") {
                        var bgposx = bgpos[0].replace("%", "") * 1;
                        if (bgposx > 0) {
                            bgposx = bgposx - 10;
                        }
                    }

                    if (s == "+") {
                        var bgposx = bgpos[0].replace("%", "") * 1;
                        if (bgposx < 100) {
                            bgposx = bgposx + 10;
                        }
                    }

                    if (s == "") {
                        var bgposx = 50;
                    }

                    var bgposy = bgpos[1].replace("%", "") * 1;

                    $activeBox.find(".is-overlay-bg").css("background-position", bgposx + "%" + " " + bgposy + "%");

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });

            jQuery(".cmd-bg-img-y")
                .unbind("click")
                .on('click', function (e) {

                    _fb.saveForUndo();

                    var s = jQuery(this).data("value");
                    var bgpos = $activeBox.find(".is-overlay-bg").css("background-position").split(" ");

                    if (s == "-") {
                        var bgposy = bgpos[1].replace("%", "") * 1;
                        if (bgposy > 0) {
                            bgposy = bgposy - 10;
                        }
                    }

                    if (s == "+") {
                        var bgposy = bgpos[1].replace("%", "") * 1;
                        if (bgposy < 100) {
                            bgposy = bgposy + 10;
                        }
                    }

                    if (s == "") {
                        var bgposy = 60;
                    }

                    var bgposx = bgpos[0].replace("%", "") * 1;

                    $activeBox.find(".is-overlay-bg").css("background-position", bgposx + "%" + " " + bgposy + "%");

                    //Trigger Change event
                    $element.data("contentbox").settings.onChange();

                    return false;
                });
        }

        /**
         * Handle edit box lazy effect events
         *
         * @private
         */
        this.handleEditBoxLazyLoadEffectEvents = function () {

            jQuery("#chkLazyBg")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();
                    $element.data("contentbox").boxLazyBg();
                    $element.data("contentbox").settings.onChange();
                });
        }

        /**
         * Handle edit box ken burns effect events
         *
         * @private
         */
        this.handleEditBoxKenBurnsEffectEvents = function () {

            jQuery("#chkAnimateBg")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();
                    $element.data("contentbox").boxAnimateBg();
                    $element.data("contentbox").settings.onChange();
                });
        }

        /**
         * Handle edit box parallax effect events
         *
         * @private
         */
        this.handleEditBoxParallaxEffectEvents = function () {

            jQuery("#chkParallaxBg")
                .unbind("click")
                .on('click', function (e) {
                    _fb.saveForUndo();
                    $element.data("contentbox").boxParallaxBg();
                    $element.data("contentbox").settings.onChange();
                });
        }

        /**
         * Handle edit box module events
         *
         * @private
         */
        this.handleEditBoxModuleEvents = function () {

            jQuery("#chkBgModule")
                .unbind("click")
                .on('click', function (e) {
                    $element.data("contentbox").boxModule();
                });
        }

        /**
         * Handle edit box pick photo events
         *
         * @private
         */
        this.handleEditBoxPickPhotoEvents = function () {

            var photoselect = $element.data("contentbox").settings.photoselect;

            jQuery(".cmd-box-pickphoto")
                .unbind("click")
                .on('click', function (e) {

                    var $modal = jQuery('.is-modal.pickphoto');
                    $element.data("contentbox").showModal($modal);

                    $modal.not('.is-modal *')
                        .off('click')
                        .on('click', function (e) {
                            if (jQuery(e.target).hasClass('is-modal')) {
                                $element.data("contentbox").hideModal($modal);
                            }
                        });

                    $modal.find('iframe').attr('src', $element.data('contentbox').settings.photoselect); //load module panel on iframe

                    return false;
                });
        }

        /**
         * Handle edit box asset events
         *
         * @private
         */
        this.handleEditBoxAssetEvents = function () {

            jQuery(".cmd-box-selectasset")
                .unbind("click")
                .on('click', function (e) {
                    $element.data("contentbox").boxSelectAsset();
                    return false;
                });
        }

        /**
         * Handle edit box animate events
         *
         * @private
         */
        this.handleEditBoxAnimationEvents = function () {

            jQuery('.cmd-box-animate').val('');

            if ($activeBox.hasClass('is-pulse')) jQuery('.cmd-box-animate').val('is-pulse');
            if ($activeBox.hasClass('is-bounceIn')) jQuery('.cmd-box-animate').val('is-bounceIn');
            if ($activeBox.hasClass('is-fadeIn')) jQuery('.cmd-box-animate').val('is-fadeIn');
            if ($activeBox.hasClass('is-fadeInDown')) jQuery('.cmd-box-animate').val('is-fadeInDown');
            if ($activeBox.hasClass('is-fadeInLeft')) jQuery('.cmd-box-animate').val('is-fadeInLeft');
            if ($activeBox.hasClass('is-fadeInRight')) jQuery('.cmd-box-animate').val('is-fadeInRight');
            if ($activeBox.hasClass('is-fadeInUp')) jQuery('.cmd-box-animate').val('is-fadeInUp');
            if ($activeBox.hasClass('is-flipInX')) jQuery('.cmd-box-animate').val('is-flipInX');
            if ($activeBox.hasClass('is-flipInY')) jQuery('.cmd-box-animate').val('is-flipInY');
            if ($activeBox.hasClass('is-slideInUp')) jQuery('.cmd-box-animate').val('is-slideInUp');
            if ($activeBox.hasClass('is-slideInDown')) jQuery('.cmd-box-animate').val('is-slideInDown');
            if ($activeBox.hasClass('is-slideInLeft')) jQuery('.cmd-box-animate').val('is-slideInLeft');
            if ($activeBox.hasClass('is-slideInRight')) jQuery('.cmd-box-animate').val('is-slideInRight');
            if ($activeBox.hasClass('is-zoomIn')) jQuery('.cmd-box-animate').val('is-zoomIn');

            jQuery('.cmd-box-animate').unbind('change');
            jQuery('.cmd-box-animate').change(function (e) {

                _fb.saveForUndo();

                $activeBox.removeClass('is-animated');
                $activeBox.removeClass('is-pulse');
                $activeBox.removeClass('is-bounceIn');
                $activeBox.removeClass('is-fadeIn');
                $activeBox.removeClass('is-fadeInDown');
                $activeBox.removeClass('is-fadeInLeft');
                $activeBox.removeClass('is-fadeInRight');
                $activeBox.removeClass('is-fadeInUp');
                $activeBox.removeClass('is-flipInX');
                $activeBox.removeClass('is-flipInY');
                $activeBox.removeClass('is-slideInUp');
                $activeBox.removeClass('is-slideInDown');
                $activeBox.removeClass('is-slideInLeft');
                $activeBox.removeClass('is-slideInRight');
                $activeBox.removeClass('is-zoomIn');

                $activeBox.removeClass('animated');
                $activeBox.removeClass('pulse');
                $activeBox.removeClass('bounceIn');
                $activeBox.removeClass('fadeIn');
                $activeBox.removeClass('fadeInDown');
                $activeBox.removeClass('fadeInLeft');
                $activeBox.removeClass('fadeInRight');
                $activeBox.removeClass('fadeInUp');
                $activeBox.removeClass('flipInX');
                $activeBox.removeClass('flipInY');
                $activeBox.removeClass('slideInUp');
                $activeBox.removeClass('slideInDown');
                $activeBox.removeClass('slideInLeft');
                $activeBox.removeClass('slideInRight');
                $activeBox.removeClass('zoomIn');

                if (jQuery(this).val() != '') {
                    $activeBox.addClass('is-animated');
                    $activeBox.addClass(jQuery(this).val());

                    $activeBox.addClass('animated');
                    $activeBox.addClass(jQuery(this).val().substr(3));

                    $activeBox.removeClass('box-active'); //need this to make animation work
                }

                //Trigger Change event
                $element.data("contentbox").settings.onChange();

                e.preventDefault();
                e.stopImmediatePropagation();
            });

            jQuery('.cmd-box-animate-test').off('click');
            jQuery('.cmd-box-animate-test').on('click', function (e) {

                $activeBox.removeClass('animated');
                $activeBox.removeClass('pulse');
                $activeBox.removeClass('bounceIn');
                $activeBox.removeClass('fadeIn');
                $activeBox.removeClass('fadeInDown');
                $activeBox.removeClass('fadeInLeft');
                $activeBox.removeClass('fadeInRight');
                $activeBox.removeClass('fadeInUp');
                $activeBox.removeClass('flipInX');
                $activeBox.removeClass('flipInY');
                $activeBox.removeClass('slideInUp');
                $activeBox.removeClass('slideInDown');
                $activeBox.removeClass('slideInLeft');
                $activeBox.removeClass('slideInRight');
                $activeBox.removeClass('zoomIn');

                setTimeout(function () {
                    $activeBox.addClass('animated');
                    $activeBox.addClass(jQuery('.cmd-box-animate').val().substr(3));

                    $activeBox.removeClass('box-active'); //need this to make animation work
                }, 50);

                //Trigger Change event
                $element.data("contentbox").settings.onChange();

                e.preventDefault();
                e.stopImmediatePropagation();
            });

            if ($activeBox.hasClass('once')) {
                jQuery('#chkAnimOnce').prop("checked", true);
            } else {
                jQuery('#chkAnimOnce').prop("checked", false);
            }
            jQuery('#chkAnimOnce').off('click');
            jQuery('#chkAnimOnce').on('click', function (e) {

                _fb.saveForUndo();

                $activeBox.data('animated', '');
                if (jQuery("#chkAnimOnce").prop("checked")) {
                    $activeBox.addClass('once');
                } else {
                    $activeBox.removeClass('once');
                }

                //Trigger Change event
                $element.data("contentbox").settings.onChange();

            });

            if ($activeBox.hasClass('delay-0ms')) jQuery('.cmd-box-animatedelay').val('delay-0ms');
            if ($activeBox.hasClass('delay-100ms')) jQuery('.cmd-box-animatedelay').val('delay-100ms');
            if ($activeBox.hasClass('delay-200ms')) jQuery('.cmd-box-animatedelay').val('delay-20ms');
            if ($activeBox.hasClass('delay-300ms')) jQuery('.cmd-box-animatedelay').val('delay-300ms');
            if ($activeBox.hasClass('delay-400ms')) jQuery('.cmd-box-animatedelay').val('delay-400ms');
            if ($activeBox.hasClass('delay-500ms')) jQuery('.cmd-box-animatedelay').val('delay-500ms');
            if ($activeBox.hasClass('delay-600ms')) jQuery('.cmd-box-animatedelay').val('delay-600ms');
            if ($activeBox.hasClass('delay-700ms')) jQuery('.cmd-box-animatedelay').val('delay-700ms');
            if ($activeBox.hasClass('delay-800ms')) jQuery('.cmd-box-animatedelay').val('delay-800ms');
            if ($activeBox.hasClass('delay-900ms')) jQuery('.cmd-box-animatedelay').val('delay-900ms');
            if ($activeBox.hasClass('delay-1000ms')) jQuery('.cmd-box-animatedelay').val('delay-1000ms');
            if ($activeBox.hasClass('delay-1100ms')) jQuery('.cmd-box-animatedelay').val('delay-1100ms');
            if ($activeBox.hasClass('delay-1200ms')) jQuery('.cmd-box-animatedelay').val('delay-1200ms');
            if ($activeBox.hasClass('delay-1300ms')) jQuery('.cmd-box-animatedelay').val('delay-1300ms');
            if ($activeBox.hasClass('delay-1400ms')) jQuery('.cmd-box-animatedelay').val('delay-1400ms');
            if ($activeBox.hasClass('delay-1500ms')) jQuery('.cmd-box-animatedelay').val('delay-1500ms');
            if ($activeBox.hasClass('delay-1600ms')) jQuery('.cmd-box-animatedelay').val('delay-1600ms');
            if ($activeBox.hasClass('delay-1700ms')) jQuery('.cmd-box-animatedelay').val('delay-1700ms');
            if ($activeBox.hasClass('delay-1800ms')) jQuery('.cmd-box-animatedelay').val('delay-1800ms');
            if ($activeBox.hasClass('delay-1900ms')) jQuery('.cmd-box-animatedelay').val('delay-1900ms');
            if ($activeBox.hasClass('delay-2000ms')) jQuery('.cmd-box-animatedelay').val('delay-2000ms');
            if ($activeBox.hasClass('delay-2100ms')) jQuery('.cmd-box-animatedelay').val('delay-2100ms');
            if ($activeBox.hasClass('delay-2200ms')) jQuery('.cmd-box-animatedelay').val('delay-2200ms');
            if ($activeBox.hasClass('delay-2300ms')) jQuery('.cmd-box-animatedelay').val('delay-2300ms');
            if ($activeBox.hasClass('delay-2400ms')) jQuery('.cmd-box-animatedelay').val('delay-2400ms');
            if ($activeBox.hasClass('delay-2500ms')) jQuery('.cmd-box-animatedelay').val('delay-2500ms');
            if ($activeBox.hasClass('delay-2600ms')) jQuery('.cmd-box-animatedelay').val('delay-2600ms');
            if ($activeBox.hasClass('delay-2700ms')) jQuery('.cmd-box-animatedelay').val('delay-2700ms');
            if ($activeBox.hasClass('delay-2800ms')) jQuery('.cmd-box-animatedelay').val('delay-2800ms');
            if ($activeBox.hasClass('delay-2900ms')) jQuery('.cmd-box-animatedelay').val('delay-2900ms');
            if ($activeBox.hasClass('delay-3000ms')) jQuery('.cmd-box-animatedelay').val('delay-3000ms');
        }

        /**
         * Handle the events fired from the edit box
         *
         * @private
         */
        this.handleEditBoxEvents = function () {

            // Size events
            this.handleEditBoxPaddingEvents();
            this.handleEditBoxSizeEvents();
            this.handleEditBoxWidthEvents();
            this.handleEditBoxPositionEvents();

            // Text events
            this.handleEditBoxTextColorEvents();
            this.handleEditBoxTextAlignEvents();
            this.handleEditBoxTextOpacityEvents();
            this.handleEditBoxTextTypographyEvents();

            // Background
            this.handleEditBoxBackgroundColorEvents();
            this.handleEditBoxGradientEvents();

            // Overlay events
            this.handleEditBoxOverlayColorEvents();
            this.handleEditBoxOverlayOpacityEvents();

            // Image events
            this.handleEditBoxImageTypeEvents();
            this.handleEditBoxImageModeEvents();
            this.handleEditBoxImageSizeEvents();
            this.handleEditBoxImagePositionEvents();
            this.handleEditBoxLazyLoadEffectEvents();
            this.handleEditBoxKenBurnsEffectEvents();
            this.handleEditBoxParallaxEffectEvents();

            // Asset / photo events
            this.handleEditBoxPickPhotoEvents();
            this.handleEditBoxAssetEvents();

            // Animation
            this.handleEditBoxAnimationEvents();
        }

        /**
         * @private
         */
        this.boxWidth = function (n) {
            $activeBox.find(".is-container").css("max-width", "");
            $activeBox.find(".is-container").removeClass("is-content-380");
            $activeBox.find(".is-container").removeClass("is-content-500");
            $activeBox.find(".is-container").removeClass("is-content-640");
            $activeBox.find(".is-container").removeClass("is-content-800");
            $activeBox.find(".is-container").removeClass("is-content-970"); //backward
            $activeBox.find(".is-container").removeClass("is-content-980");
            $activeBox.find(".is-container").removeClass("is-content-1050");
            $activeBox.find(".is-container").removeClass("is-content-1100");
            $activeBox.find(".is-container").removeClass("is-content-1200");

            if (n != 0) {
                $activeBox.find(".is-container").addClass("is-content-" + n);
            }
            return false;
        };

        /**
         * @private
         */
        this.boxBgColor = function (s) {

            $activeBox.css("background-color", "");
            $activeBox.css("background-image", "");
            this.removeBoxBgColors();

            var $overlay = $activeBox.find(".is-overlay");

            if (s === "") {
                //Default button (no color, show bg image)
                if ($activeBox.find(".is-overlay-content .is-module").length == 0) {//If not is module
                    if ($overlay.data("bg-url")) {
                        $overlay.find(".is-overlay-bg").remove(); //cleanup from old version (there can be is-overlay-bg with display:none)
                        $overlay.find(".is-overlay-color").remove(); //cleanup from old version (there can be is-overlay-color with display:none)
                        //$overlay.prepend('<div class="is-overlay-color" style="opacity:0.1"></div>');
                        //$overlay.prepend('<div class="is-overlay-bg"></div>');
                        $overlay.prepend('<div class="is-overlay-bg" style="transform:scale(1.05)" data-bottom-top="transform:translateY(-120px) scale(1.05);" data-top-bottom="transform:translateY(120px) scale(1.05)"></div>');
                        $overlay.find(".is-overlay-bg").prepend('<div class="is-overlay-color" style="opacity:0.1"></div>');
                        $overlay.find(".is-overlay-bg").css("background-image", $overlay.data("bg-url"));
                        //$overlay.removeAttr("data-bg-url");
                        $overlay.removeData("bg-url");
                    }
                }
                this.boxTextColor("");

            } else {
                // Apply bg color
                $overlay.data("bg-url", $overlay.find(".is-overlay-bg").css("background-image")); //Save bg image so that it can be restored using "Default" button.
                $overlay.find(".is-overlay-bg").remove(); //Remove bg image
                $overlay.find(".is-overlay-color").remove(); //Remove overlay color

                if (s === "grey") {
                    $activeBox.addClass("is-bg-grey");
                    this.boxTextColor("dark");
                }
                if (s === "dark") {
                    $activeBox.addClass("is-bg-dark");
                    this.boxTextColor("light");
                }
                if (s === "light") {
                    $activeBox.addClass("is-bg-light");
                    this.boxTextColor("dark");
                }
                if (s === "primary") {
                    $activeBox.addClass("bg-primary");
                    this.boxTextColor("light");
                }
                if (s === "secondary") {
                    $activeBox.addClass("bg-secondary");
                    this.boxTextColor("light");
                }
                if (s === "tertiary") {
                    $activeBox.addClass("bg-tertiary");
                    this.boxTextColor("light");
                }
                if (s === "quaternary") {
                    $activeBox.addClass("bg-quaternary");
                    this.boxTextColor("light");
                }
            }

            return false;
        };

        /**
         * Get the background colours
         *
         * @returns {*[]}
         */
        this.getBoxBgColors = function () {
            return [
                'is-bg-grey',
                'is-bg-light',
                'is-bg-dark',
                'bg-primary',
                'bg-secondary',
                'bg-tertiary',
                'bg-quaternary',
            ];
        }

        /**
         * Remove the background colours
         */
        this.removeBoxBgColors = function () {
            this.getBoxBgColors().forEach(function (value) {
                if ($activeBox.hasClass(value)) {
                    $activeBox.removeClass(value)
                }
            });
        }

        /**
         * @param s
         * @private
         */
        this.boxModule = function (s) {
            var $overlay = $activeBox.find(".is-overlay");

            if ($activeBox.find(".is-overlay").length == 0) {
                $activeBox.prepend('<div class="is-overlay"></div>');
            }
            var $overlay = $activeBox.find(".is-overlay");
            if ($overlay.find(".is-overlay-content").length == 0) {
                $overlay.append('<div class="is-overlay-content"></div>');
            }

            if (jQuery("#chkBgModule").prop("checked")) {
                $overlay.find(".is-overlay-content").html("<div class='is-module'></div>"); //[%BREAK%]

                jQuery("#divBoxBackgroundColor").css("display", "block"); //show Background settings

                $overlay.find(".is-overlay-bg").remove();
                $overlay.find(".is-overlay-color").remove();
                $overlay.data("bg-url", $overlay.find(".is-overlay-bg").css("background-image"));
            } else {
                $overlay.find(".is-overlay-content").remove();

                if ($activeBox.find(".is-container").length > 0) {
                    jQuery("#divBoxBackgroundColor").css("display", "block"); //show Background settings
                } else {
                    jQuery("#divBoxBackgroundColor").css("display", "none");
                }

                //$overlay.find(".is-overlay-bg").css("display", "block");
            }
        };

        /**
         * @private
         */
        this.boxTextColor = function (s) {
            if (s === "light") {
                $activeBox.removeClass("is-dark-text");
                $activeBox.addClass("is-light-text");
            }
            if (s === "dark") {
                $activeBox.removeClass("is-light-text");
                $activeBox.addClass("is-dark-text");
            }
            if (s === "") {
                $activeBox.removeClass("is-dark-text");
                $activeBox.removeClass("is-light-text");
            }
            return false;
        };

        /**
         * @private
         */
        this.boxTextAlign = function (s) {
            $activeBox.find(".center").removeClass("center");
            $activeBox.find(".is-builder > div > div > *").css("text-align", "");
            if (s == "right") {
                $activeBox.removeClass("is-align-left");
                $activeBox.removeClass("is-align-center");
                $activeBox.removeClass("is-align-justify");
                $activeBox.addClass("is-align-right");
            }
            if (s == "center") {
                $activeBox.removeClass("is-align-left");
                $activeBox.removeClass("is-align-right");
                $activeBox.removeClass("is-align-justify");
                $activeBox.addClass("is-align-center");
            }
            if (s == "left") {
                $activeBox.removeClass("is-align-right");
                $activeBox.removeClass("is-align-center");
                $activeBox.removeClass("is-align-justify");
                $activeBox.addClass("is-align-left");
            }
            if (s == "justify") {
                $activeBox.removeClass("is-align-left");
                $activeBox.removeClass("is-align-right");
                $activeBox.removeClass("is-align-center");
                $activeBox.addClass("is-align-justify");
            }
            return false;
        };

        /**
         * @private
         */
        this.boxTextOpacity = function (s) {
            var $cb = $activeBox.find(".is-box-centered");

            if (s == "+") {
                if ($cb.hasClass("is-opacity-20")) {
                    $cb.removeClass("is-opacity-20");
                    $cb.addClass("is-opacity-25")
                } else if ($cb.hasClass("is-opacity-25")) {
                    $cb.removeClass("is-opacity-25");
                    $cb.addClass("is-opacity-30")
                } else if ($cb.hasClass("is-opacity-30")) {
                    $cb.removeClass("is-opacity-30");
                    $cb.addClass("is-opacity-35")
                } else if ($cb.hasClass("is-opacity-35")) {
                    $cb.removeClass("is-opacity-35");
                    $cb.addClass("is-opacity-40")
                } else if ($cb.hasClass("is-opacity-40")) {
                    $cb.removeClass("is-opacity-40");
                    $cb.addClass("is-opacity-45")
                } else if ($cb.hasClass("is-opacity-45")) {
                    $cb.removeClass("is-opacity-45");
                    $cb.addClass("is-opacity-50")
                } else if ($cb.hasClass("is-opacity-50")) {
                    $cb.removeClass("is-opacity-50");
                    $cb.addClass("is-opacity-55")
                } else if ($cb.hasClass("is-opacity-55")) {
                    $cb.removeClass("is-opacity-55");
                    $cb.addClass("is-opacity-60")
                } else if ($cb.hasClass("is-opacity-60")) {
                    $cb.removeClass("is-opacity-60");
                    $cb.addClass("is-opacity-65")
                } else if ($cb.hasClass("is-opacity-65")) {
                    $cb.removeClass("is-opacity-65");
                    $cb.addClass("is-opacity-70")
                } else if ($cb.hasClass("is-opacity-70")) {
                    $cb.removeClass("is-opacity-70");
                    $cb.addClass("is-opacity-75")
                } else if ($cb.hasClass("is-opacity-75")) {
                    $cb.removeClass("is-opacity-75");
                    $cb.addClass("is-opacity-80")
                } else if ($cb.hasClass("is-opacity-80")) {
                    $cb.removeClass("is-opacity-80");
                    $cb.addClass("is-opacity-85")
                } else if ($cb.hasClass("is-opacity-85")) {
                    $cb.removeClass("is-opacity-85");
                    $cb.addClass("is-opacity-90")
                } else if ($cb.hasClass("is-opacity-90")) {
                    $cb.removeClass("is-opacity-90");
                    $cb.addClass("is-opacity-95")
                } else if ($cb.hasClass("is-opacity-95")) {
                    $cb.removeClass("is-opacity-95");
                }
                return false;
            }
            if (s == "-") {
                if ($cb.hasClass("is-opacity-20")) {
                    return false;
                } else if ($cb.hasClass("is-opacity-25")) {
                    $cb.removeClass("is-opacity-25");
                    $cb.addClass("is-opacity-20")
                } else if ($cb.hasClass("is-opacity-30")) {
                    $cb.removeClass("is-opacity-30");
                    $cb.addClass("is-opacity-25")
                } else if ($cb.hasClass("is-opacity-35")) {
                    $cb.removeClass("is-opacity-35");
                    $cb.addClass("is-opacity-30")
                } else if ($cb.hasClass("is-opacity-40")) {
                    $cb.removeClass("is-opacity-40");
                    $cb.addClass("is-opacity-35")
                } else if ($cb.hasClass("is-opacity-45")) {
                    $cb.removeClass("is-opacity-45");
                    $cb.addClass("is-opacity-40")
                } else if ($cb.hasClass("is-opacity-50")) {
                    $cb.removeClass("is-opacity-50");
                    $cb.addClass("is-opacity-45")
                } else if ($cb.hasClass("is-opacity-55")) {
                    $cb.removeClass("is-opacity-55");
                    $cb.addClass("is-opacity-50")
                } else if ($cb.hasClass("is-opacity-60")) {
                    $cb.removeClass("is-opacity-60");
                    $cb.addClass("is-opacity-55")
                } else if ($cb.hasClass("is-opacity-65")) {
                    $cb.removeClass("is-opacity-65");
                    $cb.addClass("is-opacity-60")
                } else if ($cb.hasClass("is-opacity-70")) {
                    $cb.removeClass("is-opacity-70");
                    $cb.addClass("is-opacity-65")
                } else if ($cb.hasClass("is-opacity-75")) {
                    $cb.removeClass("is-opacity-75");
                    $cb.addClass("is-opacity-70")
                } else if ($cb.hasClass("is-opacity-80")) {
                    $cb.removeClass("is-opacity-80");
                    $cb.addClass("is-opacity-75")
                } else if ($cb.hasClass("is-opacity-85")) {
                    $cb.removeClass("is-opacity-85");
                    $cb.addClass("is-opacity-80")
                } else if ($cb.hasClass("is-opacity-90")) {
                    $cb.removeClass("is-opacity-90");
                    $cb.addClass("is-opacity-85")
                } else if ($cb.hasClass("is-opacity-95")) {
                    $cb.removeClass("is-opacity-95");
                    $cb.addClass("is-opacity-90")
                } else {
                    $cb.addClass("is-opacity-95")
                }
                return false;
            }

            $cb.removeClass("is-opacity-20");
            $cb.removeClass("is-opacity-25");
            $cb.removeClass("is-opacity-30");
            $cb.removeClass("is-opacity-35");
            $cb.removeClass("is-opacity-40");
            $cb.removeClass("is-opacity-45");
            $cb.removeClass("is-opacity-50");
            $cb.removeClass("is-opacity-55");
            $cb.removeClass("is-opacity-60");
            $cb.removeClass("is-opacity-65");
            $cb.removeClass("is-opacity-70");
            $cb.removeClass("is-opacity-75");
            $cb.removeClass("is-opacity-80");
            $cb.removeClass("is-opacity-85");
            $cb.removeClass("is-opacity-90");
            $cb.removeClass("is-opacity-95");

            if (s == "0.7") {
                $cb.addClass("is-opacity-70");
            }
            if (s == "0.75") {
                $cb.addClass("is-opacity-75");
            }
            if (s == "0.8") {
                $cb.addClass("is-opacity-80");
            }
            if (s == "0.85") {
                $cb.addClass("is-opacity-85");
            }
            if (s == "0.90") {
                $cb.addClass("is-opacity-90");
            }
            if (s == "0.95") {
                $cb.addClass("is-opacity-95");
            }
            return false;
        };

        /**
         * @private
         */
        this.boxWidthSmaller = function () {

            let currentBox;
            let nextBox;
            let prevBox;

            // Get the current box
            let ok = false;
            for (let i = 1; i <= 12; i++) {
                if ($activeBox.hasClass("is-box-" + i)) {
                    ok = true;
                }
            }
            if (ok) {
                currentBox = $activeBox;
            } else {
                currentBox = $activeBox.parent();
            }

            // If the current box == 1 then just return
            if (currentBox.hasClass("is-box-1")) {
                return;
            }

            // If there is a next box then update that otherwise look for a previous box
            if (currentBox.next().length > 0) {
                nextBox = currentBox.next();
                this.boxMinus(currentBox);
                this.boxPlus(nextBox);
                return false;

            } else if (currentBox.prev().length > 0) {
                prevBox = currentBox.prev();
                this.boxMinus(currentBox);
                this.boxPlus(prevBox);
                return false;
            }
        };

        /**
         * @private
         */
        this.boxWidthLarger = function () {

            let currentBox;
            let nextBox;
            let prevBox;

            // Get the current box
            let ok = false;
            for (let i = 1; i <= 12; i++) {
                if ($activeBox.hasClass("is-box-" + i)) {
                    ok = true;
                }
            }
            if (ok) {
                currentBox = $activeBox;
            } else {
                currentBox = $activeBox.parent();
            }

            // If the current box == 12 then just return
            if (currentBox.hasClass("is-box-12")) {
                return;
            }

            // If there is a next box then update that otherwise look for a previous box
            if (currentBox.next().length > 0) {
                nextBox = currentBox.next();
                this.boxPlus(currentBox);
                this.boxMinus(nextBox);
                return false;

            } else if (currentBox.prev().length > 0) {
                prevBox = currentBox.prev();
                this.boxPlus(currentBox);
                this.boxMinus(prevBox);
                return false;
            }
        };

        /**
         * @param $box
         * @private
         */
        this.boxPlus = function ($box) {
            for (let i = 1; i < 12; i++) {
                if ($box.hasClass("is-box-" + i)) {
                    $box.removeClass("is-box-" + i);
                    $box.addClass("is-box-" + (i === 12 ? i : i + 1));
                    return;
                }
            }
        };

        /**
         * @param $box
         * @private
         */
        this.boxMinus = function ($box) {
            for (let i = 12; i > 1; i--) {
                if ($box.hasClass("is-box-" + i)) {
                    $box.removeClass("is-box-" + i);
                    $box.addClass("is-box-" + (i - 1));
                    return;
                }
            }
        };

        /**
         * Un-tick the lazy load checkbox
         *
         * @private
         */
        this.untickLazyLoadCheckbox = function () {
            jQuery("#chkLazyBg").prop("checked", false);
        }

        /**
         * Add the lazy load effect to the background image
         *
         * @private
         */
        this.addLazyLoadEffect = function () {
            let $overlay = $activeBox.find(".is-overlay");
            let overlayBg = $overlay.find(".is-overlay-bg");

            // get the image src from the background image
            let imageSrc = overlayBg
                .css('background-image')
                .slice(4, -1) // remove the url() bit
                .replace(/"/g, '') // remove the quotes
                .replace(/q=5/g, ''); // remove low quality setting

            if (imageSrc.includes('/photos/')) {
                let lazyImageSrc = imageSrc.replace(/(q=\d+)/g, '');

                // Check if the imageSrc contains a ?q=5
                if (! imageSrc.includes('?')) {
                    lazyImageSrc = lazyImageSrc + '?';
                }

                // Add the low quality setting
                lazyImageSrc = lazyImageSrc + 'q=5';

                // and add it as the background image
                overlayBg.css("background-image", "url(" + lazyImageSrc + ")");
            }

            // and add it as a data attribute
            overlayBg
                .attr('data-bg', imageSrc)
                .addClass('lazyload');
        }

        /**
         * Remove the lazy load effect to the background image
         *
         * @private
         */
        this.removeLazyLoadEffect = function () {

            let $overlay = $activeBox.find(".is-overlay");
            let overlayBg = $overlay.find(".is-overlay-bg");

            if (overlayBg.attr('data-bg')) {

                // get the image src from the data attribute
                let imageSrc = overlayBg.attr('data-bg');

                // and add it back into the background image
                overlayBg
                    .css('background-image', 'url(' + imageSrc + ')')
                    .attr('data-bg', '')
                    .removeClass('lazyload');
            }
        }

        /**
         * Handle the lazy load toggle
         *
         * @private
         */
        this.boxLazyBg = function () {
            if (jQuery("#chkLazyBg").prop("checked")) {
                this.addLazyLoadEffect();
            } else {
                this.removeLazyLoadEffect();
            }
        };

        /**
         * Un-tick the ken burns checkbox
         *
         * @private
         */
        this.untickKenBurnsCheckbox = function () {
            jQuery("#chkAnimateBg").prop("checked", false);
        }

        /**
         * Add the ken burns effect to the background image
         *
         * @private
         */
        this.addKenBurnsEffect = function () {
            var $overlay = $activeBox.find(".is-overlay");
            $overlay.find(".is-overlay-bg").addClass("is-scale-animated");
            $overlay.find(".is-overlay-bg").addClass("is-appeared");
        }

        /**
         * Remove the ken burns effect to the background image
         *
         * @private
         */
        this.removeKenBurnsEffect = function () {
            var $overlay = $activeBox.find(".is-overlay");
            $overlay.find(".is-overlay-bg").removeClass("is-scale-animated");
            $overlay.find(".is-overlay-bg").removeClass("is-appeared");
        }

        /**
         * Handle the ken burns toggle
         *
         * @private
         */
        this.boxAnimateBg = function () {
            if (jQuery("#chkAnimateBg").prop("checked")) {
                this.untickParallaxCheckbox();
                this.removeParallaxEffect();
                this.addKenBurnsEffect();
            } else {
                this.removeKenBurnsEffect();
            }
        };

        /**
         * Untick the parallax checkbox
         *
         * @private
         */
        this.untickParallaxCheckbox = function () {
            jQuery("#chkParallaxBg").prop("checked", false);
        }

        /**
         * Add the parallax effect to the background image
         *
         * @private
         */
        this.addParallaxEffect = function () {
            var $overlay = $activeBox.find(".is-overlay");
            $overlay.find(".is-overlay-bg").attr("data-bottom-top", "transform:translateY(-28%) scale(1.05)");
            $overlay.find(".is-overlay-bg").attr("data-top-bottom", "transform:translateY(0%) scale(1.05)");
            $element.data("contentbox").settings.onRender();
        }

        /**
         * Remove the parallax effect to the background image
         *
         * @private
         */
        this.removeParallaxEffect = function () {
            var $overlay = $activeBox.find(".is-overlay");
            $overlay.find(".is-overlay-bg").removeClass("skrollable");
            $overlay.find(".is-overlay-bg").removeClass("skrollable-between");
            $overlay.find(".is-overlay-bg").removeAttr("data-bottom-top");
            $overlay.find(".is-overlay-bg").removeAttr("data-top-bottom");
            $overlay.find(".is-overlay-bg").css("transform", "translateY(0) scale(1)");
            $overlay.find(".is-overlay-bg").css("transform", "");

            var s = $overlay.find(".is-overlay-bg").get(0).outerHTML;
            $overlay.find(".is-overlay-bg").remove();
            $overlay.append(s);
        }

        /**
         * Handle the parallax toggle
         *
         * @private
         */
        this.boxParallaxBg = function () {
            if (jQuery("#chkParallaxBg").prop("checked")) {
                this.untickKenBurnsCheckbox();
                this.removeKenBurnsEffect();
                this.addParallaxEffect();
            } else {
                this.removeParallaxEffect();
            }
        };

        /**
         * @private
         */
        this.boxOverlayOpacity = function (s) {
            var $overlay = $activeBox.find(".is-overlay");
            var $overlaycolor = $overlay.find(".is-overlay-color");

            if ($overlaycolor.length == 0) {
                //jQuery('<div class="is-overlay-color" style="opacity:0.1"></div>').insertAfter($overlay.find('.is-overlay-bg'));
                $overlay.find(".is-overlay-bg").prepend('<div class="is-overlay-color" style="opacity:0.1"></div>');
                $overlaycolor = $overlay.find(".is-overlay-color");
            }

            if (s == "+") {
                $overlaycolor.css("display", "block");
                if ($overlaycolor.css("opacity") == 0.01) $overlaycolor.css("opacity", 0.025);
                else if ($overlaycolor.css("opacity") == 0.025) $overlaycolor.css("opacity", 0.04);
                else if ($overlaycolor.css("opacity") == 0.04) $overlaycolor.css("opacity", 0.055);
                else if ($overlaycolor.css("opacity") == 0.055) $overlaycolor.css("opacity", 0.07);
                else if ($overlaycolor.css("opacity") == 0.07) $overlaycolor.css("opacity", 0.085);
                else if ($overlaycolor.css("opacity") == 0.085) $overlaycolor.css("opacity", 0.1);
                else if ($overlaycolor.css("opacity") == 0.1) $overlaycolor.css("opacity", 0.125);
                else if ($overlaycolor.css("opacity") == 0.125) $overlaycolor.css("opacity", 0.15);
                else if ($overlaycolor.css("opacity") == 0.15) $overlaycolor.css("opacity", 0.2);
                else if ($overlaycolor.css("opacity") == 0.2) $overlaycolor.css("opacity", 0.25);
                else if ($overlaycolor.css("opacity") == 0.25) $overlaycolor.css("opacity", 0.3);
                else if ($overlaycolor.css("opacity") == 0.3) $overlaycolor.css("opacity", 0.35);
                else if ($overlaycolor.css("opacity") == 0.35) $overlaycolor.css("opacity", 0.4);
                else if ($overlaycolor.css("opacity") == 0.4) $overlaycolor.css("opacity", 0.45);
                else if ($overlaycolor.css("opacity") == 0.45) $overlaycolor.css("opacity", 0.5);
                else if ($overlaycolor.css("opacity") == 0.5) $overlaycolor.css("opacity", 0.55);
                else if ($overlaycolor.css("opacity") == 0.55) $overlaycolor.css("opacity", 0.6);
                else if ($overlaycolor.css("opacity") == 0.6) $overlaycolor.css("opacity", 0.6);
                else $overlaycolor.css("opacity", 0.15);
            }
            if (s == "-") {
                $overlaycolor.css("display", "block");
                if ($overlaycolor.css("opacity") == 0.01) {
                    $overlaycolor.css("opacity", 0.01)
                } else if ($overlaycolor.css("opacity") == 0.025) $overlaycolor.css("opacity", 0.01);
                else if ($overlaycolor.css("opacity") == 0.04) $overlaycolor.css("opacity", 0.025);
                else if ($overlaycolor.css("opacity") == 0.055) $overlaycolor.css("opacity", 0.04);
                else if ($overlaycolor.css("opacity") == 0.07) $overlaycolor.css("opacity", 0.055);
                else if ($overlaycolor.css("opacity") == 0.085) $overlaycolor.css("opacity", 0.07);
                else if ($overlaycolor.css("opacity") == 0.1) $overlaycolor.css("opacity", 0.085);
                else if ($overlaycolor.css("opacity") == 0.125) $overlaycolor.css("opacity", 0.1);
                else if ($overlaycolor.css("opacity") == 0.15) $overlaycolor.css("opacity", 0.125);
                else if ($overlaycolor.css("opacity") == 0.2) $overlaycolor.css("opacity", 0.15);
                else if ($overlaycolor.css("opacity") == 0.25) $overlaycolor.css("opacity", 0.2);
                else if ($overlaycolor.css("opacity") == 0.3) $overlaycolor.css("opacity", 0.25);
                else if ($overlaycolor.css("opacity") == 0.35) $overlaycolor.css("opacity", 0.3);
                else if ($overlaycolor.css("opacity") == 0.4) $overlaycolor.css("opacity", 0.35);
                else if ($overlaycolor.css("opacity") == 0.45) $overlaycolor.css("opacity", 0.4);
                else if ($overlaycolor.css("opacity") == 0.5) $overlaycolor.css("opacity", 0.45);
                else if ($overlaycolor.css("opacity") == 0.55) $overlaycolor.css("opacity", 0.5);
                else if ($overlaycolor.css("opacity") == 0.6) $overlaycolor.css("opacity", 0.55);
                else {
                    $overlaycolor.css("opacity", 0.15)
                }
            }
            if (s == "0") {
                $overlaycolor.remove();
            }

            return false;
        };

        /**
         * @private
         */
        this.boxOverlayColor = function (s) {
            var $overlay = $activeBox.find(".is-overlay");
            var $overlaycolor = $overlay.find(".is-overlay-color");

            if ($overlaycolor.length == 0) {
                //jQuery('<div class="is-overlay-color" style="opacity:0.1"></div>').insertAfter($overlay.find('.is-overlay-bg'));
                $overlay.find(".is-overlay-bg").prepend('<div class="is-overlay-color" style="opacity:0.1"></div>');
                $overlaycolor = $overlay.find(".is-overlay-color");
            }

            if ($overlaycolor.css("display") == "none" || $overlaycolor.css("opacity") == 0) {//backward compatible
                $overlaycolor.css("display", "block");
                $overlaycolor.css("opacity", 0.1);
            }

            if (s == '') {
                $overlaycolor.remove();
            } else {
                $overlaycolor.css("background-color", s);
            }
            return false;
        };

        /**
         * @private
         */
        this.boxSelectAsset = function () {
            var $overlay = $activeBox.find(".is-overlay");
            var $overlaybg = $overlay.find(".is-overlay-bg");
            if (this.settings.onCoverImageSelectClick) {
                this.settings.onCoverImageSelectClick($overlaybg.get(0));
            }
            return false;
        };

        /**
         * @private
         */
        this.sectionUseScroll = function () {
            if (jQuery("#chkScrollIcon").prop("checked")) {

                var $refSection = $activeSection.find(".is-section-tool");
                jQuery('<div class="is-arrow-down bounce"><a href="#"><i class="icon fas fa-arrow-down"></i></a></div>').insertBefore($refSection); /* &darr; */

                jQuery('.is-arrow-down a').on('click', function (e) {
                    if (jQuery(this).parents(".is-section").next().html()) {
                        jQuery('html,body').animate({
                            scrollTop: jQuery(this).parents(".is-section").next().offset().top
                        }, 800);
                    }
                    e.preventDefault();
                    e.stopImmediatePropagation();
                    return false;
                });

            } else {
                $activeSection.find(".is-arrow-down").remove();
            }
            return false;
        };

        /**
         * @private
         */
        this.sectionScrollIcon = function (s) {
            if (s == "light") {
                $activeSection.find(".is-arrow-down").addClass('light');
            } else {
                $activeSection.find(".is-arrow-down").removeClass('light');
            }
            return false;
        };

        /**
         * @private
         */
        this.sectionUp = function () {
            if ($activeSection.prev('.is-section').length > 0 && ! $activeSection.prev('.is-section').hasClass('is-static')) {
                var $refSection = $activeSection.prev();
                $activeSection.insertBefore($refSection);

                //Trigger Render event
                this.settings.onRender();

                jQuery('html,body').animate({
                    scrollTop: $activeSection.offset().top
                }, 600);
            }
            return false;
        };

        /**
         * @private
         */
        this.sectionDown = function () {
            if ($activeSection.next('.is-section').length > 0 && ! $activeSection.next('.is-section').hasClass('is-static')) {
                var $refSection = $activeSection.next();
                $activeSection.insertAfter($refSection);

                //Trigger Render event
                this.settings.onRender();

                jQuery('html,body').animate({
                    scrollTop: $activeSection.offset().top
                }, 600);
            }
            return false;
        };

        /**
         * @private
         */
        this.sectionTop = function () {
            var $refSection = $element.children('.is-section').not('.is-static').first();
            $activeSection.insertBefore($refSection);

            //Trigger Render event
            this.settings.onRender();

            jQuery('html,body').animate({
                scrollTop: $activeSection.offset().top
            }, 600);
            return false;
        };

        /**
         * @private
         */
        this.sectionBottom = function () {
            var $refSection = $element.children('.is-section').not('.is-static').last();
            $activeSection.insertAfter($refSection);

            //Trigger Render event
            this.settings.onRender();

            jQuery('html,body').animate({
                scrollTop: $activeSection.offset().top
            }, 600);

            return false;
        };

        /**
         * @private
         */
        this.sectionHeight = function (n) {
            $activeSection.css("height", "");
            $activeSection.removeClass("is-section-auto");
            $activeSection.removeClass("is-section-20");
            $activeSection.removeClass("is-section-30");
            $activeSection.removeClass("is-section-40");
            $activeSection.removeClass("is-section-50");
            $activeSection.removeClass("is-section-60");
            $activeSection.removeClass("is-section-75");
            $activeSection.removeClass("is-section-100");

            if (n == 0) {
                $activeSection.addClass("is-section-auto");
            } else {
                $activeSection.addClass("is-section-" + n);
            }

            //Trigger Render event
            this.settings.onRender();

            jQuery('html,body').animate({
                scrollTop: $activeSection.offset().top
            }, 600);
            return false;
        };

        /**
         * @private
         */
        this.mainCss = function () {
            var css = '';

            var links = document.getElementsByTagName("link");
            for (var i = 0; i < links.length; i++) {
                var src = links[i].href.toLowerCase();
                if (src.indexOf('basetype-') != -1) {
                    css += links[i].outerHTML;
                }
            }

            return css;
        };

        /**
         * @private
         */
        this.sectionCss = function () {
            var css = '';

            var links = document.getElementsByTagName("link");
            for (var i = 0; i < links.length; i++) {
                var src = links[i].href.toLowerCase();
                if (src.indexOf('basetype-') != -1) {
                    //noop
                } else if (src.indexOf('type-') != -1) {
                    css += links[i].outerHTML;
                }
            }

            return css;
        };

        /**
         * @private
         */
        this.html = function (bForView) {

            cleanupUnused();

            var html = _fb.readHtml($element.get(0), bForView, true);

            return html;

        };

        /**
         * @param s
         * @private
         */
        this.viewHtml = function (s) {

            var html = this.html(true); //For View

            jQuery('#inpViewHtml').val(html);

            //used  textarea from #divSidebarSource
            jQuery('textarea').removeAttr('data-source-active');
            jQuery('textarea').removeAttr('data-source-ok');
            jQuery('textarea').removeAttr('data-source-cancel');
            jQuery('#divSidebarSource textarea').attr('data-source-active', '1');
            jQuery('#divSidebarSource textarea').attr('data-source-ok', '#btnViewHtmlOk');
            jQuery('#divSidebarSource textarea').attr('data-source-cancel', '#btnViewHtmlCancel');

            //_fb.viewHtml(); //OR:
            _fb.viewHtmlNormal();

            jQuery('#btnViewHtmlOk').off('click');
            jQuery('#btnViewHtmlOk').on('click', function (e) {

                _fb.saveForUndo();

                var html = jQuery('#inpViewHtml').val();

                html = _fb.fromViewToActual(html);

                jQuery('.is-wrapper').html(html);

                $element.data("contentbox").setup();

                //Trigger Change event
                $element.data("contentbox").settings.onChange();

            });

            jQuery('#btnViewHtmlCancel').off('click');
            jQuery('#btnViewHtmlCancel').bind('click', function (e) {

                // None, because there is no sidebar panel to close

            });

        };

        /**
         * @param s
         * @private
         */
        this.viewHtml2 = function (s) {
            jQuery('body').css('overflow', 'hidden');

            var html = this.html(true); //For View

            jQuery('#inpViewHtml').val(html);

            jQuery('#btnViewHtmlOk').off('click');
            jQuery('#btnViewHtmlOk').on('click', function (e) {

                _fb.saveForUndo();

                /*
                var $htmlEditor = jQuery('#inpViewHtml').data('CodeMirrorInstance');
                jQuery('#inpViewHtml').val($htmlEditor.getValue());
                */

                var html = jQuery('#inpViewHtml').val();

                html = _fb.fromViewToActual(html);

                jQuery('.is-wrapper').html(html);

                $element.data("contentbox").setup();

                //Trigger Change event
                $element.data("contentbox").settings.onChange();

                //Close sidebar
                jQuery('.is-sidebar-overlay').remove();
                jQuery('.is-sidebar > div').removeClass('active');
                jQuery('.is-sidebar-content').removeClass('active');
                jQuery('body').css('overflow', '');

            });

            jQuery('#btnViewHtmlCancel').off('click');
            jQuery('#btnViewHtmlCancel').bind('click', function (e) {

                //Close sidebar
                jQuery('.is-sidebar-overlay').remove();
                jQuery('.is-sidebar > div').removeClass('active');
                jQuery('.is-sidebar-content').removeClass('active');
                jQuery('body').css('overflow', '');

            });

            //Open Larger Editor

            jQuery('#divSidebarSource .edit-html-larger').off('click');
            jQuery('#divSidebarSource .edit-html-larger').on('click', function (e) {

                //used  by larger editor dialog (html.html)
                jQuery('textarea').removeAttr('data-source-active');
                jQuery('textarea').removeAttr('data-source-ok');
                jQuery('textarea').removeAttr('data-source-cancel');
                jQuery('#divSidebarSource textarea').attr('data-source-active', '1');
                jQuery('#divSidebarSource textarea').attr('data-source-ok', '#btnViewHtmlOk');
                jQuery('#divSidebarSource textarea').attr('data-source-cancel', '#btnViewHtmlCancel');

                _fb.viewHtmlLarger();

            });

            return false;
        };

        /**
         * @private
         */
        this.viewTypography = function (s) {

            var styleSelect = $element.data("contentbox").settings.styleSelect;

            if (jQuery('#ifrTypographyPanel').attr('src').indexOf('blank') != -1) {
                jQuery('#ifrTypographyPanel').attr('src', styleSelect);
            }

            return false;
        };

        /**
         * @private
         */
        this.viewIdeas = function (s) {
            jQuery('body').css('overflow', 'hidden');

            var designSelect = $element.data("contentbox").settings.designSelect;
            if (jQuery('#ifrIdeasPanel').attr('src').indexOf('blank') != -1) {
                jQuery('#ifrIdeasPanel').attr('src', designSelect);
            }

            return false;
        };

        /**
         * @param className
         * @param contentCss
         * @param pageCss
         * @private
         */
        this.boxTypography = function (className, contentCss, pageCss) {

            _fb.saveForUndo();

            var styleCssPath = $element.data("contentbox").settings.styleCssPath;

            //Check apply to what
            var applyto = jQuery('.is-sidebar > div[data-command=typography]').attr('data-applyto');

            if (applyto == 'box') {

                if ($activeBox) {
                    var classList = $activeBox.attr('class').split(/\s+/);
                    $.each(classList, function (index, item) {
                        if (item.indexOf('type-') != -1) {//Remove previous class that has prefix 'type-'
                            $activeBox.removeClass(item);
                        }
                    });

                    //Add new class
                    if (className != '') {
                        $activeBox.addClass(className);

                        //Add css
                        var exist = false;
                        var links = document.getElementsByTagName("link");
                        for (var i = 0; i < links.length; i++) {
                            var src = links[i].href.toLowerCase();
                            if (src.indexOf(contentCss.toLowerCase()) != -1) exist = true;
                        }
                        if (! exist) {
                            jQuery('head')
                                .append('<link data-name="contentstyle" data-class="' + className + '" href="' + styleCssPath + contentCss + '" rel="stylesheet">');
                        }
                    }

                    //Cleanup unused
                    var links = document.getElementsByTagName("link");
                    for (var i = 0; i < links.length; i++) {
                        if (jQuery(links[i]).attr('data-name') == 'contentstyle') {

                            var classname = jQuery(links[i]).attr('data-class');

                            //check if classname used in content
                            if (jQuery(".is-wrapper").find('.' + classname).length == 0) {
                                jQuery(links[i]).attr('data-rel', '_del');
                            }

                        }
                    }
                    jQuery('[data-rel="_del"]').remove();

                }

            } else {

                var bSectionStyleExists = false;
                var links = document.getElementsByTagName("link");
                for (var i = 0; i < links.length; i++) {
                    if (jQuery(links[i]).attr('data-name') == 'contentstyle') {
                        bSectionStyleExists = true;
                    }
                }

                if (! bSectionStyleExists) {

                    //Cleanup (remove previous css that has prefix 'basetype-')
                    var links = document.getElementsByTagName("link");
                    for (var i = 0; i < links.length; i++) {
                        var src = links[i].href.toLowerCase();
                        if (src.indexOf('basetype-') != -1) {
                            jQuery(links[i]).attr('data-rel', '_del');
                        }
                    }
                    jQuery('[data-rel="_del"]').remove();

                    //Add new page css
                    if (pageCss != '') {
                        jQuery('head').append('<link href="' + styleCssPath + pageCss + '" rel="stylesheet">');
                    }

                } else {

                    var $modal = jQuery('.is-modal.applytypography');
                    $element.data("contentbox").showModal($modal);

                    $modal.not('.is-modal *').off('click');
                    $modal.not('.is-modal *').on('click', function (e) {
                        if (jQuery(e.target).hasClass('is-modal')) {
                            $element.data("contentbox").hideModal($modal);
                        }
                    });

                    $('input:radio[name=rdoApplyTypoStyle]')[1].checked = true;

                    $modal.find('.input-ok').off('click');
                    $modal.find('.input-ok').on('click', function (e) {

                        var val = $('input[name=rdoApplyTypoStyle]:checked').val();
                        if (val == 1) {
                            var links = document.getElementsByTagName("link");
                            for (var i = 0; i < links.length; i++) {
                                if (jQuery(links[i]).attr('data-name') == 'contentstyle') {

                                    var classname = jQuery(links[i]).attr('data-class');

                                    //check if classname used in content
                                    if (jQuery(".is-wrapper").find('.' + classname).length > 0) {
                                        jQuery(".is-wrapper").find('.' + classname).removeClass(classname);
                                        jQuery(links[i]).attr('data-rel', '_del');
                                    }

                                }
                            }
                            jQuery('[data-rel="_del"]').remove();
                        }

                        //Cleanup (remove previous css that has prefix 'basetype-')
                        var links = document.getElementsByTagName("link");
                        for (var i = 0; i < links.length; i++) {
                            var src = links[i].href.toLowerCase();
                            if (src.indexOf('basetype-') != -1) {
                                jQuery(links[i]).attr('data-rel', '_del');
                            }
                        }
                        jQuery('[data-rel="_del"]').remove();

                        //Add new page css
                        if (pageCss != '') {
                            jQuery('head').append('<link href="' + styleCssPath + pageCss + '" rel="stylesheet">');
                        }

                        $element.data("contentbox").hideModal($modal);

                        //Trigger Change event
                        $element.data("contentbox").settings.onChange();

                        return false;
                    });

                }

            }

            //Trigger Change event
            $element.data("contentbox").settings.onChange();
        };

        /**
         * @param imageSrc
         * @private
         */
        this.boxImage = function (imageSrc) {

            _fb.saveForUndo();
            jQuery("#lblWait").css("display", "none");

            // Makes sure we have an overlay div
            if ($activeBox.find(".is-overlay").length == 0) {
                $activeBox.prepend('<div class="is-overlay"></div>');
            }

            // Get the overlay div
            let $overlay = $activeBox.find(".is-overlay");

            // If the overlay does not have the bg div then add it
            if ($overlay.find(".is-overlay-bg").length == 0) {
                let overlayBgHtml = `
                    <div class="is-overlay-bg"
                        style="transform:scale(1.05)"
                        data-bottom-top="transform:translateY(-120px) scale(1.05);"
                        data-top-bottom="transform:translateY(120px) scale(1.05)"></div>
                `;
                $overlay.prepend(overlayBgHtml);

                // Prepend an color overlay div over the image
                let overlayColorHtml = `
                    <div class="is-overlay-color" style="opacity:0.1"></div>
                `;
                $overlay.find(".is-overlay-bg").prepend(overlayColorHtml);
            }

            // Add the image url to the background
            let overlayBg = $overlay.find(".is-overlay-bg");

            // If the overlay background is using lazy load
            if (overlayBg.hasClass('lazyload') && imageSrc.includes('/photos/')) {

                // set the background image to the low quality version
                overlayBg.css("background-image", "url(" + imageSrc + '?q=5' + ")");

                // set the data attribute to the high quality version
                overlayBg.attr('data-bg', imageSrc);

            } else {
                overlayBg.css("background-image", "url(" + imageSrc + ")");
            }

            // Remove any bg colour classes
            $activeBox.css("background-color", "");
            $activeBox.removeClass("is-bg-light");
            $activeBox.removeClass("is-bg-grey");
            $activeBox.removeClass("is-bg-dark");

            //Trigger Render event
            $element.data("contentbox").settings.onRender();

            //Trigger Change event
            $element.data("contentbox").settings.onChange();
        };

        /**
         * @private
         */
        this.destroy = function () {

            var html = this.html();

            $element.removeData('contentbox');
            $element.unbind();

            jQuery('#_cbhtml').remove();
            jQuery('body').removeClass('sidebar-active');
            jQuery('.is-wrapper').html(html);

            _fb.destroy();
        };

        /**
         * Run the init function
         */
        this.init();
    };

    /**
     * Content box function
     *
     * This loops through all the elements that use t
     * he function $(".is-wrapper").contentbox({})
     * and applies the content box object above to theme
     */
    jQuery.fn.contentbox = function (options) {
        return this.each(function () {
            if (undefined == jQuery(this).data('contentbox')) {
                var plugin = new jQuery.contentbox(this, options);
                jQuery(this).data('contentbox', plugin);
            }
        });
    };

    /**
     * Clear fields | Clear inputs
     *
     * source: http://stackoverflow.com/questions/1043957/clearing-input-type-file-using-jquery
     * source: https://github.com/malsup/form/blob/master/jquery.form.js
     */
    jQuery.fn.clearFields = jQuery.fn.clearInputs = function (includeHidden) {

        var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list

        return this.each(function () {
            var t = this.type, tag = this.tagName.toLowerCase();

            if (re.test(t) || tag == 'textarea') {
                this.value = '';

            } else if (t == 'checkbox' || t == 'radio') {
                this.checked = false;

            } else if (tag == 'select') {
                this.selectedIndex = -1;

            } else if (t == "file") {
                if (/MSIE/.test(navigator.userAgent)) {
                    jQuery(this).replaceWith(jQuery(this).clone(true));
                } else {
                    jQuery(this).val('');
                }

            } else if (includeHidden) {
                // includeHidden can be the value true, or it can be a selector string
                // indicating a special test; for example:
                //  jQuery('#myForm').clearForm('.special:hidden')
                // the above would clean hidden inputs that have the class of 'special'
                if ((includeHidden === true && /hidden/.test(t)) ||
                    (typeof includeHidden == 'string' && jQuery(this).is(includeHidden)))
                    this.value = '';
            }
        });
    };

})(jQuery);
