Created
July 28, 2009 20:55
-
-
Save Auz/157660 to your computer and use it in GitHub Desktop.
Flext is a mootools based flexible textarea class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Flext - A Mootools Based Flexible TextArea Class | |
* version 1.0 - for mootools 1.2 | |
* by Graham McNicoll | |
* | |
* Copyright 2008-2009 - Education.com | |
* License: MIT-style license. | |
* | |
* Features: | |
* - Grows text areas when needed | |
* - Grows parents if they have a fixed height | |
* - Ghost text replacement | |
* - Text input emulation (enter can submit form, instead of new line) | |
* | |
* Usage: | |
* | |
* include the source somewhere on your page. Use the class names to trigger features. | |
* | |
* 'growme' - grow the text area (max size can be specified with rel='<max in px>') | |
* 'stopenter' - stop the enter key | |
* 'entersubmits' - submit the form when enter is pressed | |
* 'replaceghosttext' - tries to use the ghosted text features | |
* 'growparents' - grow the parent elements if needed | |
* | |
* if replaceghosttext is on, then you need to add two more attributes to the textarea. | |
* 'ghosttext' contains a copy of the original ghost text (needed for matching initial conditions), | |
* and 'ghostclass' which contains a class name to remove when the ghosting is removed (which | |
* is used to remove ghosting color). | |
* | |
* Examples: | |
* | |
* A simple growing text area: - | |
* | |
* <textarea name='mytext' class='flext growme' rel='200' ></textarea> | |
* | |
* It will find this text area by the class name, 'flext', and the 'growme' | |
* class will tell it to grow until the max size, as given by the 'rel' | |
* property (integer, in pixels). | |
* | |
* Textarea which will grow the parent elements (if needed) - | |
* | |
* <textarea name='mytext' class='flext growme growparents' rel='200' ></textarea> | |
* | |
* This is the same as above, except it will also grow any parent elements which | |
* have fixed heights when the textarea expands ('growparents'). | |
* | |
* | |
* Adv. example: | |
* | |
* <textarea name='mytext' class='flext growme stopenter entersubmits replaceghosttext ghost-text growparents' rel='60' ghosttext='enter something here' ghostclass='ghost-text'> | |
* enter something here | |
* </textarea> | |
* | |
* This example not only grows, but simulates a text input, in that 'enter' | |
* will not be passed to the textarea ('stopenter') instead it will submit | |
* the form ('entersubmits'). It also has ghosted text replacement and class | |
* changing. When this textarea receives focus, it will remove the default | |
* text (ghosttext property), and remove the class as specified by the | |
* ghostclass property. Use of these features as currently coded requires | |
* non valid xhtml, so dont use it if you require valid markup. (its on my list to fix) | |
* | |
* You can also instantiate this class manually, by leaving off the 'flext' class from | |
* any textareas, and instantiate a new class usual with the first variable being the | |
* textarea element, and the second the options object. | |
*/ | |
var Flext = new Class({ | |
Implements: Options, | |
options: { | |
aniTime: 300, //int (ms) - grow animation time | |
maxHeight: 0, //int (pixels) - one way to set a max hieght, if you dont like using 'rel' | |
defaultMaxHeight: 1000, //int (pixels) - if not otherwise set, this is the max height | |
parentDepth: 6, //int - how many levels up should to check the parent el's height. | |
//trigger classes: | |
growClass: 'growme', //string (class name)- grow the text area | |
enterStoppedClass: 'stopenter', //string (class name)- stop the enter key | |
enterSubmitsClass: 'entersubmits', //string (class name)- submit the form when enter is pressed | |
replaceGhostTextClass: 'replaceghosttext', //string (class name)- tries to use the ghosted text features | |
growParentsClass: 'growparents', //string (class name)- grow the parent elements if needed | |
//other attributes: | |
ghostTextAttr: 'ghosttext', | |
ghostClassAttr: 'ghostclass' | |
}, | |
initialize: function(el, options) { | |
this.setOptions(options); | |
this.el = document.id(el); //the textarea element. | |
//by default, we will do nothing to the text area unless it has the class... | |
this.autoGrow = el.hasClass(this.options.growClass); | |
this.stopEnter = el.hasClass(this.options.enterStoppedClass); | |
this.enterSubmits = el.hasClass(this.options.enterSubmitsClass); | |
this.useGhostText = el.hasClass(this.options.replaceGhostTextClass); | |
this.growParents = el.hasClass(this.options.growParentsClass); | |
//initialize, and add events: | |
if(this.autoGrow) { | |
this.startSize = this.el.getSize().y; | |
this.resizer = new Fx.Tween(this.el, {duration: this.options.aniTime}); | |
this.maxSize = this.options.maxHeight; | |
if(this.maxSize == 0) { | |
this.maxSize = this.el.get('rel'); | |
if(!this.maxSize || this.maxSize == '' || this.maxSize == null ) { | |
this.maxSize = this.options.defaultMaxHeight; //if one forgets to set a max height via options or from the rel, use a reasonable number. | |
} | |
} | |
this.reachedMax = false; | |
this.origSize = this.el.getSize().y; | |
this.el.setStyle('overflow', 'hidden'); | |
this.el.addEvent('keyup', function(e) { | |
this.checkSize(e); | |
}.bind(this)); | |
//get inital state: | |
this.checkSize(); | |
} | |
//watch this text area: keydown | |
if(this.stopEnter) { | |
this.el.addEvent('keydown', function(e) { | |
if(e.key == 'enter') { | |
e.stop(); | |
if(this.enterSubmits) { | |
this.submitForm(); | |
} | |
} | |
}.bind(this)); | |
} | |
//replace ghost text: | |
if(this.useGhostText) { | |
this.ghostText = this.el.get(this.options.ghostTextAttr); | |
this.ghostClass = this.el.get(this.options.ghostClassAttr); | |
if(this.ghostText) { | |
//initial states: if populated with something else, remove the class: | |
if(this.el.value != this.ghostText) { | |
this.el.removeClass(this.ghostClass); | |
} | |
//add events to watch for ghosting: | |
this.el.addEvents({ | |
//remove the ghosted text when the text area receives focus | |
'focus': function(e) { | |
if(this.el.value == this.ghostText) { | |
this.el.set('value', ''); | |
if(this.ghostClass) { | |
this.el.removeClass(this.ghostClass); | |
} | |
} | |
}.bind(this), | |
//put the ghost text back if blur'ed and its empty | |
'blur': function(e) { | |
if(this.el.value == '') { | |
this.el.set('value', this.ghostText); | |
if(this.ghostClass) { | |
this.el.addClass(this.ghostClass); | |
} | |
} | |
}.bind(this) | |
}); | |
} | |
} | |
}, | |
checkSize: function(e) { | |
var theSize = this.el.getSize(); | |
var theScrollSize = this.el.getScrollSize(); | |
if(theScrollSize.y > theSize.y) { | |
//we are scrolling, so grow: | |
this.resizeIt(theSize, theScrollSize); | |
} | |
}, | |
resizeIt: function(theSize, scrollSize) { | |
var newSize = scrollSize.y; | |
if(scrollSize.y > this.maxSize && !this.reachedMax) { | |
//we've reached the max size, grow to max size and make textarea scrollable again: | |
newSize = this.maxSize; | |
this.el.setStyle('overflow', ''); | |
this.resizer.start('height', newSize); | |
if(this.growParents) { | |
var increasedSize = newSize - this.startSize; | |
this.resizeParents(this.el, 0, increasedSize); | |
} | |
//remember that we've reached the max size: | |
this.reachedMax = true; | |
} | |
if(!this.reachedMax) { | |
//grow the text area: | |
var increasedSize = newSize - this.startSize; | |
this.startSize = newSize; | |
this.resizer.start('height', newSize); | |
//resize parent objects if needed: | |
if(this.growParents) { | |
this.resizeParents(this.el, 0, increasedSize); | |
} | |
} | |
}, | |
resizeParents: function(el, num, incSize) { | |
if(num < this.options.parentDepth) { | |
var newel = el.getParent(); | |
if(newel) { | |
if(newel.style.height && newel.style.height != '' ) { | |
newel.setStyle('height', (newel.getStyle('height').toInt()+incSize)); | |
} | |
return this.resizeParents(newel, (num+1), incSize); | |
} | |
return true; | |
} else { | |
return true; | |
} | |
}, | |
submitForm: function() { | |
var thisForm = this.el.getParent('form'); | |
if(thisForm) { | |
var formName = thisForm.get('name'); | |
document[formName].submit(); | |
} | |
} | |
}); | |
//watch the text areas: | |
window.addEvent('domready', function() { | |
$$('textarea.flext').each(function(el, i) { | |
new Flext(el); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment