ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Пятница
29 марта
927913 Топик полностью
Сидоргек (18.06.2019 11:59, просмотров: 156) ответил Сидоргек на Мне javascript писАть противно. Но многим нравится. Тут главное не язык (очень близок к C), а стык с HTML-объектами. Много чего в разных броузерах работает по разному. Завтра буду на работе - положу в аплоад код, как я это делал.
Примерно так: Написано местами коряво, ибо, как уже писАл выше javascript нэ-на-вы-жу и старался быстрее закончить Полный текст не даю, т.к.коллеги против
<!DOCTYPE HTML PUBLIC  "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>

<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<title>Control pannel</title>
	<style>
		.my_iframe {
			position: absolute;
			border: 0;
		}

		#head {
			left: 0;
			width: 100vw;
			top: 0;
			height: 50px;
		}

		#menu {
			left: 0;
			width: 200px;
			top: 50px;
			height: calc(100vh - 50px);
		}

		#content {
			left: 200px;
			width: calc(100vw - 200px);
			top: 50px;
			height: calc(100vh - 50px);
		}
	</style>
	<script id="jquery_js"></script>
	<script id="javascript_js"></script>
</head>

<body>
	<iframe src="about:blank" name="head" class="my_iframe" id="head">
		<p>Your browser does not support iframes.</p>
	</iframe>
	<iframe src="about:blank" name="menu" class="my_iframe" id="menu"></iframe>
	<iframe src="about:blank" name="content" class="my_iframe" id="content"></iframe>

	<script type="text/javascript">
		//
		// Кешированный доступ к серверу
		// В качестве хранилища используется sessionStorage
		//

		// Очистка кеша - вызывается один раз из index.html
		function cacheInit() {
			//console.log("cache init");
			sessionStorage.clear();
		}

		// Загрузка url в объект с селектором sel из doc
		// Если в кеше ещё нет, производится загрузка в кеш и после этого перенос в объект
		// Если в процессе загрузки возникает тайм-аут, сессия прерывается и делается новый запрос
		// По завершении загрузки вызывается callback
		// Для всех типов файлов кроме .js нужен jQuery !!!
		function cacheLoad(doc, url, sel, callback) {
			doc.body.style.cursor = 'wait';

			var content = _cache_read(url);

			if (content == undefined) {
				// В кеше нет - иду на сервер
				//console.log("cache load '" + url + "' from host");
				_cache_read_host(url, function () { cacheLoad(doc, url, sel, callback); });
			}
			else {
				// В кеше есть - подключаю к объекту
				//console.log("cache read '" + url + "' from cache");

				// Действия в завилсимости от типа файла
				var ext = _cache_get_xtension(url);
				switch (ext) {
					case "htm":
						//console.log("cache inst '" + url + "' as webpage");

						// Переношу в страницу
						$(sel, doc).attr("srcdoc", content).attr("src", url);
						break;

					case "js":
						//console.log("cache inst '" + url + "' as javascript");

						// Скрипты обрабатываются до jQuery, так что ID нужен без #
						if (sel.charAt(0) == '#') {
							console.warn("cache inst '" + url + "' # not need in the selector for javascript !!!");
							sel = sel.substr(1);
						}

						// Получаю объект или создаю, если не найден
						var js = doc.getElementById(sel);
						if (js == null) {
							js = document.createElement("SCRIPT");
							js.id = sel;
						}

						// Переношу в скрипт
						js.type = "text/javascript";
						js.innerHTML = content;
						break;

					case "jpg":
						//console.log("cache inst '" + url + "' as image");

						// Переношу base-64 в картинку
						$(sel, doc).attr("src", "data:image/jpeg;base64," + content);
						break;

					case "gif":
						//console.log("cache inst '" + url + "' as image");

						// Переношу base-64 в картинку
						$(sel, doc).attr("src", "data:image/gif;base64," + content);
						break;

					case "png":
						//console.log("cache inst '" + url + "' as image");

						// Переношу base-64 в картинку
						$(sel, doc).attr("src", "data:image/png;base64," + content);
						break;

					case "css":
						//console.log("cache inst '" + url + "' as css");

						// Переношу в страницу (добавляю в элемент с типом STYLE)
						$(sel, doc).append("\n" + content);
						break;

					default:
						//console.error("cache inst '" + url + "' unknown file type '" + ext + "' !!!");
						break;
				}

				doc.body.style.cursor = 'auto';

				// Если задан callback, вызываю
				if (callback != undefined) {
					callback();
				}
			}
		}

		// Рекурсивная "групповая" загрузка и кеширование скриптов
		// doc - document, откуда вызвана функция
		// В массиве пары URL - селектор объекта, в который грузить
		// Если очередной объект == null, значит всё загружено и вместо URL - callback
		// index - индекс для рекурсивного вызова
		function cacheLoadMulti(doc, list, index) {
			// Это первый вызов ?
			if (index == undefined) {
				index = 0;
			}

			// Это последний вызов ?
			if (list[index + 1] == undefined) {
				callback = list[index];
				if (callback != undefined) {
					callback();
				}

				return;
			}

			// Гружу очередной URL
			var url = list[index];
			var obj = list[index + 1];
			cacheLoad(
				doc, url, obj,
				function () {
					cacheLoadMulti(doc, list, index + 2);
				}
			);
		}

		// Внутренняя функция - фозвращает имя файла без параметров
		function _cache_get_fname(url) {
			// Отсекаю параметры
			var fname = url.split("?");
			return fname[0];
		}

		// Внутренняя функция - выделяет расширение файла
		function _cache_get_xtension(url) {
			// Отсекаю параметры
			ext = _cache_get_fname(url);

			// Получаю расширение
			ext = ext.split(".");
			ext = ext[ext.length - 1];

			return ext;
		}

		// Внутренняя функция - читает из кеша содержимое файла
		// Если такого нет, возвращает undefined
		function _cache_read(url) {
			var fname = _cache_get_fname(url);

			var content = sessionStorage.getItem(fname);

			if ((content == undefined) || (content == null)) {
				return undefined;
			}

			var c = JSON.parse(content);
			if ((c == undefined) || (c == null)) {
				sessionStorage.removeItem(fname);
				return undefined;
			}

			if ((c.content == undefined) || (c.content == null)) {
				sessionStorage.removeItem(fname);
				return undefined;
			}

			return c.content;
		}

		// Внутренняя функция - загрузка с сервера в кеш c перезапросами по тайм-ауту
		function _cache_read_host(url, callback) {
			var xmlhttp = new XMLHttpRequest();

			var timer = undefined;
			var timer_restart = 0;

			function on_timeout() {
				//console.warn("cache load '" + url + "' timeout");
				timer = undefined;

				timer_restart = 1;
				xmlhttp.abort();

				_cache_read_host(url, callback)
			}

			xmlhttp.onreadystatechange = function () {
				if (timer_restart != 0) {
					return;
				}

				// Перезапускаю таймер
				if (timer != undefined) {
					clearTimeout(timer);
				}
				timer = setTimeout(on_timeout, 5555);

				if (xmlhttp.readyState == 4) {
					// Останавливаю тавймер
					if (timer != undefined) {
						clearTimeout(timer);
					}

					if (xmlhttp.status == 200) {
						//console.log("cache load '" + url + "' ok");

						// Тип содержимого по расширению
						var payload;
						switch (_cache_get_xtension(url)) {
							case "ico":
							case "gif":
							case "png":
							case "jpg":
								// Интерпретирую как бинарные данные и преобразую в строку base-64
								var arr = new Uint8Array(xmlhttp.response);
								var raw = String.fromCharCode.apply(null, arr);
								payload = btoa(raw);
								break;

							default:
								// Интерпретирую как строку Unicode
								payload = new TextDecoder().decode(xmlhttp.response);
								break;
						}

						// Пишу в кеш
						sessionStorage.setItem(_cache_get_fname(url), JSON.stringify({ content: payload }));

						// Если нужно - вызываю колбэк
						if (callback) callback();
					}
					else {
						//console.warn("cache load '" + url + "' error " + xmlhttp.status);

						// При ошибке выззываю сам себя ещё раз
						setTimeout(function () { _cache_read_host(url, callback); }, 111);
					}
				}
			}

			// Запускаю запрос
			xmlhttp.open("GET", url, true);
			xmlhttp.responseType = "arraybuffer";
			xmlhttp.send(null);
		}

		// Обертка для GET-запроса к cgi-bin/ajax.cgi с перезапросом по тайм-ауту
		function smartGet(obj, oncomplete, timeout) {
			if (timeout == undefined) {
				timeout = 5555;
			}

			$.ajax({
				url: "cgi-bin/ajax.cgi",
				data: obj,
				timeout: timeout,
				success: oncomplete,
				error: function () {
					//console.warn("$.get '" + JSON.stringify(obj) + "' timeout");
					setTimeout(function () { smartGet(obj, oncomplete, timeout); }, 111);
				}
			});
		}

		// ----------------------------------------------------------------------------------------

		//
		// Отсюда начинается выполнение скрипта
		// Дожидаюсь, пока загрузится страница и начинаю
		//
		window.onload = function () {
			// Очищаю кеш
			cacheInit();

			// Загружаю скрипты
			var load_instructions = [
				"js/jquery.js", "jquery_js",
				"js/javascript.js", "javascript_js",
				AfterPageReady
			];
			cacheLoadMulti(document, load_instructions);
		};

		// Вызыается после того, как все элементы страницы загрузились
		function AfterPageReady() {
			// Запрашиваю имя и версию устройства для заголовка страницы
			// Большой тайм-аут для того, что бы успеть ввести пароль
			smartGet({ device_name: "", app_version: "", snmp: "get" }, OnRqComplete, 30000);
		}
		function OnRqComplete(data) {
			// Разбираю ответ
			var obj = jQuery.parseJSON(data);

			// Жду, пока все переменные станут доступны
			if (
				(obj.device_name == undefined) ||
				(obj.app_version == undefined) ||
				(obj.snmp_on == undefined)) {
				window.setTimeout(AfterPageReady, 1234);
				return;
			}

			// Заголовок окна
			var tstr = decodeURI(obj.device_name) + " v." + (obj.app_version >> 8) + "." + (obj.app_version % 256);
			if (obj.snmp_on == 1) {
				tstr += " - " + fromUTF8(obj.snmp_syslocation);
			}
			document.title = tstr;

			// Загружаю и отображаю заголовок
			var load_instructions = [
				"header.htm", "#head",
				undefined
			];
			cacheLoadMulti(document, load_instructions);
		}

		// Вызывается со страницы заголовка после того, как она полностью загрузилась
		function OnHeaderComplete() {
			// Загружаю и отображаю меню
			var load_instructions = [
				"menu.htm", "#menu",
				undefined
			];
			cacheLoadMulti(document, load_instructions);
		}

		// Вызывается со страницы меню после того, как она полностью загрузилась
		function OnMenuComplete() {
			// Загружаю и отображаю страницу
			var load_instructions = [
				//"tun.htm?num=1", "#content",
				"inp.htm", "#content",
				undefined
			];
			cacheLoadMulti(document, load_instructions);
		}
	</script>
</body>

</html>