176 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			176 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
| (function() {
 | |
|   // Technique from Juriy Zaytsev
 | |
|   // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
 | |
|   function isEventSupported(eventName) {
 | |
|     var el = document.createElement('div');
 | |
|     eventName = 'on' + eventName;
 | |
|     var isSupported = (eventName in el);
 | |
|     if (!isSupported) {
 | |
|       el.setAttribute(eventName, 'return;');
 | |
|       isSupported = typeof el[eventName] == 'function';
 | |
|     }
 | |
|     el = null;
 | |
|     return isSupported;
 | |
|   }
 | |
| 
 | |
|   function isForm(element) {
 | |
|     return Object.isElement(element) && element.nodeName.toUpperCase() == 'FORM'
 | |
|   }
 | |
| 
 | |
|   function isInput(element) {
 | |
|     if (Object.isElement(element)) {
 | |
|       var name = element.nodeName.toUpperCase()
 | |
|       return name == 'INPUT' || name == 'SELECT' || name == 'TEXTAREA'
 | |
|     }
 | |
|     else return false
 | |
|   }
 | |
| 
 | |
|   var submitBubbles = isEventSupported('submit'),
 | |
|       changeBubbles = isEventSupported('change')
 | |
| 
 | |
|   if (!submitBubbles || !changeBubbles) {
 | |
|     // augment the Event.Handler class to observe custom events when needed
 | |
|     Event.Handler.prototype.initialize = Event.Handler.prototype.initialize.wrap(
 | |
|       function(init, element, eventName, selector, callback) {
 | |
|         init(element, eventName, selector, callback)
 | |
|         // is the handler being attached to an element that doesn't support this event?
 | |
|         if ( (!submitBubbles && this.eventName == 'submit' && !isForm(this.element)) ||
 | |
|              (!changeBubbles && this.eventName == 'change' && !isInput(this.element)) ) {
 | |
|           // "submit" => "emulated:submit"
 | |
|           this.eventName = 'emulated:' + this.eventName
 | |
|         }
 | |
|       }
 | |
|     )
 | |
|   }
 | |
| 
 | |
|   if (!submitBubbles) {
 | |
|     // discover forms on the page by observing focus events which always bubble
 | |
|     document.on('focusin', 'form', function(focusEvent, form) {
 | |
|       // special handler for the real "submit" event (one-time operation)
 | |
|       if (!form.retrieve('emulated:submit')) {
 | |
|         form.on('submit', function(submitEvent) {
 | |
|           var emulated = form.fire('emulated:submit', submitEvent, true)
 | |
|           // if custom event received preventDefault, cancel the real one too
 | |
|           if (emulated.returnValue === false) submitEvent.preventDefault()
 | |
|         })
 | |
|         form.store('emulated:submit', true)
 | |
|       }
 | |
|     })
 | |
|   }
 | |
| 
 | |
|   if (!changeBubbles) {
 | |
|     // discover form inputs on the page
 | |
|     document.on('focusin', 'input, select, texarea', function(focusEvent, input) {
 | |
|       // special handler for real "change" events
 | |
|       if (!input.retrieve('emulated:change')) {
 | |
|         input.on('change', function(changeEvent) {
 | |
|           input.fire('emulated:change', changeEvent, true)
 | |
|         })
 | |
|         input.store('emulated:change', true)
 | |
|       }
 | |
|     })
 | |
|   }
 | |
| 
 | |
|   function handleRemote(element) {
 | |
|     var method, url, params;
 | |
| 
 | |
|     var event = element.fire("ajax:before");
 | |
|     if (event.stopped) return false;
 | |
| 
 | |
|     if (element.tagName.toLowerCase() === 'form') {
 | |
|       method = element.readAttribute('method') || 'post';
 | |
|       url    = element.readAttribute('action');
 | |
|       params = element.serialize();
 | |
|     } else {
 | |
|       method = element.readAttribute('data-method') || 'get';
 | |
|       url    = element.readAttribute('href');
 | |
|       params = {};
 | |
|     }
 | |
| 
 | |
|     new Ajax.Request(url, {
 | |
|       method: method,
 | |
|       parameters: params,
 | |
|       evalScripts: true,
 | |
| 
 | |
|       onComplete:    function(request) { element.fire("ajax:complete", request); },
 | |
|       onSuccess:     function(request) { element.fire("ajax:success",  request); },
 | |
|       onFailure:     function(request) { element.fire("ajax:failure",  request); }
 | |
|     });
 | |
| 
 | |
|     element.fire("ajax:after");
 | |
|   }
 | |
| 
 | |
|   function handleMethod(element) {
 | |
|     var method = element.readAttribute('data-method'),
 | |
|         url = element.readAttribute('href'),
 | |
|         csrf_param = $$('meta[name=csrf-param]')[0],
 | |
|         csrf_token = $$('meta[name=csrf-token]')[0];
 | |
| 
 | |
|     var form = new Element('form', { method: "POST", action: url, style: "display: none;" });
 | |
|     element.parentNode.insert(form);
 | |
| 
 | |
|     if (method !== 'post') {
 | |
|       var field = new Element('input', { type: 'hidden', name: '_method', value: method });
 | |
|       form.insert(field);
 | |
|     }
 | |
| 
 | |
|     if (csrf_param) {
 | |
|       var param = csrf_param.readAttribute('content'),
 | |
|           token = csrf_token.readAttribute('content'),
 | |
|           field = new Element('input', { type: 'hidden', name: param, value: token });
 | |
|       form.insert(field);
 | |
|     }
 | |
| 
 | |
|     form.submit();
 | |
|   }
 | |
| 
 | |
| 
 | |
|   document.on("click", "*[data-confirm]", function(event, element) {
 | |
|     var message = element.readAttribute('data-confirm');
 | |
|     if (!confirm(message)) event.stop();
 | |
|   });
 | |
| 
 | |
|   document.on("click", "a[data-remote]", function(event, element) {
 | |
|     if (event.stopped) return;
 | |
|     handleRemote(element);
 | |
|     event.stop();
 | |
|   });
 | |
| 
 | |
|   document.on("click", "a[data-method]", function(event, element) {
 | |
|     if (event.stopped) return;
 | |
|     handleMethod(element);
 | |
|     event.stop();
 | |
|   });
 | |
| 
 | |
|   document.on("submit", function(event) {
 | |
|     var element = event.findElement(),
 | |
|         message = element.readAttribute('data-confirm');
 | |
|     if (message && !confirm(message)) {
 | |
|       event.stop();
 | |
|       return false;
 | |
|     }
 | |
| 
 | |
|     var inputs = element.select("input[type=submit][data-disable-with]");
 | |
|     inputs.each(function(input) {
 | |
|       input.disabled = true;
 | |
|       input.writeAttribute('data-original-value', input.value);
 | |
|       input.value = input.readAttribute('data-disable-with');
 | |
|     });
 | |
| 
 | |
|     var element = event.findElement("form[data-remote]");
 | |
|     if (element) {
 | |
|       handleRemote(element);
 | |
|       event.stop();
 | |
|     }
 | |
|   });
 | |
| 
 | |
|   document.on("ajax:after", "form", function(event, element) {
 | |
|     var inputs = element.select("input[type=submit][disabled=true][data-disable-with]");
 | |
|     inputs.each(function(input) {
 | |
|       input.value = input.readAttribute('data-original-value');
 | |
|       input.removeAttribute('data-original-value');
 | |
|       input.disabled = false;
 | |
|     });
 | |
|   });
 | |
| })();
 |