@oat-sa/tao-core-ui 3.19.2 → 3.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/datatable.js CHANGED
@@ -228,7 +228,7 @@ define(['jquery', 'lodash', 'i18n', 'core/pluginifier', 'handlebars', 'lib/handl
228
228
  buffer += ">";
229
229
  if (helper = helpers.label) { stack1 = helper.call(depth0, {hash:{},data:data}); }
230
230
  else { helper = (depth0 && depth0.label); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
231
- buffer += escapeExpression(stack1);
231
+ if(stack1 || stack1 === 0) { buffer += stack1; }
232
232
  stack1 = helpers['if'].call(depth0, (depth0 && depth0.alias), {hash:{},inverse:self.noop,fn:self.program(51, program51, data),data:data});
233
233
  if(stack1 || stack1 === 0) { buffer += stack1; }
234
234
  stack1 = helpers['if'].call(depth0, (depth0 && depth0.comment), {hash:{},inverse:self.noop,fn:self.program(53, program53, data),data:data});
@@ -563,9 +563,10 @@ define(['jquery', 'lodash', 'i18n', 'core/pluginifier', 'handlebars', 'lib/handl
563
563
  buffer += ">\n ";
564
564
  stack1 = helpers['if'].call(depth0, (depth2 && depth2.icon), {hash:{},inverse:self.noop,fn:self.programWithDepth(75, program75, data, depth2),data:data});
565
565
  if(stack1 || stack1 === 0) { buffer += stack1; }
566
- buffer += "\n "
567
- + escapeExpression(((stack1 = (depth2 && depth2.label)),typeof stack1 === functionType ? stack1.apply(depth0) : stack1))
568
- + "\n </button>\n ";
566
+ buffer += "\n ";
567
+ stack1 = ((stack1 = (depth2 && depth2.label)),typeof stack1 === functionType ? stack1.apply(depth0) : stack1);
568
+ if(stack1 || stack1 === 0) { buffer += stack1; }
569
+ buffer += "\n </button>\n ";
569
570
  return buffer;
570
571
  }
571
572
 
package/dist/dialog.js CHANGED
@@ -118,8 +118,8 @@ define(['jquery', 'lodash', 'i18n', 'handlebars', 'lib/handlebars/helpers', 'ui/
118
118
  buffer += "\n <span class=\"label\">";
119
119
  if (helper = helpers.label) { stack1 = helper.call(depth0, {hash:{},data:data}); }
120
120
  else { helper = (depth0 && depth0.label); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
121
- buffer += escapeExpression(stack1)
122
- + "</span>\n </button>\n";
121
+ if(stack1 || stack1 === 0) { buffer += stack1; }
122
+ buffer += "</span>\n </button>\n";
123
123
  return buffer;
124
124
  }
125
125
  function program2(depth0,data) {
package/dist/feedback.js CHANGED
@@ -96,6 +96,32 @@ define(['jquery', 'lodash', 'core/format', 'ui/component', 'util/wrapLongWords',
96
96
  //change the display (absolute or in the flow)
97
97
  popup: true
98
98
  };
99
+ var feedbackFactory;
100
+ const RUBY_HTML = /<\s*(?:ruby|rt|rp|rb)\b/i;
101
+ const RUBY_BLOCK = /<ruby\b[^>]*>[\s\S]*?<\/ruby>/gi;
102
+
103
+ /**
104
+ * HTML-encodes a string while preserving ruby annotation blocks.
105
+ *
106
+ * @param {String} str
107
+ * @returns {String}
108
+ */
109
+ function encodeHtmlPreservingRuby(str) {
110
+ var parts = [];
111
+ var rubies = [];
112
+ var lastIndex = 0;
113
+ var match;
114
+ RUBY_BLOCK.lastIndex = 0;
115
+ while ((match = RUBY_BLOCK.exec(str)) !== null) {
116
+ parts.push(str.slice(lastIndex, match.index));
117
+ rubies.push(match[0]);
118
+ lastIndex = match.index + match[0].length;
119
+ }
120
+ parts.push(str.slice(lastIndex));
121
+ return parts.map(function (part, index) {
122
+ return encode.html(part) + (rubies[index] || '');
123
+ }).join('');
124
+ }
99
125
 
100
126
  /**
101
127
  * Creates a feedback object.
@@ -110,7 +136,7 @@ define(['jquery', 'lodash', 'core/format', 'ui/component', 'util/wrapLongWords',
110
136
  * @returns {feedback} the feedback object
111
137
  * @throws {TypeError} without a container
112
138
  */
113
- var feedbackFactory = function feedbackFactory($container, config) {
139
+ feedbackFactory = function ($container, config) {
114
140
  var feedback;
115
141
  const codeEnter = 13;
116
142
  const codeSpace = 32;
@@ -146,14 +172,15 @@ define(['jquery', 'lodash', 'core/format', 'ui/component', 'util/wrapLongWords',
146
172
  }
147
173
  this.config = _.defaults(options || {}, this.config);
148
174
  this.config.level = level;
175
+ const hasRubyHtml = typeof displayedMessage === 'string' && RUBY_HTML.test(displayedMessage);
149
176
 
150
177
  // encode plain text string to html
151
178
  if (this.config.encodeHtml) {
152
- displayedMessage = encode.html(displayedMessage);
179
+ displayedMessage = hasRubyHtml ? encodeHtmlPreservingRuby(displayedMessage) : encode.html(displayedMessage);
153
180
  }
154
181
 
155
182
  // wrap long words
156
- if (this.config.wrapLongWordsAfter) {
183
+ if (this.config.wrapLongWordsAfter && !hasRubyHtml) {
157
184
  displayedMessage = wrapLongWords(displayedMessage, this.config.wrapLongWordsAfter);
158
185
  }
159
186
 
@@ -285,7 +312,8 @@ define(['jquery', 'lodash', 'core/format', 'ui/component', 'util/wrapLongWords',
285
312
  _.pull(currents, this);
286
313
  }).init(config);
287
314
  };
315
+ var feedbackFactory$1 = feedbackFactory;
288
316
 
289
- return feedbackFactory;
317
+ return feedbackFactory$1;
290
318
 
291
319
  });
@@ -86,9 +86,9 @@ define(['jquery', 'lodash', 'i18n', 'ui/component', 'ui/feedback', 'util/url', '
86
86
  buffer += " aria-required=\"true\">\n ";
87
87
  stack1 = helpers['if'].call(depth0, ((stack1 = (depth0 && depth0.fieldMessages)),stack1 == null || stack1 === false ? stack1 : stack1.password), {hash:{},inverse:self.noop,fn:self.program(7, program7, data),data:data});
88
88
  if(stack1 || stack1 === 0) { buffer += stack1; }
89
- buffer += "\n </div>\n <div class=\"form-toolbar\"><input type=\"submit\" id=\"connect\" name=\"connect\" disabled=\"disabled\" class=\"disabled\" value=\""
89
+ buffer += "\n </div>\n <div class=\"form-toolbar\">\n <button type=\"submit\" id=\"connect\" name=\"connect\" disabled=\"disabled\" class=\"disabled\">"
90
90
  + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Log in", options) : helperMissing.call(depth0, "__", "Log in", options)))
91
- + "\"></div>\n </form>\n</div>\n";
91
+ + "</button>\n </div>\n </form>\n</div>\n";
92
92
  return buffer;
93
93
  });
94
94
  function loginTpl(data, options, asString) {
@@ -124,8 +124,8 @@ define(['jquery', 'lodash', 'i18n', 'ui/component', 'ui/hider', 'ui/class/select
124
124
  + " ";
125
125
  if (helper = helpers.type) { stack1 = helper.call(depth0, {hash:{},data:data}); }
126
126
  else { helper = (depth0 && depth0.type); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
127
- buffer += escapeExpression(stack1)
128
- + " : </span><span class=\"selected-num\">0</span>\n </div>\n </footer>\n ";
127
+ if(stack1 || stack1 === 0) { buffer += stack1; }
128
+ buffer += " : </span><span class=\"selected-num\">0</span>\n </div>\n </footer>\n ";
129
129
  return buffer;
130
130
  }
131
131
 
@@ -242,7 +242,7 @@ define(['jquery', 'lodash', 'core/request', 'ui/pagination', 'handlebars', 'lib/
242
242
  $selected.parent('li').addClass('active');
243
243
 
244
244
  //internal event to set the file-selector content
245
- updateSelectedClass(fullPath, subTree.total, $selected.data('children-limit'));
245
+ updateSelectedClass(fullPath, content.total, content.childrenLimit);
246
246
  $container.trigger(`folderselect.${ns}`, [content.label, getPage(content.children), content.path, content]);
247
247
  renderPagination();
248
248
  }
@@ -267,9 +267,11 @@ define(['jquery', 'lodash', 'core/request', 'ui/pagination', 'handlebars', 'lib/
267
267
  // if not all, new file will be loaded with next page
268
268
  subTree.children.push(file);
269
269
  }
270
- subTree.total++;
271
- selectedClass.total++;
272
- $container.trigger(`folderselect.${ns}`, [subTree.label, getPage(subTree.children), path]);
270
+ subTree.total = Number.isFinite(Number(subTree.total)) ? Number(subTree.total) + 1 : 1;
271
+ if (selectedClass.path === path) {
272
+ selectedClass.total = subTree.total;
273
+ }
274
+ $container.trigger(`folderselect.${ns}`, [subTree.label, getPage(subTree.children), path, subTree]);
273
275
  renderPagination();
274
276
  }
275
277
  }
@@ -328,7 +330,9 @@ define(['jquery', 'lodash', 'core/request', 'ui/pagination', 'handlebars', 'lib/
328
330
  return !!item.uri;
329
331
  });
330
332
  setToPath(tree, path, {
331
- children: loadedFiles
333
+ children: loadedFiles,
334
+ total: data.total,
335
+ childrenLimit: data.childrenLimit
332
336
  });
333
337
  content = getByPath(tree, path);
334
338
  cb(content);
@@ -392,7 +396,12 @@ define(['jquery', 'lodash', 'core/request', 'ui/pagination', 'handlebars', 'lib/
392
396
  if (tree) {
393
397
  if (tree.path === path) {
394
398
  tree.children = tree.children ? tree.children.concat(data.children) : data.children;
395
- tree.total = data.total;
399
+ if (Object.prototype.hasOwnProperty.call(data, 'total')) {
400
+ tree.total = data.total;
401
+ }
402
+ if (Object.prototype.hasOwnProperty.call(data, 'childrenLimit')) {
403
+ tree.childrenLimit = data.childrenLimit;
404
+ }
396
405
  } else if (tree.children) {
397
406
  _.forEach(tree.children, function (child) {
398
407
  done = setToPath(child, path, data);
@@ -483,10 +492,12 @@ define(['jquery', 'lodash', 'core/request', 'ui/pagination', 'handlebars', 'lib/
483
492
  * @param {Number} childrenLimit - page size
484
493
  */
485
494
  function updateSelectedClass(path, total, childrenLimit) {
495
+ const normalizedTotal = Number(total);
496
+ const normalizedChildrenLimit = Number(childrenLimit);
486
497
  selectedClass = {
487
498
  path,
488
- total,
489
- childrenLimit,
499
+ total: Number.isFinite(normalizedTotal) && normalizedTotal >= 0 ? normalizedTotal : 0,
500
+ childrenLimit: Number.isFinite(normalizedChildrenLimit) && normalizedChildrenLimit > 0 ? normalizedChildrenLimit : selectedClass.childrenLimit || 10,
490
501
  page: 1
491
502
  };
492
503
  }
@@ -495,9 +506,14 @@ define(['jquery', 'lodash', 'core/request', 'ui/pagination', 'handlebars', 'lib/
495
506
  */
496
507
  function renderPagination() {
497
508
  const $paginationContainer = $$1('.pagination-bottom', $container);
509
+ const total = Number(selectedClass.total);
510
+ const childrenLimit = Number(selectedClass.childrenLimit);
498
511
  $paginationContainer.empty();
499
- const totalPages = Math.ceil(selectedClass.total / selectedClass.childrenLimit);
500
- if (selectedClass.total && totalPages > 1) {
512
+ if (!Number.isFinite(total) || !Number.isFinite(childrenLimit) || childrenLimit <= 0) {
513
+ return;
514
+ }
515
+ const totalPages = Math.ceil(total / childrenLimit);
516
+ if (total > 0 && totalPages > 1) {
501
517
  paginationComponent({
502
518
  mode: 'simple',
503
519
  activePage: selectedClass.page,
@@ -375,19 +375,16 @@ define(['jquery', 'lodash', 'async', 'i18n', 'core/mimetype', 'handlebars', 'lib
375
375
  function setUpUploader(currentPath) {
376
376
  let errors = [];
377
377
  let $switcher = $$1('.upload-switcher a', $fileSelector);
378
+ let isUploadMode = false;
378
379
  $uploader.on('upload.uploader', function (e, file, result) {
379
- let path = $$1(`[data-display="${currentPath}"]`).data('path') || $$1(`[data-display="/${currentPath}"]`).data('path');
380
- if (!path) {
381
- path = currentPath;
382
- }
383
- $container.trigger(`filenew.${ns}`, [result, path]);
380
+ $container.trigger(`filenew.${ns}`, [result, currentPath]);
384
381
  });
385
382
  $uploader.on('fail.uploader', function (e, file, err) {
386
383
  errors.push(__('Unable to upload file %s : %s', file.name, err.message));
387
384
  });
388
385
  $uploader.on('end.uploader', function () {
389
386
  if (errors.length === 0) {
390
- _.delay(switchUpload, 500);
387
+ setUploadMode(false);
391
388
  } else {
392
389
  feedback().error(`<ul><li>${errors.join('</li><li>')}</li></ul>`, {
393
390
  encodeHtml: false
@@ -461,8 +458,9 @@ define(['jquery', 'lodash', 'async', 'i18n', 'core/mimetype', 'handlebars', 'lib
461
458
  uploadUrl: `${options.uploadUrl}?${$$1.param(options.params)}&${options.pathParam}=${currentPath}&relPath=${currentPath}`
462
459
  });
463
460
  });
464
- function switchUpload() {
465
- if ($fileContainer.css('display') === 'none') {
461
+ function setUploadMode(enableUploadMode) {
462
+ if (!enableUploadMode) {
463
+ isUploadMode = false;
466
464
  $uploader.hide();
467
465
  $fileContainer.show();
468
466
  // Note: show() would display as inline, not inline-block!
@@ -472,6 +470,7 @@ define(['jquery', 'lodash', 'async', 'i18n', 'core/mimetype', 'handlebars', 'lib
472
470
  $switcher.filter('.listing').hide();
473
471
  $browserTitle.text(__('Browse folders:'));
474
472
  } else {
473
+ isUploadMode = true;
475
474
  $fileContainer.hide();
476
475
  $placeholder.hide();
477
476
  $uploader.show();
@@ -487,8 +486,13 @@ define(['jquery', 'lodash', 'async', 'i18n', 'core/mimetype', 'handlebars', 'lib
487
486
  //switch to upload mode
488
487
  $switcher.click(function (e) {
489
488
  e.preventDefault();
490
- switchUpload();
489
+ if ($$1(this).hasClass('upload')) {
490
+ setUploadMode(true);
491
+ } else if ($$1(this).hasClass('listing')) {
492
+ setUploadMode(false);
493
+ }
491
494
  });
495
+ setUploadMode(isUploadMode);
492
496
  }
493
497
  function updateFiles(path, files) {
494
498
  $fileContainer.empty();
@@ -32,8 +32,8 @@ define(['jquery', 'lodash', 'core/pluginifier', 'ui/resourcemgr/fileBrowser', 'u
32
32
  buffer += "\">\n\n <h2>";
33
33
  if (helper = helpers.title) { stack1 = helper.call(depth0, {hash:{},data:data}); }
34
34
  else { helper = (depth0 && depth0.title); stack1 = typeof helper === functionType ? helper.call(depth0, {hash:{},data:data}) : helper; }
35
- buffer += escapeExpression(stack1)
36
- + "</h2>\n\n <div class=\"file-wrapper\">\n\n <!-- left section: items selection -->\n <section class=\"file-browser\">\n <h1>"
35
+ if(stack1 || stack1 === 0) { buffer += stack1; }
36
+ buffer += "</h2>\n\n <div class=\"file-wrapper\">\n\n <!-- left section: items selection -->\n <section class=\"file-browser\">\n <h1>"
37
37
  + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Browse resources", options) : helperMissing.call(depth0, "__", "Browse resources", options)))
38
38
  + "</h1>\n <div class=\"file-browser-wrapper\"></div>\n </section>\n\n <!-- test editor -->\n <section class=\"file-selector\">\n\n <h1>\n <div class=\"title lft\"></div>\n <div class=\"upload-switcher rgt\">\n <a href=\"#\" class=\"btn-info small upload hidden\"><span class=\"icon-add\"></span>"
39
39
  + escapeExpression((helper = helpers.__ || (depth0 && depth0.__),options={hash:{},data:data},helper ? helper.call(depth0, "Add file(s)", options) : helperMissing.call(depth0, "__", "Add file(s)", options)))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oat-sa/tao-core-ui",
3
- "version": "3.19.2",
3
+ "version": "3.21.0",
4
4
  "displayName": "TAO Core UI",
5
5
  "description": "UI libraries of TAO",
6
6
  "scripts": {
@@ -52,7 +52,7 @@
52
52
  "@oat-sa/prettier-config": "^0.1.1",
53
53
  "@oat-sa/rollup-plugin-wildcard-external": "^1.0.0",
54
54
  "@oat-sa/tao-calculator": "^0.6.2",
55
- "@oat-sa/tao-core-libs": "^1.0.0",
55
+ "@oat-sa/tao-core-libs": "^1.2.1",
56
56
  "@oat-sa/tao-core-sdk": "^3.0.0",
57
57
  "@oat-sa/tao-core-shared-libs": "^1.6.1",
58
58
  "@oat-sa/tao-qunit-testrunner": "^2.0.0",
@@ -64,7 +64,7 @@
64
64
  data-sort-by="{{#if sortId}}{{sortId}}{{else}}{{id}}{{/if}}"
65
65
  {{#if sorttype}}data-sort-type="{{sorttype}}"{{/if}}
66
66
  tabindex="0"
67
- {{/if}}>{{label}}{{#if alias}} <span class="alias">({{alias}})</span>{{/if}}{{#if comment}} <span class="comment">/ {{comment}}</span>{{/if}}</div>
67
+ {{/if}}>{{{label}}}{{#if alias}} <span class="alias">({{alias}})</span>{{/if}}{{#if comment}} <span class="comment">/ {{comment}}</span>{{/if}}</div>
68
68
  {{#if filterable}}
69
69
  <aside data-column="{{id}}" class="filter column
70
70
  {{#if customFilter}} customInput" >
@@ -132,7 +132,7 @@
132
132
  {{#if ../../title}} title="{{../../../title}}"{{/if}}
133
133
  {{#if ../../disabled}} disabled="disabled"{{/if}}>
134
134
  {{#if ../../icon}}<span class="icon-{{../../../icon}}"></span>{{/if}}
135
- {{../../label}}
135
+ {{{../../label}}}
136
136
  </button>
137
137
  {{/unless}}
138
138
  {{/with}}
@@ -1,6 +1,6 @@
1
1
  {{#each buttons}}
2
2
  <button class="btn-{{type}} small {{id}}" data-control="{{id}}" type="button">
3
3
  {{#if icon}}<span class="icon-{{icon}}"></span> {{/if}}
4
- <span class="label">{{label}}</span>
4
+ <span class="label">{{{label}}}</span>
5
5
  </button>
6
6
  {{/each}}
package/src/feedback.js CHANGED
@@ -70,6 +70,36 @@ var defaultOptions = {
70
70
  popup: true
71
71
  };
72
72
 
73
+ var feedbackFactory;
74
+
75
+ const RUBY_HTML = /<\s*(?:ruby|rt|rp|rb)\b/i;
76
+ const RUBY_BLOCK = /<ruby\b[^>]*>[\s\S]*?<\/ruby>/gi;
77
+
78
+ /**
79
+ * HTML-encodes a string while preserving ruby annotation blocks.
80
+ *
81
+ * @param {String} str
82
+ * @returns {String}
83
+ */
84
+ function encodeHtmlPreservingRuby(str) {
85
+ var parts = [];
86
+ var rubies = [];
87
+ var lastIndex = 0;
88
+ var match;
89
+
90
+ RUBY_BLOCK.lastIndex = 0;
91
+ while ((match = RUBY_BLOCK.exec(str)) !== null) {
92
+ parts.push(str.slice(lastIndex, match.index));
93
+ rubies.push(match[0]);
94
+ lastIndex = match.index + match[0].length;
95
+ }
96
+ parts.push(str.slice(lastIndex));
97
+
98
+ return parts.map(function(part, index) {
99
+ return encode.html(part) + (rubies[index] || '');
100
+ }).join('');
101
+ }
102
+
73
103
  /**
74
104
  * Creates a feedback object.
75
105
  *
@@ -83,7 +113,7 @@ var defaultOptions = {
83
113
  * @returns {feedback} the feedback object
84
114
  * @throws {TypeError} without a container
85
115
  */
86
- var feedbackFactory = function feedbackFactory($container, config) {
116
+ feedbackFactory = function ($container, config) {
87
117
  var feedback;
88
118
  const codeEnter = 13;
89
119
  const codeSpace = 32;
@@ -124,13 +154,18 @@ var feedbackFactory = function feedbackFactory($container, config) {
124
154
  this.config = _.defaults(options || {}, this.config);
125
155
  this.config.level = level;
126
156
 
157
+ const hasRubyHtml =
158
+ typeof displayedMessage === 'string' && RUBY_HTML.test(displayedMessage);
159
+
127
160
  // encode plain text string to html
128
161
  if (this.config.encodeHtml) {
129
- displayedMessage = encode.html(displayedMessage);
162
+ displayedMessage = hasRubyHtml
163
+ ? encodeHtmlPreservingRuby(displayedMessage)
164
+ : encode.html(displayedMessage);
130
165
  }
131
166
 
132
167
  // wrap long words
133
- if (this.config.wrapLongWordsAfter) {
168
+ if (this.config.wrapLongWordsAfter && !hasRubyHtml) {
134
169
  displayedMessage = wrapLongWords(displayedMessage, this.config.wrapLongWordsAfter);
135
170
  }
136
171
 
@@ -24,6 +24,8 @@
24
24
  </div>
25
25
  {{/if}}
26
26
  </div>
27
- <div class="form-toolbar"><input type="submit" id="connect" name="connect" disabled="disabled" class="disabled" value="{{__ "Log in"}}"></div>
27
+ <div class="form-toolbar">
28
+ <button type="submit" id="connect" name="connect" disabled="disabled" class="disabled">{{__ "Log in"}}</button>
29
+ </div>
28
30
  </form>
29
31
  </div>
@@ -39,7 +39,7 @@
39
39
  {{#if multiple}}
40
40
  <footer>
41
41
  <div class="get-selection">
42
- <span>{{__ 'Selected'}} {{type}} : </span><span class="selected-num">0</span>
42
+ <span>{{__ 'Selected'}} {{{ type }}} : </span><span class="selected-num">0</span>
43
43
  </div>
44
44
  </footer>
45
45
  {{/if}}
@@ -107,7 +107,7 @@ export default function (options) {
107
107
  $selected.parent('li').addClass('active');
108
108
 
109
109
  //internal event to set the file-selector content
110
- updateSelectedClass(fullPath, subTree.total, $selected.data('children-limit'));
110
+ updateSelectedClass(fullPath, content.total, content.childrenLimit);
111
111
  $container.trigger(`folderselect.${ns}`, [
112
112
  content.label,
113
113
  getPage(content.children),
@@ -137,9 +137,11 @@ export default function (options) {
137
137
  // if not all, new file will be loaded with next page
138
138
  subTree.children.push(file);
139
139
  }
140
- subTree.total++;
141
- selectedClass.total++;
142
- $container.trigger(`folderselect.${ns}`, [subTree.label, getPage(subTree.children), path]);
140
+ subTree.total = Number.isFinite(Number(subTree.total)) ? Number(subTree.total) + 1 : 1;
141
+ if (selectedClass.path === path) {
142
+ selectedClass.total = subTree.total;
143
+ }
144
+ $container.trigger(`folderselect.${ns}`, [subTree.label, getPage(subTree.children), path, subTree]);
143
145
  renderPagination();
144
146
  }
145
147
  }
@@ -201,7 +203,11 @@ export default function (options) {
201
203
  const loadedFiles = _.filter(data.children, function (item) {
202
204
  return !!item.uri;
203
205
  });
204
- setToPath(tree, path, { children: loadedFiles });
206
+ setToPath(tree, path, {
207
+ children: loadedFiles,
208
+ total: data.total,
209
+ childrenLimit: data.childrenLimit
210
+ });
205
211
  content = getByPath(tree, path);
206
212
  cb(content);
207
213
  });
@@ -263,7 +269,12 @@ export default function (options) {
263
269
  if (tree) {
264
270
  if (tree.path === path) {
265
271
  tree.children = tree.children ? tree.children.concat(data.children) : data.children;
266
- tree.total = data.total;
272
+ if (Object.prototype.hasOwnProperty.call(data, 'total')) {
273
+ tree.total = data.total;
274
+ }
275
+ if (Object.prototype.hasOwnProperty.call(data, 'childrenLimit')) {
276
+ tree.childrenLimit = data.childrenLimit;
277
+ }
267
278
  } else if (tree.children) {
268
279
  _.forEach(tree.children, function (child) {
269
280
  done = setToPath(child, path, data);
@@ -356,10 +367,16 @@ export default function (options) {
356
367
  * @param {Number} childrenLimit - page size
357
368
  */
358
369
  function updateSelectedClass(path, total, childrenLimit) {
370
+ const normalizedTotal = Number(total);
371
+ const normalizedChildrenLimit = Number(childrenLimit);
372
+
359
373
  selectedClass = {
360
374
  path,
361
- total,
362
- childrenLimit,
375
+ total: Number.isFinite(normalizedTotal) && normalizedTotal >= 0 ? normalizedTotal : 0,
376
+ childrenLimit:
377
+ Number.isFinite(normalizedChildrenLimit) && normalizedChildrenLimit > 0
378
+ ? normalizedChildrenLimit
379
+ : selectedClass.childrenLimit || 10,
363
380
  page: 1
364
381
  };
365
382
  }
@@ -368,10 +385,18 @@ export default function (options) {
368
385
  */
369
386
  function renderPagination() {
370
387
  const $paginationContainer = $('.pagination-bottom', $container);
388
+ const total = Number(selectedClass.total);
389
+ const childrenLimit = Number(selectedClass.childrenLimit);
390
+
371
391
  $paginationContainer.empty();
372
- const totalPages = Math.ceil(selectedClass.total / selectedClass.childrenLimit);
373
392
 
374
- if (selectedClass.total && totalPages > 1) {
393
+ if (!Number.isFinite(total) || !Number.isFinite(childrenLimit) || childrenLimit <= 0) {
394
+ return;
395
+ }
396
+
397
+ const totalPages = Math.ceil(total / childrenLimit);
398
+
399
+ if (total > 0 && totalPages > 1) {
375
400
  paginationComponent({
376
401
  mode: 'simple',
377
402
  activePage: selectedClass.page,
@@ -231,14 +231,10 @@ export default function (options) {
231
231
  function setUpUploader(currentPath) {
232
232
  let errors = [];
233
233
  let $switcher = $('.upload-switcher a', $fileSelector);
234
+ let isUploadMode = false;
234
235
 
235
236
  $uploader.on('upload.uploader', function (e, file, result) {
236
- let path =
237
- $(`[data-display="${currentPath}"]`).data('path') || $(`[data-display="/${currentPath}"]`).data('path');
238
- if (!path) {
239
- path = currentPath;
240
- }
241
- $container.trigger(`filenew.${ns}`, [result, path]);
237
+ $container.trigger(`filenew.${ns}`, [result, currentPath]);
242
238
  });
243
239
  $uploader.on('fail.uploader', function (e, file, err) {
244
240
  errors.push(__('Unable to upload file %s : %s', file.name, err.message));
@@ -246,7 +242,7 @@ export default function (options) {
246
242
 
247
243
  $uploader.on('end.uploader', function () {
248
244
  if (errors.length === 0) {
249
- _.delay(switchUpload, 500);
245
+ setUploadMode(false);
250
246
  } else {
251
247
  feedback().error(`<ul><li>${errors.join('</li><li>')}</li></ul>`, { encodeHtml: false });
252
248
  }
@@ -333,8 +329,9 @@ export default function (options) {
333
329
  });
334
330
  });
335
331
 
336
- function switchUpload() {
337
- if ($fileContainer.css('display') === 'none') {
332
+ function setUploadMode(enableUploadMode) {
333
+ if (!enableUploadMode) {
334
+ isUploadMode = false;
338
335
  $uploader.hide();
339
336
  $fileContainer.show();
340
337
  // Note: show() would display as inline, not inline-block!
@@ -342,6 +339,7 @@ export default function (options) {
342
339
  $switcher.filter('.listing').hide();
343
340
  $browserTitle.text(__('Browse folders:'));
344
341
  } else {
342
+ isUploadMode = true;
345
343
  $fileContainer.hide();
346
344
  $placeholder.hide();
347
345
  $uploader.show();
@@ -355,8 +353,14 @@ export default function (options) {
355
353
  //switch to upload mode
356
354
  $switcher.click(function (e) {
357
355
  e.preventDefault();
358
- switchUpload();
356
+ if ($(this).hasClass('upload')) {
357
+ setUploadMode(true);
358
+ } else if ($(this).hasClass('listing')) {
359
+ setUploadMode(false);
360
+ }
359
361
  });
362
+
363
+ setUploadMode(isUploadMode);
360
364
  }
361
365
 
362
366
  function updateFiles(path, files) {
@@ -1,6 +1,6 @@
1
1
  <div class="resourcemgr modal {{#if className}}{{className}}{{/if}}">
2
2
 
3
- <h2>{{title}}</h2>
3
+ <h2>{{{ title }}}</h2>
4
4
 
5
5
  <div class="file-wrapper">
6
6