Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 14.07.2017, 12:21
Интересующийся
Отправить личное сообщение для zapalych Посмотреть профиль Найти все сообщения от zapalych
 
Регистрация: 30.06.2017
Сообщений: 11

Переключатель оформления на примитивном javascript
Здравствуйте, помогите, пожалуйста, разобраться с проблемой.

Пишу скрипт для переключения оформления сайта. Принципиальная схема такая:
Есть кнопка, при нажатии которой добавляются классы в body, и изымается дефолтный.
При необходимости посетитель может понажимать дополнительно появившиейся кнопки для изменения размера шрифта, и цветового оформления.

Написанный ранее скрипт работает на всех браузерах, кроме злополучного IE8 и ранее, поскольку использованы были такие свойства как classlist, например.

Пробовал внедрить разные библиотеки, polyfill, но единственное к чему это привело, так это к тому, что сайт стал жутко долго грузиться. В связи с этим, решил что лучше всего будет переписать скрипт, используя более примитивный синтаксис, но пробелы в знаниях не позволяют реализовать задумку.

На мой взгляд, основная проблема состоит в том, что я записываю в localstorage три разных типа (с логической точки зрения) классов, которые должны менять разные свойства отображения, обращаясь в CSS-файл, и тут возникает конфликт.

Сделал вывод localstorage в консоль и постоянно наблюдаю одну и ту же картину: один и тот же класс записан в несколько раз.

Разными путями пытался решить проблему и уже запутался, так что, вполне допускаю, что на данный момент в коде присутствуют повторения или лишние команды. Итак, вот так выглядит код на данный момент:

function hasClass(el, className) {
  if (el.classList)
    return el.classList.contains(className)
  else
    return !!el.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'))
}

function addClass(el, className) {
  if (el.classList)
    el.classList.add(className)
  else if (!hasClass(el, className)) el.className += " " + className
}

function removeClass(el, className) {
  if (el.classList)
    el.classList.remove(className)
  else if (hasClass(el, className)) {
    var reg = new RegExp('(\\s|^)' + className + '(\\s|$)')
    el.className=el.className.replace(reg, ' ')
  }
}

function addstyle(className){
var bodyver = document.getElementsByTagName("body")[0];
addClass(bodyver, className);
localStorage.setItem("statever", className);
}
function addcolor(className){
var bodycol = document.getElementsByTagName("body")[0];
addClass(bodycol, className);
localStorage.setItem("statecol", className);
}
function addsize(className){
var bodysize = document.getElementsByTagName("body")[0];
addClass(bodysize, className);
localStorage.setItem("statesize", className);
}
function clearstyle(className){
var bodyclear = document.getElementsByTagName("body")[0];
removeClass(bodyclear, className);
localStorage.removeItem("className");
}



<button onclick="addstyle('style-c'); addstyle('style-a'); addstyle('style-blackfont-whitebgr'); clearstyle('style-norm');" class="style-c" id="click-style-c" style="font-size:18px; background:none; border:none;">Кнопка вызова дополнительной панели</button>

<!--При клике появляется вот это !-->
<p style="font-size:30px; text-align:center;">Размер:<button onclick="addsize('style-a'); clearstyle('style-aa'); clearstyle('style-aaa');" class="style-a" style="font-size:30px; background:none; border:none;">А</button>
					<button onclick="addsize('style-aa'); clearstyle('style-a'); clearstyle('style-aaa');" class="style-aa" style="font-size:40px; background:none; border:none;">А</button>
					<button onclick="addsize('style-aaa'); clearstyle('style-a'); clearstyle('style-aa');" class="style-aaa" style="font-size:50px; background:none; border:none;">А</button>
					Цвет:<button onclick="addcolor('style-blackfont-whitebgr'); clearstyle('style-whitefont-greenbgr'); clearstyle('style-whitefont-blackbgr');" class="style-blackfont-whitebgr" style="font-size:50px; color:black; background:white; border:black;">А</button>
					<button onclick="clearstyle('style-blackfont-whitebgr'); addcolor('style-whitefont-greenbgr'); clearstyle('style-whitefont-blackbgr');" class="style-whitefont-greenbgr" style="font-size:50px; color:white; background:green; border:black;">А</button>
					<button onclick="clearstyle('style-blackfont-whitebgr'); clearstyle('style-whitefont-greenbgr'); addcolor('style-whitefont-blackbgr');" class="style-whitefont-blackbgr" style="font-size:50px; color:white; background:black; border:black;">А</button>
					<button onclick="addstyle('style-norm'); clearstyle('style-c'); clearstyle('style-a'); clearstyle('style-aa'); clearstyle('style-aaa'); clearstyle('style-blackfont-whitebgr'); clearstyle('style-whitefont-greenbgr'); clearstyle('style-whitefont-blackbgr');" class="style-norm" style="font-size:30px; background:none; border:none;">Обычная версия</button></p>


var statever = localStorage.getItem("statever");
			addstyle(!!statever ? statever : "style-norm");
			var statecol = localStorage.getItem("statecol");
			addcolor(!!statecol ? statecol : "style-norm");
			var statesize = localStorage.getItem("statesize");
			addsize(!!statesize ? statesize : "style-norm");

console.log(statever);
console.log(statecol);
console.log(statesize);

			var bodyclassstylec = localStorage.getItem("statever");
			if (bodyclassstylec.className = 'style-c'){
				localStorage.getItem("statever");
				localStorage.getItem("statecol");
				localStorage.getItem("statesize");
				removeClass(bodyclassstylec, 'style-norm');
				localStorage.removeItem('style-norm');
				}

			var bodyclassstylenorm = localStorage.getItem("statever");
			if (bodyclassstylenorm.className != 'style-c'){
				addClass(typeofbody, 'style-norm');
				removeClass(bodyclassstylenorm, 'style-c');
				removeClass(bodyclassstylenorm, 'style-a');
				removeClass(bodyclassstylenorm, 'style-aa');
				removeClass(bodyclassstylenorm, 'style-aaa');
				removeClass(bodyclassstylenorm, 'style-blackfont-whitebgr');
				removeClass(bodyclassstylenorm, 'style-whitefont-greenbgr');
				removeClass(bodyclassstylenorm, 'style-whitefont-blackbgr');
				localStorage.removeItem('style-c');
				localStorage.removeItem('style-a');
				localStorage.removeItem('style-aa');
				localStorage.removeItem('style-aaa');
				localStorage.removeItem('style-blackfont-whitebgr');
				localStorage.removeItem('style-whitefont-greenbgr');
				localStorage.removeItem('style-whitefont-blackbgr');
				}

			var bodyclassstylea = localStorage.getItem("statesize");
			if (bodyclassstylea.className = "style-a"){
				addClass(bodyclassstylea, 'style-c');
				removeClass(bodyclassstylea, 'style-aa');
				removeClass(bodyclassstylea, 'style-aaa');
				localStorage.removeItem('style-aa');
				localStorage.removeItem('style-aaa');
				}

			var bodyclassstyleaa = localStorage.getItem("statesize");
			if (bodyclassstyleaa.className = "style-aa"){
				addClass(bodyclassstyleaa, 'style-c');
				removeClass(bodyclassstyleaa, 'style-a');
				removeClass(bodyclassstyleaa, 'style-aaa');
				localStorage.removeItem('style-a');
				localStorage.removeItem('style-aaa');
				}

			var bodyclassstyleaaa = localStorage.getItem("statesize");
			if (bodyclassstyleaaa.className = "style-aaa"){
				addClass(bodyclassstyleaaa, 'style-c');
				removeClass(bodyclassstyleaaa, 'style-a');
				removeClass(bodyclassstyleaaa, 'style-aa');
				localStorage.removeItem('style-a');
				localStorage.removeItem('style-aa');
				}

			var bodyclassstylebw = localStorage.getItem("statecol");
			if (bodyclassstylebw.className = "style-blackfont-whitebgr"){
				addClass(bodyclassstylebw, 'style-c');
				removeClass(bodyclassstylebw, 'style-whitefont-greenbgr');
				removeClass(bodyclassstylebw, 'style-whitefont-blackbgr');
				localStorage.removeItem('style-whitefont-greenbgr');
				localStorage.removeItem('style-whitefont-blackbgr');
				}

			var bodyclassstylewg = localStorage.getItem("statecol");
			if (bodyclassstylewg.className = "style-whitefont-greenbgr"){
				addClass(bodyclassstylewg, 'style-c');
				removeClass(bodyclassstylewg, 'style-blackfont-whitebgr');
				removeClass(bodyclassstylewg, 'style-whitefont-blackbgr');
				localStorage.removeItem('style-blackfont-whitebgr');
				localStorage.removeItem('style-whitefont-blackbgr');
				}

			var bodyclassstylewb = localStorage.getItem("statecol");
			if (bodyclassstylewb.className = "style-whitefont-blackbgr"){
				addClass(bodyclassstylewb, 'style-c');
				removeClass(bodyclassstylewb, 'style-blackfont-whitebgr');
				removeClass(bodyclassstylewb, 'style-whitefont-greenbgr');
				localStorage.removeItem('style-blackfont-whitebgr');
				localStorage.removeItem('style-whitefont-greenbgr');
				};


Само по себе переключение в рамках одной страницы работает так как нужно, но если обновить страницу или перейти на соседнюю, то и в localstorage остается бардак, и как следствие в классах body постоянно находятся противоречащие необходимому результату классы.

логика конечного результата по классам такова:
Если нужна обычная версия, то должен сохраняться класс style-norm.
Если же нужно убрать лишнее оформление, то style-norm исключается, и ему на смену приходит style-c. При Нажатии кнопки вызова доп.панели прописываются так же style-a и style-blackfont-whitebgr.
Далее размер шрифтов регулируется классами style-a, style-aa, style-aaa (они друг друга исключают, а так же одновременно с ними не должен существовать класс style-norm, и обязательно должен быть style-c).
Цвет шрифтов регулируется классами style-blackfont-whitebgr, style-whitefont-blackbgr, style-whitefont-greenbgr (они друг друга исключают, а так же одновременно с ними не должен существовать класс style-norm, и обязательно должен быть style-c).

Простите, за огромное количества текста, я никого не держу за идиота - просто я то свою логику понимаю, а вот из кода (тем более, что раз уж он не работает так, как мне необходимо) может быть не всё очевидно.

Последний раз редактировалось zapalych, 14.07.2017 в 13:15. Причина: дополнение кода
Ответить с цитированием
  #2 (permalink)  
Старый 14.07.2017, 12:58
Интересующийся
Отправить личное сообщение для fearmear.wrk Посмотреть профиль Найти все сообщения от fearmear.wrk
 
Регистрация: 14.07.2017
Сообщений: 21

Описка в функции clearstyle:
localStorage.removeItem("className");

Скорее всего ожидалось
localStorage.removeItem(className);


Откуда-то вылезли удаления из localStorage того чего там никогда не было записано:
localStorage.removeItem('style-norm');


Почти каждый if делает присваивание вместо сравнения:
bodyclassstylec.className = 'style-c'

Тут скорее всего предполагалось проверять есть ли такой класс. Без classList это можно сделать так:
bodyclassstylec.className.match(/style-c/);


Вместо этого:
document.getElementsByTagName("body")[0]

достаточно
document.body


Как работает функция addClass осталось загадкой.

Рекомендую посмотреть на какой-нибудь js unit testing инструмент (Jest), если хотите быть уверены, что ваш код вообще работает так, как предполагалось.

Последний раз редактировалось fearmear.wrk, 14.07.2017 в 13:12.
Ответить с цитированием
  #3 (permalink)  
Старый 14.07.2017, 13:18
Интересующийся
Отправить личное сообщение для zapalych Посмотреть профиль Найти все сообщения от zapalych
 
Регистрация: 30.06.2017
Сообщений: 11

По функции addClass дополнил исходное сообщение.
Ответить с цитированием
  #4 (permalink)  
Старый 14.07.2017, 13:27
Интересующийся
Отправить личное сообщение для fearmear.wrk Посмотреть профиль Найти все сообщения от fearmear.wrk
 
Регистрация: 14.07.2017
Сообщений: 21

var bodyclassstylenorm = localStorage.getItem("statever");

Тут bodyclassstylenorm будет строкой, поэтому условие типа
if (bodyclassstylenorm.className != 'style-c'){

не работает. Попробуйте сравнить со строкой:
if (bodyclassstylenorm !== 'style-c'){

И таких мест 8 штук.

Вообще localStorage всегда хранит свои записи в формате строки, поэтому если хочется хранить что-то другое можно использовать JSON.parse и JSON.stringify при чтении и записи соответственно.

Последний раз редактировалось fearmear.wrk, 14.07.2017 в 13:34.
Ответить с цитированием
  #5 (permalink)  
Старый 14.07.2017, 13:38
Интересующийся
Отправить личное сообщение для zapalych Посмотреть профиль Найти все сообщения от zapalych
 
Регистрация: 30.06.2017
Сообщений: 11

Сообщение от fearmear.wrk Посмотреть сообщение
Вообще localStorage всегда хранит свои записи в формате строки, поэтому если хочется хранить что-то другое можно использовать JSON.parse и JSON.stringify при чтении и записи соответственно.
Вы хотите сказать, что те три типа записей в localstorage при чтении скрипт не различает?
Ответить с цитированием
  #6 (permalink)  
Старый 14.07.2017, 13:47
Интересующийся
Отправить личное сообщение для fearmear.wrk Посмотреть профиль Найти все сообщения от fearmear.wrk
 
Регистрация: 14.07.2017
Сообщений: 21

Сообщение от zapalych Посмотреть сообщение
Вы хотите сказать, что те три типа записей в localstorage при чтении скрипт не различает?
Тут как раз различает, т.к. в вашем случае строка пишется.
Ответить с цитированием
  #7 (permalink)  
Старый 14.07.2017, 13:52
Интересующийся
Отправить личное сообщение для zapalych Посмотреть профиль Найти все сообщения от zapalych
 
Регистрация: 30.06.2017
Сообщений: 11

Но я тогда не очень понимаю понимаю почему происходит так, что по моей логике в statever может быть записано либо style-c либо style-norm, а по факту в консоли у меня выводится другой класс. Или еще бывает все три записи style-norm.
Ответить с цитированием
  #8 (permalink)  
Старый 14.07.2017, 14:04
Интересующийся
Отправить личное сообщение для zapalych Посмотреть профиль Найти все сообщения от zapalych
 
Регистрация: 30.06.2017
Сообщений: 11

Глупая ошибка была!
Я сам же по кнопке вызываю не ту функцию! С записями в localstorage вроде все наладилось.
Но при обновлении до сих пор не сохраняется выбранная совокупность классов. Нужно ведь из localstorage запрашивать, верно?
Ответить с цитированием
  #9 (permalink)  
Старый 14.07.2017, 14:28
Аватар для j0hnik
Профессор
Отправить личное сообщение для j0hnik Посмотреть профиль Найти все сообщения от j0hnik
 
Регистрация: 01.12.2016
Сообщений: 3,650

Этот код можно существенно сократить используя циклы.
Ответить с цитированием
  #10 (permalink)  
Старый 14.07.2017, 14:30
Интересующийся
Отправить личное сообщение для zapalych Посмотреть профиль Найти все сообщения от zapalych
 
Регистрация: 30.06.2017
Сообщений: 11

Проблема решена! Огромное спасибо за помощь.
На всякий случай, оставлю итоговый код, вдруг кому-то пригодится. Он, конечно, не идеален, но работает без подключения дополнительных библиотек. Только что проверил на IE8, всё переключается так, как задумано!

function hasClass(el, className) {
  if (el.classList)
    return el.classList.contains(className)
  else
    return !!el.className.match(new RegExp('(\\s|^)' + className + '(\\s|$)'))
}

function addClass(el, className) {
  if (el.classList)
    el.classList.add(className)
  else if (!hasClass(el, className)) el.className += " " + className
}

function removeClass(el, className) {
  if (el.classList)
    el.classList.remove(className)
  else if (hasClass(el, className)) {
    var reg = new RegExp('(\\s|^)' + className + '(\\s|$)')
    el.className=el.className.replace(reg, ' ')
  }
}

function addstyle(className){
var bodyver = document.getElementsByTagName("body")[0];
addClass(bodyver, className);
localStorage.setItem("statever", className);
}
function addcolor(className){
var bodycol = document.getElementsByTagName("body")[0];
addClass(bodycol, className);
localStorage.setItem("statecol", className);
}
function addsize(className){
var bodysize = document.getElementsByTagName("body")[0];
addClass(bodysize, className);
localStorage.setItem("statesize", className);
}
function clearstyle(className){
var bodyclear = document.getElementsByTagName("body")[0];
removeClass(bodyclear, className);
localStorage.removeItem(className);
}


<div class="style-form" style="margin:0; padding:0; position:fixed; top:60px; right:20px; z-index:99999;">
<button onclick="addsize('style-a'); addcolor('style-blackfont-whitebgr'); addstyle('style-c'); clearstyle('style-norm');" class="style-c" id="click-style-c" style="font-size:18px; background:none; border:none;">Включить доп.панель</button>
</div>


<!-- Панель доп.изменений !-->
<div class="panel-style-c">
<p style="font-size:30px; text-align:center;">Размер:<button onclick="addsize('style-a'); clearstyle('style-aa'); clearstyle('style-aaa');" class="style-a" style="font-size:30px; background:none; border:none;">А</button>
<button onclick="addsize('style-aa'); clearstyle('style-a'); clearstyle('style-aaa');" class="style-aa" style="font-size:40px; background:none; border:none;">А</button>
<button onclick="addsize('style-aaa'); clearstyle('style-a'); clearstyle('style-aa');" class="style-aaa" style="font-size:50px; background:none; border:none;">А</button>
Цвет:<button onclick="addcolor('style-blackfont-whitebgr'); clearstyle('style-whitefont-greenbgr'); clearstyle('style-whitefont-blackbgr');" class="style-blackfont-whitebgr" style="font-size:50px; color:black; background:white; border:black;">А</button>
<button onclick="clearstyle('style-blackfont-whitebgr'); addcolor('style-whitefont-greenbgr'); clearstyle('style-whitefont-blackbgr');" class="style-whitefont-greenbgr" style="font-size:50px; color:white; background:green; border:black;">А</button>
<button onclick="clearstyle('style-blackfont-whitebgr'); clearstyle('style-whitefont-greenbgr'); addcolor('style-whitefont-blackbgr');" class="style-whitefont-blackbgr" style="font-size:50px; color:white; background:black; border:black;">А</button>
<button onclick="addstyle('style-norm'); clearstyle('style-c'); clearstyle('style-a'); clearstyle('style-aa'); clearstyle('style-aaa'); clearstyle('style-blackfont-whitebgr'); clearstyle('style-whitefont-greenbgr'); clearstyle('style-whitefont-blackbgr');" class="style-norm" style="font-size:30px; background:none; border:none;">Обычная версия</button></p>
</div>


var statever = localStorage.getItem("statever");
addstyle(!!statever ? statever : "style-norm");
var statecol = localStorage.getItem("statecol");
addcolor(!!statecol ? statecol : "");
var statesize = localStorage.getItem("statesize");
addsize(!!statesize ? statesize : "");

console.log(statever);
console.log(statecol);
console.log(statesize);

var bodyclassstylec = document.body;
	if (statever == 'style-c'){
		localStorage.getItem("statever");
		localStorage.getItem("statecol");
		localStorage.getItem("statesize");
		removeClass(bodyclassstylec, "style-norm");
		localStorage.removeItem("style-norm");
	}

var bodyclassstylenorm = document.body;
	if (statever !== 'style-c'){
		removeClass(bodyclassstylenorm, "style-c");
		removeClass(bodyclassstylenorm, "style-a");
		removeClass(bodyclassstylenorm, "style-aa");
		removeClass(bodyclassstylenorm, "style-aaa");
		removeClass(bodyclassstylenorm, "style-blackfont-whitebgr");
		removeClass(bodyclassstylenorm, "style-whitefont-greenbgr");
		removeClass(bodyclassstylenorm, "style-whitefont-blackbgr");
		addClass(bodyclassstylenorm, "style-norm");
		localStorage.removeItem("style-c");
		localStorage.removeItem("style-a");
		localStorage.removeItem("style-aa");
		localStorage.removeItem("style-aaa");
		localStorage.removeItem("style-blackfont-whitebgr");
		localStorage.removeItem("style-whitefont-greenbgr");
		localStorage.removeItem("style-whitefont-blackbgr");
	}

var bodyclassstylea = document.body;
	if (bodyclassstylea == 'style-a'){
		addClass(bodyclassstylea, 'style-c');
		removeClass(bodyclassstylea, "style-aa");
		removeClass(bodyclassstylea, "style-aaa");
		removeClass(bodyclassstylea, "style-norm");
		localStorage.removeItem("style-aa");
		localStorage.removeItem("style-aaa");
		localStorage.removeItem("style-norm");
	} else if (bodyclassstylea == 'style-aa'){
		addClass(bodyclassstylea, 'style-c');
		removeClass(bodyclassstylea, "style-a");
		removeClass(bodyclassstylea, "style-aaa");
		removeClass(bodyclassstylea, "style-norm");
		localStorage.removeItem("style-a");
		localStorage.removeItem("style-aaa");
		localStorage.removeItem("style-norm");
	} else if (bodyclassstylea =='style-aaa'){
		addClass(bodyclassstylea, 'style-c');
		removeClass(bodyclassstylea, "style-a");
		removeClass(bodyclassstylea, "style-aa");
		removeClass(bodyclassstylea, "style-norm");
		localStorage.removeItem("style-a");
		localStorage.removeItem("style-aa");
		localStorage.removeItem("style-norm");
	}

var bodyclassstyle = document.body;
	if (bodyclassstyle == 'style-blackfont-whitebgr'){
		addClass(bodyclassstyle, 'style-c');
		removeClass(bodyclassstyle, "style-whitefont-greenbgr");
		removeClass(bodyclassstyle, "style-whitefont-blackbgr");
		localStorage.removeItem("style-whitefont-greenbgr");
		localStorage.removeItem("style-whitefont-blackbgr");
		localStorage.removeItem("style-norm");
	}else if (bodyclassstyle == 'style-whitefont-greenbgr'){
		addClass(bodyclassstyle, "style-c");
		removeClass(bodyclassstyle, "style-blackfont-whitebgr");
		removeClass(bodyclassstyle, "style-whitefont-blackbgr");
		localStorage.removeItem("style-blackfont-whitebgr");
		localStorage.removeItem("style-whitefont-blackbgr");
		localStorage.removeItem("style-norm");
	} else if (bodyclassstyle == 'style-whitefont-blackbgr'){
		addClass(bodyclassstyle, "style-c");
		removeClass(bodyclassstyle, "style-blackfont-whitebgr");
		removeClass(bodyclassstyle, "style-whitefont-greenbgr");
		localStorage.removeItem("style-blackfont-whitebgr");
		localStorage.removeItem("style-whitefont-greenbgr");
		localStorage.removeItem("style-norm");
	}
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Книга: JavaScript. Сильные стороны Magneto Учебные материалы 16 21.04.2013 15:28
Интерпретатор Java на JS kobezzza Оффтопик 24 11.10.2012 18:32
Первый Moscow JavaScript Meetup korenyushkin Общие вопросы Javascript 0 26.07.2011 15:23
Последние книги по JavaScript! monolithed Учебные материалы 7 26.10.2010 19:40
Выдвет ошибку JavaScript Ромио Opera, Safari и др. 4 21.10.2010 20:34