okno jQuery UI zamiast alert () dla atrybutu rails 3 Data-confirm

W Rails 3, podanie parametru: confirm do link_to wypełni atrybut data-confirm odnośnika. Spowoduje to wywołanie alertu JS () po kliknięciu łącza.

Używam adaptera rails jQuery UJS ( https://github.com/rails/jquery-ujs ). odpowiedni kod z rails.js to:

$('body').delegate('a[data-confirm], button[data-confirm], input[data-confirm]', 'click.rails', function () {
    var el = $(this);
    if (el.triggerAndReturn('confirm')) {
        if (!confirm(el.attr('data-confirm'))) {
            return false;
        }
    }
});

I

triggerAndReturn: function (name, data) {
        var event = new $.Event(name);
        this.trigger(event, data);

        return event.result !== false;
    }

Chciałbym wiedzieć, jak można to zmodyfikować, aby zamiast tego uzyskać okno dialogowe jQuery (np. okno dialogowe jQuery UI ) umożliwiające użytkownikowi potwierdzenie albo odwołaj.

Moja znajomość JavaScript nie jest wystarczająca, aby osiągnąć to elegancko. Moim obecnym podejściem byłoby po prostu przepisanie $('body').funkcja delegate () zamiast tego tworzy instancję lightbox. Wyobrażam sobie jednak, że istnieje bardziej skuteczne podejście niż to.

Author: Sai Perchard, 2010-12-12

5 answers

Właśnie dodałem zewnętrzne API do Rails jquery-ujs dla dokładnie tego rodzaju personalizacji. Możesz teraz tworzyć szyny.js używa niestandardowego okna dialogowego potwierdzenia poprzez podłączenie (i ponowne zapisanie 1 linii) funkcji $.rails.allowAction.

Zobacz mój artykuł, Rails jQuery UJS: Now Interactive , aby uzyskać pełne wyjaśnienie z przykładami.

EDIT: począwszy od tego zatwierdzenia , przeniosłem confirm funkcję dialogową do obiektu $.rails, aby można było go teraz jeszcze łatwiej modyfikować lub zamieniać. Np.

$.rails.confirm = function(message) { return myConfirmDialog(message); };
 13
Author: jangosteve,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-08 17:27:45

Jak wspomnieli inni, nie możesz użyć okna dialogowego jQuery, ponieważ $.rails.confirm musi zostać zablokowane, dopóki nie zwróci odpowiedzi użytkowników.

Możesz jednak nadpisać $.rails.allowAction w swoim pliku application.js w następujący sposób:

$.rails.allowAction = function(element) {
        var message = element.data('confirm'),
        answer = false, callback;
        if (!message) { return true; }

        if ($.rails.fire(element, 'confirm')) {
                myCustomConfirmBox(message, function() {
                        callback = $.rails.fire(element,
                                'confirm:complete', [answer]);
                        if(callback) {
                                var oldAllowAction = $.rails.allowAction;
                                $.rails.allowAction = function() { return true; };
                                element.trigger('click');
                                $.rails.allowAction = oldAllowAction;
                        }
                });
        }
        return false;
}

function myCustomConfirmBox(message, callback) {
        // implement your own confirm box here
        // call callback() if the user says yes
}

Działa poprzez natychmiastowe zwrócenie false, dzięki czemu skutecznie anuluje Zdarzenie kliknięcia. Jednak twoja niestandardowa funkcja może następnie wywołać oddzwanianie, aby faktycznie podążać za linkiem / przesłać formularz.

 15
Author: Marc Schütz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-24 12:04:50

Nie rozumiem, dlaczego musisz używać okna dialogowego jQuery, gdy funkcja JavaScript confirm() nadal będzie działać poprawnie. Zrobiłbym coś takiego:

$('a[data-confirm]').click(funciton() {
  confirm($(this).data("confirm"));
});

Jeśli zamiast tego chcesz użyć okna dialogowego, jest to trochę inne. Możesz jednorazowo każde okno dialogowe, które chcesz, lub prawdopodobnie możesz przyjąć jednolitą aplikację podejścia, tak aby Twoje rails.js lub Twoje podanie.js może obsłużyć każdą instancję okna dialogowego. Na przykład, potrzebujesz czegoś takiego na swoim Strona:

<a class="dialogLauncher">The link that creates your dialog</a>
<div class="dialog" title="My confirmation title" style="display:none">
  <p>My confirmation message</p>
</div>

Wtedy w Twoim js:

$('.dialogLauncher').click(function() {
  var dialog = $(this).next('.dialog');
  dialog.dialog();
})

Jeśli chcesz jeszcze bardziej dostosować swoje okno dialogowe, sprawdź ten przykład.

Edit

Teraz, gdy o tym myślę, byłaby to dobra okazja dla niestandardowego konstruktora formularzy. Możesz nadpisać jeden ze swoich tagów linków Rails do wyjściowego html, podobnego do tego, co jest wymienione powyżej, gdy występuje określony atrybut, np. :dialog => true. Na pewno w ten sposób Railsy to zrobi. Możesz dodać inne opcje do Twój tag, jak tytuł okna dialogowego itp.

Edit

Jeszcze lepiej, zamiast :dialog => true Użyj :confirm => "my confirm message" tak jak normalnie, ale w nadpisaniu link_to użyjesz opcji :confirm, aby utworzyć okno dialogowe html, którego potrzebuje jQuery, usunąć tę opcję, a następnie wywołać super.

 0
Author: Samo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-12-15 20:51:13

Tak to działa. Proszę sugerować wszelkie poprawki / ulepszenia

#

W szynach.js

#
// Added new variable
var deleteConfirmed = false;

// Changed function to use jquery dialog instead of confirm   
$('body').delegate('a[data-confirm], button[data-confirm], input[data-confirm]', 'click.rails', function () {
        var el = $(this);
        /*
        if (el.triggerAndReturn('confirm')) {

            if (!confirm(el.attr('data-confirm'))) {
                return false;
            }

        }
        */

        if (el.triggerAndReturn('confirm')) {    

            if(deleteConfirmed) {
                deleteConfirmed = false;
                return true;
            }

            $( "#dialog-confirm" ).dialog("option", "buttons",
                    {
                        "Delete": function() {
                            $( this ).dialog( "close" );
                            deleteConfirmed = true;
                            el.trigger('click');   
                            return true;
                        },
                        Cancel: function() {
                            $( this ).dialog( "close" );
                            return false;
                        }
                    }
            );

            $( "#dialog-confirm" ).dialog("open");

            return false;

        }


    });
#

W aplikacji.js

#
//Ensure confirm Dialog is pre-created
jQuery(function () {


    $( "#dialog-confirm" ).dialog({
        autoOpen: false,
        resizable: false,
        height:140,
        modal: true     
    });

});
#

W układzie.html Alt możesz umieścić ten div w dowolnym miejscu w wygenerowanym html

#
        <div id='dialog-confirm' title='Confirm Delete'> 
          <p> 
            <span class='ui-icon-alert' style='float:left; margin:0 7px 20px 0;'> 
              This item will be permanently deleted. Are you sure?
            </span> 
          </p> 
        </div> 
 0
Author: Mohith Thimmaiah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-17 19:02:18

Najbardziej podobała mi się odpowiedź od @ Marc Schütz na temat nadpisywania $.rails.allowAction wszystkiego, co znalazłem w Internecie - ale nie jestem wielkim fanem nadpisywania funkcji w allowAction, ponieważ jest ona używana w całej bazie kodowej jQuery-ujs (co jeśli są skutki uboczne? Lub jeśli źródło tej metody ulegnie zmianie w przyszłej aktualizacji?).

Zdecydowanie najlepszym podejściem byłoby zwrócenie obietnicy... Ale nie wygląda na to, że to się stanie w najbliższym czasie.]} :(

Więc... Zwijałem własną metodę, o której myślę, że warto wspomnieć, ponieważ jest ona lżejsza od metody opisanej powyżej. Nie porywa allowAction. Tutaj jest:

# Nuke the default confirmation dialog. Always return true 
# since we don't want it blocking our custom modal.
$.rails.confirm = (message) -> true

# Hook into any data-confirm elements and pop a custom modal
$(document).on 'confirm', '[data-confirm]', ->
  if !$(this).data('confirmed')
    myCustomModal 'Are you sure?', $(this).data('confirm'), =>
      $(this).data('confirmed', true)
      $(this).trigger('click.rails')
    false
  else
    true

# myCustomModal is a function that takes (title, message, confirmCallback)
Jak to działa? Cóż, jeśli spojrzysz na źródło , zauważysz, że metoda allowAction zatrzyma się, jeśli confirm event zwróci fałszywą wartość. Więc przepływ wynosi:
  1. użytkownik kliknie link lub przycisk z atrybutem data-confirm. Na linku lub przycisku nie ma data-confirmed, więc wpadamy w najpierw jeśli block, wyzwalamy nasz Niestandardowy modal i zwracamy false, zatrzymując w ten sposób kontynuację akcji w programie obsługi kliknięć ujs.
  2. Użytkownik potwierdza w modalu niestandardowym, a callback jest wyzwalany. Zapisujemy stan elementu poprzez data('confirmed', true) i ponownie wywołujemy to samo zdarzenie, które zostało wywołane wcześniej (click.rails).
  3. tym razem confirm event spadnie do else bloku (ponieważ data('confirmed') jest prawdziwe) i zwróci true, powodując, że allowAction blok zostanie oceniony na true.

I ' m oczywiście brakuje mi nawet innych sposobów, które mogą to jeszcze uprościć, ale myślę, że jest to naprawdę elastyczne podejście do uzyskania niestandardowego modalu potwierdzenia bez łamania rdzenia {15]} funkcjonalności.

(również, ponieważ używamy .on() będzie to wiązać się z dowolnymi data-confirm elementami na stronie w czasie ładowania lub w przyszłości, podobnie jak działa .delegate(), w przypadku, gdy się zastanawiasz.)

 0
Author: Mark G.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-29 06:53:18