1 | dojo.provide("dojox.rails"); |
---|
2 | dojo.require("dojo.NodeList-traverse"); |
---|
3 | |
---|
4 | dojox.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 | |
---|
28 | dojo.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)); |
---|