1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
setDefaults = Behavior.create({ initialize: function(obj) { myforms = this.element; myforms.writeAttribute({onsubmit: ''}) this.setFormDefaults(); var inp; }, setFormDefaults: function(e){ var inp; for(var i=0;i<myforms.elements.length;i++) { this.setDefaultValue(myforms.elements[i]); this.setFieldHandlers(myforms.elements[i]); } }, setDefaultValue: function(formField) { if(formField.type == 'text') { $(formField.id).removeClassName('highlight'); if(formField.value=='') { $(formField.id).addClassName('optional'); formField.value=formField.title; } } }, setFieldHandlers: function(ff){ if( ff && ff.type == 'text') { ff.onfocus = function() { if(this.type == 'text') { if(this.value==this.title && this.hasClassName('optional')) { this.value=''; $(this.id).removeClassName('optional'); } $(this.id).addClassName('highlight'); } } ff.onblur = function () { if(this.type == 'text') { if(this.value=='') { this.value=this.title; $(this.id).addClassName('optional'); } $(this.id).removeClassName('highlight'); } } } }, clearFormDefaults: function() { if(myforms && myforms.tagName.toLowerCase() == "form") { for(var i=0;i<myforms.elements.length;i++) { inp = myforms.elements[i]; if( inp.type == 'text' && inp.title == inp.value) { inp.value = ''; } } } }, onsubmit: function() { this.clearFormDefaults(); this.sendRequest(); return false; }, oncomplete: function() { Event.addBehavior.reload(); }, sendRequest:function() { new Ajax.Request(this.element.action, {asynchronous:true, evalScripts:true, method:'put', parameters: Form.serialize(myforms) +'&authenticity_token=' + encodeURIComponent( window._token ) }); } }); //Lowpro handler Event.addBehavior({ 'form.useSimpleDefaults': Remote.Form, 'form.useSimpleDefaults': setDefaults });
Refactorings
No refactoring yet !
John Sietsma
October 11, 2008, October 11, 2008 04:51, permalink
I couldn't resist a JQuery refactor.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
$.fn.setHighlight = function() { return this.each( function() { $(this).removeClass('optional'); $(this).addClass('highlight'); } ); } $.fn.setOptional = function() { return this.each( function () { $(this).val( $(this).attr('title') ); $(this).addClass('optional'); } ); } function isDefault() { return $(this).val()==$(this).attr('title'); } function isEmpty() { return $(this).val()==""; } $( function(event) { $("form > input[type='text']") .setOptional() .focus( function() { $(this).filter(".optional").filter(isDefault).val("").removeClass('optional').end().end().setHighlight();}) .blur( function() { $(this).filter(isEmpty).setOptional().end().removeClass('highlight');}) } );
openid.aol.com/forwardfootmedia
October 11, 2008, October 11, 2008 20:41, permalink
29 lines over 90, Not bad. Curious, any particular reason you decided to go for separate functions over keeping the methods with in an object?
John Sietsma
October 12, 2008, October 12, 2008 03:09, permalink
No really, I suppose just because of the size of refactoring.
There is still a lot that could be done:
- The "set" functions are misnamed as they have side effects. There is something not quite right about them and their use of classes.
- I could make the "is" functions more generic since they both check against val.
- "form > input[type='text']" can just be be ":text".
- It doesn't work for text areas.
- If the "set" functions properly returned a JQuery object I could rearrange the event chain so I didn't need the end() calls.
- I could make the whole thing a plugin so users could just do $(form).makeTitlesDefault() or something like it.
But I'm not going to spend another couple of hours on it!
Adam
October 14, 2008, October 14, 2008 19:12, permalink
Prototype version based on the JQuery refactoring.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
FormDefault = { setHighlight: function(object) { var element = FormDefault.element(object); if (FormDefault.isOptional(element)) { element.removeClassName('optional'); element.addClassName('highlight'); } }, setOptional: function(object) { var element = FormDefault.element(object); if (element.value.empty()) { element.value = element.title; element.addClassName('optional'); } }, element: function(object) { return object.isElement() ? object : object.element(); }, isOptional: function(element) { return element.classNames.include('optional') && element.value != element.title; } } document.observe('dom:loaded', function() { $$("form > input[type='text']") .invoke('observe', 'focus', FormDefault.setHighlight) .invoke('observe', 'blur', FormDefault.setOptional) .each(FormDefault.setOptional); });
openid.aol.com/forwardfootmedia
October 14, 2008, October 14, 2008 19:39, permalink
I like the naming of formDefault. Very clean. I am guessing I will have to do the legwork were the sendRequest is concerned :)
The script binds itself to a form with the class “useSimpleDefaults” if a form element is left unpopulated, the script will populate the filed by extracting text from the title attribute. When an input’s onfocus event is triggerd, the background color wil change by toggeling the inputs class and clear the default title value from the field. When the form is submited, the default values are cleared and an ajax request is made to submit the form. The code could use a bit of refactoring, yet it provides a good example to exploring this approach.