Implement new themes; fixes
This commit is contained in:
parent
ac89c87e29
commit
d410b4663d
18 changed files with 15789 additions and 1552 deletions
|
|
@ -66,8 +66,8 @@ $("#usercount").mouseenter(function (ev) {
|
|||
// re-using profile-box class for convenience
|
||||
var popup = $("<div/>")
|
||||
.addClass("profile-box")
|
||||
.css("top", (ev.pageY + 5) + "px")
|
||||
.css("left", (ev.pageX) + "px")
|
||||
.css("top", (ev.clientY + 5) + "px")
|
||||
.css("left", (ev.clientX) + "px")
|
||||
.appendTo($("#usercount"));
|
||||
|
||||
var contents = "";
|
||||
|
|
@ -84,8 +84,8 @@ $("#usercount").mousemove(function (ev) {
|
|||
if(popup.length == 0)
|
||||
return;
|
||||
|
||||
popup.css("top", (ev.pageY + 5) + "px");
|
||||
popup.css("left", (ev.pageX) + "px");
|
||||
popup.css("top", (ev.clientY + 5) + "px");
|
||||
popup.css("left", (ev.clientX) + "px");
|
||||
});
|
||||
|
||||
$("#usercount").mouseleave(function () {
|
||||
|
|
|
|||
|
|
@ -603,6 +603,7 @@ function showUserOptions() {
|
|||
|
||||
function saveUserOptions() {
|
||||
USEROPTS.theme = $("#us-theme").val();
|
||||
createCookie("cytube-theme", USEROPTS.theme, 1000);
|
||||
USEROPTS.layout = $("#us-layout").val();
|
||||
USEROPTS.ignore_channelcss = $("#us-no-channelcss").prop("checked");
|
||||
USEROPTS.ignore_channeljs = $("#us-no-channeljs").prop("checked");
|
||||
|
|
@ -629,6 +630,7 @@ function saveUserOptions() {
|
|||
}
|
||||
|
||||
storeOpts();
|
||||
applyOpts();
|
||||
}
|
||||
|
||||
function storeOpts() {
|
||||
|
|
@ -638,13 +640,16 @@ function storeOpts() {
|
|||
}
|
||||
|
||||
function applyOpts() {
|
||||
$("#usertheme").remove();
|
||||
if(USEROPTS.theme != "default") {
|
||||
$("<link/>").attr("rel", "stylesheet")
|
||||
.attr("type", "text/css")
|
||||
.attr("id", "usertheme")
|
||||
.attr("href", USEROPTS.theme)
|
||||
.appendTo($("head"));
|
||||
if ($("#usertheme").attr("href") !== USEROPTS.theme) {
|
||||
$("#usertheme").remove();
|
||||
if(USEROPTS.theme != "default") {
|
||||
$("<link/>").attr("rel", "stylesheet")
|
||||
.attr("type", "text/css")
|
||||
.attr("id", "usertheme")
|
||||
.attr("href", USEROPTS.theme)
|
||||
.appendTo($("head"));
|
||||
}
|
||||
fixWeirdButtonAlignmentIssue();
|
||||
}
|
||||
|
||||
switch (USEROPTS.layout) {
|
||||
|
|
@ -905,13 +910,7 @@ function handlePermissionChange() {
|
|||
setVisible("#clearplaylist", hasPermission("playlistclear"));
|
||||
setVisible("#shuffleplaylist", hasPermission("playlistshuffle"));
|
||||
|
||||
// Weird things happen to the alignment in chromium when I toggle visibility
|
||||
// of the above buttons
|
||||
// This fixes it?
|
||||
var wtf = $("#rightcontrols .pull-right").removeClass("pull-right")
|
||||
setTimeout(function () {
|
||||
wtf.addClass("pull-right");
|
||||
}, 1);
|
||||
fixWeirdButtonAlignmentIssue();
|
||||
|
||||
setVisible("#newpollbtn", hasPermission("pollctl"));
|
||||
$("#voteskip").attr("disabled", !hasPermission("voteskip") ||
|
||||
|
|
@ -942,6 +941,16 @@ function handlePermissionChange() {
|
|||
rebuildPlaylist();
|
||||
}
|
||||
|
||||
function fixWeirdButtonAlignmentIssue() {
|
||||
// Weird things happen to the alignment in chromium when I toggle visibility
|
||||
// of the above buttons
|
||||
// This fixes it?
|
||||
var wtf = $("#videocontrols").removeClass("pull-right");
|
||||
setTimeout(function () {
|
||||
wtf.addClass("pull-right");
|
||||
}, 1);
|
||||
}
|
||||
|
||||
/* search stuff */
|
||||
|
||||
function clearSearchResults() {
|
||||
|
|
@ -1417,7 +1426,7 @@ function hdLayout() {
|
|||
.prependTo($("#rightpane-inner"));
|
||||
|
||||
$("#plcontrol").detach().appendTo(plcontrolwrap);
|
||||
$("#rightcontrols .btn-group.pull-right").detach()
|
||||
$("#videocontrols").detach()
|
||||
.appendTo(plcontrolwrap);
|
||||
|
||||
$("#controlswrap").remove();
|
||||
|
|
@ -1669,8 +1678,10 @@ function errDialog(err) {
|
|||
var cp = $("#chatwrap").offset();
|
||||
var x = cp.left + cw/2 - div.width()/2;
|
||||
var y = cp.top + ch/2 - div.height()/2;
|
||||
div.css("left", x + "px");
|
||||
div.css("top", y + "px");
|
||||
div.css("left", x + "px")
|
||||
.css("top", y + "px")
|
||||
.css("position", "absolute");
|
||||
return div;
|
||||
}
|
||||
|
||||
function queueMessage(data, type) {
|
||||
|
|
|
|||
|
|
@ -1,145 +0,0 @@
|
|||
body {
|
||||
background-color: #222222;
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
#ytapiplayer {
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
#userlist, #messagebuffer {
|
||||
background-color: #ffffff;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.drink {
|
||||
border-color: #0000cc;
|
||||
}
|
||||
|
||||
.queue_entry {
|
||||
background-color: #000000;
|
||||
border-color: #aaaaaa;
|
||||
}
|
||||
|
||||
.queue_entry > a {
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
.queue_active {
|
||||
background-color: #666666;
|
||||
}
|
||||
|
||||
.profile-box {
|
||||
background-color: #111111;
|
||||
}
|
||||
|
||||
.user-dropdown {
|
||||
background-color: #111111;
|
||||
}
|
||||
|
||||
.dropdown-menu, .dropdown-menu > li > a {
|
||||
color: #cccccc;
|
||||
background-color: #222222;
|
||||
}
|
||||
|
||||
.dropdown-menu > li > a:hover, .dropdown-menu > li > a:active,
|
||||
.dropdown-menu > li > a:focus {
|
||||
color: #cccccc;
|
||||
background-color: #444444;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
background-color: #000000;
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
.btn, .btn:hover, .btn:active, .btn.active {
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
.btn-default {
|
||||
background-color: #000000;
|
||||
border-color: #555555;
|
||||
}
|
||||
|
||||
.btn-default:hover, .btn-default:focus, .btn-default:active, .btn-default.active {
|
||||
background-color: #222222;
|
||||
border-color: #555555;
|
||||
}
|
||||
|
||||
.btn-success {
|
||||
background-color: #006600;
|
||||
border-color: #009900;
|
||||
}
|
||||
|
||||
.btn-success:hover, .btn-success:focus, .btn-success:active, .btn-success.active {
|
||||
background-color: #008800;
|
||||
border-color: #009900;
|
||||
}
|
||||
|
||||
.btn-danger {
|
||||
background-color: #660000;
|
||||
border-color: #990000;
|
||||
}
|
||||
|
||||
.btn-danger:hover, .btn-danger:focus, .btn-danger:active, .btn-danger.active {
|
||||
background-color: #880000;
|
||||
border-color: #990000;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
border-color: #0000cc;
|
||||
background-color: #000066;
|
||||
}
|
||||
|
||||
.btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active {
|
||||
border-color: #0000cc;
|
||||
background-color: #000088;
|
||||
}
|
||||
|
||||
.btn-info {
|
||||
border-color: #0000cc;
|
||||
background-color: #000066;
|
||||
}
|
||||
|
||||
.btn-info:hover, .btn-info:focus, .btn-info:active, .btn-info.active {
|
||||
border-color: #0000cc;
|
||||
background-color: #000088;
|
||||
}
|
||||
|
||||
.well {
|
||||
background-color: #222222;
|
||||
border: 1px solid #555555;
|
||||
}
|
||||
|
||||
footer {
|
||||
background-color: #222222!important;
|
||||
}
|
||||
|
||||
.modal-content {
|
||||
background-color: #222222;
|
||||
}
|
||||
|
||||
.modal-footer {
|
||||
border-top-color: #aaaaaa;
|
||||
}
|
||||
|
||||
.nav .open > li > a {
|
||||
color: #cccccc;
|
||||
background-color: #222222;
|
||||
}
|
||||
|
||||
.nav > li > a {
|
||||
color: #cccccc;
|
||||
border-color: #aaaaaa;
|
||||
}
|
||||
|
||||
.nav > li:hover > a {
|
||||
background-color: #444444;
|
||||
color: #cccccc;
|
||||
}
|
||||
|
||||
.nav > li.active > a, .nav > li.active > a:hover, .nav > li.active > a:focus {
|
||||
background-color: #222222;
|
||||
color: #cccccc;
|
||||
}
|
||||
7720
www/css/themes/cyborg.css
Normal file
7720
www/css/themes/cyborg.css
Normal file
File diff suppressed because it is too large
Load diff
8007
www/css/themes/slate.css
Normal file
8007
www/css/themes/slate.css
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,39 +0,0 @@
|
|||
var Callbacks = {
|
||||
/* Connection failed */
|
||||
error: function (reason) {
|
||||
if (reason && reason.returnValue === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
var fail = $('<div/>').addClass('alert alert-error')
|
||||
.appendTo($('#announcements'));
|
||||
|
||||
$('<h3/>').text('Uh-oh!').appendTo(fail);
|
||||
$('<p/>').html('The socket.io connection failed. Please check that '+
|
||||
'the connection was not blocked by a firewall or '+
|
||||
'antivirus software.');
|
||||
},
|
||||
|
||||
/* Connection succeeded */
|
||||
connect: function () {
|
||||
socket.emit('join', {
|
||||
channel: CHANNEL
|
||||
});
|
||||
|
||||
/* if rejoining after the connection failed, resend password */
|
||||
if (CHANNEL.opts.password) {
|
||||
socket.once('needPassword', function () {
|
||||
socket.emit('channelPassword', {
|
||||
password: CHANNEL.opts.password
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* guest login */
|
||||
if (NAME && !LOGGEDIN) {
|
||||
socket.emit('login', {
|
||||
name: NAME
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
@ -1,184 +0,0 @@
|
|||
|
||||
function addVideo(data, position) {
|
||||
var item = $('<li/>');
|
||||
item.data('id', data.id);
|
||||
item.data('temp', data.temp);
|
||||
var btnstrip = $('<div/>').addClass('btn-group video-buttons')
|
||||
.appendTo(item);
|
||||
var title = $('<a/>', {
|
||||
href: videoLink(data.id),
|
||||
target: '_blank',
|
||||
class: 'video-title'
|
||||
}).text(data.title).appendTo(item);
|
||||
var duration = $('<span/>').addClass('video-time')
|
||||
.text(formatTime(data.duration))
|
||||
.appendTo(item);
|
||||
|
||||
if (position === 'first') {
|
||||
item.prependTo($('#playlist'));
|
||||
} else if (position === 'last') {
|
||||
item.appendTo($('#playlist'));
|
||||
} else {
|
||||
var prev = findVideo(position);
|
||||
if (prev.length > 0) {
|
||||
item.insertAfter(prev);
|
||||
}
|
||||
}
|
||||
addVideoButtons(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
function addVideoButtons(li) {
|
||||
var btns = li.find('.video-buttons');
|
||||
if (btns.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (can('playlistjump')) {
|
||||
$('<button/>').addClass('btn btn-xs btn-default')
|
||||
.html('<span class="glyphicon glyphicon-play"></span>')
|
||||
.click(function () {
|
||||
SOCKET.emit('playVideo', {
|
||||
id: li.data('id')
|
||||
});
|
||||
})
|
||||
.appendTo(btns);
|
||||
}
|
||||
|
||||
if (can('playlistmove')) {
|
||||
$('<button/>').addClass('btn btn-xs btn-default')
|
||||
.html('<span class="glyphicon glyphicon-share-alt"></span>')
|
||||
.click(function () {
|
||||
SOCKET.emit('moveVideo', {
|
||||
id: li.data('id'),
|
||||
after: CURRENT.id
|
||||
});
|
||||
})
|
||||
.appendTo(btns);
|
||||
}
|
||||
|
||||
if (can('playlistsettemp')) {
|
||||
$('<button/>').addClass('btn btn-xs btn-default')
|
||||
.html('<span class="glyphicon glyphicon-flag"></span>')
|
||||
.click(function () {
|
||||
SOCKET.emit('setTemp', {
|
||||
id: li.data('id'),
|
||||
temp: !li.data('temp')
|
||||
});
|
||||
})
|
||||
.appendTo(btns);
|
||||
}
|
||||
|
||||
if (can('playlistsettemp')) {
|
||||
$('<button/>').addClass('btn btn-xs btn-default')
|
||||
.html('<span class="glyphicon glyphicon-trash"></span>')
|
||||
.click(function () {
|
||||
SOCKET.emit('deleteVideo', {
|
||||
id: li.data('id'),
|
||||
temp: !li.data('temp')
|
||||
});
|
||||
})
|
||||
.appendTo(btns);
|
||||
}
|
||||
}
|
||||
|
||||
function videoLink(data) {
|
||||
data = data.split(':');
|
||||
var type = data[0];
|
||||
var id = data[1];
|
||||
if (type === void 0 || id === void 0) {
|
||||
return '#';
|
||||
}
|
||||
|
||||
switch(type) {
|
||||
case 'yt':
|
||||
return 'http://youtu.be/' + id;
|
||||
default:
|
||||
return '#';
|
||||
}
|
||||
}
|
||||
|
||||
function formatTime(seconds) {
|
||||
var h = parseInt(seconds / 3600);
|
||||
var m = parseInt((seconds % 3600) / 60);
|
||||
var s = seconds % 60;
|
||||
|
||||
var time = '';
|
||||
if (h !== 0) {
|
||||
h = '' + h;
|
||||
if (h.length < 2) {
|
||||
h = '0' + h;
|
||||
}
|
||||
time += h + ':';
|
||||
}
|
||||
|
||||
m = '' + m;
|
||||
if (m.length < 2) {
|
||||
m = '0' + m;
|
||||
}
|
||||
time += m + ':';
|
||||
|
||||
s = '' + s;
|
||||
if (s.lengts < 2) {
|
||||
s = '0' + s;
|
||||
}
|
||||
time += s;
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
function addChatMessage(data, buffer) {
|
||||
var last = buffer.data('lastmessagename');
|
||||
var div = $('<div/>').addClass('chatmsg')
|
||||
.addClass('chatmsg-' + data.name);
|
||||
var timestamp = $('<span/>').addClass('chat-timestamp').appendTo(div)
|
||||
.text('[' + new Date(data.time).toTimeString().split(' ')[0] + '] ');
|
||||
var username = $('<span/>').addClass('chat-name').appendTo(div);
|
||||
var message = $('<span/>').appendTo(div).text(data.message);
|
||||
if (data.msgclass === 'action') {
|
||||
username.text(data.name + ' ');
|
||||
} else {
|
||||
username.text(data.name + ': ');
|
||||
}
|
||||
switch(data.msgclass) {
|
||||
case 'action':
|
||||
timestamp.addClass('action');
|
||||
username.addClass('action');
|
||||
message.addClass('action');
|
||||
break;
|
||||
case 'spoiler':
|
||||
message.addClass('spoiler');
|
||||
break;
|
||||
case 'greentext':
|
||||
message.addClass('greentext');
|
||||
break;
|
||||
case 'shout':
|
||||
timestamp.addClass('shout');
|
||||
username.addClass('shout');
|
||||
message.addClass('shout');
|
||||
break;
|
||||
case 'drink':
|
||||
div.addClass('drink');
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!data.msgclass.match(/action|shout|drink/) &&
|
||||
data.name === last) {
|
||||
if (!data.message.match(/^\s*<strong>.+?\s*:/)) {
|
||||
username.remove();
|
||||
}
|
||||
}
|
||||
buffer.data('lastmessagename', data.name);
|
||||
|
||||
if (data.flair) {
|
||||
username.addClass(data.flair);
|
||||
}
|
||||
|
||||
div.appendTo(buffer);
|
||||
}
|
||||
|
||||
function can(what) {
|
||||
return true;
|
||||
}
|
||||
152
www/js/init.js
152
www/js/init.js
|
|
@ -1,152 +0,0 @@
|
|||
/* Local client data */
|
||||
var RANK = -1;
|
||||
var LEADER = false;
|
||||
var LEADTIMER = false;
|
||||
var PL_DRAGFROM = false;
|
||||
var PL_DRAGTO = false;
|
||||
var PL_CURRENT
|
||||
var NAME = false;
|
||||
var LOGGEDIN = false;
|
||||
var SUPERADMIN = false;
|
||||
/* Channel data */
|
||||
var CHANNEL = {
|
||||
opts: {},
|
||||
openqueue: false,
|
||||
perms: {},
|
||||
css: '',
|
||||
js: '',
|
||||
motd: '',
|
||||
motd_text: '',
|
||||
name: false,
|
||||
usercount: 0
|
||||
};
|
||||
|
||||
/* Video player data */
|
||||
var PLAYER = false;
|
||||
|
||||
/* Chat data */
|
||||
var IGNORED = [];
|
||||
var CHATHIST = [];
|
||||
var CHATTHROTTLE = false;
|
||||
var SCROLLCHAT = true;
|
||||
var LASTCHATNAME = false;
|
||||
var LASTCHATTIME = 0;
|
||||
var CHATSOUND = new Audio('/sounds/boop.wav');
|
||||
|
||||
/* Page data */
|
||||
var FOCUSED = true;
|
||||
var PAGETITLE = 'CyTube';
|
||||
var TITLE_BLINK = false;
|
||||
|
||||
/* Playlist data */
|
||||
var PLAYLIST = {
|
||||
from: false,
|
||||
to: false,
|
||||
current: false,
|
||||
waitScroll: false
|
||||
};
|
||||
|
||||
/* Check if localStorage is available */
|
||||
var NOSTORAGE = typeof localStorage === 'undefined' || localStorage === null;
|
||||
|
||||
/**
|
||||
* Retrieve an option from localStorage, or from a cookie
|
||||
* if localStorage is not available
|
||||
*/
|
||||
function getOpt(k) {
|
||||
return NOSTORAGE ? readCookie(k) : localStorage.getItem(k);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save an option to localStorage, or to a cookie
|
||||
* if localStorage is not available
|
||||
*/
|
||||
function setOpt(k, v) {
|
||||
if (NOSTORAGE) {
|
||||
setCookie(k, v, 1000)
|
||||
} else {
|
||||
localStorage.setItem(k, v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a stored value, or return the default if the stored value
|
||||
* is null. Also handles parsing of values stored as strings.
|
||||
*/
|
||||
function getOrDefault(k, def) {
|
||||
var v = getOpt(k);
|
||||
if (v == null) {
|
||||
return def;
|
||||
} else if (v === 'true') {
|
||||
return true;
|
||||
} else if (v === 'false') {
|
||||
return false;
|
||||
} else if (v.match(/^\d+$/)) {
|
||||
return parseInt(v);
|
||||
} else if (v.match(/^[\d\.]+$/)) {
|
||||
return parseFloat(v);
|
||||
} else {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
/* User options */
|
||||
var USEROPTS = {
|
||||
theme : getOrDefault("theme", "default"),
|
||||
css : getOrDefault("css", ""),
|
||||
layout : getOrDefault("layout", "default"),
|
||||
synch : getOrDefault("synch", true),
|
||||
hidevid : getOrDefault("hidevid", false),
|
||||
show_timestamps : getOrDefault("show_timestamps", true),
|
||||
modhat : getOrDefault("modhat", false),
|
||||
blink_title : getOrDefault("blink_title", false),
|
||||
sync_accuracy : getOrDefault("sync_accuracy", 2),
|
||||
wmode_transparent : getOrDefault("wmode_transparent", true),
|
||||
chatbtn : getOrDefault("chatbtn", false),
|
||||
altsocket : getOrDefault("altsocket", false),
|
||||
joinmessage : getOrDefault("joinmessage", true),
|
||||
qbtn_hide : getOrDefault("qbtn_hide", false),
|
||||
qbtn_idontlikechange : getOrDefault("qbtn_idontlikechange", false),
|
||||
first_visit : getOrDefault("first_visit", true),
|
||||
ignore_channelcss : getOrDefault("ignore_channelcss", false),
|
||||
ignore_channeljs : getOrDefault("ignore_channeljs", false),
|
||||
sort_rank : getOrDefault("sort_rank", false),
|
||||
sort_afk : getOrDefault("sort_afk", false),
|
||||
default_quality : getOrDefault("default_quality", "#quality_auto"),
|
||||
boop : getOrDefault("boop", false),
|
||||
secure_connection : getOrDefault("secure_connection", false)
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a cookie with the provided name, value, and expiration time
|
||||
*/
|
||||
function setCookie(name,value,days) {
|
||||
if (days) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime()+(days*24*60*60*1000));
|
||||
var expires = "; expires="+date.toGMTString();
|
||||
}
|
||||
else var expires = "";
|
||||
document.cookie = name+"="+value+expires+"; path=/";
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a cookie with the provided name
|
||||
*/
|
||||
function readCookie(name) {
|
||||
var nameEQ = name + "=";
|
||||
var ca = document.cookie.split(";");
|
||||
for(var i=0;i < ca.length;i++) {
|
||||
var c = ca[i];
|
||||
while (c.charAt(0)==" ") c = c.substring(1,c.length);
|
||||
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Erase a cookie
|
||||
*/
|
||||
function eraseCookie(name) {
|
||||
createCookie(name,"",-1);
|
||||
}
|
||||
23
www/js/theme.js
Normal file
23
www/js/theme.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
(function () {
|
||||
var c = document.cookie.split(";").map(function (s) {
|
||||
return s.trim();
|
||||
});
|
||||
|
||||
var theme = "default";
|
||||
for (var i = 0; i < c.length; i++) {
|
||||
if (c[i].indexOf("cytube-theme=") === 0) {
|
||||
theme = c[i].split("=")[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (theme !== "default") {
|
||||
var cur = document.getElementById("usertheme");
|
||||
cur.parentNode.removeChild(cur);
|
||||
var css = document.createElement("link");
|
||||
css.setAttribute("rel", "stylesheet");
|
||||
css.setAttribute("type", "text/css");
|
||||
css.setAttribute("href", theme);
|
||||
document.head.appendChild(css);
|
||||
}
|
||||
})();
|
||||
Loading…
Add table
Add a link
Reference in a new issue