Контроль значений в форме [Javascript]
Нужен совет (а лучше готовый код :)) по использованию JS для контроля значений, вводимых в поля формы:
[HTML]
<form action="">
<table align="center" cellpadding="0" cellspacing="1">
<tr>
<td>Image width:</td><td align="center"><input name="width" type="text" value="150" size="5" maxlength="3" /></td>
</tr>
<tr>
<td>Image heigh:</td><td align="center"><input name="heigh" type="text" value="0" size="5" maxlength="3" /></td>
</tr>
<tr>
<td>Preserve aspect ratio</td><td align="center"><input name="aspect" type="checkbox" value="yes" /></td>
</tr>
<tr>
<td align="center" colspan="2"><input name="press" type="submit" /></td>
</tr>
</table>
</form>
[/HTML]
1. При вводе (целого числового!) значения в поле "Image width", если установлен checkbox "Preserve aspect ratio", значение поля "Image heigh" должно меняться на Image width/0.7, округленное до целого.
2. При вводе (целого числового!) значения в поле "Image heigh", если установлен checkbox "Preserve aspect ratio", значение поля "Image width" должно меняться на Image width*0.7, округленное до целого.
3. При сброшеном checkbox "Preserve aspect ratio", (целые числовые!) значения полей "Image width" и "Image heigh" вводятся независимо друг от друга.
И еще желательно чтоб под NN4 работало (чтоб уж совсем по честному).
Сам в js не силен (совсем), по этому и спрашиваю у умных людей.
Спасибо
Пишите, а то готовый код можно только за деньги получить.
Или показывайте, что вы написали, а там подскажем.
Для начала копайте в сторону:
1) document.getElementById, document.getElementsByTagName
2) атрибут value, checked у input-полей, обращаетесь к ним после получения узла (тега) фукнциями, указанными выше
3) сверяете данные простым if и автозаполняете, используя то, что указано в первых двух пунктах.
Вы забыли про IE4 :( И мозиллу в самых первых её бета-версиях :((( И чтобы работало всё в Windows 3.1 :(
Попробую чего нибудь навоять, если не найдется бескорыстного кодописателя!
Как я понимаю все шаги (1,2,3) нужно вынести в функцию, а откуда к ней обращаться?
Далее вешаете события на input поля, в частности смотрите в сторону onchange, onkeydown, onkeyup.
И еще желательно чтоб под NN4 работало (чтоб уж совсем по честному).
Зачем??? :eek:
function chInt(obj,n)
{
q = obj.value;
if (isNaN(parseInt(q)) || parseInt(q)<0) obj.value=n;
else obj.value=parseInt(q);
}
</script>
<input type='text' name='size' value='0' onchange='chInt(this,"50");'>
Вот что навоял:[HTML]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
<title>Untitled Document</title>
<script langage="JavaScript">
<!--
function change(name){
if(name != 'aspect'){
if(isNaN(parseInt(document.resize.name.value)) || document.resize.name.value < 0){
alert('Wrong "'+name+'" parameter');
switch(name){
case 'width':
document.resize.width.select();
document.resize.width.focus();
break
case 'heigh':
document.resize.heigh.select();
document.resize.heigh.focus();
break
default:
}
return true
}
}
if(window.document.resize.aspect.checked){
switch(name){
case 'aspect':
case 'width':
document.resize.heigh.value =
Math.round(document.resize.width.value/0.7);
break
case 'heigh':
document.resize.width.value =
Math.round(document.resize.heigh.value*0.7);
break
default:
}
}
return true
}
// -->
</script>
</head>
<body>
<form name="resize" action="">
<table align="center" cellpadding="0" cellspacing="1" width="200">
<tr>
<td>Image width:</td><td align="center"><input name="width" type="text" value="100" size="5" maxlength="3" onchange="change(this.name); void(0);"/></td>
</tr>
<tr>
<td>Image heigh:</td><td align="center"><input name="heigh" type="text" value="143" size="5" maxlength="3" onchange="change(this.name); void(0);" /></td>
</tr>
<tr>
<td>Preserve aspect ratio</td><td align="center"><input name="aspect" type="checkbox" onclick=" change(this.name); void(0);" value="yes" /></td>
</tr>
<tr>
<td align="center" colspan="2"><input name="process" type="submit" value="Process" /></td>
</tr>
</table>
</form>
</body>
</html>
[/HTML]
не без помощи добрых людей. Спасибо.
НО все же не решил некоторые задачи:
1. Проверка значений на валидность (положительное целое) производится при событии onChange, т.е. если значение неверное и не исправлено на другое - данное событие не срабатывает! Как исправить?
2. Почему скрипт ругается как на буквы, так и на цифры (валидные данные)? Здесь видимо я что-то упустил.
3. При обнаружении ошибочного значения на поле, содержашее данное значение должен устанавливаться фокус (так должно работать!). Работает скрипт ожидаемым образом только в NN 4.05 (как ни странно!) и Opera 10, в IE 8 - поле выделяется, но не редактируется (словно фокус не установлен), в Firefox 3 - вообще ничего не выделяется. Можно исправить?
Кстати document.getElementById, document.getElementsByTagName в NN не работают!
1) Например, высота по английски - height, а не heigh
2) Код вообще криво написан, ибо "<scri pt langage="JavaScript">", так как нет такого атрибута langage. А уж чтоб совсем правильно - надо type="text/javascript"
3) Не логично в checkbox юзать значение value, имхо, даже не верно. Для установки флага есть атрибут checked
Вот переработанный код:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251" />
<title>Untitled Document</title>
<script type="text/javascript">
<!--
function is_numeric(value) {
var preg = /^\d*$/;
return preg.test(value);
}
function validate_fields(el) {
aspect = document.getElementById("image_aspect");
width = document.getElementById("image_width");
height = document.getElementById("image_height");
// проверяем на корректность поля
if( !is_numeric(width.value) ) {
alert("Введите корректно ширину картинки");
width.focus();
width.select()
return;
}
if( !is_numeric(height.value) ) {
alert("Введите корректно ширину картинки");
height.focus();
height.select()
return;
}
switch(el) {
case height:
if( aspect.checked ) {
width.value = Math.round(parseInt(height.value)*0.7);
}
break;
case width:
if( aspect.checked ) {
height.value = Math.round(parseInt(width.value)/0.7);
}
break;
default:
alert("Uknown error");
break;
}
}
// -->
</script>
</head>
<body>
<form name="resize" action="">
<table align="center" cellpadding="0" cellspacing="1" width="200">
<tr>
<td>Image width:</td>
<td align="center"><input name="width" type="text" id="image_width" value="100" size="5" maxlength="3" onkeyup="validate_fields(this);" /></td>
</tr>
<tr>
<td>Image height:</td>
<td align="center"><input name="heigh" type="text" id="image_height" value="143" size="5" maxlength="3" onkeyup="validate_fields(this);" /></td>
</tr>
<tr>
<td>Preserve aspect ratio</td>
<td align="center"><input name="aspect" id="image_aspect" type="checkbox" checked="checked" /></td>
</tr>
<tr>
<td align="center" colspan="2">
<input name="process" type="submit" value="Process" />
</td>
</tr>
</table>
</form>
</body>
</html>
Но есть пара НО, которые вы уже доделаете сами =)
1) если вставлять цифру через копипаст, то обработка события не произойдет
2) если поле пустое (удалить символы), то будет вылетать ошибка, но должно быть по идее не так.
Я, да и никто другой, кроме Вас, не собирается писать код под браузер, умерший несколько лет назад, и который никто не использует (опять же, кроме Вас). Так что и вам я советую завязать с данной глупой идеей. Это то же самое, что заявить - давайте в играх будем использовать только 16 цветов, чтобы все норм изображалось и на древних компах. В общем, просто глупо писать под давно умерший NN, который стандарты не поддерживает.
Мой код проверял только в Мозилле.
Я, да и никто другой, кроме Вас, не собирается писать код под браузер, умерший несколько лет назад, и который никто не использует (опять же, кроме Вас).
Он умер еще в начале 2000х годов. Потом некоторое время выпускался на ядре Мозиллы. Во всяком случае версии 8 и 9 были на мозилловском движке. В любом случае пациент полностью и окончательно мертв, им никто не пользуется уже много-много лет и даже у консольных браузеров вроде Lynx сейчас аудитория больше.
Так что выкиньте из головы бред про NN. Современный сайт должен работать под браузеры IE6 (и то уже спорно), IE7, IE8, Opera 9.x/10.x, Firefox 2.x/3.x, Chrome, Safari
К сожалению на сайте Netscape-а http://browser.netscape.com/releases самая ранняя доступная версия - 4.7, поэтому под 4.0 проверить мне не удалось.
Из современных браузеров проверил в firefox3.5.5, opera9.6, chrome0.3 и IE7
[html]
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
<script type="text/javascript">
<!--
// Define globals
var DEF_ASPECT_RATIO = 0.7;
function correctFResizeFld(fldname)
{
objFrm = document.forms["FormResize"];
newVal = parseInt(objFrm[fldname].value);
if(isNaN(newVal)) return NaN;
if(objFrm[fldname].value != newVal.toString())
objFrm[fldname].value = newVal;
return newVal;
}
function valFResizeFld(fldname)
{
var val;
// Do nothing if value is not a number
if(isNaN(val=correctFResizeFld(fldname))) return;
objFrm = document.forms["FormResize"];
if(!objFrm["aspect"].checked) return;
// Change another parameter if "preserve aspect ratio" flag is checked
if(fldname=="width")
{
val2 = parseInt(objFrm["height"].value);
if(isNaN(val2) || Math.round(val2*DEF_ASPECT_RATIO) != val)
{
// Change HEIGHT only if it doesn't keep the aspect ratio
objFrm["height"].value = Math.round(val/DEF_ASPECT_RATIO);
}
}else
if(fldname=="height")
{
val2 = parseInt(objFrm["width"].value);
if(isNaN(val2) || Math.round(val2/DEF_ASPECT_RATIO) != val)
{
// Change WIDTH only if it doesn't keep the aspect ratio
objFrm["width"].value = Math.round(val*DEF_ASPECT_RATIO);
}
}
return;
}
// Show/Hide tips - Doesn't work in NN4
var objTip = null;
function showtip(isShow, obj, str)
{
// Hide layer with tip message and remove object
if(!isShow)
{
document.body.removeChild(objTip);
delete(objTip);
objTip = null;
return;
}
// Create object for tip message if it doesn't exist
if(objTip == null)
{
objTip = document.createElement("DIV");
objTip.style.position = "absolute";
objTip.style.color = "#555";
objTip.style.backgroundColor = "#fff";
objTip.style.border = "solid 1px #777";
objTip.style.padding = "4px";
objTip.style.font = "12px Tahoma";
document.body.appendChild(objTip);
}
// Calculate new position for the tip message just near right to the object that invoked the tip message
postop = -10;
if(obj.offsetWidth)
posleft = obj.offsetWidth + 5;
else
posleft = 25;
if(obj.offsetParent)
do {
posleft += obj.offsetLeft;
postop += obj.offsetTop;
} while(obj = obj.offsetParent);
// Apply calculated position and show the message
objTip.style.left = posleft+"px";
objTip.style.top = postop+"px";
objTip.innerHTML = str;
return;
}
// -->
</script>
</head>
<body>
<form name="FormResize" action="">
<table align="center" cellpadding="0" cellspacing="1" border="0">
<tr>
<td>Width: </td>
<td align="center"><input name="width" type="text" id="image_width" value="100" size="5" maxlength="3" tabindex="1"
onKeyUp="valFResizeFld('width')" onBlur="valFResizeFld('width')" /></td>
<td align="center" rowspan="2" style="font-size: small;">&#9488;<br /><a hre="#" onMouseOver="showtip(true, this,'Preserve aspect ratio.<br />\nWidth = Height × '+DEF_ASPECT_RATIO)" onMouseOut="showtip(false)"><input name="aspect" id="image_aspect" type="checkbox" checked="checked" /></a><br />&#9496;</td>
</tr>
<tr>
<td>Height: </td>
<td align="center"><input name="height" type="text" id="image_height" value="143" size="5" maxlength="3" tabindex="2"
onKeyUp="valFResizeFld('height')" onBlur="valFResizeFld('height')" /></td>
</tr>
<tr>
<td align="center" colspan="2">
<input name="process" type="submit" value="resize image" style="width: 100%" tabindex="3" />
</td><td></td>
</tr>
</table>
</form>
</body>
</html>
[/html]
Также позволил себе немного изменить логику работы и интерфейс, который был реализован в Вашем примере. На мой взгляд, пугать пользователя сообщениями об ошибках когда он этого совсем не ждёт, медленно и аккуратно вбивая размеры картинки, не следует. В идеале, пользователю нужно вообще запретить вводить всё, кроме цифр, лишив его возможности ввода неверных данных, поэтому мой вариант тоже не идеальный.
Что касается поддержки старых браузеров, то я бы не стал утверждать, что современный сайт должен поддерживать какой-то список браузеров, составленный дядей Васей из форум.. крутым и очень уважаемым веб-девелопером или должен строго соответствовать стандартам, но только кошерным от W3C, а не грязным майкросовтовским :-)
Сайты делаются в первую очередь для людей, поэтому если стоит задача сделать сайт для каких-то олдскульных бородатых юзеров, которые по той или иной причине пользуются NN4, значит нужно обеспечивать поддержку этого браузера.
Другое дело, что сейчас днём с огнём таких некроманов не найдёшь. И если стоит задача просто что-то наваять, то о поддержке разных браузеров можно вообще забыть и делать всё под свой любимый "ослик" или "рыжего лиса", что там у вас.
Что касается поддержки старых браузеров, то я бы не стал утверждать, что современный сайт должен поддерживать какой-то список браузеров, составленный дядей Васей из форум.. крутым и очень уважаемым веб-девелопером или должен строго соответствовать стандартам, но только кошерным от W3C, а не грязным майкросовтовским :-)
Ествественно, вы правы. Какой смысл слушать людей, которые занимаются профессионально веб-программированием уже 10 лет? Гораздо круче придумать какой-нибудь бред и гордится этим.
Из современных браузеров проверил в firefox3.5.5, opera9.6, chrome0.3 и IE7
Chrome 0.3 ???? Интересно где вы такой раздобыли учитывая что уже давно доступна версия Chrome 3.0
А как насчет IE4 и IE5 ??
Если вы взялись поддерживать древние вымершие браузеры, то об этих тоже нельзя забывать - они как раз тех же времен что NN 4.x