rails.js 5.1 KB

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