Как определить / использовать $ (this) в скрипте обратного вызова js - PullRequest
0 голосов
/ 04 февраля 2010

Я использую Rails и jQuery, совершая ajax-вызов, инициируемый нажатием ссылки. Я установил файл application.js так, чтобы он выглядел как предложенный здесь , и он прекрасно работает. Проблема в том, как я могу использовать $ (this) в моем файле say .. update.js.erb для представления ссылки, на которую я нажал? Я не хочу присваивать идентификатор каждому, а затем перекомпилировать этот идентификатор в сценарии обратного вызова.

EDIT Чтобы привести простой пример чего-то похожего на то, что я пытаюсь сделать (и гораздо проще объяснить): если пользователь нажимает на ссылку, которая удаляет этот элемент из списка, контроллер обрабатывает обратный вызов и обратный вызов (что здесь обсуждается) удалит элемент, на который я нажал, поэтому в обратном вызове delete.js.erb просто скажет $ (this) .fadeOut (); Вот почему я хочу использовать $ (this), чтобы мне не нужно было присваивать идентификатор каждому элементу (что было бы концом света, просто более подробная разметка)

application.js

jQuery.ajaxSetup({ 'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript,application/javascript,text/html")} })

function _ajax_request(url, data, callback, type, method) {
    if (jQuery.isFunction(data)) {
        callback = data;
        data = {};
    }
    return jQuery.ajax({
        type: method,
        url: url,
        data: data,
        success: callback,
        dataType: type
    });
}

jQuery.extend({
    put: function(url, data, callback, type) {
        return _ajax_request(url, data, callback, type, 'PUT');
    },
    delete_: function(url, data, callback, type) {
        return _ajax_request(url, data, callback, type, 'DELETE');
    }
});

jQuery.fn.submitWithAjax = function() {
    this.unbind('submit', false);
    this.submit(function() {
        $.post(this.action, $(this).serialize(), null, "script");
        return false;
    })
    return this;
};

// Send data via get if <acronym title="JavaScript">JS</acronym> enabled
jQuery.fn.getWithAjax = function() {
    this.unbind('click', false);
    this.click(function() {
        $.get($(this).attr("href"), $(this).serialize(), null, "script");
        return false;
    })
    return this;
};

// Send data via Post if <acronym title="JavaScript">JS</acronym> enabled
jQuery.fn.postWithAjax = function() {
    this.unbind('click', false);
    this.click(function() {
        $.post($(this).attr("href"), $(this).serialize(), null, "script");
        return false;
    })
    return this;
};

jQuery.fn.putWithAjax = function() {
    this.unbind('click', false);
    this.click(function() {
        $.put($(this).attr("href"), $(this).serialize(), null, "script");
        return false;
    })
    return this;
};

jQuery.fn.deleteWithAjax = function() {
    this.removeAttr('onclick');
    this.unbind('click', false);
    this.click(function() {
        $.delete_($(this).attr("href"), $(this).serialize(), null, "script");
        return false;
    })
    return this;
};

// This will "ajaxify" the links
function ajaxLinks(){
    $('.ajaxForm').submitWithAjax();
    $('a.get').getWithAjax();
    $('a.post').postWithAjax();
    $('a.put').putWithAjax();
    $('a.delete').deleteWithAjax();
}

show.html.erb

<%= link_to 'Link Title', article_path(a, :sentiment => Article::Sentiment['Neutral']), :class => 'put' %>

Сочетание этих двух вещей вызовет update.js.erb в рельсах, код в этом файле используется в качестве обратного вызова ajax (в данном случае $ .put)

update.js.erb

// user feedback
$("#notice").html('<%= flash[:notice] %>');

// update the background color
$(this OR e.target).attr("color", "red");

Ответы [ 5 ]

1 голос
/ 19 февраля 2010

jQuery уже обрабатывает проблему this для вас со свойствами события:

$("a").click(function(e){
  e.preventDefault();
  $("#foo").fadeIn(3000, function(){
    $(e.target).text("Foo loaded");
  });
});​​​

Обратите внимание, как я могу вернуться к главной ссылке через event. Это относится ко всем событиям, которые также обрабатываются внутри. Просто дайте им уникальные имена, такие как e2, e3 и т. Д. Больше не нужно постоянно писать еще одну строку var item = $(this), чтобы отслеживать this три события назад.

Онлайн-демонстрация: http://jsbin.com/egelu3/edit

0 голосов
/ 21 апреля 2010

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

Решением было назначить идентификаторы каждому элементу и ссылаться на них.

0 голосов
/ 04 февраля 2010

Если ваш JS идет с сервера, действительно нет никакого способа, которым $ (это) может работать в том же контексте. ближайший вы могли бы получить загрузить какой-то скрипт с сервера и eval это в контексте вашей клиентской стороны функция.

Не соответствует действительности

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

Не думаю, что это ужасно.

Ключом к этой проблеме является функциональная область видимости. Позвольте мне показать вам, что я имею в виду. Вам необходимо создать функцию, которая вызывается перед отправкой вызова XHR. В вашем случае вы делаете это с событием click, поэтому позвольте мне показать вам пример, разработанный специально для вас:

$( '#somelink' ).click( function( )
{
    // this stores the location of the current "this" value
    // into this function, and will available even after we
    // end this function (and will still live while the XHR's
    // callback is being executed

    var theLink = this;

    // fire the AJAX call

    $.post
    (
        'some/url',

        { 'some':'data' }, // optional

        function( )
        {
            // use theLink however you want
            // it'll still be there

            // also, if you're sending in callbacks
            // as variables, you can safely say

            hideAndStore.call( theLink, data );

            // which executes callback( ), overriding
            // "this" with theLink (your DOM node)
            // and sending in the responseText as the
            // first argument
        }
    );
} );

и тогда вы можете сделать свой обратный вызов что-то вроде:

function hideAndStore( response )
{
    // you can safely use "this" as the DOM node
    $( this ).css( { 'display':'none' } );

    // and you can do whatever you wish with the response
    window.globalData = response;
}

где бы вы заставили его делать то, что вы на самом деле хотите, хаха.

Для получения дополнительной информации о функциях в JavaScript, которые изменяют значение «this», ознакомьтесь с .apply и .call в MDC

https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Function/Apply https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Function/Call

0 голосов
/ 18 февраля 2010

Что вы делаете в javascript, который вы отправляете обратно? Может быть, вы можете отправить обратно html или json и поработать с ним в режиме обратного вызова.

$('a:clickable').bind('click', function() {
  var elem = $(this);
  $.ajax({
    url: ...,
    dataType: 'json',
    success: function(data) {
      // elem is still in scope
      elem.addClass(data.class_to_add_to_link);
    }
  });
});
0 голосов
/ 04 февраля 2010

Если ваш JS исходит от сервера, на самом деле нет способа, чтобы $ (this) мог работать в том же контексте. Самое близкое, что вы могли бы получить, - это загрузить некоторый скрипт с сервера и проверить его в контексте вашей функции на стороне клиента.

У меня в основном есть идентификатор для каждого из элементов DOM, которыми я должен манипулировать, и ссылаюсь на них в своих скриптах. Это иногда некрасиво, но альтернативы хуже.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...