Question

I require Cross compatability IE7 upwards For an event listener. Due to the system I am using I can only use an external js file to create the listeners. I wish to create a rule for all textarea boxes, making they increase in height when they wrap the text meaning that you never have to scroll (They need to be printed with all the text showing). This works fine using addEventListener, but because I can't uses THIS I can not get this to work generically using attachEvent.

<html>
<style>
input[type="text"], textarea{ width:10%;}
</style>
<script>
function gettext(){
var x=document.getElementsByTagName("textarea");
var ent; 
for(i = 0; i < x.length; i++){
if (x.item(i).addEventListener) {
    x.item(i).addEventListener("keyup", function () {ChangeDepth(this)}, false)
    x.item(i).addEventListener("mouseup", function () {ChangeDepth(this)}, false)
    x.item(i).addEventListener("change", function () {ChangeDepth(this)}, false)
 }            
 else {
   ent = document.getElementById(x.item(i).id)
   x.item(i).attachEvent ("onkeyup", function () {ChangeDepth(ent)});
   x.item(i).attachEvent ("onmouseup", function () {ChangeDepth(ent)});
   x.item(i).attachEvent ("onchange", function () {ChangeDepth(ent)});

  }
}
}

function ChangeDepth(e){
var t = e.scrollHeight +'px';
if ((e.clientHeight < e.scrollHeight)||(e.clientHeight > e.scrollHeight)){e.style.height = t ;}
}
</script>
<body onload="gettext()">
<p>(Type in the textarea box when the text wraps it will increase the height of the box)<br />
<textarea name="c" cols="" rows="1" id="c"  ></textarea>
<br />
<textarea name="f" cols="" rows="1" id="f"  ></textarea></p>
</body>
</html>

This only works for the last textarea field in IE 8. I am assuming this because It only has the value of the last object. No idea what to do next

Was it helpful?

Solution

http://jsfiddle.net/KAy9a/

function wireUp() {
    console.log('wiring');
    var x = document.getElementsByTagName("textarea");
    var ent;
    for (i = 0; i < x.length; i++) {
        if (x.item(i).addEventListener) {
            x.item(i).addEventListener("keyup", ChangeDepth, false)
            x.item(i).addEventListener("mouseup", ChangeDepth, false)
            x.item(i).addEventListener("change", ChangeDepth, false)
        }
        else {
            x.item(i).attachEvent("onkeyup", ChangeDepth);
            x.item(i).attachEvent("onmouseup", ChangeDepth);
            x.item(i).attachEvent("onchange", ChangeDepth);

        }
    }
}

function ChangeDepth(e) {
    // instead of passing in the element, we get the Event object
    // we can then get the event target (or srcElement) to know where the event came from    
    e = e || event;
    e = e.target || e.srcElement;

    // the code below is the same you had before:
    var t = e.scrollHeight + 'px';
    if ((e.clientHeight < e.scrollHeight) || (e.clientHeight > e.scrollHeight)) {
        e.style.height = t;
    }
}

OTHER TIPS

You can use a cross–browser addEvent function that sets this to the element within the listener for browsers that use the old IE event model (which includes IE 8 in quirks mode). e.g.

function addEvent(el, evt, fn) {

  if (el.addEventListener) {
    el.addEventListener(evt, fn, false);

  } else if (el.attachEvent) {
    el.attachEvent('on' + evt, function() {fn.call(el);});
  }
}

Now in your code you can do:

function gettext() {
  var x = document.getElementsByTagName("textarea");
  var ent; 

Declare an extra variable to store a reference to the current element.

  var el;

  for (var i = 0; i < x.length; i++) {

Note that i should be declared, otherwise it will become a global variable when the above is executed and possibly mess with other code.

    el = x[i];

Since getElementsByTagName returns a NodeList, you can access members by index, which is less to type. Storing a reference is (imperceptibly) faster and less to type later.

    addEvent(el, 'keyup', ChangeDepth);
    addEvent(el, 'mouseup', ChangeDepth);
    addEvent(el, 'change', ChangeDepth);
 } 

You no longer need to pass a reference to the element since in the listener it will be this. Note that where addEventListener was used to attach the listener, the first argument passed will be the event object. But where attachEvent was used, it won't be passed so get it using window.event.

function ChangeDepth(e) {

  // Get a reference to the related event object
  var e = e || window.event;

  // Get a reference to the element that called the listener
  var elementThatCalledListener  = this;

  ...

}

This seems to work - JavaScript:

function load() {
    'use strict';

    function changeHeight(){
        var elem = document.activeElement;

        var heightStr = elem.scrollHeight +'px';
        if ((elem.clientHeight < elem.scrollHeight) || (elem.clientHeight > elem.scrollHeight))
        {elem.style.height = heightStr ;}
    }

    var x = document.getElementsByTagName("textarea");
    var i;

    for (i = 0; i < x.length; i++) {
        if (x[i].addEventListener) {
            x[i].addEventListener("keyup", changeHeight)
            x[i].addEventListener("mouseup", changeHeight)
            x[i].addEventListener("change", changeHeight)
        }
        else {
            x[i].attachEvent("onkeyup", changeHeight);
            x[i].attachEvent("onmouseup", changeHeight);
            x[i].attachEvent("onchange", changeHeight);
        }
    }
}

if (window.addEventListener) {
    window.addEventListener('load', load);
} else if (window.attachEvent) {
    window.attachEvent('onload', load);
}

HTML:

<!DOCTYPE html>
<style>
    input[type="text"], textarea {
        width: 10%;
    }
</style>
<p>(Type in the textarea box when the text wraps it will increase the height of the box)<br/>
    <textarea rows='1'></textarea>
    <br/>
    <textarea rows='1'></textarea>
</p>
<script type="text/javascript" src="legacyEventIE.js"></script>
</body>
</html>

Here is a link to the working code:

http://www.quirkscode.com/flat/forumPosts/legacyEventIE/legacyEventIE.html

You should avoid creating functions inside loops. This causes problems because the variables used are closure-scoped to the encapsulating function and therefore are common to all the "new" functions.

In other words:

var i, fns = [];
for(i = 0; i < 10; i++) {
    fns.push(function () { return i; });
}

Will create 10 functions that all return 10 (or whatever i ends up being):

fn[0](); //is 10
fn[5](); //is 10
i = 5;
fn[5](); //is 5

There are a few ways to fix this. The first is to use a function wrapper and pass in the dynamic variable as an argument. Like so:

ent = document.getElementById(x.item(i).id)
(function (my_ent, my_i) {
    x.item(my_i).attachEvent ("onkeyup", function () {ChangeDepth(my_ent)});
    x.item(my_i).attachEvent ("onmouseup", function () {ChangeDepth(my_ent)});
    x.item(my_i).attachEvent ("onchange", function () {ChangeDepth(my_ent)});
}(ent, i));

Another, arguably better, solution (at least one that won't cause JSLint to yell at you) is to create a generator function:

var attachEvents = function (item, ent) {
    item.attachEvent ("onkeyup", function () {ChangeDepth(ent)});
    item.attachEvent ("onmouseup", function () {ChangeDepth(ent)});
    item.attachEvent ("onchange", function () {ChangeDepth(ent)});
};

//... Inside the for loop:
    else {
        ent = document.getElementById(x.item(i).id)
        attachEvents(x.item(i), ent);
    }

This is better because its not as "heavy" and it is easier to determine what data are relevant to the creation of the event handlers (e.g. it's easier to maintain).

But it does require more of a change. So it's up to you.

var add_event_column_rubrics = function(){
    var id_current_event;
    var secect_class_column_rubrics = document.querySelector('.rubric_click');

    if(secect_class_column_rubrics.addEventListener)//other
        secect_class_column_rubrics.addEventListener('click',function(e){f_secect_class_column_rubrics(e)},false);
    else{if(secect_class_column_rubrics.attachEvent)//IE
        secect_class_column_rubrics.addEventListener('onclick',f_secect_class_column_rubrics);
}

    var f_secect_class_column_rubrics = function(e){
        e=e||window.event;
        e=e.target||e.srcElement;`enter code here`
        // console.log(e);//debug
        id_current_event = e.id;
        alert(id_current_event);
    };
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top