1 | ;
|
2 | var __extends = (this && this.__extends) || (function () {
|
3 | var extendStatics = function (d, b) {
|
4 | extendStatics = Object.setPrototypeOf ||
|
5 | ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
6 | function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
|
7 | return extendStatics(d, b);
|
8 | }
|
9 | return function (d, b) {
|
10 | extendStatics(d, b);
|
11 | function __() { this.constructor = d; }
|
12 | d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
13 | };
|
14 | })();
|
15 | Object.defineProperty(exports, "__esModule", { value: true });
|
16 | /*-----------------------------------------------------------------------------
|
17 | | Copyright (c) 2014-2017, PhosphorJS Contributors
|
18 | |
|
19 | | Distributed under the terms of the BSD 3-Clause License.
|
20 | |
|
21 | | The full license is in the file LICENSE, distributed with this software.
|
22 | |----------------------------------------------------------------------------*/
|
23 | var algorithm_1 = require("@phosphor/algorithm");
|
24 | var domutils_1 = require("@phosphor/domutils");
|
25 | var dragdrop_1 = require("@phosphor/dragdrop");
|
26 | var messaging_1 = require("@phosphor/messaging");
|
27 | var signaling_1 = require("@phosphor/signaling");
|
28 | var virtualdom_1 = require("@phosphor/virtualdom");
|
29 | var title_1 = require("./title");
|
30 | var widget_1 = require("./widget");
|
31 | /**
|
32 | * A widget which displays titles as a single row or column of tabs.
|
33 | *
|
34 | * #### Notes
|
35 | * If CSS transforms are used to rotate nodes for vertically oriented
|
36 | * text, then tab dragging will not work correctly. The `tabsMovable`
|
37 | * property should be set to `false` when rotating nodes from CSS.
|
38 | */
|
39 | var TabBar = /** @class */ (function (_super) {
|
40 | __extends(TabBar, _super);
|
41 | /**
|
42 | * Construct a new tab bar.
|
43 | *
|
44 | * @param options - The options for initializing the tab bar.
|
45 | */
|
46 | function TabBar(options) {
|
47 | if (options === void 0) { options = {}; }
|
48 | var _this = _super.call(this, { node: Private.createNode() }) || this;
|
49 | _this._currentIndex = -1;
|
50 | _this._titles = [];
|
51 | _this._previousTitle = null;
|
52 | _this._dragData = null;
|
53 | _this._tabMoved = new signaling_1.Signal(_this);
|
54 | _this._currentChanged = new signaling_1.Signal(_this);
|
55 | _this._tabCloseRequested = new signaling_1.Signal(_this);
|
56 | _this._tabDetachRequested = new signaling_1.Signal(_this);
|
57 | _this._tabActivateRequested = new signaling_1.Signal(_this);
|
58 | _this.addClass('p-TabBar');
|
59 | _this.setFlag(widget_1.Widget.Flag.DisallowLayout);
|
60 | _this.tabsMovable = options.tabsMovable || false;
|
61 | _this.allowDeselect = options.allowDeselect || false;
|
62 | _this.insertBehavior = options.insertBehavior || 'select-tab-if-needed';
|
63 | _this.removeBehavior = options.removeBehavior || 'select-tab-after';
|
64 | _this.renderer = options.renderer || TabBar.defaultRenderer;
|
65 | _this._orientation = options.orientation || 'horizontal';
|
66 | _this.dataset['orientation'] = _this._orientation;
|
67 | return _this;
|
68 | }
|
69 | /**
|
70 | * Dispose of the resources held by the widget.
|
71 | */
|
72 | TabBar.prototype.dispose = function () {
|
73 | this._releaseMouse();
|
74 | this._titles.length = 0;
|
75 | this._previousTitle = null;
|
76 | _super.prototype.dispose.call(this);
|
77 | };
|
78 | Object.defineProperty(TabBar.prototype, "currentChanged", {
|
79 | /**
|
80 | * A signal emitted when the current tab is changed.
|
81 | *
|
82 | * #### Notes
|
83 | * This signal is emitted when the currently selected tab is changed
|
84 | * either through user or programmatic interaction.
|
85 | *
|
86 | * Notably, this signal is not emitted when the index of the current
|
87 | * tab changes due to tabs being inserted, removed, or moved. It is
|
88 | * only emitted when the actual current tab node is changed.
|
89 | */
|
90 | get: function () {
|
91 | return this._currentChanged;
|
92 | },
|
93 | enumerable: true,
|
94 | configurable: true
|
95 | });
|
96 | Object.defineProperty(TabBar.prototype, "tabMoved", {
|
97 | /**
|
98 | * A signal emitted when a tab is moved by the user.
|
99 | *
|
100 | * #### Notes
|
101 | * This signal is emitted when a tab is moved by user interaction.
|
102 | *
|
103 | * This signal is not emitted when a tab is moved programmatically.
|
104 | */
|
105 | get: function () {
|
106 | return this._tabMoved;
|
107 | },
|
108 | enumerable: true,
|
109 | configurable: true
|
110 | });
|
111 | Object.defineProperty(TabBar.prototype, "tabActivateRequested", {
|
112 | /**
|
113 | * A signal emitted when a tab is clicked by the user.
|
114 | *
|
115 | * #### Notes
|
116 | * If the clicked tab is not the current tab, the clicked tab will be
|
117 | * made current and the `currentChanged` signal will be emitted first.
|
118 | *
|
119 | * This signal is emitted even if the clicked tab is the current tab.
|
120 | */
|
121 | get: function () {
|
122 | return this._tabActivateRequested;
|
123 | },
|
124 | enumerable: true,
|
125 | configurable: true
|
126 | });
|
127 | Object.defineProperty(TabBar.prototype, "tabCloseRequested", {
|
128 | /**
|
129 | * A signal emitted when a tab close icon is clicked.
|
130 | *
|
131 | * #### Notes
|
132 | * This signal is not emitted unless the tab title is `closable`.
|
133 | */
|
134 | get: function () {
|
135 | return this._tabCloseRequested;
|
136 | },
|
137 | enumerable: true,
|
138 | configurable: true
|
139 | });
|
140 | Object.defineProperty(TabBar.prototype, "tabDetachRequested", {
|
141 | /**
|
142 | * A signal emitted when a tab is dragged beyond the detach threshold.
|
143 | *
|
144 | * #### Notes
|
145 | * This signal is emitted when the user drags a tab with the mouse,
|
146 | * and mouse is dragged beyond the detach threshold.
|
147 | *
|
148 | * The consumer of the signal should call `releaseMouse` and remove
|
149 | * the tab in order to complete the detach.
|
150 | *
|
151 | * This signal is only emitted once per drag cycle.
|
152 | */
|
153 | get: function () {
|
154 | return this._tabDetachRequested;
|
155 | },
|
156 | enumerable: true,
|
157 | configurable: true
|
158 | });
|
159 | Object.defineProperty(TabBar.prototype, "currentTitle", {
|
160 | /**
|
161 | * Get the currently selected title.
|
162 | *
|
163 | * #### Notes
|
164 | * This will be `null` if no tab is selected.
|
165 | */
|
166 | get: function () {
|
167 | return this._titles[this._currentIndex] || null;
|
168 | },
|
169 | /**
|
170 | * Set the currently selected title.
|
171 | *
|
172 | * #### Notes
|
173 | * If the title does not exist, the title will be set to `null`.
|
174 | */
|
175 | set: function (value) {
|
176 | this.currentIndex = value ? this._titles.indexOf(value) : -1;
|
177 | },
|
178 | enumerable: true,
|
179 | configurable: true
|
180 | });
|
181 | Object.defineProperty(TabBar.prototype, "currentIndex", {
|
182 | /**
|
183 | * Get the index of the currently selected tab.
|
184 | *
|
185 | * #### Notes
|
186 | * This will be `-1` if no tab is selected.
|
187 | */
|
188 | get: function () {
|
189 | return this._currentIndex;
|
190 | },
|
191 | /**
|
192 | * Set the index of the currently selected tab.
|
193 | *
|
194 | * #### Notes
|
195 | * If the value is out of range, the index will be set to `-1`.
|
196 | */
|
197 | set: function (value) {
|
198 | // Adjust for an out of range index.
|
199 | if (value < 0 || value >= this._titles.length) {
|
200 | value = -1;
|
201 | }
|
202 | // Bail early if the index will not change.
|
203 | if (this._currentIndex === value) {
|
204 | return;
|
205 | }
|
206 | // Look up the previous index and title.
|
207 | var pi = this._currentIndex;
|
208 | var pt = this._titles[pi] || null;
|
209 | // Look up the current index and title.
|
210 | var ci = value;
|
211 | var ct = this._titles[ci] || null;
|
212 | // Update the current index and previous title.
|
213 | this._currentIndex = ci;
|
214 | this._previousTitle = pt;
|
215 | // Schedule an update of the tabs.
|
216 | this.update();
|
217 | // Emit the current changed signal.
|
218 | this._currentChanged.emit({
|
219 | previousIndex: pi, previousTitle: pt,
|
220 | currentIndex: ci, currentTitle: ct
|
221 | });
|
222 | },
|
223 | enumerable: true,
|
224 | configurable: true
|
225 | });
|
226 | Object.defineProperty(TabBar.prototype, "orientation", {
|
227 | /**
|
228 | * Get the orientation of the tab bar.
|
229 | *
|
230 | * #### Notes
|
231 | * This controls whether the tabs are arranged in a row or column.
|
232 | */
|
233 | get: function () {
|
234 | return this._orientation;
|
235 | },
|
236 | /**
|
237 | * Set the orientation of the tab bar.
|
238 | *
|
239 | * #### Notes
|
240 | * This controls whether the tabs are arranged in a row or column.
|
241 | */
|
242 | set: function (value) {
|
243 | // Do nothing if the orientation does not change.
|
244 | if (this._orientation === value) {
|
245 | return;
|
246 | }
|
247 | // Release the mouse before making any changes.
|
248 | this._releaseMouse();
|
249 | // Toggle the orientation values.
|
250 | this._orientation = value;
|
251 | this.dataset['orientation'] = value;
|
252 | },
|
253 | enumerable: true,
|
254 | configurable: true
|
255 | });
|
256 | Object.defineProperty(TabBar.prototype, "titles", {
|
257 | /**
|
258 | * A read-only array of the titles in the tab bar.
|
259 | */
|
260 | get: function () {
|
261 | return this._titles;
|
262 | },
|
263 | enumerable: true,
|
264 | configurable: true
|
265 | });
|
266 | Object.defineProperty(TabBar.prototype, "contentNode", {
|
267 | /**
|
268 | * The tab bar content node.
|
269 | *
|
270 | * #### Notes
|
271 | * This is the node which holds the tab nodes.
|
272 | *
|
273 | * Modifying this node directly can lead to undefined behavior.
|
274 | */
|
275 | get: function () {
|
276 | return this.node.getElementsByClassName('p-TabBar-content')[0];
|
277 | },
|
278 | enumerable: true,
|
279 | configurable: true
|
280 | });
|
281 | /**
|
282 | * Add a tab to the end of the tab bar.
|
283 | *
|
284 | * @param value - The title which holds the data for the tab,
|
285 | * or an options object to convert to a title.
|
286 | *
|
287 | * @returns The title object added to the tab bar.
|
288 | *
|
289 | * #### Notes
|
290 | * If the title is already added to the tab bar, it will be moved.
|
291 | */
|
292 | TabBar.prototype.addTab = function (value) {
|
293 | return this.insertTab(this._titles.length, value);
|
294 | };
|
295 | /**
|
296 | * Insert a tab into the tab bar at the specified index.
|
297 | *
|
298 | * @param index - The index at which to insert the tab.
|
299 | *
|
300 | * @param value - The title which holds the data for the tab,
|
301 | * or an options object to convert to a title.
|
302 | *
|
303 | * @returns The title object added to the tab bar.
|
304 | *
|
305 | * #### Notes
|
306 | * The index will be clamped to the bounds of the tabs.
|
307 | *
|
308 | * If the title is already added to the tab bar, it will be moved.
|
309 | */
|
310 | TabBar.prototype.insertTab = function (index, value) {
|
311 | // Release the mouse before making any changes.
|
312 | this._releaseMouse();
|
313 | // Coerce the value to a title.
|
314 | var title = Private.asTitle(value);
|
315 | // Look up the index of the title.
|
316 | var i = this._titles.indexOf(title);
|
317 | // Clamp the insert index to the array bounds.
|
318 | var j = Math.max(0, Math.min(index, this._titles.length));
|
319 | // If the title is not in the array, insert it.
|
320 | if (i === -1) {
|
321 | // Insert the title into the array.
|
322 | algorithm_1.ArrayExt.insert(this._titles, j, title);
|
323 | // Connect to the title changed signal.
|
324 | title.changed.connect(this._onTitleChanged, this);
|
325 | // Schedule an update of the tabs.
|
326 | this.update();
|
327 | // Adjust the current index for the insert.
|
328 | this._adjustCurrentForInsert(j, title);
|
329 | // Return the title added to the tab bar.
|
330 | return title;
|
331 | }
|
332 | // Otherwise, the title exists in the array and should be moved.
|
333 | // Adjust the index if the location is at the end of the array.
|
334 | if (j === this._titles.length) {
|
335 | j--;
|
336 | }
|
337 | // Bail if there is no effective move.
|
338 | if (i === j) {
|
339 | return title;
|
340 | }
|
341 | // Move the title to the new location.
|
342 | algorithm_1.ArrayExt.move(this._titles, i, j);
|
343 | // Schedule an update of the tabs.
|
344 | this.update();
|
345 | // Adjust the current index for the move.
|
346 | this._adjustCurrentForMove(i, j);
|
347 | // Return the title added to the tab bar.
|
348 | return title;
|
349 | };
|
350 | /**
|
351 | * Remove a tab from the tab bar.
|
352 | *
|
353 | * @param title - The title for the tab to remove.
|
354 | *
|
355 | * #### Notes
|
356 | * This is a no-op if the title is not in the tab bar.
|
357 | */
|
358 | TabBar.prototype.removeTab = function (title) {
|
359 | this.removeTabAt(this._titles.indexOf(title));
|
360 | };
|
361 | /**
|
362 | * Remove the tab at a given index from the tab bar.
|
363 | *
|
364 | * @param index - The index of the tab to remove.
|
365 | *
|
366 | * #### Notes
|
367 | * This is a no-op if the index is out of range.
|
368 | */
|
369 | TabBar.prototype.removeTabAt = function (index) {
|
370 | // Release the mouse before making any changes.
|
371 | this._releaseMouse();
|
372 | // Remove the title from the array.
|
373 | var title = algorithm_1.ArrayExt.removeAt(this._titles, index);
|
374 | // Bail if the index is out of range.
|
375 | if (!title) {
|
376 | return;
|
377 | }
|
378 | // Disconnect from the title changed signal.
|
379 | title.changed.disconnect(this._onTitleChanged, this);
|
380 | // Clear the previous title if it's being removed.
|
381 | if (title === this._previousTitle) {
|
382 | this._previousTitle = null;
|
383 | }
|
384 | // Schedule an update of the tabs.
|
385 | this.update();
|
386 | // Adjust the current index for the remove.
|
387 | this._adjustCurrentForRemove(index, title);
|
388 | };
|
389 | /**
|
390 | * Remove all tabs from the tab bar.
|
391 | */
|
392 | TabBar.prototype.clearTabs = function () {
|
393 | // Bail if there is nothing to remove.
|
394 | if (this._titles.length === 0) {
|
395 | return;
|
396 | }
|
397 | // Release the mouse before making any changes.
|
398 | this._releaseMouse();
|
399 | // Disconnect from the title changed signals.
|
400 | for (var _i = 0, _a = this._titles; _i < _a.length; _i++) {
|
401 | var title = _a[_i];
|
402 | title.changed.disconnect(this._onTitleChanged, this);
|
403 | }
|
404 | // Get the current index and title.
|
405 | var pi = this.currentIndex;
|
406 | var pt = this.currentTitle;
|
407 | // Reset the current index and previous title.
|
408 | this._currentIndex = -1;
|
409 | this._previousTitle = null;
|
410 | // Clear the title array.
|
411 | this._titles.length = 0;
|
412 | // Schedule an update of the tabs.
|
413 | this.update();
|
414 | // If no tab was selected, there's nothing else to do.
|
415 | if (pi === -1) {
|
416 | return;
|
417 | }
|
418 | // Emit the current changed signal.
|
419 | this._currentChanged.emit({
|
420 | previousIndex: pi, previousTitle: pt,
|
421 | currentIndex: -1, currentTitle: null
|
422 | });
|
423 | };
|
424 | /**
|
425 | * Release the mouse and restore the non-dragged tab positions.
|
426 | *
|
427 | * #### Notes
|
428 | * This will cause the tab bar to stop handling mouse events and to
|
429 | * restore the tabs to their non-dragged positions.
|
430 | */
|
431 | TabBar.prototype.releaseMouse = function () {
|
432 | this._releaseMouse();
|
433 | };
|
434 | /**
|
435 | * Handle the DOM events for the tab bar.
|
436 | *
|
437 | * @param event - The DOM event sent to the tab bar.
|
438 | *
|
439 | * #### Notes
|
440 | * This method implements the DOM `EventListener` interface and is
|
441 | * called in response to events on the tab bar's DOM node.
|
442 | *
|
443 | * This should not be called directly by user code.
|
444 | */
|
445 | TabBar.prototype.handleEvent = function (event) {
|
446 | switch (event.type) {
|
447 | case 'mousedown':
|
448 | this._evtMouseDown(event);
|
449 | break;
|
450 | case 'mousemove':
|
451 | this._evtMouseMove(event);
|
452 | break;
|
453 | case 'mouseup':
|
454 | this._evtMouseUp(event);
|
455 | break;
|
456 | case 'keydown':
|
457 | this._evtKeyDown(event);
|
458 | break;
|
459 | case 'contextmenu':
|
460 | event.preventDefault();
|
461 | event.stopPropagation();
|
462 | break;
|
463 | }
|
464 | };
|
465 | /**
|
466 | * A message handler invoked on a `'before-attach'` message.
|
467 | */
|
468 | TabBar.prototype.onBeforeAttach = function (msg) {
|
469 | this.node.addEventListener('mousedown', this);
|
470 | };
|
471 | /**
|
472 | * A message handler invoked on an `'after-detach'` message.
|
473 | */
|
474 | TabBar.prototype.onAfterDetach = function (msg) {
|
475 | this.node.removeEventListener('mousedown', this);
|
476 | this._releaseMouse();
|
477 | };
|
478 | /**
|
479 | * A message handler invoked on an `'update-request'` message.
|
480 | */
|
481 | TabBar.prototype.onUpdateRequest = function (msg) {
|
482 | var titles = this._titles;
|
483 | var renderer = this.renderer;
|
484 | var currentTitle = this.currentTitle;
|
485 | var content = new Array(titles.length);
|
486 | for (var i = 0, n = titles.length; i < n; ++i) {
|
487 | var title = titles[i];
|
488 | var current = title === currentTitle;
|
489 | var zIndex = current ? n : n - i - 1;
|
490 | content[i] = renderer.renderTab({ title: title, current: current, zIndex: zIndex });
|
491 | }
|
492 | virtualdom_1.VirtualDOM.render(content, this.contentNode);
|
493 | };
|
494 | /**
|
495 | * Handle the `'keydown'` event for the tab bar.
|
496 | */
|
497 | TabBar.prototype._evtKeyDown = function (event) {
|
498 | // Stop all input events during drag.
|
499 | event.preventDefault();
|
500 | event.stopPropagation();
|
501 | // Release the mouse if `Escape` is pressed.
|
502 | if (event.keyCode === 27) {
|
503 | this._releaseMouse();
|
504 | }
|
505 | };
|
506 | /**
|
507 | * Handle the `'mousedown'` event for the tab bar.
|
508 | */
|
509 | TabBar.prototype._evtMouseDown = function (event) {
|
510 | // Do nothing if it's not a left or middle mouse press.
|
511 | if (event.button !== 0 && event.button !== 1) {
|
512 | return;
|
513 | }
|
514 | // Do nothing if a drag is in progress.
|
515 | if (this._dragData) {
|
516 | return;
|
517 | }
|
518 | // Lookup the tab nodes.
|
519 | var tabs = this.contentNode.children;
|
520 | // Find the index of the pressed tab.
|
521 | var index = algorithm_1.ArrayExt.findFirstIndex(tabs, function (tab) {
|
522 | return domutils_1.ElementExt.hitTest(tab, event.clientX, event.clientY);
|
523 | });
|
524 | // Do nothing if the press is not on a tab.
|
525 | if (index === -1) {
|
526 | return;
|
527 | }
|
528 | // Pressing on a tab stops the event propagation.
|
529 | event.preventDefault();
|
530 | event.stopPropagation();
|
531 | // Initialize the non-measured parts of the drag data.
|
532 | this._dragData = {
|
533 | tab: tabs[index],
|
534 | index: index,
|
535 | pressX: event.clientX,
|
536 | pressY: event.clientY,
|
537 | tabPos: -1,
|
538 | tabSize: -1,
|
539 | tabPressPos: -1,
|
540 | targetIndex: -1,
|
541 | tabLayout: null,
|
542 | contentRect: null,
|
543 | override: null,
|
544 | dragActive: false,
|
545 | dragAborted: false,
|
546 | detachRequested: false
|
547 | };
|
548 | // Add the document mouse up listener.
|
549 | document.addEventListener('mouseup', this, true);
|
550 | // Do nothing else if the middle button is clicked.
|
551 | if (event.button === 1) {
|
552 | return;
|
553 | }
|
554 | // Do nothing else if the close icon is clicked.
|
555 | var icon = tabs[index].querySelector(this.renderer.closeIconSelector);
|
556 | if (icon && icon.contains(event.target)) {
|
557 | return;
|
558 | }
|
559 | // Add the extra listeners if the tabs are movable.
|
560 | if (this.tabsMovable) {
|
561 | document.addEventListener('mousemove', this, true);
|
562 | document.addEventListener('keydown', this, true);
|
563 | document.addEventListener('contextmenu', this, true);
|
564 | }
|
565 | // Update the current index as appropriate.
|
566 | if (this.allowDeselect && this.currentIndex === index) {
|
567 | this.currentIndex = -1;
|
568 | }
|
569 | else {
|
570 | this.currentIndex = index;
|
571 | }
|
572 | // Do nothing else if there is no current tab.
|
573 | if (this.currentIndex === -1) {
|
574 | return;
|
575 | }
|
576 | // Emit the tab activate request signal.
|
577 | this._tabActivateRequested.emit({
|
578 | index: this.currentIndex, title: this.currentTitle
|
579 | });
|
580 | };
|
581 | /**
|
582 | * Handle the `'mousemove'` event for the tab bar.
|
583 | */
|
584 | TabBar.prototype._evtMouseMove = function (event) {
|
585 | // Do nothing if no drag is in progress.
|
586 | var data = this._dragData;
|
587 | if (!data) {
|
588 | return;
|
589 | }
|
590 | // Suppress the event during a drag.
|
591 | event.preventDefault();
|
592 | event.stopPropagation();
|
593 | // Lookup the tab nodes.
|
594 | var tabs = this.contentNode.children;
|
595 | // Bail early if the drag threshold has not been met.
|
596 | if (!data.dragActive && !Private.dragExceeded(data, event)) {
|
597 | return;
|
598 | }
|
599 | // Activate the drag if necessary.
|
600 | if (!data.dragActive) {
|
601 | // Fill in the rest of the drag data measurements.
|
602 | var tabRect = data.tab.getBoundingClientRect();
|
603 | if (this._orientation === 'horizontal') {
|
604 | data.tabPos = data.tab.offsetLeft;
|
605 | data.tabSize = tabRect.width;
|
606 | data.tabPressPos = data.pressX - tabRect.left;
|
607 | }
|
608 | else {
|
609 | data.tabPos = data.tab.offsetTop;
|
610 | data.tabSize = tabRect.height;
|
611 | data.tabPressPos = data.pressY - tabRect.top;
|
612 | }
|
613 | data.tabLayout = Private.snapTabLayout(tabs, this._orientation);
|
614 | data.contentRect = this.contentNode.getBoundingClientRect();
|
615 | data.override = dragdrop_1.Drag.overrideCursor('default');
|
616 | // Add the dragging style classes.
|
617 | data.tab.classList.add('p-mod-dragging');
|
618 | this.addClass('p-mod-dragging');
|
619 | // Mark the drag as active.
|
620 | data.dragActive = true;
|
621 | }
|
622 | // Emit the detach requested signal if the threshold is exceeded.
|
623 | if (!data.detachRequested && Private.detachExceeded(data, event)) {
|
624 | // Only emit the signal once per drag cycle.
|
625 | data.detachRequested = true;
|
626 | // Setup the arguments for the signal.
|
627 | var index = data.index;
|
628 | var clientX = event.clientX;
|
629 | var clientY = event.clientY;
|
630 | var tab = tabs[index];
|
631 | var title = this._titles[index];
|
632 | // Emit the tab detach requested signal.
|
633 | this._tabDetachRequested.emit({ index: index, title: title, tab: tab, clientX: clientX, clientY: clientY });
|
634 | // Bail if the signal handler aborted the drag.
|
635 | if (data.dragAborted) {
|
636 | return;
|
637 | }
|
638 | }
|
639 | // Update the positions of the tabs.
|
640 | Private.layoutTabs(tabs, data, event, this._orientation);
|
641 | };
|
642 | /**
|
643 | * Handle the `'mouseup'` event for the document.
|
644 | */
|
645 | TabBar.prototype._evtMouseUp = function (event) {
|
646 | var _this = this;
|
647 | // Do nothing if it's not a left or middle mouse release.
|
648 | if (event.button !== 0 && event.button !== 1) {
|
649 | return;
|
650 | }
|
651 | // Do nothing if no drag is in progress.
|
652 | var data = this._dragData;
|
653 | if (!data) {
|
654 | return;
|
655 | }
|
656 | // Stop the event propagation.
|
657 | event.preventDefault();
|
658 | event.stopPropagation();
|
659 | // Remove the extra mouse event listeners.
|
660 | document.removeEventListener('mousemove', this, true);
|
661 | document.removeEventListener('mouseup', this, true);
|
662 | document.removeEventListener('keydown', this, true);
|
663 | document.removeEventListener('contextmenu', this, true);
|
664 | // Handle a release when the drag is not active.
|
665 | if (!data.dragActive) {
|
666 | // Clear the drag data.
|
667 | this._dragData = null;
|
668 | // Lookup the tab nodes.
|
669 | var tabs = this.contentNode.children;
|
670 | // Find the index of the released tab.
|
671 | var index = algorithm_1.ArrayExt.findFirstIndex(tabs, function (tab) {
|
672 | return domutils_1.ElementExt.hitTest(tab, event.clientX, event.clientY);
|
673 | });
|
674 | // Do nothing if the release is not on the original pressed tab.
|
675 | if (index !== data.index) {
|
676 | return;
|
677 | }
|
678 | // Ignore the release if the title is not closable.
|
679 | var title = this._titles[index];
|
680 | if (!title.closable) {
|
681 | return;
|
682 | }
|
683 | // Emit the close requested signal if the middle button is released.
|
684 | if (event.button === 1) {
|
685 | this._tabCloseRequested.emit({ index: index, title: title });
|
686 | return;
|
687 | }
|
688 | // Emit the close requested signal if the close icon was released.
|
689 | var icon = tabs[index].querySelector(this.renderer.closeIconSelector);
|
690 | if (icon && icon.contains(event.target)) {
|
691 | this._tabCloseRequested.emit({ index: index, title: title });
|
692 | return;
|
693 | }
|
694 | // Otherwise, there is nothing left to do.
|
695 | return;
|
696 | }
|
697 | // Do nothing if the left button is not released.
|
698 | if (event.button !== 0) {
|
699 | return;
|
700 | }
|
701 | // Position the tab at its final resting position.
|
702 | Private.finalizeTabPosition(data, this._orientation);
|
703 | // Remove the dragging class from the tab so it can be transitioned.
|
704 | data.tab.classList.remove('p-mod-dragging');
|
705 | // Parse the transition duration for releasing the tab.
|
706 | var duration = Private.parseTransitionDuration(data.tab);
|
707 | // Complete the release on a timer to allow the tab to transition.
|
708 | setTimeout(function () {
|
709 | // Do nothing if the drag has been aborted.
|
710 | if (data.dragAborted) {
|
711 | return;
|
712 | }
|
713 | // Clear the drag data reference.
|
714 | _this._dragData = null;
|
715 | // Reset the positions of the tabs.
|
716 | Private.resetTabPositions(_this.contentNode.children, _this._orientation);
|
717 | // Clear the cursor grab.
|
718 | data.override.dispose();
|
719 | // Remove the remaining dragging style.
|
720 | _this.removeClass('p-mod-dragging');
|
721 | // If the tab was not moved, there is nothing else to do.
|
722 | var i = data.index;
|
723 | var j = data.targetIndex;
|
724 | if (j === -1 || i === j) {
|
725 | return;
|
726 | }
|
727 | // Move the title to the new locations.
|
728 | algorithm_1.ArrayExt.move(_this._titles, i, j);
|
729 | // Adjust the current index for the move.
|
730 | _this._adjustCurrentForMove(i, j);
|
731 | // Emit the tab moved signal.
|
732 | _this._tabMoved.emit({
|
733 | fromIndex: i, toIndex: j, title: _this._titles[j]
|
734 | });
|
735 | // Update the tabs immediately to prevent flicker.
|
736 | messaging_1.MessageLoop.sendMessage(_this, widget_1.Widget.Msg.UpdateRequest);
|
737 | }, duration);
|
738 | };
|
739 | /**
|
740 | * Release the mouse and restore the non-dragged tab positions.
|
741 | */
|
742 | TabBar.prototype._releaseMouse = function () {
|
743 | // Do nothing if no drag is in progress.
|
744 | var data = this._dragData;
|
745 | if (!data) {
|
746 | return;
|
747 | }
|
748 | // Clear the drag data reference.
|
749 | this._dragData = null;
|
750 | // Remove the extra mouse listeners.
|
751 | document.removeEventListener('mousemove', this, true);
|
752 | document.removeEventListener('mouseup', this, true);
|
753 | document.removeEventListener('keydown', this, true);
|
754 | document.removeEventListener('contextmenu', this, true);
|
755 | // Indicate the drag has been aborted. This allows the mouse
|
756 | // event handlers to return early when the drag is canceled.
|
757 | data.dragAborted = true;
|
758 | // If the drag is not active, there's nothing more to do.
|
759 | if (!data.dragActive) {
|
760 | return;
|
761 | }
|
762 | // Reset the tabs to their non-dragged positions.
|
763 | Private.resetTabPositions(this.contentNode.children, this._orientation);
|
764 | // Clear the cursor override.
|
765 | data.override.dispose();
|
766 | // Clear the dragging style classes.
|
767 | data.tab.classList.remove('p-mod-dragging');
|
768 | this.removeClass('p-mod-dragging');
|
769 | };
|
770 | /**
|
771 | * Adjust the current index for a tab insert operation.
|
772 | *
|
773 | * This method accounts for the tab bar's insertion behavior when
|
774 | * adjusting the current index and emitting the changed signal.
|
775 | */
|
776 | TabBar.prototype._adjustCurrentForInsert = function (i, title) {
|
777 | // Lookup commonly used variables.
|
778 | var ct = this.currentTitle;
|
779 | var ci = this._currentIndex;
|
780 | var bh = this.insertBehavior;
|
781 | // Handle the behavior where the new tab is always selected,
|
782 | // or the behavior where the new tab is selected if needed.
|
783 | if (bh === 'select-tab' || (bh === 'select-tab-if-needed' && ci === -1)) {
|
784 | this._currentIndex = i;
|
785 | this._previousTitle = ct;
|
786 | this._currentChanged.emit({
|
787 | previousIndex: ci, previousTitle: ct,
|
788 | currentIndex: i, currentTitle: title
|
789 | });
|
790 | return;
|
791 | }
|
792 | // Otherwise, silently adjust the current index if needed.
|
793 | if (ci >= i) {
|
794 | this._currentIndex++;
|
795 | }
|
796 | };
|
797 | /**
|
798 | * Adjust the current index for a tab move operation.
|
799 | *
|
800 | * This method will not cause the actual current tab to change.
|
801 | * It silently adjusts the index to account for the given move.
|
802 | */
|
803 | TabBar.prototype._adjustCurrentForMove = function (i, j) {
|
804 | if (this._currentIndex === i) {
|
805 | this._currentIndex = j;
|
806 | }
|
807 | else if (this._currentIndex < i && this._currentIndex >= j) {
|
808 | this._currentIndex++;
|
809 | }
|
810 | else if (this._currentIndex > i && this._currentIndex <= j) {
|
811 | this._currentIndex--;
|
812 | }
|
813 | };
|
814 | /**
|
815 | * Adjust the current index for a tab remove operation.
|
816 | *
|
817 | * This method accounts for the tab bar's remove behavior when
|
818 | * adjusting the current index and emitting the changed signal.
|
819 | */
|
820 | TabBar.prototype._adjustCurrentForRemove = function (i, title) {
|
821 | // Lookup commonly used variables.
|
822 | var ci = this._currentIndex;
|
823 | var bh = this.removeBehavior;
|
824 | // Silently adjust the index if the current tab is not removed.
|
825 | if (ci !== i) {
|
826 | if (ci > i) {
|
827 | this._currentIndex--;
|
828 | }
|
829 | return;
|
830 | }
|
831 | // No tab gets selected if the tab bar is empty.
|
832 | if (this._titles.length === 0) {
|
833 | this._currentIndex = -1;
|
834 | this._currentChanged.emit({
|
835 | previousIndex: i, previousTitle: title,
|
836 | currentIndex: -1, currentTitle: null
|
837 | });
|
838 | return;
|
839 | }
|
840 | // Handle behavior where the next sibling tab is selected.
|
841 | if (bh === 'select-tab-after') {
|
842 | this._currentIndex = Math.min(i, this._titles.length - 1);
|
843 | this._currentChanged.emit({
|
844 | previousIndex: i, previousTitle: title,
|
845 | currentIndex: this._currentIndex, currentTitle: this.currentTitle
|
846 | });
|
847 | return;
|
848 | }
|
849 | // Handle behavior where the previous sibling tab is selected.
|
850 | if (bh === 'select-tab-before') {
|
851 | this._currentIndex = Math.max(0, i - 1);
|
852 | this._currentChanged.emit({
|
853 | previousIndex: i, previousTitle: title,
|
854 | currentIndex: this._currentIndex, currentTitle: this.currentTitle
|
855 | });
|
856 | return;
|
857 | }
|
858 | // Handle behavior where the previous history tab is selected.
|
859 | if (bh === 'select-previous-tab') {
|
860 | if (this._previousTitle) {
|
861 | this._currentIndex = this._titles.indexOf(this._previousTitle);
|
862 | this._previousTitle = null;
|
863 | }
|
864 | else {
|
865 | this._currentIndex = Math.min(i, this._titles.length - 1);
|
866 | }
|
867 | this._currentChanged.emit({
|
868 | previousIndex: i, previousTitle: title,
|
869 | currentIndex: this._currentIndex, currentTitle: this.currentTitle
|
870 | });
|
871 | return;
|
872 | }
|
873 | // Otherwise, no tab gets selected.
|
874 | this._currentIndex = -1;
|
875 | this._currentChanged.emit({
|
876 | previousIndex: i, previousTitle: title,
|
877 | currentIndex: -1, currentTitle: null
|
878 | });
|
879 | };
|
880 | /**
|
881 | * Handle the `changed` signal of a title object.
|
882 | */
|
883 | TabBar.prototype._onTitleChanged = function (sender) {
|
884 | this.update();
|
885 | };
|
886 | return TabBar;
|
887 | }(widget_1.Widget));
|
888 | exports.TabBar = TabBar;
|
889 | /**
|
890 | * The namespace for the `TabBar` class statics.
|
891 | */
|
892 | (function (TabBar) {
|
893 | /**
|
894 | * The default implementation of `IRenderer`.
|
895 | *
|
896 | * #### Notes
|
897 | * Subclasses are free to reimplement rendering methods as needed.
|
898 | */
|
899 | var Renderer = /** @class */ (function () {
|
900 | /**
|
901 | * Construct a new renderer.
|
902 | */
|
903 | function Renderer() {
|
904 | /**
|
905 | * A selector which matches the close icon node in a tab.
|
906 | */
|
907 | this.closeIconSelector = '.p-TabBar-tabCloseIcon';
|
908 | this._tabID = 0;
|
909 | this._tabKeys = new WeakMap();
|
910 | }
|
911 | /**
|
912 | * Render the virtual element for a tab.
|
913 | *
|
914 | * @param data - The data to use for rendering the tab.
|
915 | *
|
916 | * @returns A virtual element representing the tab.
|
917 | */
|
918 | Renderer.prototype.renderTab = function (data) {
|
919 | var title = data.title.caption;
|
920 | var key = this.createTabKey(data);
|
921 | var style = this.createTabStyle(data);
|
922 | var className = this.createTabClass(data);
|
923 | var dataset = this.createTabDataset(data);
|
924 | return (virtualdom_1.h.li({ key: key, className: className, title: title, style: style, dataset: dataset }, this.renderIcon(data), this.renderLabel(data), this.renderCloseIcon(data)));
|
925 | };
|
926 | /**
|
927 | * Render the icon element for a tab.
|
928 | *
|
929 | * @param data - The data to use for rendering the tab.
|
930 | *
|
931 | * @returns A virtual element representing the tab icon.
|
932 | */
|
933 | Renderer.prototype.renderIcon = function (data) {
|
934 | var className = this.createIconClass(data);
|
935 | return virtualdom_1.h.div({ className: className }, data.title.iconLabel);
|
936 | };
|
937 | /**
|
938 | * Render the label element for a tab.
|
939 | *
|
940 | * @param data - The data to use for rendering the tab.
|
941 | *
|
942 | * @returns A virtual element representing the tab label.
|
943 | */
|
944 | Renderer.prototype.renderLabel = function (data) {
|
945 | return virtualdom_1.h.div({ className: 'p-TabBar-tabLabel' }, data.title.label);
|
946 | };
|
947 | /**
|
948 | * Render the close icon element for a tab.
|
949 | *
|
950 | * @param data - The data to use for rendering the tab.
|
951 | *
|
952 | * @returns A virtual element representing the tab close icon.
|
953 | */
|
954 | Renderer.prototype.renderCloseIcon = function (data) {
|
955 | return virtualdom_1.h.div({ className: 'p-TabBar-tabCloseIcon' });
|
956 | };
|
957 | /**
|
958 | * Create a unique render key for the tab.
|
959 | *
|
960 | * @param data - The data to use for the tab.
|
961 | *
|
962 | * @returns The unique render key for the tab.
|
963 | *
|
964 | * #### Notes
|
965 | * This method caches the key against the tab title the first time
|
966 | * the key is generated. This enables efficient rendering of moved
|
967 | * tabs and avoids subtle hover style artifacts.
|
968 | */
|
969 | Renderer.prototype.createTabKey = function (data) {
|
970 | var key = this._tabKeys.get(data.title);
|
971 | if (key === undefined) {
|
972 | key = "tab-key-" + this._tabID++;
|
973 | this._tabKeys.set(data.title, key);
|
974 | }
|
975 | return key;
|
976 | };
|
977 | /**
|
978 | * Create the inline style object for a tab.
|
979 | *
|
980 | * @param data - The data to use for the tab.
|
981 | *
|
982 | * @returns The inline style data for the tab.
|
983 | */
|
984 | Renderer.prototype.createTabStyle = function (data) {
|
985 | return { zIndex: "" + data.zIndex };
|
986 | };
|
987 | /**
|
988 | * Create the class name for the tab.
|
989 | *
|
990 | * @param data - The data to use for the tab.
|
991 | *
|
992 | * @returns The full class name for the tab.
|
993 | */
|
994 | Renderer.prototype.createTabClass = function (data) {
|
995 | var name = 'p-TabBar-tab';
|
996 | if (data.title.className) {
|
997 | name += " " + data.title.className;
|
998 | }
|
999 | if (data.title.closable) {
|
1000 | name += ' p-mod-closable';
|
1001 | }
|
1002 | if (data.current) {
|
1003 | name += ' p-mod-current';
|
1004 | }
|
1005 | return name;
|
1006 | };
|
1007 | /**
|
1008 | * Create the dataset for a tab.
|
1009 | *
|
1010 | * @param data - The data to use for the tab.
|
1011 | *
|
1012 | * @returns The dataset for the tab.
|
1013 | */
|
1014 | Renderer.prototype.createTabDataset = function (data) {
|
1015 | return data.title.dataset;
|
1016 | };
|
1017 | /**
|
1018 | * Create the class name for the tab icon.
|
1019 | *
|
1020 | * @param data - The data to use for the tab.
|
1021 | *
|
1022 | * @returns The full class name for the tab icon.
|
1023 | */
|
1024 | Renderer.prototype.createIconClass = function (data) {
|
1025 | var name = 'p-TabBar-tabIcon';
|
1026 | var extra = data.title.iconClass;
|
1027 | return extra ? name + " " + extra : name;
|
1028 | };
|
1029 | return Renderer;
|
1030 | }());
|
1031 | TabBar.Renderer = Renderer;
|
1032 | /**
|
1033 | * The default `Renderer` instance.
|
1034 | */
|
1035 | TabBar.defaultRenderer = new Renderer();
|
1036 | })(TabBar = exports.TabBar || (exports.TabBar = {}));
|
1037 | exports.TabBar = TabBar;
|
1038 | /**
|
1039 | * The namespace for the module implementation details.
|
1040 | */
|
1041 | var Private;
|
1042 | (function (Private) {
|
1043 | /**
|
1044 | * The start drag distance threshold.
|
1045 | */
|
1046 | Private.DRAG_THRESHOLD = 5;
|
1047 | /**
|
1048 | * The detach distance threshold.
|
1049 | */
|
1050 | Private.DETACH_THRESHOLD = 20;
|
1051 | /**
|
1052 | * Create the DOM node for a tab bar.
|
1053 | */
|
1054 | function createNode() {
|
1055 | var node = document.createElement('div');
|
1056 | var content = document.createElement('ul');
|
1057 | content.className = 'p-TabBar-content';
|
1058 | node.appendChild(content);
|
1059 | return node;
|
1060 | }
|
1061 | Private.createNode = createNode;
|
1062 | /**
|
1063 | * Coerce a title or options into a real title.
|
1064 | */
|
1065 | function asTitle(value) {
|
1066 | return value instanceof title_1.Title ? value : new title_1.Title(value);
|
1067 | }
|
1068 | Private.asTitle = asTitle;
|
1069 | /**
|
1070 | * Parse the transition duration for a tab node.
|
1071 | */
|
1072 | function parseTransitionDuration(tab) {
|
1073 | var style = window.getComputedStyle(tab);
|
1074 | return 1000 * (parseFloat(style.transitionDuration) || 0);
|
1075 | }
|
1076 | Private.parseTransitionDuration = parseTransitionDuration;
|
1077 | /**
|
1078 | * Get a snapshot of the current tab layout values.
|
1079 | */
|
1080 | function snapTabLayout(tabs, orientation) {
|
1081 | var layout = new Array(tabs.length);
|
1082 | for (var i = 0, n = tabs.length; i < n; ++i) {
|
1083 | var node = tabs[i];
|
1084 | var style = window.getComputedStyle(node);
|
1085 | if (orientation === 'horizontal') {
|
1086 | layout[i] = {
|
1087 | pos: node.offsetLeft,
|
1088 | size: node.offsetWidth,
|
1089 | margin: parseFloat(style.marginLeft) || 0
|
1090 | };
|
1091 | }
|
1092 | else {
|
1093 | layout[i] = {
|
1094 | pos: node.offsetTop,
|
1095 | size: node.offsetHeight,
|
1096 | margin: parseFloat(style.marginTop) || 0
|
1097 | };
|
1098 | }
|
1099 | }
|
1100 | return layout;
|
1101 | }
|
1102 | Private.snapTabLayout = snapTabLayout;
|
1103 | /**
|
1104 | * Test if the event exceeds the drag threshold.
|
1105 | */
|
1106 | function dragExceeded(data, event) {
|
1107 | var dx = Math.abs(event.clientX - data.pressX);
|
1108 | var dy = Math.abs(event.clientY - data.pressY);
|
1109 | return dx >= Private.DRAG_THRESHOLD || dy >= Private.DRAG_THRESHOLD;
|
1110 | }
|
1111 | Private.dragExceeded = dragExceeded;
|
1112 | /**
|
1113 | * Test if the event exceeds the drag detach threshold.
|
1114 | */
|
1115 | function detachExceeded(data, event) {
|
1116 | var rect = data.contentRect;
|
1117 | return ((event.clientX < rect.left - Private.DETACH_THRESHOLD) ||
|
1118 | (event.clientX >= rect.right + Private.DETACH_THRESHOLD) ||
|
1119 | (event.clientY < rect.top - Private.DETACH_THRESHOLD) ||
|
1120 | (event.clientY >= rect.bottom + Private.DETACH_THRESHOLD));
|
1121 | }
|
1122 | Private.detachExceeded = detachExceeded;
|
1123 | /**
|
1124 | * Update the relative tab positions and computed target index.
|
1125 | */
|
1126 | function layoutTabs(tabs, data, event, orientation) {
|
1127 | // Compute the orientation-sensitive values.
|
1128 | var pressPos;
|
1129 | var localPos;
|
1130 | var clientPos;
|
1131 | var clientSize;
|
1132 | if (orientation === 'horizontal') {
|
1133 | pressPos = data.pressX;
|
1134 | localPos = event.clientX - data.contentRect.left;
|
1135 | clientPos = event.clientX;
|
1136 | clientSize = data.contentRect.width;
|
1137 | }
|
1138 | else {
|
1139 | pressPos = data.pressY;
|
1140 | localPos = event.clientY - data.contentRect.top;
|
1141 | clientPos = event.clientY;
|
1142 | clientSize = data.contentRect.height;
|
1143 | }
|
1144 | // Compute the target data.
|
1145 | var targetIndex = data.index;
|
1146 | var targetPos = localPos - data.tabPressPos;
|
1147 | var targetEnd = targetPos + data.tabSize;
|
1148 | // Update the relative tab positions.
|
1149 | for (var i = 0, n = tabs.length; i < n; ++i) {
|
1150 | var pxPos = void 0;
|
1151 | var layout = data.tabLayout[i];
|
1152 | var threshold = layout.pos + (layout.size >> 1);
|
1153 | if (i < data.index && targetPos < threshold) {
|
1154 | pxPos = data.tabSize + data.tabLayout[i + 1].margin + "px";
|
1155 | targetIndex = Math.min(targetIndex, i);
|
1156 | }
|
1157 | else if (i > data.index && targetEnd > threshold) {
|
1158 | pxPos = -data.tabSize - layout.margin + "px";
|
1159 | targetIndex = Math.max(targetIndex, i);
|
1160 | }
|
1161 | else if (i === data.index) {
|
1162 | var ideal = clientPos - pressPos;
|
1163 | var limit = clientSize - (data.tabPos + data.tabSize);
|
1164 | pxPos = Math.max(-data.tabPos, Math.min(ideal, limit)) + "px";
|
1165 | }
|
1166 | else {
|
1167 | pxPos = '';
|
1168 | }
|
1169 | if (orientation === 'horizontal') {
|
1170 | tabs[i].style.left = pxPos;
|
1171 | }
|
1172 | else {
|
1173 | tabs[i].style.top = pxPos;
|
1174 | }
|
1175 | }
|
1176 | // Update the computed target index.
|
1177 | data.targetIndex = targetIndex;
|
1178 | }
|
1179 | Private.layoutTabs = layoutTabs;
|
1180 | /**
|
1181 | * Position the drag tab at its final resting relative position.
|
1182 | */
|
1183 | function finalizeTabPosition(data, orientation) {
|
1184 | // Compute the orientation-sensitive client size.
|
1185 | var clientSize;
|
1186 | if (orientation === 'horizontal') {
|
1187 | clientSize = data.contentRect.width;
|
1188 | }
|
1189 | else {
|
1190 | clientSize = data.contentRect.height;
|
1191 | }
|
1192 | // Compute the ideal final tab position.
|
1193 | var ideal;
|
1194 | if (data.targetIndex === data.index) {
|
1195 | ideal = 0;
|
1196 | }
|
1197 | else if (data.targetIndex > data.index) {
|
1198 | var tgt = data.tabLayout[data.targetIndex];
|
1199 | ideal = tgt.pos + tgt.size - data.tabSize - data.tabPos;
|
1200 | }
|
1201 | else {
|
1202 | var tgt = data.tabLayout[data.targetIndex];
|
1203 | ideal = tgt.pos - data.tabPos;
|
1204 | }
|
1205 | // Compute the tab position limit.
|
1206 | var limit = clientSize - (data.tabPos + data.tabSize);
|
1207 | var final = Math.max(-data.tabPos, Math.min(ideal, limit));
|
1208 | // Set the final orientation-sensitive position.
|
1209 | if (orientation === 'horizontal') {
|
1210 | data.tab.style.left = final + "px";
|
1211 | }
|
1212 | else {
|
1213 | data.tab.style.top = final + "px";
|
1214 | }
|
1215 | }
|
1216 | Private.finalizeTabPosition = finalizeTabPosition;
|
1217 | /**
|
1218 | * Reset the relative positions of the given tabs.
|
1219 | */
|
1220 | function resetTabPositions(tabs, orientation) {
|
1221 | algorithm_1.each(tabs, function (tab) {
|
1222 | if (orientation === 'horizontal') {
|
1223 | tab.style.left = '';
|
1224 | }
|
1225 | else {
|
1226 | tab.style.top = '';
|
1227 | }
|
1228 | });
|
1229 | }
|
1230 | Private.resetTabPositions = resetTabPositions;
|
1231 | })(Private || (Private = {}));
|