forked from cory/tildefriends
		
	var -> let, and standardize these calls.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3907 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
		
							
								
								
									
										207
									
								
								core/client.js
									
									
									
									
									
								
							
							
						
						
									
										207
									
								
								core/client.js
									
									
									
									
									
								
							@@ -1,19 +1,30 @@
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
var gSocket;
 | 
			
		||||
var gCredentials;
 | 
			
		||||
let gSocket;
 | 
			
		||||
let gCredentials;
 | 
			
		||||
 | 
			
		||||
var gCurrentFile;
 | 
			
		||||
var gFiles = {};
 | 
			
		||||
var gApp = {files: {}};
 | 
			
		||||
var gEditor;
 | 
			
		||||
var gSplit;
 | 
			
		||||
var gGraphs = {};
 | 
			
		||||
var gTimeSeries = {};
 | 
			
		||||
var gParentApp;
 | 
			
		||||
let gCurrentFile;
 | 
			
		||||
let gFiles = {};
 | 
			
		||||
let gApp = {files: {}};
 | 
			
		||||
let gEditor;
 | 
			
		||||
let gSplit;
 | 
			
		||||
let gGraphs = {};
 | 
			
		||||
let gTimeSeries = {};
 | 
			
		||||
let gParentApp;
 | 
			
		||||
let gOriginalInput;
 | 
			
		||||
 | 
			
		||||
var kErrorColor = "#dc322f";
 | 
			
		||||
var kStatusColor = "#fff";
 | 
			
		||||
let kErrorColor = "#dc322f";
 | 
			
		||||
let kStatusColor = "#fff";
 | 
			
		||||
 | 
			
		||||
/* Functions that server-side app code can call through app.setDocument()-style
 | 
			
		||||
 * calls. */
 | 
			
		||||
const k_api = {
 | 
			
		||||
	setDocument: {args: ['content'], func: api_setDocument},
 | 
			
		||||
	postMessage: {args: ['message'], func: api_postMessage},
 | 
			
		||||
	error: {args: ['error'], func: api_error},
 | 
			
		||||
	localStorageSet: {args: ['key', 'value'], func: api_localStorageSet},
 | 
			
		||||
	localStorageGet: {args: ['key'], func: api_localStorageGet},
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
window.addEventListener("keydown", function(event) {
 | 
			
		||||
	if (event.keyCode == 83 && (event.altKey || event.ctrlKey)) {
 | 
			
		||||
@@ -35,13 +46,13 @@ function ensureLoaded(nodes, callback) {
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var search = nodes.shift();
 | 
			
		||||
	var head = document.head;
 | 
			
		||||
	var found = false;
 | 
			
		||||
	for (var i = 0; i < head.childNodes.length; i++) {
 | 
			
		||||
	let search = nodes.shift();
 | 
			
		||||
	let head = document.head;
 | 
			
		||||
	let found = false;
 | 
			
		||||
	for (let i = 0; i < head.childNodes.length; i++) {
 | 
			
		||||
		if (head.childNodes[i].tagName == search.tagName) {
 | 
			
		||||
			var match = true;
 | 
			
		||||
			for (var attribute in search.attributes) {
 | 
			
		||||
			let match = true;
 | 
			
		||||
			for (let attribute in search.attributes) {
 | 
			
		||||
				if (head.childNodes[i].attributes[attribute].value != search.attributes[attribute]) {
 | 
			
		||||
					match = false;
 | 
			
		||||
				}
 | 
			
		||||
@@ -55,11 +66,11 @@ function ensureLoaded(nodes, callback) {
 | 
			
		||||
	if (found) {
 | 
			
		||||
		ensureLoaded(nodes, callback);
 | 
			
		||||
	} else {
 | 
			
		||||
		var node = document.createElement(search.tagName);
 | 
			
		||||
		let node = document.createElement(search.tagName);
 | 
			
		||||
		node.onreadystatechange = node.onload = function() {
 | 
			
		||||
			ensureLoaded(nodes, callback);
 | 
			
		||||
		};
 | 
			
		||||
		for (var attribute in search.attributes) {
 | 
			
		||||
		for (let attribute in search.attributes) {
 | 
			
		||||
			node.setAttribute(attribute, search.attributes[attribute]);
 | 
			
		||||
		}
 | 
			
		||||
		head.insertBefore(node, head.firstChild);
 | 
			
		||||
@@ -133,8 +144,8 @@ function trace() {
 | 
			
		||||
			}
 | 
			
		||||
			return response.arrayBuffer();
 | 
			
		||||
		}).then(function(data) {
 | 
			
		||||
			var perfetto = window.open('/perfetto/');
 | 
			
		||||
			var done = false;
 | 
			
		||||
			let perfetto = window.open('/perfetto/');
 | 
			
		||||
			let done = false;
 | 
			
		||||
			if (perfetto) {
 | 
			
		||||
				function message_handler(message) {
 | 
			
		||||
					if (message.data == 'PONG') {
 | 
			
		||||
@@ -232,8 +243,8 @@ function load(path) {
 | 
			
		||||
			});
 | 
			
		||||
		}
 | 
			
		||||
		gFiles = {};
 | 
			
		||||
		var isApp = false;
 | 
			
		||||
		var promises = [];
 | 
			
		||||
		let isApp = false;
 | 
			
		||||
		let promises = [];
 | 
			
		||||
 | 
			
		||||
		if (json && json['type'] == 'tildefriends-app') {
 | 
			
		||||
			isApp = true;
 | 
			
		||||
@@ -248,7 +259,7 @@ function load(path) {
 | 
			
		||||
		}
 | 
			
		||||
		if (!isApp) {
 | 
			
		||||
			document.getElementById("editPane").style.display = 'flex';
 | 
			
		||||
			var text = '// New script.\n';
 | 
			
		||||
			let text = '// New script.\n';
 | 
			
		||||
			gCurrentFile = 'app.js';
 | 
			
		||||
			gFiles[gCurrentFile] = {
 | 
			
		||||
				doc: new CodeMirror.Doc(text, guessMode(gCurrentFile)),
 | 
			
		||||
@@ -280,9 +291,9 @@ function save(save_to) {
 | 
			
		||||
		gFiles[gCurrentFile].doc = gEditor.getDoc();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var save_path = save_to;
 | 
			
		||||
	let save_path = save_to;
 | 
			
		||||
	if (!save_path) {
 | 
			
		||||
		var name = document.getElementById("name");
 | 
			
		||||
		let name = document.getElementById("name");
 | 
			
		||||
		if (name && name.value) {
 | 
			
		||||
			save_path = name.value;
 | 
			
		||||
		} else {
 | 
			
		||||
@@ -290,7 +301,7 @@ function save(save_to) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var promises = [];
 | 
			
		||||
	let promises = [];
 | 
			
		||||
	for (let name of Object.keys(gFiles)) {
 | 
			
		||||
		let file = gFiles[name];
 | 
			
		||||
		if (file.doc.isClean(file.generation)) {
 | 
			
		||||
@@ -318,7 +329,7 @@ function save(save_to) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return Promise.all(promises).then(function() {
 | 
			
		||||
		var app = {
 | 
			
		||||
		let app = {
 | 
			
		||||
			type: "tildefriends-app",
 | 
			
		||||
			files: Object.fromEntries(Object.keys(gFiles).map(x => [x, gFiles[x].id || gApp.files[x]])),
 | 
			
		||||
		};
 | 
			
		||||
@@ -366,9 +377,9 @@ function pushToParent() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function url() {
 | 
			
		||||
	var hash = window.location.href.indexOf('#');
 | 
			
		||||
	var question = window.location.href.indexOf('?');
 | 
			
		||||
	var end = -1;
 | 
			
		||||
	let hash = window.location.href.indexOf('#');
 | 
			
		||||
	let question = window.location.href.indexOf('?');
 | 
			
		||||
	let end = -1;
 | 
			
		||||
	if (hash != -1 && (hash < end || end == -1))
 | 
			
		||||
	{
 | 
			
		||||
		end = hash;
 | 
			
		||||
@@ -384,13 +395,42 @@ function hash() {
 | 
			
		||||
	return window.location.hash != "#" ? window.location.hash : "";
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function api_setDocument(content) {
 | 
			
		||||
	let iframe = document.getElementById("document");
 | 
			
		||||
	iframe.srcdoc = content;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function api_postMessage(message) {
 | 
			
		||||
	let iframe = document.getElementById("document");
 | 
			
		||||
	iframe.contentWindow.postMessage(message, "*");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function api_error(error) {
 | 
			
		||||
	if (error) {
 | 
			
		||||
		if (typeof(error) == 'string') {
 | 
			
		||||
			setStatusMessage('⚠️ ' + error, '#f00');
 | 
			
		||||
		} else {
 | 
			
		||||
			setStatusMessage('⚠️ ' + merror.message + '\n' + error.stack, '#f00');
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	console.log('error', error);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function api_localStorageSet(key, value) {
 | 
			
		||||
	window.localStorage.setItem('app:' + key, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function api_localStorageGet(key, value) {
 | 
			
		||||
	send({message: 'localStorage', key: key, value: window.localStorage.getItem('app:' + key)});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function receive(message) {
 | 
			
		||||
	if (message && message.action == "session") {
 | 
			
		||||
		setStatusMessage("🟢 Executing...", kStatusColor);
 | 
			
		||||
		gCredentials = message.credentials;
 | 
			
		||||
		gParentApp = message.parentApp;
 | 
			
		||||
		updateLogin();
 | 
			
		||||
		var parent_enabled = message.parentApp;
 | 
			
		||||
		let parent_enabled = message.parentApp;
 | 
			
		||||
		document.getElementById('push_to_parent').style.display = parent_enabled ? 'inline-block' : 'none';
 | 
			
		||||
		document.getElementById('pull_from_parent').style.display = parent_enabled ? 'inline-block' : 'none';
 | 
			
		||||
	} else if (message && message.action == "ready") {
 | 
			
		||||
@@ -402,32 +442,13 @@ function receive(message) {
 | 
			
		||||
			/* Stats were opened before we connected. */
 | 
			
		||||
			send({action: 'enableStats', enabled: true});
 | 
			
		||||
		}
 | 
			
		||||
	} else if (message && message.action == "setDocument") {
 | 
			
		||||
		var iframe = document.getElementById("document");
 | 
			
		||||
		iframe.srcdoc = message.content;
 | 
			
		||||
	} else if (message && message.action == "postMessage") {
 | 
			
		||||
		var iframe = document.getElementById("document");
 | 
			
		||||
		iframe.contentWindow.postMessage(message.message, "*");
 | 
			
		||||
	} else if (message && message.action == "ping") {
 | 
			
		||||
		send({action: "pong"});
 | 
			
		||||
	} else if (message && message.action == "error") {
 | 
			
		||||
		if (message.error) {
 | 
			
		||||
			if (typeof(message.error) == 'string') {
 | 
			
		||||
				setStatusMessage('⚠️ ' + message.error, '#f00');
 | 
			
		||||
			} else {
 | 
			
		||||
				setStatusMessage('⚠️ ' + mmessage.error.message + '\n' + message.error.stack, '#f00');
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		console.log('error', message);
 | 
			
		||||
	} else if (message && message.action == "localStorageSet") {
 | 
			
		||||
		window.localStorage.setItem('app:' + message.key, message.value);
 | 
			
		||||
	} else if (message && message.action == "localStorageGet") {
 | 
			
		||||
		send({message: 'localStorage', key: message.key, value: window.localStorage.getItem('app:' + message.key)});
 | 
			
		||||
	} else if (message && message.action == "print") {
 | 
			
		||||
		console.log('app>', ...message.args);
 | 
			
		||||
	} else if (message && message.action == "stats") {
 | 
			
		||||
		var now = new Date().getTime();
 | 
			
		||||
		for (var key of Object.keys(message.stats)) {
 | 
			
		||||
		let now = new Date().getTime();
 | 
			
		||||
		for (let key of Object.keys(message.stats)) {
 | 
			
		||||
			const k_groups = {
 | 
			
		||||
				rpc_in: {group: 'rpc', name: 'in'},
 | 
			
		||||
				rpc_out: {group: 'rpc', name: 'out'},
 | 
			
		||||
@@ -499,6 +520,11 @@ function receive(message) {
 | 
			
		||||
			}
 | 
			
		||||
			timeseries.append(now, message.stats[key]);
 | 
			
		||||
		}
 | 
			
		||||
	} else if (message && message.action) {
 | 
			
		||||
		let api = k_api[message.action];
 | 
			
		||||
		if (api) {
 | 
			
		||||
			api.func(...api.args.map(x => message[x]));
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -515,7 +541,7 @@ function keyEvent(event) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function setStatusMessage(message, color) {
 | 
			
		||||
	var node = document.getElementById("status");
 | 
			
		||||
	let node = document.getElementById("status");
 | 
			
		||||
	while (node.firstChild) {
 | 
			
		||||
		node.removeChild(node.firstChild);
 | 
			
		||||
	}
 | 
			
		||||
@@ -536,12 +562,12 @@ function send(value) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function updateLogin() {
 | 
			
		||||
	var login = document.getElementById("login");
 | 
			
		||||
	let login = document.getElementById("login");
 | 
			
		||||
	while (login.firstChild) {
 | 
			
		||||
		login.removeChild(login.firstChild);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var a = document.createElement("a");
 | 
			
		||||
	let a = document.createElement("a");
 | 
			
		||||
	if (gCredentials && gCredentials.session) {
 | 
			
		||||
		a.appendChild(document.createTextNode("logout " + gCredentials.session.name));
 | 
			
		||||
		a.setAttribute("href", "/login/logout?return=" + encodeURIComponent(url() + hash()));
 | 
			
		||||
@@ -552,11 +578,10 @@ function updateLogin() {
 | 
			
		||||
	login.appendChild(a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var gOriginalInput;
 | 
			
		||||
function dragHover(event) {
 | 
			
		||||
	event.stopPropagation();
 | 
			
		||||
	event.preventDefault();
 | 
			
		||||
	var input = document.getElementById("input");
 | 
			
		||||
	let input = document.getElementById("input");
 | 
			
		||||
	if (event.type == "dragover") {
 | 
			
		||||
		if (!input.classList.contains("drop")) {
 | 
			
		||||
			input.classList.add("drop");
 | 
			
		||||
@@ -570,17 +595,17 @@ function dragHover(event) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function fixImage(sourceData, maxWidth, maxHeight, callback) {
 | 
			
		||||
	var result = sourceData;
 | 
			
		||||
	var image = new Image();
 | 
			
		||||
	let result = sourceData;
 | 
			
		||||
	let image = new Image();
 | 
			
		||||
	image.crossOrigin = "anonymous";
 | 
			
		||||
	image.referrerPolicy = "no-referrer";
 | 
			
		||||
	image.onload = function() {
 | 
			
		||||
		if (image.width > maxWidth || image.height > maxHeight) {
 | 
			
		||||
			var downScale = Math.min(maxWidth / image.width, maxHeight / image.height);
 | 
			
		||||
			var canvas = document.createElement("canvas");
 | 
			
		||||
			let downScale = Math.min(maxWidth / image.width, maxHeight / image.height);
 | 
			
		||||
			let canvas = document.createElement("canvas");
 | 
			
		||||
			canvas.width = image.width * downScale;
 | 
			
		||||
			canvas.height = image.height * downScale;
 | 
			
		||||
			var context = canvas.getContext("2d");
 | 
			
		||||
			let context = canvas.getContext("2d");
 | 
			
		||||
			context.clearRect(0, 0, canvas.width, canvas.height);
 | 
			
		||||
			image.width = canvas.width;
 | 
			
		||||
			image.height = canvas.height;
 | 
			
		||||
@@ -605,13 +630,13 @@ function fileDropRead(event) {
 | 
			
		||||
function fileDrop(event) {
 | 
			
		||||
	dragHover(event);
 | 
			
		||||
 | 
			
		||||
	var done = false;
 | 
			
		||||
	let done = false;
 | 
			
		||||
	if (!done) {
 | 
			
		||||
		var files = event.target.files || event.dataTransfer.files;
 | 
			
		||||
		for (var i = 0; i < files.length; i++) {
 | 
			
		||||
			var file = files[i];
 | 
			
		||||
		let files = event.target.files || event.dataTransfer.files;
 | 
			
		||||
		for (let i = 0; i < files.length; i++) {
 | 
			
		||||
			let file = files[i];
 | 
			
		||||
			if (file.type.substring(0, "image/".length) == "image/") {
 | 
			
		||||
				var reader = new FileReader();
 | 
			
		||||
				let reader = new FileReader();
 | 
			
		||||
				reader.onloadend = fileDropRead;
 | 
			
		||||
				reader.readAsDataURL(file);
 | 
			
		||||
				done = true;
 | 
			
		||||
@@ -620,8 +645,8 @@ function fileDrop(event) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!done) {
 | 
			
		||||
		var html = event.dataTransfer.getData("text/html");
 | 
			
		||||
		var match = /<img.*src="([^"]+)"/.exec(html);
 | 
			
		||||
		let html = event.dataTransfer.getData("text/html");
 | 
			
		||||
		let match = /<img.*src="([^"]+)"/.exec(html);
 | 
			
		||||
		if (match) {
 | 
			
		||||
			sendImage(match[1]);
 | 
			
		||||
			done = true;
 | 
			
		||||
@@ -629,7 +654,7 @@ function fileDrop(event) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!done) {
 | 
			
		||||
		var text = event.dataTransfer.getData("text/plain");
 | 
			
		||||
		let text = event.dataTransfer.getData("text/plain");
 | 
			
		||||
		if (text) {
 | 
			
		||||
			send(text);
 | 
			
		||||
			done = true;
 | 
			
		||||
@@ -638,7 +663,7 @@ function fileDrop(event) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function enableDragDrop() {
 | 
			
		||||
	var body = document.body;
 | 
			
		||||
	let body = document.body;
 | 
			
		||||
	body.addEventListener("dragover", dragHover);
 | 
			
		||||
	body.addEventListener("dragleave", dragHover);
 | 
			
		||||
	body.addEventListener("drop", fileDrop);
 | 
			
		||||
@@ -664,7 +689,7 @@ function blur() {
 | 
			
		||||
 | 
			
		||||
function message(event) {
 | 
			
		||||
	if (event.data && event.data.event == "resizeMe" && event.data.width && event.data.height) {
 | 
			
		||||
		var iframe = document.getElementById("iframe_" + event.data.name);
 | 
			
		||||
		let iframe = document.getElementById("iframe_" + event.data.name);
 | 
			
		||||
		iframe.setAttribute("width", event.data.width);
 | 
			
		||||
		iframe.setAttribute("height", event.data.height);
 | 
			
		||||
	} else if (event.data && event.data.action == "setHash") {
 | 
			
		||||
@@ -682,7 +707,7 @@ function message(event) {
 | 
			
		||||
			}
 | 
			
		||||
			return response.text();
 | 
			
		||||
		}).then(function(text) {
 | 
			
		||||
			var iframe = document.getElementById("document");
 | 
			
		||||
			let iframe = document.getElementById("document");
 | 
			
		||||
			iframe.contentWindow.postMessage({'storeBlobComplete': {name: event.data.blob.name, path: text, type: event.data.blob.type, context: event.data.context}}, '*');
 | 
			
		||||
		});
 | 
			
		||||
	} else {
 | 
			
		||||
@@ -719,13 +744,7 @@ function connectSocket(path) {
 | 
			
		||||
			gSocket.send(JSON.stringify({
 | 
			
		||||
				action: "hello",
 | 
			
		||||
				path: path,
 | 
			
		||||
				api: [
 | 
			
		||||
					['setDocument', 'content'],
 | 
			
		||||
					['postMessage', 'message'],
 | 
			
		||||
					['error', 'error'],
 | 
			
		||||
					['localStorageSet', 'key', 'value'],
 | 
			
		||||
					['localStorageGet', 'key'],
 | 
			
		||||
				],
 | 
			
		||||
				api: Object.entries(k_api).map(([key, value]) => [].concat([key], value.args)),
 | 
			
		||||
			}));
 | 
			
		||||
		}
 | 
			
		||||
		gSocket.onmessage = function(event) {
 | 
			
		||||
@@ -755,8 +774,8 @@ function connectSocket(path) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function openFile(name) {
 | 
			
		||||
	var newDoc = (name && gFiles[name]) ? gFiles[name].doc : new CodeMirror.Doc("", guessMode(name));
 | 
			
		||||
	var oldDoc = gEditor.swapDoc(newDoc);
 | 
			
		||||
	let newDoc = (name && gFiles[name]) ? gFiles[name].doc : new CodeMirror.Doc("", guessMode(name));
 | 
			
		||||
	let oldDoc = gEditor.swapDoc(newDoc);
 | 
			
		||||
	if (gFiles[gCurrentFile]) {
 | 
			
		||||
		gFiles[gCurrentFile].doc = oldDoc;
 | 
			
		||||
	}
 | 
			
		||||
@@ -770,13 +789,13 @@ function onFileClicked(event) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function updateFiles() {
 | 
			
		||||
	var node = document.getElementById("files");
 | 
			
		||||
	let node = document.getElementById("files");
 | 
			
		||||
	while (node.firstChild) {
 | 
			
		||||
		node.removeChild(node.firstChild);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (var file of Object.keys(gFiles).sort()) {
 | 
			
		||||
		var li = document.createElement("li");
 | 
			
		||||
	for (let file of Object.keys(gFiles).sort()) {
 | 
			
		||||
		let li = document.createElement("li");
 | 
			
		||||
		li.onclick = onFileClicked;
 | 
			
		||||
		li.appendChild(document.createTextNode(file));
 | 
			
		||||
		if (file == gCurrentFile) {
 | 
			
		||||
@@ -800,7 +819,7 @@ function makeNewFile(name) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function newFile() {
 | 
			
		||||
	var name = prompt("Name of new file:", "file.js");
 | 
			
		||||
	let name = prompt("Name of new file:", "file.js");
 | 
			
		||||
	if (name && !gFiles[name]) {
 | 
			
		||||
		makeNewFile(name);
 | 
			
		||||
	}
 | 
			
		||||
@@ -823,18 +842,18 @@ window.addEventListener("load", function() {
 | 
			
		||||
	for (let tag of document.getElementsByTagName('a')) {
 | 
			
		||||
		if (tag.accessKey) {
 | 
			
		||||
			tag.classList.add('tooltip_parent');
 | 
			
		||||
			var tooltip = document.createElement('div');
 | 
			
		||||
			let tooltip = document.createElement('div');
 | 
			
		||||
			tooltip.classList.add('tooltip');
 | 
			
		||||
			if (tag.dataset.tip) {
 | 
			
		||||
				var description = document.createElement('div');
 | 
			
		||||
				let description = document.createElement('div');
 | 
			
		||||
				description.innerText = tag.dataset.tip;
 | 
			
		||||
				tooltip.appendChild(description);
 | 
			
		||||
			}
 | 
			
		||||
			var parts = tag.accessKeyLabel ? tag.accessKeyLabel.split('+') : [];
 | 
			
		||||
			for (var i = 0; i < parts.length; i++)
 | 
			
		||||
			let parts = tag.accessKeyLabel ? tag.accessKeyLabel.split('+') : [];
 | 
			
		||||
			for (let i = 0; i < parts.length; i++)
 | 
			
		||||
			{
 | 
			
		||||
				var key = parts[i];
 | 
			
		||||
				var kbd = document.createElement('kbd');
 | 
			
		||||
				let key = parts[i];
 | 
			
		||||
				let kbd = document.createElement('kbd');
 | 
			
		||||
				kbd.innerText = key;
 | 
			
		||||
				tooltip.appendChild(kbd);
 | 
			
		||||
				if (i < parts.length - 1) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user