2 var PixasticEditor = (function () {
4 var $frame; // iframe container element
5 var $editor; // editor container element
7 // various UI structures
8 var accordionElements = {};
11 var $activeTabContent;
13 var isRunning = false;
17 var $imageCanvas; // the canvas holding the current state of the image
18 var $displayCanvas; // the canvas element displayed on the screen, also the working canvas (where preview operations are performed)
21 var imageWidth = 0; // dimensions of the current image state
24 var undoImages = []; // canvas elements holding previous image states
31 // test for valid file formats for toDataURL()
32 // we do that by calling it with each of the mime types in testFormats
33 // and then doing string checking on the resulting data: URI to see if it succeeded
35 var testFormats = [["image/jpeg", "JPEG"], ["image/png", "PNG"]];
36 var testCanvas = document.createElement("canvas");
37 if (testCanvas.toDataURL) {
38 testCanvas.width = testCanvas.height = 1;
39 for (var i=0;i<testFormats.length;i++) {
40 var data = testCanvas.toDataURL(testFormats[i][0]);
41 if (data.substr(0, 5 + testFormats[i][0].length) == "data:" + testFormats[i][0])
42 saveFormats.push({mime:testFormats[i][0], name:testFormats[i][1]});
47 // pops up an error dialog with the specified text (errTxt),
48 // if no context is provided, the name of the calling function is used.
49 // The final message is returned for easy throwing of actual errors
50 function errorDialog(errTxt, context) {
51 if (!($editor && $editor.get && $editor.get(0)))
52 throw new Error("errorDialog(): $editor doesn't exist");
54 var caller = errorDialog.caller.toString().split(" ")[1];
55 caller = caller.substring(0, caller.indexOf("("));
56 context = context || caller;
57 errTxt = context + "(): " + errTxt;
58 var dialog = $j("<div></div>", doc)
59 .addClass("error-dialog")
60 .attr("title", "Oops!")
63 // the dialog is added outside the Pixastic container, so get it back in.
64 var dialogParent = $j(dialog.get(0).parentNode);
65 dialogParent.appendTo($editor);
70 function enableTab(id, refresh) {
71 if (id == activeTabId && !refresh)
78 if ($activeTabContent) {
79 if ($activeTabContent.get(0)) {
80 var $parent = $j($activeTabContent.get(0).parentNode);
81 activeIndex = $parent.data("accordionindex");
82 if ($parent.data("ondeactivate")) {
83 $parent.data("ondeactivate")();
85 if ($parent.data("previewCheckbox"))
86 $parent.data("previewCheckbox").attr("checked", false);
87 $parent.data("uidesc").previewEnabled = false;
88 if ($parent.data("uidesc").forcePreview)
89 $parent.data("uidesc").previewEnabled = true;
94 for (var a in accordionElements) {
95 if (accordionElements.hasOwnProperty(a)) {
96 accordionElements[a].accordion("option", "animated", false);
97 accordionElements[a].accordion("activate", -1);
98 accordionElements[a].hide();
99 tabElements[a].removeClass("active");
104 accordionElements[id].accordion("option", "animated", false);
105 accordionElements[id].accordion("activate", refresh ? activeIndex : 0);
106 tabElements[id].addClass("active");
107 accordionElements[id].show();
108 accordionElements[id].accordion("option", "animated", "slide");
109 resetDisplayCanvas();
112 // revert to a previous image state
114 var undoImage = undoImages[idx];
117 throw new Error(errorDialog("Invalid undo state"));
118 if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))
119 throw new Error(errorDialog("$imageCanvas doesn't exist"));
121 var canvas = $imageCanvas.get(0);
123 canvas.width = imageWidth = undoImage.width;
124 canvas.height = imageHeight = undoImage.height;
125 canvas.getContext("2d").drawImage(undoImage,0,0);
127 enableTab(activeTabId, true);
128 resetDisplayCanvas();
131 function addUndo(canvasElement) {
133 throw new Error(errorDialog("No undo image state provided"));
135 if (undoImages.length == undoLevels) {
138 var undoCanvas = document.createElement("canvas");
139 undoCanvas.width = canvasElement.width;
140 undoCanvas.height = canvasElement.height;
141 undoCanvas.getContext("2d").drawImage(canvasElement,0,0);
142 $j(undoCanvas).addClass("undo-canvas");
143 undoImages.push(undoCanvas);
147 function updateUndoList() {
148 var $listCtr = $j("#undo-bar", doc)
151 var ctrHeight = $listCtr.height();
153 var $testCanvas = $j("<canvas></canvas>", doc)
154 .addClass("undo-canvas-small")
155 .addClass("far-far-away")
158 var canvasHeight = $testCanvas.height();
159 var canvasWidth = $testCanvas.width();
160 var canvasCSSHeight = canvasHeight + parseInt($testCanvas.css("margin-top"),10) + parseInt($testCanvas.css("margin-bottom"),10);
162 $testCanvas.remove();
164 var undoRatio = canvasWidth / canvasHeight;
166 for (var i=undoImages.length-1;i>=0;i--) {
168 var canvas = document.createElement("canvas");
170 .addClass("undo-canvas-small")
171 .attr("width", canvasWidth)
172 .attr("height", canvasHeight);
174 var image = undoImages[i];
177 var undoWidth, undoHeight;
178 var imageRatio = image.width / image.height;
180 if (imageRatio > undoRatio) { // image too wide
181 undoWidth = canvasWidth;
182 undoHeight = canvasWidth / imageRatio;
184 undoWidth = canvasHeight * imageRatio;
185 undoHeight = canvasHeight;
188 var restWidth = canvasWidth - undoWidth;
189 var restHeight = canvasHeight - undoHeight;
191 canvas.getContext("2d").drawImage(
193 0,0,image.width,image.height,
194 restWidth*0.5, restHeight*0.5,
195 undoWidth, undoHeight
199 $link = $j("<a href='#'></a>", doc)
200 .addClass("undo-link")
202 .mouseover(function(){ $j(this).addClass("hover") })
203 .mouseout(function(){ $j(this).removeClass("hover") });
204 $j(canvas).appendTo($link);
208 $link.click(function() {
213 $displayCanvas.show();
214 $j(".jcrop-holder", doc).show();
217 $link.mouseover(function() {
218 displayShowing = $displayCanvas.css("display") != "none";
219 var $imagectr = $j("#image-container", doc);
221 $j(".jcrop-holder", doc).hide();
222 $displayCanvas.hide();
223 $j(image).appendTo($imagectr);
225 var h1 = $j("#image-area", doc).height();
226 var h2 = image.height;
227 var m = Math.max(0, (h1 - h2) / 2);
228 $imagectr.css("marginTop", m);
230 $imagectr.height(image.height);
233 $link.mouseout(function() {
236 $displayCanvas.show();
237 $j(".jcrop-holder", doc).show();
238 updateDisplayCanvas();
242 $j(canvas).attr("title", "Click to revert to this previous image");
249 function applyAction(id, options, afteraction) {
250 if (!Pixastic.Actions[id])
251 throw new Error("applyAction(): unknown action [" + id + "]");
253 $j("#action-bar-overlay", doc).show();
255 setTimeout(function() {
256 options.leaveDOM = true;
257 var canvasElement = $imageCanvas.get(0);
258 addUndo(canvasElement)
260 var res = Pixastic.process(
261 canvasElement, id, options,
262 function(resCanvas) {
263 canvasElement.width = imageWidth = resCanvas.width;
264 canvasElement.height = imageHeight = resCanvas.height;
266 var ctx = canvasElement.getContext("2d");
267 ctx.clearRect(0,0,imageWidth,imageHeight);
268 ctx.drawImage(resCanvas,0,0);
269 $imageCanvas = $j(canvasElement);
270 resetDisplayCanvas();
272 $j("#action-bar-overlay", doc).hide();
279 throw new Error("applyAction(): Pixastic.process() failed for action [" + id + "]");
284 function previewAction(id, options, afteraction) {
285 if (!Pixastic.Actions[id])
286 throw new Error("applyAction(): unknown action [" + id + "]");
288 $j("#action-bar-overlay", doc).show();
290 resetDisplayCanvas();
292 options.leaveDOM = true;
293 var canvasElement = $displayCanvas.get(0);
295 var res = Pixastic.process(
296 canvasElement, id, options,
297 function(resCanvas) {
299 canvasElement.width = resCanvas.width;
300 canvasElement.height = resCanvas.height;
302 var ctx = canvasElement.getContext("2d");
303 ctx.clearRect(0,0,canvasElement.width,canvasElement.height);
304 ctx.drawImage(resCanvas,0,0);
305 updateDisplayCanvas();
308 $j("#action-bar-overlay", doc).hide();
316 var onwindowresize = function() {
317 updateDisplayCanvas();
323 function buildEditor() {
325 "jquery-ui-1.7.1.custom.css",
330 for (var i=0;i<styles.length;i++) {
331 var s = doc.createElement("link");
332 s.href = baseUrl + styles[i];
334 s.rel = "stylesheet";
335 doc.getElementsByTagName("head")[0].appendChild( s );
339 accordionElements = {};
342 $activeTabContent = null;
344 // setup DOM UI skeleton
345 $editor = $j("<div />", doc)
346 .attr("id", "pixastic-editor")
347 .appendTo($j(doc.body));
350 $j("<div id='background' />", doc),
351 $j("<div id='edit-ctr-1' />", doc).append(
352 $j("<div id='edit-ctr-2' />", doc).append(
353 $j("<div id='controls-bar' />", doc).append(
354 $j("<div id='action-bar' />", doc).append(
355 $j("<div id='action-bar-overlay' />", doc)
357 $j("<div id='undo-bar' />", doc)
359 $j("<div id='image-area' />", doc).append(
360 $j("<div id='image-area-sub' />", doc).append(
361 $j("<div id='image-container' />", doc),
362 $j("<div id='image-overlay-container' />", doc).append(
363 $j("<div id='image-overlay' />", doc)
369 $j("<div id='main-bar' />", doc),
370 $j("<div id='powered-by-pixastic'><a href=\"http://www.pixastic.com/\" target=\"_blank\">Powered by Pixastic</a></div>", doc)
373 $j("#image-container", doc).append(
374 $displayCanvas = $j("<canvas />", doc)
375 .addClass("display-canvas")
378 // loop through all defined UI action controls
379 var tabs = PixasticEditor.UI.data.tabs;
381 for (var i=0;i<tabs.length;i++) {
386 var $tabElement = $j("<a href=\"#\">" + tab.title + "</a>", doc)
387 .attr("id", "main-tab-button-" + tab.id)
388 .addClass("main-tab")
392 .mouseover(function(){ $j(this).addClass("hover") })
393 .mouseout(function(){ $j(this).removeClass("hover") });
395 $j("#main-bar", doc).append($tabElement);
397 tabElements[tab.id] = $tabElement;
399 var $menu = $j("<div/>", doc);
400 accordionElements[tab.id] = $menu;
402 for (var j=0;j<tab.actions.length;j++) {
405 var action = tab.actions[j];
407 var $actionElement = $j("<div><h3><a href=\"#\">" + action.title + "</a></h3></div>", doc)
409 $menu.append($actionElement);
411 var $content = $j("<div></div>", doc)
412 .attr("id", "pixastic-action-tab-content-" + action.id)
413 .appendTo($actionElement);
415 var controlOptions = [];
417 action.previewEnabled = false;
418 if (action.forcePreview)
419 action.previewEnabled = true;
421 function togglePreview(enable, doAction) {
422 if (enable && !action.previewEnabled && doAction)
424 if (!enable && action.previewEnabled)
425 resetDisplayCanvas();
427 action.previewEnabled = enable;
430 var reset = function() {
431 for (var i in controlOptions) {
432 if (controlOptions.hasOwnProperty(i)) {
433 controlOptions[i].reset();
436 if (action.previewEnabled)
439 var doAction = function(isPreview) {
441 for (var i in controlOptions) {
442 if (controlOptions.hasOwnProperty(i)) {
443 options[i] = controlOptions[i].valueField.val();
447 var afteraction = function() {
448 if (action.onafteraction)
449 action.onafteraction(action, isPreview);
451 resetDisplayCanvas();
453 if (!isPreview && !action.forcePreview) {
454 $j("#pixastic-input-preview-" + action.id, doc).attr("checked", false);
455 togglePreview(false);
461 previewAction(action.id, options, afteraction);
463 applyAction(action.id, options, afteraction);
468 var hadInputs = false;
470 if (action.controls) {
471 var onChange = function() {};
472 if (action.isAction && action.preview) {
473 onChange = function() {
474 if (action.previewEnabled)
479 for (var k=0;k<action.controls.length;k++) {
480 var control = action.controls[k];
481 if (typeof control.defaultValue != "function") {
483 var defVal = control.defaultValue;
484 control.defaultValue = function() {
489 var controlId = action.id + "-" + control.option;
491 if (control.type != "output")
494 switch (control.type) {
496 switch (control.ui) {
498 var slider = PixasticEditor.UI.makeSlider(
499 control.label, controlId,
500 control.range[0], control.range[1], control.step, control.defaultValue, onChange
503 slider.container.appendTo($content);
504 controlOptions[control.option] = slider;
507 var text = PixasticEditor.UI.makeNumericInput(
508 control.label, control.labelRight, controlId,
509 control.range[0], control.range[1], control.step, control.defaultValue, onChange
511 text.container.appendTo($content);
512 controlOptions[control.option] = text;
517 switch (control.ui) {
519 var checkbox = PixasticEditor.UI.makeCheckbox(
520 control.label, controlId, control.defaultValue, onChange
523 checkbox.container.appendTo($content);
524 controlOptions[control.option] = checkbox;
528 switch (control.ui) {
530 var select = PixasticEditor.UI.makeSelect(
531 control.label, controlId, control.values, control.defaultValue, onChange
534 select.container.appendTo($content);
535 controlOptions[control.option] = select;
540 var outputText = $j("<div></div>", doc)
541 .addClass("ui-action-output")
542 .html(control.content)
549 if (action.isAction) {
551 var $applyButton = PixasticEditor.UI.makeButton("Apply")
552 .addClass("pixastic-option-button-apply")
553 .click(function() {doAction();});
555 $content.append($applyButton);
558 var $resetButton = PixasticEditor.UI.makeButton("Reset")
559 .addClass("pixastic-option-button-reset")
562 $content.append($resetButton)
565 if (action.preview && !action.forcePreview) {
566 var $checkctr = $j("<div></div>", doc)
567 .addClass("ui-checkbox-container")
568 .addClass("ui-preview-checkbox-container");
570 var $label = $j("<label></label>", doc)
571 .addClass("ui-checkbox-label")
572 .attr("for", "pixastic-input-preview-" + action.id)
574 .appendTo($checkctr);
576 var $checkbox = $j("<input type=\"checkbox\"></input>", doc)
577 .addClass("ui-checkbox")
578 .attr("id", "pixastic-input-preview-" + action.id)
581 togglePreview(this.checked, doAction)
584 $content.append($checkctr);
586 $content.data("previewCheckbox", $checkbox);
592 if (typeof action.content == "function") {
593 action.content($content);
596 // stupid hack to make it possible to get $content in change event (below)
597 $j("<span></span>", doc).appendTo($content);
599 $content.data("controlOptions", controlOptions);
600 $content.data("onactivate", action.onactivate);
601 $content.data("ondeactivate", action.ondeactivate);
602 $content.data("onoverlayupdate", action.onoverlayupdate);
603 $content.data("accordionindex", j);
604 $content.data("uidesc", action);
609 $j("#action-bar", doc).append($menu);
611 $menu.hide().accordion({
617 .bind("accordionchange",
618 function(event, ui) {
619 resetDisplayCanvas();
621 // oldContent / newContent are arrays of whatever elements are present in the content area
622 // We need the parent element (the one holding the content) but if there is no content, how do we get it?
623 // fixed above by always appending a <span> but that's ugly and needs to be done in some other way
624 if (ui.oldContent.get(0)) {
625 var $parent = $j(ui.oldContent.get(0).parentNode);
626 if ($parent.data("ondeactivate")) {
627 $parent.data("ondeactivate")();
630 $activeTabContent = ui.newContent;
632 if (ui.newContent.get(0)) {
633 var $parent = $j(ui.newContent.get(0).parentNode);
634 if ($parent.data("previewCheckbox"))
635 $parent.data("previewCheckbox").attr("checked", false);
636 $parent.data("uidesc").previewEnabled = false;
637 if ($parent.data("uidesc").forcePreview)
638 $parent.data("uidesc").previewEnabled = true;
640 var controlOptions = $parent.data("controlOptions");
641 for (var i in controlOptions) {
642 if (controlOptions.hasOwnProperty(i)) {
643 controlOptions[i].reset();
646 if ($parent.data("onactivate")) {
647 $parent.data("onactivate")();
650 updateDisplayCanvas();
659 $j(window).bind("resize", onwindowresize);
662 function showLoadingScreen() {
663 if ($loadingScreen) {
664 $loadingScreen.show();
667 $loadingScreen = $j("<div id=\"loading-screen\" />")
668 var $ctr = $j("<div id=\"loading-screen-cell\" />");
672 $loadingScreen.append($ctr);
673 $loadingScreen.appendTo("body");
676 function hideLoadingScreen() {
677 setTimeout(function() {
678 $loadingScreen.hide();
687 function init(callback) {
692 oldScrollLeft = document.body.scrollLeft;
693 oldScrollTop = document.body.scrollTop;
694 oldOverflow = document.body.style.overflow;
696 document.body.scrollLeft = 0;
697 document.body.scrollTop = 0;
698 document.body.style.overflow = "hidden";
700 $frame = $j("<iframe />");
703 position : "absolute",
704 left : document.body.scrollLeft + "px",
705 top : document.body.scrollTop + "px",
710 $frame.load(function(){
711 doc = $frame.get(0).contentDocument;
717 setTimeout(function(){
718 updateDisplayCanvas();
721 $frame.appendTo("body");
724 // unload the editor, remove all elements added to the page and restore whatever properties we messed with
726 $j(window).unbind("resize", onwindowresize);
732 document.body.scrollLeft = oldScrollLeft;
733 document.body.scrollTop = oldScrollTop;
734 document.body.style.overflow = oldOverflow;
740 // resets the display canvas (clears the canvas and repaints the current state)
741 // then updates display and overlay
742 function resetDisplayCanvas() {
743 if (!($displayCanvas && $displayCanvas.get)) throw new Error(errorDialog("$displayCanvas doesn't exist"));
744 if (!($imageCanvas && $imageCanvas.get)) throw new Error(errorDialog("$imageCanvas doesn't exist"));
746 var display = $displayCanvas.get(0);
747 var image = $imageCanvas.get(0);
749 if (!display) throw new Error(errorDialog("resetDisplayCanvas(): No elements in $displayCanvas"));
750 if (!image) throw new Error(errorDialog("resetDisplayCanvas(): No elements in $imageCanvas"));
752 display.width = imageWidth;
753 display.height = imageHeight;
754 display.getContext("2d").drawImage( image, 0, 0 );
756 updateDisplayCanvas();
760 // updates the display by resetting the height and margin of the image container
761 // this is mainly to keep vertical centering
762 function updateDisplayCanvas() {
763 var $imageCtr = $j("#image-container", doc);
764 var $editArea = $j("#image-area", doc);
766 if (!$imageCtr.get(0)) throw new Error(errorDialog("updateDisplayCanvas(): $imageCtr doesn't exist"));
767 if (!$displayCanvas.get(0)) throw new Error(errorDialog("updateDisplayCanvas(): $displayCanvas doesn't exist"));
768 if (!$editArea.get(0)) throw new Error(errorDialog("updateDisplayCanvas(): $editArea doesn't exist"));
770 var h2 = $displayCanvas.get(0).height;
771 var h1 = $j("#image-area", doc).height();
772 var m = Math.max(0, (h1 - h2) / 2);
773 $imageCtr.height(h2);
774 $imageCtr.css("marginTop", m);
777 // basically the same as updateDisplayCanvas but for the image overlay
778 function updateOverlay() {
779 var $overlay = $j("#image-overlay-container", doc);
780 var $imagectr = $j("#image-container", doc);
781 $overlay.height($imagectr.height());
782 $overlay.css("marginTop", $imagectr.css("marginTop"));
784 if ($activeTabContent && $activeTabContent.get(0)) {
785 var $tabContent = $j($activeTabContent.get(0).parentNode);
786 if (typeof $tabContent.data("onoverlayupdate") == "function")
787 $tabContent.data("onoverlayupdate")();
791 var imageIsLoading = false;
792 var originalImageElement;
795 function loadImage(imgEl) {
799 imageIsLoading = true;
801 originalImageElement = imgEl;
803 $imageCanvas = $j("<canvas />", doc);
804 imageCtx = $imageCanvas.get(0).getContext("2d");
808 $imageCanvas.attr("width", 0);
809 $imageCanvas.attr("height", 0);
811 if (imgEl.tagName.toLowerCase() == "img" && !imgEl._pixasticCanvas) {
812 var onload = function(el) {
813 imageWidth = el.offsetWidth;
814 imageHeight = el.offsetHeight;
815 $imageCanvas.attr("width", imageWidth);
816 $imageCanvas.attr("height", imageHeight);
817 imageCtx.drawImage(el,0,0);
819 imageIsLoading = false;
820 enableTab("reshape");
821 setTimeout(function() {
822 resetDisplayCanvas();
825 $tmpImg = $j("<img />", doc)
826 .css("position", "absolute")
827 .css("left", "-9999px")
828 .css("top", "-9999px")
830 .load(function(){onload(this);})
832 throw new Error("Could not load temporary copy image. Is provided image valid?");
835 .attr("src", imgEl.src);
836 if ($tmpImg.attr("complete")) {
837 onload($tmpImg.get(0));
840 var $canvas = imgEl._pixasticCanvas || imgEl;
841 imageWidth = $canvas.attr("width");
842 imageHeight = $canvas.attr("height");
843 $imageCanvas.attr("width", imageWidth);
844 $imageCanvas.attr("height", imageHeight);
845 imageCtx.drawImage($canvas.get(0), 0, 0);
846 imageIsLoading = false;
847 enableTab("reshape");
848 resetDisplayCanvas();
852 // return public interface
855 // don't call. For now we must load the image immediately via load()
856 loadImage : function(imgEl) {
857 if (!isRunning) return false;
861 saveToPage : function() {
862 if (!isRunning) throw new Error("PixasticEditor::saveToPage(): Editor is not running");
864 var $canvas = PixasticEditor.getImageCanvas();
865 var img = PixasticEditor.getOriginalImage();
866 if (img.tagName.toLowerCase() == "canvas") {
867 img.width = $canvas.attr("width");
868 img.height = $canvas.attr("height");
869 img.getContext("2d").drawImage($canvas.get(0), 0, 0);
871 img.src = PixasticEditor.getDataURI();
873 img._pixasticCanvas = PixasticEditor.getImageCanvas();
875 load : function(img, customBaseUrl) {
876 if (isRunning) return false;
879 throw new Error("Must be called with an image or canvas as its first argument", "PixasticEditor::load")
881 $ = PixasticEditor.jQuery;
883 baseUrl = customBaseUrl || "http://www.pixastic.com/editor-test/";
886 if (img && img.tagName.toLowerCase() == "img" || img.tagName.toLowerCase() == "canvas") {
892 unload : function() {
893 if (!isRunning) throw new Error("PixasticEditor::unload(): Editor is not running");
897 getDocument : function() {
898 if (!isRunning) throw new Error("PixasticEditor::getDocument(): Editor is not running");
903 validSaveFormats : function() {
907 getOriginalImage : function() {
908 if (!isRunning) throw new Error("PixasticEditor::getOriginalImage(): Editor is not running");
909 return originalImageElement;
912 getDataURI : function(mime) {
913 if (!isRunning) throw new Error("PixasticEditor::getDataURI(): Editor is not running");
915 if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))
916 throw new Error(errorDialog("$imageCanvas doesn't exist", "getImageCanvas"));
918 return $imageCanvas.get(0).toDataURL(mime||"image/png");
921 getImageCanvas : function() {
922 if (!isRunning) throw new Error("PixasticEditor::getImageCanvas(): Editor is not running");
924 if (!($imageCanvas && $imageCanvas.get && $imageCanvas.get(0)))
925 throw new Error(errorDialog("$imageCanvas doesn't exist", "getImageCanvas"));
929 getOverlay : function() {
930 if (!isRunning) throw new Error("PixasticEditor::getOverlay(): Editor is not running");
932 return $j("#image-overlay", doc);
934 getDisplayCanvas : function() {
935 if (!isRunning) throw new Error("PixasticEditor::getDisplayCanvas(): Editor is not running");
937 if (!($displayCanvas && $displayCanvas.get && $displayCanvas.get(0)))
938 throw new Error(errorDialog("$displayCanvas doesn't exist", "getDisplayCanvas"));
939 return $displayCanvas;
941 getDisplayWidth : function() {
942 if (!isRunning) throw new Error("PixasticEditor::getDisplayWidth(): Editor is not running");
946 getDisplayHeight : function() {
947 if (!isRunning) throw new Error("PixasticEditor::getDisplayHeight(): Editor is not running");
949 return displayHeight;
951 getImageWidth : function() {
952 if (!isRunning) throw new Error("PixasticEditor::getImageWidth(): Editor is not running");
956 getImageHeight : function() {
957 if (!isRunning) throw new Error("PixasticEditor::getImageHeight(): Editor is not running");
961 errorDialog : function() {
962 if (!isRunning) throw new Error("PixasticEditor::errorDialog(): Editor is not running");
964 return errorDialog.apply(null, arguments);