- #42446: Resizable textareas.

4.7.x
Steven Wittens 2005-12-29 03:59:30 +00:00
parent afd8ccaf7e
commit 5e49dd2a68
4 changed files with 144 additions and 1 deletions

View File

@ -760,9 +760,15 @@ function theme_form($element) {
* A themed HTML string representing the textarea.
*/
function theme_textarea($element) {
$class = 'textarea';
if ($element['#resizable'] !== false) {
drupal_add_js('misc/textarea.js');
$class .= ' resizable';
}
$cols = $element['#cols'] ? ' cols="'. $element['#cols'] .'"' : '';
return theme('form_element', $element['#title'], '<textarea'. $cols .' rows="'. $element['#rows'] .'" name="'. $element['#name'] .'" id="' . $element['#id'] .'" class="'. _form_get_class('textarea', $element['#required'], form_get_error($element)) .'"'. drupal_attributes($element['#attributes']) .'>'. check_plain($element['#value']) .'</textarea>', $element['#description'], $element['#id'], $element['#required'], form_get_error($element));
return theme('form_element', $element['#title'], '<textarea'. $cols .' rows="'. $element['#rows'] .'" name="'. $element['#name'] .'" id="' . $element['#id'] .'" class="'. _form_get_class($class, $element['#required'], form_get_error($element)) .'"'. drupal_attributes($element['#attributes']) .'>'. check_plain($element['#value']) .'</textarea>', $element['#description'], $element['#id'], $element['#required'], form_get_error($element));
}
/**

View File

@ -618,3 +618,17 @@ html.js fieldset.collapsed legend a {
* html.js fieldset.collapsible legend a {
display: block;
}
/*
** Resizable text areas
*/
.resizable-textarea {
width: 95%;
}
.resizable-textarea .grippie {
height: 14px;
background: #eee url('grippie.png') no-repeat 100% 100%;
border: 1px solid #ddd;
border-top-width: 0px;
cursor: ns-resize;
}

View File

@ -211,6 +211,10 @@ function absolutePosition(el) {
return r;
};
function dimensions(el) {
return { width: el.offsetWidth, height: el.offsetHeight };
}
/**
* Returns true if an element has a specified class name
*/
@ -279,6 +283,20 @@ function removeNode(node) {
}
}
/**
* Prevents an event from propagating.
*/
function stopEvent(event) {
if (event.preventDefault) {
event.preventDefault();
event.stopPropagation();
}
else {
event.returnValue = false;
event.cancelBubble = true;
}
}
/**
* Wrapper around document.getElementById().
*/

105
misc/textarea.js Normal file
View File

@ -0,0 +1,105 @@
if (isJsEnabled()) {
addLoadEvent(function() {
// Attach to all textareas
textareas = document.getElementsByTagName('textarea');
var textarea;
for (var i = 0; textarea = textareas[i]; ++i) {
if (hasClass(textarea, 'resizable')) {
new textArea(textarea);
}
}
});
}
function textArea(element) {
var ta = this;
this.element = element;
this.parent = this.element.parentNode;
this.dimensions = dimensions(element);
// Prepare wrapper
this.wrapper = document.createElement('div');
this.wrapper.className = 'resizable-textarea';
this.parent.insertBefore(this.wrapper, this.element);
// Add grippie and measure it
this.grippie = document.createElement('div');
this.grippie.className = 'grippie';
this.wrapper.appendChild(this.grippie);
this.grippie.dimensions = dimensions(this.grippie);
this.grippie.onmousedown = function (e) { ta.beginDrag(e); };
this.element.onmouseup = function (e) { ta.endDrag(e); };
// Set wrapper and textarea dimensions
this.wrapper.style.height = this.dimensions.height + this.grippie.dimensions.height + 1 +'px';
this.element.style.marginBottom = '0px';
this.element.style.width = '100%';
this.element.style.height = this.dimensions.height +'px';
// Wrap textarea
removeNode(this.element);
this.wrapper.insertBefore(this.element, this.grippie);
// Measure difference between desired and actual textarea dimensions to account for padding/borders
this.widthOffset = dimensions(this.wrapper).width - this.dimensions.width;
// Make the grippie line up in various browsers
if (window.opera) {
// Opera
this.grippie.style.marginRight = this.widthOffset +'px';
}
if (document.all && !window.opera) {
// IE
this.grippie.style.width = '100%';
this.grippie.style.paddingLeft = '2px';
}
// Mozilla
this.element.style.MozBoxSizing = 'border-box';
this.heightOffset = absolutePosition(this.grippie).y - absolutePosition(this.element).y - this.dimensions.height;
}
textArea.prototype.beginDrag = function (event) {
event = event || window.event;
// Capture mouse
var cp = this;
this.oldMoveHandler = document.onmousemove;
document.onmousemove = function(e) { cp.handleDrag(e); };
this.oldUpHandler = document.onmouseup;
document.onmouseup = function(e) { cp.endDrag(e); };
// Store drag offset from grippie top
var pos = absolutePosition(this.grippie);
this.dragOffset = event.clientY - pos.y;
// Make transparent
this.element.style.opacity = 0.5;
// Process
this.handleDrag(event);
}
textArea.prototype.handleDrag = function (event) {
event = event || window.event;
// Get coordinates relative to text area
var pos = absolutePosition(this.element);
var y = event.clientY - pos.y;
// Set new height
var height = Math.max(32, y - this.dragOffset - this.heightOffset);
this.wrapper.style.height = height + this.grippie.dimensions.height + 1 + 'px';
this.element.style.height = height + 'px';
// Avoid text selection
stopEvent(event);
}
textArea.prototype.endDrag = function (event) {
// Uncapture mouse
document.onmousemove = this.oldMoveHandler;
document.onmouseup = this.oldUpHandler;
// Restore opacity
this.element.style.opacity = 1.0;
}