jQuery difficulties in FireFox & XHTML - javascript

I have recently made the switch from HTML to XHTML... don't get me started on the "why" - let's just say it wasn't an option. Anyhoo...
This function worked fine in IE and FF when I was HTML, but now with XHTML I get the following error in FF:
heightElement is undefined
now here is the statement where I define heightElement
function revBars(isEFBOutput, isIXPPreview) {
if (!isIXPPreview) isIXPPreview = false;
var heightElement =
$('<div id="resizeDetectingElement" style="position:absolute; left:-9999999px height:1em;"> </div>')
.prependTo('body')
.get(0);
heightElement.currentHeight = heightElement.offsetHeight; // FireBug says the error is here.
insert();
window.onresize = refresh;
setInterval(
function() {
if (heightElement.currentHeight != heightElement.offsetHeight) {
heightElement.currentHeight = heightElement.offsetHeight; refresh();
}
}, 500);
function insert() {
var px = "px";
var color = (document.styleSheets[0].href.match("ftidStyleDay")) ? "black" : "white";
$revMarks = $('.RevMark').removeClass('RevMark').addClass('UnMarked');
if (!$revMarks.length) $revMarks = $('.UnMarked');
$revMarks.each(function() {
$('<div class="RevBar" />').css({
'background-color': color,
'width': '2px', 'position': 'absolute',
'left': (isEFBOutput && !isIXPPreview ? '.25em' : '-.75em'),
'height': this.offsetHeight,
'top': offset(this) + px
}).prependTo('body');
});
}
function refresh() { $('.RevBar').remove(); insert(); }
function offset(obj) {
var top = 0;
if (obj.offsetParent) {
do {
top += obj.offsetTop;
} while (obj = obj.offsetParent);
}
if (document.all && (!isEFBOutput || (isEFBOutput && isIXPPreview))) top -= 15;
return top;
}
}
any ideas why this is throwing an error in XHTML in FF? It still works in IE.
EDIT: Again, this code worked perfectly in FF and IE until I switched to XHTML. Firefox still creates a DOM for XHTML, right?

I rewrote some of your example, as you have errors and is incomplete with function calls that are not in the example:
$(document).ready( function(){
function revBars(isEFBOutput, isIXPPreview){
var test = "<div id=\"someElement\">whatever</div>";
$('body').prepend(test).get(0);
var heightElement = $('#someElement');
console.log( heightElement);
}
revBars();
});
At this point the heigthElement exists and the div is added to DOM.
Please provide correct problems in order to get them solved.
UPDATES
//var heightElement = $('<div id="resizeDetectingElement">whatever</div>').prependTo('body').get(0);
// this statement doesn't work
var heightElement = $('body').prepend('<div id="resizeDetectingElement">whatever</div>');
// this does
console.log(heightElement);
This is basically the same as first example.
The request that you made is to add a div before the element body and then get the first element of the body. The prependTo already returns the matched items so the get was irelevant. And you are attaching an element before the body so is normal that your variable will be empty.
Try my code and remove the downvote as not to many people had this kind of patience with your supercode.
UPDATE 2
This is an usage example for prepend() and prependTo().
<html>
<head>
<script type="text/javascript" src="../lib/jquery/jquery-1.3.2.min.js"></script>
<script type="text/javascript">
$(document).ready( function(){
$("#test_A").prepend('<div id=\'test_B\'>B</div>');
$("#test_C").prependTo( $('#test_A'));
var x = $('<div id="resizeDetectingElement">D</div>').prependTo('body').get(0);
console.log( x ); // returns the div
$(x).append('some text'); //works
});
</script>
</head>
<body>
<div id='test_A'>A</div>
<div id='test_C'>C</div>
</body>
</html>
I hope this will help to make your code work. USE $(heightElement) not just heightElement which is the div not the jQuery object.

Related

External Javascript Not Working in Firefox

I have just hit an odd problem with an external javascript file. It works perfectly in Edge and Chrome but not in Firefox (51.0.1).
I have a number of scripts at the bottom of the body of the page, like this
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="js/adblocker.js"></script>
<script>
$(document).ready(function() {
$('.dir_hotel').keyup(function(event) {
if (event.keyCode == 13) {
this.form.submit();
return false;
}
});
});
</script>
<?php if ($mobile_browser > 0) { ?>
<script>
/* MOBILE COLLAPSE MENU */
(function($) {
$.fn.collapsable = function(options) {
// iterate and reformat each matched element
return this.each(function() {
// cache this:
var obj = $(this);
var tree = obj.next('.nav');
obj.click(function(){
if( obj.is(':visible') ){tree.toggle();}
});
});
};
})(jQuery);
$(document).ready(function(){
$('.slide-trigger').collapsable();
$(".slide-trigger").click(function(){
$('.slide-trigger').html($('.slide-trigger').text() == 'Collapse MENU' ? 'MENU' : 'Collapse MENU');
});
});
</script>
<?php }?>
</body>
The adblocker.js file doesn't run. I've tried adding an alert as the first line of the .js file and the alert never appears. I've checked the console in the browser and that shows the file is not loading.
If I replace
<script src="js/adblocker.js"></script>
with
<script>
window.onload=function(){
var clientHeight = document.getElementById('travins').clientHeight;
if (clientHeight < 20) {
var node = document.getElementById("insnote");
node.innerHTML = "<a href='https://clkuk.tradedoubler.com/click?p=18211&a=1906311&g=232597' target='_blank'>Columbus Direct Travel Insurance</a>";
}
var clientHeight = document.getElementById('flights').clientHeight;
if (clientHeight < 50) {
var node = document.getElementById("flightnote");
node.innerHTML = "<a href='http://www.kqzyfj.com/click-7782323-11015988-1440520708000' target='_blank'>Skyscanner</a>";
}
var clientHeight = document.getElementById('carhire').clientHeight;
if (clientHeight < 20) {
var node = document.getElementById("hirenote");
node.innerHTML = "<a href='http://www.zestcarrental.com/click.php?adm=1018&adt=14' target='_blank'>Zest Car Rental</a>";
}
var clientHeight = document.getElementById('parking').clientHeight;
if (clientHeight < 20) {
var node = document.getElementById("parknote");
node.innerHTML = "<a href='https://clkuk.tradedoubler.com/click?p=20642&a=1906311&g=20842820' target='_blank'>Purple Parking</a>";
}
var clientHeight = document.getElementById('brittany').clientHeight;
if (clientHeight < 20) {
var node = document.getElementById("ferrynote");
node.innerHTML = "<a href='http://being.successfultogether.co.uk/click.asp?ref=731409&site=6792&type=b3&bnb=3' target='_blank'>Brittany Ferries</a>";
}
};
</script>
it works perfectly.
I've tried js/adblocker.js, /js/adblocker.js and mydomain.com/js/adblocker.js and that makes no difference. I've also double-checked that the file is actually uploaded, which it is. I must be doing something stupid, but what?
As Joe correctly suggested, the Adblock Plus extension was blocking the adblocker.js file. Changing the file name to blocker.js has solved the problem.
I have to say that I think this is a mighty crude way of filtering advertising, as there must be so many innocent ways that a file might have "ad" in the name. I'll be watching for this in future whenever my Firefox does something unexpected.
Try to put your JavaScript code between this codes
(function($) { // your code here })(jQuery); in JavaScript file. It work with me.

script works in jsfiddle but not in site

I have seen others ask this question but I couldn't find an answer that worked for me.
I posted a question a while back and someone sent me this jsFiddle: http://jsfiddle.net/r043v/LgXQX/1/
It does exactly what I need it to and the site says it's perfectly valid, but it's not working when I paste it into my document. I read about the extra invisible characters it will add when you c+p so I used jslint and it said I had gotten rid of them, but it still isn't working.
Here is the code as it is in my page (I started from scratch after it didn't work the first time so that I would be sure nothing else in my code was messing it up)
<!DOCTYPE html>
<head>
<link rel="stylesheet" href="style3.css">
<script type=”text/javascript” src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script>
$("#issues > li").click(function () {
var $img = $("#theimg");
var $li = $(this);
var newsrc = "";
newsrc = $li.data("img");
if (newsrc === undefined) newsrc = "issue" + $li.index() + ".jpg";
var loadstep = 0;
function endstep() { // end of preload or hide
if (++loadstep === 2) // if the preload is done and hide too, change src and show picture
$img.attr("src", newsrc).animate({
opacity: 1
});
}
// preload picture
var $tmpimg = $("<img/>", {
src: newsrc
}).on("load", endstep);
// hide container picture
$img.animate({
opacity: 0
}, endstep);
});
</script>
</head>
The css file only has what's in the jsFiddle and the body is copied and pasted from the html section in the fiddle. Any insight would be greatly appreciated!
You need to load the script in a $(document).ready() handler. Fiddle adds it for you. Hence it is working there.
$(document).ready(function () {
$("#issues > li").click(function () {
var $img = $("#theimg");
var $li = $(this);
var newsrc = "";
newsrc = $li.data("img");
if (newsrc === undefined) newsrc = "issue" + $li.index() + ".jpg";
var loadstep = 0;
function endstep() { // end of preload or hide
if (++loadstep === 2) // if the preload is done and hide too, change src and show picture
$img.attr("src", newsrc).animate({
opacity: 1
});
}
// preload picture
var $tmpimg = $("<img/>", {
src: newsrc
}).on("load", endstep);
// hide container picture
$img.animate({
opacity: 0
}, endstep);
});
});

Get images width on .load() doesn't work on all browsers except firefox

I post my question here because I haven't find an answer to my issue.
I load some image in JavaScript. Each of them are in its own div. And I want to get the width of the div.
this.biggerElmts.find('img').each(function(){
var div = $('<div/>', {'class': this.divMinPic}).appendTo(divMinPics);
var img = $('<img/>', {
'class': this.minPic,
alt:'Miniature '+$(this).attr("alt"),
src:this.urlPic($(this).attr("src"), this.minPicFolder)
}) // if image not found, we put de default file
.error(function(){console.log("error loading image");$(this).attr("src", this.minPicFolder + this.defaultMinPic);})
.load(function(){
console.info($(this).width());
})
.appendTo(div);});
My problem is that it works fine on Firefox, but it doesn't on all other browser.
Firefox return me 185 and each other return me 0.
If you had a jsfiddle of your code we may be able to look more specifically at what is happening. But to the best if my knowledge the onload event works fine in all browsers that I have tried, whether using pure javascript or jquery.
Here is another thread where jquery was used to do just what you are asking about.
I also have a couple of pure javascript demos on jsfiddle you can look at if you are interested.
Ok SO, here is some code to go with the links to jsfiddle
var display = document.getElementById("display"),
images = {
"F12berlinetta": "http://www.ferrari.com/Site_Collection_Image_115x55/f12_thumb_home_115x55.png",
"458 Spider": "http://www.ferrari.com/Site_Collection_Image_115x55/110823_458_spider_menu.png",
"FF": "http://www.ferrari.com/Site_Collection_Image_115x55/ff_thumb_home_115x55.png",
"458 Italia": "http://www.ferrari.com/Site_Collection_Image_115x55/458_italia_menu_1_dx_ok.png",
"Ferrari California": "http://www.ferrari.com/Site_Collection_Image_115x55/california_menu_3_sx.png"
},
keys = Object.keys(images),
loaded = 0,
menuWidth = 0,
noWaitWidth = 0;
function clickedIt(evt) {
alert("You chose the " + evt.target.title);
}
function onLoaded(evt) {
loaded += 1;
menuWidth += evt.target.offsetWidth;
evt.target.addEventListener("click", clickedIt, false);
if (loaded === keys.length) {
console.log("Waited load width", menuWidth);
}
}
keys.forEach(function (key, index) {
var newDiv = document.createElement("div"),
newImg = document.createElement("img");
newImg.id = "thumb" + index;
newImg.src = images[key];
noWaitWidth += newImg.offsetWidth;
newImg.title = key;
newImg.addEventListener("load", onLoaded, false);
newDiv.appendChild(newImg);
display.appendChild(newDiv);
});
console.log("Didn't wait load width", noWaitWidth);
Demo 1
Demo 2

Why is my Javascript not working?

This is my Javascript:
<script type="text/javascript">
function contactChange() {
var contact = document.getElementbyId("contact");
if (contact.style.display == "none") {
contact.style.display = "block";
} else {
contact.style.display = "none";
}
}
</script>
And here is my site:
http://www.andrewjalexander.com/
It's document.getElementById, not document.getElementbyId. (In JS, name of variables and functions are case-sensitive)
Debugging tip : Look at the JS console (F12 in Google Chrome and IE9, Ctrl+Shift+K in Firefox). In this case, following error can be seen:
It shows where the error happened (line 260 in your HTML/JS code) and what the error is(Object #<HTMLDocument> has no method getElementbyId).
It's getElementById, not getElementbyId. Note the upper case "B".
You're going to hate yourself for this, but you put getElementbyId() instead of getElementById(). Note the capitalized "B" in the second version.
Its getElementById in place of getElementbyId
Try to hide then show a element on scroll I had to go this route. Basically i tried to use window so I used 'body'
$(document).ready(function() {
$('body').scroll(function() {
var scroll = $('body').scrollTop();
if (scroll <= 50 ) {
console.log(scroll);
we
} else {
$("#label").css('fill', 'none');
$(".label").addClass(".transition");
}
if (scroll <= 150) {
$(".sizeLG").css('color', '#ffffff');
} else {
$(".sizeLG").css('color', '#00000000');
$(".sizeLG").addClass(".transition");
}
});
});
Make sure your id or class you used in html code will accordingly .(dot) Or #(hash) with their name.
Ex:
For id:
html:
<div id= idName>
****Some code****
<\div>
Javascript:
var VariableName = document.querySelector( "#idName");
Or
var VariableName = document.getElementById( "#idName");
For class:
html:
<div id= className>
****Some code****
<\div>
Javascript
var VariableName = document.querySelector( ".className");
Or
var VariableName = document.getElementById( ".className");

How to autosize a textarea using Prototype?

I'm currently working on an internal sales application for the company I work for, and I've got a form that allows the user to change the delivery address.
Now I think it would look much nicer, if the textarea I'm using for the main address details would just take up the area of the text in it, and automatically resize if the text was changed.
Here's a screenshot of it currently.
Any ideas?
#Chris
A good point, but there are reasons I want it to resize. I want the area it takes up to be the area of the information contained in it. As you can see in the screen shot, if I have a fixed textarea, it takes up a fair wack of vertical space.
I can reduce the font, but I need address to be large and readable. Now I can reduce the size of the text area, but then I have problems with people who have an address line that takes 3 or 4 (one takes 5) lines. Needing to have the user use a scrollbar is a major no-no.
I guess I should be a bit more specific. I'm after vertical resizing, and the width doesn't matter as much. The only problem that happens with that, is the ISO number (the large "1") gets pushed under the address when the window width is too small (as you can see on the screenshot).
It's not about having a gimick; it's about having a text field the user can edit that won't take up unnecessary space, but will show all the text in it.
Though if someone comes up with another way to approach the problem I'm open to that too.
I've modified the code a little because it was acting a little odd. I changed it to activate on keyup, because it wouldn't take into consideration the character that was just typed.
resizeIt = function() {
var str = $('iso_address').value;
var cols = $('iso_address').cols;
var linecount = 0;
$A(str.split("\n")).each(function(l) {
linecount += 1 + Math.floor(l.length / cols); // Take into account long lines
})
$('iso_address').rows = linecount;
};
Facebook does it, when you write on people's walls, but only resizes vertically.
Horizontal resize strikes me as being a mess, due to word-wrap, long lines, and so on, but vertical resize seems to be pretty safe and nice.
None of the Facebook-using-newbies I know have ever mentioned anything about it or been confused. I'd use this as anecdotal evidence to say 'go ahead, implement it'.
Some JavaScript code to do it, using Prototype (because that's what I'm familiar with):
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script src="http://www.google.com/jsapi"></script>
<script language="javascript">
google.load('prototype', '1.6.0.2');
</script>
</head>
<body>
<textarea id="text-area" rows="1" cols="50"></textarea>
<script type="text/javascript" language="javascript">
resizeIt = function() {
var str = $('text-area').value;
var cols = $('text-area').cols;
var linecount = 0;
$A(str.split("\n")).each( function(l) {
linecount += Math.ceil( l.length / cols ); // Take into account long lines
})
$('text-area').rows = linecount + 1;
};
// You could attach to keyUp, etc. if keydown doesn't work
Event.observe('text-area', 'keydown', resizeIt );
resizeIt(); //Initial on load
</script>
</body>
</html>
PS: Obviously this JavaScript code is very naive and not well tested, and you probably don't want to use it on textboxes with novels in them, but you get the general idea.
One refinement to some of these answers is to let CSS do more of the work.
The basic route seems to be:
Create a container element to hold the textarea and a hidden div
Using Javascript, keep the textarea’s contents synced with the div’s
Let the browser do the work of calculating the height of that div
Because the browser handles rendering / sizing the hidden div, we avoid
explicitly setting the textarea’s height.
document.addEventListener('DOMContentLoaded', () => {
textArea.addEventListener('change', autosize, false)
textArea.addEventListener('keydown', autosize, false)
textArea.addEventListener('keyup', autosize, false)
autosize()
}, false)
function autosize() {
// Copy textarea contents to div browser will calculate correct height
// of copy, which will make overall container taller, which will make
// textarea taller.
textCopy.innerHTML = textArea.value.replace(/\n/g, '<br/>')
}
html, body, textarea {
font-family: sans-serif;
font-size: 14px;
}
.textarea-container {
position: relative;
}
.textarea-container > div, .textarea-container > textarea {
word-wrap: break-word; /* make sure the div and the textarea wrap words in the same way */
box-sizing: border-box;
padding: 2px;
width: 100%;
}
.textarea-container > textarea {
overflow: hidden;
position: absolute;
height: 100%;
}
.textarea-container > div {
padding-bottom: 1.5em; /* A bit more than one additional line of text. */
visibility: hidden;
}
<div class="textarea-container">
<textarea id="textArea"></textarea>
<div id="textCopy"></div>
</div>
Here's another technique for autosizing a textarea.
Uses pixel height instead of line height: more accurate handling of line wrap if a proportional font is used.
Accepts either ID or element as input
Accepts an optional maximum height parameter - useful if you'd rather not let the text area grow beyond a certain size (keep it all on-screen, avoid breaking layout, etc.)
Tested on Firefox 3 and Internet Explorer 6
Code:
(plain vanilla JavaScript)
function FitToContent(id, maxHeight)
{
var text = id && id.style ? id : document.getElementById(id);
if (!text)
return;
/* Accounts for rows being deleted, pixel value may need adjusting */
if (text.clientHeight == text.scrollHeight) {
text.style.height = "30px";
}
var adjustedHeight = text.clientHeight;
if (!maxHeight || maxHeight > adjustedHeight)
{
adjustedHeight = Math.max(text.scrollHeight, adjustedHeight);
if (maxHeight)
adjustedHeight = Math.min(maxHeight, adjustedHeight);
if (adjustedHeight > text.clientHeight)
text.style.height = adjustedHeight + "px";
}
}
Demo:
(uses jQuery, targets on the textarea I'm typing into right now - if you have Firebug installed, paste both samples into the console and test on this page)
$("#post-text").keyup(function()
{
FitToContent(this, document.documentElement.clientHeight)
});
Probably the shortest solution:
jQuery(document).ready(function(){
jQuery("#textArea").on("keydown keyup", function(){
this.style.height = "1px";
this.style.height = (this.scrollHeight) + "px";
});
});
This way you don't need any hidden divs or anything like that.
Note: you might have to play with this.style.height = (this.scrollHeight) + "px"; depending on how you style the textarea (line-height, padding and that kind of stuff).
Here's a Prototype version of resizing a text area that is not dependent on the number of columns in the textarea. This is a superior technique because it allows you to control the text area via CSS as well as have variable width textarea. Additionally, this version displays the number of characters remaining. While not requested, it's a pretty useful feature and is easily removed if unwanted.
//inspired by: http://github.com/jaz303/jquery-grab-bag/blob/63d7e445b09698272b2923cb081878fd145b5e3d/javascripts/jquery.autogrow-textarea.js
if (window.Widget == undefined) window.Widget = {};
Widget.Textarea = Class.create({
initialize: function(textarea, options)
{
this.textarea = $(textarea);
this.options = $H({
'min_height' : 30,
'max_length' : 400
}).update(options);
this.textarea.observe('keyup', this.refresh.bind(this));
this._shadow = new Element('div').setStyle({
lineHeight : this.textarea.getStyle('lineHeight'),
fontSize : this.textarea.getStyle('fontSize'),
fontFamily : this.textarea.getStyle('fontFamily'),
position : 'absolute',
top: '-10000px',
left: '-10000px',
width: this.textarea.getWidth() + 'px'
});
this.textarea.insert({ after: this._shadow });
this._remainingCharacters = new Element('p').addClassName('remainingCharacters');
this.textarea.insert({after: this._remainingCharacters});
this.refresh();
},
refresh: function()
{
this._shadow.update($F(this.textarea).replace(/\n/g, '<br/>'));
this.textarea.setStyle({
height: Math.max(parseInt(this._shadow.getHeight()) + parseInt(this.textarea.getStyle('lineHeight').replace('px', '')), this.options.get('min_height')) + 'px'
});
var remaining = this.options.get('max_length') - $F(this.textarea).length;
this._remainingCharacters.update(Math.abs(remaining) + ' characters ' + (remaining > 0 ? 'remaining' : 'over the limit'));
}
});
Create the widget by calling new Widget.Textarea('element_id'). The default options can be overridden by passing them as an object, e.g. new Widget.Textarea('element_id', { max_length: 600, min_height: 50}). If you want to create it for all textareas on the page, do something like:
Event.observe(window, 'load', function() {
$$('textarea').each(function(textarea) {
new Widget.Textarea(textarea);
});
});
Here is a solution with JQuery:
$(document).ready(function() {
var $abc = $("#abc");
$abc.css("height", $abc.attr("scrollHeight"));
})
abc is a teaxtarea.
Check the below link:
http://james.padolsey.com/javascript/jquery-plugin-autoresize/
$(document).ready(function () {
$('.ExpandableTextCSS').autoResize({
// On resize:
onResize: function () {
$(this).css({ opacity: 0.8 });
},
// After resize:
animateCallback: function () {
$(this).css({ opacity: 1 });
},
// Quite slow animation:
animateDuration: 300,
// More extra space:
extraSpace:20,
//Textarea height limit
limit:10
});
});
Just revisiting this, I've made it a little bit tidier (though someone who is full bottle on Prototype/JavaScript could suggest improvements?).
var TextAreaResize = Class.create();
TextAreaResize.prototype = {
initialize: function(element, options) {
element = $(element);
this.element = element;
this.options = Object.extend(
{},
options || {});
Event.observe(this.element, 'keyup',
this.onKeyUp.bindAsEventListener(this));
this.onKeyUp();
},
onKeyUp: function() {
// We need this variable because "this" changes in the scope of the
// function below.
var cols = this.element.cols;
var linecount = 0;
$A(this.element.value.split("\n")).each(function(l) {
// We take long lines into account via the cols divide.
linecount += 1 + Math.floor(l.length / cols);
})
this.element.rows = linecount;
}
}
Just it call with:
new TextAreaResize('textarea_id_name_here');
I've made something quite easy. First I put the TextArea into a DIV. Second, I've called on the ready function to this script.
<div id="divTable">
<textarea ID="txt" Rows="1" TextMode="MultiLine" />
</div>
$(document).ready(function () {
var heightTextArea = $('#txt').height();
var divTable = document.getElementById('divTable');
$('#txt').attr('rows', parseInt(parseInt(divTable .style.height) / parseInt(altoFila)));
});
Simple. It is the maximum height of the div once it is rendered, divided by the height of one TextArea of one row.
I needed this function for myself, but none of the ones from here worked as I needed them.
So I used Orion's code and changed it.
I added in a minimum height, so that on the destruct it does not get too small.
function resizeIt( id, maxHeight, minHeight ) {
var text = id && id.style ? id : document.getElementById(id);
var str = text.value;
var cols = text.cols;
var linecount = 0;
var arStr = str.split( "\n" );
$(arStr).each(function(s) {
linecount = linecount + 1 + Math.floor(arStr[s].length / cols); // take into account long lines
});
linecount++;
linecount = Math.max(minHeight, linecount);
linecount = Math.min(maxHeight, linecount);
text.rows = linecount;
};
Like the answer of #memical.
However I found some improvements. You can use the jQuery height() function. But be aware of padding-top and padding-bottom pixels. Otherwise your textarea will grow too fast.
$(document).ready(function() {
$textarea = $("#my-textarea");
// There is some diff between scrollheight and height:
// padding-top and padding-bottom
var diff = $textarea.prop("scrollHeight") - $textarea.height();
$textarea.live("keyup", function() {
var height = $textarea.prop("scrollHeight") - diff;
$textarea.height(height);
});
});
My solution not using jQuery (because sometimes they don't have to be the same thing) is below. Though it was only tested in Internet Explorer 7, so the community can point out all the reasons this is wrong:
textarea.onkeyup = function () { this.style.height = this.scrollHeight + 'px'; }
So far I really like how it's working, and I don't care about other browsers, so I'll probably apply it to all my textareas:
// Make all textareas auto-resize vertically
var textareas = document.getElementsByTagName('textarea');
for (i = 0; i<textareas.length; i++)
{
// Retain textarea's starting height as its minimum height
textareas[i].minHeight = textareas[i].offsetHeight;
textareas[i].onkeyup = function () {
this.style.height = Math.max(this.scrollHeight, this.minHeight) + 'px';
}
textareas[i].onkeyup(); // Trigger once to set initial height
}
Here is an extension to the Prototype widget that Jeremy posted on June 4th:
It stops the user from entering more characters if you're using limits in textareas. It checks if there are characters left. If the user copies text into the textarea, the text is cut off at the max. length:
/**
* Prototype Widget: Textarea
* Automatically resizes a textarea and displays the number of remaining chars
*
* From: http://stackoverflow.com/questions/7477/autosizing-textarea
* Inspired by: http://github.com/jaz303/jquery-grab-bag/blob/63d7e445b09698272b2923cb081878fd145b5e3d/javascripts/jquery.autogrow-textarea.js
*/
if (window.Widget == undefined) window.Widget = {};
Widget.Textarea = Class.create({
initialize: function(textarea, options){
this.textarea = $(textarea);
this.options = $H({
'min_height' : 30,
'max_length' : 400
}).update(options);
this.textarea.observe('keyup', this.refresh.bind(this));
this._shadow = new Element('div').setStyle({
lineHeight : this.textarea.getStyle('lineHeight'),
fontSize : this.textarea.getStyle('fontSize'),
fontFamily : this.textarea.getStyle('fontFamily'),
position : 'absolute',
top: '-10000px',
left: '-10000px',
width: this.textarea.getWidth() + 'px'
});
this.textarea.insert({ after: this._shadow });
this._remainingCharacters = new Element('p').addClassName('remainingCharacters');
this.textarea.insert({after: this._remainingCharacters});
this.refresh();
},
refresh: function(){
this._shadow.update($F(this.textarea).replace(/\n/g, '<br/>'));
this.textarea.setStyle({
height: Math.max(parseInt(this._shadow.getHeight()) + parseInt(this.textarea.getStyle('lineHeight').replace('px', '')), this.options.get('min_height')) + 'px'
});
// Keep the text/character count inside the limits:
if($F(this.textarea).length > this.options.get('max_length')){
text = $F(this.textarea).substring(0, this.options.get('max_length'));
this.textarea.value = text;
return false;
}
var remaining = this.options.get('max_length') - $F(this.textarea).length;
this._remainingCharacters.update(Math.abs(remaining) + ' characters remaining'));
}
});
#memical had an awesome solution for setting the height of the textarea on pageload with jQuery, but for my application I wanted to be able to increase the height of the textarea as the user added more content. I built off memical's solution with the following:
$(document).ready(function() {
var $textarea = $("p.body textarea");
$textarea.css("height", ($textarea.attr("scrollHeight") + 20));
$textarea.keyup(function(){
var current_height = $textarea.css("height").replace("px", "")*1;
if (current_height + 5 <= $textarea.attr("scrollHeight")) {
$textarea.css("height", ($textarea.attr("scrollHeight") + 20));
}
});
});
It's not very smooth but it's also not a client-facing application, so smoothness doesn't really matter. (Had this been client-facing, I probably would have just used an auto-resize jQuery plugin.)
For those that are coding for IE and encounter this problem. IE has a little trick that makes it 100% CSS.
<TEXTAREA style="overflow: visible;" cols="100" ....></TEXTAREA>
You can even provide a value for rows="n" which IE will ignore, but other browsers will use. I really hate coding that implements IE hacks, but this one is very helpful. It is possible that it only works in Quirks mode.
Internet Explorer, Safari, Chrome and Opera users need to remember to explicidly set the line-height value in CSS. I do a stylesheet that sets the initial properites for all text boxes as follows.
<style>
TEXTAREA { line-height: 14px; font-size: 12px; font-family: arial }
</style>
Here is a function I just wrote in jQuery to do it - you can port it to Prototype, but they don't support the "liveness" of jQuery so elements added by Ajax requests will not respond.
This version not only expands, but it also contracts when delete or backspace is pressed.
This version relies on jQuery 1.4.2.
Enjoy ;)
http://pastebin.com/SUKeBtnx
Usage:
$("#sometextarea").textareacontrol();
or (any jQuery selector for example)
$("textarea").textareacontrol();
It was tested on Internet Explorer 7/Internet Explorer 8, Firefox 3.5, and Chrome. All works fine.
Using ASP.NET, just simply do this:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Automatic Resize TextBox</title>
<script type="text/javascript">
function setHeight(txtarea) {
txtarea.style.height = txtdesc.scrollHeight + "px";
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:TextBox ID="txtarea" runat= "server" TextMode="MultiLine" onkeyup="setHeight(this);" onkeydown="setHeight(this);" />
</form>
</body>
</html>

Categories