PageRenderTime 46ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/SitecorePackages/02_sxa/Sitecore Experience Accelerator 1.2 rev. 161216 for 8.2/sitecore/shell/client/Business Component Library/Layouts/Renderings/Forms/Uploader/Uploader.js

https://bitbucket.org/ranjith_rajendran/scph-skinalliance
JavaScript | 574 lines | 473 code | 84 blank | 17 comment | 66 complexity | 620ea97c1d975ebe622992e8987d8035 MD5 | raw file
  1. /// <reference path="../../../../Assets/lib/ui/deps/jQueryUI/jquery-ui-1.8.23.custom.min.js" />
  2. require.config({
  3. paths: {
  4. fileUpload: "/sitecore/shell/client/Speak/Assets/lib/ui/1.1/deps/jquery-File-Upload/jquery.fileupload",
  5. iFrameTransport: "/sitecore/shell/client/Speak/Assets/lib/ui/1.1/deps/jquery-File-Upload/jquery.iframe-transport"
  6. },
  7. shim: {
  8. 'fileUpload': { deps: ['jqueryui'] },
  9. 'iFrameTransport': { deps: ['fileUpload'] }
  10. }
  11. });
  12. define(["sitecore", "jqueryui", "fileUpload", "iFrameTransport"], function (_sc, fileUpload) {
  13. var progEv = !!(window.ProgressEvent),
  14. fdata = !!(window.FormData),
  15. wCreds = window.XMLHttpRequest && "withCredentials" in new XMLHttpRequest,
  16. hasXMLRequestLevel2 = progEv && fdata && wCreds,
  17. ONLYIMAGE = /^(image\/bmp|image\/dib|image\/gif|image\/jpeg|image\/jpg|image\/jpe|image\/jfif|image\/png|image\/tif|image\/tiff)$/i,
  18. uploadedSize = 0,
  19. iMaxFilesize = 10485760, // 10MB
  20. fileSizeExceededErrorMessage = "",
  21. timeoutErrorMessage = "",
  22. uploadTimer,
  23. removeExtension = function (name) {
  24. return name.replace(/\.[^/.]+$/, "");
  25. },
  26. bytesToSize = function (bytes) {
  27. var sizes = ['bytes', 'Kb', 'Mb'];
  28. if (bytes == 0) return '0 bytes';
  29. var i = parseInt(Math.floor(Math.log(bytes) / Math.log(1024)));
  30. return (bytes / Math.pow(1024, i)).toFixed(1) + ' ' + sizes[i];
  31. },
  32. Files = Backbone.Collection.extend({
  33. model: _sc.Definitions.Models.Model
  34. }),
  35. validateFile = function (file) {
  36. file.errors = file.errors || [];
  37. if (file.size > iMaxFilesize) {
  38. file.errors.push({ param: "size", msg: "invalid size" });
  39. }
  40. },
  41. validateFiles = function (files) {
  42. _.each(files, validateFile);
  43. },
  44. prepareData = function (file, component) {
  45. file.__id = _.uniqueId("file_");
  46. var size = file.size || 0;
  47. component.totalSize += size;
  48. return {
  49. id: file.__id,
  50. name: removeExtension(file.name),
  51. size: size,
  52. fileSize: bytesToSize(size),
  53. type: file.type,
  54. percentage: 0,
  55. data: file,
  56. done: undefined,
  57. bytesTransfered: 0,
  58. description: "",
  59. alternate: ""
  60. };
  61. },
  62. setupDataForFiles = function (preview, files, component, cb) {
  63. var that = this;
  64. _.each(files, function (file) {
  65. var oImage = preview.clone().get(0),
  66. modelJSON = prepareData(file, component);
  67. var isImg = ONLYIMAGE.test(file.type);
  68. if (typeof FileReader !== "undefined" && isImg) {
  69. var oReader = new FileReader();
  70. oReader.onload = function (e) {
  71. // e.target.result contains the DataURL which we will use as a source of the image
  72. oImage.src = e.target.result;
  73. oImage.onload = function () { // binding onload event
  74. // we are going to display some custom image information here
  75. modelJSON.image = e.target.result;
  76. modelJSON.width = oImage.naturalWidth;
  77. modelJSON.height = oImage.naturalHeight;
  78. modelJSON.error = false;
  79. var model = new _sc.Definitions.Models.Model(modelJSON);
  80. component.collection.add(model);
  81. cb(modelJSON);
  82. };
  83. };
  84. oReader.readAsDataURL(file);
  85. } else {
  86. modelJSON.image = "/sitecore/shell/client/Speak/Assets/img/Speak/Uploader/upload_file_icon.png";
  87. modelJSON.error = false;
  88. component.collection.add(new _sc.Definitions.Models.Model(modelJSON));
  89. cb(modelJSON);
  90. }
  91. }, this);
  92. },
  93. uploadProgress = function (data, model, cb) { // upload process in progress
  94. var percentage = Math.round(data.loaded * 100 / data.total),
  95. bytesTransfered = bytesToSize(data.total);
  96. model.set("percentage", percentage.toString());
  97. model.set("bytesTransfered", bytesTransfered);
  98. cb(model);
  99. },
  100. removeFilesFromQueue = function (model) {
  101. var index = 0;
  102. _.each(this.datas, function (data) {
  103. data.files = _.reject(data.files, function (file) {
  104. return (file.__id === model.get("id"));
  105. });
  106. if (data.files.length === 0) {
  107. this.datas.splice(index, 1);
  108. }
  109. ++index;
  110. }, this);
  111. this.totalSize = this.totalSize - model.get("size");
  112. this.collection.remove(model);
  113. if (this.uploadFile.context.forms && this.uploadFile.context.forms.length >= 1 && this.uploadFile.context.forms[0].__ids) {
  114. this.uploadFile.context.forms[0].__ids.splice(this.uploadFile.context.forms[0].__ids.indexOf(model.id), 1);
  115. }
  116. this.updateUploadInfo(this.collection.length > 0, false);
  117. this.refreshNumberFiles(false);
  118. this.refreshNumberSize(false);
  119. },
  120. updateFromQueue = function (model) {
  121. var name = model.get("name"),
  122. description = model.get("description"),
  123. id = model.get("id");
  124. _.each(this.datas, function (data) {
  125. data.files = _.reject(data.files, function (file) {
  126. if (file.__id === id) {
  127. file.name = name;
  128. file.description = description;
  129. }
  130. });
  131. }, this);
  132. };
  133. _sc.Factories.createBaseComponent({
  134. name: "Uploader",
  135. base: "ControlBase",
  136. selector: ".sc-uploader",
  137. collection: Files,
  138. listenTo: {
  139. "upload": "upload"
  140. },
  141. attributes: [
  142. { name: "destinationUrl", value: "$el.data:sc-destinationurl" },
  143. { name: "maxRequestLength", value: "$el.data:sc-maxrequestlength" },
  144. { name: "hasFilesToUpload", defaultValue: null },
  145. { name: "executionTimeout", value: "$el.data:sc-executiontimeout" },
  146. { name: "totalFiles", defaultValue: 0 },
  147. { name: "uploadedFiles", defaultValue: 0 },
  148. { name: "globalPercentage", defaultValue: 0 },
  149. { name: "totalSize", defaultValue: "0 bytes" },
  150. { name: "uploadedSize", defaultValue: "0 bytes" },
  151. { name: "queueWasAborted", defaultValue: null },
  152. { name: "database", value: "$el.data:sc-databasename" },
  153. { name: "uploadEnabled", defaultValue: false } //XAContext change
  154. ],
  155. extendModel: {
  156. set: function (key, value, options) {
  157. var _base = _sc.Definitions.Models.ControlModel;
  158. if (!_base) {
  159. _base = Backbone.Model;
  160. }
  161. if (!(options && options.initReadonlyValue) && _.isObject(key)) {
  162. key = _.omit(key, "database");
  163. _base.prototype.set.apply(this, key, value, options);
  164. } else if (!(options && options.initReadonlyValue) && key === "database") {
  165. return;
  166. }
  167. _base.prototype.set.call(this, key, value, options);
  168. }
  169. },
  170. initialize: function() {
  171. this.totalSize = 0;
  172. var databaseUri = new _sc.Definitions.Data.DatabaseUri("core"),
  173. database = new _sc.Definitions.Data.Database(databaseUri);
  174. if (!hasXMLRequestLevel2) {
  175. this.$el.find(".drag").hide();
  176. }
  177. this.databaseName = this.$el.data("sc-databasename") ? this.$el.data("sc-databasename") : "core";
  178. this.model.set("database", this.databaseName, {initReadonlyValue: true});
  179. this.setUploadUrl();
  180. this.model.set("totalFiles", 0);
  181. this.model.set("uploadedFiles", 0);
  182. this.datas = [];
  183. this.app.on("upload-info-deleted", removeFilesFromQueue, this);
  184. this.app.on("upload-info-updated", updateFromQueue, this);
  185. this.$preeview = this.$el.find(".sc-uploader-preview");
  186. this.uploadFile = this.$el.find(".sc-uploader-fileupload");
  187. this.collection.on("add", this.fileAdded, this);
  188. this.collection.on("remove", this.refreshNumberFiles(false), this);
  189. this.refreshNumberFiles(false);
  190. this.getUploadEnabled();//XAContext change
  191. this.domElements = {
  192. infoUploadingDataPanels: this.$el.find(".sc-uploader-general-info-data-uploadingData"),
  193. infoDataPanel: this.$el.find(".sc-uploader-general-info-data"),
  194. infoProgressBar: this.$el.find(".sc-uploader-general-info-progressbar")
  195. },
  196. // Gets translation of messages for error events
  197. database.getItem("{7F5A190F-64A6-495B-B148-80569C03348D}", this.setFileSizeExceededErrorMessage);
  198. database.getItem("{B995246F-A761-451E-9539-AAC4B7761F06}", this.setTimeoutErrorMessage);
  199. this.model.on("change:destinationUrl", this.changeDestinationUrl, this);
  200. },
  201. changeDestinationUrl: function () {
  202. this.setUploadUrl();
  203. this.getUploadEnabled();//XAContext change
  204. },
  205. setUploadUrl: function () {
  206. this.url = "/api/sitecore/Media/Upload?database=" + this.databaseName;
  207. var destination = this.model.get("destinationUrl");
  208. if (destination !== null) {
  209. this.url += "&destinationUrl=" + this.model.get("destinationUrl");
  210. }
  211. this.$el.find(".sc-uploader-fileupload").attr("data-url", this.url);
  212. },
  213. setTimeoutErrorMessage: function (item) {
  214. timeoutErrorMessage = item.Text;
  215. },
  216. setFileSizeExceededErrorMessage: function (item) {
  217. fileSizeExceededErrorMessage = item.Text;
  218. },
  219. getUploadedSize: function () {
  220. return bytesToSize(uploadedSize);
  221. },
  222. //XAContext change
  223. getUploadEnabled : function () {
  224. var that = this,
  225. databaseUri,
  226. escapedPath = null,
  227. first = false,
  228. selectedDestinationUrlParts,
  229. i;
  230. this.model.set("uploadEnabled",false);
  231. databaseUri = new _sc.Definitions.Data.DatabaseUri("master"),
  232. database = new _sc.Definitions.Data.Database(databaseUri);
  233. selectedDestinationUrlParts = this.model.get("destinationUrl").split("/");
  234. for (i = 0; i < selectedDestinationUrlParts.length; i++) {
  235. if (selectedDestinationUrlParts[i].indexOf("-")>0) {
  236. selectedDestinationUrlParts[i] = "#" + selectedDestinationUrlParts[i].trim("#") + "#";
  237. }
  238. }
  239. for (i = 0; i < selectedDestinationUrlParts.length; i++) {
  240. if (!first) {
  241. escapedPath = selectedDestinationUrlParts[i];
  242. }
  243. else {
  244. escapedPath = escapedPath + "/" + selectedDestinationUrlParts[i];
  245. }
  246. first=true;
  247. }
  248. database.query(escapedPath, function(itemsFromQueryArray){
  249. that.model.set("uploadEnabled",(that.model.get("hasFilesToUpload") && (itemsFromQueryArray.length>0 && itemsFromQueryArray[0].$templateId !== "{001AC668-10ED-438D-A1A5-2774CFF7C7D4}")));
  250. });
  251. },
  252. getTotalSize: function () {
  253. var hasFilesToUpload = this.model.get("totalFiles") && this.totalSize < this.model.get("maxRequestLength");
  254. if (this.model.get("hasFilesToUpload") !== hasFilesToUpload && !this.model.get("queueWasAborted")) {
  255. this.model.set("hasFilesToUpload", hasFilesToUpload);
  256. this.setFileSizeExceeded();
  257. }
  258. else if (this.model.get("queueWasAborted")) {
  259. this.model.set("hasFilesToUpload", false);
  260. }
  261. return bytesToSize(this.totalSize);
  262. },
  263. setFileSizeExceeded: function () {
  264. var errorId = "upload-error-fileSizeExceeded";
  265. if (this.totalSize > this.model.get("maxRequestLength")) {
  266. this.app.trigger("sc-error", [{ id: errorId, Message: fileSizeExceededErrorMessage + " " + bytesToSize(this.model.get("maxRequestLength")) }]);
  267. this.app.trigger(errorId, this.totalSize);
  268. } else {
  269. this.app.trigger("sc-uploader-remove", { id: errorId });
  270. }
  271. },
  272. fileAdded: function (model) {
  273. this.updateUploadInfo(true, false);
  274. this.refreshNumberFiles(false);
  275. this.app.trigger("upload-fileAdded", model);
  276. },
  277. refreshNumberSize: function (isUploading) {
  278. if (isUploading) {
  279. this.model.set("uploadedSize", this.model.get("queueWasAborted") ? this.model.get("uploadedSize") : this.getUploadedSize());
  280. return;
  281. }
  282. this.model.set("totalSize", this.getTotalSize());
  283. this.model.set("uploadedSize", 0);
  284. this.getUploadEnabled(); //XAContext change
  285. },
  286. refreshNumberFiles: function (isUploading) {
  287. if (isUploading) {
  288. this.model.set("uploadedFiles", this.model.get("queueWasAborted") ? this.model.get("uploadedFiles") : this.model.get("totalFiles") - this.collection.length);
  289. return;
  290. }
  291. this.model.set("totalFiles", this.model.get("queueWasAborted") ? 0 : this.collection.length);
  292. this.model.set("uploadedFiles", 0);
  293. },
  294. showDataPanel: function (state) {
  295. if (state) {
  296. this.domElements.infoDataPanel.show();
  297. } else {
  298. this.domElements.infoDataPanel.hide();
  299. }
  300. },
  301. showProgressBar: function (state) {
  302. if (state) {
  303. this.domElements.infoProgressBar.show();
  304. } else {
  305. this.domElements.infoProgressBar.hide();
  306. }
  307. },
  308. showUploadingDataPanel: function (state) {
  309. if (state) {
  310. this.domElements.infoUploadingDataPanels.css('display', 'inline-block');
  311. } else {
  312. this.domElements.infoUploadingDataPanels.hide();
  313. }
  314. },
  315. updateUploadInfo: function (hasFilesToUpload, isUploading, hasCompletedUploading) {
  316. this.showDataPanel(hasFilesToUpload || isUploading || hasCompletedUploading);
  317. this.showUploadingDataPanel(isUploading);
  318. this.showProgressBar(isUploading);
  319. },
  320. upload: function () {
  321. var that = this;
  322. this.startUploadTimer(this.datas);
  323. this.updateUploadInfo(true, true);
  324. //for each files - do the upload
  325. _.each(this.datas, function (data) {
  326. data.submit().error(function (jqXHR, textStatus, errorThrown) {
  327. if (jqXHR.status === 401) {
  328. _sc.Helpers.session.unauthorized();
  329. return;
  330. }
  331. // Triggers error on each model that had an abort
  332. if (errorThrown === "abort") {
  333. that.app.trigger("upload-error", { id: data.__id });
  334. } else {
  335. var errors = [{ Message: errorThrown }];
  336. that.app.trigger("sc-error", errors);
  337. that.app.trigger("upload-error", { id: data.__id, errors: errors });
  338. }
  339. });
  340. });
  341. },
  342. // Starts a timer from the setting executionTimeout
  343. startUploadTimer: function (datas) {
  344. var errorId = "uploadErrorTimeout",
  345. executionTimeout = this.model.get("executionTimeout"),
  346. currentSeconds = 0,
  347. that = this;
  348. uploadTimer = window.setInterval(function () {
  349. currentSeconds += 0.1;
  350. if (currentSeconds > executionTimeout) {
  351. // Abort each file upload, and triggers an error event with each file
  352. _.each(datas, function (data) {
  353. data.abort();
  354. });
  355. that.collection.reset();
  356. clearInterval(uploadTimer);
  357. that.app.trigger("sc-error", [{ id: errorId, Message: timeoutErrorMessage }]);
  358. // To resets the indicator width
  359. that.model.set("globalPercentage", 0);
  360. // Resets everything
  361. that.datas = [];
  362. that.totalSize = 0;
  363. uploadedSize = 0;
  364. that.model.set("queueWasAborted", true);
  365. }
  366. }, 100);
  367. },
  368. updateRealImage: function (data, id) {
  369. model = _.find(this.collection.models, function (model) {
  370. return model.get("id") === id;
  371. });
  372. model.set("image", data.uploadedFileItems[0].Icon);
  373. model.set("itemId", data.uploadedFileItems[0].ItemId);
  374. this.app.trigger("upload-fileUploaded", model.toJSON());
  375. },
  376. afterRender: function () {
  377. var that = this;
  378. this.uploadFile.fileupload({
  379. add: function (e, data) {
  380. data.url = that.url;
  381. // Resets the aborted state
  382. if (that.model.get("queueWasAborted")) {
  383. that.app.trigger("sc-uploader-remove", { id: "uploadErrorTimeout" });
  384. that.model.set("queueWasAborted", false);
  385. that.collection.reset();
  386. }
  387. that.model.set("globalPercentage", 0);
  388. var files = data.files,
  389. currentNumber = that.model.get("totalFiles") || 0;
  390. that.model.set("totalFiles", (currentNumber + files.length));
  391. validateFiles(files);
  392. setupDataForFiles(that.$preeview, files, that, function (model) {
  393. /*if (data.form) {
  394. data.form.__id = model.id;
  395. } else {*/
  396. e.target.form.__ids = e.target.form.__ids || [];
  397. e.target.form.__ids.push(model.id);
  398. /*}*/
  399. data.__id = model.id;
  400. that.datas.push(data);
  401. that.refreshNumberSize(false);
  402. });
  403. },
  404. progressall: function (e, data) {
  405. if (!that.model.get("queueWasAborted")) {
  406. var percentage = Math.round(data.loaded * 100 / data.total),
  407. bytesTransfered = bytesToSize(data.total);
  408. that.model.set("globalPercentage", percentage);
  409. }
  410. },
  411. formData: function (form) {
  412. var id = form.context.__ids.shift(),
  413. data = form.serializeArray();
  414. var token = _sc.Helpers.antiForgery.getAntiForgeryToken();
  415. data.push({ name: token.formKey, value: token.value });
  416. return this.getModelData(data, id);
  417. },
  418. getModelData: function (data, id) {
  419. for (var modelIndex in that.collection.models) {
  420. var model = that.collection.models[modelIndex];
  421. if (model.id === id) {
  422. var name = model.get("name");
  423. var description = model.get("description");
  424. var alternate = model.get("alternate");
  425. data.push({ name: "name", value: name });
  426. data.push({ name: "description", value: description });
  427. data.push({ name: "alternate", value: alternate });
  428. return data;
  429. }
  430. }
  431. return data;
  432. },
  433. done: function (e, data) {
  434. //that.datas = [];
  435. that.datas.splice(that.datas.indexOf(data), 1);
  436. if (data.jqXHR) {
  437. data.jqXHR.done(function (res, arg2, arg3) {
  438. var models = [];
  439. if (res.errorItems) {
  440. _.each(res.errorItems, function (error) {
  441. error.id = data.__id;
  442. });
  443. that.app.trigger("sc-error", res.errorItems);
  444. that.app.trigger("upload-error", { id: data.__id, errors: res.errorItems });
  445. return undefined;
  446. }
  447. that.updateRealImage.call(that, res, data.__id);
  448. ids = _.pluck(data.files, "__id");
  449. that.collection.each(function (model) {
  450. if (_.contains(ids, model.get("id"))) {
  451. models.push(model);
  452. }
  453. });
  454. _.each(models, function (model) {
  455. model.set("error", false);
  456. model.set("percentage", 100);
  457. that.collection.remove(model);
  458. }, this);
  459. uploadedSize += data.files[0].size;
  460. that.refreshNumberFiles(true);
  461. that.refreshNumberSize(true);
  462. if (that.collection.length === 0) {
  463. that.updateUploadInfo(false, false, true);
  464. setTimeout(function () {
  465. that.model.trigger("uploadCompleted");
  466. }, 1000);
  467. }
  468. });
  469. }
  470. if (that.datas.length === 0) {
  471. clearInterval(uploadTimer);
  472. }
  473. },
  474. autoUpload: false,
  475. dataType: 'json'
  476. });
  477. this.uploadFile.bind("fileuploadprogress", function (e, data) {
  478. var id = data.files[0].__id;
  479. var update = _.find(that.collection.models, function (img) {
  480. return img.get("id") === id;
  481. }, this);
  482. if (update) {
  483. uploadProgress(data, update, function (model) {
  484. that.trigger("upload-progress", model.toJSON());
  485. });
  486. }
  487. });
  488. }
  489. });
  490. });