Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Opera, input file, div tabindex (https://javascript.ru/forum/events/29562-opera-input-file-div-tabindex.html)

autosoft 03.07.2012 12:17

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>

Deff 03.07.2012 12:33

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>

autosoft 03.07.2012 12:47

Это понятно. Пусть тогда такой пример:
<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 с фокусом тоже нужен.

Deff 03.07.2012 12:49

autosoft,
Пример Выше

autosoft 03.07.2012 12:56

Пример Выше
Не работает этот пример. Ни в Opera12 (Linux) ни в Opera12 (Windows).

Событе onblur в Opera при переходе с input на div не настает.

bes 03.07.2012 15:35

Почему не настаёт, настаёт, можно проверить, пощёлкав на Tab, или выбрать какой-нибудь файл в опере (в хроме это не прокатит), вот если в опере файл не выбрать обработчик onfocus не сработает (в хроме по-любому не сработает), onblur соответственно тоже.

Deff 03.07.2012 15:44

Цитата:

Сообщение от bes
вот если в опере файл не выбрать обработчик onfocus не сработает

у мну всё работает версия 9.5 10.5 11.5

bes 03.07.2012 15:52

Цитата:

Сообщение от Deff
у мну всё работает версия 9.5 10.5 11.5

да, всё чётко и так работает, значит я где-то блажанул, пока экспериментировал:)
вот в хроме вообще не пашет, this.focus() не помогает для input type="file"

bes 03.07.2012 16:35

Для хрома, оперы и FF пока лучший вариант
<input type=file onclick='dofocus()' onchange="this.focus()" onblur='doblur()'>

в IE возникает лишний вызов onblur

autosoft 03.07.2012 17:18

Хорошо. Тогда все по-порядку (по примеру который дал 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.

bes 03.07.2012 17:48

Цитата:

Сообщение от autosoft
Во всех браузерах (кроме Opera) на 6-м шаге инициируется событие onblur первого input.
В Opera - нет. Тестировал на Opera 11 и Opera 12.

Раз нужного эффекта нет, надо искать пути его создания.
Ответ на вопрос "Почему нет?" - "Потому что так сделали!" (в IE тоже много чего есть, чего нет в других браузерах, и наоборот).

devote 03.07.2012 17:51

Цитата:

Сообщение от autosoft
Во всех браузерах (кроме Opera) на 6-м шаге инициируется событие onblur первого input.
В Opera - нет. Тестировал на Opera 11 и Opera 12.

Да вы правы, это Баг в Опере, надо будет репорт отправить.
<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>
по примеру видно что блюр работает но только на последнем инпуте

bes 03.07.2012 18:04

devote, тогда уж и про хром отправлять, там при помощи мыши фокус вообще не установить.:)

autosoft 03.07.2012 23:34

Спасибо всем за ответы. Наверное это действительно баг.

По поводу 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>

Deff 03.07.2012 23:55

<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>

autosoft 04.07.2012 00:03

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 как не было так и нет.

Deff 04.07.2012 00:14

<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>

devote 04.07.2012 00:35

Deff,
чего бы ты не лепил, но тот вариант реально Баг, я отправил репорт в Оперу. Дальше видно будет что к чему.

Deff 04.07.2012 00:38

devote,
Да баг багом, но обычно прожект доделывают не дожидаясь правки софта?
В принципе <button> стилем под div заделать

autosoft 04.07.2012 00:47

Спасибо всем за ответы! Я как раз и с 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 почему-то нет.

Deff 04.07.2012 00:57

autosoft,
Цитата:

Сообщение от autosoft
Почему он нужен? <input type=file> на странице невидим и сам находится в div.

Собственно вариант задачи достаточно стадартный - <input type=file>
сделать pozition:absolute; z- index:-100, а фокусироваться на некой кнопке - которая и вызывает загрузку( передает событие onclick на <input type=file>

autosoft 04.07.2012 01:01

Цитата:

Сообщение от Deff (Сообщение 186150)
Deff
Да баг багом, но обычно прожект доделывают не дожидаясь правки софта?

Я решил пока в Opera красоту не наводить. Просто обыграть ее и все.
Но для единого стиля интерфейса конечно все равно нужно все в порядок привести.
Тут и правда похоже подождать нужно. Если это действительно Баг то видимо его исправят.

Deff 04.07.2012 01:09

autosoft,
Имею отрицательный Опыт, в феврале репортавал - баг до сих пор не исправлен

devote 04.07.2012 01:28

Цитата:

Сообщение от autosoft
По-сути этот div - стилизованная кнопка для загрузки файлов.

Ты про это имел ввиду чтоль? Дык тут и скрипт не нужен:
<!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>

devote 04.07.2012 01:29

Цитата:

Сообщение от Deff
в феврале репортавал - баг до сих пор не исправлен

что за баг?

autosoft 04.07.2012 01:32

Цитата:

Сообщение от Deff (Сообщение 186154)
сделать pozition:absolute; z- index:-100, а фокусироваться на некой кнопке - которая и вызывает загрузку( передает событие onclick на <input type=file>

Пробовал и так.
Вот пример:
<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() на влияет. Тут на форуме уже обсуждалось.

Deff 04.07.2012 01:37

Цитата:

Сообщение от devote
что за баг?

Ти видел - про innerHTML и многo &lt;img src=

devote 04.07.2012 01:39

Цитата:

Сообщение от Deff
Ти видел - про innerHTML и многo &lt;img src=

видел, но ничего там не понял если честно.. может и разрабы тебя не поняли? Номер репорта кинь, попробую выяснить статус твоего репорта.

Deff 04.07.2012 01:39

Цитата:

Сообщение от autosoft
Если бы можно было запретить <input type=file> принимать фокус то было бы то что нужно

=================

Цитата:

Сообщение от Deff
Собственно вариант задачи достаточно стадартный - <input type=file>
сделать pozition:absolute; z- index:-100, а фокусироваться на некой кнопке


autosoft 04.07.2012 01:53

Цитата:

Сообщение от devote (Сообщение 186158)
Ты про это имел ввиду чтоль? Дык тут и скрипт не нужен:

Да. А вся суть была в этом:
Цитата:

Сообщение от devote (Сообщение 186158)
.file_field input[type="file"]:focus ~ div

Это то, что было нужно!

devote 04.07.2012 02:03

Немного поправил пример выше, в ИЕ косячно работал

devote 04.07.2012 02:45

вот полностью рабочий пример, с селектором 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.