[256] | 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)); |
---|