0

I'm working on a project based on schools and one of the features we have is school finder.

Because schools like to continue using Windows XP and stuck with Internet Explorer 1 (pun intended), I'm trying to use tradition javascript, rather than jQuery to support all browsers.

The problem is, the schools listed from the database are put into tables, each having a custom attribute called data-school-id with a value of sch-X

I am truly stuck on how to get javascript to read these values when the user clicks on the school's table cell. This is the code I currently have:

var schID = document.getElementById("data-school-id");
schID.addEventListener("click", function() {
    alert(schID.value);
}, false);

I need to grab the numeric value, though I already know how to do that. It's getting javascript to understand the dynamic attributes and it's value for each table cell that I'm stuck on.

Each of the table cells are as so:

<td data-school-id="sch-123">
    <div class="pull-left sch-logo">
        <img src="#" width="100" height="100">
    </div>
    <div class="pull-left">
        <h3>School Name</h3>
        <p><strong>Headteacher:</strong> Mr. Foo Bar</p>
    </div>
</td>
TechKat
  • 187
  • 2
  • 5
  • 14
  • 1
    You might look at [sizzle.js](http://sizzlejs.com/). `getElementById()` only works when the value is in the `id` attribute itself. – Jared Farrish Aug 22 '13 at 13:44
  • 2
    *"Because schools like to continue using Windows XP and stuck with Internet Explorer 1 (pun intended), I'm trying to use tradition javascript, rather than jQuery to support all browsers."* Wouldn't jQuery be a better option than trying to take care of all the browser incompatibilities yourself? – Felix Kling Aug 22 '13 at 13:45
  • Felix, I work in a school and half the computers here are still using Windows XP and Internet Explorer 8. We've tried jQuery on some of them and they just don't work right. – TechKat Aug 22 '13 at 13:47
  • You have to use @FelixKling to message someone specifically unless it's the OP or the answerer. IE8 and jQuery are completely compatible; you're not doing *something* right otherwise. – Jared Farrish Aug 22 '13 at 13:50
  • 1
    I agree, JQuery provides support that goes back as far as IE 7. – Craig Aug 22 '13 at 13:52
  • To be honest, I'm mostly confused about `var schID = document.getElementById("data-school-id");`, because you are mentioning custom attributes before. But this line of code would search for an element with the ID `data-school-id`. Is there really an element which has the same ID name as an attribute name? You really should clarify your question. – Felix Kling Aug 22 '13 at 13:55
  • `data-school-id` is the attribute. I think I realized now that getElementById only works on `id` attributes. – TechKat Aug 22 '13 at 14:00
  • You really want something like `document.querySelector('[data-school-id]')` or `document.querySelectorAll('[data-school-id]')` or `jQuery('[data-school-id]')`. I don't believe IE8 and lower support the former two, which is why jQuery is handy for query selecting. – Jared Farrish Aug 22 '13 at 14:00
  • @Jared: IE8 supports `querySelector` and `querySelectorAll`, not sure about attribute selectors though. – Felix Kling Aug 22 '13 at 14:01
  • And your problem is binding a handler to all elements that have the attribute? Or getting the attribute value inside the handler? Note that `addEventListener` is not supported by older IE versions either. – Felix Kling Aug 22 '13 at 14:01
  • @FelixKling - It should work like this: School > User clicks it > Javascript gets the value of `data-school-id` > uses value to register a cookie with that value. – TechKat Aug 22 '13 at 14:03

5 Answers5

1

Access it using the getAttribute method:

schID.getAttribute("data-school-id");

Update:

To convert it to a numeric value, wrap it like so:

var id = schID.getAttribute("data-school-id"),
    n = parseInt(id, 10);

I think you are also going to have trouble with your element lookup. Are you sure the table cells are created as so:

<td>
    <div id="data-school-id" data-school-id="123"/>
</td>

Why not inspect the HTML of the table and provide a little more in your question?

Update 2:

You need to add a click handler to the table and handle events that bubble up from TD elements. Use the event.target or event.source (check IE 8 documentation for those attributes). That will give you the reference to the element:

function handler(evt) {
    evt = evt || window.event;

    var td = evt.targetElement,
        schoolId = td.getAttribute("data-school-id"),
        numSchoolId = parseInt(schoolId, 10);
}
Craig
  • 4,268
  • 4
  • 36
  • 53
  • Need also to give the element an `id`, and use that in the `getElementById` call. – Tim Mac Aug 22 '13 at 13:45
  • I changed it to that and still nothing. I also removed the .value from the alert, that didn't work either. – TechKat Aug 22 '13 at 13:46
  • As per my update, can you provide some HTML for us to be able to understand what it is you are trying to do? – Craig Aug 22 '13 at 13:50
  • It's `event.srcElement` in IE and `event.target` in all other browsers. But `addEventListener` doesn't work in IE8 anyways. – Felix Kling Aug 22 '13 at 14:02
1

I would strongly recommend you revisit the idea of using JQuery, just be sure to use the older versions that support IE 6 (before 2.0) -- If the IE version is older than 6.0 tell them politely that they must update their browser if they say no -- you are working in a dysfunctional environment, find a new job. Not even Microsoft will support IE6 past April 8 2014 -- XP will be no more as far as they are concerned.

I have supported quite a bit a IE6 code using JQuery and it worked great. Your issues may be the lousy CSS support in IE6, or other incompatibilities, but they are unlikely to be JQuery themselves in my experience. You will have a codebase that is even more trapped in IE land if you continue down this path.

Gary Walker
  • 8,831
  • 3
  • 19
  • 41
0
function getElementWithAttribute(attribute)
{
  var allElements = document.getElementsByTagName('*');
  for (var i = 0; i < allElements.length; i++)
  {
    if (allElements[i].getAttribute(attribute))
    {
      return allElements[i];
    }
  }
  return null;
}

var el = getElementWithAttribute('data-school-id');

if(el != null){
    el.addEventListener("click", function() {
        alert(el.value);
     }
}
Mister Epic
  • 16,295
  • 13
  • 76
  • 147
  • How about citing source: http://www.stephanmuller.nl/element-attribute-plain-javascript/? Also, removing value from that function makes it nearly useless. It will only ever return the first element. Successive elements are unreachable. – Jo Are By Aug 22 '13 at 13:55
  • I had copied this from a project I had worked on, I wasn't aware this code was lifted from somewhere else or I would have cited. The OP seemed to indicate he wants a single element returned, so I edited it as such. – Mister Epic Aug 22 '13 at 14:12
  • Valid point. I found the page while googling for getElementsByAttr too see if there was such a function in the DOM. Since attribute names are not unique in a html document, I would recommend providing at least the possibility of reaching multiple elements. A single element is easily extracted from a list of many, while the opposite is impossible. I provided a function based on yours, which returns a list of all matching elements. – Jo Are By Aug 22 '13 at 14:24
0

Add a class reserved for the elements with data-school-id attribute. "school-elem" for example.

Use:

var schElems, i;

schElems = document.getElementsByClassName("school-elem");

for (i = 0; i < schElems.length; ++i) {
    alert(schElems[i].getAttribute('data-school-id'));
}

If you're unable to add a class (or use getElementsByClassName):

var schElems, i;

function getElementsByAttr(attr) {
    var allElems, attrElems, i;
    allElems = document.getElementsByTagName('*');
    attrElems = [];
    for (i = 0; i < allElems.length; ++i) {
        if (allElems[i].hasAttribute(attr)) attrElems.push(allElems[i]);
    }
    return attrElems;
}

schElems = getElementsByAttr('data-school-id');

for (i = 0; i < schElems.length; ++i) {
    alert(schElems[i].getAttribute('data-school-id'));
}
Jo Are By
  • 3,293
  • 1
  • 11
  • 11
0

1) If you don't want to use jQuery you have to write a function which finds a DOM elm by data-attribute ( there're a lot of answers in Stack Overflow - ex Get elements by attribute when querySelectorAll is not available without using libraries? ). This part of code:

function getAllElementsWithAttribute(attribute)
{
  var matchingElements = [];
  var allElements = document.getElementsByTagName('*');
  for (var i = 0; i < allElements.length; i++)
  {
    if (allElements[i].getAttribute(attribute)){
      matchingElements.push(allElements[i]);
    }
  }
  return matchingElements;
}

2) You have to add even listener 'cross browser'. Because IE6-8 doesn't know method - addEventListener it knows attachEvent. This part of code:

function addEvent(elem, type, handler){
    if (elem.addEventListener){
       elem.addEventListener(type, handler, false)
    } else {
       elem.attachEvent("on"+type, handler)
    }
}

3) After that you can write smth like that:

var el = getAllElementsWithAttribute('data-school-id')[0],
    elClick = function(){ alert('1') };

addEvent(el, 'click', elClick);

4) If you want to know the property of data-attribute you can do that:

 var attr = el.getAttribute('data-school-id'); // "sch-123"

getAttribute works good in IE8 http://msdn.microsoft.com/en-us/library/ie/ms536429(v=vs.85).aspx

Community
  • 1
  • 1
wrt
  • 21
  • 1
  • 4