Opera, input file, div tabindex
Добрый день. Вопрос к знатокам.
Почему в броузере Opera элемент input (file) не генерирует событие onblur при переходе фокуса на div? Пробовал в разных браузерах: IE, FF, Safari, Chromium - все так как должно быть. В Opera - при переходе с <input type=file id='file1'> на <div tabindex=0>div</div> событие onblur не настает. Почему? Как побороть? <script language='JavaScript 1.5' type='text/JavaScript'> dofocus = function (event) { document.title += 'F'; } doblur = function (event) { document.title += 'B'; } </script> <html> <body> <input type=file id='file1' onfocus='dofocus();' onblur='doblur();'> <div tabindex=0>div</div> <input type=file id='file2' onfocus='dofocus();' onblur='doblur();'> <input type=file id='file3' onfocus='dofocus();' onblur='doblur();'> </body> </html> |
autosoft,
Имхо по-моему в Опере, если только input type=file находится внутри формы с name="..."(*сказал на всякий случай), Поскольку вне формы все эти деяния с type=file без толку в любом браузе, считать из input type=file может только форма <script type="text/javascript"> function dofocus() {alert('A')} function doblur () {alert('B')} </script> <form id="upload" method="post" enctype="multipart/form-data" action="/upload7"> <input type=file id='file1' onfocus='dofocus();' onblur='doblur();'><br /> <div tabindex=0>div</div><br /> <input type=file id='file2' onfocus='dofocus();' onblur='doblur();'><br /> <div tabindex=0>div</div><br /> <input type=file id='file3' onfocus='dofocus();' onblur='doblur();'><br /> </form> |
Это понятно. Пусть тогда такой пример:
<script> dofocus = function (event) { document.title += 'F'; } doblur = function (event) { document.title += 'B'; } </script> <html> <body> <form action='/'> <input type=file id='file1' onfocus='dofocus();' onblur='doblur();'> <div tabindex=0>div</div> <input type=file id='file2' onfocus='dofocus();' onblur='doblur();'> <input type=file id='file3' onfocus='dofocus();' onblur='doblur();'> </form> </body> </html> Все равно не работает. Интересно, что если вместо "file" указать, например "text" - то все события генерируются в Opere так же как и в других браузерах. Но нужно именно "file" и div с фокусом тоже нужен. |
autosoft,
Пример Выше |
Пример Выше
Не работает этот пример. Ни в Opera12 (Linux) ни в Opera12 (Windows). Событе onblur в Opera при переходе с input на div не настает. |
Почему не настаёт, настаёт, можно проверить, пощёлкав на Tab, или выбрать какой-нибудь файл в опере (в хроме это не прокатит), вот если в опере файл не выбрать обработчик onfocus не сработает (в хроме по-любому не сработает), onblur соответственно тоже.
|
Цитата:
|
Цитата:
вот в хроме вообще не пашет, this.focus() не помогает для input type="file" |
Для хрома, оперы и FF пока лучший вариант
<input type=file onclick='dofocus()' onchange="this.focus()" onblur='doblur()'> в IE возникает лишний вызов onblur |
Хорошо. Тогда все по-порядку (по примеру который дал Deff - но сути дела это не меняет):
1. Указываем в Opere: file://localhost/home/user/www/index.html. Можно разместить файл на работающем сайте - эффект тот же. 2. Нажимаем Enter. Открывается страничка с тремя input type=file и div между ними. 3. Нажимаем Tab. Инициируется событие onfocus первого input. Открывается диалог alert. 4. Нажимаем Esc. Закрывается диалог alert. 5. Нажимаем Tab. Ничего не происходит, но курсор перемещается на кнопку первого input. Первый input все еще активен. 6. Нажимаем Tab. Курсор переходит на первый div. 7. Нажимаем Tab. Инициируется событие onfocus второго input. Открывается диалог alert. 8. ... Во всех браузерах (кроме Opera) на 6-м шаге инициируется событие onblur первого input. В Opera - нет. Тестировал на Opera 11 и Opera 12. |
Цитата:
Ответ на вопрос "Почему нет?" - "Потому что так сделали!" (в IE тоже много чего есть, чего нет в других браузерах, и наоборот). |
Цитата:
<script type="text/javascript"> function dofocus(self) {document.body.appendChild(document.createTextNode('focus('+self.name+'), '))} function doblur (self) {document.body.appendChild(document.createTextNode('blur('+self.name+'), '))} </script> <form id="upload" method="post" enctype="multipart/form-data" action="/upload7"> <input tabindex="1" type=file name='file1' onfocus='dofocus(this);' onblur='doblur(this);'><br /> <div tabindex=2>div</div><br /> <input tabindex="3" type=file name='file2' onfocus='dofocus(this);' onblur='doblur(this);'><br /> <div tabindex=4>div</div><br /> <input tabindex="5" type=file name='file3' onfocus='dofocus(this);' onblur='doblur(this);'><br /> </form>по примеру видно что блюр работает но только на последнем инпуте |
devote, тогда уж и про хром отправлять, там при помощи мыши фокус вообще не установить.:)
|
Спасибо всем за ответы. Наверное это действительно баг.
По поводу Chromium. Такой вариант подойдет? <script type="text/javascript"> doclick = function (event) { if (navigator.userAgent.toLowerCase().indexOf('webkit') >= 0) { event.stopPropagation() event.target.focus() } } </script> <html> <body> <form action='/'> <input type=file onclick='doclick(event)'> </form> </body> </html> |
<script type="text/javascript"> function dofocus(self) {document.body.appendChild(document.createTextNode('focus('+self.name+'), '))} function doblur (self) {document.body.appendChild(document.createTextNode('blur('+self.name+'), '))} </script> <form id="upload" method="post" enctype="multipart/form-data" action="/upload7"> <table> <tr><td><input type="file" name='file1' onfocus='dofocus(this);' onblur='doblur(this);'/><td>file1</td> </tr> <tr><td><input type="file" name='file2' onfocus='dofocus(this);' onblur='doblur(this);'/></td><td>file2</td> </tr> <tr><td><input type="file" name='file3' onfocus='dofocus(this);' onblur='doblur(this);'/></td><td>file3</td> </tr> </table> </form> |
Deff
Что толку то? Мне фокус нужен на div. Ну или на td, как в последнем примере. Например так: <script type="text/javascript"> function dofocus(self) {document.body.appendChild(document.createTextNode('focus('+self.name+'), '))} function doblur (self) {document.body.appendChild(document.createTextNode('blur('+self.name+'), '))} </script> <form id="upload" method="post" enctype="multipart/form-data" action="/upload7"> <table> <tr><td><input type="file" name='file1' onfocus='dofocus(this);' onblur='doblur(this);'/><td tabindex=0>file1</td> </tr> <tr><td><input type="file" name='file2' onfocus='dofocus(this);' onblur='doblur(this);'/></td><td tabindex=0>file2</td> </tr> <tr><td><input type="file" name='file3' onfocus='dofocus(this);' onblur='doblur(this);'/></td><td tabindex=0>file3</td> </tr> </table> </form> В результате: focus(file1), focus(file2), focus(file3), А onblur как не было так и нет. |
<script type="text/javascript"> function dofocus(self) {document.body.appendChild(document.createTextNode('focus('+self.name+'),'))} function doblur (self) {document.body.appendChild(document.createTextNode('blur('+self.name+'),'))} </script> <form id="upload" method="post" enctype="multipart/form-data" action="/upload7"> <table> <tr><td><input type="file" name='file1' onfocus='dofocus(this);' onblur='doblur(this);'/><td><input type="button" name='td1' onfocus='dofocus(this);' onblur='doblur(this);'/></td> </tr> <tr><td><input type="file" name='file2' onfocus='dofocus(this);' onblur='doblur(this);'/></td><td><input type="button" name='td2' onfocus='dofocus(this);' onblur='doblur(this);'/></td> </tr> <tr><td><input type="file" name='file3' onfocus='dofocus(this);' onblur='doblur(this);'/></td><td><input type="button" name='td2' onfocus='dofocus(this);' onblur='doblur(this);'/></td> </tr> </table> </form> |
Deff,
чего бы ты не лепил, но тот вариант реально Баг, я отправил репорт в Оперу. Дальше видно будет что к чему. |
devote,
Да баг багом, но обычно прожект доделывают не дожидаясь правки софта? В принципе <button> стилем под div заделать |
Спасибо всем за ответы! Я как раз и с button вариант попробовал.
Мне div нужен как контейнер. В таком div свой контрол нарисован. С рисунками и со своей логикой. И ему нужно фокус принимать. И отдавать конечно тоже. Input не подходит потому что не контейнер. Или я ошибаюсь? Заменил input на button. Вот так: <script type="text/javascript"> function dofocus(self) { document.body.appendChild(document.createTextNode('focus('+self.name+'), ')) } function doblur(self) { document.body.appendChild(document.createTextNode('blur('+self.name+'), ')) } </script> <form action='/'> <table> <tr> <td> <input type="file" name='file1' onfocus='dofocus(this)' onblur='doblur(this)'> <button name='button1' onfocus='dofocus(this)' onblur='doblur(this)'>Button1</button> </td> </tr> <tr> <td> <input type="file" name='file2' onfocus='dofocus(this)' onblur='doblur(this)'> <button name='button2' onfocus='dofocus(this)' onblur='doblur(this)'>Button2</button> </td> </tr> <tr> <td> <input type="file" name='file3' onfocus='dofocus(this)' onblur='doblur(this)'> <button name='button3' onfocus='dofocus(this)' onblur='doblur(this)'>Button3</button> </td> </tr> </table> </form> И снова события onblur нет у <input type=file>. Почему он нужен? <input type=file> на странице невидим и сам находится в div. По-сути этот div - стилизованная кнопка для загрузки файлов. Поэтому что бы его "правильно" нарисовать нужно событие onblur <input type=file>. А его в Opera почему-то нет. |
autosoft,
Цитата:
сделать pozition:absolute; z- index:-100, а фокусироваться на некой кнопке - которая и вызывает загрузку( передает событие onclick на <input type=file> |
Цитата:
Но для единого стиля интерфейса конечно все равно нужно все в порядок привести. Тут и правда похоже подождать нужно. Если это действительно Баг то видимо его исправят. |
autosoft,
Имею отрицательный Опыт, в феврале репортавал - баг до сих пор не исправлен |
Цитата:
<!DOCTYPE html> <html> <head> <style> .file_field { position: relative; border: 1px solid #000; width: 200px; height: 20px; font-weight: bold; background: -webkit-linear-gradient(top, #abd8f0, #446f86); background: -moz-linear-gradient(top, #abd8f0, #446f86); background: -o-linear-gradient(top, #abd8f0, #446f86); background: -ms-linear-gradient(top, #abd8f0, #446f86); background: linear-gradient(top, #abd8f0, #446f86); filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#abd8f0, endColorstr=#446f86); color: #ffc97d; } .file_field div { float: right; font-size: 15px; text-align: center; width: 59px; } .file_field span { display: block; float: left; width: 140px; border-right: 1px solid #000; padding: 0; margin: 0; height: 20px; background-color: #fff; color: red; overflow: hidden; white-space: nowrap; } .file_field input[type="file"] { position: absolute; top: 0; left: 0; margin: 0; border: 0; width: 100%; height: 100%; opacity: 0; filter: Alpha(opacity=0); } /* стиль кнопки при фокусе */ .file_field input[type="file"]:focus ~ div { color: #fff; } </style> </head> <body> <div class="file_field"> <input type="file" onchange="this.nextSibling.innerHTML=this.value" /><span></span><div>Browse</div> </div> <br /> <div class="file_field"> <input type="file" onchange="this.nextSibling.innerHTML=this.value" /><span></span><div>Browse</div> </div> <br /> <div class="file_field"> <input type="file" onchange="this.nextSibling.innerHTML=this.value" /><span></span><div>Browse</div> </div> </body> </html> |
Цитата:
|
Цитата:
Вот пример: <style> input.file { position:absolute; z-index:-100; } </style> <html> <body> <form action='/'> <input class=file type=file id=file> </form> <div tabindex=0 onclick="document.getElementById('file').click()">Button</div> </body> </html> Если бы можно было запретить <input type=file> принимать фокус то было бы то что нужно. Но на onfocus ни event.preventDefault() ни event.stopPropagation() на влияет. Тут на форуме уже обсуждалось. |
Цитата:
|
Цитата:
|
Цитата:
Цитата:
|
Цитата:
Цитата:
|
Немного поправил пример выше, в ИЕ косячно работал
|
вот полностью рабочий пример, с селектором input[type="file"]:focus ~ div ИЕ почему-то косячет, поэтому пришлось скриптом менять класс.
<!DOCTYPE html> <html> <head> <style> .file_field { position: relative; width: 200px; height: 22px; font-weight: bold; background: -webkit-linear-gradient(top, #abd8f0, #446f86); background: -moz-linear-gradient(top, #abd8f0, #446f86); background: -o-linear-gradient(top, #abd8f0, #446f86); background: -ms-linear-gradient(top, #abd8f0, #446f86); background: linear-gradient(top, #abd8f0, #446f86); filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr=#abd8f0, endColorstr=#446f86); color: #ffc97d; border-radius: 6px; } .file_field div { float: right; font-size: 15px; text-align: center; width: 59px; padding-top: 1px; } .file_field span { display: block; float: left; width: 140px; border: 1px solid #999; border-right: 0; padding: 0; margin: 0; height: 20px; background-color: #fff; color: red; overflow: hidden; white-space: nowrap; border-radius: 6px 0 0 6px; } .file_field input[type="file"] { position: absolute; top: 0; left: 0; padding-top: 3px; margin: 0; border: 0; width: 100%; height: 100%; opacity: 0; filter: Alpha(opacity=0); } /* убираем стандартную пунктирную фокусировку */ .file_field input[type="file"]:focus { outline: 0; } /* * стиль кнопки при фокусе, класс file_focus нужен для ИЕ * потому что ИЕ что-то тупит с селектором * input[type="file"]:focus ~ div * смотрите события onfocus, onblur */ .file_focus div, .file_field input[type="file"]:focus ~ div { color: #fff; } </style> </head> <body> <div class="file_field"> <input type="file" onchange="this.nextSibling.innerHTML=this.value" onfocus="this.parentNode.className='file_field file_focus';" onblur="this.parentNode.className='file_field';" /><span></span><div>Browse</div> </div> <br /> <div class="file_field"> <input type="file" onchange="this.nextSibling.innerHTML=this.value" onfocus="this.parentNode.className='file_field file_focus';" onblur="this.parentNode.className='file_field';" /><span></span><div>Browse</div> </div> <br /> <div class="file_field"> <input type="file" onchange="this.nextSibling.innerHTML=this.value" onfocus="this.parentNode.className='file_field file_focus';" onblur="this.parentNode.className='file_field';" /><span></span><div>Browse</div> </div> </body> </html> |
Часовой пояс GMT +3, время: 09:57. |