Created
June 6, 2012 11:39
-
-
Save DimitarChristoff/2881416 to your computer and use it in GitHub Desktop.
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
(function(){ | |
/* | |
--- | |
description: DynamicTextarea | |
license: MIT-style | |
authors: | |
- Amadeus Demarzi (http://amadeusamade.us) | |
requires: | |
core/1.3: [Core/Class, Core/Element, Core/Element.Event, Core/Element.Style, Core/Element.Dimensions] | |
provides: [DynamicTextarea] | |
... | |
*/ | |
// Prevent the plugin from overwriting existing variables | |
if (this.DynamicTextarea) return; | |
var DynamicTextarea = this.DynamicTextarea = new Class({ | |
Implements: [Options, Events], | |
options: { | |
value: '', | |
minRows: 1, | |
delay: true, | |
lineHeight: null, | |
offset: 0, | |
padding: 0 | |
// AVAILABLE EVENTS | |
// onCustomLineHeight: (function) - custom ways of determining lineHeight if necessary | |
// onInit: (function) | |
// onFocus: (function) | |
// onBlur: (function) | |
// onKeyPress: (function) | |
// onResize: (function) | |
// onEnable: (function) | |
// onDisable: (function) | |
// onClean: (function) | |
}, | |
textarea: null, | |
initialize: function(textarea,options) { | |
this.textarea = document.id(textarea); | |
if (!this.textarea) return; | |
this.setOptions(options); | |
this.parentEl = new Element('div',{ | |
styles:{ | |
padding:0, | |
margin:0, | |
border:0, | |
height:'auto', | |
width:'auto' | |
} | |
}) | |
.inject(this.textarea,'after') | |
.adopt(this.textarea); | |
// Prebind common methods | |
['focus','delayCheck','blur','scrollFix','checkSize','clean','disable','enable','getLineHeight'] | |
.each(function(method){ | |
this[method] = this[method].bind(this); | |
},this); | |
// Firefox and Opera handle scroll heights differently than all other browsers | |
if (window.Browser.firefox || window.Browser.opera) { | |
this.options.offset = | |
parseInt(this.textarea.getStyle('padding-top'),10) + | |
parseInt(this.textarea.getStyle('padding-bottom'),10) + | |
parseInt(this.textarea.getStyle('border-bottom-width'),10) + | |
parseInt(this.textarea.getStyle('border-top-width'),10); | |
} else { | |
this.options.offset = | |
parseInt(this.textarea.getStyle('border-bottom-width'),10) + | |
parseInt(this.textarea.getStyle('border-top-width'),10); | |
this.options.padding = | |
parseInt(this.textarea.getStyle('padding-top'),10) + | |
parseInt(this.textarea.getStyle('padding-bottom'),10); | |
} | |
// Disable browser resize handles, set appropriate styles | |
this.textarea.set({ | |
'rows': 1, | |
'styles': { | |
'resize': 'none', | |
'-moz-resize': 'none', | |
'-webkit-resize': 'none', | |
'position': 'relative', | |
'display': 'block', | |
'overflow': 'hidden', | |
'height': 'auto' | |
} | |
}); | |
this.getLineHeight(); | |
this.fireEvent('customLineHeight'); | |
// Set the height of the textarea, based on content | |
this.checkSize(true); | |
this.textarea.addEvent('focus',this.focus); | |
this.fireEvent('init',[textarea,options]); | |
}, | |
// This is the only crossbrowser method to determine ACTUAL lineHeight in a textarea (that I am aware of) | |
getLineHeight: function(){ | |
var backupValue = this.textarea.get('value'); | |
this.textarea.set('value', 'M'); | |
this.options.lineHeight = this.textarea.getScrollSize().y - this.options.padding; | |
this.textarea.set('value', backupValue); | |
this.textarea.setStyle('height', this.options.lineHeight * this.options.minRows); | |
}, | |
// Stops a small scroll jump on some browsers | |
scrollFix: function(){ | |
this.textarea.scrollTo(0,0); | |
}, | |
// Add interactive events, and fire focus event | |
focus: function(){ | |
this.textarea.addEvents({ | |
'keydown': this.delayCheck, | |
'keypress': this.delayCheck, | |
'blur': this.blur, | |
'scroll': this.scrollFix | |
}); | |
return this.fireEvent('focus'); | |
}, | |
// Clean out extraneaous events, and fire blur event | |
blur: function(){ | |
this.textarea.removeEvents({ | |
'keydown': this.delayCheck, | |
'keypress': this.delayCheck, | |
'blur': this.blur, | |
'scroll': this.scrollFix | |
}); | |
return this.fireEvent('blur'); | |
}, | |
// Delay checkSize because text hasn't been injected into the textarea yet | |
delayCheck: function(){ | |
if (this.options.delay === true) | |
this.options.delay = this.checkSize.delay(1); | |
}, | |
// Determine if it needs to be resized or not, and resize if necessary | |
checkSize: function(forced) { | |
var oldValue = this.options.value, | |
modifiedParent = false; | |
this.options.value = this.textarea.get('value'); | |
this.options.delay = false; | |
if (this.options.value === oldValue && forced!==true) | |
return this.options.delay = true; | |
if (!oldValue || this.options.value.length < oldValue.length || forced) { | |
modifiedParent = true; | |
this.parentEl.setStyle('height',this.parentEl.getSize().y); | |
this.textarea.setStyle('height', this.options.minRows * this.options.lineHeight); | |
} | |
var tempHeight = this.textarea.getScrollSize().y, | |
offsetHeight = this.textarea.offsetHeight, | |
cssHeight = tempHeight - this.options.padding, | |
scrollHeight = tempHeight + this.options.offset; | |
if (scrollHeight !== offsetHeight && cssHeight > this.options.minRows * this.options.lineHeight){ | |
this.textarea.setStyle('height',cssHeight); | |
this.fireEvent('resize'); | |
} | |
if(modifiedParent) this.parentEl.setStyle('height','auto'); | |
this.options.delay = true; | |
if (forced !== true) | |
return this.fireEvent('keyPress'); | |
}, | |
// Clean out this textarea's event handlers | |
clean: function(){ | |
this.textarea.removeEvents({ | |
'focus': this.focus, | |
'keydown': this.delayCheck, | |
'keypress': this.delayCheck, | |
'blur': this.blur, | |
'scroll': this.scrollFix | |
}); | |
return this.fireEvent('clean'); | |
}, | |
// Disable the textarea | |
disable: function(){ | |
this.textarea.blur(); | |
this.clean(); | |
this.textarea.set(this.options.disabled,true); | |
return this.fireEvent('disable'); | |
}, | |
// Enables the textarea | |
enable: function(){ | |
this.textarea.addEvents({ | |
'focus': this.focus, | |
'scroll': this.scrollFix | |
}); | |
this.textarea.set(this.options.disabled,false); | |
return this.fireEvent('enable'); | |
} | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment