Pull to refresh

Comments 34

Такой подход имеет смысл, если вы строите форму по каким-то данным. Тогда в эти данные можно положить еще сведения о требуемой валидации.

А если идти от разметки, то проще каждому инпуту добавить класс, который будет указывать на нужный тип валидации, типа
<input type="text" name="email" class="js-validate js-validate-email"/>
Да, действительно можно раздать полям формы классы, а не id. Но в погоне за «системностью» подхода я на это пойтить не могу.
id должен быть уникален. Что если у вас в форме два email-поля?
лучше не классами, а data- атрибутами тогда уж, что-то типа этого:

<input type="text" name="email" data-js-validators='email required'>
Тоже вариант, да.
Я пока не стремлюсь использовать data-атрибуты, потому что уж очень мало где поддерживаются нативно.
data-атрибуты поддерживаются абсолютно везде.
Ну да, а в чём проблема? Чем отличается поддержка data-атрибутов в четвёртом фоксе и ie6?
Не знаю, как там в четвертом фоксе, а в Chrome у нод есть свойство .dataset.
Что-то мне подсказывает, что в ie6 этого нет.
Ну и что? getAttribute сильно причина не использовать data-атрибуты? className ведь тоже нужно парсить.
Давайте разделим два пункта.
Первое: нативная поддержка все-таки не везде.
Второе: да, для меня это повод пока что не использовать. По ряду причин. Расписывать?
1. Ну, я так понял, что под ненативной поддержкой вы подразумевали всякие хаки, поехавшую вёрстку и т.п. в ie. Как нерабочий css для html5 без shiv-патча. На счёт dataset — согласен, есть не везде
2. Да, если не сложно.
1. Не думаю, что верстка поедет из-за дата-атрибутов даже в ie6… Хотя кто его знает:)

2.
Одна из причин — суеверная. Я не готов поручиться, что это будет работать as expected. Надо провести тесты, etc — мне лень.
Вторая — консервативная. Существует как минимум два метода, которые будут работать примерно так же по скорости и служат верой и правдой уже давно. Соответственно, не вижу острых причин что-либо менять.
Третья — семантичность это здорово, но жизнь заставляет не ставить ее во главу угла.
Много мелких замечаний к коду.

==========

function createField() {
	var members = new Array('required', 'regexp');
	for(var i = 0; i < arguments.length; i++) {
		this[members[i]] = arguments[i];
	}
}


Не очень понравился кусок. Не очевидно. Понял со второго раза. Почему нельзя было сделать так?
function createField (required, regexp) {
	if (required != null) this.required = required;
	if (regexp   != null) this.regexp   = regexp;
}


==========

Это можно было записать изящнее:

createField.prototype.regexp = /^[A-z0-9-_+. ,@]{1,}$/ig;
createField.prototype.valid = false;
createField.prototype.required = true;
createField.prototype.nullify = function() {
	this.valid = false;
};

// =>

createField.prototype = {
	regexp   : /^[A-z0-9-_+. ,@]{1,}$/ig,
	valid    : false,
	required : true,
	nullify  : function() {
		this.valid = false;
	}
};


==========

Не совсем понятна логика кое-каких названий. Например, createField — это ведь класс, который создаётся с помощью оператора new.
Или функция, которая создаёт класс. Следовательно, должен быть один из вариантов:
var field = createField();
var field = new Field();


Потому что new createField — это тавтология

==========

У меня возникло впечатление, что вы не знаете про хеш {}

почему
var single = new Array();
single['name'] = ...

если в данном случае Array не совсем подходит и правильнее будет с хешем. Тем более, можно красиво записать:

var single = {
	name  : new Field(),
	email : new Field(true, /^[A-z0-9._-]+@[A-z0-9.-]+\.[A-z]{2,4}$/),
	sex   : new Field(true, /male$/ig)
};


Хотя название single мне тоже непонятно. Тут, кажется, больше подошло бы userRegistrationForm

==========

Singleton аналогично непонятно. Во-первых, вы отошли от собственного стиля кодирования и именования переменных в стиле camelCase (regForm, createField) и назвали свойство в стиле underscore (nullify_values)

Во-вторых, даже если вы объявляете объект, который является Синглтоном, называть его "Singleton" — моветон. Вот вы назвали так форму свою. А потом в другом месте у вас ещё один синглтон рулит запросами. Он тоже назовётся Singleton? А ещё один — рулит вводом с клавиатуры — тоже Singleton? Три Singleton делают совершенно разные вещи

В третьих — неправильно делать такие вещи синглтоном. А если у меня несколько независимых форм на странице — всё, облом?

==========

submit — очень тяжёлый. неплохо бы отрефакторить, тем более там есть куда.

Все прям перетер ;)
The best ever инлайн форм валидатор — Mootools Form.Validator.Inline Live пример использования jsfiddle.net/timwienk/LgJsN/ Со всеми зависимостями он пожатый весит 32Кб это много, если поточить напильником и убрать локаль, не нужные валидолы, то до 10, думаю, можно сократить.
Сейчас все проекты используют какой-либо фрэймворк, чаще jQuery, так что лучше, если пишете свой валидатор, писать под фрэймворк.
А если вы желаете изучить принципы работы валидаторов, то лучше изучить исходник того же Form.Validator.Inline кроме изучения принципа работы найдете много интересного, плюс научитесь хорошо структурировать код.
aiwan9 и ещё прогоните, пожалуйста, свой код через JSLint (перед запуском ткните кнопку The Good Parts) и сделайте так, чтобы он вообще не ругался, на некоторые части вашего JavaScript кода больно смотреть.
Ну вы ведь со мной согласны? ;)
Конечно, сейчас не имеет смысла в продакшне писать код с нуля, но всё-же, неплохо знать, как это сделать.
Но вообще согласен с azproduction
Да. Кроме всего прочего есть момент:
    createField.prototype.valid = false;
    createField.prototype.required = true;

Свойства объекта в прототипе хранить не безопасно в плане ошибок из-за делегирующего прототипного наследования в JavaScript лучше их сразу вынести в OwnProperty в конструкторе.
aiwan9 и заодно, не используйте new Array и делайте явное объявление входных переменных в функцию :)
Комильфо:
var Field = function (required, regexp) {
    this.required = (typeof required === 'undefined') ? true : !!required;
    this.regexp = regexp || /^[A-z0-9-_+. ,@]{1,}$/ig;
    this.valid = false;
};

Field.prototype.reset = function () {
    this.valid = false;
    return this;
};
между прочим, (typeof required === 'undefined') отлично заменяется на required == null. По логике вполне подходит, т.к. если передали null, то хотели сделать значение по-умолчанию. Очень удобно.
Стараюсь сравнивать по ссылке, поэтому мне required == null не подходит, если бы undefined было бы объявлено в глобальном замыкании как это сделано в jQuery, тогда я бы сделал вот так required === undefined. Другое дело если мы пропускаем переменную required и у меня будет false, хотя ожидаем true, но для стиля JavaScript это не подходит — лучше переделать конструктор и отправить хэш {regexp: /.*/gi} в качестве единственного параметра.
а чем не подходит null, я таки не понял =)
ведь required == null будет трушным только при undefined и null =) null != false.
да, хеш — это правильно =)
Я стараюсь не сравнивать переменную по содержимому, а сравниваю по ссылке.
Ну, в случае с if (foo == null) это можно назвать альтернативой if (defined foo), но включающую проверку на null. Хотя, дело хазяйское.
Бейте меня ногами, но я полагаю, что валидация должна быть только одна — на стороне сервера. Причины простые: на стороне сервера она должна быть обязательно (понятно почему), а значит придётся повторять тот же код. Причём, наверняка, на другом языке.

Я сейчас практически всегда использую AJAX-формы. Проверка на сервере, ответ на клиенте. Массу клиент-кода экономит.
Согласен. На стороне клиента можно оставить разве что небольшие правила для экономии времени и нервов, например допустимые символы в поле (и то не сложные, например только числа) или проверку занятости логина (сразу ajax отправлять)
Используйте нормальные генераторы форм и не надо будет ничего повторять. Подобные генераторы пишутся с нуля за пару часов максимум.
То есть, вы предлагаете написать ещё дополнительный код, который будет связывать воедино логику сервера и клиента, вместо того, чтобы оставить только код на сервере?

Кроме того, генераторы форм практически всегда оборачиваются головняком для верстальщика. Особенно, если внешний вид формы нужно кастомизировать. А ещё можно вспомнить ситуации, когда форма динамически генерируется на клиенте. Предлагаете в этом случае обращаться к серверу, чтобы он сгенерировал нам форму?

Я просто не вижу смысла оставлять клиент-валидацию. Зачем она? Ну ладно, проверка занятости логина, как выше писали. Но зачем делать дважды одну и ту же проверку обычных полей ума не приложу.
Смысл валидации на клиенте в том, что она работает быстрее. Это экономит время пользователям и снижает нагрузку с сервера. Так что ее наличие — это плюс примерно того же порядка, что сжатие js- и css- файлов в один или использование спрайтов.
Я понимаю в чём смысл валидации на клиенте, честно. И отказался от неё совершенно осознано. В наше время быстрых каналов экономия времени получается на спичках, а деньги сэкономленные от работы над скриптом валидации проще вложить в апгрейд сервера, это будет лучше чем избегать нагрузки подобным способом.

Кроме того, проведённая вами параллель не совсем удачна: сжатие JS/CSS это простая технология. А логика валидации это, как ни крути, код со всеми из него вытекающими: поддержка, апдэйт либ в случае использования сторонних решений, рефакторинг.

Я понимаю, допустим, использование рэгэксп-маски на поле, там скрипт простой и универсальный, пару строчек кода в логике. Написание же полноценной валидации это всегда разработка нового мета-языка обозначений: not_empty, is_email, is_url, is_phone и т. п. И везде оно разное, хотя и стандарты тоже есть. Дублировать довольно таки сложную и трудоёмкую логику я не вижу смысла.
Вы просто не умеете их готовить :)

Валидаторы в верстку должны добавляться при помощи соответствующих атрибутов и только! Дальше по все странице проходится скрипт и смотрит эти атрибуты.

Ни верстке, ни динамической генерации формы это не помешает никак. А вот юзеру удобнее.
Я всегда их так и делал ) Я практически весь JS-код подключаю исключительно через спецаттрибуты.

И как это решает вопрос динамической генерации форм, скажите? По вашей логике генератор форм на сервере лежит, по любому нужно будет к нему обратиться, чтобы форма вышла согласно заданным в одном месте параметрам. Или я неправильно вас понял?
Ajax-валидация — по мне так хорошее решение.

А еще есть решение — сайт на nodeJS. Пишем 1 класс для валидации данных и используем его и на клиенте и на сервере.
Ага, знаю ) Я как большой поклонник JS давно хочу попробовать Node. Но возможности пока не предоставляется.

AJAX-валидация стала для меня выходом, к которому я пришёл после долгой работы с формами: наиболее удачное и автоматизируемое решение. Минимум разработки и максимум эффекта.

ЗЫ: Никаких классов в моём уютненьком прототипном JS!
Опытным путем я заметил, что когда применяется функция RegExp.test(), то сначала она возвращает результат ожидаемый, а потом прямо противоположный.

Никакой магии в этом нет, результат вполне задокументированный. Вы сталкиваетесь с lastIndex
Суть очень проста. Когда в тексте находится совпадение с регулярным выражением, то lastIndex устанавливается в его позицию и в следующий раз ищется начиная с этой позиции. Если не находится — lastIndex устанавливается в нуль. Самый простой способ бороться с этим — сбрасывать lastIndex:

var i, log = console.log,
    re = /male$/ig,
    string = '123male';

log( re.lastIndex    ); // 0
log( re.test(string) ); // true
log( re.lastIndex    ); // 7
log( re.test(string) ); // false
log( re.lastIndex    ); // 0

log( re.test(string) ); // true
log( re.lastIndex    ); // 7
re.lastIndex = 0;
log( re.test(string) ); // true
Sign up to leave a comment.

Articles