UNPKG

jquery-meme-generator

Version:

Meme Generator is a jQuery plugin allowing easily creating images with captions (memes) using interactive editor.

1,114 lines (884 loc) 33.1 kB
/* * Author: Maciej Gierej * https://github.com/MakG10/jquery-memegenerator */ (function($){ var i18n = { topTextPlaceholder: "TOP TEXT", bottomTextPlaceholder: "BOTTOM TEXT", addTextbox: "Add Textbox", advancedSettings: "Advanced Settings", toolbox: "Toolbox", optionCapitalLetters: "Use only capital letters", optionDragResize: "Enable dragging and resizing textboxes", optionDrawingAboveText: "Show drawing above text", drawingStart: "Draw", drawingStop: "Stop drawing", drawingErase: "Erase", }; var MemeGenerator = function(element, options){ var MG = this; this.settings = $.extend(true, {}, { defaultTextStyle: { color: "#FFFFFF", size: 42, lineHeight: 1.2, font: "Impact, Arial", style: "normal", forceUppercase: true, borderColor: "#000000", borderWidth: 2, }, defaultDrawingStyle: { color: "#FF0000", lineWidth: 10, }, minFontSize: 1, maxFontSize: 128, minBorderWidth: 0, maxBorderWidth: 10, fontSizeStep: 1, borderWidthStep: 1, captions: [], previewMode: "canvas", // css, canvas outputFormat: "image/png", editingEnabled: true, dragResizeEnabled: true, drawingAboveText: true, showAdvancedSettings: true, colorPicker: null, wrapperClass: "mg-wrapper", toolboxSelector: null, layout: "vertical", useBootstrap: false, useWordpressStyle: false, // Events onLayerChange: function(layerName){ return true; }, onNewTextBox: function(textBox){ return true; }, onInit: function(){ return true; } }, options); // Options possible to be overwritten by user this.userSettings = { forceUppercase: MG.settings.defaultTextStyle.forceUppercase, dragResizeEnabled: MG.settings.dragResizeEnabled, drawingAboveText: MG.settings.drawingAboveText, }; this.element = element; this.wrapper = null; this.canvasContainer = null; this.helpersContainer = null; this.canvasLayers = []; this.originalSize = []; this.scale = 1.0; this.initialized = false; // =============== // PUBLIC METHODS // =============== this.save = function(){ return MG.canvas.save().toDataURL(MG.settings.outputFormat); }; this.saveCanvas = function(){ return MG.canvas.save(); }; this.download = function(filename){ if(typeof filename === 'undefined') filename = 'image.png'; var downloadLink = $("<a></a>").attr("href", this.save()).attr("download", filename).appendTo(MG.wrapper); downloadLink[0].click(); downloadLink.remove(); }; this.serialize = function(){ return JSON.stringify(MG.getLayersData()); }; this.deserialize = function(json){ var layers = JSON.parse(json); var newLayers = []; MG.canvasLayers.forEach(function(layerName, index) { var layer = MG.wrapper.find("[data-layer='" + layerName + "']"); if(MG.getLayerType(layer)) { layer.remove(); var helper = MG.wrapper.find("[data-target-layer='" + layerName + "']"); helper.remove(); return; } newLayers.push(layerName); }); MG.canvasLayers = newLayers; layers.reverse().forEach(function(layer){ if(layer.type == 'text') { MG.ui.createTextBox("", null, layer).prependTo(MG.wrapper.find('.mg-controls')); } }); MG.events.onLayerChange(); }; this.destroy = function(){ this.element.insertAfter(this.wrapper); this.element.off('load.mg'); this.wrapper.remove(); }; // =============== // PRIVATE METHODS // =============== this.init = function(){ element.wrap('<div class="mg-wrapper"><div class="mg-image"></div></div>'); MG.wrapper = element.parent().parent(); MG.canvasContainer = $('<div class="mg-canvas"></div>').appendTo(MG.wrapper.find("> .mg-image")); MG.helpersContainer = $('<div class="mg-helpers"></div>').appendTo(MG.wrapper.find("> .mg-image")); if(MG.settings.layout == "horizontal") MG.wrapper.addClass("mg-horizontal-layout"); if(MG.settings.previewMode == "css") MG.cssPreview.enable(); $("<img>") .attr("src", element.attr("src")) .on('load', function(){ MG.originalSize[0] = this.width; MG.originalSize[1] = this.height; MG.scale = element.width() / MG.originalSize[0]; if(MG.settings.editingEnabled) { MG.wrapper.append(MG.ui.createControls()); } // Set default captions if any MG.settings.captions.forEach(function(caption, index){ var textbox = MG.wrapper.find(".mg-textbox-text").eq(index); if(textbox.length == 0) { textbox = MG.ui.createTextBox("", "center center").insertAfter(MG.wrapper.find(".mg-controls .mg-textbox").last()).find(".mg-textbox-text"); } if(MG.userSettings.forceUppercase) { caption = MG.ui._strtoupper(caption); } textbox.attr("value", caption); textbox.attr("data-text", caption); textbox.trigger("change"); }); if(MG.settings.useBootstrap) { MG.ui.bootstrapify(); } else if(MG.settings.useWordpressStyle) { MG.ui.wordpressify(); } MG.initialized = true; MG.settings.onInit.call(MG); }); $(window).on("resize", function(){ MG.scale = element.width() / MG.originalSize[0]; MG.events.onLayerChange(); }); // Handling change of the src attribute element.on('load.mg', function(){ if(!MG.initialized) return; MG.originalSize[0] = this.width; MG.originalSize[1] = this.height; MG.scale = element.width() / MG.originalSize[0]; MG.ui.resizeHelpers(); MG.events.onLayerChange(); }); }; this.ui = { createControls: function(){ var controls = $('<div class="mg-controls"></div>'); controls.append(MG.ui.createTextBox(i18n.topTextPlaceholder, "top center")); controls.append(MG.ui.createTextBox(i18n.bottomTextPlaceholder, "bottom center")); // Add extra textbox button var addTextboxButton = $('<a href="#" class="mg-add-textbox">' + i18n.addTextbox + '</a>').appendTo(controls); $(addTextboxButton).click(function(e){ e.preventDefault(); var newTextbox = MG.ui.createTextBox("", "center center").insertAfter(controls.find(".mg-textbox").last()); if(MG.settings.useBootstrap) { MG.ui.bootstrapify(); } else if(MG.settings.useWordpressStyle) { MG.ui.wordpressify(); } newTextbox.find("input[type=text]").first().focus(); MG.settings.onNewTextBox.call(MG, newTextbox); }); // Advanced settings var advancedSettingsButton = $('<a href="#" class="mg-advanced-settings-toggle">' + i18n.advancedSettings + '</a>').appendTo(controls); var advancedSettings = $('<div class="mg-advanced-settings"></div>').appendTo(controls).hide(); // -- Force uppercase option advancedSettings.append( $('<div class="option"></div>') .append($('<input type="checkbox" class="mg-option-uppercase">')) .append($('<label>' + i18n.optionCapitalLetters + '</label>')) ); controls.find(".mg-option-uppercase").prop("checked", MG.userSettings.forceUppercase); controls.find(".mg-option-uppercase").change(function(e){ e.preventDefault(); MG.userSettings.forceUppercase = $(this).is(":checked"); if(MG.userSettings.forceUppercase) { controls.find(".mg-textbox-text").css("textTransform", "uppercase"); controls.find(".mg-textbox-text").each(function(){ $(this).val(MG.ui._strtoupper($(this).val())); }); MG.events.onLayerChange(); } else { controls.find(".mg-textbox-text").css("textTransform", "none"); } }); // -- Drag & Resize option advancedSettings.append( $('<div class="option"></div>') .append($('<input type="checkbox" class="mg-option-dragresize">')) .append($('<label>' + i18n.optionDragResize + '</label>')) ); controls.find(".mg-option-dragresize").prop("checked", MG.userSettings.dragResizeEnabled); controls.find(".mg-option-dragresize").change(function(e){ e.preventDefault(); MG.userSettings.dragResizeEnabled = $(this).is(":checked"); MG.ui.destroyPositionHelpers(); if(MG.userSettings.dragResizeEnabled) { controls.find(".mg-textbox").each(function(){ MG.ui.createPositionHelper($(this)); }); } }); // -- Drawing and text - layers order advancedSettings.append( $('<div class="option"></div>') .append($('<input type="checkbox" class="mg-option-drawing-above-text">')) .append($('<label>' + i18n.optionDrawingAboveText + '</label>')) ); controls.find(".mg-option-drawing-above-text").prop("checked", MG.userSettings.dragResizeEnabled); controls.find(".mg-option-drawing-above-text").change(function(e){ e.preventDefault(); MG.userSettings.drawingAboveText = $(this).is(":checked"); if(MG.userSettings.drawingAboveText) { MG.wrapper.find(".mg-canvas canvas, .mg-css-preview").css("zIndex", 3); MG.wrapper.find(".mg-canvas, .mg-canvas .mg-drawing-layer").css("zIndex", 4); } else { MG.wrapper.find(".mg-canvas canvas, .mg-css-preview").css("zIndex", 4); MG.wrapper.find(".mg-canvas, .mg-canvas .mg-drawing-layer").css("zIndex", 3); } }); $(advancedSettingsButton).click(function(e){ e.preventDefault(); advancedSettings.slideToggle(200); advancedSettingsButton.toggleClass("active"); }); // Toolbox var toolbox; if(MG.settings.toolboxSelector == null) { var toolboxButton = $('<a href="#" class="mg-toolbox-toggle">' + i18n.toolbox + '</a>').appendTo(controls); var toolbox = $('<div class="mg-toolbox"></div>').appendTo(controls).hide(); $(toolboxButton).click(function(e){ e.preventDefault(); toolbox.slideToggle(200); toolboxButton.toggleClass("active"); }); } else { if(MG.settings.toolboxSelector instanceof jQuery) { toolbox = MG.settings.toolboxSelector; } else { toolbox = $(MG.settings.toolboxSelector); } } toolbox.append('<div class="mg-toolbox-item"><button class="mg-drawing-toggle">' + i18n.drawingStart + '</button></div>'); toolbox.append('<div class="mg-toolbox-item"><input type="text" class="colorpicker" value="' + MG.settings.defaultDrawingStyle.color + '"></div>'); toolbox.append('<div class="mg-toolbox-item"><input type="number" class="mg-drawing-line-width" value="' + MG.settings.defaultDrawingStyle.lineWidth + '"></div>'); toolbox.append('<div class="mg-toolbox-item"><button class="mg-drawing-erase">' + i18n.drawingErase + '</button></div>'); toolbox.find(".mg-drawing-toggle").click(function(){ $(this).toggleClass("active"); if($(this).hasClass("active")) { $(this).html(i18n.drawingStop); MG.drawing.enable(); } else { $(this).html(i18n.drawingStart); MG.drawing.disable(); } }); toolbox.find(".mg-drawing-line-width").on("change keyup", function(){ MG.drawing.lineWidth = parseInt($(this).val(), 10); }); toolbox.find(".mg-drawing-erase").click(function(){ MG.drawing.erase(); }); toolbox.find(".colorpicker").change(function(){ MG.drawing.color = $(this).attr("value"); }); MG.ui._bindColorpicker(toolbox.find(".colorpicker")); return controls; }, createTextBox: function(placeholder, position, params){ if(typeof params === 'undefined') params = {}; params = $.extend({ layerName: "layer" + (MG.canvasLayers.length + 1), text: "", x: 0, y: 0, maxWidth: MG.originalSize[0], fontSize: MG.settings.defaultTextStyle.size, color: MG.settings.defaultTextStyle.color, borderColor: MG.settings.defaultTextStyle.borderColor, borderWidth: MG.settings.defaultTextStyle.borderWidth }, params); params.height = Math.round(MG.settings.defaultTextStyle.lineHeight * params.fontSize); var layerName = params.layerName; var boxWidth = params.maxWidth; var boxHeight = params.height; var boxPosition = position === null ? [params.x, params.y] : MG.ui._getBoxCoordinates(position, params.maxWidth, params.height); var box = $('<div class="mg-textbox" data-layer="' + layerName + '" data-x="' + boxPosition[0] + '" data-y="' + boxPosition[1] + '" data-width="' + boxWidth + '" data-height="' + boxHeight + '"></div>'); box.append($('<input type="text" class="mg-textbox-text" placeholder="' + placeholder + '" data-text="' + params.text + '" value="' + params.text + '">')); box.append($('<input type="number" class="mg-textbox-size" value="' + params.fontSize + '" step="' + MG.settings.fontSizeStep + '" min="' + MG.settings.minFontSize + '" max="' + MG.settings.maxFontSize + '">')); if(MG.userSettings.forceUppercase) { box.find(".mg-textbox-text").css("textTransform", "uppercase"); } if(MG.settings.colorPicker != false) { box.append('<input type="text" class="mg-textbox-text-color colorpicker" value="' + params.color + '">'); box.append('<input type="text" class="mg-textbox-border-color colorpicker" value="' + params.borderColor + '">'); box.find(".colorpicker").wrap('<div class="colorpickerContainer"></div>'); MG.ui._bindColorpicker(box.find(".colorpicker")); } box.append($('<input type="number" class="mg-textbox-border-width" value="' + params.borderWidth + '" step="' + MG.settings.borderWidthStep + '" min="' + MG.settings.minBorderWidth + '" max="' + MG.settings.maxBorderWidth + '">')); // Canvas Layer MG.canvasLayers.push(layerName); // Bind events box.find(".mg-textbox-text, .mg-textbox-size, .mg-textbox-border-width").on("change keyup", function(){ if(MG.userSettings.forceUppercase) { $(this).attr("data-text", MG.ui._strtoupper($(this).val())); } MG.events.onLayerChange(layerName); }); // Position helper if(MG.userSettings.dragResizeEnabled) { MG.ui.createPositionHelper(box); } return box; }, createPositionHelper: function(box){ var layerName = box.data('layer'); var helper = $('<div class="draggable resizable" data-target-layer="' + layerName + '"></div>').appendTo(MG.helpersContainer); helper.css({left: box.attr("data-x") * MG.scale, top: box.attr("data-y") * MG.scale, width: box.attr("data-width") * MG.scale, height: box.attr("data-height") * MG.scale}); helper.draggable({ containment: MG.wrapper.find("> .mg-image > img"), drag: function(event, ui){ var layer = MG.wrapper.find("[data-layer='" + layerName + "']"); layer.attr("data-x", ui.position.left * (1 / MG.scale)); layer.attr("data-y", ui.position.top * (1 / MG.scale)); MG.events.onLayerChange(); } }); helper.resizable({ containment: MG.wrapper.find("> .mg-image > img"), resize: function(event, ui){ var layer = MG.wrapper.find("[data-layer='" + layerName + "']"); layer.attr("data-width", ui.size.width * (1 / MG.scale)); layer.attr("data-height", ui.size.height * (1 / MG.scale)); MG.events.onLayerChange(); } }); //helper.on('click', function(e){ // var layer = MG.wrapper.find("[data-layer='" + layerName + "']"); // var input = layer.find('.mg-textbox-text'); // var length = input.val().length; // // input.select(); // input[0].setSelectionRange(length, length); //}); }, resizeHelpers: function(){ MG.helpersContainer.find("> div").each(function(){ var layer = MG.wrapper.find("[data-layer='" + $(this).attr("data-target-layer") + "']"); if(layer.attr("data-width")) { $(this).css("width", parseInt(layer.attr("data-width"), 10) * MG.scale); } if(layer.attr("data-height")) { $(this).css("height", parseInt(layer.attr("data-height"), 10)); $(this).resizable("option", "minHeight", parseInt(layer.attr("data-height"), 10)); $(this).resizable("option", "maxHeight", parseInt(layer.attr("data-height"), 10)); } if(layer.attr("data-x") && layer.attr("data-y")) { $(this).css({left: layer.attr("data-x") * MG.scale, top: layer.attr("data-y") * MG.scale}); } if(parseInt($(this).css("top"), 10) + $(this).outerHeight() > MG.helpersContainer.height()) { var newTop = MG.helpersContainer.outerHeight() - $(this).outerHeight(); $(this).css("top", newTop); layer.attr("data-y", newTop * (1 / MG.scale)); } }); }, destroyPositionHelpers: function(){ MG.helpersContainer.find("> div").remove(); }, bootstrapify: function(){ var controls = MG.wrapper.find(".mg-controls"); if(!MG.wrapper.hasClass("usingBootstrap")) { controls.wrapInner('<div class="container-fluid"></div>'); } MG.wrapper.addClass("usingBootstrap"); controls.find(".mg-textbox").each(function(){ if(!$(this).hasClass("row")) { $(this).addClass("row"); $(this).find(".mg-textbox-text").addClass("form-control").wrap($("<div></div>").addClass("col-md-4")); $(this).find(".mg-textbox-size").addClass("form-control").wrap($("<div></div>").addClass("col-md-2")); $(this).find(".mg-textbox-border-width").addClass("form-control").wrap($("<div></div>").addClass("col-md-2")); $(this).find(".colorpicker").addClass("form-control") $(this).find(".colorpickerContainer").addClass("col-md-2"); $(this).find(".colorpickerReplacer").addClass("btn btn-default"); } }); if(!controls.find(".mg-add-textbox").hasClass("btn")) { controls.find(".mg-add-textbox").addClass("btn btn-default btn-block").wrap($("<div></div>").addClass("row")); } if(!controls.find(".mg-advanced-settings-toggle").hasClass("btn")) { controls.find(".mg-advanced-settings-toggle, .mg-toolbox-toggle").addClass("btn btn-primary btn-block").wrap($("<div></div>").addClass("row")); controls.find(".mg-advanced-settings, .mg-toolbox").addClass("row"); // controls.find(".mg-advanced-settings .option").addClass("row"); controls.find(".mg-advanced-settings .option input").wrap('<div class="col-md-1"></div>'); controls.find(".mg-advanced-settings .option label").wrap('<div class="col-md-11"></div>'); } if(!controls.find(".mg-drawing-toggle").hasClass("btn")) { controls.find(".mg-drawing-toggle, .mg-drawing-erase").addClass("btn btn-default btn-block"); controls.find(".mg-toolbox-item").addClass("col-md-3"); } }, wordpressify: function(){ var controls = MG.wrapper.find(".mg-controls"); MG.wrapper.addClass("usingWordpress"); if(!controls.find(".mg-add-textbox").hasClass("button")) { controls.find(".mg-add-textbox").addClass("button button-secondary"); } if(!controls.find(".mg-advanced-settings-toggle").hasClass("button")) { controls.find(".mg-advanced-settings-toggle, .mg-toolbox-toggle").addClass("button button-primary"); } if(!controls.find(".mg-drawing-toggle").hasClass("button")) { controls.find(".mg-drawing-toggle, .mg-drawing-erase").addClass("button button-secondary"); } }, _bindColorpicker: function(selector){ if(MG.settings.colorPicker == null && $.isFunction($.fn.spectrum)) { var changeEvent = function(color){ $(this).val(color.toHexString()); $(this).attr("value", color.toHexString()); $(this).trigger("change"); MG.events.onLayerChange($(this).parent().data("layer")); }; selector.spectrum({ replacerClassName: "colorpickerReplacer", change: changeEvent, move: changeEvent }); } else if(MG.settings.colorPicker == null) { selector.on("change keyup", function(){ $(this).attr("value", $(this).val()); MG.events.onLayerChange($(this).parent().data("layer")); }); } else { MG.settings.colorPicker.call(this, MG, selector); } }, _getBoxCoordinates: function(position, boxWidth, boxHeight){ var posDesc = position.split(" "); var coordinates = []; if(posDesc.length == 2) { switch(posDesc[0]) { case "center": coordinates[1] = parseInt(MG.originalSize[1] / 2, 10); break; case "bottom": coordinates[1] = MG.originalSize[1] - boxHeight; break; case "top": default: coordinates[1] = 0; break; } switch(posDesc[1]) { case "center": coordinates[0] = parseInt(MG.originalSize[0] / 2, 10) - parseInt(boxWidth / 2, 10); break; case "right": coordinates[0] = MG.originalSize[0] - boxWidth; break; case "left": default: coordinates[0] = 0; break; } } else { coordinates[0] = coordinates[1] = 0; } return coordinates; }, _normalizePosition: function(value){ return value * (1 + 1 - MG.scale); }, _strtoupper: function(text){ return text.toUpperCase(); } }; this.getLayersData = function(){ var layers = []; MG.canvasLayers.forEach(function(layerName){ var layer = MG.wrapper.find("[data-layer='" + layerName + "']"); var type = MG.getLayerType(layer); switch(type) { case 'text': layers.push({ type: type, name: layerName, text: layer.find(".mg-textbox-text").attr("data-text"), x: layer.attr("data-x"), y: layer.attr("data-y"), maxWidth: layer.attr("data-width"), fontSize: layer.find(".mg-textbox-size").val(), lineHeight: MG.settings.defaultTextStyle.lineHeight, font: MG.settings.defaultTextStyle.font, color: layer.find(".mg-textbox-text-color").val(), borderColor: layer.find(".mg-textbox-border-color").attr("value"), borderWidth: layer.find(".mg-textbox-border-width").val() }); return; // TODO: serialization of drawing? case 'drawing': layers.push({ type: type }); return; default: return; } }); return layers; }; this.getLayerType = function(layer) { if(layer.hasClass('mg-textbox')) { return 'text'; } if(layer.hasClass('mg-drawing-layer')) { return 'drawing'; } return null; }; this.canvas = { drawLayers: function(canvasScale){ if(typeof canvasScale == "undefined") canvasScale = MG.scale; MG.canvasContainer.find("canvas:not(.mg-drawing-layer)").remove(""); MG.getLayersData().forEach(function(layer){ layerElement = MG.wrapper.find("[data-layer='" + layer.name + "']"); if(layer.type == 'text') { var textCanvas = MG.canvas.drawText( layer.text, layer.x * canvasScale, layer.y * canvasScale, layer.maxWidth * canvasScale, layer.fontSize * canvasScale, layer.lineHeight, layer.font, layer.color, layer.borderColor, layer.borderWidth * canvasScale, canvasScale ); MG.canvasContainer.append(textCanvas); var textHeight = textCanvas.attr("data-text-lines") * layer.fontSize; layerElement.attr("data-height", Math.round(MG.settings.defaultTextStyle.lineHeight * textHeight)); } }); if(MG.userSettings.drawingAboveText) { MG.canvasContainer.find("canvas.mg-drawing-layer").remove().insertAfter(MG.canvasContainer.find(":last")); } else { MG.canvasContainer.find("canvas.mg-drawing-layer").remove().insertBefore(MG.canvasContainer.find(":first")); } }, drawText: function(text, x, y, maxWidth, fontSize, lineHeight, font, color, borderColor, borderWidth, scale){ if(typeof scale == "undefined") scale = 1.0; var canvasElement = $('<canvas></canvas>').attr("width", MG.originalSize[0] * scale).attr("height", MG.originalSize[1] * scale); var canvasContext = canvasElement[0].getContext("2d"); // Font settings canvasContext.font = fontSize + "px " + font; canvasContext.textAlign = "center"; canvasContext.fillStyle = color; canvasContext.strokeStyle = borderColor canvasContext.lineWidth = borderWidth; var posX = parseInt(x, 10) + parseInt(maxWidth, 10) / 2; var posY = parseInt(y, 10) + parseInt(fontSize, 10); var lineHeight = fontSize * parseFloat(lineHeight); var lines = MG.canvas._wrapText(canvasContext, text, maxWidth); lines.forEach(function(line, index){ canvasContext.fillText(line, posX, posY - borderWidth + (lineHeight - fontSize) / 2 + index * lineHeight); canvasContext.strokeText(line, posX, posY - borderWidth + (lineHeight - fontSize) / 2 + index * lineHeight); }); canvasElement.attr("data-text-lines", lines.length); return canvasElement; }, save: function(){ var image = $('<canvas></canvas>').attr("width", MG.originalSize[0]).attr("height", MG.originalSize[1])[0]; var imageContext = image.getContext("2d"); imageContext.drawImage(element[0], 0, 0); MG.canvas.drawLayers(1.0); MG.canvasContainer.find("canvas").each(function(){ imageContext.drawImage(this, 0, 0, MG.originalSize[0], MG.originalSize[1]); }); // Restore scaled layers in preview box if(MG.settings.previewMode == "canvas") { MG.canvas.drawLayers(); } else { MG.canvas.clear(); } return image; }, clear: function(){ MG.canvasContainer.find("canvas:not(.mg-drawing-layer)").remove(""); }, _wrapText: function(ctx, text, maxWidth){ var words = text.split(" "); var lines = []; var currentLine = words[0]; for(var i = 1; i < words.length; i++) { var word = words[i]; var width = ctx.measureText(currentLine + " " + word).width; if(width < maxWidth) { currentLine += " " + word; } else { lines.push(currentLine); currentLine = word; } } lines.push(currentLine); return lines; } }; this.cssPreview = { enable: function(){ MG.wrapper.find("> .mg-image").append('<div class="mg-css-preview"></div>'); }, disable: function(){ MG.wrapper.find("div.mg-css-preview").remove(); }, drawLayers: function(){ var cssPreviewContainer = MG.wrapper.find(".mg-css-preview"); cssPreviewContainer.find("div").remove(); MG.getLayersData().forEach(function(layer){ layerElement = MG.wrapper.find("[data-layer='" + layer.name + "']"); if(layer.type == 'text') { var textElement = MG.cssPreview.drawText( layer.text, layer.x * MG.scale, layer.y * MG.scale, layer.maxWidth * MG.scale, layer.fontSize * MG.scale, layer.lineHeight * MG.scale, layer.font, layer.color, layer.borderColor, layer.borderWidth * MG.scale ); cssPreviewContainer.append(textElement); layerElement.attr("data-height", Math.round(textElement.height())); } }); }, drawText: function(text, x, y, maxWidth, fontSize, lineHeight, font, color, borderColor, borderWidth){ var textElement = $("<div></div>").html(text); textElement.css({ left: x, top: y, width: maxWidth, minHeight: fontSize, fontSize: fontSize, fontFamily: font, color: color, textAlign: "center", lineHeight: parseFloat(lineHeight), textShadow: (function(borderWidth, borderColor){ var textShadow = ""; [[-1, -1], [-1, 1], [1, -1], [1, 1]].forEach(function(direction, index){ textShadow += direction[0] * borderWidth + "px " + direction[1] * borderWidth + "px 0 " + borderColor; if(index != 3) textShadow += ","; }); return textShadow; }(borderWidth, borderColor)) }); return textElement; } }; this.drawing = { container: null, canvas: null, enabled: false, flag: false, prevX: 0, currX: 0, prevY: 0, currY: 0, color: MG.settings.defaultDrawingStyle.color, lineWidth: MG.settings.defaultDrawingStyle.lineWidth, enable: function(){ if(MG.drawing.canvas == null) { MG.drawing.container = $('<div class="mg-drawing"></div>').appendTo(MG.wrapper.find("> .mg-image")); var drawingCanvas = $('<canvas class="mg-drawing-layer"></canvas>').attr("width", MG.drawing.container.width()).attr("height", MG.drawing.container.height()).appendTo(MG.canvasContainer); MG.drawing.canvas = drawingCanvas[0]; MG.drawing.initEvents(); } MG.drawing.enabled = true; MG.drawing.container.show(); }, disable: function(){ MG.drawing.enabled = false; MG.drawing.container.hide(); }, initEvents: function(){ MG.drawing.container[0].addEventListener("mousemove", function (e) { MG.drawing.handleAction("move", e) }, false); MG.drawing.container[0].addEventListener("mousedown", function (e) { MG.drawing.handleAction("down", e) }, false); MG.drawing.container[0].addEventListener("mouseup", function (e) { MG.drawing.handleAction("up", e) }, false); MG.drawing.container[0].addEventListener("mouseout", function (e) { MG.drawing.handleAction("out", e) }, false); }, draw: function(){ var context = MG.drawing.canvas.getContext("2d"); context.beginPath(); context.moveTo(MG.drawing.prevX, MG.drawing.prevY); context.lineTo(MG.drawing.currX, MG.drawing.currY); context.strokeStyle = MG.drawing.color; context.lineWidth = MG.drawing.lineWidth; context.stroke(); context.closePath(); }, erase: function(){ var context = MG.drawing.canvas.getContext("2d"); context.clearRect(0, 0, MG.drawing.canvas.width, MG.drawing.canvas.height); }, handleAction: function(action, event){ if(MG.drawing.enabled) { var context = MG.drawing.canvas.getContext("2d"); if(action == "down") { MG.drawing.prevX = MG.drawing.currX; MG.drawing.prevY = MG.drawing.currY; MG.drawing.currX = event.clientX - MG.drawing.container.offset().left; MG.drawing.currY = event.clientY - MG.drawing.container.offset().top; MG.drawing.flag = true; context.beginPath(); context.fillStyle = MG.drawing.color; context.fillRect(MG.drawing.currX, MG.drawing.currY, 2, 2); context.closePath(); } else if(action == "up" || action == "out") { MG.drawing.flag = false; } else if(action == "move") { if(MG.drawing.flag) { MG.drawing.prevX = MG.drawing.currX; MG.drawing.prevY = MG.drawing.currY; MG.drawing.currX = event.clientX - MG.drawing.container.offset().left; MG.drawing.currY = event.clientY - MG.drawing.container.offset().top; MG.drawing.draw(); } } } } }; this.events = { onLayerChange: function(layerName){ if(MG.settings.previewMode == "canvas") { MG.canvas.drawLayers(); } else if(MG.settings.previewMode == "css") { MG.cssPreview.drawLayers(); } MG.ui.resizeHelpers(); MG.settings.onLayerChange.call(MG, layerName); }, }; }; $.fn.memeGenerator = function(methodOrOptions){ var method = (typeof methodOrOptions === 'string') ? methodOrOptions : undefined; if(method) { var memeGeneratorPlugins = []; var args = (arguments.length > 1) ? Array.prototype.slice.call(arguments, 1) : undefined; var results = []; if(method == "i18n") { $.extend(i18n, args[1]); return; } this.each(function(){ var $el = $(this); var memeGeneratorPlugin = $el.data('memeGenerator'); memeGeneratorPlugins.push(memeGeneratorPlugin); }); this.each(function(index){ var memeGeneratorPlugin = memeGeneratorPlugins[index]; if(!memeGeneratorPlugin) { results.push(undefined); return; } if(typeof memeGeneratorPlugin[method] === 'function') { var result = memeGeneratorPlugin[method].apply(memeGeneratorPlugin, args); results.push(result); } else { console.warn('$.fn.memeGenerator: Undefined method "' + method + '"'); } }); return (results.length > 1) ? results : results[0]; } else { var options = (typeof methodOrOptions === 'object') ? methodOrOptions : undefined; return this.each(function(){ var $el = $(this); var memeGeneratorPlugin = new MemeGenerator($el, options); memeGeneratorPlugin.init(); $el.data('memeGenerator', memeGeneratorPlugin); }); } }; }(jQuery));