mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
use shared headroom
This commit is contained in:
parent
e5b6336256
commit
a11c82ac9d
12 changed files with 177 additions and 156 deletions
|
@ -130,11 +130,11 @@
|
|||
* @param {DOMElement} elem the header element
|
||||
* @param {Object} options options for the widget
|
||||
*/
|
||||
function Headroom(elem, options) {
|
||||
function Headroom(elems, options) {
|
||||
options = extend(options, Headroom.options);
|
||||
|
||||
this.lastKnownScrollY = 0;
|
||||
this.elem = elem;
|
||||
this.elems = elems;
|
||||
this.debouncer = new Debouncer(this.update.bind(this));
|
||||
this.tolerance = normalizeTolerance(options.tolerance);
|
||||
this.classes = options.classes;
|
||||
|
@ -143,8 +143,6 @@
|
|||
this.initialised = false;
|
||||
this.onPin = options.onPin;
|
||||
this.onUnpin = options.onUnpin;
|
||||
this.onTop = options.onTop;
|
||||
this.onNotTop = options.onNotTop;
|
||||
}
|
||||
Headroom.prototype = {
|
||||
constructor: Headroom,
|
||||
|
@ -154,13 +152,30 @@
|
|||
*/
|
||||
init: function () {
|
||||
|
||||
this.elem.classList.add(this.classes.initial);
|
||||
for (var i = 0, length = this.elems.length; i < length; i++) {
|
||||
this.elems[i].classList.add(this.classes.initial);
|
||||
}
|
||||
|
||||
this.attachEvent();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
add: function (elem) {
|
||||
elem.classList.add(this.classes.initial);
|
||||
this.elems.push(elem);
|
||||
},
|
||||
|
||||
remove: function (elem) {
|
||||
|
||||
var classes = this.classes;
|
||||
elem.classList.remove(classes.unpinned, classes.pinned, classes.initial);
|
||||
var i = this.elems.indexOf(elem);
|
||||
if (i != -1) {
|
||||
this.elems.splice(i, 1);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Unattaches events and removes any classes that were added
|
||||
*/
|
||||
|
@ -168,7 +183,11 @@
|
|||
var classes = this.classes;
|
||||
|
||||
this.initialised = false;
|
||||
this.elem.classList.remove(classes.unpinned, classes.pinned, classes.top, classes.initial);
|
||||
|
||||
for (var i = 0, length = this.elems.length; i < length; i++) {
|
||||
this.elems[i].classList.remove(classes.unpinned, classes.pinned, classes.initial);
|
||||
}
|
||||
|
||||
removeEventListenerWithOptions(this.scroller, 'scroll', this.debouncer, {
|
||||
capture: false,
|
||||
passive: true
|
||||
|
@ -196,13 +215,17 @@
|
|||
* Unpins the header if it's currently pinned
|
||||
*/
|
||||
unpin: function () {
|
||||
var classList = this.elem.classList,
|
||||
classes = this.classes;
|
||||
|
||||
if (classList.contains(classes.pinned) || !classList.contains(classes.unpinned)) {
|
||||
classList.add(classes.unpinned);
|
||||
classList.remove(classes.pinned);
|
||||
this.onUnpin && this.onUnpin.call(this);
|
||||
var classes = this.classes;
|
||||
|
||||
for (var i = 0, length = this.elems.length; i < length; i++) {
|
||||
var classList = this.elems[i].classList;
|
||||
|
||||
if (classList.contains(classes.pinned) || !classList.contains(classes.unpinned)) {
|
||||
classList.add(classes.unpinned);
|
||||
classList.remove(classes.pinned);
|
||||
this.onUnpin && this.onUnpin.call(this);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -210,42 +233,19 @@
|
|||
* Pins the header if it's currently unpinned
|
||||
*/
|
||||
pin: function () {
|
||||
var classList = this.elem.classList,
|
||||
classes = this.classes;
|
||||
|
||||
if (classList.contains(classes.unpinned)) {
|
||||
classList.remove(classes.unpinned);
|
||||
classList.add(classes.pinned);
|
||||
this.onPin && this.onPin.call(this);
|
||||
var classes = this.classes;
|
||||
|
||||
for (var i = 0, length = this.elems.length; i < length; i++) {
|
||||
var classList = this.elems[i].classList;
|
||||
|
||||
if (classList.contains(classes.unpinned)) {
|
||||
classList.remove(classes.unpinned);
|
||||
classList.add(classes.pinned);
|
||||
this.onPin && this.onPin.call(this);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the top states
|
||||
*/
|
||||
top: function () {
|
||||
var classList = this.elem.classList,
|
||||
classes = this.classes;
|
||||
|
||||
if (!classList.contains(classes.top)) {
|
||||
classList.add(classes.top);
|
||||
classList.remove(classes.notTop);
|
||||
this.onTop && this.onTop.call(this);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the not top state
|
||||
*/
|
||||
notTop: function () {
|
||||
var classList = this.elem.classList,
|
||||
classes = this.classes;
|
||||
|
||||
if (!classList.contains(classes.notTop)) {
|
||||
classList.add(classes.notTop);
|
||||
classList.remove(classes.top);
|
||||
this.onNotTop && this.onNotTop.call(this);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -315,14 +315,6 @@
|
|||
return;
|
||||
}
|
||||
|
||||
if (this.enableTopClasses) {
|
||||
if (currentScrollY <= this.offset) {
|
||||
this.top();
|
||||
} else {
|
||||
this.notTop();
|
||||
}
|
||||
}
|
||||
|
||||
if (this.shouldUnpin(currentScrollY, toleranceExceeded)) {
|
||||
this.unpin();
|
||||
}
|
||||
|
@ -347,8 +339,6 @@
|
|||
classes: {
|
||||
pinned: 'headroom--pinned',
|
||||
unpinned: 'headroom--unpinned',
|
||||
top: 'headroom--top',
|
||||
notTop: 'headroom--not-top',
|
||||
initial: 'headroom'
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div id="channelsPage" data-role="page" data-dom-cache="true" class="page libraryPage channelsPage pageWithAbsoluteTabs" data-contextname="${HeaderChannels}" data-require="scripts/channels,scripts/channelslatest,scripts/sections">
|
||||
<div id="channelsPage" data-role="page" data-dom-cache="true" class="page libraryPage channelsPage pageWithAbsoluteTabs" data-contextname="${HeaderChannels}">
|
||||
|
||||
<div is="emby-tabs" class="libraryViewNav">
|
||||
<div class="emby-tabs-slider">
|
||||
|
|
|
@ -5,16 +5,9 @@
|
|||
right: 0;
|
||||
z-index: 1;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.appfooter-headroom {
|
||||
transition: transform 180ms linear;
|
||||
}
|
||||
|
||||
.appfooter--pinned {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.appfooter--unpinned {
|
||||
.appfooter.headroom--unpinned {
|
||||
transform: translateY(100%);
|
||||
}
|
|
@ -13,27 +13,10 @@
|
|||
|
||||
function initHeadRoom(instance, elem) {
|
||||
|
||||
require(["headroom"], function () {
|
||||
require(["headroom-window"], function (headroom) {
|
||||
|
||||
// construct an instance of Headroom, passing the element
|
||||
var headroom = new Headroom(elem, {
|
||||
// or scroll tolerance per direction
|
||||
tolerance: {
|
||||
down: 20,
|
||||
up: 0
|
||||
},
|
||||
classes: {
|
||||
pinned: 'appfooter--pinned',
|
||||
unpinned: 'appfooter--unpinned',
|
||||
top: 'appfooter--top',
|
||||
notTop: 'appfooter--not-top',
|
||||
initial: 'appfooter-headroom'
|
||||
}
|
||||
});
|
||||
// initialise
|
||||
headroom.init();
|
||||
|
||||
instance.headroom = headroom;
|
||||
self.headroom = headroom;
|
||||
headroom.add(elem);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -62,10 +45,11 @@
|
|||
var self = this;
|
||||
|
||||
if (self.headroom) {
|
||||
self.headroom.destroy();
|
||||
self.headroom.remove(self.element);
|
||||
self.headroom = null;
|
||||
}
|
||||
|
||||
self.Element = null;
|
||||
self.element = null;
|
||||
};
|
||||
|
||||
return dockedTabs;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
define(['libraryBrowser', 'cardBuilder', 'emby-itemscontainer', 'emby-tabs', 'emby-button'], function (libraryBrowser, cardBuilder) {
|
||||
define(['libraryBrowser', 'cardBuilder', 'emby-itemscontainer', 'emby-tabs', 'emby-button', 'scripts/channelslatest', 'scripts/sections'], function (libraryBrowser, cardBuilder) {
|
||||
|
||||
// The base query options
|
||||
var query = {
|
||||
|
@ -70,18 +70,29 @@
|
|||
}
|
||||
}
|
||||
|
||||
pageIdOn('pageinit', "channelsPage", function () {
|
||||
return function (view, params) {
|
||||
|
||||
var page = this;
|
||||
var self = this;
|
||||
var viewTabs = view.querySelector('.libraryViewNav');
|
||||
|
||||
var mdlTabs = page.querySelector('.libraryViewNav');
|
||||
libraryBrowser.configurePaperLibraryTabs(view, viewTabs, view.querySelectorAll('.pageTabContent'), [0, 1]);
|
||||
|
||||
libraryBrowser.configurePaperLibraryTabs(page, mdlTabs, page.querySelectorAll('.pageTabContent'), [0, 1]);
|
||||
|
||||
mdlTabs.addEventListener('tabchange', function (e) {
|
||||
loadTab(page, parseInt(e.detail.selectedTabIndex));
|
||||
viewTabs.addEventListener('tabchange', function (e) {
|
||||
loadTab(view, parseInt(e.detail.selectedTabIndex));
|
||||
});
|
||||
|
||||
});
|
||||
if (AppInfo.enableHeadRoom) {
|
||||
require(["headroom-window"], function (headroom) {
|
||||
headroom.add(viewTabs);
|
||||
self.headroom = headroom;
|
||||
});
|
||||
}
|
||||
|
||||
view.addEventListener('viewdestroy', function (e) {
|
||||
|
||||
if (self.headroom) {
|
||||
self.headroom.remove(viewTabs);
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
|
@ -248,9 +248,9 @@
|
|||
loadHomeTab(view, tabContent);
|
||||
};
|
||||
|
||||
var mdlTabs = view.querySelector('.libraryViewNav');
|
||||
var viewTabs = view.querySelector('.libraryViewNav');
|
||||
|
||||
libraryBrowser.configurePaperLibraryTabs(view, mdlTabs, view.querySelectorAll('.pageTabContent'), [0, 1, 2, 3]);
|
||||
libraryBrowser.configurePaperLibraryTabs(view, viewTabs, view.querySelectorAll('.pageTabContent'), [0, 1, 2, 3]);
|
||||
|
||||
var tabControllers = [];
|
||||
var renderedTabs = [];
|
||||
|
@ -319,11 +319,11 @@
|
|||
});
|
||||
}
|
||||
|
||||
mdlTabs.addEventListener('beforetabchange', function (e) {
|
||||
viewTabs.addEventListener('beforetabchange', function (e) {
|
||||
preLoadTab(view, parseInt(e.detail.selectedTabIndex));
|
||||
});
|
||||
|
||||
mdlTabs.addEventListener('tabchange', function (e) {
|
||||
viewTabs.addEventListener('tabchange', function (e) {
|
||||
loadTab(view, parseInt(e.detail.selectedTabIndex));
|
||||
});
|
||||
|
||||
|
@ -343,7 +343,7 @@
|
|||
|
||||
if (state.NowPlayingItem && state.NowPlayingItem.MediaType == 'Video') {
|
||||
|
||||
mdlTabs.triggerTabChange();
|
||||
viewTabs.triggerTabChange();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -370,5 +370,18 @@
|
|||
Events.off(MediaController, 'playbackstop', onPlaybackStop);
|
||||
Events.off(ApiClient, "websocketmessage", onWebSocketMessage);
|
||||
});
|
||||
|
||||
if (AppInfo.enableHeadRoom) {
|
||||
require(["headroom-window"], function (headroom) {
|
||||
headroom.add(viewTabs);
|
||||
self.headroom = headroom;
|
||||
});
|
||||
}
|
||||
|
||||
view.addEventListener('viewdestroy', function (e) {
|
||||
if (self.headroom) {
|
||||
self.headroom.remove(viewTabs);
|
||||
}
|
||||
});
|
||||
};
|
||||
});
|
|
@ -879,21 +879,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
pageClassOn('pageinit', 'page', function () {
|
||||
|
||||
var page = this;
|
||||
|
||||
var isLibraryPage = page.classList.contains('libraryPage');
|
||||
|
||||
if (isLibraryPage) {
|
||||
|
||||
var navs = page.querySelectorAll('.libraryViewNav');
|
||||
for (var i = 0, length = navs.length; i < length; i++) {
|
||||
initHeadRoom(navs[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
pageClassOn('pagebeforeshow', 'page', function (e) {
|
||||
|
||||
var page = this;
|
||||
|
@ -999,18 +984,9 @@
|
|||
return;
|
||||
}
|
||||
|
||||
require(["headroom"], function () {
|
||||
require(["headroom-window"], function (headroom) {
|
||||
|
||||
// construct an instance of Headroom, passing the element
|
||||
var headroom = new Headroom(elem, {
|
||||
// or scroll tolerance per direction
|
||||
tolerance: {
|
||||
down: 40,
|
||||
up: 0
|
||||
}
|
||||
});
|
||||
// initialise
|
||||
headroom.init();
|
||||
headroom.add(elem);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -198,11 +198,11 @@
|
|||
});
|
||||
}
|
||||
|
||||
var mdlTabs = view.querySelector('.libraryViewNav');
|
||||
var viewTabs = view.querySelector('.libraryViewNav');
|
||||
|
||||
libraryBrowser.configurePaperLibraryTabs(view, mdlTabs, view.querySelectorAll('.pageTabContent'), [0, 2, 3, 4]);
|
||||
libraryBrowser.configurePaperLibraryTabs(view, viewTabs, view.querySelectorAll('.pageTabContent'), [0, 2, 3, 4]);
|
||||
|
||||
mdlTabs.addEventListener('tabchange', function (e) {
|
||||
viewTabs.addEventListener('tabchange', function (e) {
|
||||
loadTab(view, parseInt(e.detail.selectedTabIndex));
|
||||
});
|
||||
|
||||
|
@ -211,8 +211,18 @@
|
|||
document.body.classList.remove('autoScrollY');
|
||||
});
|
||||
|
||||
if (AppInfo.enableHeadRoom) {
|
||||
require(["headroom-window"], function (headroom) {
|
||||
headroom.add(viewTabs);
|
||||
self.headroom = headroom;
|
||||
});
|
||||
}
|
||||
|
||||
view.addEventListener('viewdestroy', function (e) {
|
||||
|
||||
if (self.headroom) {
|
||||
self.headroom.remove(viewTabs);
|
||||
}
|
||||
tabControllers.forEach(function (t) {
|
||||
if (t.destroy) {
|
||||
t.destroy();
|
||||
|
|
|
@ -208,15 +208,9 @@
|
|||
loadSuggestionsTab(view, params, tabContent);
|
||||
};
|
||||
|
||||
var mdlTabs = view.querySelector('.libraryViewNav');
|
||||
var viewTabs = view.querySelector('.libraryViewNav');
|
||||
|
||||
var baseUrl = 'movies.html';
|
||||
var topParentId = params.topParentId;
|
||||
if (topParentId) {
|
||||
baseUrl += '?topParentId=' + topParentId;
|
||||
}
|
||||
|
||||
libraryBrowser.configurePaperLibraryTabs(view, mdlTabs, view.querySelectorAll('.pageTabContent'), [0, 3, 4, 5]);
|
||||
libraryBrowser.configurePaperLibraryTabs(view, viewTabs, view.querySelectorAll('.pageTabContent'), [0, 3, 4, 5]);
|
||||
|
||||
var tabControllers = [];
|
||||
var renderedTabs = [];
|
||||
|
@ -290,14 +284,15 @@
|
|||
});
|
||||
}
|
||||
|
||||
mdlTabs.addEventListener('beforetabchange', function (e) {
|
||||
viewTabs.addEventListener('beforetabchange', function (e) {
|
||||
preLoadTab(view, parseInt(e.detail.selectedTabIndex));
|
||||
});
|
||||
mdlTabs.addEventListener('tabchange', function (e) {
|
||||
viewTabs.addEventListener('tabchange', function (e) {
|
||||
loadTab(view, parseInt(e.detail.selectedTabIndex));
|
||||
});
|
||||
|
||||
view.addEventListener('viewbeforeshow', function (e) {
|
||||
|
||||
if (!view.getAttribute('data-title')) {
|
||||
|
||||
var parentId = params.topParentId;
|
||||
|
@ -323,7 +318,7 @@
|
|||
if (state.NowPlayingItem && state.NowPlayingItem.MediaType == 'Video') {
|
||||
|
||||
renderedTabs = [];
|
||||
mdlTabs.triggerTabChange();
|
||||
viewTabs.triggerTabChange();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,6 +329,19 @@
|
|||
view.addEventListener('viewbeforehide', function (e) {
|
||||
Events.off(MediaController, 'playbackstop', onPlaybackStop);
|
||||
});
|
||||
|
||||
if (AppInfo.enableHeadRoom) {
|
||||
require(["headroom-window"], function (headroom) {
|
||||
headroom.add(viewTabs);
|
||||
self.headroom = headroom;
|
||||
});
|
||||
}
|
||||
|
||||
view.addEventListener('viewdestroy', function (e) {
|
||||
if (self.headroom) {
|
||||
self.headroom.remove(viewTabs);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
});
|
|
@ -349,19 +349,29 @@
|
|||
});
|
||||
}
|
||||
|
||||
var mdlTabs = view.querySelector('.libraryViewNav');
|
||||
var viewTabs = view.querySelector('.libraryViewNav');
|
||||
|
||||
libraryBrowser.configurePaperLibraryTabs(view, mdlTabs, view.querySelectorAll('.pageTabContent'), [0, 4, 5, 6]);
|
||||
libraryBrowser.configurePaperLibraryTabs(view, viewTabs, view.querySelectorAll('.pageTabContent'), [0, 4, 5, 6]);
|
||||
|
||||
mdlTabs.addEventListener('beforetabchange', function (e) {
|
||||
viewTabs.addEventListener('beforetabchange', function (e) {
|
||||
preLoadTab(view, parseInt(e.detail.selectedTabIndex));
|
||||
});
|
||||
mdlTabs.addEventListener('tabchange', function (e) {
|
||||
viewTabs.addEventListener('tabchange', function (e) {
|
||||
loadTab(view, parseInt(e.detail.selectedTabIndex));
|
||||
});
|
||||
|
||||
if (AppInfo.enableHeadRoom) {
|
||||
require(["headroom-window"], function (headroom) {
|
||||
headroom.add(viewTabs);
|
||||
self.headroom = headroom;
|
||||
});
|
||||
}
|
||||
|
||||
view.addEventListener('viewdestroy', function (e) {
|
||||
|
||||
if (self.headroom) {
|
||||
self.headroom.remove(viewTabs);
|
||||
}
|
||||
tabControllers.forEach(function (t) {
|
||||
if (t.destroy) {
|
||||
t.destroy();
|
||||
|
|
|
@ -1185,6 +1185,25 @@ var AppInfo = {};
|
|||
}
|
||||
}
|
||||
|
||||
function createWindowHeadroom() {
|
||||
// construct an instance of Headroom, passing the element
|
||||
var headroom = new Headroom([], {
|
||||
// or scroll tolerance per direction
|
||||
tolerance: {
|
||||
down: 20,
|
||||
up: 0
|
||||
},
|
||||
classes: {
|
||||
//pinned: 'appfooter--pinned',
|
||||
//unpinned: 'appfooter--unpinned',
|
||||
//initial: 'appfooter-headroom'
|
||||
}
|
||||
});
|
||||
// initialise
|
||||
headroom.init();
|
||||
return headroom;
|
||||
}
|
||||
|
||||
function initRequire() {
|
||||
|
||||
var urlArgs = "v=" + (window.dashboardVersion || new Date().getDate());
|
||||
|
@ -1491,6 +1510,8 @@ var AppInfo = {};
|
|||
return Emby.Page;
|
||||
});
|
||||
|
||||
define("headroom-window", ['headroom'], createWindowHeadroom);
|
||||
|
||||
// mock this for now. not used in this app
|
||||
define("playbackManager", [], function () {
|
||||
return {
|
||||
|
@ -1892,7 +1913,8 @@ var AppInfo = {};
|
|||
path: '/channels.html',
|
||||
dependencies: [],
|
||||
autoFocus: false,
|
||||
transition: 'fade'
|
||||
transition: 'fade',
|
||||
controller: 'scripts/channels'
|
||||
});
|
||||
|
||||
defineRoute({
|
||||
|
|
|
@ -202,34 +202,28 @@
|
|||
});
|
||||
}
|
||||
|
||||
var mdlTabs = view.querySelector('.libraryViewNav');
|
||||
var viewTabs = view.querySelector('.libraryViewNav');
|
||||
|
||||
function onPlaybackStop(e, state) {
|
||||
|
||||
if (state.NowPlayingItem && state.NowPlayingItem.MediaType == 'Video') {
|
||||
|
||||
renderedTabs = [];
|
||||
mdlTabs.triggerTabChange();
|
||||
viewTabs.triggerTabChange();
|
||||
}
|
||||
}
|
||||
|
||||
var baseUrl = 'tv.html';
|
||||
var topParentId = params.topParentId;
|
||||
if (topParentId) {
|
||||
baseUrl += '?topParentId=' + topParentId;
|
||||
}
|
||||
|
||||
if (enableScrollX()) {
|
||||
view.querySelector('#resumableItems').classList.add('hiddenScrollX');
|
||||
} else {
|
||||
view.querySelector('#resumableItems').classList.remove('hiddenScrollX');
|
||||
}
|
||||
libraryBrowser.configurePaperLibraryTabs(view, mdlTabs, view.querySelectorAll('.pageTabContent'), [0, 1, 2, 4, 5, 6]);
|
||||
libraryBrowser.configurePaperLibraryTabs(view, viewTabs, view.querySelectorAll('.pageTabContent'), [0, 1, 2, 4, 5, 6]);
|
||||
|
||||
mdlTabs.addEventListener('beforetabchange', function (e) {
|
||||
viewTabs.addEventListener('beforetabchange', function (e) {
|
||||
preLoadTab(view, parseInt(e.detail.selectedTabIndex));
|
||||
});
|
||||
mdlTabs.addEventListener('tabchange', function (e) {
|
||||
viewTabs.addEventListener('tabchange', function (e) {
|
||||
loadTab(view, parseInt(e.detail.selectedTabIndex));
|
||||
});
|
||||
|
||||
|
@ -278,8 +272,18 @@
|
|||
Events.off(ApiClient, "websocketmessage", onWebSocketMessage);
|
||||
});
|
||||
|
||||
if (AppInfo.enableHeadRoom) {
|
||||
require(["headroom-window"], function (headroom) {
|
||||
headroom.add(viewTabs);
|
||||
self.headroom = headroom;
|
||||
});
|
||||
}
|
||||
|
||||
view.addEventListener('viewdestroy', function (e) {
|
||||
|
||||
if (self.headroom) {
|
||||
self.headroom.remove(viewTabs);
|
||||
}
|
||||
tabControllers.forEach(function (t) {
|
||||
if (t.destroy) {
|
||||
t.destroy();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue