/***************************************************************************
 *
 *  ----------------------------------------------------------------------
 *                      DO NOT EDIT THIS FILE
 *  ----------------------------------------------------------------------
 *
 *                       Copyright (C) Themify
 *
 *  ----------------------------------------------------------------------
 *
 ***************************************************************************/

/**
 * Common shared code between backend and frontend Builder.
 */

;var ThemifyBuilderCommon, themifyBuilder;
(function($, window, document, undefined) {

    'use strict';

    ThemifyBuilderCommon = {
        
        fonts:[],
        safe_fonts:{},
        google_fonts:{},
        uuid: 0, // Create a universally unique identifier.
        /**
         * Function that detects whether localStorage is both supported and available.
         *
         * From MDN.
         *
         * @param type Type of the tested storage. E.g 'localStorage'.
         * @returns {boolean} True on browser having both support and availability, otherwise false.
         */
        storageAvailable: function(type) {
            try {
                var storage = window[type],
                    x = '__storage_test__';
                storage.setItem(x, x);
                storage.removeItem(x);
                return true;
            }
            catch(e) {
                return false;
            }
        },

        isFrontend: function() {
            return themifyBuilder.isFrontend === 'true';
        },

        setupLoader: function() {
            $('<div/>', {
                id: 'themify_builder_alert',
                class: 'themify-builder-alert'
            }).appendTo('body').hide();
        },

        showLoader: function(stats) {
            var $previewBtn = $('.builder_preview_lightbox'),
                $previewLoaderImage = $('.builder_preview_loader_image');

            if(stats == 'show'){
                $('#themify_builder_alert').addClass('busy').show();
            }
            else if(stats == 'spinhide'){
                $("#themify_builder_alert").delay(800).fadeOut(800, function() {
                    $(this).removeClass('busy');
                });
            } else if (stats === 'lightbox-preview') {
                $previewBtn.hide();

                if ($previewLoaderImage.length) {
                    $previewLoaderImage.show();
                } else {
                    $('<div>', {class: 'builder_preview_loader_image'}).insertBefore($previewBtn);
                }
            } else if (stats === 'lightbox-preview-hide') {
                $previewBtn.show();
                $previewLoaderImage.hide();
            } else if (stats === 'error') {
                $("#themify_builder_alert").removeClass("busy").addClass('error').delay(800).fadeOut(800, function() {
                    $(this).removeClass('error');
                });
            }
            else{
                $("#themify_builder_alert").removeClass("busy").addClass('done').delay(800).fadeOut(800, function() {
                    $(this).removeClass('done');
                });
            }
        },

        getDocHeight: function(){
            var D = document;
            return Math.max(
                Math.max(D.body.scrollHeight, D.documentElement.scrollHeight),
                Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),
                Math.max(D.body.clientHeight, D.documentElement.clientHeight)
            );
        },

        highlightColumn: function($column) {
            $('.themify_builder_col').removeClass('current_selected_column');
            $column.addClass('current_selected_column');
        },

        highlightRow: function($row) {
            $('.themify_builder_row').removeClass('current_selected_row');
            $row.addClass('current_selected_row');
        },

        highlightSubRow: function($subRow) {
            $('.themify_builder_sub_row').removeClass('current_selected_sub_row');
            $subRow.addClass('current_selected_sub_row');
        },
        setUpTooltip: function () {
            if ($('.themify_is_premium_module').length > 0 || $('.themify_builder_lite').length > 0) {
                if ($('.themify_tooltip').length === 0) {
                    $('<div class="themify_tooltip">Upgrade to premium version to get this feature<div class="themify_tooltip_arrow"><div class="themify_tooltip_arrow_border"></div><div class="themify_tooltip_arrow_background"></div></div></div>').appendTo('body');
                }
                var width = ($('.themify_tooltip').outerWidth(true) / 2) + 10,
                        height = $('.themify_tooltip').outerHeight(true) + 10,
                        is_hover;
                $('.themify_builder_lite,.themify_is_premium_module').each(function () {
                    if ($(this).children('.themify_builder_lite_modal').length === 0) {
                        var $this = $(this);
                        $('<div class="themify_builder_lite_modal"></div>').appendTo($(this)).mouseenter(function (e) {
                            var is_input = $this.children('.themify_builder_input').length > 0,
                                    tooltip = $('.themify_tooltip'),
                                    $ofset = $(this).offset(),
                                    $width = is_input ? 50 : ($(this).width() / 2) - width,
                                    is_hover = true;
                            $('.themify_builder_lite_active').removeClass('themify_builder_lite_active');
                            $(this).addClass('themify_builder_lite_active');

                            tooltip.css({top: $ofset.top - height, left: $ofset.left + $width}).delay(500)
                                    .queue(function (next) {
                                        var $el = $(this);
                                        if ($('.themify_builder_lite_active').length > 0) {
                                            if (is_hover) {
                                                $el.stop().fadeIn('fast');
                                            }
                                            else {
                                                $('.themify_builder_lite_modal').each(function () {
                                                    if ($(this).is(':hover')) {
                                                        $el.stop().fadeIn('fast');
                                                        return false;
                                                    }
                                                });
                                            }
                                        }
                                        else {
                                            $el.hide();
                                        }
                                        next();
                                    });
                            setTimeout(function () {
                                if ($('.themify_builder_lite_active').length === 0) {
                                    tooltip.hide();
                                }
                                else {
                                    var check_hover = false;
                                    $('.themify_builder_lite_modal').each(function () {
                                        if ($(this).is(':hover')) {
                                            check_hover = true;
                                            return false;
                                        }
                                    });
                                    if (!check_hover) {
                                        $('.themify_builder_lite_active').removeClass('themify_builder_lite_active');
                                        tooltip.hide();
                                    }
                                }
                            }, 1000);
                        }).mouseleave(function () {
                            is_hover = false;
                            $('.themify_builder_lite_active').removeClass('themify_builder_lite_active');
                            $('.themify_tooltip').hide();
                        });
                    }
                });
                $(window).scroll(function () {
                    $('.themify_builder_lite_active').trigger('mouseenter');
                });
            }
        },
        _saveRevision: function(callback) {
                
                var self = ThemifyBuilderCommon;
                self.LiteLightbox.prompt(themifyBuilder.enterRevComment, function(result) {
                        if (result !== null) {
                                $.ajax({
                                        type: "POST",
                                        url: themifyBuilder.ajaxurl,
                                        data: {
                                                action: 'tfb_save_revision',
                                                tfb_load_nonce: themifyBuilder.tfb_load_nonce,
                                                postid: themifyBuilder.post_ID,
                                                rev_comment: result
                                        },
                                        beforeSend: function(xhr) {
                                                self.showLoader('show');
                                        },
                                        success: function(data) {
                                                if (data.success) {
                                                        // load callback
                                                        if ($.isFunction(callback)) {
                                                                callback.call(this, data);
                                                        }
                                                } else {
                                                        alert(data.data);
                                                }
                                                self.showLoader('hide');
                                        }
                                });
                        }
                });
        },
        restoreRevision: function(event) {
                event.preventDefault();
                var revID = $(this).data('rev-id'),
                    self = ThemifyBuilderCommon,
                    restoreIt = function() {
                                $.ajax({
                                        type: "POST",
                                        url: themifyBuilder.ajaxurl,
                                        data: {
                                                action: 'tfb_restore_revision_page',
                                                tfb_load_nonce: themifyBuilder.tfb_load_nonce,
                                                revid: revID
                                        },
                                        beforeSend: function(xhr) {
                                                self.showLoader('show');
                                        },
                                        success: function(data) {
                                                if (data.success) {
                                                        self.showLoader('hide');
                                                        self.Lightbox.close();
                                                        window.location.reload();
                                                } else {
                                                        self.showLoader('error');
                                                        alert(data.data);
                                                }
                                        }
                                });
                    };

                self.LiteLightbox.confirm(themifyBuilder.confirmRestoreRev, function(response) {
                        if ('yes' == response) {
                                self._saveRevision(restoreIt);
                        } else {
                                restoreIt();
                        }
                });

        },
        deleteRevision: function(event) {
                event.preventDefault();
                var $this = $(this),
                    self = ThemifyBuilderCommon,
                    revID = $(this).data('rev-id');
                if (!confirm(themifyBuilder.confirmDeleteRev))
                        return;

                $.ajax({
                        type: "POST",
                        url: themifyBuilder.ajaxurl,
                        data: {
                                action: 'tfb_delete_revision',
                                tfb_load_nonce: themifyBuilder.tfb_load_nonce,
                                revid: revID
                        },
                        beforeSend: function(xhr) {
                                self.showLoader('show');
                                $this.parent().hide();
                        },
                        success: function(data) {
                                if (!data.success) {
                                        self.showLoader('error');
                                        $this.parent().show();
                                        alert(data.data);
                                } else {
                                        self.showLoader('hide');
                                }
                        }
                });
        },
        /**
         * Returns the closest parent Builder row.
         *
         * @param $elmt {jQuery}
         * @returns {jQuery}
         */
        getClosestRow: function($elmt) {
            return $elmt.parent().closest('.themify_builder_row');
        },

        /**
         * Returns the closest parent Builder col.
         *
         * @param $elmt {jQuery}
         * @returns {jQuery}
         */
        getClosestCol: function($elmt) {
            return $elmt.parent().closest('.themify_builder_col');
        },

        /**
         * Returns the closest parent Builder sub-row.
         *
         * @param $elmt {jQuery}
         * @returns {jQuery}
         */
        getClosestSubRow: function($elmt) {
            return $elmt.parent().closest('.themify_builder_sub_row');
        },

        /**
         * Returns the order (index) of a row/col/sub-col.
         *
         * @param $component {jQuery} The component we want to find the order of.
         */
        getComponentOrder: function($component) {
            var self = ThemifyBuilderCommon;
            var subColIndex, subRowIndex, colIndex, rowIndex;

            var componentType = self.getComponentType($component);

            if (componentType == 'sub-col') {
                subColIndex = $component.index();
                subRowIndex = self.getClosestSubRow($component).index();
                colIndex = self.getClosestCol($component).index();
                rowIndex = self.getClosestRow($component).index();

                return rowIndex + '-' + colIndex + '-' + subRowIndex + '-' + subColIndex;

            } else if (componentType == 'col') {
                colIndex = $component.index();
                rowIndex = self.getClosestRow($component).index();

                return rowIndex + '-' + colIndex;

            } else if (componentType == 'row') {
                rowIndex = $component.index();

                return rowIndex;
            }
        },

        /**
         * Returns the type of a component. Can be 'row', 'col', 'sub-col', 'module-holder', 'module', 'module-inner'.
         *
         * 'module-holder' contains 'module' + '.empty_holder_text'.
         * 'module' contains module's data such as mod name, mod contents and styling.
         * 'module-inner' contains module's contents such as title, text or any other.
         *
         * @param $component {jQuery} The component we want to detect the type of.
         */
        getComponentType: function($component) {
            if ($component.hasClass('themify_builder_col')) {
               if ($component.closest('.themify_builder_sub_row_content').length) {
                   return 'sub-col';
               } else {
                   return 'col';
               }
            } else if ($component.hasClass('themify_builder_row')) {
                return 'row';
            } else if ($component.hasClass('themify_builder_sub_row')) {
                return 'subrow';
            } else if ($component.hasClass('themify_builder_module_front')
                || $component.hasClass('themify_builder_module') /* backend */) {
                return 'module';
            } else if ($component.hasClass('themify_module_holder')) {
                return 'module-holder';
            } else if ($component.hasClass('module')) {
                return 'module-inner';
            }
        },

        /**
         * Returns component's Builder's ID.
         *
         * @param {jQuery} $component
         * @returns {Number}
         */
        getComponentBuilderId: function($component) {
            var id = $component.closest('.themify_builder_content').data('postid');

            if (typeof id === 'undefined' || isNaN(id)) {
                return -1;
            }

            return id;
        },

        /**
         * Clipboard-like functionality. Wraps localStorage with a Themify key. Supports one copied item per time.
         */
        Clipboard: {
            key : 'themify_builder_clipboard_',
            set : function( type, content ) {
                if ( ThemifyBuilderCommon.storageAvailable('localStorage') ) {
                    localStorage.setItem( this.key + 'type', type );
                    localStorage.setItem( this.key + 'content', content );
                } else {
                    alert( themifyBuilderCommon.text_no_localStorage );
                }
            },
            get : function( type ) {
                if ( ThemifyBuilderCommon.storageAvailable('localStorage') ) {
                    var savedType =  localStorage.getItem( this.key + 'type' ),
                        savedContent = localStorage.getItem( this.key + 'content' );

                    if ( typeof type === undefined || type === savedType ) {
                        return savedContent;
                    } else {
                        return false;
                    }
                } else {
                    alert( themifyBuilderCommon.text_no_localStorage );
                }
            }
        },

        confirmDataPaste: function() {
            return confirm(themifyBuilderCommon.text_confirm_data_paste);
        },

        alertWrongPaste: function() {
            alert(themifyBuilderCommon.text_alert_wrong_paste);
        },

        detectBuilderComponent: function($component) {
            if (!$component.attr('data-component')) {
                return false;
            }

            return $component.data('component');
        },

        /**
         * Returns module's settings in as {Object} if there are any, otherwise empty string.
         *
         * @param $moduleWrapper {jQuery} div.themify_builder_module_front wrapper around module.
         * @returns {string|Object}
         */
        getModuleSettings: function($moduleWrapper) {
            var settingsInText = $moduleWrapper
                .find('.front_mod_settings')
                .children('script[type="text/json"]')
                .text()
                .trim();

            if (settingsInText.length > 2 && settingsInText != 'null') {
                return JSON.parse(settingsInText);
            }

            return '';
        },

        /**
         * Returns row's styling settings as {Object} if there any, otherwise {false}.
         *
         * @param $row {jQuery} Row element, which styling settings we want to get.
         * @returns {Object|false}
         */
        getRowStylingSettings: function($row) {
            var settings = $row.find('.row_inner').children('.row-data-styling').data('styling');

            if (typeof settings === "object") {
                return settings;
            }

            return false;
        },

		/**
         * Returns sub-row's styling settings as {Object} if there any, otherwise {false}.
         *
         * @param $subrow {jQuery} Sub-Row element, which styling settings we want to get.
         * @returns {Object|false}
         */
        getSubRowStylingSettings: function($subrow) {
            var settings = $subrow.children('.subrow-data-styling').data('styling');

            if (typeof settings === "object") {
                return settings;
            }

            return false;
        },

        /**
         * Returns column's styling settings as {Object} if there any, otherwise {false}.
         *
         * @param $column {jQuery} Column element, which styling settings we want to get.
         * @returns {Object|false}
         */
        getColumnStylingSettings: function($column) {
            var settings = $column.children('.column-data-styling').data('styling');

            if (typeof settings === "object") {
                return settings;
            }

            return false;
        },

        findColumnInNewRow: function($newRow, colLocationObj) {
            var $currentCol = null;
            var colIndex, subColIndex = 0;

            if (colLocationObj.hasOwnProperty('sub-col_index')) {
                subColIndex = colLocationObj['sub-col_index'];
                colIndex = colLocationObj['col_index'];

                var $parentCol = $newRow.find(
                    '.themify_builder_row_content > .themify_builder_col:nth-child(' + (colIndex + 1) + ')'
                );
                $currentCol = $parentCol.find(
                    '.themify_builder_sub_row_content > .themify_builder_col:nth-child(' + (subColIndex + 1) + ')'
                );
            } else if (colLocationObj.hasOwnProperty('col_index')) {
                colIndex = colLocationObj['col_index'];

                $currentCol = $newRow.find(
                    '.themify_builder_row_content > .themify_builder_col:nth-child(' + (colIndex + 1) + ')'
                );
            }

            return $currentCol;
        },

        /**
         * Returns the checked radio in a named group.
         *
         * @param {jQuery} $radioInGroup A radio in a named group.
         * @param {jQuery|undefined} $context Where should the radio group be searched in.
         * @returns {jQuery}
         */
        getCheckedRadioInGroup: function($radioInGroup, $context) {
            if (typeof $context === 'undefined') {
                $context = null;
            }

            var radioGroupName = $radioInGroup.attr('name');

            return $('input:radio[name="' + radioGroupName + '"]:checked', $context);
        },

        /**
         * Loads Google Web Fonts.
         *
         * @param {Array} fontFamilies Array containing font family declarations with character sets and styles.
         *                             E.g., [ 'Open+Sans:400,700:latin,latin-ext' ]
         */
        loadGoogleFonts: function(fontFamilies, iframe) {
            iframe = iframe || false;
            var fontConfig = {
                google: { families: fontFamilies }
            };
            WebFont.load(fontConfig);
            if(iframe){
                fontConfig['context'] = iframe;
                WebFont.load(fontConfig);
            }
        },
        autoComplete:function(){
            if($('.themify_tax_autocomplete').length>0){
                var $data = [];
                $( ".themify_tax_autocomplete" ).each(function(){
                    var $this = $(this),
                    $input = $this.closest('.themify_builder_input').find('input.query_category_multiple'),
                    $val = $input.val();
                    $(this).autocomplete({
                        minLength: 2,
                        source: function( request, response ) {
                            var term = $.trim(request.term);                                                 
                            $.getJSON(themifyBuilder.ajaxurl,{
                              term: $.trim(term),
                              tax:$this.data('tax'),
                              action:$this.data('action')
                            }, 
                            function( data, status, xhr ) {
                                response( data );
                            } );
                        },
                        select: function( event, ui ) {
                            $input.val(ui.item.value);
                            this.value = ui.item.label;
                            return false;
                        }
                      }).focus(function(){ 
                          $(this).autocomplete("search");
                          return false;
                    });
                    if($val && $val!=='undefined'){
                        var object = {}; 
                        object[$this.data('tax')] = $val;
                        $data.push(object);
                    }
                    else{
                        $input.val('');
                    }
                });
                if($data){
                    $.ajax({
                        url: themifyBuilder.ajaxurl,
                        type:'POST',
                        dataType:'json',
                        data:{'data':$data,'action':'themify_builder_get_tax_data'},
                        success:function(resp){
                            if(resp){
                                for(var $i in resp){
                                    $('#themify_search_cat_'+resp[$i].tax).val(resp[$i].val);
                                }
                            }
                        }
                     });
                }
            }
        },
        hideShowBackgroundZoom:function($container){
           
            $('#background_repeat',$container).change(function(){
               BackgroundZoomChange($(this).val());
            });
            //we can't call trigger because the live styling maybe hasn't been init
            function BackgroundZoomChange($val){
                var $field = $('#background_zoom',$container).closest('.themify_builder_field');
                if($val==='repeat-none'){
                    $field.fadeIn();
                }
                else{
                    $field.fadeOut();
                }
            }
            BackgroundZoomChange($('#background_repeat',$container).val());
        },
        hideShowSliderArrow:function($container){
            if($('#show_arrow_slider',$container).length>0){
                $('#show_arrow_slider',$container).change(function(){
                    var $arrow_vertical = $('#show_arrow_buttons_vertical',$container).closest('.themify_builder_field');
                    if($(this).val()==='yes'){
                        $arrow_vertical.slideDown();
                    }
                    else{
                         $arrow_vertical.slideUp();
                    }
                }).trigger('change');
            }
        },
        hideShowBorder:function($container){
                var $apply_all = $('.style_apply_all[value="border"]',$container);
                $apply_all.each(function(){
                        var $select = $(this).closest('.themify_builder_field').prevUntil('h4').find('select.tfb_lb_option');
                        $select.change(function(){
                                var $fields = $(this).closest('.themify_builder_input').children().not('.selectwrapper')
                                if(!$(this).val() || $(this).val()==='none'){
                                    $fields.fadeOut();
                                }
                                else{
                                    $fields.fadeIn();
                                }
                        });

                });
        },
        columnDrag:function($container,$remove){
            var $holders = $('.themify_builder_column_action',$container);
            $holders.each(function(){
                var $drag = $(this).prev('.themify_grid_drag');
                if($drag.length===0){
                    $(this).before('<div class="themify_grid_drag themify_drag_right"></div><div class="themify_grid_drag themify_drag_left"></div>');
                }
                else{
                    $drag.removeAttr('style');
                }
                if($remove){
                    $(this).closest('.themify_builder_col').removeAttr('style');
                }
            });
            var $cdrags = $('.themify_grid_drag',$container),
                $min = 5;
            $cdrags.each(function(){
                
                    var $el = $(this),
                        $row = $el.closest('.themify_builder_sub_row_content'),
                        $row = $row.length===0?$el.closest('.themify_builder_row_content'):$row,
                        $columns = $row.children('.themify_builder_col'),
                        $current = $el.closest('.themify_builder_col'),
                        $el_width = false,
                        $direction = '',
                        $row_width = '',
                        $excolumn=false,
                        $helperClass = '';
                       if($el.hasClass('themify_drag_right')){
                            $direction = 'e';
                            $excolumn = $current.next('.themify_builder_col');
                            $helperClass = 'themify_grid_drag_placeholder_right';
                            $el_width = $el.width();
                        }
                        else{
                            $direction = 'w';
                            $excolumn = $current.prev('.themify_builder_col');
                            $helperClass = 'themify_grid_drag_placeholder_left';
                        }
                        
                    $el.draggable({ 
                        axis: "x",
                        cursor:'col-resize',
                        distance :0,
                        containment:'.themify_builder_row_content',
                        helper:function(event){
                            return $( '<div class="ui-widget-header themify_grid_drag_placeholder '+$helperClass+'"></div><div class="ui-widget-header themify_grid_drag_placeholder"></div>' ); 
                        },
                        start:function(event,ui){
                            $('.themify_grid_drag_current').removeClass('themify_grid_drag_current');  
                            $row_width = $row.outerWidth();
                            if($direction==='w'){
                                $el_width = $current.width();
                            }
                        },
                        stop:function(event,ui){
                            $('.themify_grid_drag_placeholder').remove();
                        },
                        drag: function(event, ui) {
                            var $pxwidth = $el_width+($direction==='w'?-(ui.position.left):ui.position.left);
                                $current.addClass('themify_grid_drag_current');
                                if($excolumn.length>0){
                                    var $width = parseFloat((100*$pxwidth)/$row_width);
                                    if($width>=$min && $width<100){
                                        var $summ = 0; 
                                        $columns.each(function(i){
                                            if(i!==$excolumn.index()){
                                                 $summ+=$(this).hasClass('themify_grid_drag_current')?$width:
                                                        ($(this).prop('style').width?parseFloat($(this).prop('style').width):parseFloat(100*parseFloat($(this).css('width'))/$row_width));
                                            }
                                            $summ+=parseFloat((parseFloat($(this).css('marginLeft'))*100)/$row_width);
                                        });
                                        var $max = 100-$summ;;
                                        if($max>=$min && $max<100){
                                           
                                            $current.css('width', $width+'%').children('.'+$helperClass).html($width.toFixed(2)+'%');
                                            $current.children('.themify_grid_drag_placeholder').last().html($max.toFixed(2)+'%');
                                            $excolumn.css('width', $max+'%');
                                        }  
                                    }
                                }
                               
                        }

                    });
              });
        },
        fontPreview:function($container,$data){
            this.autoComplete();
            this.hideShowBorder($container);
            this.hideShowSliderArrow($container);
            this.hideShowBackgroundZoom($container);
            var self = ThemifyBuilderCommon,
                $safe_fonts_html = '',
                $google_fonts_html = '';
                if(Object.keys(self.safe_fonts).length===0){
                    for(var $i in themify_builder_plupload_init.fonts.safe){
                         self.safe_fonts[themify_builder_plupload_init.fonts.safe[$i].value] = themify_builder_plupload_init.fonts.safe[$i].name;
                    } 
                    for(var $i in themify_builder_plupload_init.fonts.google){
                         self.google_fonts[themify_builder_plupload_init.fonts.google[$i].value] = themify_builder_plupload_init.fonts.google[$i].name;
                    }
                }
            $('.font-family-select',$container).each(function(){
                var name = $(this).prop('name'),
                    selected = $data && $data[name]?$data[name]:false,
                    $optgroup = $(this).find('optgroup');
                $(this).parent('.themify_builder_font_preview_wrapper').focusin(function(){
                    $(this).unbind('focusin');
                    if(!$safe_fonts_html){
                        for(var $i in self.safe_fonts){
                            var $is_selected = selected===$i?'selected="selected"':'';
                            $safe_fonts_html+='<option '+$is_selected+' data-type="webfont" value="'+$i+'">'+self.safe_fonts[$i]+'</option>';
                        }
                        for(var $i in self.google_fonts){
                            var $is_selected = selected===$i?'selected="selected"':'';
                            $google_fonts_html+='<option '+$is_selected+' value="'+$i+'">'+self.google_fonts[$i]+'</option>';
                        }
                    }
                    $optgroup.first().html($safe_fonts_html);
                    $optgroup.last().html($google_fonts_html);
                    comboSelect($(this).children('select'));
                });
                if(selected){
                    if(self.safe_fonts[selected]){
                        $optgroup.first().html('<option selected="selected" data-type="webfont" value="'+selected+'">'+self.safe_fonts[selected]+'</option>');
                    }
                    else if(self.google_fonts[selected]){
                         $optgroup.last().html('<option selected="selected"  value="'+selected+'">'+self.google_fonts[selected]+'</option>');
                    }
                }
            });
            if(self.fonts.length>0){
                var $first = $('.themify-combo-dropdown').first();
                for(var $i in self.fonts){
                    var $index = $first.find('[data-value="'+self.fonts[$i]+'"]').index();
                    showFontPreview($index,self.fonts[$i]);
                }
            }
            function comboSelect($select){
                $select.unwrap();
                 var $combo  = $select.comboSelect({
                    'comboClass':'themify-combo-select',
                    'comboArrowClass':'themify-combo-arrow',
                    'comboDropDownClass':'themify-combo-dropdown',
                    'inputClass':'themify-combo-input',
                    'disabledClass':'themify-combo-disabled',
                    'hoverClass':'themify-combo-hover',
                    'selectedClass':'themify-combo-selected',
                    'markerClass':'themify-combo-marker',

                }).parent('div');
                  
                $combo.on('comboselect:close',function(){
                    $('.themify_builder_font_preview').hide();
                });
                $combo.trigger('focusin');
                $('.themify-combo-item',$combo).unbind('hover').hover(function(){
                    var $value = $(this).data('value');
                    if($value){
                        if(!$(this).is(':visible')){
                            return;
                        }
                        var $preview = $combo.next('.themify_builder_font_preview');
                        if($value==='default'){
                            $value = 'inherit';
                        }
                        $preview.css({'top':$(this).position().top+30,'font-family':$value,'display':'block'});
                        if($value==='inherit'){
                             return;
                        }
                        if(!$(this).hasClass('themify_builder_font_loaded')){
                            var $this = $(this),
                            $index = $this.index();
                            $this.addClass('themify_builder_font_loaded');
                            $preview = $preview.children('span');
                           if($.inArray($value,self.fonts)===-1){
                                $preview.addClass('themify_show_wait');
                                if($select.find('option[value="'+$value+'"]').data('type')!=='webfont'){
                                    WebFont.load({
                                        google: {
                                            families: [$value]
                                        },
                                        fontloading: function (familyName, fvd) {
                                            self.fonts.push($value);
                                            $preview.removeClass('themify_show_wait');
                                        },
                                        fontinactive: function (familyName, fvd) {
                                            self.fonts.push($value);
                                            $preview.removeClass('themify_show_wait');
                                        }
                                    });
                                }
                                else{
                                    self.fonts.push($value);
                                    $preview.removeClass('themify_show_wait');
                                }
                            }
                            showFontPreview($index,$value,$preview);
                        }
                    }
                });
            }
            function showFontPreview($index,familyName){
                $('.themify-combo-dropdown').find('li:eq('+$index+')').addClass('themify_builder_font_loaded').css('font-family', familyName);
            }
            $('.themify-combo-arrow').unbind('click').click(function(){
                $('.themify_builder_font_preview').hide();
            });
        },
        Lightbox: {
            $lightbox: null,
            setup: function() {
                var self = ThemifyBuilderCommon.Lightbox,
                    isThemifyTheme = 'true' == themifyBuilder.isThemifyTheme? 'is-themify-theme' : 'is-not-themify-theme',
                    lightbox_func = wp.template( 'builder_lightbox'),
                    markup = lightbox_func( { is_themify_theme: isThemifyTheme } );

                self.bindEvents();

                $(markup).hide().find('#themify_builder_lightbox_parent').hide().end().appendTo('body');

                self.$lightbox = $('#themify_builder_lightbox_parent');

                function makeLightboxResizable() {
                    self.$lightbox.resizable({
                        minWidth: 500,
                        maxWidth: 880,
                        minHeight: 320, /* corresponds to min-height in themify-builder-admin-ui.css .themify_builder.builder-lightbox  */
                        maxHeight: 800,

                        create: function(_, ui) {
                            var $resizingIcon = self.$lightbox.find('.ui-resizable-handle.ui-icon-gripsmall-diagonal-se');

                            // change resizing icon to an arrow
                            $resizingIcon
                                .removeClass('ui-icon-gripsmall-diagonal-se')
                                .addClass('ui-icon-arrow-1-se');
                        },

                        resize: function(event, ui) {
                            self.adjustHeight(ui.size.height);
                            setupLightboxSizeClass();
                        },

                        stop: function() {
                            self.fixContainment();
                            $( 'body' ).trigger( 'themify_builder_lightbox_resize' );
                        }
                    });
                    $( 'body' ).on('editing_module_option', setupLightboxSizeClass )
                }

                function makeLightboxDraggable() {
                    var topBarElem = document.querySelector('#themify_builder_lightbox_parent .themify_builder_lightbox_top_bar');

                    // Hack: prevent dragging stuck on cursor
                    $('body').mouseleave(function(){
                        self.$lightbox.trigger('mouseup');
                    });

                    self.$lightbox.draggable({
                        handle: topBarElem,
                        scroll: false,
                        start: ThemifyBuilderCommon.Lightbox.fixContainment,
                        stop: ThemifyBuilderCommon.Lightbox.fixContainment
                    });
                }

                function rememberLightboxPositionSize() {
                    self.$lightbox.on('dragstop resizestop', function(event, ui) {
                        var posSizeObj = {
                            top: ui.position.top,
                            left: ui.position.left,
                            width: self.$lightbox.outerWidth(),
                            height: self.$lightbox.outerHeight()
                        };

                        var key = 'themify_builder_lightbox_frontend_pos_size';

                        if (!ThemifyBuilderCommon.isFrontend()) {
                            key = 'themify_builder_lightbox_backend_pos_size';
                        }

                        localStorage.setItem(key, JSON.stringify(posSizeObj));
                    });
                }

                function setupLightboxSizeClass() {
                        if( parseInt( self.$lightbox.width() ) > 750 ) {
                                self.$lightbox.addClass( 'larger-lightbox' );
                        } else {
                                self.$lightbox.removeClass( 'larger-lightbox' );
                        }
                }

                
                makeLightboxResizable();
                makeLightboxDraggable();
                rememberLightboxPositionSize();
            },

            bindEvents: function() {
                var self = ThemifyBuilderCommon.Lightbox;
                var $body = $('body'),
                    actionEvent = 'true' == themifyBuilder.isTouch ? 'touchend' : 'click';

                $body
                    // Top bar actions
                    .on('editing_row_option editing_column_option editing_module_option editing_subrow_option', self.selectDefaultTab)
                    .on(actionEvent, '.themify_builder_options_tab li', self.switchTabs)
                    .on(actionEvent, '.builder_cancel_lightbox', self.cancel)
                    .on(actionEvent, '#builder_submit_row_settings', themifybuilderapp.Forms.rowSaving)
                    .on(actionEvent, '#builder_submit_subrow_settings', themifybuilderapp.Forms.subRowSaving)
                    .on(actionEvent, '#builder_submit_column_settings', themifybuilderapp.Forms.columnSaving)
                    .on(actionEvent, '#builder_submit_module_settings, #builder_preview_module', themifybuilderapp.Forms.moduleSave)

                    // Content actions
                    .on('change click', '.tf-option-checkbox-js', self.clickRadioOption)
                    .on('change', '.tf-option-checkbox-enable input[type="checkbox"]', self.clickCheckboxOption)
                    .on(actionEvent, '#tfb_module_settings input[type="text"], #tfb_module_settings textarea', self.focusInput)
                    .on('change', '#tfb_module_settings .query_category_single', function(){
                        $(this).closest('.themify_builder_input').find('.query_category_multiple').val($(this).val());
                    })
                    .on(actionEvent, '.reset-styling', self.resetStyling);
                  
                   
                if (!themifyBuilder.disableShortcuts) {
                    self.saveByKeyInput();
                }
            },
            adjustHeight: function(newLightboxHeight)  {
                var self = ThemifyBuilderCommon.Lightbox;

                var $lightboxContent = self.$lightbox.find('.themify_builder_options_tab_wrapper'),
                    heightOfLightboxWithoutContent = 55;

                $lightboxContent.css('height', newLightboxHeight - heightOfLightboxWithoutContent);
            },

            fixContainment: function(){
                var self = ThemifyBuilderCommon.Lightbox,
                    el_w = self.$lightbox.outerWidth(),
                    container_w = $(window).width(),
                    container_h = $(window).height(),
                    containment = [-el_w + 20, 0, container_w - 20, container_h - 30],
                    positions = self.$lightbox.position(),
                    new_positions = {};
                positions.left < containment[0] && (new_positions.left = containment[0]), 0 > positions.top && (new_positions.top = 0), positions.left > containment[2] && (new_positions.left = containment[2]), positions.top > containment[3] && (new_positions.top = containment[3]), self.$lightbox.css(new_positions)
            },

            open: function( options, callback) {
                var self = ThemifyBuilderCommon.Lightbox,
                    $lightboxContainer = $('#themify_builder_lightbox_container');
                console.time('openLightbox');
                if (ThemifyBuilderCommon.isFrontend()) {
                    themifybuilderapp.Frontend.hideSlidingPanel();

                    themifybuilderapp.Frontend.hideModulesControl();
                    themifybuilderapp.Frontend.hideColumnsBorder();
                }

                $lightboxContainer.empty();
                self.$lightbox.addClass( 'tfb-lightbox-open' );
                $('#themify_builder_overlay').show();
                ThemifyBuilderCommon.showLoader('show');

                if ( options.loadMethod && 'inline' == options.loadMethod ) {
                    var response = ThemifyBuilderCommon.templateCache.get( 'tmpl-' + options.templateID );
                    self.openCallback( response, $lightboxContainer, callback );
                } else {
                    options.data = _.extend( options.data || {}, { nonce : themifyBuilder.tfb_load_nonce });
                    options = _.defaults( options || {}, {
                        type:    'POST',
                        url:     themifyBuilder.ajaxurl
                    });

                    var jqxhr = $.ajax(options);
                    jqxhr.done(function(response){
                        self.openCallback( response, $lightboxContainer, callback );
                    });
                }
                console.timeEnd('openLightbox');
            },

            openCallback: function( response, $lightboxContainer, callback ) {
                var self = ThemifyBuilderCommon.Lightbox;

                // Load last position and size of lightbox
                var key = 'themify_builder_lightbox_frontend_pos_size';

                if (!ThemifyBuilderCommon.isFrontend()) {
                    key = 'themify_builder_lightbox_backend_pos_size';
                }

                var posSizeJSON = localStorage.getItem(key),
                    posSizeObj = {
                        top: 100,
                        left: Math.max(0, ( ( $(window).width() / 2 ) - 300 ) ),
                        width: 600,
                        height: 500
                    };

                if (posSizeJSON !== null) {
                    posSizeObj = JSON.parse(posSizeJSON);
                }

                self.$lightbox
                    .show()
                    .css({
                        'top': posSizeObj.top,
                        'left': posSizeObj.left,
                        'width': posSizeObj.width,
                        'height': posSizeObj.height
                    })
                    .addClass('animated fadeIn')
                    .one('webkitAnimationEnd mozAnimationEnd MSAnimationEnd oanimationend animationend', function(e) {
                        self.fixContainment();
                        $(this).removeClass('animated fadeIn');
                    });

                $( document ).on( 'keyup', self.cancelKeyListener );

                ThemifyBuilderCommon.showLoader('spinhide');

                var $response = $(response);
                
                var $optionsTabItemsContainer = $response.find('#themify_builder_lightbox_options_tab_items');
                if ($optionsTabItemsContainer.length) {
                    $('.themify_builder_options_tab').append($optionsTabItemsContainer.children());
                    $optionsTabItemsContainer.remove();
                }

                var $actionButtonsContainer = $response.find('#themify_builder_lightbox_actions_items');
                if ($actionButtonsContainer.length) {
                    $('.themify_builder_lightbox_actions').append($actionButtonsContainer.children());
                    $actionButtonsContainer.remove();
                }

                $lightboxContainer.append($response);

                self.adjustHeight(posSizeObj.height);

                self.$lightbox.show();

                $('#themify_builder_lightbox_container').find('select').not('.font-family-select').wrap('<div class="selectwrapper"></div>');
                $('.selectwrapper').click(function(){
                    $(this).toggleClass('clicked');
                });
              
               
                if( $.isFunction(callback) ){
                    callback.call(this, $response[0]);
                }
                ThemifyBuilderCommon.setUpTooltip();
            },

            close: function() {
                var self = ThemifyBuilderCommon.Lightbox,
                    $tfb_dialog_form = $('form#tfb_module_settings');

                $( document ).off( 'keyup', self.cancelKeyListener );


                if ( typeof tinyMCE !== 'undefined' ) {
                    $tfb_dialog_form.find('.tfb_lb_wp_editor').each( function(){
                        var $id = $(this).prop('id');
                        switchEditors.go($id, 'tmce');
                    });
                }

                if (ThemifyBuilderCommon.isFrontend()) {
                    self.forgetRow();

                    if (themifybuilderapp.liveStylingInstance !== null) {
                        themifybuilderapp.liveStylingInstance.remove();
                    }

                    themifybuilderapp.Frontend.showSlidingPanel();

                    themifybuilderapp.Frontend.showColumnsBorder();
                }

                self.$lightbox.fadeOut(function(e) {
                    $(this).removeClass('animated fadeOut');
                    // Animation complete.
                    $('#themify_builder_lightbox_container').children().remove().end().empty();
                    self.$lightbox.find('.themify_builder_options_tab').empty();
                    self.$lightbox.find('.themify_builder_lightbox_actions')
                        .children()
                        .not('.builder_cancel_lightbox')
                        .remove();

                    $( "#themify_builder_lightbox_parent" ).removeAttr('style');

                    $('#themify_builder_overlay, #themify_builder_lightbox_parent').hide();
                    self.$lightbox.removeClass( 'tfb-lightbox-open' );

                    themifybuilderapp.vent.trigger('dom:builder:change');
                });
            },

            saveByKeyInput: function () {
                $(document).on('keydown', function (event) {
                    // Ctrl + s | Cmd + s
                    if (83 == event.which && (true == event.ctrlKey || true == event.metaKey)) {
                        var currentElement = document.activeElement.tagName.toLowerCase();

                        if (currentElement != 'input' && currentElement != 'textarea') {
                            event.preventDefault();
                            var $moduleSettings = $('#builder_submit_module_settings'),
                                $rowSetting = $('#builder_submit_row_settings'),
                                $subRowSetting = $('#builder_submit_subrow_settings'),
                                $columnSettings = $('#builder_submit_column_settings'),
                                $panelSave = $('.themify_builder_active').find('.themify-builder-front-save-title');
                            if ($moduleSettings.length > 0) {
                                $moduleSettings.trigger('click');
                            } else if ($rowSetting.length > 0) {
                                $rowSetting.trigger('click');
                            } else if ($subRowSetting.length > 0) {
                                $subRowSetting.trigger('click');
                            } else if ($columnSettings.length > 0) {
                                $columnSettings.trigger('click');
                            } else if ($panelSave.length > 0) {
                                $panelSave.trigger('click');
                            }
                        }
                    }
                });
            },

            // If clicked on the "Preview" button in lightbox, save (remember) the original (unmodified) row
            // and put it back on "Cancel" lightbox click.
            rememberedRow: null,
            rememberedCid: null,
            
            rememberRow: function( view ) {
                var self = ThemifyBuilderCommon.Lightbox;

                self.rememberedRow = view.$el[0].outerHTML;
                self.rememberedCid = view.model.cid;

                if ( 'module' === view.model.get('elType') ) {
                    view.model.trigger('custom:restoredata');
                }
            },
            revertToRememberedRow: function() {
                var self = ThemifyBuilderCommon.Lightbox,
                    model = themifybuilderapp.Models.Registry.lookup( self.rememberedCid );

                if ( model ) {
                    model.trigger('custom:restorehtml', self.rememberedRow );
                }

                self.rememberedRow = null;
                self.rememberedCid = null;
            },

            forgetRow: function() {
                var self = ThemifyBuilderCommon.Lightbox;

                self.rememberedRow = null;
                self.rememberedCid = null;
            },

            previewButtonClicked: function($link) {
                return $link.hasClass('builder_preview_lightbox');
            },

            showPreviewBtn: function() {
                $('.builder_button.builder_preview_lightbox').show();
            },

            hidePreviewBtn: function() {
                $('.builder_button.builder_preview_lightbox').hide();
            },
            clickRadioOption: function(e) {
                var selected_item = ThemifyBuilderCommon.getCheckedRadioInGroup($(this), ThemifyBuilderCommon.Lightbox.$lightbox),
                    selected_group = $('input[name="'+selected_item.prop('name')+'"]',ThemifyBuilderCommon.Lightbox.$lightbox);
                    selected_item = selected_item.data('selected');
                selected_group.each(function(){
                    if( $(this).closest( '.themify_builder_row_content' ).length ) {
                        $(this).closest( '.themify_builder_row_content' ).find('.tf-group-element-'+$(this).val()).hide();
                    } else {
                        $('.tf-group-element-'+$(this).val()).hide();
                    }
                });
                if( $(this).closest( '.themify_builder_row_content' ).length ) {
                    $(this).closest( '.themify_builder_row_content' ).find('.'+selected_item).show();
                } else {
                    $('.'+selected_item).show();
                }
                $('.thumb_preview').each(function(){
                    if($(this).find('img').length === 0) {
                        $(this).hide();
                    }
                });
            },
            clickCheckboxOption: function(e) {
               
                 $('.tf-checkbox-element').hide();
                 $(this).parent('.themify-checkbox').find('input:checked').each(function(){
                    $('.tf-checkbox-element.'+$(this).data('selected')).show();
                });
            },
            cancelKeyListener : function(e){
                var self = ThemifyBuilderCommon.Lightbox;

                if( e.keyCode == 27 ) {
                    e.preventDefault();
                    self.cancel(e);
                }
            },

            cancel: function(e) {
				e.preventDefault();

                var self = ThemifyBuilderCommon.Lightbox;

                if (self.rememberedRow !== null) {
                    self.revertToRememberedRow();
                }

                // clear undo/redo start value
                ThemifyBuilderCommon.undoManager.startValue = null;
                ThemifyBuilderCommon.undoManager.startData = {};

                self.close();
            },

            focusInput: function(e) {
                $(this).focus();
            },

            resetStyling: function(e) {
                e.preventDefault();

                var dataReset = $(this).data('reset');
                var $context = null;

                if (dataReset === 'module') {
                    $context = $('#themify_builder_options_styling');
                } else if (dataReset === 'row') {
                    $context = $('#tfb_row_settings');
                } else if (dataReset === 'subrow') {
                    $context = $('#tfb_subrow_settings');
                } else if (dataReset === 'column') {
                    $context = $('#tfb_column_settings');
                }

                var radioGroupNames = [];

                $context.find('.tfb_lb_option:not(.exclude-from-reset-field)').each(function(){
                    var $this = $(this);

                    if ($this.attr('type') === 'radio') {
                        var radioGroupName = $this.attr('name');

                        if (radioGroupNames.indexOf(radioGroupName) === -1) {
                            radioGroupNames.push(radioGroupName);
                        }
                    } else {
                        $this.val('').prop('selected', false);
                    }

                    if( $this.hasClass('themify-builder-uploader-input') ) {
                        $this.parent().find('.img-placeholder').html('').parent().hide();
                    } else if ( $this.hasClass('font-family-select') ) {
                        $this.val('default');
                    } else if( $this.hasClass('builderColorSelectInput') ) {
                        $this.parent().find('.colordisplay').val('').trigger('blur');
                    }
                });

                radioGroupNames.forEach(function(radioGroupName) {
                    $('input:radio[name="' + radioGroupName + '"]:first', $context)
                        .attr('checked', true)
                        .trigger('change');
                });

                if (ThemifyBuilderCommon.isFrontend()) {
                    ThemifyPageBuilder.liveStylingInstance.resetStyling();
                }
            },

            switchTabs: function(e) {
                var self = ThemifyBuilderCommon.Lightbox,
                    $this = $(this);

                e.preventDefault();
                $(this).addClass('current');
                setTimeout( function() {
                    $this.siblings().removeClass('current');
                }, 10 )

                var activeTabId = $(this).find('a').attr('href');
                $(activeTabId).show().siblings('.themify_builder_options_tab_wrapper').hide();

                if (ThemifyBuilderCommon.isFrontend()) {
                    self.handleDisplayOfPreviewBtn(activeTabId);
                }
            },

            selectDefaultTab: function(e) {
                var self = ThemifyBuilderCommon.Lightbox;

                $('.themify_builder_options_tab_wrapper').hide().first().show();

                var $tabItem = $('ul.themify_builder_options_tab li:first');

                $tabItem.addClass('current');

                if (ThemifyBuilderCommon.isFrontend()) {
                    var activeTabId = $tabItem.find('a').attr('href');
                    self.handleDisplayOfPreviewBtn(activeTabId);
                }
            },

            handleDisplayOfPreviewBtn: function(activeTabId) {
                var self = ThemifyBuilderCommon.Lightbox;

                if (activeTabId === '#themify_builder_options_setting') {
                    self.showPreviewBtn();
                } else {
                    self.hidePreviewBtn();
                }
            }
        },
        undoManager: {
            instance: new UndoManager(),
            events: $({}), // create empty object
            startValue: null,
            startData: {},
            set: function( $container, startValue, newValue, startData, newData ) {
                var newStartValue = startValue,
                    newNewValue = newValue,
                    newStartData = startData,
                    newNewData = newData;
                ThemifyBuilderCommon.undoManager.instance.add({
                    undo: function () {
                        $container[0].innerHTML = newStartValue;
                        themifybuilderapp.vent.trigger('dom:observer:update', $container);

                        if ( ! _.isEmpty( newStartData ) ) {
                            var model = themifybuilderapp.Models.Registry.lookup( newStartData.cid );
                            if ( model ) {
                                model.set(newStartData.value, {silent:true});
                            }
                        }
                    },
                    redo: function () {
                        $container[0].innerHTML = newNewValue;
                        themifybuilderapp.vent.trigger('dom:observer:update', $container);

                        if ( ! _.isEmpty( newNewData ) ) {
                            var model = themifybuilderapp.Models.Registry.lookup( newNewData.cid );
                            if ( model ) {
                                model.set(newNewData.value, {silent:true});
                            }
                        }
                    }
                });
                ThemifyBuilderCommon.undoManager.startValue = null;
                ThemifyBuilderCommon.undoManager.startData = {};
            },
            setStartValue: function( value ) {
                ThemifyBuilderCommon.undoManager.startValue = value;
            },
            getStartValue: function() {
                return ThemifyBuilderCommon.undoManager.startValue;
            },
            setStartData: function( data ) {
                ThemifyBuilderCommon.undoManager.startData = data;
            },
            getStartData: function() {
                return ThemifyBuilderCommon.undoManager.startData;
            }
        },
        LiteLightbox: {
            modal: new wp.media.view.Modal({
                controller: { trigger: function() {} }
            }),
            confirmView: wp.Backbone.View.extend({
                template: wp.template('builder_lite_lightbox_confirm'),
                className: 'themify_builder_lite_lightbox_content',
                initialize: function(options) {
                    this.options = options || {};
                },
                render: function() {
                    this.$el.html( this.template( { message: this.options.message, buttons: this.options.buttons } ) );
                },
                events: {
                    'click button': 'buttonClick'
                },
                buttonClick: function( event ) {
                    event.preventDefault();
                    var type = $(event.currentTarget).data('type');
                    this.trigger('litelightbox:confirm', type);
                }
            }),
            promptView: wp.Backbone.View.extend({
                template: wp.template('builder_lite_lightbox_prompt'),
                className: 'themify_builder_lite_lightbox_content',
                initialize: function(options) {
                    this.options = options || {};
                },
                render: function() {
                    this.$el.html( this.template( this.options ) );
                },
                events: {
                    'click button': 'buttonClick',
                    'keypress .themify_builder_litelightbox_prompt_input': 'keyPress'
                },
                buttonClick: function( event ) {
                    event.preventDefault();
                    var type = $(event.currentTarget).data('type'),
                        value = this.$el.find('.themify_builder_litelightbox_prompt_input').val();
                    this.trigger('litelightbox:prompt', type, value);
                },
                keyPress: function( event ) {
                    if ( event.which === 13 ) { // on enter
                        var value = $(event.currentTarget).val();
                        this.trigger('litelightbox:prompt', 'ok', value);
                    }
                }
            }),
            confirm: function( message, callback, options ) {
                options = _.defaults( options || {}, {
                    buttons: {
                        no: {
                            label: 'No'
                        },
                        yes: {
                            label: 'Yes'
                        }
                    }
                });
                options.message = message;
                var contentView = new ThemifyBuilderCommon.LiteLightbox.confirmView( options );
                ThemifyBuilderCommon.LiteLightbox.modal.content( contentView );
                ThemifyBuilderCommon.LiteLightbox.modal.open();
                contentView.on('litelightbox:confirm', function( type ){
                    ThemifyBuilderCommon.LiteLightbox.modal.close();
                    // load callback
                    if ($.isFunction(callback)) {
                        callback.call(this, type);
                    }
                });
            },
            prompt: function( message, callback, options ) {
                options = _.defaults( options || {}, {
                    buttons: {
                        cancel: {
                            label: 'Cancel'
                        },
                        ok: {
                            label: 'OK'
                        }
                    }
                });
                options.message = message;
                var promptView = new ThemifyBuilderCommon.LiteLightbox.promptView( options );
                ThemifyBuilderCommon.LiteLightbox.modal.content( promptView );
                ThemifyBuilderCommon.LiteLightbox.modal.open();
                promptView.on('litelightbox:prompt', function( type, value ){
                    ThemifyBuilderCommon.LiteLightbox.modal.close();
                    // load callback
                    if ($.isFunction(callback)) {
                        value = 'cancel' == type ? null : value;
                        callback.call(this, value);
                    }
                });
            },
			alert: function( message ) {
				ThemifyBuilderCommon.LiteLightbox.confirm( message, null, {
					buttons : {
						yes: {
							label: 'OK'
						}
					}
				} );
			}
        },
        getDomPath: function(el) {
          var stack = [];
          while ( el.parentNode != null ) {
            var sibCount = 0;
            var sibIndex = 0;
            for ( var i = 0; i < el.parentNode.childNodes.length; i++ ) {
              var sib = el.parentNode.childNodes[i];
              if ( sib.nodeName == el.nodeName ) {
                if ( sib === el ) {
                  sibIndex = sibCount;
                }
                sibCount++;
              }
            }
            if ( el.hasAttribute('id') && el.id != '' ) {
              stack.unshift(el.nodeName.toLowerCase() + '#' + el.id);
            } else if ( sibCount > 1 ) {
              stack.unshift(el.nodeName.toLowerCase() + ':eq(' + sibIndex + ')');
            } else {
              stack.unshift(el.nodeName.toLowerCase());
            }
            el = el.parentNode;
          }

          return stack.slice(1); // removes the html element
        },
        getColClassName: function( $el ) {
          var classes = $el.prop('class').split(' '),
              returnClass = 'col-full';
          for (var i = 0; i < classes.length; i++) {
            var matches = /^col([0-9]+)\-([0-9]+)/.exec(classes[i]);
            if (matches != null) {
              returnClass = matches[0];
        }
          }
          return returnClass;
        },
        templateCache: {
          get: function(selector){
            if (!this.templates){ this.templates = {}; }

            var template = this.templates[selector];
            if (!template){
              template = document.getElementById( selector ).innerHTML;

              this.templates[selector] = template;
            }

            return template;
          }
        },
        randNumber: function() {
          this.uuid++;
          return this.uuid + '-' + Math.random().toString( 36 ).substr( 2, 7 );
        }

    };

}(jQuery, window, document));