%PDF- %PDF-
Direktori : /home/bitrix/www/bitrix/js/main/core/core_uploader/ |
Current File : /home/bitrix/www/bitrix/js/main/core/core_uploader/file.js |
;(function(window){ if (window.BX["UploaderFile"]) return false; var getOrientation = (function(){ var exif = { tags : { // 0x0100 : "ImageWidth", // 0x0101 : "ImageHeight", // 0x8769 : "ExifIFDPointer", // 0x8825 : "GPSInfoIFDPointer", // 0xA005 : "InteroperabilityIFDPointer", // 0x0102 : "BitsPerSample", // 0x0103 : "Compression", // 0x0106 : "PhotometricInterpretation", 0x0112 : "Orientation", // 0x0115 : "SamplesPerPixel", // 0x011C : "PlanarConfiguration", // 0x0212 : "YCbCrSubSampling", // 0x0213 : "YCbCrPositioning", // 0x011A : "XResolution", // 0x011B : "YResolution", // 0x0128 : "ResolutionUnit", // 0x0111 : "StripOffsets", // 0x0116 : "RowsPerStrip", // 0x0117 : "StripByteCounts", // 0x0201 : "JPEGInterchangeFormat", // 0x0202 : "JPEGInterchangeFormatLength", // 0x012D : "TransferFunction", // 0x013E : "WhitePoint", // 0x013F : "PrimaryChromaticities", // 0x0211 : "YCbCrCoefficients", // 0x0214 : "ReferenceBlackWhite", // 0x0132 : "DateTime", // 0x010E : "ImageDescription", // 0x010F : "Make", // 0x0110 : "Model", // 0x0131 : "Software", // 0x013B : "Artist", // 0x8298 : "Copyright" }, getStringFromDB : function (buffer, start, length) { var outstr = "", n; for (n = start; n < start+length; n++) { outstr += String.fromCharCode(buffer.getUint8(n)); } return outstr; }, readTags : function(file, tiffStart, dirStart, strings, bigEnd) { var entries = file.getUint16(dirStart, !bigEnd), tags = {}, entryOffset, tag, i, l = 0; for (i in strings) { if (strings.hasOwnProperty(i)) l++; } for (i = 0; i < entries; i++) { entryOffset = dirStart + i*12 + 2; tag = strings[file.getUint16(entryOffset, !bigEnd)]; tags[tag] = exif.readTagValue(file, entryOffset, tiffStart, dirStart, bigEnd); l--; if (l <= 0) break; } return tags; }, readTagValue : function(file, entryOffset, tiffStart, dirStart, bigEnd) { var type = file.getUint16(entryOffset+2, !bigEnd), numValues = file.getUint32(entryOffset+4, !bigEnd), valueOffset = file.getUint32(entryOffset+8, !bigEnd) + tiffStart, offset, vals, val, n, numerator, denominator; switch (type) { case 1: // byte, 8-bit unsigned int case 7: // undefined, 8-bit byte, value depending on field if (numValues == 1) { return file.getUint8(entryOffset + 8, !bigEnd); } else { offset = numValues > 4 ? valueOffset : (entryOffset + 8); vals = []; for (n=0;n<numValues;n++) { vals[n] = file.getUint8(offset + n); } return vals; } case 2: // ascii, 8-bit byte offset = numValues > 4 ? valueOffset : (entryOffset + 8); return exif.getStringFromDB(file, offset, numValues-1); case 3: // short, 16 bit int if (numValues == 1) { return file.getUint16(entryOffset + 8, !bigEnd); } else { offset = numValues > 2 ? valueOffset : (entryOffset + 8); vals = []; for (n=0;n<numValues;n++) { vals[n] = file.getUint16(offset + 2*n, !bigEnd); } return vals; } case 4: // long, 32 bit int if (numValues == 1) { return file.getUint32(entryOffset + 8, !bigEnd); } else { vals = []; for (n=0;n<numValues;n++) { vals[n] = file.getUint32(valueOffset + 4*n, !bigEnd); } return vals; } case 5: // rational = two long values, first is numerator, second is denominator if (numValues == 1) { numerator = file.getUint32(valueOffset, !bigEnd); denominator = file.getUint32(valueOffset+4, !bigEnd); val = new Number(numerator / denominator); val.numerator = numerator; val.denominator = denominator; return val; } else { vals = []; for (n=0;n<numValues;n++) { numerator = file.getUint32(valueOffset + 8*n, !bigEnd); denominator = file.getUint32(valueOffset+4 + 8*n, !bigEnd); vals[n] = new Number(numerator / denominator); vals[n].numerator = numerator; vals[n].denominator = denominator; } return vals; } case 9: // slong, 32 bit signed int if (numValues == 1) { return file.getInt32(entryOffset + 8, !bigEnd); } else { vals = []; for (n=0;n<numValues;n++) { vals[n] = file.getInt32(valueOffset + 4*n, !bigEnd); } return vals; } case 10: // signed rational, two slongs, first is numerator, second is denominator if (numValues == 1) { return file.getInt32(valueOffset, !bigEnd) / file.getInt32(valueOffset+4, !bigEnd); } else { vals = []; for (n=0;n<numValues;n++) { vals[n] = file.getInt32(valueOffset + 8*n, !bigEnd) / file.getInt32(valueOffset+4 + 8*n, !bigEnd); } return vals; } } }, readData : function (file, start) { if (exif.getStringFromDB(file, start, 4) != "Exif") { return false; } var bigEnd, tiffOffset = start + 6; // test for TIFF validity and endianness if (file.getUint16(tiffOffset) == 0x4949) { bigEnd = false; } else if (file.getUint16(tiffOffset) == 0x4D4D) { bigEnd = true; } else { return false; } if (file.getUint16(tiffOffset+2, !bigEnd) != 0x002A) { return false; } var firstIFDOffset = file.getUint32(tiffOffset + 4, !bigEnd); if (firstIFDOffset < 0x00000008) { return false; } return exif.readTags(file, tiffOffset, tiffOffset + firstIFDOffset, exif.tags, bigEnd); }, readBase64 : function (base64) { base64 = base64.replace(/^data\:([^\;]+)\;base64,/gmi, ''); var binary_string = window.atob(base64), //decode base64 len = binary_string.length, bytes = new Uint8Array(len); for (var i = 0; i < len; i++) { bytes[i] = binary_string.charCodeAt(i); } var dataView = new DataView(bytes.buffer); if ((dataView.getUint8(0) != 0xFF) || (dataView.getUint8(1) != 0xD8)) { return false; // not a valid jpeg } var offset = 2, length = bytes.buffer.byteLength, marker, result = false; while (offset < length) { if (dataView.getUint8(offset) != 0xFF) { break; // not a valid marker, something is wrong } marker = dataView.getUint8(offset + 1); // we could implement handling for other markers here, // but we're only looking for 0xFFE1 for EXIF data if (marker == 225) { result = exif.readData(dataView, offset + 4, dataView.getUint16(offset + 2) - 2); break; } else { offset += 2 + dataView.getUint16(offset+2); } } return result; } }; return function(base64){ if (BX.type.isString(base64)) { try { var tags = exif.readBase64(base64); if(tags && tags["Orientation"]) return tags["Orientation"]; } catch (e) { } } return false; }; })(), setOrientation = function(image, cnv, ctx, exifOrientation) { var width = image.width, height = image.height; if ([5,6,7,8].indexOf(exifOrientation) >= 0) { width = image.height; height = image.width; } BX.adjust(cnv, {props: {width: width, height: height}}); ctx.save(); switch(exifOrientation) { case 2: // $img.addClass('flip'); ctx.scale(-1, 1); ctx.translate(-cnv.width, 0); break; case 3: // $img.addClass('rotate-180'); ctx.translate(cnv.width, cnv.height); ctx.rotate(Math.PI); break; case 4: // $img.addClass('flip-and-rotate-180'); ctx.scale(-1, 1); ctx.translate(0, cnv.height); ctx.rotate(Math.PI); break; case 5: // $img.addClass('flip-and-rotate-90'); ctx.scale(-1, 1); ctx.translate(0, 0); ctx.rotate(Math.PI / 2); break; case 6: // $img.addClass('rotate-90'); ctx.translate(cnv.width, 0); ctx.rotate(Math.PI / 2); break; case 7: // $img.addClass('flip-and-rotate-90'); ctx.scale(-1, 1); ctx.translate(-cnv.width, cnv.height); ctx.rotate(Math.PI * 3 / 2); break; case 8: // $img.addClass('rotate-270'); ctx.translate(0, cnv.height); ctx.rotate(Math.PI * 3 / 2); break; } ctx.drawImage(image, 0, 0); ctx.restore(); }; var BX = window.BX, statuses = { "new" : 0, ready : 1, preparing : 2, inprogress : 3, done : 4, failed : 5, stopped : 6, changed : 7, uploaded : 8}, cnvConstr = (function(){ var cnvConstructor = function(timelimit) { this.timeLimit = (typeof timelimit === "number" && timelimit > 0 ? timelimit : 50); this.status = statuses.ready; this.queue = new BX.UploaderUtils.Hash(); this.id = (new Date()).getTime(); }; cnvConstructor.prototype = { counter : 0, active : null, image : null, getImage : function() { if (!this.image) this.image = new Image(); return this.image; }, canvas : null, getCanvas : function() { if (!this.canvas) { this.canvas = BX.create('CANVAS', {style : {display: "none"}}); document.body.appendChild(this.canvas); } return this.canvas; }, context : null, getContext : function() { if (!this.context && this.getCanvas()["getContext"]) this.context = this.getCanvas().getContext('2d'); return this.context; }, reader : null, getReader : function() { if (!this.reader && window["FileReader"]) this.reader = new FileReader(); return this.reader; }, load : function(file, callback, id, callbackFail) { if (this.active !== null || (this.getReader() && this.getReader().readyState == 1)) return; this.counter++; this.active = file; var image = this.getImage(); BX.unbindAll(image); image.onload = function(){}; image.onerror = function(){}; /* Almost all browsers cache images from local resource except of FF on 06.03.2017. It appears that FF collect src and does not abort image uploading when src is changed. And we had a bug when in onload event we got e.target.src of one element but source of image was from '/bitrix/images/1.gif'. */ // TODO check if chrome and other browsers cache local files for now. If it does not then delete next 2 strings if (!BX.browser.IsFirefox()) image.src = '/bitrix/images/1.gif'; /** For Garbage collector */ this.onload = null; delete this.onload; this.onerror = null; delete this.onerror; this.onload = BX.delegate(function(e){ if (e && e.target && e.target.src && e.target.src.substr(-20) == "/bitrix/images/1.gif") return; if (!!callback) { try { callback(BX.proxy_context, this.getCanvas(), this.getContext(), getOrientation((((e && e.target && e.target.src) ? e.target.src : (BX.proxy_context || null))))); } catch (e) { BX.debug(e); } } if (!!id) { this.queue.removeItem(id); setTimeout(BX.proxy(function() { this.active = null; this.exec(); }, this), this.timeLimit); } else this.active = null; }, this); this.onerror = BX.delegate(function(){ if (!!callbackFail) { try { callbackFail(BX.proxy_context); } catch (e) { BX.debug(e); } } if (!!id) { this.queue.removeItem(id); setTimeout(BX.proxy(function() { this.active = null; this.exec(); }, this), this.timeLimit); } else this.active = null; }, this); image.name = file.name; image.onload = this.onload; image.onerror = this.onerror; var res = Object.prototype.toString.call(file); if (file["tmp_url"]) { image.src = file["tmp_url"] + (file["tmp_url"].indexOf("?") > 0 ? '&' : '?') + 'imageUploader' + this.id + this.counter; } else if (res !== '[object File]' && res !== '[object Blob]') { this.onerror(null); } else if (window["URL"]) { image.src = window["URL"]["createObjectURL"](file); } else if (this.getReader() !== null) { this.__readerOnLoad = null; delete this.__readerOnLoad; this.__readerOnLoad = BX.delegate(function(e) { this.__readerOnLoad = null; delete this.__readerOnLoad; image.src = e.target.result; }, this); this.getReader().onloadend = this.__readerOnLoad; this.getReader().onerror = BX.proxy(function(e) { this.onerror(null); }, this); this.getReader().readAsDataURL(file); } }, push : function(file, callback, failCallback) { var id = BX.UploaderUtils.getId(); this.queue.setItem(id, [id, file, callback, failCallback]); this.exec(); }, exec : function() { var item = this.queue.getFirst(); if (!!item) this.load(item[1], item[2], item[0], item[3]); }, pack : function(fileType) { return BX.UploaderUtils.dataURLToBlob(this.getCanvas().toDataURL(fileType)); } }; return cnvConstructor; })(); BX.UploaderFileCnvConstr = cnvConstr; BX.UploaderFileFileLoader = (function(){ var d = function(timelimit) { this.timeLimit = (typeof timelimit === "number" && timelimit > 0 ? timelimit : 50); this.status = statuses.ready; this.queue = new BX.UploaderUtils.Hash(); this._exec = BX.delegate(this.exec, this); }; d.prototype = { xhr : null, goToNext : function(id) { delete this.xhr; this.xhr = null; this.queue.removeItem(id); this.status = statuses.ready; setTimeout(this._exec, this.timeLimit); }, load : function(id, path, onsuccess, onfailure) { if (this.status != statuses.ready) return; this.status = statuses.inprogress; var _this = this; this.xhr = BX.ajax({ 'method': 'GET', 'data' : '', 'url': path, 'onsuccess': function(blob){if (blob === null){onfailure(blob);} else {onsuccess(blob);} _this.goToNext(id);}, 'onfailure': function(blob){onfailure(blob); _this.goToNext(id);}, 'start': false, 'preparePost':false, 'processData':false }); this.xhr.withCredentials = true; this.xhr.responseType = 'blob'; this.xhr.send(); }, push : function(path, onsuccess, onfailure) { var id = BX.UploaderUtils.getId(); this.queue.setItem(id, [id, path, onsuccess, onfailure]); this.exec(); }, exec : function() { var item = this.queue.getFirst(); if (!!item) this.load(item[0], item[1], item[2], item[3]); } }; return d; })(); var prvw = new cnvConstr(), upld = new cnvConstr(), edtr = new cnvConstr(), canvas = BX.create('CANVAS'), ctx; /** * @return {BX.UploaderFile} * @file file * @params array * @limits array * @caller {BX.Uploader} * You should work with params["fields"] in case you want to change visual part */ var mobileNames = {}; BX.UploaderFile = function (file, params, limits, caller) { this.dialogName = (this.dialogName ? this.dialogName : "BX.UploaderFile"); this.file = file; this.id = (file['id'] || 'file' + BX.UploaderUtils.getId()); this.name = file.name; this.isNode = false; if (BX.type.isDomNode(file)) { this.isNode = true; this.name = BX.UploaderUtils.getFileNameOnly(file.value); if (/\[(.+?)\]/.test(file.name)) { var tmp = /\[(.+?)\]/.exec(file.name); this.id = tmp[1]; } this.file.bxuHandler = this; } else if (file["tmp_url"] && !file["name"]) { this.name = BX.UploaderUtils.getFileNameOnly(file["tmp_url"]); } this.preview = '<span id="' + this.id + 'Canvas" class="bx-bxu-canvas"></span>'; this.nameWithoutExt = (this.name.lastIndexOf('.') > 0 ? this.name.substr(0, this.name.lastIndexOf('.')) : this.name); this.ext = this.name.substr(this.nameWithoutExt.length + 1); if (/iPhone|iPad|iPod/i.test(navigator.userAgent) && this.nameWithoutExt == "image") { var nameWithoutExt = 'mobile_' + BX.date.format("Ymd_His"); mobileNames[nameWithoutExt] = (mobileNames[nameWithoutExt] || 0); this.nameWithoutExt = nameWithoutExt + (mobileNames[nameWithoutExt] > 0 ? ("_" + mobileNames[nameWithoutExt]) : ""); this.name = this.nameWithoutExt + (BX.type.isNotEmptyString(this.ext) ? ("." + this.ext) : ""); mobileNames[nameWithoutExt]++; } this.size = ''; if (file.size) this.size = BX.UploaderUtils.getFormattedSize(file.size, 0); this.type = file.type; this.status = statuses["new"]; this.limits = limits; this.caller = caller; this.fields = { thumb : { tagName : 'SPAN', template : '<div class="someclass">#preview#<div>#name#</div>', editorTemplate : '<div class="someeditorclass"><div>#name#</div>', className : "bx-bxu-thumb-thumb", placeHolder : null }, preview : { params : { width : 400, height : 400 }, template : "#preview#", editorParams : { width : 1024, height : 860 }, editorTemplate : '<span>#preview#</span>', className : "bx-bxu-thumb-preview", placeHolder : null, events : { click : BX.delegate(this.clickFile, this) }, type : "html" }, name : { template : "#name#", editorTemplate : '<span><input type="text" name="name" value="#name#" /></span>', className : "bx-bxu-thumb-name", placeHolder : null }, type : { template : "#type#", editorTemplate : '#type#', className : "bx-bxu-thumb-type", placeHolder : null } }; if (!!params["fields"]) { var ij, key; for (var ii in params["fields"]) { if (params["fields"].hasOwnProperty(ii)) { if (!!this.fields[ii]) { for (ij in params["fields"][ii]) { if (params["fields"][ii].hasOwnProperty(ij)) { this.fields[ii][ij] = params["fields"][ii][ij]; } } } else this.fields[ii] = params["fields"][ii]; key = ii + ''; if (key.toLowerCase() != "thumb" && key.toLowerCase() != "preview") { this[key.toLowerCase()] = (!!params["fields"][ii]["value"] ? params["fields"][ii]["value"] : ""); this.log(key.toLowerCase() + ': ' + this[key.toLowerCase()]); } } } } BX.onCustomEvent(this, "onFileIsCreated", [this.id, this, this.caller]); BX.onCustomEvent(this.caller, "onFileIsCreated", [this.id, this, this.caller]); this.makePreview(); this.preparationStatus = statuses.done; return this; }; BX.UploaderFile.prototype = { log : function(text) { BX.UploaderUtils.log('file ' + this.name, text); }, makeThumb : function() { var template = this.fields.thumb.template, name, ii, events = {}, node, jj; for (ii in this.fields) { if (this.fields.hasOwnProperty(ii)) { if (this.fields[ii].template && this.fields[ii].template.indexOf('#' + ii + '#') >= 0) { name = this.id + ii.toUpperCase().substr(0, 1) + ii.substr(1); node = this.setProps(ii, this[ii], true); template = template.replace('#' + ii + '#', '<span id="' + name + '" class="' + this.fields[ii]["className"] + '">' + ( BX.type.isNotEmptyString(node.html) ? node.html.replace("#", "<\x19>") : node.html) + '</span>'); for (jj in node.events) { if (node.events.hasOwnProperty(jj)) { events[jj] = node.events[jj]; } } if (!!this.fields[ii].events) events[name] = this.fields[ii].events; } } } var res, patt = [], repl = [], tmp; while ((res = /#([^\\<\\>\\"\\']+?)#/gi.exec(template)) && !!res) { if (this[res[1]] !== undefined) { template = template.replace(res[0], BX.type.isNotEmptyString(this[res[1]]) ? this[res[1]].replace("#", "<\x19>") : this[res[1]]); } else { tmp = "<\x18" + patt.length + ">"; patt.push(tmp); repl.push(res[0]); template = template.replace(res[0], tmp); } } while ((res = patt.shift()) && res) { tmp = repl.shift(); template = template.replace(res, tmp); } template = template.replace("<\x19>", "#"); if (!!this.fields.thumb.tagName) { res = BX.create(this.fields.thumb.tagName, { attrs : { id : (this.id + 'Thumb'), className : this.fields.thumb.className }, events : this.fields.thumb.events, html : template } ); } else { res = template; } this.__makeThumbEventsObj = events; this.__makeThumbEvents = BX.delegate(function() { var ii, jj; for (ii in events) { if (events.hasOwnProperty(ii) && BX(ii)) { for (jj in events[ii]) { if (events[ii].hasOwnProperty(jj)) { BX.bind(BX(ii), jj, events[ii][jj]); } } } } this.__makeThumbEvents = null; delete this.__makeThumbEvents; }, this); BX.addCustomEvent(this, "onFileIsAppended", this.__makeThumbEvents); if (BX.type.isDomNode(this.file)) { if (BX.type.isString(template)) { this.__bindFileNode = BX.delegate(function(id) { var node = BX(id + 'Item'); if (node.tagName == 'TR') node.cells[0].appendChild(this.file); else if (node.tagName == 'TABLE') node.rows[0].cells[0].appendChild(this.file); else BX(id + 'Item').appendChild(this.file); this.__bindFileNode = null; delete this.__bindFileNode; }, this); BX.addCustomEvent(this, "onFileIsAppended", this.__bindFileNode); } else { res.appendChild(this.file); } } return res; }, checkProps : function() { var el2 = BX.UploaderUtils.FormToArray({elements : [BX.proxy_context]}), ii; for (ii in el2.data) { if (el2.data.hasOwnProperty(ii)) this[ii] = el2.data[ii]; } }, setProps : function(name, val, bReturn) { if (typeof name == "string") { if (name == "size") val = BX.UploaderUtils.getFormattedSize(this.file.size, 0); if (typeof this[name] != "undefined" && typeof this.fields[name] != "undefined") { this[name] = val; var template = this.fields[name].template. replace('#' + name + '#', this.fields[name]["type"] === "html" ? (val || '') : BX.util.htmlspecialchars(val || '')). replace(/#id#/gi, this.id), fii, fjj, el, result = {html : template, events : {}}; this.hiddenForm = (!!this.hiddenForm ? this.hiddenForm : BX.create("FORM", { style : { display : "none" } } )); this._checkProps = (!!this._checkProps ? this._checkProps : BX.delegate(this.checkProps, this)); this.hiddenForm.innerHTML = template; if (this.hiddenForm.elements.length > 0) { for (fii = 0; fii < this.hiddenForm.elements.length; fii++) { el = this.hiddenForm.elements[fii]; if (typeof this[el.name] != "undefined") { if (!el.hasAttribute("id")) el.setAttribute("id", this.id + name + BX.UploaderUtils.getId()); result.events[el.id] = { blur : this._checkProps } } } result.html = this.hiddenForm.innerHTML; } if (BX(this.hiddenForm)) BX.remove(this.hiddenForm); this.hiddenForm = null; delete this.hiddenForm; if (bReturn) return result; var node = this.getPH(name); if (!!node) { node.innerHTML = result.html; for (fii in result.events) { if (result.events.hasOwnProperty(fii)) { for (fjj in result.events[fii]) { if (result.events[fii].hasOwnProperty(fjj)) { BX.bind(BX(fii), fjj, result.events[fii][fjj]); } } } } } } } else if (!!name) { for (var ij in name) { if (name.hasOwnProperty(ij)) { if (this.fields.hasOwnProperty(ij) && ij !== "preview") this.setProps(ij, name[ij]); } } } return true; }, getProps : function(name) { if (name == "canvas") { return BX(this.id + "ProperCanvas"); } else if (typeof name == "string") { return this[name]; } var data = {}; for (var ii in this.fields) { if (this.fields.hasOwnProperty(ii) && (ii !== "preview" && ii !== "thumb")) { data[ii] = this[ii]; } } data["size"] = this.file["size"]; data["type"] = this["type"]; if (!!this.copies) { var copy; data["canvases"] = {}; while ((copy = this.copies.getNext()) && !!copy) { data["canvases"][copy.id] = { width : copy.width, height : copy.height, name : copy.name }; } } return data; }, getThumbs : function() { return null; }, getPH : function(name) { name = (typeof name === "string" ? name : ""); name = name.toLowerCase(); if (this.fields.hasOwnProperty(name)) { var id = name.substr(0, 1).toUpperCase() + name.substr(1); this.fields[name]["placeHolder"] = BX(this.id + id); return this.fields[name]["placeHolder"]; } return null; }, clickFile : function () { return false; }, makePreview: function() { this.status = statuses.ready; BX.onCustomEvent(this, "onFileIsInited", [this.id, this, this.caller]); BX.onCustomEvent(this.caller, "onFileIsInited", [this.id, this, this.caller]); this.log('is initialized as a file'); }, preparationStatus : statuses.ready, deleteFile: function() { var ii, events = this.__makeThumbEventsObj; for (ii in this.fields) { if (this.fields.hasOwnProperty(ii)) { if (!!this.fields[ii]["placeHolder"]) { this.fields[ii]["placeHolder"] = null; BX.unbindAll(this.fields[ii]["placeHolder"]); delete this.fields[ii]["placeHolder"]; } } } for (ii in events) { if (events.hasOwnProperty(ii) && BX(ii)) { BX.unbindAll(BX(ii)); } } this.file = null; delete this.file; BX.remove(this.canvas); this.canvas = null; delete this.canvas; BX.onCustomEvent(this.caller, "onFileIsDeleted", [this.id, this, this.caller]); BX.onCustomEvent(this, "onFileIsDeleted", [this, this.caller]); } }; BX.UploaderImage = function(file, params, limits, caller) { this.dialogName = "BX.UploaderImage"; BX.UploaderImage.superclass.constructor.apply(this, arguments); this.isImage = true; this.copies = new BX.UploaderUtils.Hash(); this.caller = caller; if (!this.isNode && BX.Uploader.getInstanceName() == "BX.Uploader") { if (!!params["copies"]) { var copies = params["copies"], copy; for (var ii in copies) { if (copies.hasOwnProperty(ii) && !!copies[ii]) { copy = { width : parseInt(copies[ii]['width']), height : parseInt(copies[ii]["height"]), id : ii }; if (copy['width'] > 0 && copy["height"] > 0) { this.copies.setItem(ii, copy); } } } } this.preparationStatus = statuses["new"]; BX.addCustomEvent(this, "onFileHasToBePrepared", BX.delegate(function() { this.preparationStatus = statuses.inprogress; if (this.status != statuses["new"]) { upld.push(this.file, BX.delegate(this.makeCopies, this)); } }, this)); BX.addCustomEvent(this, "onUploadDone", BX.delegate(function() { var copy; while ((copy = this.copies.getNext()) && !!copy) { copy.file = null; delete copy.file; } this.preparationStatus = statuses["new"]; }, this)); this.canvas = BX.create('CANVAS', {attrs : { id : this.id + "ProperCanvas" } } ); } else { this.preparationStatus = statuses.done; this.canvas = null; } return this; }; BX.extend(BX.UploaderImage, BX.UploaderFile); BX.UploaderImage.prototype.makePreviewImageWork = function(image, cnv, ctx, exifOrientation) { exifOrientation = parseInt(exifOrientation); var result = null, width = cnv.width, height = cnv.height; if (this.file) { this.file.width = cnv.width; this.file.height = cnv.height; } if (!!this.canvas) { setOrientation(image, cnv, ctx, exifOrientation); if (this.file) { this.file.width = cnv.width; this.file.height = cnv.height; if (exifOrientation) { this.file.exif = { Orientation : exifOrientation } } } this.applyFile(cnv, false); result = this.canvas; } else if (BX(this.id + 'Canvas')) { var res2 = BX.UploaderUtils.scaleImage({width : width, height : height}, this.fields.preview.params), props = { props : { width : res2.destin.width, height : res2.destin.height, src : image.src }, attrs : { className : (this.file.width > this.file.height ? "landscape" : "portrait") } }; switch (exifOrientation) { case 2: props.attrs.className += ' flip'; break; case 3: props.attrs.className += ' rotate-180'; break; case 4: props.attrs.className += ' flip-and-rotate-180'; break; case 5: props.attrs.className += ' flip-and-rotate-270'; break; case 6: props.attrs.className += ' rotate-90'; break; case 7: props.attrs.className += ' flip-and-rotate-90'; break; case 8: props.attrs.className += ' rotate-270'; break; } result = BX.create("IMG", props); } BX.onCustomEvent(this, "onFileCanvasIsLoaded", [this.id, this, this.caller, image]); BX.onCustomEvent(this.caller, "onFileCanvasIsLoaded", [this.id, this, this.caller, image]); if (BX(this.id + 'Canvas')) BX(this.id + 'Canvas').appendChild(result); return result; }; BX.UploaderImage.prototype.makePreviewImageLoadHandler = function(image, canvas, context, exifOrientation){ this.makePreviewImageWork(image, canvas, context, exifOrientation); this.status = statuses.ready; BX.onCustomEvent(this, "onFileIsInited", [this.id, this, this.caller]); BX.onCustomEvent(this.caller, "onFileIsInited", [this.id, this, this.caller]); this.log('is initialized as an image with preview'); if (this.preparationStatus == statuses.inprogress) this.makeCopies(image, canvas, context, exifOrientation); if (this["_makePreviewImageLoadHandler"]) { this._makePreviewImageLoadHandler = null; delete this._makePreviewImageLoadHandler; } if (this["_makePreviewImageFailedHandler"]) { this._makePreviewImageFailedHandler = null; delete this._makePreviewImageFailedHandler; } }; BX.UploaderImage.prototype.makePreviewImageFailedHandler = function(){ this.status = statuses.ready; this.preparationStatus = statuses.done; BX.onCustomEvent(this, "onFileIsInited", [this.id, this, this.caller]); BX.onCustomEvent(this.caller, "onFileIsInited", [this.id, this, this.caller]); this.log('is initialized without canvas'); if (this["_makePreviewImageLoadHandler"]) { this._makePreviewImageLoadHandler = null; delete this._makePreviewImageLoadHandler; } if (this["_makePreviewImageFailedHandler"]) { this._makePreviewImageFailedHandler = null; delete this._makePreviewImageFailedHandler; } }; BX.UploaderImage.prototype.makePreview = function() { if (!this.isNode) { this._makePreviewImageLoadHandler = BX.delegate(this.makePreviewImageLoadHandler, this); this._makePreviewImageFailedHandler = BX.delegate(this.makePreviewImageFailedHandler, this); prvw.push(this.file, this._makePreviewImageLoadHandler, this._makePreviewImageFailedHandler); } else { this.status = statuses.ready; BX.onCustomEvent(this, "onFileIsInited", [this.id, this, this.caller]); BX.onCustomEvent(this.caller, "onFileIsInited", [this.id, this, this.caller]); this.log('is initialized as an image without preview'); if (this.caller.queue.placeHolder) { this._onFileHasGotPreview = BX.delegate(function(id, item) { BX.removeCustomEvent(this, "onFileHasGotPreview", this._onFileHasGotPreview); BX.removeCustomEvent(this, "onFileHasNotGotPreview", this._onFileHasNotGotPreview); this._makePreviewImageLoadHandler = BX.delegate(function(image){ image = this.makePreviewImageWork(image); BX.onCustomEvent(this, "onFileHasPreview", [item.id, item, image]); delete this._makePreviewImageLoadHandler; delete this._makePreviewImageFailedHandler; }, this); this._makePreviewImageFailedHandler = BX.delegate(function(image){ delete this._makePreviewImageLoadHandler; delete this._makePreviewImageFailedHandler; }, this); prvw.push({tmp_url : item.file.url}, this._makePreviewImageLoadHandler, this._makePreviewImageFailedHandler); }, this); this._onFileHasNotGotPreview = BX.delegate(function(id){ if (id == this.id) { BX.removeCustomEvent(this, "onFileHasGotPreview", this._onFileHasGotPreview); BX.removeCustomEvent(this, "onFileHasNotGotPreview", this._onFileHasNotGotPreview); } }, this); BX.addCustomEvent(this, "onFileHasGotPreview", this._onFileHasGotPreview); BX.addCustomEvent(this, "onFileHasNotGotPreview", this._onFileHasNotGotPreview); BX.onCustomEvent(this.caller, "onFileNeedsPreview", [this.id, this, this.caller]); } } return true; }; BX.UploaderImage.prototype.checkPreview = function() { // TODO check preview }; BX.UploaderImage.prototype.applyFile = function(cnv, params) { this.checkPreview(); if (!!params && params.data ) this.setProps(params.data); var realScale = BX.UploaderUtils.scaleImage(cnv, {width : this.limits["uploadFileWidth"], height : this.limits["uploadFileHeight"]}), prvwScale = BX.UploaderUtils.scaleImage(cnv, this.fields.preview.params), prvwProps = { props : { width : prvwScale.destin.width, height : prvwScale.destin.height }, attrs : { className : "bx-bxu-proper-canvas"+(prvwScale.destin.width > prvwScale.destin.height ? " landscape" : " portrait") } }; if (realScale.bNeedCreatePicture || !!params) { BX.adjust(canvas, { props : { width : realScale.destin.width, height : realScale.destin.height } } ); ctx = canvas.getContext('2d'); ctx.drawImage(cnv, realScale.source.x, realScale.source.y, realScale.source.width, realScale.source.height, realScale.destin.x, realScale.destin.y, realScale.destin.width, realScale.destin.height ); var dataURI = canvas.toDataURL(this.file.type); this.file = BX.UploaderUtils.dataURLToBlob(dataURI); } this.file.name = this.name; this.file.width = realScale.destin.width; this.file.height = realScale.destin.height; BX.adjust(this.canvas, prvwProps); ctx = this.canvas.getContext('2d'); ctx.drawImage(cnv, prvwScale.source.x, prvwScale.source.y, prvwScale.source.width, prvwScale.source.height, prvwScale.destin.x, prvwScale.destin.y, prvwScale.destin.width, prvwScale.destin.height ); ctx = null; cnv = null; this.setProps('size'); this.status = statuses.changed; }; BX.UploaderImage.prototype.clickFile = function() { if (!this.canvas || !BX["CanvasEditor"] || this.status == statuses["new"]) return false; if (!this.__showEditor) { this.__showEditor = BX.delegate(this.showEditor, this); this.eFunc = { "apply" : BX.delegate(this.applyFile, this), "delete" : BX.delegate(this.deleteFile, this), "clear" : BX.delegate(function() { BX.removeCustomEvent(editor, "onApplyCanvas", this.eFunc["apply"]); BX.removeCustomEvent(editor, "onDeleteCanvas", this.eFunc["delete"]); BX.removeCustomEvent(editor, "onClose", this.eFunc["clear"]); }, this) }; } var template = this.fields.thumb.editorTemplate, name; for (var ii in this.fields) { if (this.fields.hasOwnProperty(ii)) { name = ii.substr(0, 1).toUpperCase() + ii.substr(1); template = template.replace('#' + ii + '#', (ii === "preview" ? "" : ('<span id="' + this.id + name + 'Editor" class="' + this.fields[ii]["className"] + '">' + this.fields[ii]["editorTemplate"].replace('#' + ii + '#', (!!this[ii] ? BX.util.htmlspecialchars(this[ii]) : '')) + '</span>'))); } } BX.adjust(edtr.getCanvas(), { props : { width : this.file.width, height : this.file.height } } ); edtr.getContext().drawImage(this.canvas, 0, 0, this.canvas.width, this.canvas.height, 0, 0, edtr.getCanvas().width, edtr.getCanvas().height); var editor = BX.CanvasEditor.show(edtr.getCanvas(), {title : this.name, template : template}); BX.addCustomEvent(editor, "onApplyCanvas", this.eFunc["apply"]); BX.addCustomEvent(editor, "onDeleteCanvas", this.eFunc["delete"]); BX.addCustomEvent(editor, "onClose", this.eFunc["clear"]); BX.onCustomEvent(this, "onCanvasEditorIsCreated", [editor, this]); edtr.push(this.file, this.__showEditor); this.editor = editor; return false; }; BX.UploaderImage.prototype.showEditor = function(image, canvas, context, exifOrientation) { BX.adjust(canvas, { props : { width : this.file.width, height : this.file.height } } ); setOrientation(image, canvas, context, exifOrientation); this.editor.copyCanvas(canvas); }; BX.UploaderImage.prototype.makeCopies = function(image, cnv, ctx, exifOrientation) { var copy, res, dataURI, result, context = canvas.getContext('2d'); setOrientation(image, canvas, context, exifOrientation); while ((copy = this.copies.getNext()) && !!copy) { res = BX.UploaderUtils.scaleImage(canvas, copy); BX.adjust(cnv, {props : { width : res.destin.width, height : res.destin.height } } ); ctx.drawImage(canvas, res.source.x, res.source.y, res.source.width, res.source.height, res.destin.x, res.destin.y, res.destin.width, res.destin.height ); dataURI = cnv.toDataURL(this.file.type); result = BX.UploaderUtils.dataURLToBlob(dataURI); result.width = cnv.width; result.height = cnv.height; result.name = this.name; result.thumb = copy.id; result.canvases = this.copies.length; result.canvas = this.copies.pointer - 1; copy.file = result; } this.preparationStatus = statuses.done; }; BX.UploaderImage.prototype.getThumbs = function(name) { if (name == "getCount") return this.copies.length; var res = (typeof name == "string" ? this.copies.getItem(name) : this.copies.getNext()); if (!!res) return res.file; return null; }; return true; }(window));