Reputation:
For my small wiki application, I mostly need to have the textarea used to edit the contents to use soft (or virtual) wrapping. However, in some cases, not wrapping the content would be preferable. I thought I would do this by simply having a button to turn off wrapping. Here is the simplified code:
<form name="wikiedit" action="[[script_name]]" method="post">
<textarea name="content" rows="25" cols="90" wrap="virtual">[[content]]</textarea>
<input type="button" onclick="document.wikiedit.content.wrap='off';" value="No Wrap">
<input type="submit" value="Save">
</form>
It works with IE, but not with Firefox or Opera. How should I do this?
Upvotes: 3
Views: 9409
Reputation: 6259
Here's a variant of bobince's answer that doesn't require cloning the textarea:
function setWrap(area, wrap) {
if (area.wrap) {
area.wrap = wrap;
} else { // wrap attribute not supported - try Mozilla workaround
area.setAttribute("wrap", wrap);
area.style.overflow = "hidden";
area.style.overflow = "auto";
}
}
This is similar to VK's comment in the bug that bobince referenced, but setting display instead of overflow didn't work for me unless I put the second set in a setTimeout.
Upvotes: 0
Reputation:
Although, this is a old post, but as I getting help from this, I also what to show a easier method I found just now. And I think it's more correct.
To replace the .cloneNode(), I think the best method is:
child.setAttribute( 'wrap', wrap ); parent.removeChild( child ); parent.appendChild( child );
using this way, you can not only save the attributes of itself, but also the attributes you added, for example, a script handle or something else.
Upvotes: 0
Reputation: 536587
See bug 41464: https://bugzilla.mozilla.org/show_bug.cgi?id=41464
Nasty workaround for now is to replace the textarea with a clone of itself:
function setWrap(area, wrap) {
if (area.wrap) {
area.wrap= wrap;
} else { // wrap attribute not supported - try Mozilla workaround
area.setAttribute('wrap', wrap);
var newarea= area.cloneNode(true);
newarea.value= area.value;
area.parentNode.replaceChild(newarea, area);
}
}
Unrelated: try to avoid accessing elements straight out of the document object, it is unreliable on some browsers and causes name clash problems. ‘document.forms.wikiedit’ is better, and moving to ‘id’ on the form instead of ‘name’ and then using ‘document.getElementById('wikiedit')’ better still.
form.elements.content is also more reliable than form.content for similar reasons... or, indeed, you could give the textarea an ID and go straight to the textarea with getElementById without having to bother look at the form.
Upvotes: 2
Reputation: 49218
Here is a primer on textarea wrap, including a CSS solution:
http://www.web-wise-wizard.com/html-tutorials/html-form-forms-textarea-wrap.html
The CSS solution they cite is:
white-space: pre; overflow: auto;
Which would be:
<script type="text/javascript">
function setNoWrap(textarea) {
textarea.style.whiteSpace = 'pre';
textarea.style.overflow = 'auto';
}
</script>
<form name="wikiedit" action="[[script_name]]" method="post">
<textarea name="content" rows="25" cols="90" wrap="virtual">[[content]]</textarea>
<input type="button" onclick="setNoWrap(this);" value="No Wrap">
<input type="submit" value="Save">
</form>
Upvotes: 1
Reputation: 546273
According to the HTML 4.01 spec, wrap
isn't a valid attribute for <textarea>
s which would explain why it's so difficult and strange. It looks as though Firefox actually does use the wrap
attribute, but it won't let you change it.
I do have a solution though! It's pretty awful, but here it is. Completely replace the textarea with a new one.
// this is the onclick handler for your button
document.getElementById("nowrapButton").onclick = function() {
var oldOne = this.form.content; // the old textarea
var newOne = document.createElement('textarea'); // the new textarea
var attrs = ['name', 'rows', 'cols']; // these are the attributes to keep
for (var i = 0; i < attrs.length; ++i) {
// copy the attributes to the new one
newOne.setAttribute(attrs[i], oldOne.getAttribute(attrs[i]));
}
// toggle the wrapping on and off
if (oldOne.getAttribute('wrap') != 'off') {
newOne.setAttribute('wrap', 'off');
}
// copy the text over
newOne.value = oldOne.value;
// add the new one
oldOne.parentNode.insertBefore(newOne, oldOne);
// get rid of the old one
oldOne.parentNode.removeChild(oldOne);
return false;
};
Here's a working version of this you can play with: http://jsbin.com/ugepa
As usual, this'd be much nicer in jQuery. :)
Upvotes: 0