Jump to content
  • 0

Стилизация input type="radio"...


DjTarik
 Share

Question

Задача такая: нужно стилизовать input type="radio".

Я мыслю так:

- В определённой форме находим все инпуты;

- Далее среди них находим те, у которых тип - "radio";

- Потом проверяем, кто имеет checked="checked";

- Меняем класс родительскому элементу;

HTML:

<form action="#" enctype="application/x-www-form-urlencoded" method="get" id="#" class="change-form" onclick="ChangeInput(this)">
<fieldset>
<legend>Стилизованный "input type='radio'"</legend>
<ul>
<li><span><input type="radio" name="#" value="#" id="switch_6" /></span><label for="switch_6">Переключатель 6</label></li>
<li><span><input type="radio" name="#" value="#" id="switch_7" /></span><label for="switch_7">Переключатель 7</label></li>
<li><span><input type="radio" name="#" value="#" id="switch_8" /></span><label for="switch_8">Переключатель 8</label></li>
<li><span><input type="radio" name="#" value="#" id="switch_9" /></span><label for="switch_9">Переключатель 9</label></li>
<li><span><input type="radio" name="#" value="#" id="switch_10" /></span><label for="switch_10">Переключатель 10</label></li>
</ul>
</fieldset>
</form>

JS:

<script type="text/javascript">
// <![CDATA[
function ChangeInput(obj)
{
var el, name, type;
el = obj.elements;
for (i = 0; i<el.length; i++)
{
name = el[i].nodeName;
if (name.toLowerCase() == "input")
{
type = el[i].type;
if (type.toLowerCase() == "radio")
{
if (el[i].checked)
{
el[i].parentNode.className="on";
}
else
{
el[i].parentNode.className="off";
}
};
};
};
};
// ]]>
</script>

Но что-то мне подсказывает, что всё это сделать можно красивее и код должен быть чище.

Отсюда вопросы:

1. Правильно ли я делаю "в теории", или есть лучше способы?

2. Как можно упростить код и сделать его чище?

JS я тока постигаю основы, поэтому сильно не пинайте)

Хочется написать вариант с нуля и понять смысл, так что Фреймворки не интересуют.

Спасибо.

Link to comment
Share on other sites

  • Answers 51
  • Created
  • Last Reply

Top Posters For This Question

Recommended Posts

  • 0
Searcher, не... i туда передавать не обязательно.

как раз таки без и и не получается...

Разобрался с вызовом, но не могу сделать переменную i глобальной...

Ща выложу код.

onload = ChangeInput;

function ChangeInput()
{
var list = document.getElementById('SwitchWrap'); // id списка
var array = list.getElementsByTagName('input'); // массив из элементов 'input'
for (i = 0; i<array.length; i++)
{
var el = array[i]; // 'input'
var parent = el.parentNode; // 'label'
neighbor = el.previousSibling; // 'span'

// замыкания на i
(function(i) {

parent.onclick = function (){Extra(i);}

})(i);

};

};

function Extra(i)
{
alert(i);
}

Так работает.

А если я делаю 'i' глобальной - не получается.(

Глобальной - это я так понимаю

onload = ChangeInput;
var i;

function ChangeInput()
{
...

Edited by DjTarik
Link to comment
Share on other sites

  • 0

Это ужас какой-то...

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>
<title>An XHTML 1.0 Strict standard template</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />

<style type="text/css">
* {
margin: 0;
padding: 0;
font: 12px Tahoma, Arial, sans-serif;
}

body {
margin: 10px;
}

a {
color: black;
}

.active {
color: red;
}
</style>

<script type="text/javascript">
function CheckSwitch(elem) {
this.elem = typeof elem == 'string' ? document.getElementById(elem) : elem;
this.chk = this.elem.getElementsByTagName('input');
}

CheckSwitch.prototype.getInfo = function(elem) {
alert('Вы поменяли чекбокс с именем ' + elem.name + ' и значением ' + elem.value + ' и установили значение checked в ' + elem.checked);
}

CheckSwitch.prototype.setListeners = function() {
var prnt = this;

for (var i = 0; i < this.chk.length; i++) {
(function(i) {
if (prnt.chk[i].type == 'checkbox') {
prnt.chk[i].onchange = function() {
prnt.getInfo(this);
}
}
})(i);
}
}

window.onload = function() {
var obj = new CheckSwitch('test');
obj.setListeners();
}
</script>
</head>

<body>

<fotm id="test" action="" method="post">
<input type="checkbox" name="checkgox01" checked="checked" value="1" />
<input type="checkbox" name="checkgox02" value="2" />
<input type="checkbox" name="checkgox03" value="3" />
<input type="checkbox" name="checkgox04" value="4" />
<input type="checkbox" name="checkgox05" value="5" />
<input type="checkbox" name="checkgox06" value="6" />
<input type="checkbox" name="checkgox07" value="7" />
<input type="checkbox" name="checkgox08" value="8" />
<input type="checkbox" name="checkgox09" value="9" />
<input type="checkbox" name="checkgox10" value="10" />
</form>

</body>
</html>

Если уж так не поймете, то я даже и не знаю как объяснить...

Link to comment
Share on other sites

  • 0
Это ужас какой-то...

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">

<head>
<title>An XHTML 1.0 Strict standard template</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<meta http-equiv="Content-Style-Type" content="text/css" />
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />

<style type="text/css">
* {
margin: 0;
padding: 0;
font: 12px Tahoma, Arial, sans-serif;
}

body {
margin: 10px;
}

a {
color: black;
}

.active {
color: red;
}
</style>

<script type="text/javascript">
function CheckSwitch(elem) {
this.elem = typeof elem == 'string' ? document.getElementById(elem) : elem;
this.chk = this.elem.getElementsByTagName('input');
}

CheckSwitch.prototype.getInfo = function(elem) {
alert('Вы поменяли чекбокс с именем ' + elem.name + ' и значением ' + elem.value + ' и установили значение checked в ' + elem.checked);
}

CheckSwitch.prototype.setListeners = function() {
var prnt = this;

for (var i = 0; i < this.chk.length; i++) {
(function(i) {
if (prnt.chk[i].type == 'checkbox') {
prnt.chk[i].onchange = function() {
prnt.getInfo(this);
}
}
})(i);
}
}

window.onload = function() {
var obj = new CheckSwitch('test');
obj.setListeners();
}
</script>
</head>

<body>

<fotm id="test" action="" method="post">
<input type="checkbox" name="checkgox01" checked="checked" value="1" />
<input type="checkbox" name="checkgox02" value="2" />
<input type="checkbox" name="checkgox03" value="3" />
<input type="checkbox" name="checkgox04" value="4" />
<input type="checkbox" name="checkgox05" value="5" />
<input type="checkbox" name="checkgox06" value="6" />
<input type="checkbox" name="checkgox07" value="7" />
<input type="checkbox" name="checkgox08" value="8" />
<input type="checkbox" name="checkgox09" value="9" />
<input type="checkbox" name="checkgox10" value="10" />
</form>

</body>
</html>

Если уж так не поймете, то я даже и не знаю как объяснить...

=) Я же тока начинаю учить) Поэтому и вопросы глупые, что поделать...(

Спасибо за код, разберусь, потом отпишу.

Link to comment
Share on other sites

  • 0

Я понимаю, что уже всех достал, но всё же спрошу:

В принципе, у меня получилось, то, что нужно:

	<script type="text/javascript">
// <![CDATA[

// Descr -->
onload = ChangeInput;

function ChangeInput()
{
var list = document.getElementById('SwitchWrap'); // id списка
var array = list.getElementsByTagName('input'); // массив из элементов 'input'
for (i = 0; i<array.length; i++)
{
var el = array[i]; // 'input'
var parent = el.parentNode; // 'label'
var neighbor = el.previousSibling; // 'span'

if(el.checked)
{
neighbor.className = 'on'; // если активный - устанавливаем класс

(function(i){
parent.onmouseover = function ()
{
array[i].previousSibling.className = 'on-hover'; // если наводим мышь - меняем класс на ховер
}
parent.onmouseout = function ()
{
array[i].previousSibling.className = 'on'; // если убираем мышь - меняе класс обратно
}
})(i);

}
else
{
neighbor.className = ''; // если не активный - устанавливаем пустой класс (не знаю, как удалить таким способом)

(function(i){
parent.onmouseover = function ()
{
array[i].previousSibling.className = 'off-hover'; // если наводим мышь - меняем класс на ховер
}
parent.onmouseout = function ()
{
array[i].previousSibling.className = ''; // если убираем мышь - меняе класс обратно
}
})(i);

parent.onclick = ChangeInput;

};
};
};

// ]]>
</script>

<ul id="SwitchWrap">
<li><label for="switch_6"><span><!-- // --></span><input type="radio" name="#" value="#" id="switch_6" />Переключатель 6</label></li>
<li><label for="switch_7"><span><!-- // --></span><input type="radio" name="#" value="#" checked="checked" id="switch_7" />Переключатель 7</label></li>
<li><label for="switch_8"><span><!-- // --></span><input type="radio" name="#" value="#" id="switch_8" />Переключатель 8</label></li>
<li><label for="switch_9"><span><!-- // --></span><input type="radio" name="#" value="#" id="switch_9" />Переключатель 9</label></li>
<li><label for="switch_10"><span><!-- // --></span><input type="radio" name="#" value="#" id="switch_10" />Переключатель 10</label></li>
</ul>

Но есть ещё вопросы:

1. Как правильнее устанавливать классы:

- array.previousSibling.className = 'on';

или

- array.previousSibling.setAttribute('class','on');

(Просто первым вариантом я не могу удалить класс. Только сделать его пустым.)

2. Я в начале определил:

var el = array; // 'input'

var parent = el.parentNode; // 'label'

var neighbor = el.previousSibling; // 'span'

Всё норм. Но когда я в замыкании - я не могу их использовать.

Т.е. я вместо:

array.previousSibling.className = 'on-hover';

не могу написать

neighbor.className = 'on-hover';

не пойму, почему?

Ещё раз спасибо.

Link to comment
Share on other sites

  • 0
Просто первым вариантом я не могу удалить класс. Только сделать его пустым

Ну и пусть он будет пустой, не все ли равно?

Всё норм. Но когда я в замыкании - я не могу их использовать.

Потому, что вне замыкания тут:

var el = array;

всегда будет последний элемент массива.

Для того замыкание и нужно.

Link to comment
Share on other sites

  • 0
Ну и пусть он будет пустой, не все ли равно?

Так а какой вариант правильнее юзать?

Потому, что вне замыкания тут:

var el = array;

всегда будет последний элемент массива.

Для того замыкание и нужно.

Ясно. Ща ещё кое что попробую, потом спрошу)

Link to comment
Share on other sites

  • 0

Ребята, нужен хелп.

Вроде во всём разобрался, всё понятно, сделал так:

function StylisedRadio()
{
var wrapper = document.getElementById('StylisedRadioWrapper');
var array = wrapper.getElementsByTagName('input');
for (var i = 0; i<array.length; i++)
{
var el = array[i]; // input
var neighbor = el.nextSibling; // label
var child = neighbor.firstChild; // span
el.className = 'hide-input';
if(el.checked)
{
child.className = 'radio-on';
(function(i){
neighbor.onmouseover = function ()
{
array[i].nextSibling.firstChild.className = 'radio-on-over';
};
neighbor.onmouseout = function ()
{
array[i].nextSibling.firstChild.className = 'radio-on';
};
})(i);
}
else
{
child.className = '';
(function(i){
neighbor.onmouseover = function ()
{
array[i].nextSibling.firstChild.className = 'radio-off-over';
};
neighbor.onmouseout = function ()
{
array[i].nextSibling.firstChild.className = '';
};
neighbor.onclick = function ()
{
array[i].checked = 'true';
StylisedRadio ();
};
})(i);

};
};
};

В Опере не работает. Не могу понять почему? O_o Где я накосячил?

Для большей юзабельности - ссылка:

http://tarik.kasperovich.ru/test/index.html

Спасибо.

Link to comment
Share on other sites

  • 0
Я в коде не разбирался, так только мельком глянул...

Может не надо в checked строку передавать?

// вместо
array[i].checked = 'true';

// попробуйте
array[i].checked = true;

я пробовал - не в этом дело.

Такое чувство, что Опера не видит мои <span>

Я даже не знаю, в какую сторону копать? O_o

Link to comment
Share on other sites

  • 0
А что в опере неработает? Я какраз в опере все просматривал (10.51). Все вроде работает.

У меня ни в одной из версий не пашет. Должно быть так:

Изначально - просто прозрачный спан. При наведении - фон красный.

Если инпут выбран - спан синий. При наведении - зелёный.

Так?

Ставьте алерты везде и смотрите какой из них Опера не показывает. А вообще эта Опера - то еще ГЭ...

Проверяю алертами сами переменные:

var el = array[i];	// input
alert(el);
var neighbor = el.nextSibling; // label
alert(neighbor);
var child = neighbor.firstChild; // span
alert(child);

В FF:

[object HTMLInputElement]

[object HTMLLabelElement]

[object HTMLSpanElement]

В Opera:

[object HTMLInputElement]

[object HTMLLabelElement]

[object HTMLElement]

Это нормально? Третья строка в опере...

Link to comment
Share on other sites

  • 0
У меня ни в одной из версий не пашет. Должно быть так:

Изначально - просто прозрачный спан. При наведении - фон красный.

Если инпут выбран - спан синий. При наведении - зелёный.

Да, именно так.

Link to comment
Share on other sites

  • 0

Вы бы их не просто алертили, а алертили по tagName и nodeName. Так понятней будет. А вообще зря вы в детьми, потомками и родителями заморачиваетесь. Есть же готовый метод getElementsByTagName, его и используйте. Может Опера видит какой-то непечатаемый символ и считает его как ноду?

Link to comment
Share on other sites

  • 0
Вы бы их не просто алертили, а алертили по tagName и nodeName. Так понятней будет. А вообще зря вы в детьми, потомками и родителями заморачиваетесь. Есть же готовый метод getElementsByTagName, его и используйте. Может Опера видит какой-то непечатаемый символ и считает его как ноду?

OK, ща буду пробовать. Потом отпишу.

P.S. Давай на "ты"...

Link to comment
Share on other sites

  • 0

Короче - понял в чём проблема...

Когда я ставлю событие

(function(i){
neighbor.onmouseover = function ()
{
alert("1");
array[i].nextSibling.firstChild.className = 'radio-on-over';
};
neighbor.onmouseout = function ()
{
alert("2");
array[i].nextSibling.firstChild.className = 'radio-on';
};
})(i);

- алерты срабатывают, а изменение классов - нет. Почему - пока не понял... Может всё дело в замыкания? O_o

Не получается сменить класс... Стиль могу присвоить - а вот класс - нет... Что за фигня? Где я намудрил?

Link to comment
Share on other sites

  • 0

Снова работал с этим скриптом - появился ещё вопрос:

// Stylised "input type='radio'" -->
function StylisedFormRadio()
{
var form = document.getElementById('StylisedFormRadio'); // form's id -->
var array = form.elements; // array of form's elements -->
for (var i = 0; i < array.length; i++)
{
var el = array[i]; // element -->
if (el.type == 'radio') // only "input type='radio'" -->
{
var label = el.nextSibling; // label
if (label.lastChild.nodeType == '3') // [object Text]
{
var span = document.createElement('span'); // span
label.appendChild(span);
}
else
{
var span = label.lastChild; // span
}
el.className = 'hide-input';
if (el.checked)
{
span.className = 'radio-on';
label.onmouseover = function()
{
this.lastChild.className = 'radio-on-over';
}
label.onmouseout = function()
{
this.lastChild.className = 'radio-on';
}
}
else
{
span.className = '';
label.onmouseover = function()
{
this.lastChild.className = 'radio-off-over';
}
label.onmouseout = function()
{
this.lastChild.className = '';
}
label.onclick = function()
{
this.previousSibling.checked = true;
StylisedFormRadio();
}
}
}
}
}
// -->

- всё работает, всё классно. Но:

там где у меня идёт проверка

if (el.checked)
{
//
}
else
{
//
StylisedFormRadio();
}

Мне нужно делать рекурсию.

Я повторяю всю функцию, а мне нужно только кусок:

if (el.checked)
{
//
}
else
{
//
}

Какие есть способы выполнить внутри функции определённые куски кода?

Мне нужно что-то типа "goto"...

Есть такое? И как поступать в таких случаях?

Link to comment
Share on other sites

  • 0
Вынеси в отдельную функцию и повторяй сколько душе угодно

ну я так и хотел делать... а потом передумал, потому что много параметров приходится туда передавать... Да и эти замыкания.

P.S. Но, я так понял, меток в JS нету?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share


×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue. See more about our Guidelines and Privacy Policy