From ad56309cb07dc437abddf63333797c5bb7fa0d72 Mon Sep 17 00:00:00 2001 From: mappu Date: Wed, 17 May 2023 18:09:28 +1200 Subject: [PATCH] sdk: replace all the early-load logic with promises --- static/sdk.js | 626 ++++++++++++++++++++++++-------------------------- 1 file changed, 306 insertions(+), 320 deletions(-) diff --git a/static/sdk.js b/static/sdk.js index 9dd5497..d3423c7 100644 --- a/static/sdk.js +++ b/static/sdk.js @@ -12,29 +12,16 @@ return currentScript.replace(currentScriptFile, ''); }; - var loadScript = function(url, onLoad) { - var script = document.createElement('script'); - script.onload = onLoad; - script.src = url; - document.head.appendChild(script); + var loadScript = function(url) { + return new Promise(function(resolve, reject) { + var script = document.createElement('script'); + script.onload = resolve; + script.onerror = reject; + script.src = url; + document.head.appendChild(script); + }); }; - var loadScripts = function(urls, onLoad) { - // load sequentially - var i = 0; - var loadNext = function() { - if (i === urls.length) { - onLoad(); - return; - } - - var url = urls[i]; - i += 1; - loadScript(url, loadNext); - }; - loadNext(); - }; - var formatBytes = function(bytes) { var k = 1024, m = (1024*1024), g = (1024*1024*1024); @@ -221,7 +208,7 @@ `; - var initArea = function (elementSelector, onUploaded, onClose) { + var initArea = function (aboutInfo, elementSelector, onUploaded, onClose) { onUploaded = onUploaded || function () { }; onClose = onClose || function () { }; @@ -233,303 +220,282 @@ // // Create a new div for ourselves on top of the existing area - $.get(contented.baseURL + "about", function (ret) { - - var extraText = ""; - if (ret.MaxUploadBytes > 0) { - extraText = " (max " + formatBytes(ret.MaxUploadBytes) + ")"; - } - + var extraText = ""; + if (aboutInfo.MaxUploadBytes > 0) { + extraText = " (max " + formatBytes(aboutInfo.MaxUploadBytes) + ")"; + } - var $f = $("
").html(widgetHtml); - $f.find(".contented-extratext").text(extraText); + var $f = $("
").html(widgetHtml); + $f.find(".contented-extratext").text(extraText); - // Tab buttons - - var hasSetupDrawingBoardYet = false; - var setType = function (type) { - $f.find(".contented-upload-type").removeClass("contented-upload-type-active"); - $f.find(".contented-upload-type[data-upload-type=" + type + "]").addClass("contented-upload-type-active"); + // Tab buttons + + var hasSetupDrawingBoardYet = false; + var setType = function (type) { + $f.find(".contented-upload-type").removeClass("contented-upload-type-active"); + $f.find(".contented-upload-type[data-upload-type=" + type + "]").addClass("contented-upload-type-active"); - $f.find(".contented-upload-if").removeClass("contented-active"); - $f.find(".contented-if-" + type).addClass("contented-active"); - - if (type == "drag") { - enablePasteHandler(); - } else { - disablePasteHandler(); - } - - if (type == "drawing" && !hasSetupDrawingBoardYet) { - setupDrawingBoard(); - hasSetupDrawingBoardYet = true; - } - }; - - $f.find(".contented-upload-type").click(function () { - setType($(this).attr('data-upload-type')); - }); - - // Widget positioning - - var $element = $(element); - var offset = $element.offset(); - - $f.css({ - 'position': 'absolute', - 'left': offset.left + "px", - 'top': offset.top + "px", - 'width': $element.width() + "px", - 'min-width': $element.width() + "px", - 'max-width': $element.width() + "px", - 'height': $element.height() + "px", - 'min-height': $element.height() + "px", - 'max-height': $element.height() + "px" - }); - - // Drag and drop support - - $f.find('.contented').on('dragover dragenter', function (e) { - e.preventDefault(); - e.stopPropagation(); - $(this).addClass('is-dragging'); - }); - - $f.find('.contented').on('dragleave dragend', function (e) { - e.preventDefault(); - e.stopPropagation(); - $(this).removeClass('is-dragging'); - }); - - $f.find('.contented').on('drop', function (e) { - e.preventDefault(); - e.stopPropagation(); - handleUploadFrom(e.originalEvent.dataTransfer.files); - }); - - $f.find('.contented-file-upload').on('click', function(e) { - e.preventDefault(); - e.stopPropagation(); - handleUploadFrom($(".contented-file-selector")[0].files); - }); - - // Pastebin - - $f.find('.contented-paste-upload').on('click', function(e) { - e.preventDefault(); - e.stopPropagation(); - var blob = new Blob([$(".contented-if-paste textarea").val()], {type : 'text/plain'}); - handleUploadFrom([blob]); - }); - - // Ctrl+V uploads - - var pasteHandler = function(e) { - e.preventDefault(); - e.stopPropagation(); - - var items = (e.clipboardData || e.originalEvent.clipboardData).items; - var items_length = items.length; - var blobs = []; - var handled = 0; - var haveHandled = function() { - handled += 1; - if (handled == items_length) { - - if (blobs.length > 0) { - handleUploadFrom( blobs ); - } else { - // alert("Pasted 0 files"); - } - } - }; - - for (var i = 0; i < items.length; ++i) { - var item = items[i]; - var mimeType = item.type; - if (item.kind === 'file') { - blobs.push(item.getAsFile()); - haveHandled(); - - } else if (item.kind === 'string') { - item.getAsString(function(s) { - blobs.push( new Blob([s], {type : mimeType}) ); - haveHandled(); - }); - - } else { - // file|string are the only supported types in - // all browsers at the time of writing - // Ignore future possibilities - haveHandled(); - } - } - }; - var enablePasteHandler = function() { - document.addEventListener('paste', pasteHandler); - }; - var disablePasteHandler = function() { - document.removeEventListener('paste', pasteHandler); - }; - - // Embed in DOM, load default area - - $("body").append($f); - if (!contented.supportsDrop()) { - setType('file'); - } else { - setType('drag'); - } - - // Drawing board - - var setupDrawingBoard = function() { - - $("head").append( - '' - ); - - var db_id = "contented-drawing-area-" + guid(); - var $db = $("
").attr('id', db_id); - - DrawingBoard.Control.ContentedUpload = DrawingBoard.Control.extend({ - name: 'upload', - - initialize: function() { - var $el = this.$el; - - $el.append(''); - $el.on('click', '.contented-drawingboard-upload', $.proxy(function(e) { - e.preventDefault(); - e.stopPropagation(); - - $el.prop('disabled', true); - $el.text('Saving...'); - - $db.find("canvas")[0].toBlob(function(theBlob) { - handleUploadFrom([ theBlob ]); - }); - }, this)); - } - }); - - $db.css({ - //'width': $f.find(".contented-content-area").width(), - 'height': $f.find(".contented-content-area").height(), - 'overflow': 'hidden' - }); - - $f.find(".contented-drawing-area").append($db); - var db = new DrawingBoard.Board(db_id, { - 'controls': [ - 'Color', - 'Size', - 'DrawingMode', - 'Navigation', - 'ContentedUpload' - ], - 'controlsPosition': 'center', - 'enlargeYourContainer': false, - 'webStorage': false, - 'droppable': false // don't mess with existing drop support - }); - - }; - - // Close button - - var ourClose = function () { - $f.remove(); // remove from dom - disablePasteHandler(); - onClose(); // upstream close - }; - $f.find(".contented-close").click(function () { - ourClose(); - }) - - // Progress bar - - var setProgressCaption = function(message) { - $f.find(".contented-if-progress label").text(message); - }; - var setProgressPercentage = function(frc) { - $f.find(".contented-progress-element").css('width', (frc * 100) + "%"); - }; - - // Common upload handler - - var handleUploadFrom = function(files) { - - setProgressCaption("Uploading, please wait..."); - setProgressPercentage(0); - setType("progress"); - - $f.find(".contented-upload-type-selector").hide(); - $f.find(".contented").removeClass('is-dragging'); - - // Ajax uploader - var ajaxData = new FormData(); - for (var i = 0; i < files.length; ++i) { - ajaxData.append("f", files[i]); - } - - // ajax request - $.ajax({ - url: contented.baseURL + "upload", - type: "POST", - data: ajaxData, - dataType: 'json', // response type - cache: false, - contentType: false, - processData: false, - xhr: function() { - var xhr = $.ajaxSettings.xhr(); - xhr.upload.addEventListener( - 'progress', - function(ev) { - if (ev.lengthComputable) { - setProgressCaption("Uploading (" + formatBytes(ev.loaded) + " / " + formatBytes(ev.total) + ")..."); - setProgressPercentage(ev.total == 0 ? 0 : ev.loaded / ev.total); - } - }, - false - ); - return xhr; - }, - complete: function () { - setProgressPercentage(1); - }, - success: function (data) { - setProgressCaption("Upload completed successfully."); - onUploaded(data); - ourClose(); - }, - error: function () { - setProgressCaption("Upload failed!"); - } - }); - - } - - // . - - }); + $f.find(".contented-upload-if").removeClass("contented-active"); + $f.find(".contented-if-" + type).addClass("contented-active"); + + if (type == "drag") { + enablePasteHandler(); + } else { + disablePasteHandler(); + } + + if (type == "drawing" && !hasSetupDrawingBoardYet) { + setupDrawingBoard(); + hasSetupDrawingBoardYet = true; + } + }; + $f.find(".contented-upload-type").click(function () { + setType($(this).attr('data-upload-type')); }); - }; + // Widget positioning - var afterScriptsLoaded = function() { - - // Update fields in global variable - contented.init = initArea; - contented.loaded = true; + var $element = $(element); + var offset = $element.offset(); + + $f.css({ + 'position': 'absolute', + 'left': offset.left + "px", + 'top': offset.top + "px", + 'width': $element.width() + "px", + 'min-width': $element.width() + "px", + 'max-width': $element.width() + "px", + 'height': $element.height() + "px", + 'min-height': $element.height() + "px", + 'max-height': $element.height() + "px" + }); + + // Drag and drop support - // Call initArea for all pre-initialised elements - for (var i = 0; i < contented.__preInit.length; ++i) { - initArea(contented.__preInit[i][0], contented.__preInit[i][1], contented.__preInit[i][2]); + $f.find('.contented').on('dragover dragenter', function (e) { + e.preventDefault(); + e.stopPropagation(); + $(this).addClass('is-dragging'); + }); + + $f.find('.contented').on('dragleave dragend', function (e) { + e.preventDefault(); + e.stopPropagation(); + $(this).removeClass('is-dragging'); + }); + + $f.find('.contented').on('drop', function (e) { + e.preventDefault(); + e.stopPropagation(); + handleUploadFrom(e.originalEvent.dataTransfer.files); + }); + + $f.find('.contented-file-upload').on('click', function(e) { + e.preventDefault(); + e.stopPropagation(); + handleUploadFrom($(".contented-file-selector")[0].files); + }); + + // Pastebin + + $f.find('.contented-paste-upload').on('click', function(e) { + e.preventDefault(); + e.stopPropagation(); + var blob = new Blob([$(".contented-if-paste textarea").val()], {type : 'text/plain'}); + handleUploadFrom([blob]); + }); + + // Ctrl+V uploads + + var pasteHandler = function(e) { + e.preventDefault(); + e.stopPropagation(); + + var items = (e.clipboardData || e.originalEvent.clipboardData).items; + var items_length = items.length; + var blobs = []; + var handled = 0; + var haveHandled = function() { + handled += 1; + if (handled == items_length) { + + if (blobs.length > 0) { + handleUploadFrom( blobs ); + } else { + // alert("Pasted 0 files"); + } + } + }; + + for (var i = 0; i < items.length; ++i) { + var item = items[i]; + var mimeType = item.type; + if (item.kind === 'file') { + blobs.push(item.getAsFile()); + haveHandled(); + + } else if (item.kind === 'string') { + item.getAsString(function(s) { + blobs.push( new Blob([s], {type : mimeType}) ); + haveHandled(); + }); + + } else { + // file|string are the only supported types in + // all browsers at the time of writing + // Ignore future possibilities + haveHandled(); + } + } + }; + var enablePasteHandler = function() { + document.addEventListener('paste', pasteHandler); + }; + var disablePasteHandler = function() { + document.removeEventListener('paste', pasteHandler); + }; + + // Embed in DOM, load default area + + $("body").append($f); + if (!contented.supportsDrop()) { + setType('file'); + } else { + setType('drag'); } + + // Drawing board + + var setupDrawingBoard = function() { + + $("head").append( + '' + ); + + var db_id = "contented-drawing-area-" + guid(); + var $db = $("
").attr('id', db_id); + + DrawingBoard.Control.ContentedUpload = DrawingBoard.Control.extend({ + name: 'upload', + + initialize: function() { + var $el = this.$el; + + $el.append(''); + $el.on('click', '.contented-drawingboard-upload', $.proxy(function(e) { + e.preventDefault(); + e.stopPropagation(); + + $el.prop('disabled', true); + $el.text('Saving...'); + + $db.find("canvas")[0].toBlob(function(theBlob) { + handleUploadFrom([ theBlob ]); + }); + }, this)); + } + }); + + $db.css({ + //'width': $f.find(".contented-content-area").width(), + 'height': $f.find(".contented-content-area").height(), + 'overflow': 'hidden' + }); + + $f.find(".contented-drawing-area").append($db); + var db = new DrawingBoard.Board(db_id, { + 'controls': [ + 'Color', + 'Size', + 'DrawingMode', + 'Navigation', + 'ContentedUpload' + ], + 'controlsPosition': 'center', + 'enlargeYourContainer': false, + 'webStorage': false, + 'droppable': false // don't mess with existing drop support + }); + + }; + + // Close button + + var ourClose = function () { + $f.remove(); // remove from dom + disablePasteHandler(); + onClose(); // upstream close + }; + $f.find(".contented-close").click(function () { + ourClose(); + }) + + // Progress bar + + var setProgressCaption = function(message) { + $f.find(".contented-if-progress label").text(message); + }; + var setProgressPercentage = function(frc) { + $f.find(".contented-progress-element").css('width', (frc * 100) + "%"); + }; + + // Common upload handler + + var handleUploadFrom = function(files) { + + setProgressCaption("Uploading, please wait..."); + setProgressPercentage(0); + setType("progress"); + + $f.find(".contented-upload-type-selector").hide(); + $f.find(".contented").removeClass('is-dragging'); + + // Ajax uploader + var ajaxData = new FormData(); + for (var i = 0; i < files.length; ++i) { + ajaxData.append("f", files[i]); + } + + // ajax request + $.ajax({ + url: contented.baseURL + "upload", + type: "POST", + data: ajaxData, + dataType: 'json', // response type + cache: false, + contentType: false, + processData: false, + xhr: function() { + var xhr = $.ajaxSettings.xhr(); + xhr.upload.addEventListener( + 'progress', + function(ev) { + if (ev.lengthComputable) { + setProgressCaption("Uploading (" + formatBytes(ev.loaded) + " / " + formatBytes(ev.total) + ")..."); + setProgressPercentage(ev.total == 0 ? 0 : ev.loaded / ev.total); + } + }, + false + ); + return xhr; + }, + complete: function () { + setProgressPercentage(1); + }, + success: function (data) { + setProgressCaption("Upload completed successfully."); + onUploaded(data); + ourClose(); + }, + error: function () { + setProgressCaption("Upload failed!"); + } + }); + + } + }; var init = function() { @@ -537,6 +503,34 @@ var currentScriptPath = getCurrentScriptPath(); var baseURL = currentScriptPath.replace('sdk.js', ''); + // Kick off background promises + + var loader = new Promise(function(resolve, reject) { + if (typeof jQuery === "undefined") { + loadScript(contented.baseURL + "jquery-3.7.0.min.js").then(resolve); + } else { + resolve(); + } + + }).then(function() { return new Promise(function(resolve, reject) { + if (typeof DrawingBoard === "undefined") { + loadScript(contented.baseURL + "drawingboard-0.4.6.min.js").then(resolve); + } else { + resolve(); + } + + })}).then(function() { return new Promise(function(resolve, reject) { + $.get(contented.baseURL + "about", function (aboutInfo) { + resolve(aboutInfo); + }); + + })}).then(function(aboutInfo) { + // Update fields in global variable + window.contented.loaded = true; + + return aboutInfo; + }); + window.contented = { "loaded": false, @@ -552,7 +546,9 @@ * @param Function onClose Called when the widget is being destroyed */ "init": function(elementSelector, onUploaded, onClose) { - contented.__preInit.push([elementSelector, onUploaded, onClose]); + loader.then(function(aboutInfo) { + initArea(aboutInfo, elementSelector, onUploaded, onClose); + }); }, /** @@ -589,16 +585,6 @@ } }; - // Load scripts - var needScripts = []; - if (typeof jQuery === "undefined") { - needScripts.push(contented.baseURL + "jquery-3.7.0.min.js"); - } - if (typeof DrawingBoard === "undefined") { - needScripts.push(contented.baseURL + "drawingboard-0.4.6.min.js"); - } - - loadScripts(needScripts, afterScriptsLoaded); }; init();