7774 читателя, 1444 поста
Администрация
Модераторы
Полезности для web-разработчиков.
<a href="#" onclick="document.getElementById('myform').submit(); return false;">Отправить</a>
<input type="submit" value="Отправить" class="link" />
addEvent(window, 'load', windowLoad);
/* Кроссбраузерное добавление обработчика события */
function addEvent(obj, evType, fn){
if (obj.addEventListener) {
obj.addEventListener(evType, fn, false);
} else if (obj.attachEvent) {
obj.attachEvent('on' + evType, fn);
}
}
/* Получаем родительскую форму для элемента */
function getParentForm(obj) {
while ((obj = obj.parentNode)) {
if (obj.nodeName == 'FORM') {
break;
}
}
return obj;
}
/* Ищем все submit-кнопки с классом link и заменяем их на ссылки */
function windowLoad() {
var buttons = document.getElementsByTagName('input');
for (var i = 0; i < buttons.length ; i++) {
if (buttons[i].getAttribute('type') == 'submit' && buttons[i].className == 'link') {
var link = document.createElement('a');
link.appendChild(document.createTextNode(buttons[i].getAttribute('value')));
link.setAttribute('href', '#');
addEvent(link, 'click', linkClick);
var parent = buttons[i].parentNode;
parent.removeChild(buttons[i]);
parent.appendChild(link);
}
}
}
/* Отправляем форму по нажатию на ссылку */
function linkClick(e) {
var e = window.event || e;
var target = e.target || e.srcElement;
var parentForm = getParentForm(target);
parentForm.submit();
if (window.event) { e.returnValue = false; } else { e.preventDefault(); }
}
button, а span нужен для того чтобы можно было в Firefox добавить подчеркивание текста.<button type="submit" class="link"><span>Отправить</span></button>
var buttons = document.getElementsByTagName('button');
for (var i = 0; i < buttons.length ; i++) {
if (buttons[i].getAttribute('type') == 'submit' && buttons[i].className == 'link') {
var link = document.createElement('a');
link.appendChild(document.createTextNode(buttons[i].firstChild.firstChild.nodeValue));
button.link {
/* Первые два свойства нужны чтобы убрать отступы в IE */
overflow: visible;
width: auto;
/* Убираем отступы */
margin: 0;
padding: 0;
/* Убираем все элементы оформления кнопки */
background: none;
border: none;
/* Обычный для ссылок курсор */
cursor: pointer;
}
/* Ссылка обычно подчеркнута */
button.link span {
color: #00f;
text-decoration: underline;
}
-moz-user-select: text; чтобы текст кнопки можно было выделять, но я сомневаюсь в такой надобности.<form>
<input type="text" name="a" />
<input type="submit" id="push-me" style="display:none" />
</form>
<label for="push-me">fake submit</label>
комментарии (141)
или эту
или эту
< button type = submit > </button >
< input type = submit / >
Правильнее предлагать заказчиу или дизайнеру почитать Раскина и Купера прежде чем лепить такие «шедевры».
Форма — это не только набор полей ввода. Она может быть целиком невидимой и нужной только лишь для технической реализации задачи (и борьбе со сложным и неудобным решением, которое получается если обойтись без нее).
К тому же, мое замечание касалось внешнего вида и поведения псевдо-кнопки, а не ее технической реализации.
Как я написал в конце топика, без js можно и обойтись оставив только стилизированную кнопку, но у пользователей с включенным js не будет настоящей ссылки.
Я привел все возможные варианты решения. Использовать ли их все вместе или по отдельности уже зависит от конкретной ситуации.
Нарисуйте ссылку и сделайте type=image!
А в будущем (ну, когда с деньгами проблем не будет) сразу посылайте таких нахер, т.к. по ходу дальнейшей работы они выдадут не один подобный перл (not perl!).
Тогда не удастся добавить подчеркивание (если оно необходимо) в Firefox в стандартном режиме.
Отправить
<script>
$('#submit').hide();
$('#a').show();
</script>
С другой стороны, вы где-то так и предлагаете, только усложненно.
Можно и так, но прописывать в html постоянно и кнопку и ссылку лень (двигатель прогресса) плюс семантика и все такое :), а так за нас все делает js :)
onsubmitслучайненько? :-)Например Opera Mini это ~ 7% рунета, а на ней свет клином тоже не сошёлся есть и другие моб. устройства.
т.е. чтоб допустим клик на кнопку «показать комментарии» перезагрузит заново всю страницу и в уже перезагруженной покажет эти комментарии.
Подробнее тут.
Но поставленная задача имеет право жить, поэтому ждем _красивое_ решение :)
Впрочем решение приведенное в статье, хотя и хитрый хак, но весьма и весьма :)
Пользователь ценит качество, удивительно, правда?
Адаптироваться под рынок нужно и правильно, но доходить до крайностей убивая на разработку простого продукта в десять раз больше времени, что бы я мог открывать ваш мегасайт на своем полудохлом Сименсе, простите, это загиб.
Понятно, что специально «писать сайт под перфокарты» не надо, если хотя бы делать все качественно, это имеет свои преимущества. Например, если вы забьете на пользователей без скрипта, вы можете заодно поставить палки в колеса гугловскому боту, ну и так далее.
И есть еще человеческий фактор, мне например, неинтересно делать что-то совсем уж некачественно, ради экономии небольшого количества времени (да и сам потом же запутаешься в плохо написанном коде).
Приведите пример такой функциональности. Мне кажется Вы прячете свою лень за «невозможностью».
ps: динамических
Медленный/нестабильный канал, ошибка в скриптах, неправильное кеширование, кривой прокси-сервер в корпоративной сети и тд. Вот для таких случаев тоже оч полезно иметь сайт, который будет продолжать работать без js.
Дело в том, что в случаях «отключил js» и «вышел в нет с мобильника» люди делают это осознанно, и как-бы сами виноваты. Поэтому как-бы можно сайт для них не вытачивать, сами разберутся. А вот в случае «js не догрузился» пользователи обычно уже ни в чем не виноваты и поделать ничего не могут, выручить может только предусмотрительный разработчик на белом коне с graceful degradation.
Поэтому я за то, чтобы не забивать на поддержку людей без js.
Кеширование — это в настройках сервера. Например, отдастся клиенту старая версия странички вдруг. Из-за излишне агрессивно настроенного reverse proxy. Бывает такое на shared-хостингах. Или с http-хидерами перемудрит кто-нибудь. И скрипт какой-нибудь (не обязательно обработчик онСабмит, а что-нибудь еще) завершится с ошибкой из-за несовпадения его ожиданий по части html кода с тем, что есть.
Он может завершиться с ошибкой и из-за какого-нибудь кривого браузера. Или просто потому, что код кривой и где-то не работает, так тоже бывает, живем мы не в идеальном мире. Выберет, например, getElementById что-нибудь с name=myform вместо id=myform в IE. И у этой фигни с name=myform не будет метода submit(), и все упадет. Гипотетически такая возможность есть даже в этом элементарном примере. Причин ошибок в js может быть куча, от кривых рук разработчика до баннерорезалок, фаерволов и проксей на публичных точках wi-fi. При этом выполнение js на странице остановится. Причем часто не только того скрипта, где ошибка, а вообще всего js.
Особенность клиентской части в том, что ее ведь не проконтролируешь, и там много всякой дикости случается. Такие ситуации в прошлое вовсе не уходят. Быть может, даже наоборот — чем больше js на странице, тем более вероятно, что где-то в нем ошибка.
Также нет желания смотреть рекламу и убогие попытки студентов-вебмастеров выпендриться, установив какой нибудь эффект к jQuery.
:)
Ага, у меня тоже иногда ощущение что никому кроме написавших это школьников, это никому не нужно. За флешевые вставки вообще руки отрывать надо, кроме авторов, они никому не нужны. Такие сайты, как например artlebedev.ru как-то умудряются работать без скриптов и флеша.
> Но без JS и прочих фич Вы, в первую очередь, Вы теряете функционал который мог бы предложить вам конкретный ресурс.
Зачем нужен яваскрипт, чтобы прочесть текст, или отправить комменатрий? Мне не надо чтобы форма комментария вылетала и переливалась всеми цветами. Жаль что даже авторы того же Хабра этого не понимают, обвешали сайт кучей кое-как написанных скриптов, в результате постоянно надписи типа «Some error. We know», или зависания. Не, если вы говорите о таком «функционале», я как-нибудь без него обойдусь.
Чтобы сделать это с удобством.
Мне вообще не понятно, на какие это сайты Вы ходите, где сделанные школьниками формы переливаются цветами. Может лучше прямо скажите — мешает popup на порнухе и все встанет на свои места.
Во-первых, приведите пример кода, написанного «кое-как».
Во-вторых, Вы за своими эмоциями начинаете говорить чепуху: «Some error» происходит на сервере, причем тут js? Или Вам приятнее уйти на страницу 500?
загляните в любой хаброJSник — код написан именно «кое-как», особенно там не не скопитырен, а написан самостоятельно.
Вы знаете, иногда структурированность и локоничность, безусловно, — отличный способ преподнести контент определенного содержания конечному пользователю. Но иногда бывают такие случаи, вы знаете, от балды пример совершенно, не заходил — не знаю, какой нибудь диснеевский сайт или сайт там, ну не знаю, да майспэйс, с которого у меня сейчас музычка тянется какая то, да любой, более менее развлекательный ресурс, в них во всех есть какой нибудь флэш плэер в котором крутится какая нибудь фановая музычка (без которой конечно же можно обойтись, но так интересней). Или, о точно, пасхалки во флэшках, весело и непринужденно. И ведь без скриптов никуда.
В общем идея не в том, что эти все флэшки или скрипты «написанные школьниками» — это, не спорю, может в некоторых случаях и мозолит глаз обычных обывателей, как я и Вы, но когда это вписывается в дизайн или удобно по функционалу, признайте, не будьте ханжой, это красиво и удобно=)
Кстати, возвращаясь к Вашему упоменанию artlebedev'у: у них в бизнес линче вроде постраничная навигация (помимо обычных хтмлных ссылок), скриптово работает, хотя это может и совершенно «не нужно, есть ссылки» (обойдемся без пруфлинков, все и так знают). И более того, даже там создатели не потрудились запихать этот навигационный блок в noscript.
Так что это конечно все довольно спорно=)
А вот мания ставить флешку в шапку сайта к примеру, «чтоб блестело» — дурь.
> но когда это вписывается в дизайн или удобно по функционалу, признайте, не будьте ханжой, это красиво и удобно=)
Понятно, что где-то есть и профессионалы, но их по моему не так много. Опять же, еслди ради флеша мне надо ждать — я его лучше отключу, серьезно, пусть грузят в фоновом режиме или еще как-то.
У Лебедева навигация сделана в носкрипте видимо для поисковиков.
<a href="/blogs/webdev/65471/?reply_to=1834683#form_reply_1834683">ответить</a>
На сервере нарисовать форму в нужном месте, в зависимости от reply_to :-P
Кстати, отдельный луч презрения Хабраразработчикам за тяжеленный код коммента, мало того что там пробелов и HTML кода раза в 4 больше чем полезного текста, так он зараза пока грузится намертво блокирует Оперу. Чтоб у вас там все так же тормозило.
:)
а на счет глючащего скрипта — дык это же уже недостатки реализации.
Эта статья это, можно сказать, ход моих мыслей по поводу решения проблемы :) Хотелось полностью раскрыть тему. Как использовать и что уже зависит от ТЗ.
<script>
document.write("<a href=\"#\" onclick=\"document.getElementById('myform').submit(); return false;\">Отправить</a>");
</script>
<noscript>
<input type="submit">
</noscript>
Но, если серьезно… автор, вы правда считаете, что подобному топику место на хабре?
<form>
<input type="text" name="a" />
<input type="submit" id="push-me" style="display:none" />
</form>
<label for="push-me">fake submit</label>
При тестировании на скорую руку не обнаружил каких-то явных минусов.
Спасибо!
Правда, клик по лабелу для такой кнопки ничего не дает, но это уже другой вопрос.
position: absolute; left: -10000px?Кстати, не понимаю в чем проблема, но у меня display: none; в Опере то работает, то не работает. Видимо что-то я перемудрил :)
Но в решении этой проблемы такое поведение нам не поможет.
KISS
Обратите внимание, во всех вариантах есть куча проблем
Напирмер, найдите ошибку в следующих 2х строчках:
parent.removeChild(buttons[i]);
parent.appendChild(link);
(подсказка: buttons[i] не обязательно последний чайлд своего парента)
+ следующий вариант не будет работать сразу по 2м причинам:
<input type=«submit» name=«add» value=«Отправить» class=«link add» />
<input type=«submit» name=«remove» value=«Удалить» class=«link remove» />
1) На сервер не отправляется name нажатой кнопки
2) Не сработает условие buttons[i].className == 'link'
Вариант с, как уже было отмечено выше, не кросс-браузерный, и кнопка не получает фокус.
Повторюсь: ваша статья — хорошая иллюстрация для принципа KISS. Чем сложнее решение, тем больше в нем ошибок.
Да, спасибо, я погорячился, есть ведь замечательный метод:
replaceChild(newChild, oldChild)
класс (если может использоваться несколько) можно проверять регулярным выражением приблизительно так
(^|\s)class(\s|$)
А name можно отправлять (если есть такая необходимость) создавая по нажатию на ссылку скрытый параметр.
в итоге получаем увеличение бюджета проекта ради сотых долей процента пользователей (да и те доли процента — скорее всего роботы). безсмысленно это все.
Хм, а по моим данным Ваша оценка количества пользователей, у которых что-то не сработало (сотые доли процента) отличается от реальной в сотни раз. И оценка трудозатрат (в 2 раза больше работы на тестирование) тоже излишне завышена.
Да нет ничего сложного нет в том, чтоб сначала сделать вариант без js, а потом сверху «навесить» что нужно. Это миф какой-то про дублирование функционала. К контроллеру приходит запрос, если он аяксовый — отдается json с данными, если нет — рендерится шаблон. Дублирование функционала — это скорее проблема организации разработки, а не graceful degradation.
Если есть какой-то сложный интерактивный элемент на js — не нужно его полностью реализовывать в варианте без js, такой фанатизм — зло, конечно. Задача — чтобы сайтом пользоваться можно было нормально, не больше. Разумный компромисс найти всегда можно, и никакого увеличения бюджета это не несет.
совсем не согласен. написание дополнительного кода — это уже увеличение бюджета.
> И оценка трудозатрат (в 2 раза больше работы на тестирование) тоже излишне завышена
вместо «проверить со включенным js» нужно «проверить со включенным js»+«проверить с отключенным js»
как бы как раз в 2 раза.
>Это миф какой-то про дублирование функционала
может я не совсем корректно выразился, но под дублированием я подразумевал как раз вот это — «запрос, если он аяксовый — отдается json с данными, если нет — рендерится шаблон». тут как минимум а) нужно делать дополнительный шаблон и б) делать отдельные контролы (да, да, контрол может быть один, но нужно будет реализовывать два механизма работы, все равно это две задачи вместо одной).
> оценка количества пользователей, у которых что-то не сработало (сотые доли процента) отличается от реальной в сотни раз
отличается только если не разделять статистику на пользователей ПК и пользователей мобильных устройств. но даже если ориентироваться и на мобильных пользователей, все равно лучше сделать отдельную версию для таких пользователей, чем заставлять их грузить контент, который у них не будет работать и потому для них бесполезен
это решается грамотной архитектурой + частичными шаблонами.
это решается дополнительными трудозатратами и увеличением бюджета. а грамотная архитектура — в данном случае всего лишь средство уменьшения доп. трудозатрат, но к нулю она их никак не сведет.
Так что экономия на качестве кода имхо подходит для одноразовых проектов, где ничего не будет расширяться или дополняться, чтобы один раз сделать и ничего больше не трогать.
Submit
P.S. Не скажу, что вариант самый лучший, просто хочу сказать автору, что вариантов решение проблемы можно найти уйму, даже и не извращаясь с js
a style=position:relative
Link text
input type=submit style=position:absolute;left:0;opacity:0;filter:alpha(opacity=0)
/a
но причем тут они? js может не загрузиться, он может не поддерживаться устройством или программой, работающей с сайтом или веб-приложением. это что, тоже херня чтоли?
1. Пользователь-мудак с IE6
2. Пользователь-мудак с намеренно отлюченными JS
А выжигать огнём и не подпускать к интернетам надо тех, кто стремится выжигать огнём и не подпускать к интернетам :)
По-моему, нужно было просто написать, что такого дизайнера надо отправить работать дворником или водителем. А заказчиков таких не бывает.
Тогда уж проще так: [script] doc.write(код ссылки) [/script][noscript] input type=submit [/noscript], но это на редкость тупое решение.
не хватает проверки на obj'екта на null.
2) Кончайте закрывать непарные теги, xhtml мёртв.
На вкус и цвет товарища нет ;)
.form
и становится ненужной конструкция с while
Тогда пишем noscript:
<noscript>
/>
</noscript>
Про какие-то банальности рассказываете. Чудо-пост.
зы. я не минусовал