source: Dev/branches/rest-dojo-ui/client/dojox/rails.js @ 257

Last change on this file since 257 was 256, checked in by hendrikvanantwerpen, 13 years ago

Reworked project structure based on REST interaction and Dojo library. As
soon as this is stable, the old jQueryUI branch can be removed (it's
kept for reference).

File size: 4.7 KB
Line 
1dojo.provide("dojox.rails");
2dojo.require("dojo.NodeList-traverse");
3
4dojox.rails.live = function(selector, evtName, fn){
5        if (dojo.isIE && evtName.match(/^(on)?submit$/i)){
6                dojox.rails.live(selector, "click", function(evt){
7                        var target = evt.target, tag = target.tagName.toLowerCase();
8                        if ((tag == "input" || tag == "button") && dojo.attr(target, "type").toLowerCase() == "submit"){
9                                 var form = dojo.query(target).closest("form");
10                                 if (form.length){
11                                        var h = dojo.connect(form[0], "submit", function(evt){
12                                                dojo.disconnect(h);
13                                                fn.call(evt.target, evt);
14                                        });
15                                }
16                        }
17                });
18        }else{
19                dojo.connect(dojo.body(), evtName, function(evt){
20                        var nl = dojo.query(evt.target).closest(selector);
21                        if (nl.length){
22                                fn.call(nl[0], evt);
23                        }
24                });
25        }
26};
27
28dojo.ready((function(d, dr, dg){
29        return function() {
30                var q = d.query, live = dr.live,
31                                csrfToken = q("meta[name=csrf-token]").attr("content"),
32                    csrfParam = q("meta[name=csrf-param]").attr("content");
33
34                var createFormForLink = function(url, method){
35                        var form = '<form style="display:none" method="post" action="'+ url +'">' +
36                                '<input type="hidden" name="_method" value="'+ method +'" />' +
37                                '<input type="hidden" name="'+ csrfParam +'" value="'+ csrfToken +'" />' +
38                                '</form>';
39                        return dojo.place(form, dojo.body());
40                };
41
42                var disable = function(elements){
43                        d.forEach(elements, function(node){
44                                if (!d.attr(node, "disabled")){
45                                        var attr = node.tagName.toLowerCase() == "input" ? "value" : "innerHTML";
46                                        var message = d.attr(node, "data-disable-with");
47                                        var originalValue = d.attr(node, attr);
48                                        d.attr(node, "disabled", true);
49                                        d.attr(node, "data-original-value", originalValue);
50                                        d.attr(node, attr, message);
51                                }
52                        });
53                };
54
55                var typeMap = {
56                        "text":                  "text",
57                        "json":                  "application/json",
58                        "json-comment-optional": "text",
59                        "json-comment-filtered": "text",
60                        "javascript":            "application/javascript",
61                        "xml":                   "text/xml"
62                };
63
64                var handleRemote = function(evt){
65                        var el = evt.target, tag = el.tagName.toLowerCase();
66                        var content = tag.toLowerCase() == "form" ? d.formToObject(el) : {},
67                                        type   =  d.attr(el, "data-type") || "javascript",
68                                        method = (d.attr(el, "method")    || d.attr(el, "data-method") || "get").toLowerCase(),
69                                        url    =  d.attr(el, "action")    || d.attr(el, "href");
70
71                        if (tag != "form" && method != "get"){
72                                        el = createFormForLink(url, method);
73                                        method = "POST";
74                        }
75                        evt.preventDefault();
76
77
78                        // ajax:loading, ajax:loaded, and ajax:interactive are not supported
79                        d.publish("ajax:before", [el]);
80                        var deferred = d.xhr(method, {
81                                url:      url,
82                                headers:  { "Accept": typeMap[type] },
83                                content:  content,
84                                handleAs: type,
85                                load:             function(response, ioArgs) {d.publish("ajax:success",  [el, response, ioArgs]);},
86                                error:    function(response, ioArgs) {d.publish("ajax:failure",  [el, response, ioArgs]);},
87                                handle:   function(response, ioArgs) {d.publish("ajax:complete", [el, response, ioArgs]);}
88                        });
89                        d.publish("ajax:after", [el]);
90                };
91
92                var handleEnable        = function(el){
93                        q("*[data-disable-with][disabled]", el).forEach(function(node){
94                                var attr = node.tagName.toLowerCase() == "input" ? "value" : "innerHTML";
95                                var value = d.attr(node, "data-original-value");
96                                d.attr(node, "disabled", false);
97                                d.attr(node, "data-original-value", null);
98                                d.attr(node, attr, value);
99                        });
100                };
101
102                var handleDataMethod = function(evt){
103                        var el = evt.target, form = createFormForLink(el.href, dojo.attr(el, "data-method"));
104                        evt.preventDefault();
105                        form.submit();
106                };
107
108                var handleFormSubmit = function(evt){
109                        var el = evt.target, elements = q("*[data-disable-with]", el);
110                        if (elements.length){ disable(elements); }
111                        if (d.attr(el, "data-remote")){
112                                evt.preventDefault();
113                                handleRemote(evt);
114                        }
115                };
116
117                var handleConfirm = function(evt){
118                        var proceed = dg.confirm(d.attr(evt.target, "data-confirm"));
119                        if (!proceed){
120                                evt.preventDefault();
121                        }else if (d.attr(evt.target, "data-remote")){
122                                handleRemote(evt);
123                        }
124                };
125
126                // Register data-{action} elements.      Order is important since the return values
127                // from previously called functions in the connect chain influence whether
128                // or not the next function in the chain is called.
129
130                // Register data-confirm elements
131                live("*[data-confirm]", "click", handleConfirm);
132
133                // data-disable-with only applies to forms
134                d.subscribe("ajax:complete", handleEnable);
135
136                // Register data-remote elements
137                live("a[data-remote]:not([data-confirm])", "click", handleRemote);
138                live("a[data-method]:not([data-remote])", "click", handleDataMethod);
139
140                // Handle form submits
141                live("form", "submit", handleFormSubmit);
142        };
143})(dojo, dojox.rails, dojo.global));
Note: See TracBrowser for help on using the repository browser.