Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Передача параметров в колбэки и дальнейшее их вешанье на события. (https://javascript.ru/forum/misc/20657-peredacha-parametrov-v-kolbehki-i-dalnejjshee-ikh-veshane-na-sobytiya.html)

Gremlin 12.08.2011 15:37

Передача параметров в колбэки и дальнейшее их вешанье на события.
 
Не могу понять как передать параметры в коллбэки и повесить колбэки на события. Т.е. если у колбэка есть параметры, то он срабатывает не по наступлению события, мгновенно после загрузки страницы.
Не получается это сделать ни на чистом JavaScript, ни на jQuery.
Например. есть некая функция
methodName: function(par1,par2,callbackName){
$('#someId').bind('click',callbackName);         
}


если в параметр callbackName вошла функция без параметров, то она запустится по наступлению события клика на someId, а если в параметр callbackName вошла функция с параметрами, то она запускается мгновенно.
Уже испробовал следующие варианты:
$('#someId').click(myCallback);
$('#someId').Click = myCallback;
$('#someId').attr('onClick',myCallback); $('#someId').bind('click',myCallback);

Ничего не выходит.
Вызвать после наступления события функцию с параметрами помогло только следующее:
<button onclick="SomeObject.methodName(<?=$par1?>, <?=$par1?>)">doSomethind</button>

Знаю что это не очень красиво, что нельзя мешать JS и HTML, но это единственный рабочий способ, который я нашел. К тому-же ВКонтакте делаются так-же, суда по просмотру исходного кода.

Но как в функцию передать колбэк с параметрами и повесить его на событие ВНУТРИ функции, в которую он передается - не могу понять :help: . Этот гад - колбэк запускается мгновенно.
Помогите, кто сталкивался с такой задачей.

devote 12.08.2011 15:54

methodName: function(par1,par2,callbackName){ 
    $('#someId').bind('click',function(){
        callbackName(par1, par2);
    });
}

Gremlin 12.08.2011 17:24

К сожалению этот способ не помогает - все немного сложнее.
Задача - создать окно, аналогичное по функциям Джаваскриптовскому Confirm. Но чтобы оно было красивое ))). Функция получает в себя строки, которые будут выводитья в окне, и callback-функцию, которая будет быполняться в случае нажатия на кнопку подстверждения.
Вот функция вывода окна:
areYouSure: function(title,question,okText,cancelText,myCallback){
        $.ajax({	
            url: "/views/V_Common/V_AreYouSure.php",	//получаем с сервака ХТМЛ-код будущего окна
            dataType: "html", 
            success: function(data) {
                var sureBox = $(data); //начинаем создавать ДОМ-Элемент
                sureBox.attr('title',title); 
                sureBox.find('p').text(question);
                sureBox.find('#ok').text(okText);
                sureBox.find('#ok').bind('click',myCallback); /*вешаем колбэк, на кнопку ОК (который, меня уже задолбал сразу запускаться)*/
                sureBox.find('#ok').click(function(){sureBox.dialog( "close" );});
                sureBox.find('#cancel').text(cancelText);
                sureBox.find('#cancel').click(function(){sureBox.dialog( "close" );});
                sureBox.appendTo($('body')); /*Запихиваем новый элемент в ДОМ и делаем из него выпадающее окошко при помощи jQuery UI*/
                sureBox.dialog({resizable: false,
                        draggable: false,
                        modal: true,
                        show: 'fade',
                        hide: 'fade',
                        position: ['center',180]
                });
            },
            error: function (XMLHttpRequest, textStatus, errorThrown){
               Common.makeAlert('AJAX не прокатил', 'Какая-то ошибка');
            }
        });
    }

Простой пример использования данной функции:
askLogout: function(){
        this.areYouSure('Предупреждение', 'Вы уверенны что хотите выйти?', 'Выйти', 'Нет', this.logout())        
    },
    logout: function(){
        document.location.href = "/logout/";
    },


Пример использования чуть посложнее:

Common.areYouSure('Предепреждение', 
                                        'После удаления группу будет невозможно восстаеновить.Вы уверены что хотите удалить эту группу?',
                                        'Удалить группу', 'Отмена',
                                        Groups.destroy(id_group));

destroy: function(id_group){
        //alert('Удалялка группы' + id_group);
        $.ajax({
            type: "POST",		
            url: "/index.php?controller=C_Groups&method=destroyGroup",	
            data: 'id_group=' + id_group,
            dataType: "xml", 
            success: function(data) {
                var canDestroy = $(data).find('canDestroy').text();
                switch (canDestroy) {
                    case 'yes':
                        Common.makeAlert('Поздравляем!', 'Вы удалили данную группу');
                        break;
                    case 'notOwner':
                        Common.makeAlert('Предупреждение!', 'Вы не можете удалить эту группу потому-что не являетесь ее владельцем');
                        break;    
                    default:
                        break;
                }

            },
            error: function (XMLHttpRequest, textStatus, errorThrown){
               Common.makeAlert('AJAX не прокатил', 'Какая-то ошибка');
            }
        });
    }

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

Пока-что я нашел такой рабочий способ вызова, но он не очень хорош:
askLogout: function(){
        this.areYouSure('Предупреждение', 
                               'Вы уверенны что хотите выйти?', 
                               'Выйти', 
                               'Нет', 
                               function(){Common.logout()})        
    },

Данный способ плох по следующей причине:
logout и areYouSure являются методами одного и того-же обьекта common. Приходиться вызывать метод текущего объекта не по-человечески через this (this.logout()), а через конкретно его имя (Common.logout()), что не очень-то красиво.

Я даже вопрос немного переформулировал:

Как правильно и красиво передать внутрь функции А параметром функцию Б в виде колбека, чтобы выполнилось следующее:
1 - Функция Б (колбэк) будет подписана на событие внутри функции А
2 - Функция Б может оказатья любой, следовательно количество передаваемых параметров в функцию Б может быть различное.

devote 12.08.2011 17:47

погодь, тебе нужно просто передать параметр this ?
sureBox.find('#ok').bind('click',function(){
    myCallback.call( Common );
    // или
    // myCallback.apply( Common, arguments );
});

Gremlin 12.08.2011 18:58

Нет, параметр this передавать не нужно.
Мне нужно было следующее (уже сделал что хотел:dance: ):
Так не работало и вызывало метод не дожидаясь события
Common.areYouSure('Предепреждение',
                           'После удаления группу будет невозможно восстаеновить.Вы уверены что хотите удалить эту группу?',
                           'Удалить группу', 'Отмена',
                           Groups.destroy(id_group));


Так работало, но код выглядел как-то корявенько
Common.areYouSure('Предепреждение', 
                                        'После удаления группу будет невозможно восстаеновить.Вы уверены что хотите удалить эту группу?',
                                        'Удалить группу', 'Отмена',
                                        function(){Groups.destroy(id_group)});



А так стало аккуратно выглядеть и при этом работать как нужно :victory: .
Common.areYouSure('Предепреждение', 
                                        'После удаления группу будет невозможно восстаеновить.Вы уверены что хотите удалить эту группу?',
                                        'Удалить группу', 'Отмена',
                                        Groups.destroy.call(id_group));


Тем не менее большое спасибо за советы тебе, Devote :thanks: . Ты натолкнул меня на мысль передать параметр не в скобках а через Call. С ним все заработало как и требовалось.
Хотя осталось смутное предчувствие по поводу этого хитрого метода call : насколько я понял, он необходим как-раз для передачи параметров в функции - колбэки. Но помоему я неправильно понял :-? ...
В справочнике на этом сайте есть его описание, но чет не могу понять полностью его предназначение. Не мог бы ты подсказать, как говориться, на пальцах, для чего он еще нужен? :)

devote 12.08.2011 19:46

Groups.destroy.call(id_group)
И это работает??:blink: Я удивлен, обычно первым параметром передается то кем будет this

а вообще он нужен скажем вот:
function myFunc( myParam ) {
    alert( this ); // это прототип объекта qwerty
    alert( myParam ); // 'param1'
}

(function(){
    var qwerty = function( callback ) {
        return new qwerty.prototype.init( callback );
    }
    qwerty.prototype = {
        constructor: qwerty,
        init: function( callback, param ) {
            callback.call( this, 'param1', 'param2' );
            return this;
        },
        test: function( callback ) {
            callback.apply( this, arguments );
            return this;
        }
    }
    qwerty.prototype.init.prototype = qwerty.prototype;
    window.qwerty = qwerty;
})();


qwerty( myFunc ).test( function(){
    alert( this ); // это прототип объекта qwerty
    alert( Array.prototype.slice.call( arguments, 0 ).splice(1) ); // 'arg1', 'arg2', 'arg3'
}, 'arg1', 'arg2', 'arg3');
вообщем через нее можно передавать аргументы совершенно любое количество в любую функцию

melky 12.08.2011 20:13

Цитата:

Сообщение от devote (Сообщение 120136)
Groups.destroy.call(id_group)
И это работает??:blink: Я удивлен, обычно первым параметром передается то кем будет this

интересно получилось. хотя, в JS всё - объекты. может ли это стать паттерном ?

осталось подумать,как это можно использовать.

(function(){ alert(this[0]) }).call(["hello!"]);

iterator = function(a,b){ alert(a+b) };

(function(a){ for(var i in this) a(i,this[i]); }).call({" one ":" hello "},iterator);


удивляюсь просто, нигде такого ещё не встречал

devote 12.08.2011 20:19

(function(){ alert(this); alert(arguments[0]) }).call("hello", "World!!!");

Gremlin 12.08.2011 21:29

Пока не поздно - отпишусь. Все как работало криво, так и работает криво :-E . Буду дальше пытаться через call передать...

devote 12.08.2011 21:35

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

Gremlin 12.08.2011 22:50

В общем, единственный найденный мной способ передачи параметра в функцию-колбэк вот такой.

Common.areYouSure('Предепреждение',
                                        'Текст вопроса?',
                                        'Удалить ', 'не удалять',
                                        function(){Groups.destroy(id_group)});

Вся соль в этой строчке: если параметром передавать это, то колбэк запускается по наступолению события, что и требовалось.
function(){Groups.destroy(id_group)}


а если параметром передавать это, то колбэк запускается сразу при загрузке страницы, что изначально было проблемой.
Groups.destroy(id_group)


У меня все таким образом завелось. Пардон за бурю в стакане )))

Да, вот еще что: пример сделать не могу в рамках этого форума, т.к. запустить можно либо отдельно ХТМЛ, либо отдельно Яваскрипт. А у меня колбэк должен привязываться к событию онКлик на элемент ХТМЛ.

devote 12.08.2011 22:57

areYouSure: function(title, question, okText, cancelText, myCallback, args) {
//.... многа кода
    sureBox.find('#ok').bind('click', function() {
        myCallback.apply( this, args );
    });
// .... еще кода
}

function mycallbackfunc() {
    alert( Array.prototype.slice.call( arguments, 0 ) );
}

Common.areYouSure('blabla', 
                           'blabla blabla', 
                           'Удалить blabla', 'Отмена blabla', 
                           mycallbackfunc, [param1, param2, ... и т.д. ]);

devote 12.08.2011 23:02

Цитата:

Сообщение от Gremlin
запустить можно либо отдельно ХТМЛ

он же и яваскрипт запускает тот что в теге скрипт :)

devote 12.08.2011 23:04

<div>Я просто HTML</div>
<script type="text/javascript">
   alert("А я JavaScript =)");
</script>

Gremlin 13.08.2011 01:00

Блин, точно, можно ))

Gremlin 13.08.2011 02:01

Сделал как в посте 12. Сделал по образу и подобию с 1-й по 7-ю строки и с 13-й по 16-ю. Так тоже работает:thanks: areYouSure стала немножечкого запутанее выглядеть, но зато её вызов стал куда приятнее :) Нагляднее варианта ещё не встречал.

Только вот эта функция взорвала мозг:
function mycallbackfunc() {
    alert( Array.prototype.slice.call( arguments, 0 ) );
}

У нее в скобках не указаны входящие аргументы: получается что при использовании apply входящие аргументы могут не указываться в функции? Они прямо внутрь нее без указания залетают что-ли? :-?

И что эта за конструкция внутри алерта такая убийственная??? :blink:
Насколько я понял (предварительно погугливши), ее задача превратить полученный обьект с параметрами в обычный массив для возможности дальнейшего его вывода. Но вот главная непонятка: что это за параметр такой arguments? Это какая-то зарезервированная входящая переменная(обьект), в которой находятся все переданные call-ом параметры? Думаю что да, но не уверен. Пробовал вставлять эту строку в любую из своих вызываемых функций - она действительно выводит список аргументов.


И следовательно напрашивается новый вопрос: как лучше и правильнее получать аргументы внутри вызываемой функции: через указание аргументов в скобках после слова function, или получать при помощи этого хитрого обьекта arguments, манипуляции над которым проводятся в строке 10?

devote 13.08.2011 06:06

Цитата:

Сообщение от Gremlin
в которой находятся все переданные call-ом параметры? Думаю что да, но не уверен.

Можешь быть уверенным =)
Цитата:

Сообщение от Gremlin
через указание аргументов в скобках после слова function, или получать при помощи этого хитрого обьекта arguments

А это уже от желания зависит )

Gremlin 13.08.2011 07:54

Огромное спасибо за помощь :) Все таки удалось понять друг-друга. Буду писать дальше. :write:


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