jsuites 6.2.1 → 6.3.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.
Files changed (2) hide show
  1. package/dist/jsuites.js +322 -24
  2. package/package.json +1 -1
package/dist/jsuites.js CHANGED
@@ -14506,11 +14506,22 @@ function Tabs(el, options) {
14506
14506
  var prev = null;
14507
14507
  var next = null;
14508
14508
  var border = null;
14509
+ var header = null;
14510
+ var controls = null;
14511
+ var add = null;
14512
+
14513
+ // Event handler references for cleanup
14514
+ var headersClickHandler = null;
14515
+ var headersContextMenuHandler = null;
14509
14516
 
14510
14517
  // Helpers
14511
14518
  const setBorder = function(index) {
14512
14519
  if (obj.options.animation) {
14513
14520
  setTimeout(function() {
14521
+ // Guard against destroyed state
14522
+ if (!obj.headers || !obj.headers.children[index]) {
14523
+ return;
14524
+ }
14514
14525
  let rect = obj.headers.children[index].getBoundingClientRect();
14515
14526
 
14516
14527
  if (obj.options.palette === 'modern') {
@@ -14531,6 +14542,10 @@ function Tabs(el, options) {
14531
14542
  }
14532
14543
 
14533
14544
  var updateControls = function(x) {
14545
+ // Guard against destroyed state
14546
+ if (!obj.headers) {
14547
+ return;
14548
+ }
14534
14549
  if (typeof(obj.headers.scrollTo) == 'function') {
14535
14550
  obj.headers.scrollTo({
14536
14551
  left: x,
@@ -14845,7 +14860,7 @@ function Tabs(el, options) {
14845
14860
  }
14846
14861
 
14847
14862
  // Header
14848
- var header = document.createElement('div');
14863
+ header = document.createElement('div');
14849
14864
  header.className = 'jtabs-headers-container';
14850
14865
  header.appendChild(obj.headers);
14851
14866
  if (obj.options.maxWidth) {
@@ -14853,7 +14868,7 @@ function Tabs(el, options) {
14853
14868
  }
14854
14869
 
14855
14870
  // Controls
14856
- var controls = document.createElement('div');
14871
+ controls = document.createElement('div');
14857
14872
  controls.className = 'jtabs-controls';
14858
14873
  controls.setAttribute('draggable', 'false');
14859
14874
  header.appendChild(controls);
@@ -14869,7 +14884,7 @@ function Tabs(el, options) {
14869
14884
 
14870
14885
  // New button
14871
14886
  if (obj.options.allowCreate == true) {
14872
- var add = document.createElement('div');
14887
+ add = document.createElement('div');
14873
14888
  add.className = 'jtabs-add';
14874
14889
  add.onclick = function() {
14875
14890
  obj.create();
@@ -14938,7 +14953,7 @@ function Tabs(el, options) {
14938
14953
  }
14939
14954
 
14940
14955
  // Events
14941
- obj.headers.addEventListener("click", function(e) {
14956
+ headersClickHandler = function(e) {
14942
14957
  if (e.target.parentNode.classList.contains('jtabs-headers')) {
14943
14958
  var target = e.target;
14944
14959
  } else {
@@ -14954,11 +14969,13 @@ function Tabs(el, options) {
14954
14969
  if (typeof(obj.options.onclick) == 'function') {
14955
14970
  obj.options.onclick(el, obj, index, obj.headers.children[index], obj.content.children[index]);
14956
14971
  }
14957
- });
14972
+ };
14973
+ obj.headers.addEventListener("click", headersClickHandler);
14958
14974
 
14959
- obj.headers.addEventListener("contextmenu", function(e) {
14975
+ headersContextMenuHandler = function(e) {
14960
14976
  obj.selectIndex(e.target);
14961
- });
14977
+ };
14978
+ obj.headers.addEventListener("contextmenu", headersContextMenuHandler);
14962
14979
 
14963
14980
  if (obj.headers.children.length) {
14964
14981
  // Open first tab
@@ -15032,6 +15049,71 @@ function Tabs(el, options) {
15032
15049
  obj.init();
15033
15050
  }
15034
15051
 
15052
+ /**
15053
+ * Destroy the tabs instance and release all resources
15054
+ */
15055
+ obj.destroy = function() {
15056
+ // Remove event listeners from headers
15057
+ if (obj.headers) {
15058
+ if (headersClickHandler) {
15059
+ obj.headers.removeEventListener('click', headersClickHandler);
15060
+ }
15061
+ if (headersContextMenuHandler) {
15062
+ obj.headers.removeEventListener('contextmenu', headersContextMenuHandler);
15063
+ }
15064
+ }
15065
+
15066
+ // Clear onclick handlers
15067
+ if (prev) {
15068
+ prev.onclick = null;
15069
+ }
15070
+ if (next) {
15071
+ next.onclick = null;
15072
+ }
15073
+ if (add) {
15074
+ add.onclick = null;
15075
+ }
15076
+
15077
+ // Remove DOM elements
15078
+ if (header && header.parentNode) {
15079
+ header.parentNode.removeChild(header);
15080
+ }
15081
+ if (obj.content && obj.content.parentNode) {
15082
+ obj.content.parentNode.removeChild(obj.content);
15083
+ }
15084
+
15085
+ // Remove class from element
15086
+ el.classList.remove('jtabs');
15087
+ el.classList.remove('jtabs-animation');
15088
+ el.classList.remove('jtabs-modern');
15089
+
15090
+ // Remove instance reference
15091
+ delete el.tabs;
15092
+
15093
+ // Clear options callbacks to release closures
15094
+ if (obj.options) {
15095
+ obj.options.onclick = null;
15096
+ obj.options.onload = null;
15097
+ obj.options.onchange = null;
15098
+ obj.options.oncreate = null;
15099
+ obj.options.ondelete = null;
15100
+ obj.options.onbeforecreate = null;
15101
+ obj.options.onchangeposition = null;
15102
+ }
15103
+
15104
+ // Clear references
15105
+ obj.headers = null;
15106
+ obj.content = null;
15107
+ header = null;
15108
+ controls = null;
15109
+ prev = null;
15110
+ next = null;
15111
+ border = null;
15112
+ add = null;
15113
+ headersClickHandler = null;
15114
+ headersContextMenuHandler = null;
15115
+ }
15116
+
15035
15117
  el.tabs = obj;
15036
15118
 
15037
15119
  return obj;
@@ -15231,11 +15313,13 @@ function Color(el, options) {
15231
15313
  * Close color pallete
15232
15314
  */
15233
15315
  obj.close = function(ignoreEvents) {
15234
- if (container.classList.contains('jcolor-focus')) {
15316
+ if (container && container.classList.contains('jcolor-focus')) {
15235
15317
  // Remove focus
15236
15318
  container.classList.remove('jcolor-focus');
15237
15319
  // Make sure backdrop is hidden
15238
- backdrop.style.display = '';
15320
+ if (backdrop) {
15321
+ backdrop.style.display = '';
15322
+ }
15239
15323
  // Call related events
15240
15324
  if (! ignoreEvents && typeof(obj.options.onclose) == 'function') {
15241
15325
  obj.options.onclose(el, obj);
@@ -15244,7 +15328,7 @@ function Color(el, options) {
15244
15328
  tracking(obj, false);
15245
15329
  }
15246
15330
 
15247
- return obj.options.value;
15331
+ return obj.options.value ? obj.options.value : null;
15248
15332
  }
15249
15333
 
15250
15334
  /**
@@ -15655,7 +15739,7 @@ function Color(el, options) {
15655
15739
  el.appendChild(container);
15656
15740
  }
15657
15741
 
15658
- container.addEventListener("click", function(e) {
15742
+ containerClickHandler = function(e) {
15659
15743
  if (e.target.tagName == 'TD') {
15660
15744
  var value = e.target.getAttribute('data-value');
15661
15745
  if (value) {
@@ -15674,21 +15758,24 @@ function Color(el, options) {
15674
15758
  } else {
15675
15759
  obj.open();
15676
15760
  }
15677
- });
15761
+ };
15762
+ container.addEventListener("click", containerClickHandler);
15678
15763
 
15679
15764
  /**
15680
15765
  * If element is focus open the picker
15681
15766
  */
15682
- el.addEventListener("mouseup", function(e) {
15767
+ elMouseupHandler = function(e) {
15683
15768
  obj.open();
15684
- });
15769
+ };
15770
+ el.addEventListener("mouseup", elMouseupHandler);
15685
15771
 
15686
15772
  // If the picker is open on the spectrum tab, it changes the canvas size when the window size is changed
15687
- window.addEventListener('resize', function() {
15773
+ windowResizeHandler = function() {
15688
15774
  if (container.classList.contains('jcolor-focus') && jsuitesTabs.getActive() == 1) {
15689
15775
  resizeCanvas();
15690
15776
  }
15691
- });
15777
+ };
15778
+ window.addEventListener('resize', windowResizeHandler);
15692
15779
 
15693
15780
  // Default opened
15694
15781
  if (obj.options.opened == true) {
@@ -15732,6 +15819,73 @@ function Color(el, options) {
15732
15819
  }
15733
15820
  }
15734
15821
 
15822
+ // Store event handler references for cleanup
15823
+ var containerClickHandler = null;
15824
+ var elMouseupHandler = null;
15825
+ var windowResizeHandler = null;
15826
+
15827
+ /**
15828
+ * Destroy the color picker instance and release all resources
15829
+ */
15830
+ obj.destroy = function() {
15831
+ // Close if open (removes from tracking)
15832
+ obj.close(true);
15833
+
15834
+ // Remove event listeners
15835
+ if (container && containerClickHandler) {
15836
+ container.removeEventListener('click', containerClickHandler);
15837
+ }
15838
+ if (el && elMouseupHandler) {
15839
+ el.removeEventListener('mouseup', elMouseupHandler);
15840
+ }
15841
+ if (windowResizeHandler) {
15842
+ window.removeEventListener('resize', windowResizeHandler);
15843
+ }
15844
+
15845
+ // Destroy the tabs component if it has destroy method
15846
+ if (jsuitesTabs && typeof jsuitesTabs.destroy === 'function') {
15847
+ jsuitesTabs.destroy();
15848
+ }
15849
+
15850
+ // Clear rgbInputs references
15851
+ rgbInputs = [];
15852
+
15853
+ // Remove container from DOM
15854
+ if (container && container.parentNode) {
15855
+ container.parentNode.removeChild(container);
15856
+ }
15857
+
15858
+ // Clean up element
15859
+ if (el.tagName === 'INPUT') {
15860
+ el.classList.remove('jcolor-input');
15861
+ el.readOnly = false;
15862
+ el.style.color = '';
15863
+ el.style.backgroundColor = '';
15864
+ }
15865
+
15866
+ // Remove instance properties from el
15867
+ delete el.color;
15868
+ delete el.change;
15869
+ delete el.val;
15870
+
15871
+ // Clear options callbacks to release closures
15872
+ if (obj.options) {
15873
+ obj.options.onchange = null;
15874
+ obj.options.onclose = null;
15875
+ obj.options.onopen = null;
15876
+ obj.options.onload = null;
15877
+ }
15878
+
15879
+ // Clear references
15880
+ container = null;
15881
+ backdrop = null;
15882
+ content = null;
15883
+ resetButton = null;
15884
+ closeButton = null;
15885
+ tabs = null;
15886
+ jsuitesTabs = null;
15887
+ }
15888
+
15735
15889
  init();
15736
15890
 
15737
15891
  return obj;
@@ -18108,6 +18262,58 @@ function Picker(el, options) {
18108
18262
  }
18109
18263
  }
18110
18264
 
18265
+ /**
18266
+ * Destroy the picker instance and release all resources
18267
+ */
18268
+ obj.destroy = function() {
18269
+ // Close if open (removes from tracking)
18270
+ obj.close();
18271
+
18272
+ // Remove event listeners
18273
+ el.onmousedown = null;
18274
+ if (dropdownContent) {
18275
+ dropdownContent.onclick = null;
18276
+ }
18277
+
18278
+ // Remove created DOM elements
18279
+ if (dropdownHeader && dropdownHeader.parentNode) {
18280
+ dropdownHeader.parentNode.removeChild(dropdownHeader);
18281
+ }
18282
+ if (dropdownContent && dropdownContent.parentNode) {
18283
+ dropdownContent.parentNode.removeChild(dropdownContent);
18284
+ }
18285
+
18286
+ // Remove classes and attributes from el
18287
+ el.classList.remove('jpicker');
18288
+ el.classList.remove('jpicker-focus');
18289
+ el.removeAttribute('role');
18290
+ el.removeAttribute('aria-haspopup');
18291
+ el.removeAttribute('aria-expanded');
18292
+ el.removeAttribute('aria-controls');
18293
+ el.removeAttribute('tabindex');
18294
+
18295
+ // Remove instance properties from el
18296
+ delete el.picker;
18297
+ delete el.value;
18298
+ delete el.change;
18299
+ delete el.val;
18300
+
18301
+ // Clear options callbacks to release closures
18302
+ if (obj.options) {
18303
+ obj.options.onchange = null;
18304
+ obj.options.onclose = null;
18305
+ obj.options.onopen = null;
18306
+ obj.options.onload = null;
18307
+ obj.options.onselect = null;
18308
+ obj.options.onmouseover = null;
18309
+ obj.options.render = null;
18310
+ }
18311
+
18312
+ // Clear references
18313
+ dropdownHeader = null;
18314
+ dropdownContent = null;
18315
+ }
18316
+
18111
18317
  /**
18112
18318
  * Create floating picker
18113
18319
  */
@@ -18190,6 +18396,13 @@ function Toolbar(el, options) {
18190
18396
  var obj = { type:'toolbar' };
18191
18397
  obj.options = {};
18192
18398
 
18399
+ // Track internal components for cleanup
18400
+ var internalComponents = [];
18401
+
18402
+ // Event handler references for cleanup
18403
+ var elClickHandler = null;
18404
+ var windowResizeHandler = null;
18405
+
18193
18406
  // Default configuration
18194
18407
  var defaults = {
18195
18408
  app: null,
@@ -18260,8 +18473,88 @@ function Toolbar(el, options) {
18260
18473
  }
18261
18474
 
18262
18475
  obj.destroy = function() {
18263
- toolbar.remove();
18476
+ // Close if open (removes from tracking)
18477
+ obj.close();
18478
+
18479
+ // Destroy all internal components (pickers, etc.)
18480
+ for (var i = 0; i < internalComponents.length; i++) {
18481
+ var comp = internalComponents[i];
18482
+ if (comp) {
18483
+ // First destroy any nested components created in onload (stored on the picker instance)
18484
+ if (comp.components && comp.components.length) {
18485
+ for (var j = 0; j < comp.components.length; j++) {
18486
+ if (comp.components[j] && typeof comp.components[j].destroy === 'function') {
18487
+ comp.components[j].destroy();
18488
+ }
18489
+ }
18490
+ comp.components = null;
18491
+ }
18492
+ // Then destroy the picker/component itself
18493
+ if (typeof comp.destroy === 'function') {
18494
+ comp.destroy();
18495
+ }
18496
+ }
18497
+ }
18498
+ internalComponents = [];
18499
+
18500
+ // Clear onclick handlers from DOM elements (releases bound function references)
18501
+ if (toolbarContent) {
18502
+ var items = toolbarContent.querySelectorAll('.jtoolbar-item');
18503
+ for (var i = 0; i < items.length; i++) {
18504
+ items[i].onclick = null;
18505
+ items[i].updateState = null;
18506
+ }
18507
+ }
18508
+ if (toolbarFloating) {
18509
+ var items = toolbarFloating.querySelectorAll('.jtoolbar-item');
18510
+ for (var i = 0; i < items.length; i++) {
18511
+ items[i].onclick = null;
18512
+ items[i].updateState = null;
18513
+ }
18514
+ }
18515
+
18516
+ // Clear options items callbacks to release closures
18517
+ if (obj.options && obj.options.items) {
18518
+ for (var i = 0; i < obj.options.items.length; i++) {
18519
+ var item = obj.options.items[i];
18520
+ // Clear all callback references
18521
+ item.onclick = null;
18522
+ item.onchange = null;
18523
+ item.onload = null;
18524
+ item.render = null;
18525
+ item.updateState = null;
18526
+ item.onopen = null;
18527
+ item.onclose = null;
18528
+ }
18529
+ obj.options.items = null;
18530
+ }
18531
+
18532
+ // Remove event listeners
18533
+ if (elClickHandler) {
18534
+ el.removeEventListener('click', elClickHandler);
18535
+ elClickHandler = null;
18536
+ }
18537
+ if (windowResizeHandler) {
18538
+ window.removeEventListener('resize', windowResizeHandler);
18539
+ windowResizeHandler = null;
18540
+ }
18541
+
18542
+ // Clear DOM
18264
18543
  el.innerHTML = '';
18544
+
18545
+ // Clear references
18546
+ toolbarContent = null;
18547
+ toolbarFloating = null;
18548
+ toolbarArrow = null;
18549
+
18550
+ // Remove classes
18551
+ el.classList.remove('jtoolbar');
18552
+ el.classList.remove('jtoolbar-container');
18553
+ el.classList.remove('jtoolbar-mobile');
18554
+ el.classList.remove('jtoolbar-disabled');
18555
+
18556
+ // Remove instance reference
18557
+ delete el.toolbar;
18265
18558
  }
18266
18559
 
18267
18560
  obj.update = function(a, b) {
@@ -18323,7 +18616,8 @@ function Toolbar(el, options) {
18323
18616
  }
18324
18617
 
18325
18618
  if (items[i].type == 'select' || items[i].type == 'dropdown') {
18326
- Picker(toolbarItem, items[i]);
18619
+ var picker = Picker(toolbarItem, items[i]);
18620
+ internalComponents.push(picker);
18327
18621
  } else if (items[i].type == 'divisor') {
18328
18622
  toolbarItem.classList.add('jtoolbar-divisor');
18329
18623
  } else if (items[i].type == 'label') {
@@ -18417,7 +18711,9 @@ function Toolbar(el, options) {
18417
18711
  }
18418
18712
 
18419
18713
  obj.close = function() {
18420
- toolbarArrow.classList.remove('jtoolbar-arrow-selected')
18714
+ if (toolbarArrow) {
18715
+ toolbarArrow.classList.remove('jtoolbar-arrow-selected')
18716
+ }
18421
18717
  // End tracking
18422
18718
  tracking(obj, false);
18423
18719
  }
@@ -18460,7 +18756,7 @@ function Toolbar(el, options) {
18460
18756
  el.classList[state]('jtoolbar-disabled');
18461
18757
  }
18462
18758
 
18463
- el.onclick = function(e) {
18759
+ elClickHandler = function(e) {
18464
18760
  var element = helpers.findElement(e.target, 'jtoolbar-item');
18465
18761
  if (element) {
18466
18762
  obj.selectItem(element);
@@ -18469,11 +18765,13 @@ function Toolbar(el, options) {
18469
18765
  if (e.target.classList.contains('jtoolbar-arrow') || e.target.parentNode.classList.contains('jtoolbar-arrow')) {
18470
18766
  obj.open();
18471
18767
  }
18472
- }
18768
+ };
18769
+ el.addEventListener('click', elClickHandler);
18473
18770
 
18474
- window.addEventListener('resize', function() {
18771
+ windowResizeHandler = function() {
18475
18772
  obj.refresh();
18476
- });
18773
+ };
18774
+ window.addEventListener('resize', windowResizeHandler);
18477
18775
 
18478
18776
  // Toolbar
18479
18777
  el.classList.add('jtoolbar');
@@ -23149,7 +23447,7 @@ var jSuites = {
23149
23447
  ...dictionary,
23150
23448
  ...helpers,
23151
23449
  /** Current version */
23152
- version: '6.2.1',
23450
+ version: '6.3.0',
23153
23451
  /** Bind new extensions to Jsuites */
23154
23452
  setExtensions: function(o) {
23155
23453
  if (typeof(o) == 'object') {
package/package.json CHANGED
@@ -26,7 +26,7 @@
26
26
  },
27
27
  "main": "dist/jsuites.js",
28
28
  "types": "dist/jsuites.d.ts",
29
- "version": "6.2.1",
29
+ "version": "6.3.0",
30
30
  "bugs": "https://github.com/jsuites/jsuites/issues",
31
31
  "homepage": "https://github.com/jsuites/jsuites",
32
32
  "docs": "https://jsuites.net",