/* nbdesignerjs
 * @author  netbaseteam
 * @link https://cmsmart.net
 * @version 1.8.1
 * @created Jun 2016
 * @modified 25, Dec 2017
 * */
function checkFireFox() {
    if (navigator.userAgent.toLowerCase().indexOf("firefox") > -1) return true
}
function arrayMin(arr) {
    return arr.reduce(function (p, v) {
        p = parseInt(p);
        v = parseInt(v);
        return (p < v ? p : v);
    });
};
var langjs = {
    "DELETE_ITEM_MESSAGE" : "Are you sure you want to delete this item?",
    "DELETE_ALL_ITEM_MESSAGE" : "Are you sure you want to delete all layers?",
    "LAYER_IMAGE" : "Image",
    "LAYER_GROUP" : "Group",
    "LAYER_PATH" : "Path",
    "LAYER_RECTANGLE" : "Rectangle",
    "LAYER_CIRCLE" : "Circle",
    "LAYER_TRIANGLE" : "Triangle",
    "LAYER_LINE" : "Line",
    "LAYER_POLYGON" : "Polygon",
    "LANGUAGE" : "Language",
    "PREVIEW" : "Preview",
    "ZOOM_IN" : "Zoom In",
    "ZOOM_OUT" : "Zoom Out",
    "TEMPLATE" : "Template",
    "ALIGN" : "Align",
    "ALIGN_LEFT" : "Align Left",
    "ALIGN_RIGHT" : "Align Right",
    "ALIGN_TOP" : "Align Top",
    "ALIGN_BOTTOM" : "Align Bottom",
    "ALIGN_MIDDLE_VERTICAL" : "Align Middle Vertival",
    "ALIGN_MIDDLE_HORIZONTAL" : "Align Middle Horizontal",
    "UNDO" : "Undo",
    "REDO" : "Redo",
    "DOWNLOAD" : "Download",
    "SNAP_GRID" : "Snap grid",
    "PNG" : "PNG",
    "JPG" : "JPG",
    "PDF" : "PDF",
    "LOCK" : "Lock",
    "ELEMENT_UPLOAD" : "Element Upload",
    "LOCK_ALL_ADJUSMENT" : "Lock all adjustment",
    "LOCK_HORIZONTAL_MOVEMENT" : "Lock horizontal movement",
    "LOCK_VERTITAL_MOVEMENT" : "Lock vertical movement",
    "LOCK_HORIZONTAL_SCALING" : "Lock horizontal scaling",
    "LOCK_VERTITAL_SCALING" : "Lock vertical scaling",
    "DISABLE_DRAW_MODE" : "Disable draw mode",
    "LOCK_ROTATION" : "Lock rotation",
    "DESELECT_GROUP" : "Deselect group",
    "REPLACE_IMAGE" : "Replace image",
    "MES_ALLOW_UPLOAD_IMG" : "Only images are allowed",
    "MES_ERROR_MAXSIZE_UPLOAD" : "Oops, file upload larger than",
    "MES_ERROR_MINSIZE_UPLOAD" : "Oops, file upload smaller than",
    "FONT_CAT" : "Font Categories",
    "CAT" : "Categories",
    "TERM_ALERT" : "Please read and accept the terms",
    "DESELECT_ALL"  : "Deselect All",
    "EXCEED_NUMBER" :   "Exceed number of upload files!",
    "NOT_ALLOWED_FILE"  :   "File type not allowed",
    "RETURN_TO_SHOP"  :   "Return to shop",
    "DIMENSION" :   "Dimension",
    "SHOW_BLEED" :   "Show Bleed line",
    "YES" :   "Yes",
    "CANCEL" :   "Cancel",
    "BACKGROUND" :   "Background",
    "BEFORE" :   "Before",
    "AFTER" :   "After",
    "CANNOT_DELETE_LOCKED" : "Can not delete locked layer",
    "LOADING" : "Loading..."
};
function checkIE() {
    var ua = window.navigator.userAgent;
    var msie = ua.indexOf("MSIE");
    if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) return true;
    else return false;
    return false
}
function Check_IE_Version(){
    /*http://stackoverflow.com/questions/31757852/how-can-i-detect-internet-explorer-ie-and-microsoft-edge-using-javascript/32107845#32107845*/
    var rv = -1; 
    if (navigator.appName == 'Microsoft Internet Explorer'){
       var ua = navigator.userAgent,
           re  = new RegExp("MSIE ([0-9]{1,}[\\.0-9]{0,})");
       if (re.exec(ua) !== null){
         rv = parseFloat( RegExp.$1 );
       }
    }
    else if(navigator.appName == "Netscape"){                     
       if(navigator.appVersion.indexOf('Trident') === -1) rv = 12;
       else rv = 11;
    }       
    return rv;          
}
(function(c) {
    var b, d, e, f, g, h = c.body,
        a = c.createElement("div");
    a.innerHTML = '<span style="' + ["position:absolute", "width:auto", "font-size:128px", "left:-99999px"].join(" !important;") + '">' + Array(100).join("wi") + "</span>";
    a = a.firstChild;
    b = function(b) {
        //a.innerHTML = '<span style="' + ["position:absolute", "width:auto", "font-size:128px", "left:-99999px"].join(" !important;") + '">' + b + "</span>";
        a.style.fontFamily = b;
        h.appendChild(a);
        g = a.clientWidth;
        h.removeChild(a);
        return g
    };
    d = b("monospace");
    e = b("serif");
    f = b("sans-serif");
    window.isFontAvailable = function(a) {
        return d !== b(a + ",monospace") || f !== b(a + ",sans-serif") || e !== b(a + ",serif")
    }
})(document);

//(function(d){function c(c){b.style.fontFamily=c;e.appendChild(b);f=b.clientWidth;e.removeChild(b);return f}var f,e=d.body,b=d.createElement("span");b.innerHTML=Array(100).join("wi");b.style.cssText=["position:absolute","width:auto","font-size:128px","left:-99999px"].join(" !important;");var g=c("monospace"),h=c("serif"),k=c("sans-serif");window.isFontAvailable=function(b){return g!==c(b+",monospace")||k!==c(b+",sans-serif")||h!==c(b+",serif")}})(document);

window.performance = window.performance || {};
performance.now = function() {
    return performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow || Date.now
}();
var canvas = null;
var canvasContainerX = 0;
var canvasContainerY = 0;
var colorTrend = ["f98332", "A31A48", "4C49A2", "B8DC3C", "CB2402", "DB2464", "35235D", "EA3556", "61D2D6", "EDE5E2", "ED146F", "EDDE45", "9BF0E9"];
function hexToRGB(hex) {
    var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
    hex = hex.replace(shorthandRegex, function(m, r, g, b) {
        return r + r + g + g + b + b
    });
    var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
    return result ? {
        r: parseInt(result[1], 16),
        g: parseInt(result[2], 16),
        b: parseInt(result[3], 16)
    } : null
}
function toType(obj) {
    return {}.toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}
function isUpperCase(str) {
    return str === str.toUpperCase();
}
function changePattern(url) {
    fabric.util.loadImage(url, function(img) {
        var fill = new fabric.Pattern({
            source: img,
            repeat: "repeat"
        });
        var scope = angular.element(document.getElementById("designer-controller")).scope();
        scope.canvas.item(scope.editableItem).fill = fill;
        scope.canvas.setActiveObject(scope.canvas.item(scope.canvas.getObjects().length - 1));
        if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
    })
}
function degToRad(degrees) {
    return degrees * (Math.PI / 180)
}
function show_indicator() {
    $(".od_processing").show();
    $(".od_processing").css("opacity", 1)
}
function checkNavigator() {
    var ua = window.navigator.userAgent,
        msie = ua.indexOf("MSIE "),
        support = true;
    if (msie > 0) {
        var ver = parseInt(ua.substring(msie + 5, ua.indexOf(".", msie)), 10);
        if (ver < 10) support = false
    }
    return support
}
function hide_indicator() {
    var support = checkNavigator();
    if (!support) {
        $("#first_message").html("Oops! My app not support IE version less than 10...<br /><span>Try with model browser.</span>");
        $(".od_processing").show();
        $(".od_processing").css("opacity", 1)
    } else {
        $(".od_processing").hide();
        $(".od_processing").css("opacity", 0)
    }
}
function show_processing() {
    $("#nbdesigner_processing").addClass("show")
}
function hide_processing() {
    $("#nbdesigner_processing").removeClass("show")
}
function addColorStop() {
    var html = '<div class="row container_color_stop">';
    html += '<div class="col-xs-6">';
    html += '<input type="text" class="ip_shadow jscolor gradient_stop_color" value="F98332" >';
    html += '<input type="text" class="ip_shadow special gradient_stop" value="0">';
    html += '</div><div class="col-xs-5 nb_slider"></div>';
    html += '<div class="clear"></div></div>';
    jQuery("#gradient").append(html);
    jQuery(".nb_slider").slider({
        animate: true,
        slide: function(event, ui) {
            jQuery(this).parent().find(".gradient_stop").val(ui.value /
                100)
        }
    });
    jscolor.installByClassName("jscolor")
}
function removeColorStop() {
    jQuery("#gradient .container_color_stop:last-child").remove()
}
function createGradient() {
    var option = {};
    var length = jQuery("#gradient .container_color_stop").length - 1;
    jQuery("#gradient .container_color_stop").each(function(key, data) {
        var stop = 0;
        stop = jQuery(this).find(".gradient_stop").val();
        if (key == 0) stop = 0;
        if (key == length) stop = 1;
        temp = stop;
        var color = "#" + jQuery(this).find(".gradient_stop_color").val();
        option[stop] = color
    });
    return option
}
function getBinary(file) {
    var xhr = new XMLHttpRequest;
    xhr.open("GET", file, false);
    xhr.overrideMimeType("text/plain; charset=x-user-defined");
    xhr.send(null);
    return xhr.responseText
}
function base64Encode(str) {
    var CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    var out = "",
        i = 0,
        len = str.length,
        c1, c2, c3;
    while (i < len) {
        c1 = str.charCodeAt(i++) & 255;
        if (i == len) {
            out += CHARS.charAt(c1 >> 2);
            out += CHARS.charAt((c1 & 3) << 4);
            out += "==";
            break
        }
        c2 = str.charCodeAt(i++);
        if (i == len) {
            out += CHARS.charAt(c1 >> 2);
            out += CHARS.charAt((c1 & 3) << 4 | (c2 & 240) >> 4);
            out += CHARS.charAt((c2 & 15) << 2);
            out += "=";
            break
        }
        c3 = str.charCodeAt(i++);
        out += CHARS.charAt(c1 >> 2);
        out += CHARS.charAt((c1 & 3) << 4 | (c2 & 240) >> 4);
        out +=
            CHARS.charAt((c2 & 15) << 2 | (c3 & 192) >> 6);
        out += CHARS.charAt(c3 & 63)
    }
    return out
}
function checkMobileDevice(){
    var isMobile = false; 
    if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent) 
    || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(navigator.userAgent.substr(0,4))) isMobile = true;    
    return isMobile;
};
(function() {   
    jQuery("#dg-outline-width").slider({
        animate: true,
        slide: function(event, ui) {
            jQuery(".outline-value").html(ui.value);
            var scope = angular.element(document.getElementById("designer-controller")).scope();
            scope.editable.strokeTemp = ui.value / 100 * 5;
            scope.changeStroke(null, scope.editable.strokeTemp);
            if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
        }
    });
    jQuery(".nb_slider").slider({
        animate: true,
        slide: function(event, ui) {
            jQuery(this).parent().find(".gradient_stop").val(ui.value / 100)
        }
    });
    jQuery("#opacity-text").slider({
        animate: true,
        min: 0,
        max: 1,
        step: .01,
        slide: function(event, ui) {
            var scope = angular.element(document.getElementById("designer-controller")).scope();
            scope.setOpacity(ui.value);
            if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
        }
    });
    jQuery('[data-toggle="tooltip"]').tooltip();
    jQuery("#text-arc").slider({
        animate: true,
        slide: function(event, ui) {
            var scope = angular.element(document.getElementById("designer-controller")).scope();
            jQuery("#text-arc-value").html(ui.value);
            scope.changeCurve(ui.value);
            if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
        }
    });
    jQuery("#letter-spacing").slider({
        animate: true,
        min: 1,
        max: 1000,
        slide: function(event, ui) {
            var scope = angular.element(document.getElementById("designer-controller")).scope();
            scope.changeLetterSpacing(ui.value);
            if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
        }
    });    
    jQuery("#shadow_x, #image_shadow_x").slider({
        animate: true,
        min: 0,
        max: 25,
        slide: function(event, ui) {
            var scope = angular.element(document.getElementById("designer-controller")).scope();
            scope.shadow.x = ui.value;
            scope.changeShadow();
            if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
        }
    });
    jQuery("#shadow_blur, #image_shadow_blur").slider({
        animate: true,
        min: 0,
        max: 25,
        slide: function(event,
            ui) {
            var scope = angular.element(document.getElementById("designer-controller")).scope();
            scope.shadow.blur = ui.value;
            scope.changeShadow();
            if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
        }
    });
    jQuery("#brush_width").slider({
        animate: true,
        min: 0,
        max: 50,
        slide: function(event, ui) {
            var scope = angular.element(document.getElementById("designer-controller")).scope();
            scope.brushWidth = ui.value;
            scope.setDrawingLineWidth(scope.brushWidth);
            if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !==
                "$digest") scope.$apply()
        }
    });
    jQuery("#brush_opacity").slider({
        animate: true,
        min: 0,
        max: 1,
        step: .01,
        slide: function(event, ui) {
            var scope = angular.element(document.getElementById("designer-controller")).scope();
            scope.brushOpacity = 1 - ui.value;
            scope.setDrawingLineOpacity(scope.brushOpacity);
            if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
        }
    });
    jQuery("#brush_shadow_width").slider({
        animate: true,
        min: 0,
        max: 150,
        slide: function(event, ui) {
            var scope = angular.element(document.getElementById("designer-controller")).scope();
            scope.brushShadowWidth = ui.value;
            scope.setDrawingLineShadowWidth(scope.brushShadowWidth);
            if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
        }
    });
    jQuery("#shadow_y, #image_shadow_y").slider({
        animate: true,
        min: 0,
        max: 25,
        slide: function(event, ui) {
            var scope = angular.element(document.getElementById("designer-controller")).scope();
            scope.shadow.y = ui.value;
            scope.changeShadow();
            if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
        }
    });
    jQuery("#shadow_alpha, #image_shadow_alpha").slider({
        animate: true,
        min: 0,
        max: 1,
        step: .01,
        slide: function(event, ui) {
            var scope = angular.element(document.getElementById("designer-controller")).scope();
            scope.shadow.alpha = 1 - ui.value;
            scope.changeShadow();
            if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
        }
    });
    jQuery("#opacity_shape").slider({
        animate: true,
        min: 0,
        max: 1,
        step: .01,
        slide: function(event, ui) {
            var scope = angular.element(document.getElementById("designer-controller")).scope();
            scope.setOpacity(ui.value);
            if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !==
                "$digest") scope.$apply()
        }
    });
    jQuery("#opacity_svg, #image_opacity").slider({
        animate: true,
        min: 0,
        max: 1,
        step: .01,
        slide: function(event, ui) {
            var scope = angular.element(document.getElementById("designer-controller")).scope();
            scope.setOpacity(ui.value);
            if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
        }
    });
    $("a.nb_toggle_popoup").on("click", function(e) {
        e.preventDefault();
        $(this).parent().find("div.nb_toggle_popoup").toggle()
    });
    $("#rotation-text, #rotation-image, #rotation-shape, #rotation-svg").knob({
        width: 50,
        height: 50,
        min: -1,
        max: 360,
        fgColor: "#DD577A",
        bgColor: "#9BF0E9",
        displayPrevious: false,
        readOnly: false,
        cursor: 10,
        thickness: ".3",
        "change": function(v) {
            var object = canvas.getActiveObject();
            if (object != null) {
                object.setAngle(v);
                canvas.renderAll()
            }
        },
        "release": function(v) {
            var object = canvas.getActiveObject();
            if (object != null) {
                object.setAngle(v);
                canvas.renderAll()
            }
        }
    });
    $(".accordion").accordion({
        collapsible: true,
        heightStyle: "content"
    });
    $(".nb_acc, .has-croll").perfectScrollbar();
    if (jQuery(".popovers").length) jQuery(".popovers").popover();
    function applyFilter(index, filter) {
        var scope = angular.element(document.getElementById("designer-controller")).scope();
        var object = scope.canvas.getActiveObject();
        if (object == null) return;
        object.filters[index] = filter;
        object.applyFilters(function() {
            scope.canvas.renderAll(canvas.renderAll.bind(canvas))
        });
        if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
    }
    function applyFilterValue(index, prop, value) {
        var scope = angular.element(document.getElementById("designer-controller")).scope();
        var object = scope.canvas.getActiveObject();
        if (object == null) return;
        if (object.filters[index]) {
            object.filters[index][prop] = value;
            object.applyFilters(canvas.renderAll.bind(canvas))
        }
        if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
    }
    f = fabric.Image.filters;
    $("#grayscale-filter").on("change", function() {
        applyFilter(0, this.checked && new f.Grayscale)
    });
    $("#invert-filter").on("change", function() {
        applyFilter(1, this.checked && new f.Invert)
    });
    $("#sepia-filter").on("change", function() {
        applyFilter(3,
            this.checked && new f.Sepia)
    });
    $("#sepia2-filter").on("change", function() {
        applyFilter(4, this.checked && new f.Sepia2)
    });
    $("#remove-color-filter").on("change", function() {
        applyFilter(20, this.checked && new f.RemoveColor({
            color: [255, 205, 109]
        }))
    });
    $("#remove-white-filter").on("change", function() {
        applyFilter(2, this.checked && new f.RemoveWhite({
            threshold: $("#remove-white-threshold").value,
            distance: $("#remove-white-distance").value
        }))
    });
    $("#brightness-filter").on("change", function() {
        applyFilter(5, this.checked &&
            new f.Brightness({
                brightness: parseInt($("#brightness-value").value, 10)
            }))
    });
    $("#noise-filter").on("change", function() {
        applyFilter(6, this.checked && new f.Noise({
            noise: parseInt($("#noise-value").value, 10)
        }))
    });
    $("#gradient-transparency-filter").on("change", function() {
        applyFilter(7, this.checked && new f.GradientTransparency({
            threshold: parseInt($("#gradient-transparency-value").value, 10)
        }))
    });
    $("#pixelate-filter").on("change", function() {
        applyFilter(8, this.checked && new f.Pixelate({
            blocksize: parseInt($("#pixelate-value").value,
                10)
        }))
    });
    $("#blur-filter").on("change", function() {
        applyFilter(9, this.checked && new f.Convolute({
            matrix: [1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9]
        }))
    });
    $("#sharpen-filter").on("change", function() {
        applyFilter(10, this.checked && new f.Convolute({
            matrix: [0, -1, 0, -1, 5, -1, 0, -1, 0]
        }))
    });
    $("#emboss-filter").on("change", function() {
        applyFilter(11, this.checked && new f.Convolute({
            matrix: [1, 1, 1, 1, .7, -1, -1, -1, -1]
        }))
    });
    $("#edge-enhance-filter").on("change", function() {
        applyFilter(11, this.checked && new f.Convolute({
            matrix: [-1, -1, -1, -1, 9, -1, -1, -1, -1]
        }))
    });
    $("#tint-filter").on("change", function() {
        applyFilter(12, this.checked && new f.Tint({
            color: jQuery("#tint-color").val(),
            opacity: parseFloat(jQuery("#tint-opacity").val())
        }))
    });
    $("#tint-color").on("change", function() {
        applyFilterValue(12, "color", this.value)
    });
    $("#multiply-filter").on("change", function() {
        applyFilter(13, this.checked && new f.Multiply({
            color: document.getElementById("multiply-color").value
        }))
    });
    $("#multiply-color").on("change", function() {
        applyFilterValue(13, "color",
            this.value)
    });
    var blend_mode = "add";
    $("#blend-filter").on("change", function() {
        applyFilter(14, this.checked && new f.Blend({
            color: document.getElementById("blend-color").value,
            mode: blend_mode
        }))
    });
    changeBlendMode = function(mode) {
        blend_mode = mode;
        applyFilterValue(14, "mode", mode)
    };
    $("#blend-color").on("change", function() {
        applyFilterValue(14, "color", this.value)
    });
    var filter = {
        "grayscale": 0,
        "invert": 1,
        "remove-white": 2,
        "sepia": 3,
        "sepia2": 4,
        "brightness": 5,
        "noise": 6,
        "gradient-transparency": 7,
        "pixelate": 8,
        "blur": 9,
        "sharpen": 10,
        "emboss": 11,
        "tint": 12,
        "multiply": 13,
        "blend": 14,
        "edge-enhance": 15
    };
    jQuery(".remove-white-threshold, .remove-white-distance, .brightness-value, .gradient-transparency-value").slider({
        animate: true,
        max: 255,
        slide: function(event, ui) {
            var index = filter[jQuery(this).next().data("parent")];
            var type = jQuery(this).next().data("type");
            jQuery(this).next().val(ui.value);
            applyFilterValue(index, type, parseInt(ui.value))
        }
    });
    jQuery(".noise-value").slider({
        animate: true,
        max: 1E3,
        slide: function(event, ui) {
            var index =
                filter[jQuery(this).next().data("parent")];
            var type = jQuery(this).next().data("type");
            jQuery(this).next().val(ui.value);
            applyFilterValue(index, type, parseInt(ui.value))
        }
    });
    jQuery(".pixelate-value").slider({
        animate: true,
        min: 2,
        max: 20,
        slide: function(event, ui) {
            var index = filter[jQuery(this).next().data("parent")];
            var type = jQuery(this).next().data("type");
            jQuery(this).next().val(ui.value);
            applyFilterValue(index, type, parseInt(ui.value))
        }
    });
    jQuery(".tint-opacity").slider({
        animate: true,
        min: 0,
        max: 1,
        step: .1,
        slide: function(event,
            ui) {
            var index = filter[jQuery(this).next().data("parent")];
            var type = jQuery(this).next().data("type");
            jQuery(this).next().val(ui.value);
            applyFilterValue(index, type, parseFloat(ui.value))
        }
    });
    applyImageFilters = function() {
        canvas.forEachObject(function(obj) {
            if (obj.type === "image" && obj.filters.length) obj.applyFilters(function() {
                obj.canvas.renderAll()
            })
        })
    };
    var mobile = checkMobileDevice();
    if(!mobile){
        jQuery("#layers").sortable({
            stop: function(event, ui) {
                var scope = angular.element(document.getElementById("designer-controller")).scope();
                var chain = [];
                jQuery("#layers .layer").each(function() {
                    chain.push(jQuery(this).attr("id").replace("layer-",""))
                });
                chain = chain.reverse();
                var length = chain.length;
                if (length == 1) return;
                var temp = [],
                    temp1 = [];
                _.each(chain, function(value, key) {
                    chain[key] = parseInt(value);
                    if (chain[key] - key != 0) temp.push(key);
                    if (chain[key] - key > 1 || chain[key] - key < -1) {
                        temp1.push(chain[key]);
                        temp1.push(key)
                    }
                });
                if (temp1.length == 0) {
                    var from = temp[0];
                    var to = temp[1]
                } else {
                    var from = temp1[0];
                    var to = temp1[1]
                }
                scope.sortLayer(from, to);
                if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
            }
        })
    }
    canvas = new fabric.Canvas("designer-canvas");
    canvas.selection = false;
    //canvas.selection = true;
    canvas.controlsAboveOverlay = true;
    canvas.on("selection:cleared", function(options) {
        var scope = angular.element(document.getElementById("designer-controller")).scope();
        scope.canvas = canvas;
        scope.closePopover();
        if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply();
        var mobile = false;
        if ($(window).width() < 768) mobile = true;
        if (mobile) hideConfig();
        if ($("#addition_tool").hasClass("open")) $("#addition_tool .menu_right").triggerHandler("click");
        $('#replace-element-upload').hide();
        scope.editableItem = null;
        scope.shapeMode = false
    });
    canvas.on("mouse:down", function(options) {
        var scope = angular.element(document.getElementById("designer-controller")).scope();
        var object = options.target;
        if(scope.canvas.getActiveGroup()){
            scope.canvas.getActiveGroup().set({
                hasRotatingPoint: false,
                borderColor: "rgba(220, 220, 220, 1)"
            });
            scope.canvas.getActiveGroup().forEachObject(function(obj) {
                obj.set({borderColor: "rgba(220, 220, 220, 0)"});
            });                 
            scope.showAlignToolbar = true;
        }else{
            scope.showAlignToolbar = false;
        }
        if (object == null ) return;  
        var angle = object.angle;
        if (object.angle > 360) angle = angle - 360;
        if (angle < 0) angle = angle + 360;        
        scope.currentItemParameters = {
            'left' : object.left,
            'top' : object.top,
            'scaleX' : object.scaleX,
            'scaleY' : object.scaleY,
            'angle' : angle
        };        
        if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
    });
    canvas.on("mouse:over", function(e) {
        var thisItem = canvas.getObjects().indexOf(e.target);
        var selectedItem = canvas.getObjects().indexOf(canvas.getActiveObject());
        if (thisItem != selectedItem);
        else;
        var scope = angular.element(document.getElementById("designer-controller")).scope();
        if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply();
        canvas.renderAll()
    });
    canvas.on("mouse:out", function(e) {
        canvas.renderAll()
    });
    canvas.on("mouse:up", function(e) {
        var scope = angular.element(document.getElementById("designer-controller")).scope()
    });
    canvas.on("path:created", function(e) {
        var scope = angular.element(document.getElementById("designer-controller")).scope(),
            index = scope.canvas.getObjects().length - 1;
        scope.addLayers(scope.canvas.item(index), scope.canvas.item(index).get("type"),
            index);
        showLayer();
        if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
    });
    canvas.on("object:added", function(options) {
        var object = options.target;
        if (object.type === "path-group" || object.type === "path"){
            //console.log(object.paths);
        }
    });
    canvas.on('text:changed', function (opt) {
        var t1 = opt.target;
        if (t1.width > t1.fixedWidth) {
            t1.fontSize *= t1.fixedWidth / (t1.width + 1);
            t1.width = t1.fixedWidth;
        }
    });    
    canvas.on("object:selected", function(options) {
        var scope = angular.element(document.getElementById("designer-controller")).scope();
        var object = options.target;
        var thisItem = canvas.getObjects().indexOf(canvas.getActiveObject());
        var mobile = false;
        if ($(window).width() < 768) mobile = true;
        if (!mobile) showLayer();
        showConfig();
        scope.lockProportion = angular.isDefined(object.lockUniScaling) ? object.lockUniScaling : false;
        canvas.getActiveObject().set({
            borderColor: "rgba(220, 220, 220, 1)",
            borderWidth: 10,
            hasRotatingPoint: false,
            cornerSize: 12,
            borderOpacityWhenMoving: 1,
            lockUniScaling: scope.lockProportion
        });
        scope.editableItem = thisItem;
        scope.editable.angle = object.angle;
        var angle = object.angle;
        if (object.angle > 360) angle = angle - 360;
        if (angle < 0) angle = angle + 360;
        angle = parseInt(angle);
        scope.editable.pattern = false;
        scope.editable.width = object.getWidth();
        scope.editable.height = object.getHeight();
        scope.currentLayerActive = thisItem;
        scope.editable.type = object.type;
        if (toType(object.getFill()) === "string") scope.editable.fill = object.getFill();
        else if (toType(object.getFill()) === "object") scope.editable.pattern = true;
        scope.editable.stroke = object.getStroke();
        scope.editable.strokeWidth = object.getStrokeWidth() * 20;
        if (object.type === "i-text" || object.type === "text" || object.type === "curvedText") {
            scope.showPopover("text");
            scope.editable.text = object.getText();
            scope.editable.textAlign = object.getTextAlign();
            scope.editable.fontFamily = object.getFontFamily();
            scope.editable.fontSize = object.getFontSize();
            scope.editable.charSpacing = object.get('charSpacing');
            scope.editable.ptFontSize = scope.editable.fontSize;
            if(object.type != "curvedText"){
                var newFontSize = object.fontSize * object.scaleX;
                var newPtFontSize = newFontSize / scope.ratioConvertFont;
                newPtFontSize = newPtFontSize.toFixed(2);
                var minSize = arrayMin(scope.listFontSizeInPt);
                if( scope.forceMinSize && minSize > newPtFontSize ){
                    newPtFontSize = minSize;
                    newFontSize = newPtFontSize * scope.ratioConvertFont;
                    newPtFontSize = newPtFontSize.toFixed(2);
                }
                object.set({
                    scaleX: 1,
                    scaleY: 1,
                    fontSize: newFontSize,
                    ptFontSize: newPtFontSize
                });
                scope.editable.ptFontSize = object.get('ptFontSize');
            };
            scope.editable.lineHeight = object.get('lineHeight');
            if( _.size(scope._allFonts )){
                var match = false;
                _.each(scope._allFonts, function( font ){
                    if(font.alias == scope.editable.fontFamily){
                        scope.currentFont = font;
                        match = true;
                    }
                });
                if(!match) scope.currentFont = {alias : 'Roboto', name : 'Roboto'};
            }else {
                scope.currentFont = {alias : 'Roboto', name : 'Roboto'};
            }
            jQuery("#letter-spacing").slider('value',object.get('charSpacing'));
            $("#rotation-text").val(angle).trigger("change")
        }
        if(object.type === "curvedText" && NBDESIGNCONFIG['lang_rtl'] == 'rtl'){
            if(object.rtl) scope.editable.text = reverseString(object.getText());
        }
        scope.editable.available_color = false;
        if (object.type === "image" || object.type === "custom-image") {
            scope.showPopover("art");
            $("#rotation-image").val(angle).trigger("change");
            var opacity = object.get("opacity");
            $("#image_opacity").slider("value", 1 - opacity);
            
            /* layer color */
            if( angular.isDefined( object.available_color ) ){
                scope.editable.available_color = object.available_color;
            }           
            scope.editable.available_color_list = [];
            if( angular.isDefined( object.available_color_list ) ){
                scope.editable.available_color_list = object.available_color_list.split(',');
            }
            scope.editable.color_link_group = '';
            if( angular.isDefined( object.color_link_group ) ){
                scope.editable.color_link_group = object.color_link_group;
            }
        }
        if (object.type === "rect" || object.type === "triangle" || object.type === "line" || object.type === "polygon" || object.type === "circle") {
            var opacity = object.get("opacity");
            scope.showPopover("draw");
            scope.shapeMode=true;
            $("#opacity_shape").slider("value", 1 - opacity);
            $("#rotation-shape").val(angle).trigger("change");
        }
        if (object.type === "curvedText") scope.editable.effect = "block";
        else scope.editable.effect = "none";
        if (object.type === "path-group" || object.type === "path") {
            scope.showPopover("clipArt");
            var opacity = object.get("opacity");
            $("#rotation-svg").val(angle).trigger("change");
            $("#opacity_svg").slider("value", 1 - opacity)
        }
        if(typeof object.itemId === 'undefined') {
            var d = new Date();
            var itemId = d.getTime();  
            object.set({"itemId" : itemId})
        }
        scope.updatePositionReplaceButton();
        if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply();
        return
    });
    canvas.on("object:scaling", function(options) {
        var object = options.target;
        var scope = angular.element(document.getElementById("designer-controller")).scope();
        scope.editable.width = object.getWidth();
        scope.editable.height = object.getHeight();
        scope.updatePositionReplaceButton();
        if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
    });
    canvas.on("object:moving", function(options) {
        var object = options.target;
        var grid = 10;
        var scope = angular.element(document.getElementById("designer-controller")).scope();        
        if(scope.gridMode){
            object.set({
                left: Math.round(object.left / grid) * grid,
                top: Math.round(object.top / grid) * grid
            });           
        }
        scope.updatePositionReplaceButton();
        if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply();
        return        
    });
    canvas.on("object:rotating", function(options) {
        var object = options.target;
        var scope = angular.element(document.getElementById("designer-controller")).scope();
        var thisItem = canvas.getObjects().indexOf(canvas.getActiveObject());
        var angle = object.angle;
        if (object.angle > 360) angle = angle - 360;
        if (angle < 0) angle = angle + 360;
        angle = parseInt(angle);        
        if (object.type === "i-text" || object.type === "text" || object.type === "curvedText") $("#rotation-text").val(angle).trigger("update");
        if (object.type === "image" || object.type === "custom-image") $("#rotation-image").val(angle).trigger("change");
        if (object.type === "rect" || object.type === "triangle" || object.type === "line" || object.type === "polygon" || object.type === "circle") $("#rotation-shape").val(angle).trigger("change");
        if (object.type === "path-group" || object.type === "path") $("#rotation-svg").val(angle).trigger("change")
    });
    canvas.on("object:modified", function(options) {
        var object = options.target;
        var scope = angular.element(document.getElementById("designer-controller")).scope();
        var thisItem = canvas.getObjects().indexOf(canvas.getActiveObject());
        scope.editableItem = thisItem;
        scope.canvas = canvas;
        var angle = object.angle;
        if (object.angle > 360) angle = angle - 360;
        if (angle < 0) angle = angle + 360;
        angle = parseInt(angle);
        scope.editable.angle = angle;
        if (object.type === "i-text" || object.type === "text" || object.type === "curvedText") {
            scope.editable.spacing = object.get("spacing");
            scope.editable.text = object.getText();
            if(object.type != "curvedText"){
                var newFontSize = object.fontSize * object.scaleX;
                var newPtFontSize = newFontSize / scope.ratioConvertFont;
                newPtFontSize = newPtFontSize.toFixed(2);
                var minSize = arrayMin(scope.listFontSizeInPt);
                if( scope.forceMinSize && minSize > newPtFontSize ){
                    newPtFontSize = minSize;
                    newFontSize = newPtFontSize * scope.ratioConvertFont;
                    newPtFontSize = newPtFontSize.toFixed(2);
                }
                object.set({
                    scaleX: 1,
                    scaleY: 1,
                    fontSize: newFontSize,
                    ptFontSize: newPtFontSize
                });  
                scope.editable.fontSize = newFontSize;
                scope.editable.ptFontSize = newPtFontSize;
            }
            $("#rotation-text").val(angle).trigger("change")
        }
        if(object.type === "curvedText" && NBDESIGNCONFIG['lang_rtl'] == 'rtl'){
            if(object.rtl) scope.editable.text = reverseString(object.getText());
        }        
        scope.editable.width = object.getWidth();
        scope.editable.height = object.getHeight();  
        if (object.type === "image" || object.type === "custom-image") $("#rotation-image").val(angle).trigger("change");
        if (object.type === "rect" || object.type === "triangle" || object.type === "line" || object.type === "polygon" || object.type === "circle") $("#rotation-shape").val(angle).trigger("change");
        if (object.type === "path-group" || object.type === "path") $("#rotation-svg").val(angle).trigger("change");                
        scope.setUndoRedo({element: object, parameters: JSON.stringify(scope.currentItemParameters), interaction: 'modify'});
        scope.$apply();
        return
    });
    canvas.on("before:render", function() {
        var scope = angular.element(document.getElementById("designer-controller")).scope();
        scope.processing = 0;
        if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
    });
    canvas.on("after:render", function(e) {
        var scope = angular.element(document.getElementById("designer-controller")).scope();
        scope.processing = 100;
        if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
    });
    canvas2 = new fabric.Canvas("crop_canvas");
    canvas2.on("object:moving", function(options) {
        var object = options.target;
        ajustCropPath(object)
    });
    canvas2.on("object:rotating", function(options) {
        var object = options.target;
        ajustCropPath(object)
    });
    canvas2.on("object:scaling", function(options) {
        var object = options.target;
        ajustCropPath(object)
    });
    canvas2.on("object:modified", function(options) {
        var object = options.target;
        ajustCropPath(object)
    });
    canvas2.on("object:selected", function(options) {
        var object = options.target;
        ajustCropPath(object)
    });
    canvas2.on("path:created", function() {
        canvas2.isDrawingMode = false;
        var scope = angular.element(document.getElementById("designer-controller")).scope();
        var index = canvas2.getObjects().length;
        if (canvas2.item(2) && index > 3) canvas2.remove(canvas2.item(2));
        scope.currentPathCrop = canvas2.item(2).path;
        var object = canvas2.item(2);
        canvas2.item(2).set({
            centeredScaling: true,
            hasRotatingPoint: false
        });
        canvas2.item(2)["setControlVisible"]("tl", false);
        canvas2.item(2)["setControlVisible"]("bl", false);
        canvas2.setActiveObject(object);
        canvas2.renderAll();
        ajustCropPath(object);
        if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
    });
    function ajustCropPath(object) {
        var scope = angular.element(document.getElementById("designer-controller")).scope();
        var path = new fabric.Path(scope.currentPathCrop);
        var scaleX = object.get("scaleX"),
            scaleY = object.get("scaleY"),
            ratioX = canvas2.item(1).get("scaleX"),
            ratioY = canvas2.item(1).get("scaleY"),
            cv_witdth = canvas2.width,
            cv_height = canvas2.height,
            crop_width = object.get("width"),
            crop_height = object.get("height"),
            old_left = cv_witdth / 2 - crop_width / 2,
            old_top = cv_height / 2 - crop_height / 2,
            left = object.get("left") - crop_width / 2,
            top = object.get("top") - crop_height / 2;
        path.set({
            originX: "center",
            originY: "center",
            left: (object.get("left") - cv_witdth / 2) * 1 / ratioX,
            top: (object.get("top") - cv_height / 2) * 1 / ratioY,
            scaleX: 1 / ratioX * scaleX,
            scaleY: 1 / ratioY * scaleY,
            angle: object.angle,
            fill: "#9bf0e9",
            strokeWidth: 0,
            opacity: 0
        });
        canvas2.item(1).set({
            clipTo: function(ctx) {
                path.render(ctx)
            }
        });
        if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
    }
    angular.module("app", ["LocalStorageModule", "angularFileUpload", "imgpreload", "angularSpectrumColorpicker"]).constant("_", window._).config(function(localStorageServiceProvider) {
        localStorageServiceProvider.prefix = "nbdesigner"
    })
})();
/**
 * List path mark
 * @for function crop image
 * @type array conatain SVG path
 */
var listPath = {
    "path_mark": "M1.398,84.129c3.305,20.461,9.73,50.635,13.591,67.385c2.354,10.212,12.549,23.734,18.51,30.02c4.923,5.191,27.513,23.343,38.34,27.589c18.604,7.295,33.984,4.187,46.012-8.306c12.028-12.493,25.595-34.78,27.954-43.994c2.587-10.105,5.065-26.842,4.313-37.243c-1.036-14.316-14.224-69.332-16.806-79.55c-4.48-17.735-26.246-48.821-80.609-37.668C-1.66,13.514-1.879,63.844,1.398,84.129z",
    "path_crop": "M0 0 L0 100 L100 100 L100 0Z",
    "path_1": "M 12 0 l 2.139 2.629 l 3.068 -1.441 l 0.786 3.297 l 3.389 0.033 l -0.722 3.312 l 3.039 1.5 l -2.088 2.67 l 2.088 2.67 l -3.039 1.5 l 0.722 3.312 l -3.389 0.033 l -0.786 3.297 l -3.068 -1.441 l -2.139 2.629 l -2.139 -2.629 l -3.068 1.441 l -0.786 -3.297 l -3.389 -0.033 l 0.722 -3.312 l -3.039 -1.5 l 2.088 -2.67 l -2.088 -2.67 l 3.039 -1.5 l -0.722 -3.312 l 3.389 -0.033 l 0.786 -3.297 l 3.068 1.441 Z",
    "path_2": "M 0.054 23 c 0.971 -1.912 2.048 -4.538 1.993 -6.368 c -1.308 -1.562 -2.047 -3.575 -2.047 -5.625 c 0 -5.781 5.662 -10.007 12 -10.007 c 6.299 0 12 4.195 12 10.007 c 0 6.052 -6.732 11.705 -15.968 9.458 c -1.678 1.027 -5.377 2.065 -7.978 2.535 Z",
    "path_3": "M-12,0a12,12 0 1,0 24,0a12,12 0 1,0 -24,0",
    "path_4": "M 9 0 c -5 0 -9 7 -9 14 c 0 5 3 10 9 10 c 6 0 9 -5 9 -10 c 0 -7 -4 -14 -9 -14 Z",
    "path_5": "M 12 4.248 c -3.148 -5.402 -12 -3.825 -12 2.944 c 0 4.661 5.571 9.427 12 15.808 c 6.43 -6.381 12 -11.147 12 -15.808 c 0 -6.792 -8.875 -8.306 -12 -2.944 Z",
    "path_6": "M 18 1 l -6 4 l -6 -4 l -6 5 v 7 l 12 10 l 12 -10 v -7 Z",
    "path_7": "M 24 16.971 l -7.029 7.029 h -9.942 l -7.029 -7.029 v -9.942 l 7.029 -7.029 h 9.942 l 7.029 7.029 Z",
    "path_8": "M 12 0 c -2.995 2.995 -7.486 4 -11 4 c 0 8.583 5.068 16.097 11 20 c 5.932 -3.903 11 -11.417 11 -20 c -3.514 0 -8.005 -1.005 -11 -4 Z",
    "path_9": "M 1 4 c 0 8.578 5.071 16.1 11 20 c 5.929 -3.9 11 -11.422 11 -20 c -2.828 -2.329 -7.153 -4 -11 -4 c -3.838 0 -8.172 1.671 -11 4 Z",
    "path_10": "M 12 0.587 l 3.668 7.568 l 8.332 1.151 l -6.064 5.828 l 1.48 8.279 l -7.416 -3.967 l -7.417 3.967 l 1.481 -8.279 l -6.064 -5.828 l 8.332 -1.151 Z",
    "path_11": "M 0.000 16.000 L 12.000 20.785 L 13.856 8.000 L 24.000 0.000 L 13.856 -8.000 L 12.000 -20.785 L 0.000 -16.000 L -12.000 -20.785 L -13.856 -8.000 L -24.000 0.000 L -13.856 8.000 L -12.000 20.785 z",
    "path_12": "M10,10 h20 a2,2 0 0 0.1 2,2 v20 a2,2 0 0 0.1 -2,2 h-20 a2,2 0 0 0.1 -2,-2 v-20 a2,2 0 0 0.1 2,-2 z",
    "path_13": "M0 0 L24 0 L12 20.78z"
};
"use strict";
var topLeftImage = new Image;
topLeftImage.src = NBDESIGNCONFIG['assets_url'] + "images/fa_times.png";
var topRightImage = new Image;
topRightImage.src = NBDESIGNCONFIG['assets_url'] + "images/fa_rotate.png";
var bottomRightImage = new Image;
bottomRightImage.src = NBDESIGNCONFIG['assets_url'] + "images/fa_resize.png";
var bottomLeftImage = new Image;
bottomLeftImage.src = NBDESIGNCONFIG['assets_url'] + "images/fa_layers.png";
function isVML() {
    return typeof G_vmlCanvasManager !== "undefined"
}
fabric.Object.prototype.centeredScaling = true;
fabric.Object.prototype.statefullCache = true;
fabric.Object.prototype.cacheProperties = (
  'fill stroke strokeWidth strokeDashArray width height stroke strokeWidth strokeDashArray' +
  ' strokeLineCap strokeLineJoin strokeMiterLimit fillRule backgroundColor'
).split(' ');
fabric.Object.prototype._drawControl = function(control, ctx, methodName, left, top) {
    var size = this.cornerSize;
    if (this.isControlVisible(control)) {
        isVML() || this.transparentCorners || ctx.clearRect(left, top, size, size);
        ctx.strokeStyle = "rgba(220, 220, 220, 1)";
        ctx.lineWidth = 1;
        if (control == "tl") {
            ctx.drawImage(topLeftImage, left, top, size, size);
            ctx.strokeRect(left, top, size, size)
        } else if (control == "tr") {
            ctx.drawImage(topRightImage, left, top, size, size);
            ctx.strokeRect(left, top, size, size)
        } else if (control == "bl") {
            ctx.drawImage(bottomLeftImage,
                left, top, size, size);
            ctx.strokeRect(left, top, size, size)
        } else if (control == "br") {
            ctx.drawImage(bottomRightImage, left, top, size, size);
            ctx.strokeRect(left, top, size, size)
        } else;
    }
};
fabric.Canvas.prototype._getActionFromCorner = function(target, corner) {
    var action = "drag";
    if (corner) {
        action = corner === "ml" || corner === "mr" ? "scaleX" : corner === "mt" || corner === "mb" ? "scaleY" : corner === "tl" ? "rotate" : "scale";
        if (corner == "tr") action = "rotate";
        if (corner == "tl") {
            action = "delete";
            deleteObject()
        }
        if (corner == "bl") {
            action = "layer";
            var scope = angular.element(document.getElementById("designer-controller")).scope();
            scope.duplicateItem();
            if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
        }
    }
    return action
};
function deleteObject(index) {
    $.confirm({
        text: langjs["DELETE_ITEM_MESSAGE"],
        confirm: function() {
            var scope = angular.element(document.getElementById("designer-controller")).scope();
            if( scope.isLockMovement() ) {
                alert(langjs['CANNOT_DELETE_LOCKED']);
                return;
            }
            if (index == null) {
                scope.setUndoRedo({
                    element: scope.canvas.getActiveObject(),
                    parameters: scope.getItemJson(scope.canvas.getActiveObject()),
                    interaction: 'remove'
                });      
                if(scope.canvas.getActiveGroup()){
                    var group = scope.canvas.getActiveGroup(),
                    items = group.getObjects();
                    items.forEach(function(item, index){
                        scope.canvas.remove(item);
                    });
                    scope.deactiveGroup();
                }else{
                    scope.canvas.remove(scope.canvas.getActiveObject());
                }
                scope.editableItem = null;                
                scope.closePopover()
            } else {      
                scope.setUndoRedo({
                    element: scope.canvas.item(index),
                    parameters: scope.getItemJson(scope.canvas.item(index)),
                    interaction: 'remove'
                });       
                scope.canvas.remove(scope.canvas.item(index));
            }         
            scope.drawCanvas();
            scope.pop.art = "none";
            scope.pop.text = "none";
            scope.pop.clipArt = "none";
            scope.pop.qrcode = "none";
            scope.pop.draw = "none"; 
            scope.updateCurrentLayerAfterDelete();
            if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
        },
        cancel: function() {}
    })
}
function deleteAllObject() {
    $.confirm({
        text: langjs["DELETE_ALL_ITEM_MESSAGE"],
        confirm: function() {
            var scope = angular.element(document.getElementById("designer-controller")).scope();
            scope.canvas.clear();
            scope.closePopover();
            scope.updateCurrentLayerAfterDelete();
            scope.clearHistory();
            if ($("#gesture .menu_gesture").hasClass("open")) $("#gesture .menu_gesture .m-center").triggerHandler("click");
            if ($("#layer").hasClass("open")) $("#layer").triggerHandler("click");
            scope.pop.art = "none";
            scope.pop.text = "none";
            scope.pop.clipArt = "none";
            scope.pop.qrcode = "none";
            scope.pop.draw = "none";               
            if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
        },
        cancel: function() {}
    })
}
fabric.Canvas.prototype._handleCursorAndEvent = function(e, target) {
    this._setCursorFromEvent(e, target);
    var _this = this;
    setTimeout(function() {
        _this._setCursorFromEvent(e, target)
    }, 50);
    this.fire("mouse:up", {
        target: target,
        e: e
    });
    target && target.fire("mouseup", {
        e: e
    })
};
fabric.Canvas.prototype._getRotatedCornerCursor = function(corner, target) {
    var cursorOffset = {
        mt: 0,
        tr: 1,
        mr: 2,
        br: 3,
        mb: 4,
        bl: 5,
        ml: 6,
        tl: 7
    };
    if (corner == "tr") return "copy";
    if (corner == "tl") return "pointer";
    if (corner == "bl") return "cell";
    var n = Math.round(target.getAngle() % 360 / 45);
    if (n < 0) n += 8;
    n += cursorOffset[corner];
    n %= 8;
    return this.cursorMap[n]
};
fabric.CustomImage = fabric.util.createClass(fabric.Image, {
    type: "custom-image",
    initialize: function(element, options) {
        this.callSuper("initialize", element, options);
        options && this.set("origin_src", options.origin_src)
    },
    toObject: function() {
        return fabric.util.object.extend(this.callSuper("toObject"), {
            "origin_src": this.origin_src
        })
    }
});
fabric.CustomImage.fromObject = function(object, callback) {
    fabric.util.loadImage(object.src, function(img) {
        callback && callback(new fabric.CustomImage(img, object))
    })
};
fabric.CustomImage.async = true;

function addFontFaceToFaric(name, type, url) {
    var font = name.replace(/\s/g, "+");
    if (type == "google") fabric.googleFonts[font] = "https://fonts.googleapis.com/css?family=" + font;
    else {
        base64 = base64Encode(getBinary(url));
        fabric.fontPaths[font] = base64
    }
}
var _window = {
    "width": 500,
    "height": 500
};
function calcCanvasWidth() {
    var w = $(window).width();
    var h = $(window).height();
    if (w > h - 120) _window.width = h - 120;
    else _window.width = w;
    return _window.width
}
function reverseString(s) {
  return s.split('').reverse().join('');
}
var attachProductInfo = 0;
var itemConfig = {
    'clickToUpload' : false,
    'rtl' : false,
    'lockMovementX' : false,
    'lockMovementY' : false,
    'lockScalingX' : false,
    'lockScalingY' : false,
    'lockRotation' : false
};
var app = angular.module("imgpreload", []);
$(nbd_window).on("resize", function() {
    var scope = angular.element(document.getElementById("designer-controller")).scope();
    scope.resetDimension();
    if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
});
app.directive("spinnerOnLoad", function() {
    return {
        restrict: "A",
        link: function(scope, element) {
            element.on("load", function() {
                element.removeClass("spinner-hide");
                element.addClass("spinner-show");
                element.parent().removeAttr("width");
                element.parent().find("span").remove()
            });           
            scope.$watch("ngSrc", function() {
                element.addClass("spinner-hide");
                element.parent().append('<span class="spinner"></span>')
            })
        }
    }
}).directive("fontOnLoad", function() {
    return {
        restrict: "A",
        link: function(scope, element) {
            var start = setInterval(function() {
                var font = element.find(".nbdesigner_font_name").data("font");
                if (isFontAvailable(font)) {
                    element.find(".spinner").remove();
                    element.removeAttr("width");
                    element.css("opacity", 1);
                    clearInterval(start)
                }
            }, 100);
            var to = setTimeout(function() {
                var font = element.find(".nbdesigner_font_name").data("font");
                if (isFontAvailable(font)) clearInterval(to);
                if (!isFontAvailable(font)) {
                    element.find(".spinner").remove();
                    element.removeAttr("width");
                    element.css("opacity", 1);                    
                    clearInterval(start);
                    //element.remove()
                }
            }, 5E3);
            element.append('<span class="spinner"></span>')
        }
    }
});
angular.module("app").controller("DesignerController", function($scope, PatternService, ProductService, localStorageService, FontService, ArtService, QrcodeService, $interval, $upload, $timeout, LanguageService, AdminTemplateService, CartDesignsService, UserDesignsService) {
    $scope.canvas = null;
    $scope.designerWidth = calcCanvasWidth();
    $scope.designerHeight = calcCanvasWidth();
    $scope.originDesignerWidth = calcCanvasWidth();
    $scope.originDesignerHeight = calcCanvasWidth();
    $scope.modeMobile = false;
    var w = $(window).width();
    if (w < 768) $scope.modeMobile = true;
    $scope.offset = w / 2 - $scope.designerWidth / 2;
    $scope.editableItem = null;
    $scope.editableObject = null;
    $scope.currentVariant = {};
    $scope.currentVariant.info = {};
    $scope.varaints = {};
    $scope.varaints.frames = {};
    $scope.varaints.areaDesign = {};
    $scope.varaints.areaParams = {};
    $scope.currentVariant.orientationActive = "frame_0";
    $scope.currentVariant.orientationBefore = "frame_0";
    $scope.currentVariant.index = 0;
    $scope.layers = {};
    $scope.currentLayers = [];
    $scope.currentLayerActive = 1;
    $scope.currentColor = "FFFFFF";
    $scope.editMode = "none";
    $scope.borderColor = "#000000";
    $scope.colorOptional = NBDESIGNCONFIG['nbdesigner_default_color'].substr(1, 7);
    $scope.colorStrokeOptional = NBDESIGNCONFIG['nbdesigner_default_color'].substr(1, 7);
    $scope.background = NBDESIGNCONFIG['nbdesigner_default_color'].substr(1, 7);
    $scope.lockProportion = true;
    $scope.lineHeight = 1;
    $scope.fontSize = 30;
    $scope.loaded = 0;
    $scope.shadow = {};
    $scope.shadow.x = 0;
    $scope.shadow.y = 0;
    $scope.shadow.blur = 0;
    $scope.shadow.alpha = 1;
    $scope.shadow.color = NBDESIGNCONFIG['nbdesigner_default_color'].substr(1, 7);
    $scope.loaded = 0;
    $scope.zoom = 1;
    $scope.settings = {};
    $scope.Popover = "none";
    $scope.currentFont = {};
    $scope.currentFont.name = "Roboto";
    $scope.pop = {};
    $scope.pop.type = "";
    $scope.pop.text = "none";
    $scope.pop.art = "none";
    $scope.pop.clipArt = "none";
    $scope.pop.qrcode = "none";
    $scope.pop.draw = "none";
    $scope.canvases = {};
    $scope.svgs = {};
    $scope.undos = {};
    $scope.redos = {};
    $scope.dataCustomerDesign = {};
    $scope.editable = {};
    $scope._ = _;
    $scope.uploadURL = [];
    $scope.file = [];
    $scope.loading = false;
    $scope.currentCateFont = langjs['FONT_CAT'];
    $scope.contentText = "Text Here";
    $scope.designScale = calcCanvasWidth() / NBDESIGNCONFIG['stage_dimension']['width'];
    $scope.scale = {};
    $scope.rateConvertCm2Px96dpi = 37.8;
    $scope.currentScale = "1";
    $scope.iid = "images";
    $scope.qrCodeContent = '';
    $scope.qrCodeContentHolder = NBDESIGNCONFIG['nbdesigner_default_qrcode'];
    $scope.imgPageSize = 10;
    $scope.artPageSize = 10;
    $scope.artPageSizes = [];
    $scope.imgCurrentPage = 0;
    $scope.artCat = [];
    $scope.arts = [];
    $scope.curentCatArt = "0";
    $scope.currentCatArtName = langjs['CAT'];
    $scope.editable.paths = [];
    $scope.pathColor = [];
    $scope.countArt = 0;
    $scope.fontPageSize = 10;
    $scope.fontPageSizes = [];
    $scope.fontCat = [];
    $scope.fonts = [];
    $scope.AllFonts = [];
    $scope.google_font = [];
    $scope.googleFont = [];
    $scope.customFont = [];
    $scope.googleFontPageSize = 10;
    $scope.adminTemplatePageSize = 8;
    $scope.listDesignsInCartPageSize = 8;
    $scope.listMyDesignsPageSize = 8;
    $scope.curentCatFont = "0";
    $scope.currentCatFontName = langjs['CAT'];
    $scope.countFont = 0;
    $scope.enableGroup = false;
    $scope.colorBrush = NBDESIGNCONFIG['nbdesigner_default_color'].substr(1, 7);
    $scope.brushShadowWidth = 1;
    $scope.brushWidth = 1;
    $scope.brushOpacity = 1;
    $scope.brushAngle = 0;
    $scope.colorShape = NBDESIGNCONFIG['nbdesigner_default_color'].substr(1, 7);
    $scope.shapeMode = false;
    $scope.currentPreview = NBDESIGNCONFIG['assets_url'] + "images/default.png";
    $scope.processing = 100;
    $scope.currentPathCrop = listPath.path_crop;
    $scope.patterns = [];
    $scope.patternPageSize = 10;
    $scope.imageFromUrl = "";
    $scope.fontCollection = {};
    $scope.currentFontCollection = [];
    $scope.ajustmentScale = 1;
    $scope.ajustmentOrientationScale = [];
    $scope.flagChangeOrientation = [];
    $scope.ignoreLocalDesign = false;
    $scope.adminListTemplate = [];
    $scope.backgroundId = 0;
    $scope.statusWebcam = false;
    $scope.onLoadProduct = false;
    $scope.rtlLang = (NBDESIGNCONFIG['lang_rtl'] == 'rtl') ? true : false;
    $scope.langMode = NBDESIGNCONFIG['lang_rtl'];
    $scope.refProduct = [];
    $scope.showAlignToolbar = false;
    $scope.holdShiftKey = false;
    $scope.gridMode = false;
    $scope.task = NBDESIGNCONFIG['task'];
    $scope.design_type = NBDESIGNCONFIG['design_type'];
    $scope.orientationActiveUndoStatus = false;
    $scope.orientationActiveRedoStatus = false;
    $scope.currentItemParameters = {};
    $scope.readyReplaceImage = false;
    $scope.colorPalette = colorPalette;
    $scope.includeOverlay = true;
    $scope.designMode = 'custom';
    $scope.dropboxImages = [];
    if( NBDESIGNCONFIG['nbdesigner_show_all_color'] == 'yes' )
    $scope.backgroundPalette = ['#f44336','#e91e63','#9c27b0','#673ab7', '#3f51b5','#2196f3','#03a9f4','#00bcd4','#009688','#4caf50', '#8bc34a', '#cddc39', '#ffeb3b', '#ffc107', '#ff9800', '#ff5722', '#795548', '#9e9e9e', '#607d8b', '#374046'];
    if(NBDESIGNCONFIG['nbdesigner_show_all_color'] == 'no') $scope.backgroundPalette = _.uniq( _.flatten( colorPalette ) );
    $scope.changeDesignMode = function( mode ){
        $scope.designMode = mode;
        if( mode == 'upload'){
            $timeout(function(){
                if(jQuery('#nbd-upload-note').hasClass('first_time_in_hour')){
                    jQuery('#nbd-upload-note').triggerHandler('click');
                }
            }, 500);
        }
        jQuery('#design-options').hide();
    };
    $scope.resetDimension = function() {
        $scope.designerWidth = calcCanvasWidth();
        $scope.designerHeight = calcCanvasWidth();
        $scope.originDesignerWidth = calcCanvasWidth();
        $scope.originDesignerHeight = calcCanvasWidth();        
        $scope.modeMobile = false;
        var oldScale = $scope.designScale;
        $scope.designScale = calcCanvasWidth() / NBDESIGNCONFIG['stage_dimension']['width'];
        var w = $(window).width();
        if (w < 768) $scope.modeMobile = true;
        $scope.offset = w / 2 - $scope.designerWidth / 2;
        $scope.zoomCanvas();
        var orientation =  $scope.currentVariant.orientationActive,
        index = orientation.substring(6);
        $scope.ajustmentOrientationScale[index] = $scope.designScale;
        $scope.resizeDesign($scope.designScale, oldScale);
    };
    $scope.ajustAfterAddItem = function(type) {
        var d = new Date();
        var itemId = d.getTime();         
        var index = $scope.canvas.getObjects().length - 1;
        $scope.canvas.setActiveObject($scope.canvas.item(index));
        //$scope.canvas.item($scope.editableItem).centerH();
        //$scope.canvas.item($scope.editableItem).centerV();
        $scope.canvas.viewportCenterObject($scope.canvas.item($scope.editableItem));
        $scope.canvas.item($scope.editableItem).setCoords();
        if( angular.isUndefined( type ) ) type = $scope.canvas.item($scope.editableItem).type;
        $scope.canvas.item($scope.editableItem).set({"itemId" : itemId});
        $scope.drawCanvas();
        $scope.setUndoRedo({
            element: $scope.canvas.item(index),
            parameters: $scope.getItemJson($scope.canvas.item(index)),
            interaction: "add"
        });      
        $scope.addLayers($scope.canvas.getActiveObject(), type, index);
    };
    $scope.setItemConfig = function(item, prop, value){
        if(!!item.configuration){
            var config = item.configuration;
            if(config.hasOwnProperty(prop)){
                config[prop] = value;
                item.configuration = config
            }else {
                var con = {};
                con[prop] = value;
                item.configuration = _.merge(config, con);
            }
        }else {
            var config = {};
            config[prop] = value;
            item.configuration = config
        }
    };
    $scope.getItemConfig = function(item, prop){
        if(!!item.configuration){
            var config = item.configuration;
            if(config.hasOwnProperty(prop)){
                return config[prop];
            }else{
                return false;
            }
        }else{
            return false;
        }
    };
    $scope.addText = function() {
        $scope.disableDrawMode();
        $scope.showPopover("text");
        //$scope.zoom = 1;
        var defaultText = $scope.settings.nbdesigner_default_text;
        if( $scope.multipleEdit ){
            $scope.canvas.forEachObject(function(obj, index) {   
                if( obj.type == 'text' || obj.type == 'curvedText' ){ 
                    defaultText = obj.getText();      
                }
            });               
        };        
        $scope.zoomCanvas();
        var text = new fabric.Text(defaultText, {
            left: 100,
            top: 10,
            fill: NBDESIGNCONFIG['nbdesigner_default_color'],
            fontFamily: "Roboto",
            radius: 50,
            fontSize: 30,
            ptFontSize: 30 / $scope.ratioConvertFont,
            textAlign: "center",
            noScaleCache: false,
            spacing: 0
        });     
        $scope.canvas.add(text);
        $scope.ajustAfterAddItem("text");
//        $scope.canvas.getActiveObject().setTextBackgroundColor('rgba(255,255,0,0.8)');
//        $scope.drawCanvas();
    };
    $scope.addTextBox = function(){
        var text = new fabric.Textbox('MyText', {
            width: 150,
            top: 5,
            left: 5,
            fontSize: 16,
            textAlign: 'center',
            fixedWidth: 150
        });        
        $scope.canvas.add(text);
        $scope.ajustAfterAddItem("text");
    };
    $scope.addGroup = function(){
        
    }; 
    $scope.changeLetterSpacing = function(value){
        if ($scope.editableItem == null) return;
        var object = $scope.canvas.item($scope.editableItem);
        $scope.setUndoRedo({
            element:  $scope.canvas.item($scope.editableItem), 
            parameters: JSON.stringify({"charSpacing" : object.get('charSpacing')}), 
            interaction: 'modify'
        });
        object.set({'charSpacing': value});
        $scope.drawCanvas();
    };
    $scope.autoResize = false;
    $scope.multipleEdit = false;
    $scope.ChangeText = function() {
        if ($scope.editableItem == null) return;
        var object = $scope.canvas.item($scope.editableItem);
//        console.log(object.text);
//        $scope.setUndoRedo({
//            element:  $scope.canvas.item($scope.editableItem), 
//            parameters: JSON.stringify({"text" : object.text}), 
//            interaction: 'modify'
//        }); 
        if( object.get("type") == "curvedText" ){
            var oldBoundingRect = object.getBoundingRect();
            var oldTop = object.getTop();
        };
        if( $scope.isUpperCase( object ) ) $scope.editable.text = $scope.editable.text.toUpperCase();
        if( $scope.multipleEdit ){
            $scope.canvas.forEachObject(function(obj) {
                if( obj.type == 'text' || obj.type == 'curvedText' ){ 
                    obj.setText($scope.editable.text);
                }
            });             
        }else{
            object.setText($scope.editable.text);
        }
        if( $scope.autoResize ){
            var fontSize = object.getFontSize(),
                bound = object.getBoundingRect();
            while ( bound.left + bound.width > $scope.canvas.width ) {
                object.setFontSize(fontSize - 1);
                $scope.drawCanvas();
                fontSize = object.getFontSize();
                bound = object.getBoundingRect();    
            }        
        }
        if( object.get("type") == "curvedText" ){
            var newBoundingRect = object.getBoundingRect();
            var newTop = oldTop - newBoundingRect.top + oldBoundingRect.top;            
            object.set({'top': newTop});
        };
        if( $scope.multipleEdit ){
            $scope.canvas.forEachObject(function(obj, index) {   
                if( obj.type == 'text' || obj.type == 'curvedText' ){ 
                    $scope.addLayers(obj, obj.type, index);      
                }
            });               
        }else{
            var type = $scope.canvas.item($scope.editableItem).get("type");
            $scope.addLayers(object, type, $scope.editableItem);            
        }
        /* always center */
        //$scope.setHorizontalCenter();
        $scope.drawCanvas();
    };
    $scope.changeFont = function(font) {
        if ($scope.editableItem == null) {
            jQuery("#dg-fonts").modal("hide");
            alert('Please choose text!');
            return;
        }
        var object = $scope.canvas.item($scope.editableItem);
        if( object.get("type") == "curvedText" ){
            var oldBoundingRect = object.getBoundingRect();
            var oldTop = object.getTop();
        };        
        /*var stop = $interval(function() {
            var name = (font.alias) ? (font.alias) : font.name;
            if (isFontAvailable(name)) {
                $scope.setUndoRedo({
                    element:  $scope.canvas.item($scope.editableItem), 
                    parameters: JSON.stringify({"fontFamily" : $scope.canvas.item($scope.editableItem).fontFamily}), 
                    interaction: 'modify'
                });                  
                $scope.currentFont = font;
                $scope.canvas.item($scope.editableItem).setFontFamily(name);
                $scope.canvas.setActiveObject($scope.canvas.item($scope.editableItem));                
                if( object.get("type") == "curvedText" ){
                    var newBoundingRect = object.getBoundingRect();
                    var newTop = oldTop - newBoundingRect.top + oldBoundingRect.top;            
                    object.set({'top': newTop});
                };                                
                $scope.canvas.item($scope.editableItem).setCoords();
                $scope.drawCanvas();
                $interval.cancel(stop);
            }
        }, 100);*/
        
        var name = (font.alias) ? (font.alias) : font.name;
        var FontFace = new FontFaceObserver(name),
            preview = $scope.subsets[font.subset];
        FontFace.load(preview).then(function () {
            $scope.setUndoRedo({
                element:  $scope.canvas.item($scope.editableItem), 
                parameters: JSON.stringify({"fontFamily" : $scope.canvas.item($scope.editableItem).fontFamily}), 
                interaction: 'modify'
            });                  
            $scope.currentFont = font;
            $scope.canvas.item($scope.editableItem).setFontFamily(name);
            $scope.canvas.setActiveObject($scope.canvas.item($scope.editableItem));                
            if( object.get("type") == "curvedText" ){
                var newBoundingRect = object.getBoundingRect();
                var newTop = oldTop - newBoundingRect.top + oldBoundingRect.top;            
                object.set({'top': newTop});
            };                                
            $scope.canvas.item($scope.editableItem).setCoords();
            $scope.drawCanvas();
        }, function () {
            //todosomething
        });         
        jQuery("#dg-fonts").modal("hide");
    };
    $scope.closePopover = function() {
        $scope.Popover = "none";
    };
    $scope.showPopover = function(type) {
        $scope.pop.type = type;
        $scope.pop.text = "none";
        $scope.pop.art = "none";
        $scope.pop.qrcode = "none";
        $scope.pop.clipArt = "none";
        $scope.pop.draw = "none";
        $scope.Popover = "block";
        switch (type) {
            case "text":
                $scope.pop.text = "block";
                break;
            case "art":
                $scope.pop.art = "block";
                break;
            case "qrcode":
                $scope.pop.qrcode =
                    "block";
                break;
            case "clipArt":
                $scope.pop.clipArt = "block";
                break;
            case "draw":
                $scope.pop.draw = "block";
                break;
            default:
                $scope.pop.text = "none";
                $scope.pop.art = "none";
                $scope.pop.qrcode = "none";
                $scope.pop.clipArt = "none";
                $scope.pop.draw = "none"
        }
    };
    $scope.drawCanvas = function() {
        $scope.canvas.calcOffset();       
        $scope.canvas.renderAll();
        var orientation = $scope.currentVariant.orientationActive;
        $scope.dataCustomerDesign[orientation] = $scope.canvas.toDataURL();
    };
    $scope.changeColor = function(e) {
        if ($scope.editableItem == null) return;
        $scope.setUndoRedo({
            element:  $scope.canvas.item($scope.editableItem), 
            parameters: JSON.stringify({"fill" : $scope.editable.fill}), 
            interaction: 'modify'
        });
        var color = tinycolor(e).toHexString();
        $scope.canvas.item($scope.editableItem).setFill(color);
        $scope.editable.fill = color;        
        $scope.drawCanvas()
    };
    
    /* Layer color */
    $scope.curentLayerAvailableColors = [];
    $scope.toggleAvailableColor = function(){
        if ($scope.editableItem == null) return;
        var object =  $scope.canvas.item($scope.editableItem);
        object.set({"available_color" : $scope.editable.available_color});
    };
    $scope.layerColorAvailable = '#fff';
    $scope.addColorForLayer = function(){
        if ($scope.editableItem == null) return;
        var object =  $scope.canvas.item($scope.editableItem);
        if( angular.isDefined( object.available_color_list ) ){
            object.available_color_list = object.available_color_list + ',' + $scope.layerColorAvailable;
        }else{
            object.available_color_list = '' + $scope.layerColorAvailable;
        };
        $scope.editable.available_color_list = object.available_color_list.split(','); 
    };
    $scope.removeColorLayer = function( $index ){
        if ($scope.editableItem == null) return;
        var object =  $scope.canvas.item($scope.editableItem);
        $scope.editable.available_color_list.splice($index, 1);
        object.available_color_list = $scope.editable.available_color_list.join(',');
    };
    $scope.setColorForLayer = function( color ){
        if ($scope.editableItem == null) return;
        var object =  $scope.canvas.item($scope.editableItem);
        var filter = {
            color: color,
            opacity: 1
        };
        $scope.setUndoRedo({
            element:  $scope.canvas.item($scope.editableItem), 
            parameters: JSON.stringify({ "filters" : object.filters }), 
            interaction: 'modify'
        });
        $scope.applyFilters(object, 12, filter, false);
        if( angular.isDefined( object.color_link_group ) && object.color_link_group != '' ){
            $scope.colorLinkGroup[object.color_link_group] = color;
        };        
        object.applyFilters(function() {
            $scope.canvas.renderAll()
        });        
    };
    $scope.applyFilters = function(object, index, _filter, apply_immediately){
        var f = fabric.Image.filters;
        var filter = false;
        switch (index) {
            case 0:
                filter = new f.Grayscale;
                break;             
            case 1:
                filter = new f.Invert;
                break;   
            case 2:
                filter = new f.RemoveWhite({
                    threshold: _filter.threshold,
                    distance: _filter.distance
                });
                break;             
            case 3:
                filter = new f.Sepia;
                break;             
            case 4:
                filter = new f.Sepia2;
                break;            
            case 5:
                filter = new f.Brightness({
                    brightness: _filter.brightness
                });
                break;            
            case 6:
                filter = new f.Noise({
                    noise: _filter.noise
                });
                break;              
            case 7:
                filter = new f.GradientTransparency({
                    threshold: _filter.threshold
                });
                break;             
            case 8:
                filter = new f.Pixelate({
                    blocksize: _filter.blocksize
                });
                break;             
            case 9:
                filter = new f.Convolute({
                    matrix: [1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9, 1 / 9]
                });
                break;             
            case 10:
                filter = new f.Convolute({
                    matrix: [0, -1, 0, -1, 5, -1, 0, -1, 0]
                });
                break;        
            case 11:
                filter = new f.Convolute({
                    matrix: [-1, -1, -1, -1, 9, -1, -1, -1, -1]
                });
                break;
            case 12:
                filter = new f.Tint({
                    color: _filter.color,
                    opacity: _filter.opacity
                });
                break;
        }  
        object.filters[index] = filter;
        if( apply_immediately ){
            object.applyFilters(function() {
                $scope.canvas.renderAll()
            });     
        }
    };
    $scope.colorLinkGroup = [];
    $scope.setColorLinkGroup = function(){
        if ($scope.editableItem == null) return;
        var object =  $scope.canvas.item($scope.editableItem);
        object.set({"color_link_group" : $scope.editable.color_link_group});
    };
    $scope.updateLayerColor = function(){
        $scope.canvas.forEachObject(function(obj) {
            if (obj.type === "image" && angular.isDefined( obj.color_link_group ) 
                    && obj.color_link_group != '' && angular.isDefined( $scope.colorLinkGroup[obj.color_link_group] ) ){
                var filter = {
                    color: $scope.colorLinkGroup[obj.color_link_group],
                    opacity: 1
                };
                $scope.applyFilters(obj, 12, filter, false);
            }
        })        
    };
    /* End. Layer color */
    
    $scope.backgroundColor = '#ffffff';
    $scope.changeBackground = function( color ){
        $scope.canvas.setBackgroundColor(color, function(){
            $scope.drawCanvas();
        });
    };
    $scope.changeStroke = function(c, stroke) {
        if ($scope.editableItem == null) return;
        $scope.setUndoRedo({
            element:  $scope.canvas.item($scope.editableItem), 
            parameters: JSON.stringify({"stroke" : $scope.editable.stroke}), 
            interaction: 'modify'
        });        
        if (c) {
            var color = "#" + c;
            if(c.charAt(0) == "r" || c.charAt(0) == "#") color = c;
            $scope.editable.stroke = color;
            $scope.canvas.item($scope.editableItem).setStroke($scope.editable.stroke)
        }
        if (stroke) $scope.canvas.item($scope.editableItem).setStrokeWidth(stroke);
        $scope.drawCanvas();
    };
    $scope.toggleItalic = function(){
        if ($scope.editableItem == null) return;
        $scope.setUndoRedo({
            element:  $scope.canvas.item($scope.editableItem), 
            parameters: JSON.stringify({"fontStyle" : $scope.canvas.item($scope.editableItem).fontStyle}), 
            interaction: 'modify'
        });         
        if ($scope.editable.italic) {
            $scope.editable.italic = false;
            $scope.canvas.item($scope.editableItem).setFontStyle("normal");
        } else {
            $scope.editable.italic = true;
            $scope.canvas.item($scope.editableItem).setFontStyle("italic");
        }
        $scope.drawCanvas();
    };
    $scope.isUpperCase = function( object ){
        var _isUpperCase = angular.isDefined(object.is_uppercase) ? object.is_uppercase : false;
        return _isUpperCase;
    };
    $scope.toggleTextCase = function(){
        if ($scope.editableItem == null) return;
        var object =  $scope.canvas.item($scope.editableItem);
        var _isUpperCase = $scope.isUpperCase( object );
        var _text = $scope.editable.text;
        if( _isUpperCase ){
            $scope.editable.text = $scope.editable.text.toLowerCase();
            _isUpperCase = false;
        }else{
            $scope.editable.text = $scope.editable.text.toUpperCase();
            _isUpperCase = true;
        }
        $scope.setUndoRedo({
            element:  $scope.canvas.item($scope.editableItem), 
            parameters: JSON.stringify({"is_uppercase" : _isUpperCase, 'text': _text}), 
            interaction: 'modify'
        });         
        object.setText($scope.editable.text);
        object.set({"is_uppercase" : _isUpperCase});
        $scope.drawCanvas();
    };
    $scope.toggleBold = function() {
        if ($scope.editableItem == null) return;
        $scope.setUndoRedo({
            element:  $scope.canvas.item($scope.editableItem), 
            parameters: JSON.stringify({"fontWeight" : $scope.canvas.item($scope.editableItem).fontWeight}), 
            interaction: 'modify'
        });            
        if ($scope.editable.bold) {
            $scope.editable.bold = false;
            $scope.canvas.item($scope.editableItem).setFontWeight("normal")
        } else {
            $scope.editable.bold = true;
            $scope.canvas.item($scope.editableItem).setFontWeight("bold")
        }
        $scope.drawCanvas()
    };
    $scope.toggleTextDecoration = function(decoration) {
        if ($scope.editableItem == null) return;
        $scope.setUndoRedo({
            element:  $scope.canvas.item($scope.editableItem), 
            parameters: JSON.stringify({"textDecoration" : $scope.canvas.item($scope.editableItem).textDecoration}), 
            interaction: 'modify'
        });           
        if ($scope.editable.textDecoration == decoration) {
            $scope.editable.textDecoration = "";
            $scope.canvas.item($scope.editableItem).setTextDecoration("")
        } else {
            $scope.editable.textDecoration =
                decoration;
            $scope.canvas.item($scope.editableItem).setTextDecoration(decoration)
        }
        $scope.drawCanvas()
    };
    $scope.changeShadow = function() {
        if ($scope.editableItem == null) return;
        var color = {"r" : 0, "g" : 0 , "b" : 0};
        if($scope.shadow.color.charAt(0) == "r" || $scope.shadow.color.charAt(0) == "#"){
            color = tinycolor($scope.shadow.color).toRgb();
        }else {
            color = hexToRGB("#" + $scope.shadow.color);
        }
        var shadow = "rgba(" + color.r + ", " + color.g + ", " + color.b + ", " + $scope.shadow.alpha + ") " + $scope.shadow.x + "px " + $scope.shadow.y + "px " + $scope.shadow.blur + "px";
        $scope.canvas.item($scope.editableItem).setShadow(shadow);
        $scope.drawCanvas()
    };
    $scope.removeShadow = function() {
        if ($scope.editableItem == null) return;
        $scope.canvas.item($scope.editableItem).setShadow("");
        $scope.drawCanvas()
    };
    $scope.flipHorizontal = function() {
        var obj = $scope.canvas.getActiveObject();
        if (obj == null) return;
        if( $scope.isLockMovement() ) return;
        $scope.setUndoRedo({
            element:  $scope.canvas.item($scope.editableItem), 
            parameters: JSON.stringify({"flipY" : $scope.canvas.item($scope.editableItem).flipY}), 
            interaction: 'modify'
        });          
        $scope.canvas.item($scope.editableItem).toggle("flipY");
        $scope.canvas.item($scope.editableItem).setCoords();
        $scope.drawCanvas()
    };
    $scope.flipVertical = function() {
        var obj = $scope.canvas.getActiveObject();
        if (obj == null) return;
        if( $scope.isLockMovement() ) return;
        $scope.setUndoRedo({
            element:  $scope.canvas.item($scope.editableItem), 
            parameters: JSON.stringify({"flipX" : $scope.canvas.item($scope.editableItem).flipX}), 
            interaction: 'modify'
        });           
        $scope.canvas.item($scope.editableItem).toggle("flipX");
        $scope.canvas.item($scope.editableItem).setCoords();
        $scope.drawCanvas()
    };
    $scope.setHorizontalCenter = function() {
        var obj = $scope.canvas.getActiveObject();
        if (obj == null) return;
        if( $scope.isLockMovement() ) return;
        $scope.canvas.viewportCenterObjectH($scope.canvas.item($scope.editableItem));
        $scope.canvas.item($scope.editableItem).setCoords();
        $scope.drawCanvas()
    };
    $scope.setVerticalCenter = function() {
        var obj = $scope.canvas.getActiveObject();
        if (obj == null) return;
        if( $scope.isLockMovement() ) return;
        $scope.canvas.viewportCenterObjectV($scope.canvas.item($scope.editableItem));
        $scope.canvas.item($scope.editableItem).setCoords();
        $scope.drawCanvas()
    };
    $scope.isLockMovement = function(){
        var obj = $scope.canvas.getActiveObject();
        if(obj.get("lockMovementX") || obj.get("lockMovementY") ) return true;
        return false;
    };
    $scope.ShiftLeft = function() {
        var obj = $scope.canvas.getActiveObject();
        if (obj == null) return;
        if(obj.get("lockMovementX")) return;
        $scope.setUndoRedo({
            element:  $scope.canvas.item($scope.editableItem), 
            parameters: JSON.stringify({"left" : $scope.canvas.item($scope.editableItem).left}), 
            interaction: 'modify'
        });          
        var width = $scope.canvas.width / 100;
        var left = $scope.canvas.item($scope.editableItem).left;
        $scope.canvas.item($scope.editableItem).set("left", left - width);
        $scope.canvas.item($scope.editableItem).setCoords();
        $scope.drawCanvas()
    };
    $scope.ShiftRight = function() {
        var obj = $scope.canvas.getActiveObject();
        if (obj == null) return;
        if(obj.get("lockMovementX")) return;
        $scope.setUndoRedo({
            element:  $scope.canvas.item($scope.editableItem), 
            parameters: JSON.stringify({"left" : $scope.canvas.item($scope.editableItem).left}), 
            interaction: 'modify'
        });          
        var width = $scope.canvas.width / 100;
        var left = $scope.canvas.item($scope.editableItem).left;
        $scope.canvas.item($scope.editableItem).set("left", left + width);
        $scope.canvas.item($scope.editableItem).setCoords();
        $scope.drawCanvas()
    };
    $scope.ShiftUp = function() {
        var obj = $scope.canvas.getActiveObject();
        if (obj == null) return;
        if(obj.get("lockMovementY")) return;
        $scope.setUndoRedo({
            element:  $scope.canvas.item($scope.editableItem), 
            parameters: JSON.stringify({"top" : $scope.canvas.item($scope.editableItem).top}), 
            interaction: 'modify'
        });          
        var height = $scope.canvas.height / 100;
        var top = $scope.canvas.item($scope.editableItem).top;
        $scope.canvas.item($scope.editableItem).set("top", top - height);
        $scope.canvas.item($scope.editableItem).setCoords();
        $scope.drawCanvas()
    };
    $scope.ShiftDown = function() {
        var obj = $scope.canvas.getActiveObject();
        if (obj == null) return;
        if(obj.get("lockMovementY")) return;
        $scope.setUndoRedo({
            element:  $scope.canvas.item($scope.editableItem), 
            parameters: JSON.stringify({"top" : $scope.canvas.item($scope.editableItem).top}), 
            interaction: 'modify'
        });         
        var height = $scope.canvas.height / 100;
        var top = $scope.canvas.item($scope.editableItem).top;
        $scope.canvas.item($scope.editableItem).set("top", top + height);
        $scope.canvas.item($scope.editableItem).setCoords();
        $scope.drawCanvas()
    };
    $scope.alignGroupLeft = function(){
        if($scope.canvas.getActiveGroup === null) return;
        var arr = [];
        $scope.canvas.getActiveGroup().forEachObject(function(obj) {
            arr.push(obj.get("left"));
        });        
        var val = _.min(arr);
        $scope.canvas.getActiveGroup().forEachObject(function(obj) {
            obj.set({"left" : val});
            obj.setCoords();
        });  
        $scope.drawCanvas()
    };
    $scope.alignGroupTop = function(){
        if($scope.canvas.getActiveGroup === null) return;
        var arr = [];
        $scope.canvas.getActiveGroup().forEachObject(function(obj) {
            arr.push(obj.get("top"));
        });        
        var val = _.min(arr);
        $scope.canvas.getActiveGroup().forEachObject(function(obj) {
            obj.set({"top" : val});
            obj.setCoords();
        });  
        $scope.drawCanvas()
    };  
    $scope.alignGroupRight = function(){
        if($scope.canvas.getActiveGroup === null) return;
        var arr = [];
        $scope.canvas.getActiveGroup().forEachObject(function(obj) {
            var left = obj.get("left");
            var width = obj.get("scaleX") * obj.get("width");
            arr.push(left + width);
        });        
        var val = _.max(arr);
        $scope.canvas.getActiveGroup().forEachObject(function(obj) {
            var left = val - obj.get("scaleX") * obj.get("width");
            obj.set({"left" : left});
            obj.setCoords();
        });  
        $scope.drawCanvas()
    };   
    $scope.alignGroupBottom = function(){
        if($scope.canvas.getActiveGroup === null) return;
        var arr = [];
        $scope.canvas.getActiveGroup().forEachObject(function(obj) {
            var left = obj.get("top");
            var width = obj.get("scaleY") * obj.get("height");
            arr.push(left + width);
        });        
        var val = _.max(arr);
        $scope.canvas.getActiveGroup().forEachObject(function(obj) {
            var top = val - obj.get("scaleY") * obj.get("height");
            obj.set({"top" : top});
            obj.setCoords();
        });  
        $scope.drawCanvas()
    };  
    $scope.alignGroupVer = function(){
        if($scope.canvas.getActiveGroup === null) return;
        //var hafl_width = $scope.currentVariant.designArea['area_design_width'] * $scope.zoom * $scope.designScale / 2;      
        var arr = [];
        $scope.canvas.getActiveGroup().forEachObject(function(obj, index) {
            var left = obj.get("left");
            var width = obj.get("scaleX") * obj.get("width") / 2;
            arr.push(left + width);
        });  
        var val = _.min(arr);
        $scope.canvas.getActiveGroup().forEachObject(function(obj) {
            var left = val - obj.get("scaleX") * obj.get("width") / 2;
            obj.set({"left" : left});    
            obj.setCoords();
        });
        $scope.canvas.getActiveGroup().setObjectsCoords();
        $scope.drawCanvas()
    };
    $scope.alignGroupHor = function(){
        if($scope.canvas.getActiveGroup === null) return;
        var arr = [];
        $scope.canvas.getActiveGroup().forEachObject(function(obj) {
            var left = obj.get("top");
            var width = obj.get("scaleY") * obj.get("height") / 2;
            arr.push(left + width);
        });        
        var val = _.min(arr);
        $scope.canvas.getActiveGroup().forEachObject(function(obj) {
            var top = val - obj.get("scaleY") * obj.get("height") / 2;
            obj.set({"top" : top});
            obj.setCoords();
        });  
        $scope.drawCanvas()     
    };    
    $scope.deactiveGroup = function(){
        $scope.canvas.deactivateAll().renderAll();
        $scope.showAlignToolbar = false;
    };
    $scope.unlockProportion = function() {
        if ($scope.editableItem == null) return;
        var item = $scope.canvas.item($scope.editableItem);
        var lockProportion = angular.isDefined( item.lockUniScaling ) ? !item.lockUniScaling : true;
        item.set({lockUniScaling: lockProportion});
        $scope.canvas.setActiveObject(item);
        $scope.drawCanvas()
    };
    $scope.rotateText = function(angle) {
        if ($scope.editableItem == null) return;
        if (!!angle) {
            if (angle > 360) angle = angle - 360;
            if (angle < 0) angle = angle + 360;
            $scope.canvas.item($scope.editableItem).setAngle(angle);
            $scope.drawCanvas()
        } else {
            $scope.canvas.item($scope.editableItem).setAngle(0);
            $scope.drawCanvas()
        }
    };
    $scope.deleteAllItem = function() {
        deleteAllObject();     
        $scope.drawCanvas()
    };
    $scope.align = function(layout) {
        if ($scope.editableItem == null) return;
        $scope.setUndoRedo({
            element:  $scope.canvas.item($scope.editableItem), 
            parameters: JSON.stringify({"textAlign" : $scope.canvas.item($scope.editableItem).textAlign}), 
            interaction: 'modify'
        });         
        $scope.editable.textAlign = layout;
        $scope.canvas.item($scope.editableItem).setTextAlign(layout);
        $scope.drawCanvas()
    };
    $scope.setOpacity = function(value) {
        if ($scope.editableItem == null) return;
        var value = 1 - value;
        $scope.setUndoRedo({
            element:  $scope.canvas.item($scope.editableItem), 
            parameters: JSON.stringify({"opacity" : $scope.canvas.item($scope.editableItem).opacity}), 
            interaction: 'modify'
        });         
        $scope.canvas.item($scope.editableItem).set({
            opacity: value
        });
        $scope.drawCanvas()
    };
    $scope.setBackground = function(e) {
        if ($scope.editableItem == null) return;
        $scope.setUndoRedo({
            element:  $scope.canvas.item($scope.editableItem), 
            parameters: JSON.stringify({"textBackgroundColor" : $scope.canvas.item($scope.editableItem).getTextBackgroundColor()}), 
            interaction: 'modify'
        });	        
        if (!e){
            var color = $scope.background;
            color = tinycolor(color).toHexString();
            $scope.canvas.item($scope.editableItem).setTextBackgroundColor(color);
        }else {
            $scope.canvas.item($scope.editableItem).setTextBackgroundColor("");
        }
        $scope.drawCanvas()
    };
    $scope.setLineHeight = function() {
        if ($scope.editableItem == null) return;
        $scope.canvas.item($scope.editableItem).setLineHeight($scope.editable.lineHeight);
        $scope.drawCanvas()
    };
    $scope.changeTextDirection = function(){
        $scope.rtlLang = !$scope.rtlLang;
    };
    $scope.changeCurve = function(val) {
        if ($scope.editableItem == null) return;
        var index = $scope.editableItem;
        var text = $scope.canvas.item(index).getText();
        if ($scope.canvas.item(index).get("type") == "curvedText") {
            $scope.canvas.item(index).set({
                radius: (100 - val) * 2.5
            });
            $scope.drawCanvas();
            return
        }
        var curve = $scope.canvas.item(index);
        var option = {};
        if($scope.rtlLang){
            option.rtl = true;
        }        
        option.left = curve.left;
        option.top = curve.top;
        option.textAlign = curve.textAlign;
        option.fill = curve.fill;
        option.angle = curve.angle;
        option.textBackgroundColor = curve.textBackgroundColor;
        option.stroke = curve.stroke;
        option.fontSize = curve.fontSize;
        option.fontFamily = curve.fontFamily;
        option.lineHeight = curve.lineHeight;
        option.height = curve.height;
        option.width = curve.width;
        
        option.originX = 'center';
        option.originY = 'bottom';
        
        option.radius = (100 - val) * 2.5;
        var curvedtext = new fabric.CurvedText(text, option);
        $scope.canvas.remove($scope.canvas.getActiveObject());
        $scope.drawCanvas();
        $scope.canvas.add(curvedtext);
        var index = $scope.canvas.getObjects().length - 1;
        if(NBDESIGNCONFIG['lang_rtl'] == 'rtl'){
            $scope.setItemConfig($scope.canvas.item(index), 'rtl', true); 
        }        
        $scope.canvas.setActiveObject($scope.canvas.item(index));
        $scope.canvas.item($scope.editableItem).centerH();
        $scope.canvas.item($scope.editableItem).centerV();
        $scope.canvas.item($scope.editableItem).setCoords();
        $scope.drawCanvas()
    };
    $scope.setSpacing = function() {
            if ($scope.editableItem == null) return;
            $scope.canvas.item($scope.editableItem).set("spacing", $scope.editable.spacing);
            $scope.drawCanvas()
        };
    $scope.changeEffect = function(val) {
        if ($scope.editableItem == null) return;
        $scope.canvas.item($scope.editableItem).set("effect", val);
        $scope.drawCanvas()
    };
    $scope.reverseCurve = function() {
        if ($scope.editableItem == null) return;
        var reverse = angular.element(document.querySelector("input#curve_reverse")).is(":checked");
        $scope.canvas.item($scope.editableItem).set("reverse",reverse);
        $scope.drawCanvas()
    };
    $scope.formatListString = function( str ){
        return str.replace(/,/g, ", ");
    };
    $scope.changePattern = function(path) {
        var url = $scope.ajustUrl(path);
        changePattern(url);
        jQuery("#dg-pattern").modal("hide");
        $scope.drawCanvas()
    };
    $scope.ajustUrl = function(path) {
        return NBDESIGNCONFIG['assets_url'] + path
    };
    $scope.loadPattern = function() {
        if ($scope.patterns.length > 0) return;
        PatternService.fn(function(data) {
            if (data.flag == "1") $scope.patterns = data.data.patterns;
            else console.log("Error! Try again!")
        })
    };
    $scope.changePatternRepeat = function(val) {
        $scope.canvas.item($scope.editableItem).fill.repeat =
            val;
        $scope.drawCanvas()
    };
    $scope.setFontSize = function() {
        if ($scope.editableItem == null) return;
        var object = $scope.canvas.item($scope.editableItem);
        if( object.get("type") == "curvedText" ){
            var oldBoundingRect = object.getBoundingRect();
            var oldTop = object.getTop();
        };
        var minSize = arrayMin($scope.listFontSizeInPt);
        if( $scope.forceMinSize && minSize > $scope.editable.ptFontSize ) $scope.editable.ptFontSize = minSize;
        $scope.editable.fontSize = $scope.editable.ptFontSize * $scope.ratioConvertFont;
        $scope.canvas.item($scope.editableItem).setFontSize($scope.editable.fontSize);
        if( object.get("type") == "curvedText" ){
            var newBoundingRect = object.getBoundingRect();
            var newTop = oldTop - newBoundingRect.top + oldBoundingRect.top;            
            object.set({'top': newTop});
        };
        $scope.drawCanvas()
    };
    $scope.setGradient = function() {
        if ($scope.editableItem == null) return;
        var option = createGradient();
        var direction = "h";
        direction = angular.element(document.querySelector('input[name="gradient_direction"]:checked')).val();
        var width = $scope.canvas.item($scope.editableItem).getWidth();
        var height = $scope.canvas.item($scope.editableItem).getHeight();
        if (direction == "h") $scope.canvas.item($scope.editableItem).setGradient("fill", {
            type: "linear",
            x1: -width,
            y1: 0,
            x2: 0,
            y2: 0,
            colorStops: option
        });
        else $scope.canvas.item($scope.editableItem).setGradient("fill", {
            type: "linear",
            x1: 0,
            y1: 0,
            x2: 0,
            y2: height / 2,
            colorStops: option
        });
        $scope.drawCanvas();
    };
    $scope.zoomOut = function() {
        $scope.zoom = $scope.zoom - .1;
        if ($scope.zoom <= 1) $scope.zoom = $scope.currentScale < 1 ? $scope.currentScale : 1;
        $scope.canvas.setZoom($scope.zoom);
        $scope.zoomCanvas();
        $scope.updatePositionReplaceButton();
    };
    $scope.zoomIn = function() {
        $scope.zoom = $scope.zoom + .1;
        if ($scope.zoom >= 2) $scope.zoom = 2;
        $scope.zoomCanvas();
        $scope.updatePositionReplaceButton();
        jQuery('#nbd-viewport').perfectScrollbar('update');
    };
    $scope.scaleItem = function(command) {
        var obj = $scope.canvas.getActiveObject();
        if (!obj) return;
        if( $scope.isLockMovement() ) return;
        var scaleX = obj.scaleX,
            scaleY = obj.scaleY,
            left = obj.left,
            top = obj.top,
            width = obj.width * scaleX,
            height = obj.height * scaleY,
            factor = 1;
        if (command == "+") factor = 1.1;
        else factor = .9;
        var tempScaleX = scaleX * factor,
            tempScaleY = scaleY * factor,
            tempWidth = width * factor,
            tempHeight = height * factor,
            tempLeft = left + width / 2 - tempWidth / 2,
            tempTop = top + height / 2 - tempHeight / 2;
        obj.scaleX = tempScaleX;
        obj.scaleY = tempScaleY;
        obj.left = tempLeft;
        obj.top = tempTop;
        obj.setCoords();
        $scope.drawCanvas()
    };
    $scope.zoomCanvas = function() {
        $scope.zoomViewport();
        var width = $scope.zoom * $scope.currentVariant.designArea["area_design_width"] * $scope.designScale;
        var height = $scope.zoom * $scope.currentVariant.designArea["area_design_height"] * $scope.designScale;
        $scope.canvas.setDimensions({
            "width": width,
            "height": height
        });  
        $scope.canvas.calcOffset();
        $scope.canvas.setZoom($scope.zoom);  
        /*
        if($scope.currentVariant.info[$scope.currentSide.id]["source"]['area_design_type'] == "2"){
            var clipPath = new fabric.Path("M20.668 13.312c0.059-0.427 0.089-0.846 0.089-1.251 0-2.437-0.846-4.544-2.513-6.263-1.685-1.735-3.755-2.615-6.152-2.615-0.279 0-0.546 0.013-0.801 0.038-0.756-0.35-1.568-0.526-2.426-0.526-1.609 0-3.053 0.61-4.174 1.765-1.105 1.135-1.691 2.585-1.691 4.192 0 0.832 0.156 1.619 0.466 2.348-0.047 0.357-0.070 0.713-0.070 1.062 0 2.438 0.853 4.547 2.532 6.267 1.693 1.732 3.768 2.61 6.164 2.61 0.254 0 0.547-0.020 0.896-0.060 0.69 0.283 1.409 0.426 2.146 0.426 1.588 0 3.025-0.614 4.157-1.777 1.117-1.143 1.709-2.6 1.709-4.211 0-0.677-0.111-1.349-0.332-2.005zM15.5 15.348c-0.284 0.427-0.729 0.781-1.339 1.065-0.609 0.243-1.31 0.365-2.1 0.365-0.954 0-1.756-0.173-2.404-0.519-0.467-0.262-0.833-0.598-1.096-1.003-0.284-0.447-0.428-0.862-0.428-1.248 0-0.243 0.092-0.457 0.274-0.639 0.184-0.184 0.416-0.274 0.7-0.274 0.203 0 0.406 0.072 0.609 0.213 0.162 0.162 0.283 0.366 0.364 0.609 0.021 0.020 0.153 0.253 0.396 0.7 0.102 0.141 0.284 0.283 0.547 0.425 0.245 0.122 0.568 0.183 0.975 0.183 0.548 0 1.005-0.121 1.37-0.364 0.324-0.224 0.486-0.507 0.486-0.853 0-0.284-0.092-0.498-0.274-0.639-0.183-0.184-0.415-0.324-0.699-0.427-0.081-0.021-0.188-0.047-0.319-0.075-0.133-0.031-0.285-0.071-0.457-0.123-0.172-0.051-0.32-0.086-0.441-0.106-0.689-0.141-1.277-0.324-1.766-0.548-0.426-0.162-0.811-0.445-1.156-0.851-0.283-0.386-0.426-0.843-0.426-1.37 0-0.528 0.152-0.994 0.457-1.4 0.304-0.406 0.74-0.711 1.308-0.913 0.569-0.224 1.219-0.334 1.949-0.334 0.548 0 1.066 0.070 1.552 0.213 0.468 0.162 0.843 0.355 1.127 0.579 0.263 0.243 0.477 0.486 0.639 0.729 0.142 0.324 0.214 0.589 0.214 0.791 0 0.265-0.092 0.488-0.275 0.669-0.201 0.204-0.436 0.306-0.699 0.306-0.223 0-0.416-0.061-0.578-0.184-0.102-0.101-0.233-0.283-0.396-0.547-0.121-0.284-0.314-0.537-0.577-0.762-0.243-0.182-0.619-0.273-1.127-0.273s-0.892 0.102-1.156 0.305c-0.284 0.184-0.426 0.396-0.426 0.639 0 0.162 0.050 0.296 0.152 0.396 0.102 0.143 0.232 0.255 0.396 0.336 0.102 0.060 0.274 0.132 0.518 0.212 0.061 0.021 0.197 0.057 0.41 0.106 0.213 0.053 0.391 0.087 0.533 0.107 0.283 0.061 0.771 0.192 1.461 0.396 0.406 0.141 0.791 0.323 1.156 0.548 0.346 0.242 0.599 0.517 0.762 0.82 0.162 0.365 0.242 0.771 0.242 1.217-0.002 0.548-0.154 1.056-0.458 1.523z");  
            clipPath.set({
                originX: "center",
                originY: "center",
                fill: "#9bf0e9",
                left: $scope.canvas.width/2,
                top: $scope.canvas.height/2,    
                scaleX: $scope.canvas.width/clipPath.width,
                scaleY: $scope.canvas.height/clipPath.height,
                opacity: 1
            });             
            $scope.canvas.clipTo = function(ctx) {
                clipPath.render(ctx)
            };     
        }else {
            $scope.canvas.clipTo = null;
        };       
        */
        $scope.drawCanvas()
    };
    $scope.loadProduct = function(template_id) {
        show_indicator();
        $scope.adminListTemplate = [];
        ProductService.getProduct(template_id).then(function(data) {
            hide_indicator();
            $scope.resetCustomDimension();          
            $scope.initStage(data);
        })
    };
    $scope.keepLocalDesign = false;
    $scope.customSize = false;
    $scope.flagChangeCustomSize = true;
    $scope.initStage = function(data){
        /* open templates when loaded */
        /* 
        $scope.loadAdminListDesign();
        $timeout(function(){
            jQuery('#dg-expand-feature').modal('show');
        }, 1000);
        */
        $scope.onLoadProduct = false;
        $scope.only_svg = 0;
        (NBDESIGNCONFIG['ui_mode'] == "1") && nbd_window.NBDESIGNERPRODUCT.nbdesigner_ready(); 
        $scope.beforeInitStage(data);
        if( angular.isDefined(data.product) ) $scope.varaints.areaDesign = data.product;
        if( angular.isDefined(data.upload) ) $scope.uploadSetting = data.upload;
        if( NBDESIGNCONFIG['enable_upload_without_design'] == "2" ) {
            hide_indicator();
            return;
        }
        if( attachProductInfo ){
            if( angular.isDefined(data.variation_form) ){
                jQuery('#variation-form-wrap').html(data.variation_form);
                jQuery( '.variations_form' ).each( function() {
                    jQuery( this ).wc_variation_form();
                });     
                jQuery('#dg-product-info').modal('show');
                jQuery('#dg-product-info a[href="#product-variation"]').tab("show");
            }
            if( angular.isDefined(data.variation_id) ){
                NBDESIGNCONFIG['variation_id'] = data.variation_id;
            }
            if( angular.isDefined(data.product_info) ){
                jQuery('#product-info-wrap-inner').html(data.product_info.html);
            }
            attachProductInfo = 0;
        }
        if( angular.isDefined(data.option) ) {
            $scope.productOptions = data.option;
            if( NBDESIGNCONFIG['show_variation'] == "3" ){
                jQuery('#dg-load-product').modal("show");
            }else if( $scope.productOptions.allow_specify_dimension == 1 && $scope.settings.task == 'new'){
                jQuery('#custom-dimension-tg').trigger('click');
                $timeout(function(){
                    jQuery('#custom-dimension-tg').removeClass('active');
                }, 10000);
            }
            if( angular.isDefined($scope.productOptions.multiple_edit) ){
                $scope.multipleEdit = $scope.productOptions.multiple_edit == 1 ? true : false;
            };
            $scope.rateConvertCm2Px = Math.round($scope.rateConvertCm2Px96dpi * (parseInt($scope.productOptions.dpi) / 96) * 10) / 10;
        } 
        $scope.ajustmentScale = $scope.designScale;
        if (toType(data.design) == "object" && !$scope.keepLocalDesign){
            /* Edit design */
            $scope.canvases = data.design;   
            /* Fix src image with multistore */
            var multisite = false;
            if( multisite ){
                _.each($scope.canvases, function( canvas, side ){
                    _.each(canvas['objects'], function( item, index ) {
                        if( item.type == 'image' ){ 
                            var _src = item.src;
                            var src = _src.split('nbdesigner');
                            $scope.canvases[side]['objects'][index]['src'] = NBDESIGNCONFIG['nbd_content_url'] + src[1];
                        }
                    }); 
                });
            }
            if(toType(data.ref) === "array"){
                $scope.refProduct = data.ref;
            };            
            if(toType(data.config_ref) === "object"){
                $scope.ajustmentScale = data.config_ref['scale'];
            }else if(toType(data.config) === "object"){
                $scope.ajustmentScale = data.config['scale'];
                if(angular.isDefined(data.config['custom_dimension'])){
                    $scope.customWidth = parseFloat( data.config['custom_dimension']['width'] );
                    $scope.customHeight = parseFloat( data.config['custom_dimension']['height'] );
                    $scope.customSide = parseInt( data.config['custom_dimension']['side'] );
                    $scope.customPrice = parseFloat(  data.config['custom_dimension']['price'] );
                    $scope.flagChangeCustomSize = true;
                    $scope.customSize = true;
                }
            }       
            if(toType(data.fonts) === "array"){
                var font_url = NBDESIGNCONFIG['font_url'];
                $scope.loadAdminDesignFont(data.fonts, font_url);
                return;
            }
            $scope.changeOrientation();   
            $scope.loaded = 100;
            hide_indicator()                
        } else {
            if( $scope.currentProductId != '' ){
                var sid = "p_" + scope.currentProductId,
                cid = "c_" + scope.currentProductId;                 
            }else{
                var sid = "p_" + NBDESIGNCONFIG['product_id'],
                cid = "c_" + NBDESIGNCONFIG['product_id'];                
            }
            if ((toType(localStorageService.get(sid)) === "object") && (NBDESIGNCONFIG['task'] == "new") && !$scope.ignoreLocalDesign && !NBDESIGNCONFIG['is_designer'] && (NBDESIGNCONFIG['nbdesigner_save_latest_design'] == 'yes')){
                $scope.canvases = localStorageService.get(sid);
                if(toType(localStorageService.get(cid)) === "object"){
                    var config = localStorageService.get(cid);
                    $scope.ajustmentScale = config['scale'];
                    $scope.loadAdminDesignFont(config['font_used'], config['furl']);
                }
            }else if(toType(data.admindesign) === "object"){
                $scope.canvases = data.admindesign;    
                if(toType(data.config) === "object"){
                    $scope.ajustmentScale = data.config['scale'];
                }                      
                if(toType(data.fonts) === "array"){
                    var font_url = NBDESIGNCONFIG['font_url'];
                    $scope.loadAdminDesignFont(data.fonts, font_url);
                }  
            }else{
                $scope.changeOrientation();            
                $scope.loaded = 100;
                hide_indicator()                      
            }
        }
    };
    $scope.loadAdminListDesign = function(){
        if(! _.size($scope.adminListTemplate)){
            show_indicator();
            AdminTemplateService.getDesign().then(function(data) {     
                if(data['mes'] == 'success'){
                    _.each(data.data, function(value, index){
                        $scope.adminListTemplate.push(value);
                    })
                }else{
                    alert('Oops! Try again');
                }
                hide_indicator();
            })
        }
        $('#nbdesigner-list-template').addClass('open');
        $('#design-editor-container').removeClass('open');
    };
    $scope.listDesignsInCart = [];
    $scope.loadDesignInCart = function( force ){
        if(! _.size($scope.listDesignsInCart) || force != undefined){
            show_indicator();
            $scope.listDesignsInCart = [];
            CartDesignsService.getDesign().then(function(data) {  
                if(data['flag'] == 1){
                    _.each(data.designs, function(value, index){
                        $scope.listDesignsInCart.push(value);
                    });
                }else{
                    alert('Oops! Try again');
                }
                hide_indicator();
            })            
        }
    };
    $scope.loadCartDesign = function( $ref_id ){
        show_indicator();
        CartDesignsService.getDesign( $ref_id ).then(function(data) {  
            if( data['flag'] == 1){
                $scope.canvas.clear();
                if( $scope.flagChangeDimension ){
                    $scope.flagChangeOrientation = [];
                }
                $scope.initStage(data);
                jQuery('#dg-expand-feature').modal("hide");
            }
        })  
    };
    $scope.loadMoreDesignsInCart = function(){
        $scope.listDesignsInCartPageSize += 8;
        $("#nbd-list-cart-design").stop().animate({
            scrollTop: $("#nbd-list-cart-design").prop("scrollHeight")
        }, 400)         
    };
    $scope.listUserDesigns = [];
    $scope.listUserDesignsPageSize = 8;
    $scope.loadUserDesign = function(id){
        if(!$scope.settings['is_logged']) return;
        if(! _.size($scope.listUserDesigns) ){
            show_indicator();
            UserDesignsService.getDesign(id).then(function(data) { 
                if(data['flag'] == 1){
                    $scope.settings['is_logged'] = 1;
                    _.each(data.designs, function(value, index){
                        $scope.listUserDesigns.push(value);
                    });
                }else if( data['flag'] == 2 ){
                    $scope.settings['is_logged'] = 0;
                }
                hide_indicator();
            })            
        }
    };
    $scope.loadMoreUserDesigns = function(){
        $scope.listUserDesignsPageSize += 8;
        $("#nbd-list-my-design").stop().animate({
            scrollTop: $("#nbd-list-my-design").prop("scrollHeight")
        }, 400)         
    };
    $scope.loadMyDesign = function( $ref_id ){
        show_indicator();
        UserDesignsService.getDesign( $ref_id ).then(function(data) {  
            if( data['flag'] == 1){
                $scope.canvas.clear();
                if( $scope.flagChangeDimension ){
                    $scope.flagChangeOrientation = [];
                }
                $scope.initStage(data);
                jQuery('#dg-expand-feature').modal("hide");
            }
        })  
    };    
    $scope.listProducts = [];
    $scope.listProductsPageSize = 8;
    $scope.listProductsLoaded = false;
    $scope.loadListProduct = function(){
        if( $scope.listProductsLoaded ) return;
        show_indicator();
        ProductService.getListProducts().then(function(data) {
            $scope.listProducts = data;
            $scope.listProductsLoaded = true;
            hide_indicator();
        })
    };
    $scope.loadMoreProduct = function(){
        $scope.listProductsPageSize += 8;
        $("#nbd-list-product").stop().animate({
            scrollTop: $("#nbd-list-product").prop("scrollHeight")
        }, 400)        
    };
    $scope.currentPreviewProduct = {};
    $scope.currentProductId = '';
    $scope._switchProduct = function(){
        var product = {
            'type'  :  $scope.currentPreviewProduct.type,
            'product_id'  :  $scope.currentPreviewProduct.product_id
        }
        $scope.switchProduct( product );
        jQuery('#dg-product-info-preview').modal('hide');
    }
    $scope.switchProduct = function( product ){
        $scope.saveDesign();
        $scope.currentProductId = NBDESIGNCONFIG['product_id'];
//        if( product.type == 'simple' ){
            attachProductInfo = 1;
            $scope.settings.product_type = (product.type == 'variable') ? 'variable' : 'simple';
            NBDESIGNCONFIG['product_type'] = $scope.settings.product_type;
            $scope.keepLocalDesign = true;
            NBDESIGNCONFIG['product_id'] = product.product_id;
            NBDESIGNCONFIG['variation_id'] = 0;
            _.each($scope.currentVariant.info, function(val, key){
                $scope.refProduct[key] = val['source'];
            });
            $scope.flagChangeOrientation = [];
            $scope.loadProduct('');
            jQuery('#dg-load-product').modal("hide");
            $scope.adminListTemplate = [];
//        }else {
//            show_indicator();
//            window.location = product.url;
//        }
    };
    $scope.resetCustomDimension = function(){
        $scope.originProduct = [];
        $scope.flagChangeDimension = false;
        $scope.customDefaultReady = true;        
    };
    $scope.changeDimension = function( initReDesign ){
        if(angular.isUndefined($scope.customWidth) || $scope.customWidth < 0 || angular.isUndefined($scope.customHeight) || $scope.customHeight < 0){
            alert('Incorrect dimension');
            return;
        }
        $scope.customDefaultReady = false;
        $scope.customWidth = parseFloat( $scope.customWidth );
        $scope.customHeight = parseFloat( $scope.customHeight );
        if( !initReDesign ) $scope.saveDesign();
        if( !$scope.flagChangeDimension ){
            $scope.originProduct = angular.copy( $scope.varaints.areaDesign );
            $scope.flagChangeDimension = true;
        }    
        _.each($scope.varaints.areaDesign, function(val, key){
            $scope.refProduct[key] = angular.copy( val );
            $scope.varaints.areaDesign[key]['real_width'] = $scope.customWidth;
            $scope.varaints.areaDesign[key]['real_height'] = $scope.customHeight;
            if( $scope.customWidth > $scope.customHeight ){
                var ratio = 500 / $scope.customWidth;
                $scope.varaints.areaDesign[key]["img_src_width"] = $scope.varaints.areaDesign[key]["area_design_width"] = 500;
                $scope.varaints.areaDesign[key]["img_src_left"] = $scope.varaints.areaDesign[key]["area_design_left"] = 0;
                $scope.varaints.areaDesign[key]["area_design_height"] = $scope.varaints.areaDesign[key]["img_src_height"] = Math.round( ratio * $scope.customHeight );
                $scope.varaints.areaDesign[key]["img_src_top"] = $scope.varaints.areaDesign[key]["area_design_top"] = Math.round( 250 - $scope.varaints.areaDesign[key]["area_design_height"] / 2 );
            }else {
                var ratio = 500 / $scope.customHeight;
                $scope.varaints.areaDesign[key]["img_src_height"] = $scope.varaints.areaDesign[key]["area_design_height"] = 500;
                $scope.varaints.areaDesign[key]["img_src_top"] = $scope.varaints.areaDesign[key]["area_design_top"] = 0;
                $scope.varaints.areaDesign[key]["area_design_width"] = $scope.varaints.areaDesign[key]["img_src_width"] = Math.round( ratio * $scope.customWidth );                
                $scope.varaints.areaDesign[key]["img_src_left"] = $scope.varaints.areaDesign[key]["area_design_left"] = Math.round( 250 - $scope.varaints.areaDesign[key]["area_design_width"] / 2 );
            }
        });
        var len = $scope.currentVariant.info.length;
        if( len >= $scope.customSide ){
            $scope.varaints.areaDesign = $scope.varaints.areaDesign.slice(0, $scope.customSide);
        }else {
            for( var i = len; i < $scope.customSide; i++  ){
                $scope.varaints.areaDesign[i] = angular.copy( $scope.varaints.areaDesign[0] );
                $scope.varaints.areaDesign[i]['orientation_name'] = 'Side ' + (i + 1);
                //$scope.canvases["frame_"+i] = angular.copy( $scope.canvases["frame_0"] );
                //$scope.flagChangeOrientation[i] = 1;
            }
        };
        //$scope.flagChangeOrientation = [];
        $scope.changeOrientation();        
        if( !initReDesign ) {
            jQuery('#dg-custom-dimension').modal("hide");
        }       
    };
    $scope.positionPageType = 2;
    $scope.pageSourceType = 1;
    $scope.currentPagePositionIndex = 0;
    $scope.flagCustomProduct = false;
    $scope.currentPageDimension = 'width x height';
    $scope.changePageSource = function( variation ){
        $scope.currentPageSource = angular.copy( variation );
    };
    $scope.changePagePosition = function(variation, index){
        $scope.currentPagePosition = variation;
        $scope.currentPagePositionIndex = index;
    };
    $scope._changePageDimension = function(dim){
        $scope.currentPageDimension = dim.width + ' x ' + dim.height + ' ' + $scope.settings['nbdesigner_dimensions_unit'];
        $scope.customWidth2 = parseFloat( dim.width );
        $scope.customHeight2 = parseFloat( dim.height );        
    };
    $scope.insertPage = function(){
        $scope.saveDesign();
        var len = $scope.varaints.areaDesign.length,
            temp = [],
            insertIndex = $scope.positionPageType == 1 ? $scope.currentPagePositionIndex : ($scope.currentPagePositionIndex + 1),
            frame_old_index = 'frame_' + $scope.currentPagePositionIndex,
            frame_new_index = 'frame_' + insertIndex;
        if($scope.pageSourceType == 1){
            $scope.varaints.areaDesign.splice(insertIndex, 0, $scope.currentPageSource);
        }else {
            $scope.varaints.areaDesign.splice(insertIndex, 0, angular.copy($scope.varaints.areaDesign[0]));
            $scope.varaints.areaDesign[insertIndex]['real_width'] = $scope.customWidth2;
            $scope.varaints.areaDesign[insertIndex]['real_height'] = $scope.customHeight2;   
            $scope.varaints.areaDesign[insertIndex]['bg_type'] = 'color';
            $scope.varaints.areaDesign[insertIndex]['bg_color_value'] = '#ffffff';
            if( $scope.customWidth2 > $scope.customHeight2 ){
                var ratio = 500 / $scope.customWidth2;
                $scope.varaints.areaDesign[insertIndex]["img_src_width"] = $scope.varaints.areaDesign[insertIndex]["area_design_width"] = 500;
                $scope.varaints.areaDesign[insertIndex]["img_src_left"] = $scope.varaints.areaDesign[insertIndex]["area_design_left"] = 0;
                $scope.varaints.areaDesign[insertIndex]["area_design_height"] = $scope.varaints.areaDesign[insertIndex]["img_src_height"] = Math.round( ratio * $scope.customHeight2 );
                $scope.varaints.areaDesign[insertIndex]["img_src_top"] = $scope.varaints.areaDesign[insertIndex]["area_design_top"] = Math.round( 250 - $scope.varaints.areaDesign[insertIndex]["area_design_height"] / 2 );
            }else {
                var ratio = 500 / $scope.customHeight2;
                $scope.varaints.areaDesign[insertIndex]["img_src_height"] = $scope.varaints.areaDesign[insertIndex]["area_design_height"] = 500;
                $scope.varaints.areaDesign[insertIndex]["img_src_top"] = $scope.varaints.areaDesign[insertIndex]["area_design_top"] = 0;
                $scope.varaints.areaDesign[insertIndex]["area_design_width"] = $scope.varaints.areaDesign[insertIndex]["img_src_width"] = Math.round( ratio * $scope.customWidth2 );                
                $scope.varaints.areaDesign[insertIndex]["img_src_left"] = $scope.varaints.areaDesign[insertIndex]["area_design_left"] = Math.round( 250 - $scope.varaints.areaDesign[insertIndex]["area_design_width"] / 2 );
            }            
        }
        $scope.varaints.areaDesign[insertIndex]['orientation_name'] = 'Side ' + (insertIndex + 1);          
        for( var i =  len; i > insertIndex; i--){
            var _frame_src = 'frame_' + (i - 1),
                _frame_dst = 'frame_' + i;
            if(angular.isDefined($scope.svgs[_frame_src])){
                $scope.svgs[_frame_dst] = $scope.svgs[_frame_src];
            }
            if(angular.isDefined($scope.canvases[_frame_src])){
                $scope.canvases[_frame_dst] = angular.copy($scope.canvases[_frame_src]);
            }
            if(angular.isDefined($scope.dataCustomerDesign[_frame_src])){
                $scope.dataCustomerDesign[_frame_dst] = $scope.dataCustomerDesign[_frame_src];
            }                
        }
        $scope.flagCustomProduct = true;
        $scope.changeOrientation();        
        jQuery('#dg-custom-dimension').modal("hide");
    };
    $scope.reverseDimension = function(){
        $scope.varaints.areaDesign = [];
        $scope.varaints.areaDesign = angular.copy( $scope.originProduct );
        $scope.flagChangeDimension = false;
        $scope.changeOrientation();
        jQuery('#dg-custom-dimension').modal("hide");
    };
    $scope.cancelDimension = function(){
        jQuery('#dg-custom-dimension').modal("hide");
    };
    $scope.currentDimension = 'width x height';
    $scope.customPrice = 0;
    $scope.customReadyToChagne = false;
    $scope._changeDimension = function( dim ){
        $scope.currentDimension = dim.width + ' x ' + dim.height + ' ' + $scope.settings['nbdesigner_dimensions_unit'];
        $scope.customWidth = parseFloat( dim.width );
        $scope.customHeight = parseFloat( dim.height );
        $scope.customPrice = parseFloat( dim.price );
        $scope.customSide = $scope.currentVariant.info.length;
        $scope.customReadyToChagne = true;
    };
    $scope.loadExtraAdminDesign = function(template_id){
        $scope.loaded = 0;
        $scope.ignoreLocalDesign = true;
        $scope.flagLoadExtraAdminDesign = true;
        $scope.flagChangeTemplate = [];
        show_indicator();
        $('#dg-expand-feature').modal("hide");
        $scope.canvas.clear();
        if( $scope.flagChangeDimension ){
            $scope.flagChangeOrientation = [];
            $scope.refProduct = [];
            _.each($scope.originProduct, function(val, key){
                $scope.refProduct[key] = angular.copy( val );      
            });
        }
        $scope.loadProduct(template_id);
    };
    $scope.loadAdminDesignFont = function(fonts, assets_font_url){
        if(fonts.length){
            $scope._allFonts = fonts;
            _.each(fonts, function(font){
                /*
                 * Deprecated since 1.9.0
                 * 
                if(font.type == "google"){
                    jQuery("head").append("<link href='https://fonts.googleapis.com/css?family=" + font.name.replace(" ", "+") + "' rel='stylesheet' type='text/css'>")
                }else{
                    var fontFamily = font.alias ? font.alias : font.name;
                    if (!isFontAvailable(fontFamily)) {
                        var font_url = font.url ? font.url : font.name + '.' +font.ext; 
                        if(!(font_url.indexOf('http') > -1)) font_url = assets_font_url + font_url;
                        if (font.type = "ttf") font.type = "truetype";
                        var css = "";
                        css = "<style type='text/css'>";
                        css += "@font-face {font-family: '" + font.alias + "';";
                        css += "src: local('\u263a'),";
                        css += "url('" + font_url + "') format('" + font.type + "')";
                        css += "}";
                        css += "</style>";
                        jQuery("head").append(css)
                    }                
                }*/
                var fontName = font.alias,
                    fontType = font.type;
                var font_id = fontName.replace(/\s/gi, '').toLowerCase();
                if( !jQuery('#' + font_id).length ){
                    if(fontType == 'google'){
                        jQuery('head').append('<link id="' + font_id + '" href="https://fonts.googleapis.com/css?family='+ fontName.replace(/\s/gi, '+') +'" rel="stylesheet" type="text/css">');
                    }else{
                        var font_url = font.url;
                        if(! (font.url.indexOf("http") > -1)) font_url = NBDESIGNCONFIG['font_url'] + font.url; 
                        if (fontType == "ttf") type = "truetype";
                        var css = "";
                        css = "<style type='text/css' id='" + font_id + "' >";
                        css += "@font-face {font-family: '" + fontName + "';";
                        css += "src: local('\u263a'),";
                        css += "url('" + font_url + "') format('" + type + "')";
                        css += "}";
                        css += "</style>";
                        jQuery("head").append(css)                    
                    }
                }
            });
            var check = [], timeout = 0;
            var stop = $interval(function() {
                var _check = true;
                timeout += 100;
                _.each(fonts, function(font, key){
                    /*
                    if (!isFontAvailable(font.alias)) {
                        check[key] = false;
                    }else{
                        check[key] = true;
                    }*/
                    var FontFace = new FontFaceObserver(font.alias),
                        preview = $scope.subsets[font.subset];
                    check[key] = false;    
                    FontFace.load(preview).then(function () {
                        check[key] = true;
                        var _check = true;
                        _.each(check, function(c){
                            if(!c) _check = false;
                        });
                        if((_check && key == ( fonts.length - 1 )) || timeout > 5000 ){
                            $scope.changeOrientation();            
                            $scope.loaded = 100;
                            hide_indicator()                
                            $interval.cancel(stop);                    
                        } 
                    }, function () {
                        
                    });                 
                });
            }, 100);
        }else{
            $scope.changeOrientation();            
            $scope.loaded = 100;
            hide_indicator()              
        }
    };
    $scope.loadLanguage = function(code) {
        var first = false;
        if(code == null){
            code = 'en';
            if(NBDESIGNCONFIG['lang_code'] != '') code = NBDESIGNCONFIG['lang_code'];
            first = true;
        } else{
            show_indicator();
            $(".translate-switch").removeClass('open');
        }
        LanguageService.getLang(code).then(function(data) {
            if(data.mes == "success"){
                $scope.langs = data.langs;
                _.each($scope.langs, function(val, key) {
                    $scope.langs[key] = val.replace(/\\/g, '');
                });                
                $scope.langCategories = data.cat;
                $scope.currentCatLang = data.code;
                angular.extend(langjs, $scope.langs);
                initTooltip();
                initDialogLang();
                locale = data.code.substring(0, 2);
            }
            if(first){
                $scope.loaded = 70;
            } else{
                hide_indicator();
            }
        })     
    };    
    $scope.loadFont = function(index) {
        if ($scope.fontCat.length > 0 || $scope.fonts.length > 0) return;
        FontService.fn(function(data) {
            if (data.flag == "1") {
                if (toType(data.cat) == "array"){
                    if( angular.isDefined(NBDESIGNCONFIG.product_data.option.font_cats) ){
                        data.cat = data.cat.filter(function(cat){
                            var cid = cat.id;
                            return NBDESIGNCONFIG.product_data.option.font_cats.indexOf(cid) > -1;
                        });
                    };
                    $scope.fontCat = data.cat;
                    $scope.curentCatFont = data.cat[0].id;
                }
                if (toType(data.fonts) == "array") {
                    $scope.fonts = data.fonts;
                    $scope.getAmountFont($scope.fonts, $scope.curentCatFont);
                    $scope.customFont = JSON.parse(JSON.stringify(data.fonts))
                }
                if (toType(data.google_font) == "array") {
                    $scope.google_font = data.google_font;
                    $scope.googleFont = JSON.parse(JSON.stringify(data.google_font))
                }
                $scope.AllFonts = $scope.fonts;
                if( data.google_font ){
                    $scope._allFonts = JSON.parse(JSON.stringify(data.google_font));
                }else{
                    $scope._allFonts = [];
                }
                _.each($scope.customFont, function(font){
                    $scope._allFonts.push(font);
                });
                $scope.changeFontPageSize(true)
                //$scope.loadGoogleFont()
            } else console.log("Error! Try again!")
        })
    };
    $scope.loadGoogleFont = function() {
        if( ! _.size( $scope.googleFont ) ) return;
        $scope.changeFontCat({
            "id": "99",
            "name": "Google Font"
        });
        $scope.changeFontPageSize(true)
    };
    $scope.changeFontPageSize = function(first) {
        var previousIndex =0,
            arr = [],
            list = "";
        if (!first) {
            previousIndex = $scope.fontPageSize;
            $scope.fontPageSize = $scope.fontPageSize + 10
        }
        /* Deprecated since 1.9.0 */
        /*if ($scope.curentCatFont == "99") {
            arr = $scope.googleFont;
            var lastIndex = previousIndex + 10;
            if (arr.length < lastIndex - 1) lastIndex = arr.length + 1;
            var _arr = arr.slice(previousIndex, lastIndex);
            _.each(_arr, function(val, key) {
                var name = val.name;
                name = name.split(" ").join("+");
                list = list + name + "|"
            });
            list = list.slice(0, list.length - 1);
            $("head").append("<link href='https://fonts.googleapis.com/css?family=" + list + "' rel='stylesheet' type='text/css'>")
        } else {
            arr = $scope.customFont;
            arr = $scope.filterCat(arr, $scope.curentCatFont);
            var lastIndex = previousIndex + 10;
            if (arr.length < lastIndex - 1) lastIndex = arr.length + 1;
            var _arr = arr.slice(previousIndex, lastIndex);
            _.each(_arr, function(val, key) {
                if (!isFontAvailable(val.alias)) {
                    var font_url = val.url;
                    if(! (val.url.indexOf("http") > -1)) font_url = NBDESIGNCONFIG['font_url'] + val.url;
                    var type = val.type;
                    if (type == "ttf") type = "truetype";
                    var css = "";
                    css = "<style type='text/css'>";
                    css += "@font-face {font-family: '" + val.alias + "';";
                    css += "src: local('\u263a'),";
                    css += "url('" + font_url + "') format('" + type + "')";
                    css += "}";
                    css += "</style>";
                    jQuery("head").append(css)
                }
            })
        }*/
        $("#nbdesigner_font_container").stop().animate({
            scrollTop: $("#nbdesigner_font_container").prop("scrollHeight")
        }, 400)            
    };
    $scope.filterCat = function(arr, id) {
        var output = [];
        _.each(arr, function(val, key) {
            if (val.cat.length == 0) val.cat = ["0"];
            if ($.inArray(id, val.cat) >= 0) output.push(val)
        });
        return output
    };
    $scope.changeFontCat = function(cat) {
        var first = false;
        if (cat.id == "99") $scope.AllFonts = $scope.google_font;
        else $scope.AllFonts = $scope.fonts;
        $scope.fontPageSizes[$scope.curentCatFont] = $scope.fontPageSize;
        if ($scope.fontPageSizes[cat.id]) $scope.fontPageSize = $scope.fontPageSizes[cat.id];
        else {
            first = true;
            $scope.fontPageSize = 10
        }
        $scope.currentCatFontName = cat.name;
        $scope.curentCatFont = cat.id;
        if (cat.id == "99") $scope.countFont = $scope.google_font.length;
        else {
            $scope.getAmountFont($scope.fonts, $scope.curentCatFont);
            if (first) $scope.changeFontPageSize(first)
        }
        $("#nbdesigner_font_container").stop().animate({
            scrollTop: 0
        }, 400)        
    };
    $scope.loadArt = function() {
        if ($scope.artCat.length > 0 || $scope.arts.length > 0) return;
        $scope.disableDrawMode();
        ArtService.fn(function(data) {
            if (data.flag == "1") {
                if (toType(data.cat) == "array"){
                    if( angular.isDefined(NBDESIGNCONFIG.product_data.option.art_cats) ){
                        data.cat = data.cat.filter(function(cat){
                            var cid = cat.id;
                            return NBDESIGNCONFIG.product_data.option.art_cats.indexOf(cid) > -1;
                        });
                    };
                    $scope.artCat = data.cat;
                    if( data.cat.length == 0 ) data.arts = [];
                }                              
                if (toType(data.arts) == "array") {
                    $scope.arts = data.arts;    
                    _.each($scope.arts, function(art, key) {
                        if( !( art.url.indexOf("http") > -1 ) ){
                            $scope.arts[key]['url'] = NBDESIGNCONFIG['art_url'] + art.url;
                        }
                    });
                    $scope.getAmountArt($scope.arts, $scope.curentCatArt)
                }
                _.each($scope.artCat, function(cat, key) {
                    cat.amount = $scope.countArtByCatID($scope.arts, cat.id);
                });  
                var cart_sort = _.sortBy($scope.artCat, 'name');
                if( data.cat.length ){
                    $scope.curentCatArt = cart_sort[0]['id'];
                }else{
                    $scope.curentCatArt = 0;
                }
            } else console.log("Error! Try again!")
        })
    };
    $scope.changeArtCat = function(cat) {
        $scope.artPageSizes[$scope.curentCatArt] = $scope.artPageSize;
        if ($scope.artPageSizes[cat.id]) $scope.artPageSize = $scope.artPageSizes[cat.id];
        else $scope.artPageSize = 10;
        $scope.currentCatArtName = cat.name;
        $scope.curentCatArt = cat.id;
        $scope.getAmountArt($scope.arts, $scope.curentCatArt);
        $("#nbdesigner_art_container").stop().animate({
            scrollTop: 0
        }, 400)
    };
    $scope.loadMoreArt = function(){
        $scope.artPageSize += 10;
        $("#nbdesigner_art_container").stop().animate({
            scrollTop: $("#nbdesigner_art_container").prop("scrollHeight")
        }, 400)        
    };
    $scope.getAmountArt = function(input, cat_id) {
        $scope.countArt = 0;
        _.each(input, function(val, key) {
            if ($.inArray(cat_id, val.cat) >= 0) $scope.countArt++
        });
    };
    $scope.countArtByCatID = function(input, cat_id) {
        var count = 0;
        _.each(input, function(val, key) {
            if (val.cat.length == 0) val.cat = ["0"];
            if ($.inArray(cat_id, val.cat) >= 0) count++
        });
        return count;
    };    
    $scope.getAmountFont = function(input, cat_id) {
        $scope.countFont = 0;
        _.each(input, function(val, key) {
            if ($.inArray(cat_id, val.cat) >= 0) $scope.countFont++
        })
    };
    $scope.addSvgFromString = function(){
        var svg = $scope.svgCode;
        fabric.loadSVGFromString(svg, function(ob, op) {
            var obj = fabric.util.groupSVGElements(ob, op);
            $scope.canvas.add((new fabric.PathGroup(ob, op)).set({
                left: 100,
                top: 100
            }));   
            $scope.canvas.setActiveObject($scope.canvas.item($scope.canvas.getObjects().length - 1));
            var max_width = $scope.canvas.width * .9;
            var max_height = $scope.canvas.height * .9;
            var new_width = max_width;
            if (op.width < max_width) new_width = op.width;
            var width_ratio = new_width / op.width;
            var new_height = op.height * width_ratio;
            if (new_height > max_height) {
                new_height = max_height;
                var height_ratio = new_height / op.height;
                new_width = op.width * height_ratio
            }
            var editable = $scope.canvas.getActiveObject();
            _.each(editable.paths, function(path, index) {});
            $scope.canvas.getActiveObject().set({
                scaleX: new_width / op.width,
                scaleY: new_height / op.height
            });
            $scope.ajustAfterAddItem("path-group");
            jQuery("#dg-myclipart").modal("hide");
            $scope.drawCanvas()            
        });
    };    
    $scope.addArt = function(art) {
        if(NBDESIGNCONFIG['is_wpml']){
            art.url = art.url.replace(NBDESIGNCONFIG['home_url'], NBDESIGNCONFIG['icl_home_url']);
        }
        if(art.url.match(/\.(jpeg|jpg|gif|png)$/) != null){
            $scope.addImage(art.url);
            jQuery("#dg-cliparts").modal("hide");
        }else{
            fabric.loadSVGFromURL(art.url, function(ob, op) {
                $scope.canvas.add((new fabric.PathGroup(ob, op)).set({
                    left: 100,
                    top: 100,
                    svg_name: art.name
                }));
                $scope.canvas.setActiveObject($scope.canvas.item($scope.canvas.getObjects().length - 1));
                var max_width = $scope.canvas.width * .9;
                var max_height = $scope.canvas.height * .9;
                var new_width = max_width;
                if (op.width < max_width) new_width = op.width;
                var width_ratio = new_width / op.width;
                var new_height = op.height * width_ratio;
                if (new_height > max_height) {
                    new_height = max_height;
                    var height_ratio = new_height / op.height;
                    new_width = op.width * height_ratio
                }
                var editable = $scope.canvas.getActiveObject();
                _.each(editable.paths, function(path, index) {});
                $scope.canvas.getActiveObject().set({
                    scaleX: new_width / op.width,
                    scaleY: new_height / op.height
                });
                $scope.ajustAfterAddItem("path-group");
                jQuery("#dg-cliparts").modal("hide");
                $scope.drawCanvas()
            })            
        }
    };
    $scope.showPathConfig = function() {
        if ($scope.editableItem == null) {
            $scope.editable._paths = [];
            $scope.editable.paths = [];
            return
        }
        var object = $scope.canvas.item($scope.editableItem);
        var type = object.get("type");
        if (type != "path-group" && type != "path") return;
        $scope.editable._paths = object.paths;
        jQuery('.modal-backdrop').css({'opacity': 0});
        $scope.editable.paths = $scope.getColorPath(object.paths)
    };
    $scope.getColorPath = function(paths) {
        var output = [];
        console.log(paths);
        _.each(paths, function(path, key) {
            if (toType(path.fill) == 'string') {
                output.push({
                    "fill": tinycolor(path.fill).toHex(),
                    "key": key
                });
                $scope.pathColor[key] = tinycolor(path.fill).toHex()                
            }
        });
        return output
    };
    $scope.getColorCode = function(color) {
        return "#" + color
    };
    $scope.updatePathColor = function(color) {
        var hex = $scope.pathColor[color.key];
        hex = tinycolor(hex).toHexString();
        if ($scope.editable.type == "path-group") $scope.editable._paths[color.key].fill = hex;
        $scope.drawCanvas()
    };
    $scope.showGrid = function() {};
    $scope.deleteLayer = function(e) {
        deleteObject(e.index)
    };
    $scope.activeLayer = function(e) {
        if ($scope.canvas.item(e.index).get("selectable") && $scope.canvas.item(e.index).get("visible")) {
            $scope.canvas.setActiveObject($scope.canvas.item(e.index));
            $scope.drawCanvas()
        } else return
    };
    $scope.parseObject = function(str) {
        var f = str.replace(/'/g, '"');
        var e = JSON.parse(f);
        return e
    };
    $scope.nextOrientation = function( index ){
        var next = index + 1;
        $scope.changeOrientation({
            "name": "frame_" + next,
            "id": next
        });
    };
    $scope.previousOrientation = function( index ){
        var prev = index - 1;
        $scope.changeOrientation({
            "name": "frame_" + prev,
            "id": prev
        });        
    };  
    $scope.existDesign = function( orientation ){
        if( angular.isDefined($scope.dataCustomerDesign[orientation.name]) ) return true;
        return false;
    };
    $scope.flagChangeTemplate = [];
    $scope.changeOrientation = function(p) {
        destroyTooltipFrame();
        $scope.keepLocalDesign = false;
        var first = false;
        if (p == null) {
            p = {
                "name": "frame_0",
                "id": 0
            };
            first = true
        }
        $scope.currentSide = p;
        $scope.currentVariant.orientationBefore = $scope.currentVariant.orientationActive;
        if (!first) $scope.saveDesign($scope.currentVariant.orientationBefore);
        $scope.currentVariant.orientationActive = p.name;
        var i = 0;
        $scope.currentVariant.info = [];
        _.each($scope.varaints.areaDesign, function(value, key) {
            if(!value['show_overlay']) value['show_overlay'] = "0";
            if(!value['img_overlay']) value['img_overlay'] = "";
            $scope.currentVariant.info[key] = {
                "source": value,
                "name": "frame_" + key,
                "v_index": $scope.currentVariant.index,
                "id": key
            };
            i++
        });
        if( $scope.customSize && $scope.flagChangeCustomSize){
            $scope.flagChangeCustomSize = false;
            $scope.changeDimension( true );
        };
        var _img = [{
            "img_src": $scope.currentVariant.info[p.id]["source"]["img_src"],
            "bg_type": (!!$scope.currentVariant.info[p.id]["source"]["bg_type"]) ? $scope.currentVariant.info[p.id]["source"]["bg_type"] : 'image',
            "bg_color_value": (!!$scope.currentVariant.info[p.id]["source"]["bg_color_value"]) ? $scope.currentVariant.info[p.id]["source"]["bg_color_value"] : '#ffffff',
            "img_src_left": $scope.currentVariant.info[p.id]["source"]["img_src_left"],
            "img_src_top": $scope.currentVariant.info[p.id]["source"]["img_src_top"],
            "img_src_width": $scope.currentVariant.info[p.id]["source"]["img_src_width"],
            "img_src_height": $scope.currentVariant.info[p.id]["source"]["img_src_height"]
        }];
        $scope.currentPageSource = angular.copy($scope.currentVariant.info[p.id]["source"]);
        $scope.currentPagePosition = angular.copy($scope.currentVariant.info[p.id]["source"]);
        $scope.currentPagePositionIndex = p.id;        
        if(!!$scope.currentVariant.info[p.id]["source"]["include_overlay"]){
            $scope.includeOverlay = parseInt($scope.currentVariant.info[p.id]["source"]["include_overlay"]);
        };
        $scope.currentVariant.numberFrame = i;
        $scope.currentVariant.activeImages = _img;
        $scope.currentVariant.designArea = $scope.varaints.areaDesign[p.id];
        var _width = $scope.currentVariant.designArea.area_design_width * $scope.designScale,
            _height = $scope.currentVariant.designArea.area_design_height * $scope.designScale;   
        $scope.scale[p.name] = $scope.currentVariant.info[p.id]["source"]["real_width"] * $scope.rateConvertCm2Px / _width;
        $scope.currentScale = $scope.scale[p.name];
        var unitRatio = $scope.settings.nbdesigner_dimensions_unit == 'mm' ? 0.1 : ($scope.settings.nbdesigner_dimensions_unit == 'in' ? 2.54 : 1);
        var factor = $scope.settings.nbdesigner_dimensions_unit == 'mm' ? 645.16 : ($scope.settings.nbdesigner_dimensions_unit == 'in' ? 1 :  6.4516);
        $scope.ratioConvertFont = _width / ($scope.currentVariant.info[p.id]["source"].real_width / unitRatio * 2.54 * 72) * factor;
        $scope.canvas.setDimensions({
            "width": _width,
            "height": _height
        });
        if (!first) $scope.updateCurrentLayer();     
        $scope.canvas.clear();
        if($scope.currentVariant.info[p.id]["source"]["show_overlay"] == "1" && $scope.currentVariant.info[p.id]["source"]["include_overlay"] == "1" && $scope.currentVariant.info[p.id]["source"]["img_overlay"] != ''){            
            var overlay_src = $scope.currentVariant.info[p.id]["source"]["img_overlay"],
                width = 500, height = 500;
            fabric.Image.fromURL(overlay_src, function(op) {
                width = op.width;
                height = op.height;
                $scope.canvas.setOverlayImage(overlay_src, function(){                
                    $scope.canvas.overlayImageLeft = 0;
                    $scope.canvas.overlayImageTop = 0;
                    $scope.canvas.overlayImage.scaleX = $scope.canvas.width / width;
                    $scope.canvas.overlayImage.scaleY = $scope.canvas.height / height;
                    $scope.canvas.renderAll()
                });                               
            }, {crossOrigin: 'anonymous'});
        } else {
            $scope.canvas.overlayImage = null;           
        };
        $scope.ignoreLocalDesign = false;
        if (angular.isDefined($scope.canvases[p.name])){
            $scope.canvas.loadFromJSON($scope.canvases[p.name], function() {  
                $scope.updateLayerColor();
                applyImageFilters();
                $scope.canvas.renderAll();
                $scope.updateCurrentLayerAfterDelete();
                if(angular.isUndefined($scope.flagChangeOrientation[p.id])){
                    $scope.resizeDesign($scope.designScale, $scope.ajustmentScale);
                    $scope.fitReferenceDesign(p.id);
                    $scope.flagChangeOrientation[p.id] = 1;
                }else if($scope.ajustmentOrientationScale[p.id] != $scope.designScale){
                    $scope.resizeDesign($scope.designScale, $scope.ajustmentOrientationScale[p.id]);
                } else if($scope.flagLoadExtraAdminDesign && angular.isUndefined($scope.flagChangeTemplate[p.id])){
                    $scope.resizeDesign($scope.designScale, $scope.ajustmentScale);
                    if( $scope.flagChangeTemplate.length == $scope.currentVariant.numberFrame ) $scope.flagLoadExtraAdminDesign = false;
                };
                $scope.flagChangeTemplate[p.id] = 1;
                $scope.ajustmentOrientationScale[p.id] = $scope.designScale;
                
//                if($scope.currentVariant.info[p.id]["source"]["show_overlay"] == "1" && $scope.currentVariant.info[p.id]["source"]["img_overlay"] != ''){  
//                    var overlay_src = $scope.currentVariant.info[p.id]["source"]["img_overlay"];
//                    $scope.updateOverlay(overlay_src);            
//                }
            });
        };
        if( $scope.bleedStatus ) {
            jQuery('.nbd-bleed, .nbd-safe-zone').show();
        }else {
            jQuery('.nbd-bleed, .nbd-safe-zone').hide();          
        }         
        $scope.updateUndoRedoStatus();
        $scope.showAlignToolbar = false;
        $scope.customSide = $scope.currentVariant.info.length;
        $scope.zoom = $scope.currentScale < 1 ? $scope.currentScale : 1;
        $scope.zoomCanvas();    
        $scope.drawCanvas();  
        $timeout(function(){
            initTooltipFrame();
        }, 0);
        $scope.canvas.isDrawingMode = false
    };
    $scope.updateOverlay = function(overlay_src){
        var overlayItemId = $scope.getOverlayLayer();
        console.log(overlayItemId);
        if( !overlayItemId ){
            fabric.Image.fromURL(overlay_src, function(op) {
                $scope.canvas.add(op);
                $scope.canvas.setActiveObject($scope.canvas.item($scope.canvas.getObjects().length - 1));
                var object = $scope.canvas.getActiveObject();
                object.bringToFront();
                object.set({
                    isOverlay:1,
                    selectable: false,
                    scaleX: $scope.canvas.width / object.width / $scope.zoom,
                    scaleY:  $scope.canvas.height / object.height / $scope.zoom                    
                });
                $scope.canvas.deactivateAll();
                $scope.zoomCanvas();    
                $scope.drawCanvas();                
                $scope.updateCurrentLayerAfterDelete();               
            });
        };
    };
    $scope.getOverlayLayer = function(){
        var itemId = false;
        $scope.canvas.forEachObject(function(obj) {
            if (obj.type === "image" && obj.isOverlay != undefined ) {
                itemId =  obj.itemId;
            }
        });
        return itemId;
    };   
    $scope.resizeDesign = function(newScale, oldScale){
        if(newScale == oldScale) return;
        var factor = newScale / oldScale;
        $scope.canvas.forEachObject(function(obj) {     
            var scaleX = obj.scaleX,
            scaleY = obj.scaleY,
            left = obj.left,
            top = obj.top,
            tempScaleX = scaleX * factor,
            tempScaleY = scaleY * factor,
            tempLeft = left * factor,
            tempTop = top * factor;   
            obj.scaleX = tempScaleX;
            obj.scaleY = tempScaleY;
            obj.left = tempLeft;
            obj.top = tempTop;  
            obj.setCoords();
        });   
        $scope.canvas.calcOffset();
        var frame_id = $scope.currentSide.id;
        if($scope.currentVariant.info[frame_id]["source"]["show_overlay"] == "1" && $scope.currentVariant.info[frame_id]["source"]["img_overlay"] != ''){            
            var overlay_src = $scope.currentVariant.info[frame_id]["source"]["img_overlay"],
                width = 500, height = 500;
            fabric.Image.fromURL(overlay_src, function(op) {
                width = op.width;
                height = op.height;
                $scope.canvas.setOverlayImage(overlay_src, function(){                
                    $scope.canvas.overlayImageLeft = 0;
                    $scope.canvas.overlayImageTop = 0;
                    $scope.canvas.overlayImage.scaleX = $scope.canvas.width / width;
                    $scope.canvas.overlayImage.scaleY = $scope.canvas.height / height;
                    $scope.canvas.renderAll()
                });                               
            }, {crossOrigin: 'anonymous'});
        } else {
            $scope.canvas.overlayImage = null;           
        };        
        $scope.drawCanvas();        
    };
    $scope.snapGrid = function(){
        $scope.gridMode = ! $scope.gridMode;
        jQuery('.canvas-container .upper-canvas').toggleClass('has-grid');
    };
    $scope.fitReferenceDesign = function(id){   
        if( angular.isUndefined($scope.refProduct[id]) ) return;
        var ref_width = $scope.refProduct[id]["area_design_width"],
        ref_height = $scope.refProduct[id]["area_design_height"],
        width = $scope.currentVariant.info[id]["source"]["area_design_width"],
        height = $scope.currentVariant.info[id]["source"]["area_design_height"];
        if((ref_width/ref_height) > (width/height)){
            $scope.resizeDesign(width/ref_width, 1);
            var offset_top = (height - ref_height*width/ref_width) * $scope.zoom * $scope.designScale / 2;
            $scope.canvas.forEachObject(function(obj) {  
                obj.top = obj.top + offset_top;   
            })
        }else{
            $scope.resizeDesign(height/ref_height, 1);
            var offset_left = (width - ref_width*height/ref_height) * $scope.zoom * $scope.designScale / 2;
            $scope.canvas.forEachObject(function(obj) {  
                obj.left = obj.left + offset_left;    
            })            
        }    
        $scope.canvas.calcOffset();
        $scope.drawCanvas();          
    };
    $scope.resource = {};
    $scope.pdfPreview = [];
    $scope.enableJsPdf = false;
    $scope.saveDesign = function(orientation) {
        if (orientation == null) orientation = $scope.currentVariant.orientationActive;
        $scope.zoom = 1;
        $scope.zoomCanvas();
        $scope.drawCanvas();
        var json = canvas.toJSON(['itemId', 'selectable', 'lockMovementX', 'lockMovementY', 'lockScalingX', 'lockScalingY', 'lockRotation', 'rtl', 'elementUpload', 'forceLock', 'isBg', 'is_uppercase','available_color','available_color_list','color_link_group','isOverlay','ptFontSize']);      
        var config = {};
        if ($scope.modeMobile) {
            var _width = $scope.currentVariant.designArea.area_design_width * $scope.designScale,
                _height = $scope.currentVariant.designArea.area_design_height * $scope.designScale;
            if (_width > _height){
                if (_width * $scope.currentScale > 1E3){
                    $scope.zoom = 1E3 / _width;
                }else {
                    $scope.zoom = $scope.currentScale;
                }
            }else {
                if (_height * $scope.currentScale > 1E3){
                    $scope.zoom = 1E3 / _height;
                }else{
                    $scope.zoom = $scope.currentScale
                }
            }
        } else {
            $scope.zoom = $scope.currentScale;
            if( $scope.currentVariant.designArea.area_design_width * $scope.designScale * $scope.currentScale > 5E3 ){
                $scope.zoom = 1;
                $scope.only_svg = 1;
            }            
        };
        /* Calculate PDF preview dimension */
        if( $scope.enableJsPdf ){
            $scope.pdfPreview[orientation] = {
                left: Math.round($scope.zoom * $scope.currentVariant.designArea.area_design_left * $scope.designScale),
                top: Math.round($scope.zoom * $scope.currentVariant.designArea.area_design_top * $scope.designScale),
                width: Math.round($scope.zoom * $scope.currentVariant.designArea.area_design_width * $scope.designScale),
                height: Math.round($scope.zoom * $scope.currentVariant.designArea.area_design_height * $scope.designScale),
                src_width: Math.round($scope.zoom * $scope.currentVariant.designArea.img_src_width * $scope.designScale),
                src_height: Math.round($scope.zoom * $scope.currentVariant.designArea.img_src_height * $scope.designScale),
                src_left: Math.round($scope.zoom * $scope.currentVariant.designArea.img_src_left * $scope.designScale),
                src_top: Math.round($scope.zoom * $scope.currentVariant.designArea.img_src_top * $scope.designScale),
                src_type: $scope.currentVariant.designArea.bg_type,
                src: $scope.currentVariant.designArea.img_src,
                src_color: $scope.currentVariant.designArea.bg_color_value
            };
        }
        /* End. Calculate PDF preview dimension */
        /* @deprecated siince 1.9.0
         */
        if( $scope.canvas.overlayImage ){
            var _scaleX = $scope.canvas.overlayImage.scaleX,
            _scaleY = $scope.canvas.overlayImage.scaleY;   
        };    
        if($scope.canvas.overlayImage && !$scope.includeOverlay){
            $scope.canvas.overlayImage.scaleX = 0;
            $scope.canvas.overlayImage.scaleY = 0;
        };
//        if($scope.canvas.overlayImage && !$scope.includeOverlay){ 
//            var overlayItemId = $scope.getOverlayLayer();
//            if( overlayItemId ){
//                var itemIndex = $scope.getItemById( overlayItemId );
//                $scope.canvas.item( itemIndex ).set({
//                    visible: false
//                });                
//            }
//        };
//        if($scope.currentVariant.info[$scope.currentSide.id].source.area_design_type == "2"){
//            $scope.canvas.clipTo = function(ctx) {
//                ctx.ellipse($scope.canvas.width/2, $scope.canvas.height/2, $scope.canvas.width/2, $scope.canvas.height/2, 0, 0, Math.PI * 2, true);
//            };
//        }else {
//            $scope.canvas.clipTo = null;
//        };         
        $scope.zoomCanvas();
        $scope.drawCanvas();
        // If sasve design to JPG
        //$scope.addBackground('#fff');
        // Save to JPG
        var svg = canvas.deactivateAll().toSVG();  
        $scope.svgs[orientation] = svg;
        var design = canvas.deactivateAll().toDataURL();
        // Save to JPG
        //var design = canvas.deactivateAll().toDataURL({format:'jpg'}); 
        $scope.canvases[orientation] = json;
        $scope.fontCollection[orientation] = $scope.getUsedFonts();
        $scope.dataCustomerDesign[orientation] = design;
        $scope.currentPreview = design;

        $timeout(function(){
            $scope.zoom = 1;

            /* @deprecated siince 1.9.0
             * */
            $timeout(function(){
                if($scope.canvas.overlayImage){
                    $scope.canvas.overlayImage.scaleX = _scaleX;
                    $scope.canvas.overlayImage.scaleY = _scaleY;            
                }            
            });

    //        if($scope.canvas.overlayImage && !$scope.includeOverlay){ 
    //            var overlayItemId = $scope.getOverlayLayer();
    //            if( overlayItemId ){
    //                var itemIndex = $scope.getItemById( overlayItemId );
    //                $scope.canvas.item( itemIndex ).set({
    //                    visible: true
    //                });                
    //            }
    //        };       

            // If sasve design to JPG
            //$scope.canvas.setBackgroundColor('rgba(255,255,255,0)');
            $scope.zoomCanvas();
            $scope.drawCanvas();
        });
        var sid = "p_" + NBDESIGNCONFIG['product_id'],
        cid = "c_" + NBDESIGNCONFIG['product_id'];
        
        config['scale'] = $scope.designScale;        
        config['furl'] = NBDESIGNCONFIG['font_url'];      
        config['font_used'] = $scope.filterFontUsed();   
        if( $scope.flagChangeDimension ) {
            config['custom_dimension'] = { width: $scope.customWidth, height: $scope.customHeight, price: $scope.customPrice };
        }
        config['product'] = $scope.varaints.areaDesign;
        try {
            localStorageService.set(sid, $scope.canvases);
            localStorageService.set(cid, config);
        } catch (e) {
            localStorageService.clearAll();
            localStorageService.set(sid, $scope.canvases);
            localStorageService.set(cid, config);
        }
    };
    $scope.getUsedFonts = function() {
        var fonts = [];
        $scope.canvas.forEachObject(function(object) {
            if ( object.type === "i-text" || object.type === "text" || object.type === "curvedText" || object.type === 'textbox' ) fonts.push(object.getFontFamily());
        });
        return fonts
    };
    $scope.filterFontUsed = function(){
        var usedFonts = [];
        _.forEach($scope.fontCollection, function(used_fonts) {
            _.each(used_fonts, function(used_font){
                _.each($scope._allFonts, function(font){
                    if(font.alias == used_font){
                        usedFonts.push(font);
                    }
                });       
            });      
        });
        return _.uniq(usedFonts);
    };
    $scope.preview = function() {
        $scope.saveDesign();

    };
    $scope.storeDesign = function() {
        $scope.saveDesign();
        var fonts = $scope.filterFontUsed(),
        config = {'scale' : $scope.designScale, 'dpi' : $scope.productOptions.dpi,'only_svg': $scope.only_svg};
        if( $scope.flagChangeDimension ) {
            var _customPrice = parseInt( $scope.customPrice ) *$scope.varaints.areaDesign.length;
            if( $scope.initNoPage < $scope.varaints.areaDesign.length ){
                if( angular.isDefined( $scope.productOptions.price_per_page ) ){
                    _customPrice += ( $scope.varaints.areaDesign.length - $scope.initNoPage ) * $scope.productOptions.price_per_page;
                }
            } 
            config.initNoPage = $scope.initNoPage;
            config.custom_dimension = { width: $scope.customWidth, height: $scope.customHeight, price: _customPrice, side: $scope.customSide };
        }
        config['product'] = $scope.varaints.areaDesign;   
        if( _.size( $scope.listFileUpload ) ){
            nbd_window.show_upload_thumb($scope.listFileUpload);
            nbd_window.NBDESIGNERPRODUCT.update_nbu_value($scope.listFileUpload);
        }else if( NBDESIGNCONFIG['ui_mode'] == "1" ) {
            nbd_window.show_upload_thumb([]);
        }
        NBDESIGNERCART.save_design($scope.dataCustomerDesign, $scope.canvases, fonts, config, $scope.svgs);
    };
    $scope.saveCart = function(){
        if( NBDESIGNCONFIG['enable_upload_without_design'] == 1 ){
            $scope.saveDesign();
            var fonts = $scope.filterFontUsed(),
            config = {'scale' : $scope.designScale, 'dpi' : $scope.productOptions.dpi};
            if( $scope.flagChangeDimension ) {
                config.custom_dimension = { width: $scope.customWidth, height: $scope.customHeight, price: $scope.customPrice, side: $scope.customSide };
            }
            config['product'] = $scope.varaints.areaDesign;     
        }
        var files = '';
        _.each($scope.listFileUpload, function(val, key){
            files += key == 0 ? val.name : '|' + val.name;
        });  
        NBDESIGNERCART.save_cart($scope.dataCustomerDesign, $scope.canvases, fonts, config, files, $scope.svgs);        
    };
    $scope.toggleImportArea = function(){
        $('#design-editor-container').toggleClass('open');
        $('#nbdesigner-list-template').removeClass('open');
        $("#nbdesigner-list-template").stop().animate({
            scrollTop: 0
        }, 400)         
    };
    $scope.exportDesign = function(){
        $scope.saveDesign();
        var filename = 'design.json',
        text = JSON.stringify($scope.canvases),
        a = document.createElement('a');
        a.setAttribute('href', 'data:text/plain;charset=utf-u,'+ text);
        a.setAttribute('download', filename);
        a.click()       
    };
    $scope.downloadPNG = function(){
        $scope.saveDesign();
        _.each($scope.dataCustomerDesign, function(val, key){
            var filename = key + '.png',
            a = document.createElement('a');
            a.setAttribute('href', val);
            a.setAttribute('download', filename);
            a.click() 
        });       
    };
    $scope.downloadJPG = function(){
        $scope.saveDesign();
        _.each($scope.dataCustomerDesign, function(val, key){
            var filename = key + '.jpg',
            a = document.createElement('a');
            a.setAttribute('href', val);
            a.setAttribute('download', filename);
            a.click() 
        });       
    }; 
    $scope.downloadPDF = function(){
        $scope.saveDesign();
        var _index = 0;
        var doc = null;
        show_indicator();
        _.each($scope.dataCustomerDesign, function(val, key){
            var height = $scope.pdfPreview[key].src_height / 72;
            var width = $scope.pdfPreview[key].src_width / 72;
            var orientation = width > height ? 'landscape' : 'portrait';
            if( _index ){
                doc.addPage([width, height],orientation );
            }else{
                doc = new jsPDF({
                    orientation: orientation,
                    unit: 'in',
                    format: [width, height]                    
                });
            }
            _index++;
            $scope.pdfPreview[key].index = _index;
            doc.setPage($scope.pdfPreview[key].index);    
            if( $scope.pdfPreview[key].src_type == 'color' ){
                doc.setDrawColor(0);
                doc.setFillColor(tinycolor($scope.pdfPreview[key].src_color).toRgb().r, tinycolor($scope.pdfPreview[key].src_color).toRgb().g, tinycolor($scope.pdfPreview[key].src_color).toRgb().b);
                doc.rect(0, 0, width, height, 'F');
                doc.addImage(val, 'PNG', ($scope.pdfPreview[key].left - $scope.pdfPreview[key].src_left) / 72, ( $scope.pdfPreview[key].top - $scope.pdfPreview[key].src_top ) / 72, $scope.pdfPreview[key].width / 72, $scope.pdfPreview[key].height / 72);
            }else if( $scope.pdfPreview[key].src_type == 'image' ){
                function getBase64Image(img) {
                    var __canvas = document.createElement("canvas");
                    __canvas.width = img.width;
                    __canvas.height = img.height;
                    var ctx = __canvas.getContext("2d");
                    ctx.drawImage(img, 0, 0);
                    return __canvas.toDataURL("image/png");
                }  
                var img = new Image();
                img.onload = function(){
                    var dataURI = getBase64Image(img);
                    doc.setPage($scope.pdfPreview[key].index);
                    doc.addImage(dataURI, 'PNG', 0, 0, width, height);
                    doc.addImage(val, 'PNG', ($scope.pdfPreview[key].left - $scope.pdfPreview[key].src_left) / 72, ( $scope.pdfPreview[key].top - $scope.pdfPreview[key].src_top ) / 72, $scope.pdfPreview[key].width / 72, $scope.pdfPreview[key].height / 72);         
                };   
                img.src = $scope.pdfPreview[key].src;
            }
            
        });
        setTimeout(function(){
            doc.save('design.pdf'); 
            hide_indicator();
        }, 1000);
        
    };
    $scope.importDesign = function(){
        var datadesign = JSON.parse($('#design-json-content').val());
        if(toType(datadesign) === 'object'){            
            show_indicator();
            $scope.canvases = datadesign;
            $scope.changeOrientation();  
            hide_indicator();   
        }
        $('#dg-expand-feature').modal("hide");
    };
    $scope.resetAdminDesign = function(){
        $scope.loaded = 0;
        $scope.ignoreLocalDesign = true;
        show_indicator();
        $('#dg-expand-feature').modal("hide");
        $scope.canvas.clear();
        $scope.loadProduct(NBDESIGNCONFIG['product_id'], 0, 'primary');
        $scope.clearHistory();
    };
    $scope.calcLeft = function(left) {
        if (angular.isDefined(left)) {
            var offsetWidth = $scope.designerWidth / 2;
            left *= $scope.designScale;
            //return offsetWidth - (offsetWidth - left) * $scope.zoom
            return left * $scope.zoom;
        }
    };
    $scope.bleedStatus = true;
    $scope.showBleed = function(){
        if( $scope.bleedStatus ) {
            jQuery('.nbd-bleed, .nbd-safe-zone').hide();
        }else {
            jQuery('.nbd-bleed, .nbd-safe-zone').show();          
        }
        $scope.bleedStatus = !$scope.bleedStatus;
        var ignore = localStorageService.get('nbd_ignore_mes');
        if( !ignore || ignore == 2 ){
            jQuery('#dg-bleed-tip').modal('show');
        }
    };
    $scope.ignoreMessage = function(){
        if( jQuery('#nbd-bleed-notify').is(':checked') ){
            localStorageService.set('nbd_ignore_mes', 1);
        }else{
            localStorageService.set('nbd_ignore_mes', 2);
        }
    };    
    $scope.zoomViewport = function(){
        $scope.designerWidth = $scope.originDesignerWidth * $scope.zoom;
        $scope.designerHeight = $scope.originDesignerHeight * $scope.zoom;
        var w = $(window).width();
        $scope.offset = (w - $scope.designerWidth) / 2;
        if( $scope.offset < 0 ) $scope.offset = 0;
    };
    $scope.calcWidthThumb = function(n){
        return (n < 4) ? n : 4;
    };
    $scope.calcDimension = function(width) {
        width = $scope.zoom * width * $scope.designScale;
        width = width + "px";
        return width;
    };
    $scope.calcBleedSize = function( command, size, bleed, ratio ){
        var result = '';
        var size = parseFloat(size);
        switch(command){
            case 'width':
            case 'height':    
                result = ( size  - Math.round( 2 * bleed * ratio ) ) * $scope.zoom * $scope.designScale;
                break;     
            case 'left':
            case 'top':
                result = ( size  + Math.round( bleed * ratio ) ) * $scope.zoom * $scope.designScale;
                break;             
        }
        return result;
    };
    $scope.calcSafeZone = function( command, size, bleed, margin, ratio ){
        var result = '';
        var size = parseFloat(size),
            bleed = parseFloat(bleed),
            margin = parseFloat(margin),
            ratio = parseFloat(ratio);
        switch(command){
            case 'width':
            case 'height':    
                result = ( size  - Math.round( 2 * ( margin + bleed ) * ratio ) ) * $scope.zoom * $scope.designScale;
                break;     
            case 'left':
            case 'top':
                result = ( size  + Math.round( ( margin + bleed ) * ratio ) ) * $scope.zoom * $scope.designScale;
                break;             
        }
        return result;
    };    
    $scope.addLayers = function(object, type, index) {
        var layer = {};
        if (type === "text" || type === "i-text" || type === "curvedText") {
            var title = object.text;
            if (title.length > 20) title = title.substring(0, 19);
            if(object.rtl) title = reverseString(title);
            layer = {
                "name": title,
                "type": "text",
                "src": "",
                "index": index
            }
        }
        if (type === "image") layer = {
            "name": langjs["LAYER_IMAGE"],
            "type": "image",
            "src": object.getSvgSrc(),
            "index": index
        };
        if (type == "custom-image") layer = {
            "name": langjs["LAYER_IMAGE"],
            "type": "image",
            "src": object.origin_src,
            "index": index
        };
        if (type === "path-group") layer = {
            "name": "SVG",
            "type": "path-group",
            "src": NBDESIGNCONFIG['assets_url'] + "images/svg.png",
            "index": index
        };
        if (type === "group") layer = {
            "name": langjs["LAYER_GROUP"],
            "type": "path-group",
            "src": NBDESIGNCONFIG['assets_url'] + "images/svg.png",
            "index": index
        };
        if (type === "path") layer = {
            "name": langjs["LAYER_PATH"],
            "type": "path",
            "src": NBDESIGNCONFIG['assets_url'] + "images/path.png",
            "index": index
        };
        if (type === "rect") layer = {
            "name": langjs["LAYER_RECTANGLE"],
            "type": "rect",
            "src": NBDESIGNCONFIG['assets_url'] + "images/mark/mark_12.svg",
            "index": index
        };
        if( object.isBg ) {
            layer.name = langjs["BACKGROUND"];
            layer.isBg = 1;
        }
        if( object.isOverlay ) {
            layer.name = "Overlay";
            layer.isOverlay = 1;
        }        
        if (type === "circle") layer = {
            "name": langjs["LAYER_CIRCLE"],
            "type": "circle",
            "src": NBDESIGNCONFIG['assets_url'] + "images/mark/mark_03.svg",
            "index": index
        };
        if (type === "triangle") layer = {
            "name": langjs["LAYER_TRIANGLE"],
            "type": "triangle",
            "src": NBDESIGNCONFIG['assets_url'] +
                "images/mark/mark_13.svg",
            "index": index
        };
        if (type === "line") layer = {
            "name": langjs["LAYER_LINE"],
            "type": "line",
            "src": NBDESIGNCONFIG['assets_url'] + "images/path.png",
            "index": index
        };
        if (type === "polygon") layer = {
            "name": langjs["LAYER_POLYGON"],
            "type": "polygon",
            "src": NBDESIGNCONFIG['assets_url'] + "images/mark/mark_11.svg",
            "index": index
        };
        if(!object.get("selectable") || !object.get("visible")){
            layer.class = "lock";
        }else{
            layer.class = '';
        }
        if( angular.isDefined(object.svg_name) ) {
            layer.name = object.svg_name;
        }
        if (angular.isUndefined($scope.layers[$scope.currentVariant.orientationActive])) $scope.layers[$scope.currentVariant.orientationActive] = [];
        var layers = $scope.layers[$scope.currentVariant.orientationActive];
        layers[index] = layer;
        $scope.updateCurrentLayer()
    };
    $scope.sortLayer = function(from, to) {
        var length = $scope.canvas.getObjects().length,
            itemBgId = $scope.getBackgroundLayer();    
        if( itemBgId && (from == 0 || to == 0) ) {
            $scope.updateCurrentLayerAfterDelete();
            return;
        }
        if (angular.isUndefined(from) || angular.isUndefined(to)) return;
        if (from < to) {
            for (var j = 0; j < from; j++) $scope.bringToFront(0);
            for (j = 0; j < to - from; j++) $scope.bringToFront(1);
            for (j = to; j < length; j++) $scope.bringToFront(0)
        } else {
            for (var j = 0; j < to; j++) $scope.bringToFront(0);
            $scope.bringToFront(from - to);
            for (j = 0; j < length - to - 1; j++) $scope.bringToFront(0)
        }
        $scope.updateCurrentLayerAfterDelete();
        $scope.canvas.deactivateAll();
        $scope.canvas.setActiveObject($scope.canvas.item(to))
    };
    $scope.bringToFront = function(index) {
        $scope.canvas.item(index).bringToFront()
    };
    $scope.setStackPosition = function(command) {
        var object = canvas.getActiveObject();
        if (object == null) return;
        switch (command) {
            case "bringToFront":
                object.bringToFront();
                break;
            case "bringForward":
                object.bringForward();
                break;
            case "sendBackwards":
                object.sendBackwards();
                break;
            case "sendToBack":
                object.sendToBack();
                break
        }
        var bgItemid = $scope.getBackgroundLayer(),
        idActiveObject = $scope.canvas.getObjects().indexOf( object );     
        if( bgItemid && idActiveObject == 0 ) {
            object.moveTo(1);
        };
        var overlayItemId = $scope.getOverlayLayer(),
            numberLayer = $scope.canvas.getObjects().length;    
        if( overlayItemId && idActiveObject == (numberLayer - 1) ){
            object.moveTo(numberLayer - 2);
        }
        $scope.canvas.setActiveObject(object);
        $scope.updateCurrentLayerAfterDelete();
        $scope.canvas.deactivateAll().renderAll();
    };
    $scope.updateCurrentLayerAfterDelete = function() {
        var index = $scope.canvas.getObjects().length;
        $scope.layers[$scope.currentVariant.orientationActive] = [];
        if (index === 0) {
            $scope.layers[$scope.currentVariant.orientationActive] = [];
            $scope.currentLayers = [];
            return
        }
        for (var i = 0; i < index; i++) {
            var type = $scope.canvas.item(i).get("type");
            $scope.addLayers($scope.canvas.item(i), type, i)
        }
    };
    $scope.updateCurrentLayer = function() {
        $scope.currentLayers = $scope.layers[$scope.currentVariant.orientationActive]
    }
    $scope.getQrCode = function() {
        var type_qrcode = 'svg';
        if( type_qrcode == 'png' ){
            QrcodeService.fn($scope.qrCodeContent, function(data) {
                if (data.flag == "1") {
                    var html = '<img src="' + data.src + '" class="qr_image shadow hover-shadow" onclick="NBDESIGNERFUNC.addQrImage(\'' + data.src + "')\" spinner-on-load />";
                    $("#qrcode-img").html("");
                    $("#qrcode-img").append(html);
                    $scope.uploadURL.push(data.src);
                    if( NBDESIGNCONFIG['nbdesigner_cache_uploaded_image'] == 'yes' ){
                        localStorageService.set($scope.iid, $scope.uploadURL)
                    }
                } else alert("Error! Try again!")
            })
        }else{
            var qr = qrcode(4, 'L');
            qr.addData( $scope.qrCodeContent );
            qr.make();
            $scope.svgCode = qr.createSvgTag(); 
            $scope.addSvgFromString();    
            $scope.svgCode = '';
            jQuery('#dg-qrcode').modal('hide');
        }
    };
    $scope.showDrawConfig = function() {
        showConfig();
        $scope.showPopover("draw")
    };
    $scope.changeDrawMode = function() {
        $scope.canvas.isDrawingMode = true;
        $scope.freeDrawingMode = "Pencil";
        $scope.setDrawingLineColor($scope.colorBrush);
        $scope.setDrawingLineWidth($scope.brushWidth);
        $scope.setDrawingLineShadowWidth($scope.brushShadowWidth);
        $scope.setDrawingLineOpacity($scope.brushOpacity)
    };
    $scope.disableDrawMode = function() {
        $scope.canvas.isDrawingMode = false
    };
    $scope.setDrawingMode = function(type) {
        $scope.canvas.isDrawingMode = true;
        $scope.freeDrawingMode = type;
        if (type === "hline") $scope.canvas.freeDrawingBrush = $scope.vLinePatternBrush;
        else if (type === "vline") $scope.canvas.freeDrawingBrush = $scope.hLinePatternBrush;
        else if (type === "square") $scope.canvas.freeDrawingBrush = $scope.squarePatternBrush;
        else if (type === "diamond") $scope.canvas.freeDrawingBrush = $scope.diamondPatternBrush;
        else if (type === "texture") $scope.canvas.freeDrawingBrush = $scope.texturePatternBrush;
        else $scope.canvas.freeDrawingBrush = new fabric[type + "Brush"]($scope.canvas);
        jQuery("#brush_width").slider("value", 0);
        jQuery("#brush_shadow_width").slider("value", 0);
        if (!jQuery("#show_popover_option_draw").hasClass("open")) jQuery("#show_popover_option_draw").triggerHandler("click")
    };
    $scope.setDrawingLineColor = function(value) {        
        value = tinycolor(value).toHexString();
        if ($scope.canvas.freeDrawingBrush) $scope.canvas.freeDrawingBrush.color = value
    };
    $scope.setDrawingLineWidth = function(value) {
        if ($scope.canvas.freeDrawingBrush) $scope.canvas.freeDrawingBrush.width = parseInt(value, 10) || 1
    };
    $scope.setDrawingLineOpacity = function(value) {
        if ($scope.canvas.freeDrawingBrush) $scope.canvas.freeDrawingBrush.opacity = value
    };
    $scope.setDrawingLineShadowWidth = function(value) {
        if ($scope.canvas.freeDrawingBrush) {
            var blur = parseInt(value, 10) || 0;
            if (blur > 0) $scope.canvas.freeDrawingBrush.shadow =
                new fabric.Shadow({
                    blur: blur,
                    offsetX: 10,
                    offsetY: 10
                });
            else $scope.canvas.freeDrawingBrush.shadow = null
        }
    };
    $scope.initBrushes = function() {
        if (!fabric.PatternBrush) return;
        $scope.initVLinePatternBrush();
        $scope.initHLinePatternBrush();
        $scope.initSquarePatternBrush();
        $scope.initDiamondPatternBrush();
        $scope.initImagePatternBrush()
    };
    $scope.initImagePatternBrush = function() {
        var img = new Image;
        img.src = NBDESIGNCONFIG['assets_url'] + "images/honey_im_subtle.png";
        $scope.texturePatternBrush = new fabric.PatternBrush(canvas);
        $scope.texturePatternBrush.source =
            img
    };
    $scope.initDiamondPatternBrush = function() {
        $scope.diamondPatternBrush = new fabric.PatternBrush(canvas);
        $scope.diamondPatternBrush.getPatternSrc = function() {
            var squareWidth = 10,
                squareDistance = 5;
            var patternCanvas = fabric.document.createElement("canvas");
            var rect = new fabric.Rect({
                width: squareWidth,
                height: squareWidth,
                angle: 45,
                fill: this.color
            });
            var canvasWidth = rect.getBoundingRectWidth();
            patternCanvas.width = patternCanvas.height = canvasWidth + squareDistance;
            rect.set({
                left: canvasWidth / 2,
                top: canvasWidth / 2
            });
            var ctx = patternCanvas.getContext("2d");
            rect.render(ctx);
            return patternCanvas
        }
    };
    $scope.initSquarePatternBrush = function() {
        $scope.squarePatternBrush = new fabric.PatternBrush(canvas);
        $scope.squarePatternBrush.getPatternSrc = function() {
            var squareWidth = 10,
                squareDistance = 2;
            var patternCanvas = fabric.document.createElement("canvas");
            patternCanvas.width = patternCanvas.height = squareWidth + squareDistance;
            var ctx = patternCanvas.getContext("2d");
            ctx.fillStyle = this.color;
            ctx.fillRect(0, 0, squareWidth, squareWidth);
            return patternCanvas
        }
    };
    $scope.initVLinePatternBrush = function() {
        $scope.vLinePatternBrush = new fabric.PatternBrush(canvas);
        $scope.vLinePatternBrush.getPatternSrc = function() {
            var patternCanvas = fabric.document.createElement("canvas");
            patternCanvas.width = patternCanvas.height = 10;
            var ctx = patternCanvas.getContext("2d");
            ctx.strokeStyle = this.color;
            ctx.lineWidth = 5;
            ctx.beginPath();
            ctx.moveTo(0, 5);
            ctx.lineTo(10, 5);
            ctx.closePath();
            ctx.stroke();
            return patternCanvas
        }
    };
    $scope.initHLinePatternBrush = function() {
        $scope.hLinePatternBrush = new fabric.PatternBrush(canvas);
        $scope.hLinePatternBrush.getPatternSrc = function() {
            var patternCanvas = fabric.document.createElement("canvas");
            patternCanvas.width = patternCanvas.height = 10;
            var ctx = patternCanvas.getContext("2d");
            ctx.strokeStyle = this.color;
            ctx.lineWidth = 5;
            ctx.beginPath();
            ctx.moveTo(5, 0);
            ctx.lineTo(5, 10);
            ctx.closePath();
            ctx.stroke();
            return patternCanvas
        }
    };
    $scope.getRandomColor = function() {
        return colorTrend[Math.floor(Math.random() * colorTrend.length)]
    };
    $scope.addRect = function() {
        $("#opacity_shape").slider("value", 0);
        var _default =
            $scope.designerWidth > 50 ? 50 : $scope.designerWidth;
        $scope.canvas.add(new fabric.Rect({
            left: 0,
            top: 0,
            fill: NBDESIGNCONFIG['nbdesigner_default_color'],
            width: _default,
            height: _default,
            strokeWidth: 1,
            opacity: 1
        }));
        $scope.ajustAfterAddItem("rect")
    };
    $scope.showBackgroundOption = function(){
        jQuery('.pop-bg-color').toggleClass('active');
    };
    $scope.getBackgroundLayer = function(){
        var itemId = false;
        $scope.canvas.forEachObject(function(obj) {
            if (obj.type === "rect" && obj.isBg != undefined ) {
                itemId =  obj.itemId;
            }
        });
        return itemId;
    };
    $scope.colorBackground = '#607d8b';
    $scope.changeBackgroundColor = function( color ){
        $scope.addBackground(color);
    };
    $scope.addBackground = function( color ){
        var bgItemId = $scope.getBackgroundLayer();
        if( bgItemId ){
            var itemIndex = $scope.getItemById( bgItemId );
            $scope.canvas.item( itemIndex ).set({
                fill: color
            });
        }else{
            $scope.canvas.add(new fabric.Rect({
                left: -10,
                top: -10,
                fill: color,
                width: $scope.canvas.width + 20,
                height: $scope.canvas.height + 20,
                selectable: false,
                isBg: 1
            }));   
            $scope.ajustAfterAddItem("rect");
            $scope.canvas.getActiveObject().moveTo(0);
            $scope.updateCurrentLayerAfterDelete();
        }
        $scope.canvas.deactivateAll();
        $scope.drawCanvas();
    };
    $scope.removeBackgroundStage = function(){
        var bgItemId = $scope.getBackgroundLayer();
        if( bgItemId ){
            var itemIndex = $scope.getItemById( bgItemId );
            $scope.canvas.remove($scope.canvas.item(itemIndex));
            $scope.updateCurrentLayerAfterDelete();
            $scope.drawCanvas();
        }        
    };
    $scope.addCircle = function() {
        $("#opacity_shape").slider("value", 0);
        var _default = $scope.designerWidth > 50 ? 50 : $scope.designerWidth;
        $scope.canvas.add(new fabric.Circle({
            left: 0,
            top: 0,
            fill: NBDESIGNCONFIG['nbdesigner_default_color'],
            radius: _default,
            opacity: 1
        }));
        $scope.ajustAfterAddItem("circle")
    };
    $scope.addTriangle = function() {
        $("#opacity_shape").slider("value", 0);
        var _default = $scope.designerWidth > 50 ? 50 : $scope.designerWidth;
        $scope.canvas.add(new fabric.Triangle({
            left: 0,
            top: 0,
            fill: NBDESIGNCONFIG['nbdesigner_default_color'],
            width: _default,
            height: _default,
            opacity: 1
        }));
        $scope.ajustAfterAddItem("triangle")
    };
    $scope.addLine = function() {
        $("#opacity_shape").slider("value", 0);
        $scope.canvas.add(new fabric.Line([50, 100, 200, 200], {
            left: 0,
            top: 0,
            stroke: NBDESIGNCONFIG['nbdesigner_default_color']
        }));
        $scope.ajustAfterAddItem("line")
    };
    $scope.addPolygon = function(type) {
        $("#opacity_shape").slider("value",0);
        switch(type) {
            case 'star':
                $scope.canvas.add(new fabric.Polygon([{x: 40,y: 60}, {x: 60,y: 74.641}, {x: 57.321,y: 50}, {x: 80,y: 40}, {x: 57.321,y: 30}, {x: 60,y: 5.359}, {x: 40,y: 20}, {x: 20,y: 5.359}, {x: 22.679,y: 30}, {x: 0,y: 40}, {x: 22.679,y: 50}, {x: 20,y: 74.641}], {
                    left: 0,
                    top: 0,
                    fill: NBDESIGNCONFIG['nbdesigner_default_color']
                }));
                break;
            case 'hex':    
                $scope.canvas.add(new fabric.Polygon([{x: 10,y: 17.321},{x: -10,y: 17.321},{x: -20,y: 0},{x: -10,y: -17.321},{x: 10,y: -17.321},{x: 20,y: 0}], {
                    left: 0,
                    top: 0,
                    fill: NBDESIGNCONFIG['nbdesigner_default_color']
                }));
        }
        $scope.ajustAfterAddItem("polygon")
    };
    $scope.setShapeColor = function(e) {
        e = tinycolor(e).toHexString();
        if ($scope.editable.type === "line") {
            $scope.changeStroke(e);
        } else if ($scope.editable.type === "rect" || $scope.editable.type === "triangle" || $scope.editable.type === "polygon" || $scope.editable.type === "circle"){
            $scope.changeColor(e)
        }
    };
    $scope.onFileUploadSelect = function( $files ){
        $scope.errorUpload = "";
        $scope.progressUpload = 0; 
        var file = $files[0],
            maxsize = parseFloat( $scope.uploadSetting.maxsize ) * 1024 * 1024,
            minsize = parseFloat( $scope.uploadSetting.minsize ) * 1024 * 1024,  
            arr = file.name.split("."),
            ext = arr[ arr.length - 1 ];    
        if( file.size > maxsize ){
            $scope.errorUpload = langjs['MES_ERROR_MAXSIZE_UPLOAD'] + " " + $scope.uploadSetting.maxsize + " MB";
            alert($scope.errorUpload);
        }else if(file.size < minsize){
            $scope.errorUpload += langjs['MES_ERROR_MINSIZE_UPLOAD'] + " " + $scope.uploadSetting.minsize + " MB";
            alert($scope.errorUpload);
        }else if(( $scope.uploadSetting.allow_type != '' && $scope.uploadSetting.allow_type.indexOf(ext) === -1) || $scope.uploadSetting.disallow_type.indexOf(ext) > 0){
            $scope.errorUpload += langjs['NOT_ALLOWED_FILE'];
            alert($scope.errorUpload);
            jQuery('#nbd-upload-note').triggerHandler('click');            
        } else{
            $scope.fileUpload = $files;
        }
    };
    $scope.listFileUpload = [];
    $scope.fileUpload = [];
    $scope.startUploadDesign = function(){
        if($scope.listFileUpload.length >= $scope.uploadSetting.number){
            alert(langjs['EXCEED_NUMBER']);
            return;
        };
        $scope.progressUpload = 1;
        $scope.loading = true;
        var first_time = $scope.listFileUpload.length > 0 ? 2 : 1;
        $scope.upload = $upload.upload({
            url: NBDESIGNCONFIG['ajax_url'],
            method: "POST",
            withCredentials: true,
            data: {
                "product_id"    :   NBDESIGNCONFIG['product_id'],
                "variation_id"    :   NBDESIGNCONFIG['variation_id'],
                "nbu_item_key"    :   NBDESIGNCONFIG['nbu_item_key'],
                "cart_item_key"    :   NBDESIGNCONFIG['cart_item_key'],               
                "task"    :   NBDESIGNCONFIG['task'],
                "first_time"    :   first_time,
                "action" : "nbd_upload_design_file",
                "nonce" : NBDESIGNCONFIG['nonce']
            },
            file: $scope.fileUpload
        }).progress(function(evt) {
            $scope.progressUpload = parseInt(100 * evt.loaded / evt.total)
        }).success(function(data, status, headers, config) {
            $scope.loading = false;
            if( data.flag == 1 ){
                $scope.listFileUpload.push( { src : data.src, name : data.name } );
            }else {
                alert(data.mes);
            }           
            $scope.fileUpload = [];
            if( NBDESIGNCONFIG['ui_mode'] == "1"  ) {
                nbd_window.show_upload_thumb($scope.listFileUpload);
            };             
        });
    };
    $scope.deleteUploadfile = function( index ){
        $scope.listFileUpload.splice(index, 1);
        if( NBDESIGNCONFIG['ui_mode'] == "1"  ) {
            nbd_window.show_upload_thumb($scope.listFileUpload);
        };        
    };
    $scope.completeUpload = function(){
        if( NBDESIGNCONFIG['task'] == "reup" ){
            show_indicator();
            var files = '';
            _.each($scope.listFileUpload, function(val, key){
                files += key == 0 ? val.name : '|' + val.name;
            });   
            $.ajax({
                url: NBDESIGNCONFIG['ajax_url'],
                method: "POST",  
                data: {
                    "action": "nbd_update_customer_upload",
                    "nonce": NBDESIGNCONFIG['nonce'],
                    "cart_item_key": NBDESIGNCONFIG['cart_item_key'],
                    "nbu_item_key": NBDESIGNCONFIG['nbu_item_key'],
                    "design_type": NBDESIGNCONFIG['design_type'],
                    "order_id": NBDESIGNCONFIG['order_id'],
                    "task2": NBDESIGNCONFIG['task2'],
                    "nbd_file": files
                }
            }).done(function(data){
                if(data == 'success') {
                    if(NBDESIGNCONFIG['redirect_url'] != ""){
                        window.location = NBDESIGNCONFIG['redirect_url'];
                        return;
                    }                     
                }else {
                    alert(data);
                    window.location = NBDESIGNCONFIG['redirect_url'];
                }
                hide_indicator();
            });
        }else if( ( NBDESIGNCONFIG['task2'] == "update" || NBDESIGNCONFIG['task'] == "new" ) && NBDESIGNCONFIG['ui_mode'] == 2 ) {
            $scope.saveCart();
        }else{
            if(NBDESIGNCONFIG['ui_mode'] == "1"){
                nbd_window.hideDesignFrame();
                nbd_window.show_upload_thumb($scope.listFileUpload);
                nbd_window.NBDESIGNERPRODUCT.update_nbu_value($scope.listFileUpload);
            }
            if(NBDESIGNCONFIG['redirect_url'] != ""){
                window.location = NBDESIGNCONFIG['redirect_url'];
                return;
            }             
        }      
    };
    $scope.listImageBeforeUpload = '';
    $scope.onFileSelect = function($files) {
        $scope.errorUpload = "";
        $scope.progressUpload = 0;
        $scope.file = [];
        var max_size = parseInt($scope.settings.nbdesigner_maxsize_upload),     
        min_size = parseInt($scope.settings.nbdesigner_minsize_upload);
        for (var i = 0; i < $files.length; i++) {
            if ($files[i].type.indexOf("image") === -1) {
                $scope.errorUpload = langjs['MES_ALLOW_UPLOAD_IMG'];
                continue
            }
            if ($files[i].size > max_size * 1024 * 1024 ) {
                $scope.errorUpload = langjs['MES_ERROR_MAXSIZE_UPLOAD'] + " " + max_size + " MB";
                continue
            }else if($files[i].size < min_size * 1024 * 1024){
                $scope.errorUpload = langjs['MES_ERROR_MINSIZE_UPLOAD'] + " " + min_size + " MB";
                continue                
            }
            $scope.file.push($files[i]);
            $scope.listImageBeforeUpload += $files[i].name;
            if(i < ($files.length-1)) $scope.listImageBeforeUpload += ' | ';
        }
    };
    $scope.startUpload = function() {
        if(jQuery('#accept_term').length > 0 && !jQuery('#accept_term').is(':checked')){
            alert(langjs['TERM_ALERT']);
            return;
        }
        if ($scope.errorUpload == "") {
            jQuery('#upload-tabs a[href="#uploaded-photo"]').tab("show");
            $scope.loading = true;
            $scope.ajaxUploadFiles( 0 );
            $scope.listImageBeforeUpload = '';
            if ($scope.file.length == 0) $scope.loading = false
        } else alert($scope.errorUpload)
    };
    $scope.ajaxUploadFiles = function( i ){
        $scope.progressUpload = 1;
        $scope.upload = $upload.upload({
            url: NBDESIGNCONFIG['ajax_url'],
            method: "POST",
            withCredentials: true,
            data: {
                "action": "nbdesigner_customer_upload",
                "nonce": NBDESIGNCONFIG['nonce']
            },
            file: $scope.file[i]
        }).progress(function(evt) {
            $scope.progressUpload = parseInt(100 * evt.loaded / evt.total)
        }).success(function(data, status, headers, config) {
            if (angular.isUndefined(data.src)) {
                alert(data.mes);
            }
            else {
                $scope.uploadURL.push(data.src);
                if( NBDESIGNCONFIG['nbdesigner_cache_uploaded_image'] == 'yes' ){
                    localStorageService.set($scope.iid, $scope.uploadURL)
                }
            }
            if( i < ( $scope.file.length - 1 ) ){
                $scope.ajaxUploadFiles( i + 1 );
            }else{
                $scope.loading = false
            }
        })        
    }; 
    $scope.loadLocalStorageImage = function() {
        $scope.disableDrawMode();
        var localSource = localStorageService.get($scope.iid, $scope.uploadURL);
        if (!!localSource && toType(localSource) == "array") $scope.uploadURL = localSource;
        $scope.loaded = 30
    };
    $scope.hasGetUserMedia = function(){
        return !!(navigator.getUserMedia || navigator.webkitGetUserMedia ||
            navigator.mozGetUserMedia || navigator.msGetUserMedia);        
    };
    $scope.initWebcam = function(){
        $scope.statusWebcam = true;
        Webcam.set({
            width: 400,
            height: 300,
            dest_width: 1280,
            dest_height: 960,
            image_format: 'jpeg',
            jpeg_quality: 100
        });   
        Webcam.set("constraints", {
            optional: [{ minWidth: 600 }]
        });
        Webcam.attach( '#my_camera' );     
        Webcam.setSWFLocation(NBDESIGNCONFIG['assets_url'] + 'webcam.swf');  
    };
    $scope.takeSnapshot = function(){
        show_indicator();
        Webcam.snap( function(data_uri) {
            $scope.resetWebcam();
            $scope.statusWebcam = false;
            var raw_image_data = data_uri.replace(/^data\:image\/\w+\;base64\,/, '');
            jQuery.ajax({
                url: NBDESIGNCONFIG['ajax_url'],
                method: "POST",   
                data: {
                    "action": "nbdesigner_save_webcam_image",
                    "image": raw_image_data,
                    "nonce": NBDESIGNCONFIG['nonce']                  
                }
            }).done(function(data){
                hide_indicator();
                data = JSON.parse(data);
                if(data.flag == 'success'){
                    jQuery("#dg-myclipart").modal("hide");
                    $scope.addImage(data.url);
                }else{
                    alert('Oops! Try again!');
                    $scope.initWebcam();
                }
            });
        } );       
    };
    $scope.pauseWebcam = function(){
        Webcam.freeze();
    };
    $scope.unPauseWebcam = function(){
        Webcam.unfreeze();
    };    
    $scope.resetWebcam = function(){
        if($scope.statusWebcam){
            Webcam.reset();
            $scope.statusWebcam = false;
            $scope.langs['STOPWEBCAM'] = $scope.langs["STARTWEBCAM"] ? $scope.langs["STARTWEBCAM"] : 'Start Webcam';
        }else{
            $scope.initWebcam();
            $scope.statusWebcam = true;
            $scope.langs['STOPWEBCAM'] = $scope.langs["STOPWEBCAM2"] ? $scope.langs["STOPWEBCAM2"] : 'Stop Webcam';
        }        
    };      
    $scope.loadMoreFacebookPhoto = function() {
        if ($("#nbdesigner_fb_next").val() == "") return;
        nbdesigner_fb1()
    };  
    $scope.instaAccessToken = '';
    $scope.authenticateInstagram = function(){
        var instaAccessToken = localStorageService.get('nbd_instagram_token');
        $scope.instaAccessToken = instaAccessToken;
        if(instaAccessToken){
            $scope.loadInstagramPhotos(instaAccessToken);
        }else {
            $scope._authenticateInstagram();
        }
    };
    $scope.switchInstagram = function(){
        localStorageService.remove('nbd_instagram_token');
        $('#instagram_login').show();   
        $('#instagram_logout').hide();   
    };
    $scope.login = function(){
        var popupLeft = (window.screen.width - 700) / 2,
            popupTop = (window.screen.height - 500) / 2,
            popup = window.open(NBDESIGNCONFIG['login_url'], '', 'width=700,height=500,left='+popupLeft+',top='+popupTop+'');
        popup.onload = new function() {
            if(window.location.hash.length == 0) {
                popup.open(NBDESIGNCONFIG['login_url'], '_self');
            }; 
            var interval = setInterval(function () {
                try {
                    if (popup.location.hash.length) {
                        if(popup.location.hash.length){
                            clearInterval(interval);
                            $scope.settings['is_logged'] = 1;
                            popup.close();
                            $scope.loadUserDesign();
                        }
                    }
                } catch (evt) {
                    //permission denied
                }
            }, 100);   
        }    
    };
    $scope._authenticateInstagram = function(){
        var popupLeft = (window.screen.width - 700) / 2,
                popupTop = (window.screen.height - 500) / 2;  
        var url = 'https://instagram.com/oauth/authorize/?client_id='+NBDESIGNCONFIG['nbdesigner_instagram_app_id']+'&redirect_uri='+NBDESIGNCONFIG['instagram_redirect_uri']+'&response_type=token';
        var popup = window.open(url, '_blank', 'width=700,height=500,left='+popupLeft+',top='+popupTop+'');
        popup.onload = new function() {
            if(window.location.hash.length == 0) {
                popup.open(url, '_self');
            };
            var interval = setInterval(function () {
                try {
                    if (popup.location.hash.length) {
                        clearInterval(interval);
                        instaAccessToken = popup.location.hash.slice(14);
                        localStorageService.set('nbd_instagram_token', instaAccessToken);
                        $scope.instaAccessToken = instaAccessToken;
                        popup.close();
                        $scope.loadInstagramPhotos(instaAccessToken);
                    }
                } catch (evt) {
                    //permission denied
                }
            }, 100);            
        }
    };
    $scope.loadInstagramPhotos = function(instaAccessToken){
        var endpointUrl = 'https://api.instagram.com/v1/users/self/media/recent?access_token='+instaAccessToken;
        jQuery.ajax({
            method: 'GET',
            url: endpointUrl,
            dataType: 'jsonp',
            jsonp: 'callback',
            jsonpCallback: 'jsonpcallback',
            cache: false,
            success: function(data) {
                if(data.data) {
                    var html ='', count = 0;
                    $('#instagram_login').hide();   
                    $.each(data.data, function(i, item) {
                        if(item.type == 'image') {
                            count++;
                            var imageWidth = String(item.images.standard_resolution.width),
                            imageHeight = item.images.standard_resolution.height,
                            regexImageSize = new RegExp('/s'+imageWidth+'x'+imageHeight, 'g'),
                            //image = item.images.standard_resolution.url.replace(regexImageSize,'');
                            image = item.images.standard_resolution.url;
                            html += '<img class="img-responsive img-thumbnail nbdesigner_upload_image shadow hover-shadow" data-url="" onclick="NBDESIGNERFUNC.addFacebookImage(\'' + image + '\', this)" src="' + image + '" />';
                        };
                    });
                    $("#instagram_images").html('');
                    if( count == 0 ) html = 'No image available!';
                    $("#instagram_images").prepend(html);
                }
            }
        });      
    };
    $scope.addFacebookImage = function(img, $event){
        var url = angular.isDefined(img.link) ? img.link : img;
        NBDESIGNERFUNC.addFacebookImage(url, $event.currentTarget);
    };
    $scope.authenticateDropbox = function(){
        var dbtaAccessToken = localStorageService.get('nbd_dropbox_token');
        if(dbtaAccessToken){
            $scope.loadDropboxPhotos(dbtaAccessToken);
        }else {
            $scope._authenticateDropbox();
        }        
    };
    var _dropboxImages = [];
    $scope.getDropboxImages = function(files){
        _.each(files, function(file, index){
            _dropboxImages.push({
                id :  file.id,
                link :  file.link
            });            
        });
        $scope.dropboxImages = _.uniq(_dropboxImages);
        var html = '';
        _.each($scope.dropboxImages, function(image){
            html += '<img class="img-responsive img-thumbnail nbdesigner_upload_image shadow hover-shadow" data-url="" onclick="NBDESIGNERFUNC.addFacebookImage(\'' + image.link + '\', this)" src="' + image.link + '" />';
        });
        if( _.size($scope.dropboxImages) == 0 ) html = 'No image available!';
        $("#dropbox_images").prepend(html);        
    };
    $scope._authenticateDropbox = function(){
        var popupLeft = (window.screen.width - 700) / 2,
                popupTop = (window.screen.height - 500) / 2;  
        var redirect = 'dev.cmsmart.net:3000/wp46/wp-content/plugins/nbdesignerv130/includes/auth-dropbox.php';
        var url = 'https://www.dropbox.com/oauth2/authorize?client_id='+NBDESIGNCONFIG['nbdesigner_dropbox_app_id']+'&redirect_uri='+redirect+'&response_type=token';
        var popup = window.open(url, '', 'width=700,height=500,left='+popupLeft+',top='+popupTop+'');
        var parseQueryString = function(str){
            var ret = Object.create(null);
            if (typeof str !== 'string') {
                return ret;
            }
            str = str.trim().replace(/^(\?|#|&)/, '');
            if (!str) {
                return ret;
            }
            str.split('&').forEach(function (param) {
                var parts = param.replace(/\+/g, ' ').split('=');
                var key = parts.shift();
                var val = parts.length > 0 ? parts.join('=') : undefined;
                key = decodeURIComponent(key);
                val = val === undefined ? null : decodeURIComponent(val);

                if (ret[key] === undefined) {
                    ret[key] = val;
                } else if (Array.isArray(ret[key])) {
                    ret[key].push(val);
                } else {
                    ret[key] = [ret[key], val];
                }
            });
            return ret;            
        };
        popup.onload = new function() {
            if(window.location.hash.length == 0) {
                popup.open(url, '_self');
            };
            var interval = setInterval(function () {
                try {
                    if (popup.location.hash.length) {
                        clearInterval(interval);
                        dbtaAccessToken = parseQueryString(popup.location.hash).access_token;
                        localStorageService.set('nbd_dropbox_token', dbtaAccessToken);
                        popup.close();
                        $scope.loadInstagramPhotos(dbtaAccessToken);
                    }
                } catch (evt) {
                    //permission denied
                }
            }, 100);               
        }
    }
    $scope.loadDropboxPhotos = function(dbtaAccessToken){
        //todo something
        var dbtaAccessToken = 'gazuxYhvRDAAAAAAAAAAGPHvdUoklzHGMBqD6lO2ELuOmeGi2dTZRkOI6AzCpkd5';
        console.log(dbtaAccessToken);
    };
    $scope.addImage = function(url, params) {
        //$scope.zoom = 1;
        $scope.zoomCanvas();
        fabric.Image.fromURL(url, function(op) {
            jQuery("#dg-myclipart").modal("hide");
            jQuery("#dg-qrcode").modal("hide");
            if(params){
                var object = $scope.canvas.getActiveObject();
                var element = object.getElement();
                $scope.setUndoRedo({
                    element: $scope.canvas.getActiveObject(),
                    parameters: JSON.stringify({"src" : element.src}),
                    interaction: "modify"
                });  
                element.setAttribute("src", url);  
                $scope.canvas.getActiveObject().set({
                    width: op.width,
                    height: op.height,
                    scaleX: object.width * object.scaleX / op.width,
                    scaleY: object.width * object.scaleX / op.width                  
                });
                object.setCoords();
                $scope.updatePositionReplaceButton();
                $scope.updateCurrentLayerAfterDelete();
            } else {
                $scope.canvas.add(op);
                $scope.showPopover("art");
                $scope.canvas.setActiveObject($scope.canvas.item($scope.canvas.getObjects().length - 1));
                var max_width = $scope.canvas.width * .9;
                var max_height = $scope.canvas.height * .9; 
                var new_width = max_width;
                if (op.width < max_width) new_width = op.width;
                var width_ratio = new_width / op.width;
                var new_height = op.height * width_ratio;
                if (new_height > max_height) {
                    new_height = max_height;
                    var height_ratio = new_height / op.height;
                    new_width = op.width * height_ratio
                }
                $scope.canvas.getActiveObject().set({
                    scaleX: new_width / op.width / $scope.zoom,
                    scaleY: new_height / op.height / $scope.zoom,
                    fill: '#ff0000'
                });
                /*** clipTo Image
                var __object = $scope.canvas.getActiveObject(),
                __width = __object.width > __object.height ? __object.height : __object.width;
                var clipPath = new fabric.Path(listPath['path_2']);
                clipPath.set({
                    originX: "center",
                    originY: "center",
                    opacity: 0,
                    hasRotatingPoint: false,
                    scaleX: __width / clipPath.width,
                    scaleY: __width / clipPath.height,
                    centeredScaling: true	
                });
                $scope.canvas.getActiveObject().set({
                    clipTo: function (ctx) {
                        clipPath.render(ctx);
                    }
                });
                */
                $scope.ajustAfterAddItem("image");                
            }
            $scope.drawCanvas()
        }, {crossOrigin: 'anonymous'})
    };
    $scope.fitWithDesignArea = function(){
        if ($scope.editableItem == null) return;
        var object = $scope.canvas.item($scope.editableItem);
        var factor = object.width/object.height > $scope.canvas.width/$scope.canvas.height ? $scope.canvas.width / object.width / $scope.zoom : $scope.canvas.height / object.height / $scope.zoom;
        object.set({
            top: 0,
            left: 0,
            scaleX: factor,
            scaleY: factor
        });
        $scope.deselectAll();
        $scope.updatePositionReplaceButton();
    };  
    $scope.svgCode = '';
    $scope.addImageFromUrl = function() {
        if( $scope.svgCode !== '' ){
            $scope.addSvgFromString();
            return
        }
        if ($scope.imageFromUrl == "") {
            alert("Image url empty!");
            return
        }
        if($scope.imageFromUrl.match(/\.(svg)$/) != null ){
            var art = {url: $scope.imageFromUrl};
            $scope.addArt(art);
            jQuery("#dg-myclipart").modal("hide");
            return
        }
        if( $scope.imageFromUrl.indexOf( NBDESIGNCONFIG['home_url'] ) > -1 ){
            $scope.addImage( $scope.imageFromUrl );   
            return
        }
        show_indicator();
        jQuery.ajax({
            url: NBDESIGNCONFIG['ajax_url'],
            method: "POST",
            data: {
                "action": "nbdesigner_copy_image_from_url",
                "nonce": NBDESIGNCONFIG['nonce'],
                "url": $scope.imageFromUrl,
                "gapi": $scope.gapi
            }
        }).done(function(data) {
            data = JSON.parse(data);
            if(data['flag'] == 1){
                hide_indicator();
                $scope.uploadURL.push(data['src']);
                $scope.addImage(data['src']);      
            } else{
                hide_indicator();
                jQuery('#upload-tabs a[href="#upload-computer"]').tab("show");
                alert('Try to download image and then upload to our server!');
            }

        })
    };
    $scope.pixabayPerPage = 30;
    $scope.pixabayImages = [];
    $scope.pixabay_key = 'blue flower';
    $scope.pixabayPages = 1;
    $scope.searchPixabay = function(){
        $scope.pixabayImages = [];
        $scope.pixabayPage = 1;
        $scope.callPixabayApi( $scope.pixabayPage );
    };
    $scope.callPixabayApi = function(){
        if( $scope.pixabayPage <= $scope.pixabayPages  ){
            jQuery('#pixabay_loading').show();
            jQuery.get('https://pixabay.com/api/?key='+ NBDESIGNCONFIG['nbdesigner_pixabay_api_key'] +'&response_group=high_resolution&image_type=photo&per_page='+$scope.pixabayPerPage+'&page='+$scope.pixabayPage+'&search_term='+encodeURIComponent($scope.pixabay_key), function(){
            }).done(function(data){
                _.each(data.hits, function(val, key) {
                    $scope.pixabayImages.push({
                       // url: val.imageURL,
                        link: val.largeImageURL,
                        preview: val.previewURL
                    });
                });
                $scope.pixabayPages = Math.ceil(data.totalHits/$scope.pixabayPerPage);
                jQuery('#pixabay_loading').hide();
                if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
            });
        }
    };
    $scope.unsplash_key = 'blue flower';
    $scope.unsplashPerPage = 20;
    $scope.unsplashImages = [];    
    $scope.unsplashPages = 1;
    $scope.searchUnsplash = function(){
        $scope.unsplashImages = [];
        $scope.unsplashPage = 1;
        $scope.callUnsplashApi( $scope.unsplashPage );
    };    
    $scope.callUnsplashApi = function(){
        if( $scope.unsplashPage <= $scope.unsplashPages  ){
            jQuery('#unsplash_loading').show();
            jQuery.get('https://api.unsplash.com/search/photos/?client_id='+ NBDESIGNCONFIG['nbdesigner_unsplash_api_key'] +'&per_page='+$scope.unsplashPerPage+'&page='+$scope.unsplashPage+'&query='+encodeURIComponent($scope.unsplash_key), function(){
            }).done(function(data){
                _.each(data.results, function(val, key) {
                    $scope.unsplashImages.push({
                       // url: val.imageURL,
                        link: val.urls.raw,
                        preview: val.urls.small
                    });
                });
                $scope.unsplashPages = data.total_pages;
                jQuery('#unsplash_loading').hide();
                if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
            });
        }        
    };
    $scope.resetImage = function() {
        var object = $scope.canvas.getActiveObject();
        if (object == null) return;
        object.filters = [];
        object.applyFilters();
        var _url = "";
        if ($scope.canvas.item($scope.editableItem).get("type") == "custom-image") {
            _url = $scope.canvas.item($scope.editableItem).origin_src;
            if (_url != "") {
                $scope.canvas.remove($scope.canvas.getActiveObject());
                $scope.addImage(_url)
            }
        }
        $scope.drawCanvas()
    };
    $scope.loadSource = function() {
        var localSource = localStorageService.get($scope.iid, $scope.uploadURL);
        if (!!localSource && toType(localSource) == "array") $scope.uploadURL = localSource;
        $scope.loaded = 30
    };
    $scope.initCropCanvas = function(type) {
        canvas2.clear();
        canvas2.calcOffset();
        canvas2.setZoom(1);
        canvas2.renderAll();
        canvas2.isDrawingMode = false;
        if ($scope.editableItem == null) return;
        if (type === "crop") {
            $scope.cropToolMode = true;
            $scope.clipPathMode = false
        } else {
            $scope.cropToolMode = false;
            $scope.clipPathMode = true
        }
        var width = 400,
            height = 400;
        var _url = "";
        if ($scope.canvas.item($scope.editableItem).get("type") == "image") _url = $scope.canvas.item($scope.editableItem).getSvgSrc();
        if ($scope.canvas.item($scope.editableItem).get("type") == "custom-image") _url = $scope.canvas.item($scope.editableItem).origin_src;
        var url = _url,
            _type =
            $scope.canvas.item($scope.editableItem).type;
        if (url == "") return;
        if (!$scope.modeMobile) {
            width = 600;
            height = 400
        } else {
            width = $(window).width() - 20;
            height = 250
        }
        canvas2.setDimensions({
            "width": width,
            "height": height
        });
        $("#shape_canvas").css({
            "width": width,
            "height": height
        });
        var ratio = 1;
        var originImg = new Image;
        originImg.onload = function() {
            op = new fabric.Image(originImg);
            canvas2.add(op);
            var new_width = op.width;
            if (op.width > width) new_width = width;
            var width_ratio = op.width / new_width;
            var new_height = op.height / width_ratio;
            ratio = width_ratio;
            if (new_height > 400) {
                new_height = 400;
                var height_ratio = op.height / new_height;
                new_width = op.width / height_ratio;
                ratio = height_ratio
            }
            canvas2.item(0).set({
                top: 0,
                left: 0,
                scaleX: 1 / ratio,
                scaleY: 1 / ratio,
                selectable: false,
                hasControls: false,
                hasBorders: false,
                opacity: .7
            }).center().setCoords();
            canvas2.renderAll();
            if ($scope.cropToolMode) {
                var path = new fabric.Path(listPath.path_crop),
                    path2 = new fabric.Path(listPath.path_crop);
                $scope.currentPathCrop = listPath.path_crop;
                path.set({
                    originX: "center",
                    originY: "center",
                    scaleX: ratio,
                    scaleY: ratio,
                    fill: "#9bf0e9",
                    opacity: 0
                });
                path2.set({
                    originX: "center",
                    originY: "center",
                    opacity: 0,
                    hasRotatingPoint: false,
                    centeredScaling: true
                })
            } else {
                var path = new fabric.Path(listPath.path_1),
                    path2 = new fabric.Path(listPath.path_1);
                $scope.currentPathCrop = listPath.path_1;
                path.set({
                    originX: "center",
                    originY: "center",
                    scaleX: ratio * 3,
                    scaleY: ratio * 3,
                    fill: "#9bf0e9",
                    opacity: 0
                });
                path2.set({
                    originX: "center",
                    originY: "center",
                    opacity: 0,
                    scaleX: 3,
                    scaleY: 3,
                    hasRotatingPoint: false,
                    centeredScaling: true
                })
            }
            canvas2.renderAll();
            var op2 = new fabric.Image(originImg, {
                top: 0,
                left: 0,
                scaleX: 1 / ratio,
                scaleY: 1 / ratio,
                selectable: false,
                hasControls: false,
                hasBorders: false
            });
            canvas2.add(op2);
            var c = document.getElementById("shape_canvas");
            var _ctx = c.getContext("2d");
            var shape = canvas.item(1);
            canvas2.item(1).set({
                clipTo: function(ctx) {
                    path.render(ctx)
                }
            }).center().setCoords();
            canvas2.add(path2);
            canvas2.item(2).set({
                borderColor: "rgba(220, 220, 220, 1)"
            });
            canvas2.item(2)["setControlVisible"]("tl", false);
            canvas2.item(2)["setControlVisible"]("bl",
                false);
            canvas2.item(2).center().setCoords();
            canvas2.setActiveObject(canvas2.item(2));
            canvas2.renderAll()
        };
        originImg.src = url
    };
    $scope.cropImage = function() {
        var _url = "";
        if ($scope.canvas.item($scope.editableItem).get("type") == "image") _url = $scope.canvas.item($scope.editableItem).getSvgSrc();
        if ($scope.canvas.item($scope.editableItem).get("type") == "custom-image") _url = $scope.canvas.item($scope.editableItem).get("origin_src");
        var url = _url,
            width = canvas2.item(2).get("width"),
            height = canvas2.item(2).get("height"),
            scaleX = canvas2.item(2).get("scaleX"),
            scaleY = canvas2.item(2).get("scaleY"),
            left = canvas2.item(2).get("left"),
            top = canvas2.item(2).get("top"),
            i_top = canvas2.item(1).get("top"),
            i_left = canvas2.item(1).get("left"),
            ratio = 1 / canvas2.item(0).get("scaleX");
        /* Save croped image on server */    
        var bound = canvas2.item(2).getBoundingRect(),
            imgBound =  canvas2.item(0).getBoundingRect(),
            imgScaleX = 1 / canvas2.item(0).get("scaleX"),
            imgScaleY = 1 / canvas2.item(0).get("scaleY");
        var fd = new FormData();
        fd.append('nonce', NBDESIGNCONFIG['nonce']);
        fd.append('action', 'nbd_crop_image');
        fd.append('url', _url);
        fd.append('startX', (bound.left - imgBound.left) * imgScaleX);
        fd.append('startY', (bound.top - imgBound.top) * imgScaleY);
        fd.append('width', bound.width * imgScaleX);
        fd.append('height', bound.height * imgScaleY);
        canvas2.remove(canvas2.item(0));
        canvas2.remove(canvas2.item(2));         
        var length = canvas2.getObjects().length;
        while (length > 1) {
            canvas2.remove(canvas2.item(1));
            length = canvas2.getObjects().length
        }
        canvas2.item(0).set({
            "left": scaleX * width / 2 - left + i_left,
            "top": scaleY * height / 2 - top + i_top
        });
        canvas2.setDimensions({
            "width": scaleX * width * ratio,
            "height": scaleY * height * ratio
        });
        canvas2.calcOffset();
        canvas2.setZoom(ratio);
        canvas2.renderAll();
        var img = new Image;
        show_indicator();
        function add_image(){
            img.onload = function() {
                var f_img = new fabric.CustomImage(img, {
                    "origin_src": url
                });
                $scope.canvas.remove($scope.canvas.getActiveObject());
                $scope.canvas.add(f_img);
                var op_width = scaleX * width * ratio,
                    op_height = scaleX * height * ratio;
                jQuery("#dg-crop-image").modal("hide");
                var max_width = $scope.canvas.width * .7;
                var max_height = $scope.canvas.height *.7;
                var new_width = max_width;
                if (op_width < max_width) new_width = op_width;
                var width_ratio = new_width / op_width;
                var new_height = op_height * width_ratio;
                if (new_height > max_height) {
                    new_height = max_height;
                    var height_ratio = new_height / op_height;
                    new_width = op_width * height_ratio
                }
                var index = $scope.canvas.getObjects().length - 1;
                $scope.canvas.setActiveObject($scope.canvas.item(index));
                $scope.addLayers($scope.canvas.getActiveObject(), "custom-image", index);
                $scope.canvas.getActiveObject().set({
                    scaleX: new_width / op_width,
                    scaleY: new_height /
                        op_height
                }).center().setCoords();
                $scope.drawCanvas();
                hide_indicator();
            }             
        }
        if( $scope.cropToolMode && $scope.cropByRect ){
            jQuery.ajax({
                url: NBDESIGNCONFIG['ajax_url'],
                method: "POST",   
                processData: false,
                contentType: false,
                data: fd
            }).done(function(data){
                if( data.flag == 1 ){
                    img.src = data.url;
                }else{
                    img.src = canvas2.deactivateAll().toDataURL();
                }
                add_image();
            });
        }else{
            img.src = canvas2.deactivateAll().toDataURL();
            add_image();
        }
    };
    $scope.lassoTool = function() {
        $scope.cropToolMode = true;
        $scope.cropByRect = false;
        $scope.clipPathMode = false;
        canvas2.remove(canvas2.item(2));
        canvas2.item(1).set({
            clipTo: function(ctx) {
                ctx.rect(0, 0, 0, 0)
            }
        });
        canvas2.renderAll();
        canvas2.isDrawingMode = true;
        $scope.freeDrawingMode = "Pencil";
        canvas2.freeDrawingBrush = new fabric["PencilBrush"](canvas2)
    };
    $scope.cropByRect = true;
    $scope.cropTool = function() {
        $scope.cropToolMode = true;
        $scope.cropByRect = true;
        $scope.clipPathMode = false;
        $scope.currentPathCrop = listPath.path_crop;
        path2 = new fabric.Path($scope.currentPathCrop);
        path2.set({
            originX: "center",
            originY: "center",
            opacity: 0,
            hasRotatingPoint: false,
            centeredScaling: true
        });
        canvas2.remove(canvas2.item(2));
        canvas2.add(path2);
        canvas2.item(2).center().setCoords();
        canvas2.item(2)["setControlVisible"]("tl", false);
        canvas2.item(2)["setControlVisible"]("bl", false);
        canvas2.setActiveObject(canvas2.item(2));
        canvas2.renderAll()
    };
    $scope.clipPath = function(type) {
        var index = "path_" + type;
        $scope.currentPathCrop = listPath[index];
        path2 = new fabric.Path($scope.currentPathCrop);
        path2.set({
            originX: "center",
            originY: "center",
            opacity: 0,
            hasRotatingPoint: false,
            scaleX: 3,
            scaleY: 3,
            centeredScaling: true
        });
        canvas2.remove(canvas2.item(2));
        canvas2.add(path2);
        canvas2.item(2).center().setCoords();
        canvas2.item(2)["setControlVisible"]("tl", false);
        canvas2.item(2)["setControlVisible"]("bl", false);
        canvas2.setActiveObject(canvas2.item(2));
        canvas2.renderAll()
    };
    $scope.toggleLockLayer = function(layer, $event) {
        $event.stopPropagation();
        var bool = !$scope.canvas.item(layer.index).get("selectable"),
            id = "#layer-" + layer.index,
            forceLock = $scope.canvas.item(layer.index).get("forceLock");
        if($scope.task == 'create' || $scope.design_type == 'template'){
            $scope.canvas.item(layer.index).set({
                "forceLock" : !forceLock
            });             
        }else{
            if(forceLock) return;
        }
        $scope.canvas.item(layer.index).set({
            selectable: bool
        });
        if (bool) {
            jQuery(id).removeClass("lock");
            jQuery(id + " .nbdesigner_lock_layer i").removeClass("fa-lock");
            jQuery(id + " .nbdesigner_lock_layer i").addClass("fa-unlock-alt")
        } else {
            $scope.editableItem = null;
            jQuery(id).addClass("lock");
            jQuery(id + " .nbdesigner_lock_layer i").addClass("fa-lock");
            jQuery(id + " .nbdesigner_lock_layer i").removeClass("fa-unlock-alt")
        }
        $scope.canvas.deactivateAll();
        $scope.drawCanvas()
    };
    $scope.lockItem = function(command){
        var object = $scope.canvas.getActiveObject();
        if (object == null) return;        
        switch(command) {
            case "a" :
                var index = $scope.canvas.getObjects().indexOf($scope.canvas.getActiveObject());
                $scope.toggleLockLayer({'index' : index});
                break;
            case "x" :
                var val = ! object.get("lockMovementX");
                object.set({
                    lockMovementX : val
                });
                break;    
            case "y" :
                var val = ! object.get("lockMovementY");
                object.set({
                    lockMovementY : val
                });
                break;       
            case "sx" :
                var val = ! object.get("lockScalingX");
                object.set({
                    lockScalingX : val
                });
                break;     
            case "sy" :
                var val = ! object.get("lockScalingY");
                object.set({
                    lockScalingY : val
                });
                break;    
            case "r" :
                var val = ! object.get("lockRotation");
                object.set({
                    lockRotation : val
                });
                break;             
            default: break;
        }
        $scope.getStatusItem();
    };
    $scope.getStatusItem = function(){
        var object = $scope.canvas.getActiveObject();
        if (object == null) return;         
        $scope.editable.lockMovementX = object.get('lockMovementX');
        $scope.editable.lockMovementY = object.get('lockMovementY');
        $scope.editable.lockScalingX = object.get('lockScalingX');
        $scope.editable.lockScalingY = object.get('lockScalingY');
        $scope.editable.lockRotation = object.get('lockRotation');
        $scope.editable.selectable = object.get('selectable');           
    };
    $scope.toggleVisibleLayer = function(layer){
        var bool = !$scope.canvas.item(layer.index).get("visible"),
            id = "#layer-" + layer.index;
        $scope.canvas.item(layer.index).set({
            visible: bool
        });   
        if (bool) {
            jQuery(id).removeClass("lock");
            jQuery(id).addClass("active");
            jQuery(id + " .nbdesigner_visible_layer i").addClass("fa-eye");
            jQuery(id + " .nbdesigner_visible_layer i").removeClass("fa-eye-slash")
        } else {
            jQuery(id).addClass("lock");
            jQuery(id).removeClass("active");
            jQuery(id + " .nbdesigner_visible_layer i").removeClass("fa-eye");
            jQuery(id + " .nbdesigner_visible_layer i").addClass("fa-eye-slash")            
        }
        $scope.canvas.deactivateAll();
        $scope.drawCanvas()        
    };
    $scope.duplicateItem = function() {
        var object = $scope.canvas.getActiveObject();
        if (object == null) return;
        var json = object.toJSON();
        var klass = fabric.util.getKlass(json.type);
        if( !klass.async ){
            $scope.canvas.add(klass.fromObject(json));
        }else{
            klass.fromObject(json, function(item){
                $scope.canvas.add(item);		
            });              
        }
        var index = $scope.canvas.getObjects().length - 1;
        $scope.canvas.deactivateAll();
        var item = $scope.canvas.item(index),
            left = item.getLeft(),
            top =  item.getTop();        
        $scope.canvas.setActiveObject(item);
        item.setLeft(left + 10);
        item.setTop(top + 10);
        $scope.drawCanvas();
        $scope.updateCurrentLayerAfterDelete();
        $scope.setUndoRedo({
            element: $scope.canvas.item(index),
            parameters: $scope.getItemJson($scope.canvas.item(index)),
            interaction: "add"
        });  
    };
    $scope.setUndoRedo = function(undo, redo){
        if (undo) {
            if(angular.isUndefined($scope.undos[$scope.currentVariant.orientationActive])) $scope.undos[$scope.currentVariant.orientationActive] = [];
            $scope.undos[$scope.currentVariant.orientationActive].push(undo);
            if ($scope.undos[$scope.currentVariant.orientationActive].length > 100) {
                $scope.undos[$scope.currentVariant.orientationActive].shift();
            }
        }
        if (redo) {
            if(angular.isUndefined($scope.redos[$scope.currentVariant.orientationActive])) $scope.redos[$scope.currentVariant.orientationActive] = [];
            $scope.redos[$scope.currentVariant.orientationActive].push(redo);
        }  
        $scope.updateCurrentLayerAfterDelete();
        $scope.updateUndoRedoStatus();
    };   
    $scope.clearHistory = function(){
        $scope.undos[$scope.currentVariant.orientationActive] = [];
        $scope.redos[$scope.currentVariant.orientationActive] = [];
        $scope.updateUndoRedoStatus();        
    };
    $scope.undoDesign = function(){
        if($scope.undos[$scope.currentVariant.orientationActive].length > 0) {
            var last = $scope.undos[$scope.currentVariant.orientationActive].pop();
            var _parameters = last.parameters;            
            if(last.interaction === 'remove') {
                $scope.canvas.add(last.element);
                last.interaction = 'add';
            }
            else if(last.interaction === 'add') {
                var item = $scope.canvas.item($scope.getItemById(last.element.itemId));
                $scope.canvas.remove(item);
                last.interaction = 'remove';
            }else {         
                var item = $scope.canvas.item($scope.getItemById(last.element.itemId));
                var parameters = JSON.parse(_parameters);
                _.each(parameters, function(val, key) {
                    parameters[key] = item.get(key);
                });
                _parameters = JSON.stringify(parameters);
                $scope.setItemParameters(last.parameters, last.element.itemId);  
            }
            $scope.setUndoRedo(false, {
                element: last.element,
                parameters: _parameters,
                interaction: last.interaction
            }); 
            $scope.drawCanvas();
        }
    };
    $scope.redoDesign = function(){
        if($scope.redos[$scope.currentVariant.orientationActive].length > 0) {
            var last = $scope.redos[$scope.currentVariant.orientationActive].pop();
            var _parameters = last.parameters;            
            if(last.interaction === 'remove') {
                $scope.canvas.add(last.element);
                last.interaction = 'add';
            }
            else if(last.interaction === 'add') {
                var item = $scope.canvas.item($scope.getItemById(last.element.itemId));
                $scope.canvas.remove(item);
                last.interaction = 'remove';
            }else {
                var item = $scope.canvas.item($scope.getItemById(last.element.itemId));
                var parameters = JSON.parse(_parameters);
                _.each(parameters, function(val, key) {
                    parameters[key] = item.get(key);
                });
                _parameters = JSON.stringify(parameters);                
                $scope.setItemParameters(last.parameters, last.element.itemId);
            }
            $scope.setUndoRedo({
                element: last.element,
                parameters: _parameters,
                interaction: last.interaction
            });
            $scope.drawCanvas();
        }
    };  
    $scope.getItemJson = function(item, params){
        if(params){
            return JSON.stringify(params);
        }else{
            return JSON.stringify(item);
        }
    };
    $scope.setItemParameters = function(parameters, itemId){
        var params = JSON.parse(parameters);
        var item = $scope.canvas.item($scope.getItemById(itemId));
        if(typeof params.src !== "undefined"){
            fabric.Image.fromURL(params.src, function(op) {
                item.getElement().setAttribute("src", params.src);  
                $scope.updateCurrentLayerAfterDelete();
                setTimeout(function(){ $scope.drawCanvas(); }, 1);
            })	            
        }        
        item.set(params);
        item.setCoords();
        if( angular.isDefined(params.filters) ){
            _.each(params.filters, function(value, index){
                if(value != null){
                    $scope.applyFilters(item, index, value, false);
                };
            });
            item.applyFilters(function() {
                $scope.canvas.renderAll()
            });
        }
    };
    $scope.updateUndoRedoStatus = function(){
        $scope.orientationActiveUndoStatus = false;
        $scope.orientationActiveRedoStatus = false;
        if(angular.isDefined($scope.undos[$scope.currentVariant.orientationActive])){ 
            if($scope.undos[$scope.currentVariant.orientationActive].length > 0){
                $scope.orientationActiveUndoStatus = true;
            }
        }      
        if(angular.isDefined($scope.redos[$scope.currentVariant.orientationActive])){ 
            if($scope.redos[$scope.currentVariant.orientationActive].length > 0){
                $scope.orientationActiveRedoStatus = true;
            }
        }      
    }; 
    $scope.getItemById = function(id){
        var len = $scope.canvas.getObjects().length;       
        for (var i = 0; i < len; i++) {
            if($scope.canvas.item(i).get('itemId') == id) return i;
        }        
    };    
    $scope.setElementUpload = function(){
        if ($scope.editableItem == null) return;
        var object = $scope.canvas.item($scope.editableItem);
        if (object.type === "image" || object.type === "custom-image"){
            if(typeof object.elementUpload  === 'undefined'){
                object.set({'elementUpload' : true});
            }else {
                var hasUpload = !object.elementUpload;
                object.set({'elementUpload' : hasUpload});
            }         
            $scope.updatePositionReplaceButton();
        }
        return;
    };
    $scope.deselectAll = function(){
        $scope.canvas.deactivateAll();
        $scope.drawCanvas();
    };
    $scope.updatePositionReplaceButton = function(){    
        if( $scope.editableItem == null ) return;
        var object = $scope.canvas.item($scope.editableItem);
        if( $scope.canvas.getActiveGroup() ) return;
        $('#replace-element-upload').hide();
        if (object.type === "image" || object.type === "custom-image") {
            if(typeof object.elementUpload !== 'undefined'){
                if(object.elementUpload){
                    var left = (object.left + object.width * object.get('scaleX') / 2) * $scope.zoom - 17,
                    top = (object.top + object.height * object.get('scaleY') / 2) * $scope.zoom - 17;
                    if(left < 10) left = 10;
                    if(top < 10) top = 10;
                    left = left + $scope.calcLeft($scope.currentVariant.designArea['area_design_left']);
                    top = top + $scope.calcLeft($scope.currentVariant.designArea['area_design_top']);
                    $('#replace-element-upload').css({
                        left: left + "px",
                        top: top + "px"   
                    }).show();
                }
            }	
        }
        return;
    };
    $scope.preReplaceImage = function(){
        $scope.readyReplaceImage = true;
        $('#dg-myclipart').modal('show');
        //$('#upload-tabs a[href="#uploaded-photo"]').tab("show");
        
    };
    $scope.beforeInitStage = function(data){
        if( angular.isDefined(nbd_window.NBDESIGNERPRODUCT) && angular.isDefined(nbd_window.NBDESIGNERPRODUCT.att_swatch) ){
            var swatch = data.option.swatches[nbd_window.NBDESIGNERPRODUCT.att_swatch];
            angular.forEach(data.product, function(side, sIndex){
                side.bg_color_value = swatch[sIndex].color;
                side.img_src = swatch[sIndex].image;
            });
            $scope.settings.swatch_preview = [];
            angular.forEach(nbd_window.NBDESIGNERPRODUCT.att_swatches, function(swatch, swIndex){
                $scope.settings.swatch_preview.push({i: swatch, s: data.option.swatch_preview[swatch]});
            });
            $scope.settings.product_data.option.swatches = data.option.swatches;
        }
    };
    $scope.initParams = function(){
        _.each(NBDESIGNCONFIG, function(value, index){
            $scope.settings[index] = value;
        }); 
        if( angular.isDefined(NBDESIGNCONFIG['product_data'].option.allow_upload) && NBDESIGNCONFIG['product_data'].option.allow_upload == "1" ){
            $scope.settings.nbdesigner_enable_image = 'yes';
        }
    };
    $scope.init = function() {
        show_indicator();
        $scope.resetCustomDimension();
        $scope.initParams();
        $scope.subsets = NBDESIGNCONFIG['subsets'];
        if( NBDESIGNCONFIG['task'] == 'reup' || NBDESIGNCONFIG['enable_upload_without_design'] == 2 ){
            $scope.designMode = 'upload';
        }
        if (!checkNavigator()) {
            hide_indicator();
            return
        }
        $scope.canvas = canvas;
        $scope.loaded = 0;
        angular.extend(langjs, NBDESIGNLANG['langs']);
        $scope.langs = NBDESIGNLANG['langs'];
        _.each($scope.langs, function(val, key) {
            $scope.langs[key] = val.replace(/\\/g, '');
        });  
        $scope.currentCatFontName = langjs['CAT'];
        $scope.currentCatArtName = langjs['CAT'];
        $scope.langCategories = NBDESIGNLANG['cat'];
        $scope.currentCatLang = NBDESIGNLANG['code']; 
        if( show_left_menu_tooltip ){
            var stop = $interval(function() {
                if( menuLoaded ){
                    initTooltip();
                    $interval.cancel(stop);	
                } 
            }, 10);              
        }else{
            initTooltip();
        }       
        initDialogLang();
        $scope.listFontSizeInPt = ['6','8','10','12','14','16','18','21','24','28','32','36','42','48','56','64','72','80','88','96','104','120','144','288','576','1152'];
        $scope.forceMinSize = true;   
        if( angular.isDefined(NBDESIGNCONFIG.product_data.option.listFontSizeInPt) ){
            if( NBDESIGNCONFIG.product_data.option.listFontSizeInPt != '' ){
                NBDESIGNCONFIG.product_data.option.listFontSizeInPt = NBDESIGNCONFIG.product_data.option.listFontSizeInPt.replace(/ /g, '');
                $scope.listFontSizeInPt = NBDESIGNCONFIG.product_data.option.listFontSizeInPt.split(',');
            }
        };        
        if(NBDESIGNCONFIG['nbdesigner_dimensions_unit'] == 'mm'){
            $scope.rateConvertCm2Px96dpi = $scope.rateConvertCm2Px96dpi * 0.1;
        }else if(NBDESIGNCONFIG['nbdesigner_dimensions_unit'] == 'in'){
            $scope.rateConvertCm2Px96dpi = $scope.rateConvertCm2Px96dpi * 2.54;
        }        
        $scope.initStage(NBDESIGNCONFIG['product_data']);
        if( NBDESIGNCONFIG["product_data"].config == null || angular.isUndefined( NBDESIGNCONFIG['product_data'].config) || angular.isUndefined( NBDESIGNCONFIG['product_data'].config.initNoPage ) ){
            $scope.initNoPage = NBDESIGNCONFIG['product_data'].product.length;
        }else if(angular.isDefined(NBDESIGNCONFIG["product_data"].config.initNoPage)){
            $scope.initNoPage = NBDESIGNCONFIG['product_data'].config.initNoPage;
        }
        if(toType(NBDESIGNCONFIG['list_file_upload']) == 'array'){
            $scope.listFileUpload = NBDESIGNCONFIG['list_file_upload'];
        }
        $scope.initBrushes();
        var log = "c"+"o"+"n"+"s"+"o"+"l"+"e.i"+"n"+"f"+"o('%cP"+"o"+"we"+"r"+"e"+"d b"+"y %cN"+"E"+"T%cB"+"A"+"S"+"E%cT"+"E"+"A"+"M', 'color: orange; font-size: 20px;', 'color: red; font-size: 40px;', 'color: green; font-size: 40px;', 'color: #F48024; font-size: 40px;')";
        eval(log);
        if (checkFireFox() || (Check_IE_Version() > 0)) jQuery("input.jscolor").removeAttr("disabled");
    };
    $scope.init();
    $scope.changeSwatch = function( swatch_val ){
        swatch_val = swatch_val ? swatch_val : nbd_window.NBDESIGNERPRODUCT.att_swatch;
        var swatch = [];
        angular.copy(NBDESIGNCONFIG.product_data.option.swatches[swatch_val], swatch);
        if($scope.settings.ui_mode == 1){
            nbd_window.postMessage("change_nbd_swatch---"+swatch_val, window.location.origin);
        }
        if ($scope.$root.$$phase !== "$apply" && $scope.$root.$$phase !== "$digest") $scope.$apply();
        $scope.changeOrientation($scope.currentVariant.info[0]);
    };
    $scope.debug = function() {
//        var svg = canvas.toSVG()
//            var filename = 'text.txt',
//            a = document.createElement('a');
//            a.setAttribute('href', 'data:image/svg+xml;charset=utf-8,' + svg);
//            a.setAttribute('download', filename);
//            a.click() 
//       console.log($scope.canvas.toSVG());
//       console.log($scope.canvases);
//console.log($scope.canvas.getObjects());
//console.log($scope.canvas.getActiveObject().getTop());
//console.log($scope.canvas.getActiveObject().getHeight());
//$scope.canvas.getActiveObject().set({'radius': 100});
$scope.fitWithDesignArea();
//console.log($scope.canvas.getActiveObject());
    };
    $scope.changeBackgroundId = function(n){
        $('body').css('background-image', "url(" +NBDESIGNCONFIG['assets_url'] + 'images/background/' + n + '.png' + ")");
        $scope.backgroundId = n;
    };
    $scope.removeBackgroundImage = function(){
        $('body').css('background-image', "none");
    };
    $scope.changeVariation = function(){
        var variation_id = jQuery('input[name="variation_id"]').val();
        if( NBDESIGNCONFIG['variation_id'] == variation_id ){
            jQuery('#dg-product-info').modal('hide');
            return;
        }
        if(!$scope.onLoadProduct && variation_id != ''){
            NBDESIGNCONFIG['variation_id'] = variation_id;
            $scope.loaded = 0;
            $scope.onLoadProduct = true;
            show_indicator();
            $scope.canvas.clear();
            $scope.flagChangeOrientation = [];
            $scope.loadProduct('');             
        }
        if( variation_id == '' ) {
            alert(langjs['PLEASE_CHOOSE_ALL_OPTION']);
        }
    };
    $scope.cancelChangeVariation = function(){
        jQuery('#dg-product-info').modal('hide');
    };
    $scope.loadProductDescription = function( $event, product ){
        var el = jQuery($event.currentTarget);
        el.removeClass('active');
        el.parent().find('.fa-spinner').addClass('active');
        jQuery('#design-container').addClass('nbd-disable-event');
	ProductService.getProductDescription( product.product_id ).then(function(data) {
            if( data.product_id ){
                jQuery('#design-container').removeClass('nbd-disable-event');
                el.addClass('active');
                el.parent().find('.fa-spinner').removeClass('active');
                jQuery('#product-info-preview-wrap-inner').html(data.html);
                $scope.currentPreviewProduct = {
                    'type'  :  data.type,
                    'product_id'  :  data.product_id
                }            
                jQuery('#dg-product-info-preview').modal("show");
            }else{
                alert( 'Opps! Try again later!' );
            }
        })        
    };
    $scope.state = "pub";
    window.scope = $scope
});
angular.module("app").factory("ArtService", function($http) {
    return {
        fn: function(callback) {
            if ($("#loading_art_upload").hasClass("hidden")) $("#loading_art_upload").removeClass("hidden");
            $http({
                method: "POST",
                url: NBDESIGNCONFIG['ajax_url'],
                params: {
                    action: "nbdesigner_get_art",
                    nonce: NBDESIGNCONFIG['nonce_get']
                }
            }).success(function(data, status, headers, config) {
                callback(data);
                if (!$("#loading_art_upload").hasClass("hidden")) $("#loading_art_upload").addClass("hidden")
            }).error(function(data, status,
                headers, config) {
                alert("Error! Try again!");
                if (!$("#loading_art_upload").hasClass("hidden")) $("#loading_art_upload").addClass("hidden")
            })
        }
    }
});
angular.module("app").factory("FontService", function($http) {
    return {
        fn: function(callback) {
            if ($("#loading_font_upload").hasClass("hidden")) $("#loading_font_upload").removeClass("hidden");
            $http({
                method: "POST",
                url: NBDESIGNCONFIG['ajax_url'],
                params: {
                    action: "nbdesigner_get_font",
                    nonce: NBDESIGNCONFIG['nonce_get']
                }
            }).success(function(data, status, headers, config) {
                callback(data);
                if (!$("#loading_font_upload").hasClass("hidden")) $("#loading_font_upload").addClass("hidden")
            }).error(function(data,
                status, headers, config) {
                alert("Error! Try again!");
                if (!$("#loading_font_upload").hasClass("hidden")) $("#loading_font_upload").addClass("hidden")
            })
        }
    }
});
angular.module("app").directive("fontOnLoading", ['$interval', function($interval) {
    return {
        restrict: "A",
        scope: {
            font: '=font',
            preview: '=preview',
            loading: '@loading'
        },
        link: function(scope, element) {
            var fontName = scope.font.alias,
                fontType = scope.font.type;
            var font_id = fontName.replace(/\s/gi, '').toLowerCase();
            if( !jQuery('#' + font_id).length ){
                if(fontType == 'google'){
                    jQuery('head').append('<link id="' + font_id + '" href="https://fonts.googleapis.com/css?family='+ fontName.replace(/\s/gi, '+') +':400,400i,700,700i" rel="stylesheet" type="text/css">');
                }else{
                    var font_url = scope.font.url;
                    if(! (scope.font.url.indexOf("http") > -1)) font_url = NBDESIGNCONFIG['font_url'] + scope.font.url; 
                    var type = fontType.toLowerCase() == "ttf" ? "truetype" : 'woff';
                    var css = "";
                    css = "<style type='text/css' id='" + font_id + "' >";
                    css += "@font-face {font-family: '" + fontName + "';";
                    css += "src: local('\u263a'),";
                    css += "url('" + font_url + "') format('" + type + "')";
                    css += "}";
                    css += "</style>";
                    jQuery("head").append(css)                    
                }
            }
            var font = new FontFaceObserver(fontName);             
            font.load(scope.preview).then(function () {
                element.find(".font-loading").remove();
                element.find(".font-preview").show();
                element.parents('.gg-font-preview').removeClass('disable');
            }, function () {
                console.log('Font '+fontName+' is not available');
            }); 
            element.append('<span class="font-loading">'+scope.loading+'</span>')
        }
    }
}]);
angular.module("app").factory("PatternService", function($q, $http) {
    return {
        fn: function(callback) {
            if ($("#loading_pattern").hasClass("hidden")) $("#loading_pattern").removeClass("hidden");
            $http({
                method: "POST",
                url: NBDESIGNCONFIG['ajax_url'],
                params: {
                    action: "nbdesigner_get_pattern",
                    nonce: NBDESIGNCONFIG['nonce_get']
                }
            }).success(function(data, status, headers, config) {
                callback(data);
                if (!$("#loading_pattern").hasClass("hidden")) $("#loading_pattern").addClass("hidden")
            }).error(function(data, status, headers, config) {
                alert("Error! Try again!");
                if (!$("#loading_pattern").hasClass("hidden")) $("#loading_pattern").addClass("hidden")
            })
        }
    }
});
angular.module("app").service("PriceService", function() {});
angular.module("app").service("ProductService", function($http, $q) {
    this.getProduct = function(template_id) {
        var deferred = $q.defer();
        var data = "action=nbdesigner_get_product_info&nonce=" + NBDESIGNCONFIG['nonce'] + "&product_id=" + NBDESIGNCONFIG['product_id'] + '&variation_id=' + NBDESIGNCONFIG['variation_id'] + '&task=' + NBDESIGNCONFIG['task'] + '&attach_product_info=' + attachProductInfo + '&product_type=' + NBDESIGNCONFIG['product_type'];
        if( template_id != '' ) data += '&template_id=' + template_id;
        $http({
            url: NBDESIGNCONFIG['ajax_url'],
            method: "POST",
            data:     data,
            headers: {
                "Content-Type": "application/x-www-form-urlencoded",
                "Cache-Control" : "no-cache"
            }
        }).success(function(data, status, headers, config) {
            deferred.resolve(data)
        }).error(function(data, status, headers, config) {
            deferred.reject(data)
        });
        return deferred.promise
    };
    this.getListProducts = function(){
        var deferred = $q.defer();
        var data = "action=nbd_get_nbd_products&nonce=" + NBDESIGNCONFIG['nonce'];
        $http({
            url: NBDESIGNCONFIG['ajax_url'],
            method: "POST",
            data:     data,
            headers: {
                "Content-Type": "application/x-www-form-urlencoded",
                "Cache-Control" : "no-cache"
            }            
        }).success(function(data, status, headers, config) {
            deferred.resolve(data)
        }).error(function(data, status, headers, config) {
            deferred.reject(data)
        });
        return deferred.promise
    };
    this.getVariationForm = function(){
        var deferred = $q.defer();
        var data = "action=nbd_get_variation_form&nonce=" + NBDESIGNCONFIG['nonce'] + '&product_id=' + NBDESIGNCONFIG['product_id'] + '&variation_id=' + NBDESIGNCONFIG['variation_id'];
        $http({
            url: NBDESIGNCONFIG['ajax_url'],
            method: "POST",
            data:     data,
            headers: {
                "Content-Type": "application/x-www-form-urlencoded",
                "Cache-Control" : "no-cache"
            }            
        }).success(function(data, status, headers, config) {
            deferred.resolve(data)
        }).error(function(data, status, headers, config) {
            deferred.reject(data)
        });
        return deferred.promise        
    };
    this.getProductDescription = function( product_id ){
        var deferred = $q.defer();
        var data = "action=nbd_get_product_description&nonce=" + NBDESIGNCONFIG['nonce'] + '&product_id=' + product_id;
        $http({
            url: NBDESIGNCONFIG['ajax_url'],
            method: "POST",
            data:     data,
            headers: {
                "Content-Type": "application/x-www-form-urlencoded",
                "Cache-Control" : "no-cache"
            }            
        }).success(function(data, status, headers, config) {
            deferred.resolve(data)
        }).error(function(data, status, headers, config) {
            deferred.reject(data)
        });
        return deferred.promise        
    };    
});
angular.module("app").factory("QrcodeService", function($http) {
    return {
        fn: function(data, callback) {
            $("#loading_qrcode").removeClass("hidden");
            $http({
                method: "POST",
                url: NBDESIGNCONFIG['ajax_url'],
                params: {
                    data: data,
                    action: "nbdesigner_get_qrcode",
                    nonce: NBDESIGNCONFIG['nonce']
                }
            }).success(function(data, status, headers, config) {
                callback(data);
                $("#loading_qrcode").addClass("hidden")
            }).error(function(data, status, headers, config) {
                $("#loading_qrcode").addClass("hidden");
                alert("Error! Try again!")
            })
        }
    }
});
angular.module("app").service("LanguageService", function($http, $q) {
    this.getLang = function(code) {
        var deferred = $q.defer();
        $http({
            url: NBDESIGNCONFIG['ajax_url'],
            method: "POST",
            data: "action=nbdesigner_get_language&nonce=" + NBDESIGNCONFIG['nonce'] + "&code=" + code ,
            headers: {
                "Content-Type": "application/x-www-form-urlencoded"
            }            
        }).success(function(data, status, headers, config) {
            deferred.resolve(data)
        }).error(function(data, status, headers, config) {
            deferred.reject(data)
        });
        return deferred.promise;
    };   
});
angular.module("app").service("AdminTemplateService", function($http, $q) {
    this.getDesign = function() {
        var deferred = $q.defer();
        $http({
            url: NBDESIGNCONFIG['ajax_url'],
            method: "POST",
            data: "action=nbdesigner_load_admin_design&nonce=" + NBDESIGNCONFIG['nonce'] + "&product_id=" + NBDESIGNCONFIG['product_id'] + "&variation_id=" + NBDESIGNCONFIG['variation_id'],
            headers: {
                "Content-Type": "application/x-www-form-urlencoded"
            }            
        }).success(function(data, status, headers, config) {
            deferred.resolve(data)
        }).error(function(data, status, headers, config) {
            deferred.reject(data)
        });
        return deferred.promise;
    };   
});
angular.module("app").service("CartDesignsService", function($http, $q) {
    this.getDesign = function( id ) {
        var deferred = $q.defer();
        var data = "action=nbd_get_designs_in_cart&nonce=" + NBDESIGNCONFIG['nonce'];
        if( id != undefined ) data += '&did=' + id;
        $http({
            url: NBDESIGNCONFIG['ajax_url'],
            method: "POST",
            data: data,
            headers: {
                "Content-Type": "application/x-www-form-urlencoded"
            }            
        }).success(function(data, status, headers, config) {
            deferred.resolve(data)
        }).error(function(data, status, headers, config) {
            deferred.reject(data)
        });
        return deferred.promise;
    };   
});
angular.module("app").service("UserDesignsService", function($http, $q) {
    this.getDesign = function(id) {
        var deferred = $q.defer();
        var data = "action=nbd_get_user_designs&nonce=" + NBDESIGNCONFIG['nonce'];
        if(id != undefined) data += '&did=' + id;
        $http({
            url: NBDESIGNCONFIG['ajax_url'],
            method: "POST",
            data: data,
            headers: {
                "Content-Type": "application/x-www-form-urlencoded"
            }            
        }).success(function(data, status, headers, config) {
            deferred.resolve(data)
        }).error(function(data, status, headers, config) {
            deferred.reject(data)
        });
        return deferred.promise;
    };   
});
var NBDESIGNERCART = {
    build_form: function(data_img, data_json, fonts, config, action, svgs){
        if( NBDESIGNCONFIG['enable_upload_without_design'] == 1 ){
            var design_blob = new Blob([JSON.stringify(data_json)], {type: "application/json"}),
            config_blob = new Blob([JSON.stringify(config)], {type: "application/json"}),
            font_blob = new Blob([JSON.stringify(fonts)], {type: "application/json"}); 
        }
        var fd = new FormData();
        fd.append('action', action);
        fd.append('nonce', NBDESIGNCONFIG['nonce']);
        fd.append('product_id', NBDESIGNCONFIG['product_id']);
        fd.append('variation_id', NBDESIGNCONFIG['variation_id']);
        fd.append('task', NBDESIGNCONFIG['task']);         
        fd.append('task2', NBDESIGNCONFIG['task2']);         
        fd.append('design_type', NBDESIGNCONFIG['design_type']); 
        fd.append('nbd_item_key', NBDESIGNCONFIG['nbd_item_key']);           
        fd.append('nbu_item_key', NBDESIGNCONFIG['nbu_item_key']);           
        fd.append('cart_item_key', NBDESIGNCONFIG['cart_item_key']);           
        fd.append('order_id', NBDESIGNCONFIG['order_id']);           
        fd.append('enable_upload_without_design', NBDESIGNCONFIG['enable_upload_without_design']);           
        fd.append('auto_add_to_cart', NBDESIGNCONFIG['nbdesigner_auto_add_cart_in_detail_page']); 
        if( angular.isDefined(nbd_window.NBDESIGNERPRODUCT) && angular.isDefined(nbd_window.NBDESIGNERPRODUCT.att_swatch) ){
            fd.append('att_swatch', nbd_window.NBDESIGNERPRODUCT.att_swatch);
        }
        if( NBDESIGNCONFIG['enable_upload_without_design'] == 1 ){
            fd.append('used_font', font_blob);      
            fd.append('config', config_blob);              
            fd.append('design', design_blob);      
            _.each(data_img, function(val, key) {
                fd.append(key, makeblob(val));     
            });  
            _.each(svgs, function(val, key) {
                var svg = new Blob([val], {type: "image/svg"});   
                fd.append(key + '_svg', svg);     
            });     
        }
        return fd;
    },
    save_design : function(data_img, data_json, fonts, config, svgs){
        show_indicator(); 
        var action = 'nbd_save_customer_design';
        var fd = this.build_form(data_img, data_json, fonts, config, action, svgs);
        jQuery.ajax({
            url: NBDESIGNCONFIG['ajax_url'],
            method: "POST",   
            processData: false,
            contentType: false,                
            data: fd
        }).done(function(data){
            var _data = JSON.parse(data);
            if (_data.flag == "success") {
                if(NBDESIGNCONFIG['redirect_url'] != ""){
                    window.location = NBDESIGNCONFIG['redirect_url'];
                    return;
                }
                if( NBDESIGNCONFIG['ui_mode'] == "1" ){
                    if( NBDESIGNCONFIG['nbdesigner_auto_add_cart_in_detail_page'] == "yes" && _data.added == 1 ){
                        jQuery('#design-container').addClass('nbd-prevent-events');
                        nbd_window.location = NBDESIGNCONFIG['cart_url'];
                    }else{
                        nbd_window.NBDESIGNERPRODUCT.product_id = NBDESIGNCONFIG['product_id'];
                        nbd_window.NBDESIGNERPRODUCT.variation_id = NBDESIGNCONFIG['variation_id'];             
                        nbd_window.NBDESIGNERPRODUCT.folder = _data.folder;
                        nbd_window.NBDESIGNERPRODUCT.show_design_thumbnail(_data.image, NBDESIGNCONFIG['task']);
                        nbd_window.NBDESIGNERPRODUCT.get_sugget_design(NBDESIGNCONFIG['product_id'], NBDESIGNCONFIG['variation_id']);                        
                    }
                }
            } else {
                alert(_data.mes);
                //alert("Something wrong! Please try again...");
            }
            hide_indicator()
        });         
    },
    save_cart : function(data_img, data_json, fonts, config, files, svgs){
        show_indicator(); 
        var action = 'nbd_save_cart_design';
        var fd = this.build_form(data_img, data_json, fonts, config, action, svgs);
        fd.append('nbd_file', files);  
        jQuery.ajax({
            url: NBDESIGNCONFIG['ajax_url'],
            method: "POST",   
            processData: false,
            contentType: false,                
            data: fd
        }).done(function(data){
            var _data = JSON.parse(data);
            if (_data.flag == "success") {
                jQuery('#info').addClass('disable');
                if( NBDESIGNCONFIG.task2 == 'cuz' ) {
                    window.location = NBDESIGNCONFIG['redirect_url'];
                    return;
                }
                window.location = NBDESIGNCONFIG['cart_url'];
            } else {
                alert(_data.mes);
            }
            hide_indicator()
        });          
    }
};
var makeblob = function (dataURL) { 
    var BASE64_MARKER = ';base64,';
    if (dataURL.indexOf(BASE64_MARKER) == -1) {
        var parts = dataURL.split(',');
        var contentType = parts[0].split(':')[1];
        var raw = decodeURIComponent(parts[1]);
        return new Blob([raw], { type: contentType });
    }
    var parts = dataURL.split(BASE64_MARKER);
    var contentType = parts[0].split(':')[1];
    var raw = window.atob(parts[1]);
    var rawLength = raw.length;
    var uInt8Array = new Uint8Array(rawLength);
    for (var i = 0; i < rawLength; ++i) {
        uInt8Array[i] = raw.charCodeAt(i);
    }
    return new Blob([uInt8Array], { type: contentType });
}
var nbdesigner_fb1 = function() {
    $("#loading_fb_upload").removeClass("hidden");
    FB.getLoginStatus(function(response) {
        if (response.status === "connected") {
            var uid = response.authResponse.userID;
            var accessToken = response.authResponse.accessToken;
            var next = $("#nbdesigner_fb_next").val();
            if (next == "") var photo_json = "https://graph.facebook.com/" + uid + "/photos/uploaded/?limit=5&fields=source,images,link&access_token=" + accessToken;
            else photo_json = next;
            $.getJSON(photo_json, function() {
                console.log("Get album success!")
            }).done(function(data) {
                var photos = data.data;
                var html = "";
                $.each(photos, function(key, val) {
                    var src = "";
                    if (val.images) src = val.images[0].source;
                    else src = val.source;
                    html += '<img class="img-responsive img-thumbnail nbdesigner_upload_image shadow hover-shadow" data-url="" onclick="NBDESIGNERFUNC.addFacebookImage(\'' + src + '\', this)" src="' + src + '" />'
                });
                $("#uploaded-facebook").prepend(html);
                if (data.paging.next) {
                    $("#nbdesigner_fb_next").val(data.paging.next);
                    if ($("#facebook-load-more").hasClass("hidden")) $("#facebook-load-more").removeClass("hidden")
                } else {
                    $("#nbdesigner_fb_next").val("");
                    if (!$("#facebook-load-more").hasClass("hidden")) $("#facebook-load-more").addClass("hidden")
                }
                if (!$("#loading_fb_upload").hasClass("hidden")) $("#loading_fb_upload").addClass("hidden")
            }).fail(function() {
                if (!$("#loading_fb_upload").hasClass("hidden")) $("#loading_fb_upload").addClass("hidden")
            }).always(function() {
                if (!$("#loading_fb_upload").hasClass("hidden")) $("#loading_fb_upload").addClass("hidden")
            })
        }
    })
};
var NBDESIGNERFUNC = {
    addFacebookImage: function(url, e) {
        var _url = jQuery(e).attr('data-url');   
        var sefl = jQuery(e);
        var scope = angular.element(document.getElementById("designer-controller")).scope();       
        if(_url != ''){
            scope.addImage(_url)
        }else{
            show_indicator();
            jQuery.ajax({
                url: NBDESIGNCONFIG['ajax_url'],
                method: "POST",
                data: {
                    "action": "nbdesigner_copy_image_from_url",
                    "nonce": NBDESIGNCONFIG['nonce'],
                    "url": url
                }
            }).done(function(data) {
                data = JSON.parse(data);
                if(data['flag'] == 1){
                    sefl.attr('data-url', data['src']);
                    scope.addImage(data['src'])
                }else{
                    alert('Try to download image and then upload to our server!');
                    jQuery('#upload-tabs a[href="#upload-computer"]').tab("show");
                }
                hide_indicator()
            });             
        }       
        if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
    },
    addQrImage: function(url) {
        var scope = angular.element(document.getElementById("designer-controller")).scope();
        scope.addImage(url);
        scope.disableDrawMode();
        if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
    },
    debug : function(){
//        jQuery.ajax({
//            url: NBDESIGNCONFIG['ajax_url'],
//            method: "POST",
//            data : {
//                action: "nbdesigner_get_product_info",
//                nonce: NBDESIGNCONFIG['nonce'],
//                id: NBDESIGNCONFIG['product_id']
//            }            
//        }).done(function(data) {
//            console.log(JSON.parse(data));
//        });   
        
    }
};
angular.module("app").filter("reverse", function() {
    return function(items) {
        if (!angular.isArray(items)) return items;
        return items.slice().reverse()
    }
}).filter("startFrom", function() {
    return function(input, start) {
        start = +start;
        return input.slice(start)
    }
}).filter("filterCat", function() {
    return function(input, cat_id) {
        var output = [];
        _.each(input, function(val, key) {
            if (!val.cat) val.cat = ["99"];
            if (val.cat.length == 0) val.cat = ["0"];
            if ($.inArray(cat_id, val.cat) >= 0) output.push(val)
        });
        return output
    }
}).filter("filterName", function() {
    return function(input, name) {
        if( name == '' || name == undefined ) return input;
        var output = [];
        _.each(input, function(val, key) {
            if( val.name.toLowerCase().indexOf(name) > -1 ) {
                output.push(val)
            }
        });
        return output
    }
}).filter("range",function(){
  return function(input, total) {
    total = parseInt(total);
    for (var i=0; i<total; i++) {
      input.push(i);
    }
    return input;
  };
});
angular.module("app").directive("owlCarousel", function() {
    return {
        restrict: "E",
        transclude: false,
        link: function(scope) {
            scope.initCarousel = function(element) {
                var defaultOptions = {};
                var customOptions = scope.$eval($(element).attr("data-options"));
                for (var key in customOptions) defaultOptions[key] = customOptions[key];
                $(element).owlCarousel(defaultOptions)
            }
        }
    }
}).directive("owlCarouselItem", [function() {
    return {
        restrict: "A",
        transclude: false,
        link: function(scope, element) {
            if (scope.$last) scope.initCarousel(element.parent())
        }
    }
}]).directive("pathArtDirective", [function() {
    return function(scope, element, attrs) {
        if (scope.$last) {
            jscolor.installByClassName("jscolor");
            if (checkFireFox() || (Check_IE_Version() > 0)) jQuery("input.jscolor").removeAttr("disabled")
        }
    }
}]);
jQuery(document).ready(function($){
    //nbd_window.jQuery('.variations_form.cart').on('change', function(){
    nbd_window.jQuery('input[name="variation_id"]').on('change', function(){
        if( NBDESIGNCONFIG['ui_mode'] == 1 ){
            var variation_id = nbd_window.jQuery('input[name="variation_id"]').val();
            if(NBDESIGNCONFIG['variation_id'] == variation_id) return;
            var scope = angular.element(document.getElementById("designer-controller")).scope();
            if(variation_id != ''){
                nbd_window.NBDESIGNERPRODUCT.nbdesigner_unready();
                if(NBDESIGNCONFIG['nbdesigner_hide_button_cart_in_detail_page'] == 'yes'){
                    nbd_window.jQuery('button[type="submit"].single_add_to_cart_button').hide();
                }
            }
            NBDESIGNCONFIG['variation_id'] = variation_id;
            if(!scope.onLoadProduct && variation_id != ''){
                scope.loaded = 0;
                scope.onLoadProduct = true;
                show_indicator();
                scope.canvas.clear();
                scope.flagChangeOrientation = [];
                scope.loadProduct('');              
            }      
            if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
        }
    });
    nbd_window.jQuery('.reset_variations').on('click', function(){
        if( NBDESIGNCONFIG['ui_mode'] == 1 ){
            var scope = angular.element(document.getElementById("designer-controller")).scope();
            nbd_window.NBDESIGNERPRODUCT.nbdesigner_unready();
            if(NBDESIGNCONFIG['nbdesigner_hide_button_cart_in_detail_page'] == 'yes'){
                nbd_window.jQuery('button[type="submit"].single_add_to_cart_button').hide();
            }      
            NBDESIGNCONFIG['variation_id'] = NBDESIGNCONFIG['default_variation_id'];
            if(!scope.onLoadProduct){
                scope.loaded = 0;
                scope.onLoadProduct = true;
                show_indicator();
                scope.canvas.clear();
                scope.flagChangeOrientation = [];
                scope.loadProduct('');              
            }      
            if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
        }
    });     
    $('html').on('click', function(e){
        if(e.target.id != 'nbd-viewport') return;
        var scope = angular.element(document.getElementById("designer-controller")).scope();
        scope.deselectAll();
        if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
    });
    $(document).bind('keydown', function(e) {
        var scope = angular.element(document.getElementById("designer-controller")).scope();
        var object = scope.canvas.getActiveObject();
        var $target = $(e.target);   
        if(e.shiftKey){
            scope.holdShiftKey = true;
        }else{
            scope.holdShiftKey = false;
        }
        switch(e.which) {
            case 37:
                if (object == null || $target.is('textarea,input[type="text"],input[type="number"]')) return;
                if(! object.get("lockMovementX")) {
                    scope.ShiftLeft();
                }
                break;
            case 39:
                if (object == null || $target.is('textarea,input[type="text"],input[type="number"]')) return;
                if(! object.get("lockMovementX")) {
                    scope.ShiftRight();
                }
                break;   
            case 38:
                if (object == null || $target.is('textarea,input[type="text"],input[type="number"]')) return;
                if(! object.get("lockMovementY")) {
                    scope.ShiftUp();
                }
                break;  
            case 40:
                if (object == null || $target.is('textarea,input[type="text"],input[type="number"]')) return;
                if(! object.get("lockMovementY")) {
                    scope.ShiftDown();
                }
                break;    
            case 46:
                if (object == null || $target.is('textarea,input[type="text"],input[type="number"]')) return;                
                deleteObject(scope.editableItem);
                break; 
            case 67:
                if (object == null || $target.is('textarea,input[type="text"],input[type="number"]')) return;                
                if(e.ctrlKey){
                    scope.duplicateItem();
                }
                break;             
            case 90:
                if(e.ctrlKey){
                    scope.undoDesign();
                }
                break;  
            case 89:
                if(e.ctrlKey){
                    scope.redoDesign();
                }
                break;               
            case 107:
                if (object == null || $target.is('textarea,input[type="text"],input[type="number"]')) return;             
                if(e.shiftKey){
                    scope.scaleItem("+");
                }                
                break; 
            case 109:
                if (object == null || $target.is('textarea,input[type="text"],input[type="number"]')) return;             
                if(e.shiftKey){
                    scope.scaleItem("-");
                }  
                break;   
            case 27:
                scope.canvas.isDrawingMode = false;
                break;   
            default: return; 
        }
        if (scope.$root.$$phase !== "$apply" && scope.$root.$$phase !== "$digest") scope.$apply()
    }); 
    $('#dg-myclipart').on('hidden.bs.modal', function () {
        var scope = angular.element(document.getElementById("designer-controller")).scope();
        scope.readyReplaceImage = false;
    })    
});
initTooltip = function(){
    jQuery('.nbd-tooltip-i18n').each( function(){
        var key = jQuery(this).data("lang"),
        title = langjs[key];
        jQuery(this).tooltip( "destroy" );   
        jQuery(this).tooltip({ 
            trigger: "hover",
            title : title,
            container : "body"
        }).on('click', function(){
            jQuery(this).tooltip('hide');
        })   
        /* ticket: #5a1fa99a85e99de379a478a4 */
        if( show_left_menu_tooltip ){
            var sefl = jQuery(this);
            var key = sefl.data("lang"),
            title = langjs[key];
            if( key == 'ADD_TEXT' || key == 'ADD_CLIPART' || key == 'ADD_IMAGE' || key == 'FREE_DRAW' || key == 'ADD_QRCODE' || key == 'TEMPLATE' ){
                sefl.tooltip( "destroy" );   
                sefl.tooltip({ 
                    trigger: "manual",
                    title : title,
                    container : "body"
                }).tooltip('show');                        
            }     
        }         
    })      
};
destroyTooltipFrame = function(){
    jQuery('.nbd-tooltip-frame').each( function(){
        jQuery(this).tooltip( "destroy" );       
    })    
};
initTooltipFrame = function(){
    jQuery('.nbd-tooltip-frame').each( function(){
        var title = jQuery(this).data("lang");
        jQuery(this).tooltip({ 
            trigger: "hover",
            title : title,
            container : "body"
        }).on('click', function(){
            $(this).tooltip('hide');
        });          
    })
};
initDialogLang = function(){
    $.confirm.options = {
        title: "",
        confirmButtonClass: "btn-primary",
        confirmButton: langjs['YES'],
        cancelButton: langjs['CANCEL']
    };
};
window.onbeforeunload = function() {
    //todo
};