Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Инкапсуляция, чтение файла и event в firefox (https://javascript.ru/forum/events/30819-inkapsulyaciya-chtenie-fajjla-i-event-v-firefox.html)

platedz 16.08.2012 22:35

Инкапсуляция, чтение файла и event в firefox
 
Здравствуйте, уважаемые специалисты. Очень расчитываю на Вашу помощь и поддержку.

Вот код

topmenu = (function() {

return {
filesload: function(evt,func)
				{ 
				var reader = new FileReader();
				
					var files = evt.target.files; 
							
							

					
						
							reader.onload = function(e) 
					
								{
							
									func(e.target.result,files[0]);
									
								}
								
								
							  reader.readAsArrayBuffer(files[0]);
     
					}, 
				replace: function(s,e)
					{
					
						this[s](event,e);
						
					}
				
	
	}

}());

Если вызвать так, то работает и в опере и хром и файрфоркс
topmenu.sub(document.getElementById("inpField"),"change",function(e)
					{
						
						topmenu.filesload(e,function(s)
						{
							
							alert(s);

						});
						
					});


А так только в хром и опере

topmenu.sub(document.getElementById("inpField"),"change",function(e)
					{
						
						topmenu.replace.call(topmenu,"filesload",function(u,f)
							{
								
					
								alert(u+" = "+f.name);
							
							})
						
					});


Файр фокс выдает event is not defined

Вопрос 1) почему? и как поправить?
Вопрос 2) Как я могу вернуть e.target.result, чтобы потом их обработать? Я так понимаю причина в onload.
Вопрос 3) И последний вопрос касательно инкапсуляции. Какую роль играют в этом коде function(s){}(v) s и v?

oneguy 16.08.2012 23:08

Вы, наверно, неполный код привели - у вас в topmenu нет свойства sub.

vadim5june 16.08.2012 23:12

Цитата:

Сообщение от oneguy (Сообщение 198133)
Вы, наверно, неполный код привели - у вас в topmenu нет свойства sub.

sub это редко встречающейся метод
http://www.w3schools.com/jsref/jsref_sub.asp

oneguy 16.08.2012 23:19

Цитата:

Сообщение от vadim5june (Сообщение 198134)
sub это редко встречающейся метод
http://www.w3schools.com/jsref/jsref_sub.asp

Да, но вы невнимательно посмотрели код. В Object.prototype нет метода sub.

vadim5june 16.08.2012 23:19

Цитата:

Сообщение от platedz
Как я могу вернуть e.target.result, чтобы потом их обработать

Вы же передаете свой callback в нем и обрабатывайте или передайте в другую функцию
в асинхронных процессах вернуть с помощью return нельзя

platedz 16.08.2012 23:20

Код не полный, полный бы здесь не поместился.
Вот sub
sub: function(elem,type,block) 
				{
						try { 
								try {

									elem.addEventListener(type, block, false);

								} catch(e) {

									elem.attachEvent("on"+type, block);

								}
							} catch(e){}



				}

vadim5june 16.08.2012 23:23

Цитата:

Сообщение от oneguy (Сообщение 198138)
Да, но вы невнимательно посмотрели код. В Object.prototype нет метода sub.

извиняюсь это метод String

platedz 16.08.2012 23:25

Цитата:

Сообщение от vadim5june (Сообщение 198139)
Вы же передаете свой callback в нем и обраьатывайте или передайте в другую функцию
в асинхронных процессах вернуть с помощью return нельзя

Может быть есть способ сделать данный процесс синхронным?

oneguy 16.08.2012 23:34

Цитата:

Сообщение от platedz (Сообщение 198142)
Может быть есть способ сделать данный процесс синхронным?

Вы ведь повесили обработчик на onchange. Он по идее должен срабатывать при изменении пользователем значения файлового поля, поэтому он как раз должен быть асинхронным.
Цитата:

Сообщение от platedz
Вопрос 1) почему? и как поправить?

В Фаерфоксе, возможно, не срабатывает потому, что вы использовали глобальную переменную event, а нужно брать событие, как аргумент в обработчике?
Цитата:

Сообщение от platedz
Вопрос 3) И последний вопрос касательно инкапсуляции. Какую роль играют в этом коде function(s){}(v) s и v?

У вас в коде ведь использован такой шаблон, без параментров: function(){}()

vadim5june 16.08.2012 23:35

Цитата:

Сообщение от platedz (Сообщение 198142)
Может быть есть способ сделать данный процесс синхронным?

Это мы сделать не в состоянии
С помощью callback так же удобно все обрабатывается
в первом случае у Вас это function(s){alert(s)}
здесь передавайте свою функцию обработки-в чем проблема?
при этом s это будет e.target.result
можно добавить второй параметр-это будет files[0]
function(s,fl){}

platedz 16.08.2012 23:45

Спасибо за ответы. В данном случае проблема не велика. Т.е. все необходимые действия я могу выполнить и так. Но мне было бы удобнее получить данные, чтобы впоследствии с ними работать.
Больше всего, честно говоря, интересуют вопрос 1 и 3

vadim5june 16.08.2012 23:49

Цитата:

Сообщение от platedz
Какую роль играют в этом коде function(s){}(v) s и v?

s-формальный параметр
v -фактический
рекомендуется писать так (function(s){})(v)

platedz 17.08.2012 00:02

Цитата:

Сообщение от oneguy (Сообщение 198145)
Вы ведь повесили обработчик на onchange. Он по идее должен срабатывать при изменении пользователем значения файлового поля, поэтому он как раз должен быть асинхронным.

Может быть следует использовать другой обработчик, который позволит дождаться загрузки чтения файла. Подскажите, пожалуйста.

Цитата:

Сообщение от oneguy (Сообщение 198145)
В Фаерфоксе, возможно, не срабатывает потому, что вы использовали глобальную переменную event, а нужно брать событие, как аргумент в обработчике?

А как это делается?

Цитата:

Сообщение от oneguy (Сообщение 198145)
У вас в коде ведь использован такой шаблон, без параментров: function(){}()

Я честно говоря совсем недавно познакомился как и инкапсуляцией так и с замыканием. Но сколько не читал на эту тему, так и не понял, для чего использовать данные параметры, что и куда они возвращают. Буду крайне признателен если просвятите, особенно на каком-нибудь простом примере.

platedz 17.08.2012 00:04

Цитата:

Сообщение от vadim5june (Сообщение 198151)
s-формальный параметр
v -фактический
рекомендуется писать так (function(s){})(v)

Разъясните поподробнее пожалуйста, буду очень благодарен.

vadim5june 17.08.2012 00:10

Цитата:

Сообщение от platedz (Сообщение 198161)
Разъясните поподробнее пожалуйста, буду очень благодарен.

(function(s){alert(s)})(5);//5
объявляем функцию и сразу выполняем

vadim5june 17.08.2012 00:19

Цитата:

Сообщение от platedz
topmenu.replace.call

А зачем Вам этот метод нужен?

platedz 17.08.2012 00:21

Цитата:

Сообщение от vadim5june (Сообщение 198163)
(function(s){alert(s)})(5);//5
объявляем функцию и сразу выполняем

Т.е. если я правильно понимаю в данном примере (function(s){alert(s)})(v) мы передаем данные из v в s. Так как видимо передать их из вне мы наверное не можем, учитывая что var s = 5; (function(s){alert(s)})() не работает.
Я все правильно понимаю???

platedz 17.08.2012 00:23

Цитата:

Сообщение от vadim5june (Сообщение 198166)
А зачем Вам этот метод нужен?

Для расширения кругозора. Учусь, так сказать. Только он почему-то не передает event в файрфокс. А как поправить не знаю.

vadim5june 17.08.2012 00:26

Цитата:

Сообщение от platedz (Сообщение 198167)
Т.е. если я правильно понимаю в данном примере (function(s){alert(s)})(v) мы передаем данные из v в s. Так как видимо передать их из вне мы наверное не можем, учитывая что var s = 5; (function(s){alert(s)})() не работает.
Я все правильно понимаю???

Выполняем функция с параметром v
основной смысл что мы не создаем на глобальном уровне имени функции
(не засоряем)
с именем так бы выглядело
function f(s){alert(s)};
f(5);

vadim5june 17.08.2012 00:31

Цитата:

Сообщение от platedz (Сообщение 198168)
Для расширения кругозора. Учусь, так сказать. Только он почему-то не передает event в файрфокс. А как поправить не знаю.

он здесь this[s](event,e);
не определен-но я так и не понял его смысла-ведь он делает тоже что и
filesload только более сложным образом?
Или еще что то?

cyber 17.08.2012 00:32

блин код не читаемые вообще....
вы бы сначала почитали про стиль написания (это не троллинг, говорю как есть)

platedz 17.08.2012 00:45

Цитата:

Сообщение от vadim5june (Сообщение 198169)
Выполняем функция с параметром v
основной смысл что мы не создаем на глобальном уровне имени функции
(не засоряем)
с именем так бы выглядело
function f(s){alert(s)};
f(5);

Спасибо большое. Теперь понятно вроде, хотя практические применения не очень ясны. Например вот это.

http://habrahabr.ru/post/38642/

в частности

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

Пускай у нас есть массив ссылок, и наша задача — сделать так, чтобы при клике на каждую выводился алертом ее порядковый номер. Первое решение, что приходит в голову, выглядит так:
for (var i = 0; i < links.length; i++) {
links[i].onclick = function() {
alert(i);
}
}
На деле же оказывается, что при клике на любую ссылку выводится одно и то же число — значение links.length. Почему так происходит? В связи с замыканием объявленная вспомогательная переменная i продолжает существовать, при чём и в тот момент, когда мы кликаем по ссылке. Поскольку к тому времени цикл уже прошёл, i остаётся равным кол-ву ссылок — это значение мы и видим при кликах.

Решается эта проблема следующим образом:
for (var i = 0; i < links.length; i++) {
(function(i) {
links[i].onclick = function() {
alert(i);
}
})(i);
}
Здесь с помощью еще одного замыкания мы «затеняем» переменную i, создавая ее копию в его локальной области видимости на каждом шаге цикла. Благодаря этому всё теперь работает как задумывалось.

cyber 17.08.2012 00:50

или так=)
for (var i = 0; i < links.length; i++) (function(i) {
links[i].onclick = function() {
alert(i);
}
})(i);

а лучше использовать делегирование

platedz 17.08.2012 01:08

Цитата:

Сообщение от vadim5june (Сообщение 198172)
он здесь this[s](event,e);
не определен-но я так и не понял его смысла-ведь он делает тоже что и
filesload только более сложным образом?
Или еще что то?

topmenu.filesload(e,function(s){alert(s);});

topmenu.replace.call(topmenu,"filesload",function( u,f) { alert(u+" = "+f.name);})

Эти два кода по сути аналогичный, но последний реализован через call

В данном случае мы через call получаем
topmenu["filesload"](e,function(s){ alert(s); });

vadim5june 17.08.2012 01:27

Цитата:

Сообщение от platedz
В данном случае мы через call получаем
topmenu["filesload"](e,function(s){ alert(s); });

Ну да-и зачем это нужно?
Наверное есть какой то смысл и он может и связан с этим event который не везде работает
Вы код откуда взяли?

platedz 17.08.2012 01:33

Цитата:

Сообщение от cyber (Сообщение 198178)
или так=)
for (var i = 0; i < links.length; i++) (function(i) {
links[i].onclick = function() {
alert(i);
}
})(i);

а лучше использовать делегирование

Спасибо за способ. Возьму на заметку.
Насколько я понимаю в указанном мною примере в цикле идет перебор всех ссылок, и назначается каждому событие клик которое выполняет функцию алерт со значением i. Без инкапсуляции значение i после исполнения кода остается глобальным и при вызове функции в алерте вызывается глобальная переменная i.
С инкапсуляцией видимо ей передается не сама переменная, а ее значение, уже после исполнения кода. Я правильно понимаю? Или я чего-то не понимаю?

При этом на вновь созданную ссылку данный код уже не действует, и остается вопрос, как его получить?
for (var i = 0; i < document.links.length; i++) {
(function(i) {
document.links[i].onclick = function() {
alert(i);
var newElem = document.createElement("a");
newElem.href = "#";
newElem.innerHTML = "Новая ссылка";
document.body.insertBefore(newElem, document.body.firstChild);
return false;
}
})(i);
}

С делегированием я к сожалению еще не знаком, если только в джиквери, но думаю, что это не совсем то, или скорее совсем не то.

platedz 17.08.2012 01:36

Цитата:

Сообщение от vadim5june (Сообщение 198186)
Ну да-и зачем это нужно?
Наверное есть какой то смысл и он может и связан с этим event который не везде работает
Вы код откуда взяли?

Код я из головы взял. Просто я пытаюсь реализовать предыдущие замыкания через call. Смысл получить знание.

cyber 17.08.2012 01:38

там получается замыкание , при каждой итерации цикла вызывается функция,а в замыкание значения переменных (как бы правильно сказать) не обнуляются

platedz 17.08.2012 04:47

Спасибо всем ответившим. В принципе остался только вопрос с event. Надеюсь, и на него найдется ответ.

vadim5june 17.08.2012 08:49

Цитата:

Сообщение от platedz
В принципе остался только вопрос с event

а почему Вы event не передаете?
topmenu.replace.call(topmenu,"filesload",e,function(u,f){...
...
replace: function(s,evn,e)
                    {
this[s](evn,e);
 }

platedz 17.08.2012 13:53

Цитата:

Сообщение от vadim5june (Сообщение 198216)
а почему Вы event не передаете?
topmenu.replace.call(topmenu,"filesload",e,function(u,f){...
...
replace: function(s,evn,e)
                    {
this[s](evn,e);
 }

Спасибо, так и сделал. Видимо я думал, что event глобальный объект, который доступен всегда при обращении к event. Т.е. this[s](event,e), определиться из любого места.

Спасибо еще раз

platedz 21.11.2012 18:08

Здравствуйте, подскажите пожалуйста, есть примерно следующий плагин на jquery, те. плагин как и все плагины на jquery, но я никак не соображу как получить доступ к объекту и его методам

(function ($) {
	var C = function () {
		
			defaults = {
			......
			},
			fillRGBFields = function  (a, b) {
			......
			}

	});
})(jQuery);


Как мне сделать что-то навроде for(i in C) alert(i + " : " + C[i])

platedz 01.01.2013 23:59

Подскажите, пожалуйста, а почему

если при инкапсуляции вызвать Блок
return
{
и поставить скобку на новую строку, return не работает

dmitriymar 02.01.2013 00:07

Цитата:

Сообщение от platedz
и поставить скобку на новую строку, return не работает

это особенности . return как раз таки и сработает. :)
то что возвращает return ,должно быть записано в одну строчку с ним. Иначе, перенос интерпретатор\компилятор воспринимает как окончание команды return, воспринимает как- ;

platedz 02.01.2013 00:39

Спасибо за ответ.
Я к тому что for if и тд. Нормально обрабатывают блок, когда { на другой строке, а чем return так отличился?

dmitriymar 02.01.2013 01:06

Цитата:

Сообщение от platedz
Я к тому что for if и тд. Нормально обрабатывают блок, когда { на другой строке, а чем return так отличился?

Цитата:

Сообщение от dmitriymar
это особенности .

Цитата:

Сообщение от dmitriymar
то что возвращает return ,должно быть записано в одну строчку с ним.

Цитата:

Сообщение от dmitriymar
Иначе, перенос интерпретатор\компилятор воспринимает как окончание команды return, воспринимает как - ;


что не ясного в ответе,чтоб задавать вопрос повторно ? что это особенность "языка" с return?
чем отличается особенная ситуация от обычной?
тем, что она особенная -она исключение.

platedz 02.01.2013 01:20

Я понял особенности, просто может еще где-то есть подобные особенности, а я не знаю.

platedz 31.03.2013 21:44

Подскажите, как правильно выполнить следующее

for(var i=0; i<document.getElementsByName("my_name").length; i++)
{
	document.getElementsByName("my_name")[i].onkeyup = function(i)
	{
		console.log(i);
	}
}

Aetae 31.03.2013 22:01

Цитата:

Сообщение от platedz (Сообщение 243608)
Подскажите, как правильно выполнить следующее

for(var i=0; i<document.getElementsByName("my_name").length; i++)
{
	document.getElementsByName("my_name")[i].onkeyup = function(i)
	{
		console.log(i);
	}
}

Хрестоматийный пример для использования замыканий.

Кстати так:
for(var i=0; i<document.getElementsByName("my_name").length; i++){
	document.getElementsByName("my_name")[i].onkeyup = ...
}
делать не рекомендуется, ибо каждую итерацию цикла у вас сначала идёт получение заново всех элементов ByName("my_name"), затем получение заново длины, а после, в теле цикла, ещё раз получение всех элементов ByName("my_name"). Всё это вещи тратящие вычислительное время. В современных браузерах предусмотрено всяческое кеширование подобных случаев на уровне движка, но я бы не рекомендовал слишком уж полагаться на это.
Более экономичный вариант:
for(var i=0, my_name=document.getElementsByName("my_name"), l=my_name.length; i<l; i++){
	my_name[i].onkeyup = ...
}


P.S. Ну и лично мне больше всего нравится для таких случаев использовать обратный перебор:) :
var my_name=document.getElementsByName("my_name"), i=my_name.length; 
while(i--){
	my_name[i].onkeyup = ...
}




Пример: Если не разобрались сами с замыканиями.
for(var i=0, my_name=document.getElementsByName("my_name"), l=my_name.length; i<l; i++){
	my_name[i].onkeyup = function(i){
		return function(){
			console.log(i);
		}
	}(i) 
}

platedz 31.03.2013 22:14

Большое спасибо.
Посмотрел пример и вышло так
for(var i=0; i<document.getElementsByName("my_name").length; i++)
{
	document.getElementsByName("my_name")[i].onkeyup = function(x)
	{
		return function(){console.log(x)}; 
	}(i)
}


Не ясно только, почему не выходит так

for(var i=0; i<document.getElementsByName("my_name").length; i++)
{
	document.getElementsByName("my_name")[i].onkeyup = function(x)
	{
		console.log(x)
	}(i)
}


Буду благодарен за разъяснения


Часовой пояс GMT +3, время: 22:16.