3

I have the following HTML check box

<input name="1" title="" id="1"  style="position: absolute; top: 333px; left: 760px; tabindex: 11; z-order: 99;" type="checkbox" CHECKED="checked" runat="server" value="on"/>

I want to grab the value given for tabindex inside the style attribute above. Things to note:

  1. I know that tabindex is in the wrong place (it shouldn't be in the style attribute text, it should be an attribute on its own). I can't change that, it's done by a (very old) tool I can't modify.

  2. I have to support IE8, and when I tried I ran into an issue with IE8 not handling \s in regular expressions quite correctly (it doesn't match hard spaces).

I tried to use .search() to do this but I don't know how to return the string value when I'm searching for my checkbox with the following line:

var test = document.getElementsByTagName("input");

The goal is to grab the value for tabindex from the style attribute and then assign it to the element correctly.

Community
  • 1
  • 1
Sean
  • 897
  • 4
  • 20
  • 42
  • Why are you using string manipulation, instead of using the element in the DOM? – freefaller May 13 '15 at 09:16
  • Any reason you are not using the DOM? – Sverri M. Olsen May 13 '15 at 09:16
  • I've no idea how to do either of that. The tab index is set in another location which for some reason places it in the Style portion. As this isn't valid CSS, it's ignored. I need to take that value and place it in the proper HTML element TabIndex – Sean May 13 '15 at 09:19

3 Answers3

9

Updated Answer:

Re your comment:

I know it's in the wrong place, but I've no way of manually moving it.

Okay, so that's why we're using regex, gotcha.

So we have two tasks here:

  1. Get the text of the style attribute, which should be easy but is stupidly difficult on IE8.

  2. Get the value of the tabindex from that text.

First, getting the style attribute text: Unfortunately, by default IE8 will display "intranet" sites in the ridiculously-misnamed "compatibility view". (That is: Compatible with old broken IE7 and earlier, not compatible with, you know, standards.) And IE7 and earlier had a horrible bug: element.getAttribute("style") gave you the style object, not the style attribute text; the same object you get with element.style. And although they fixed that in IE8, in compatibility view it's broken (to be..."compatible").

So this:

var text = element.getAttribute("style"):

...will give us a string on any decent browser, and on IE8 when not in compatibility view, but will give us an object when in compatibility view.

So to get the text we have to look elsewhere. Fortunately, Microsoft were the ones who pioneered innerHTML and outerHTML, so we can do this:

var text = element.getAttribute("style"):
if (typeof text !== "string") {
    text = element.outerHTML;
}

That gives us more than just the style text, of course, but it's close enough. We're still not trying to parse HTML with regex (although we're pushing it a bit with outerHTML, but it's on an input and so fairly contained), we're looking for a limited thing within a limited string..

Now from that text we need the tabindex value: This expression matches tabIndex (case-insensitive) followed by any whitespace followed by : followed by whitespace followed by some number of digits, which we capture:

/\btabindex\s*:\s*(\d+)/i

We can then use the capture group to get the value from the incorrect location and set it in the correct location:

var element = document.getElementById("1");
var text = element.getAttribute("style");
if (typeof text !== "string") {
    // Bad IE! Bad!
    text = element.outerHTML;
}
var match = /\btabindex\s*:\s*(\d+)/i.exec(text);
var index = match && match[1];
if (index) {
    element.setAttribute("tabindex", index);
}
alert("Index: " + (index || "unknown"));

Live Example:

var element = document.getElementById("1");
var text = element.getAttribute("style");
if (typeof text !== "string") {
    // Bad IE! Bad!
    text = element.outerHTML;
}
var match = /\btabindex\s*:\s*(\d+)/i.exec(text);
var index = match && match[1];
if (index) {
    element.setAttribute("tabindex", index);
}
alert("Index: " + (index || "unknown"));
<input name="1" title="" id="1"  style="position: absolute; top: 333px; left: 760px; tabindex: 11; z-order: 99;" type="checkbox" CHECKED="checked" runat="server" value="on"/>

Re your comment:

But would the above still work if i changed the first line to document.getElementsByTagName("input");

Sure, you just do it in a loop:

var list, index, element, text, match;
list = document.getElementsByTagName("input");
for (index = 0; index < list.length; ++index) {
    element = list[index];
    text = element.getAttribute("style");
    if (typeof text !== "string") {
        // Bad IE! Bad!
        text = element.outerHTML;
    }
    match = /\btabindex\s*:\s*(\d+)/i.exec(text);
    tabindex = match && match[1];
    if (tabindex) {
        element.setAttribute("tabindex", tabindex);
    }
}

(I called the tabindex tabindex there, since loop indexes are frequently called index.)


Original Answer:

Your tabIndex is in the wrong place: It's not a style property, it's a stand-alone attribute:

<input name="1" title="" id="1" tabindex="11" style="position: absolute; top: 333px; left: 760px; z-order: 99;" type="checkbox" CHECKED="checked" runat="server" value="on"/>
<!-- Here ----------------------^                                                       -->

Then use the tabIndex reflected property:

var index = document.getElementById("1").tabIndex;

Live Example:

alert(document.getElementById("1").tabIndex);
<input name="1" title="" id="1" tabindex="11" style="position: absolute; top: 333px; left: 760px; z-order: 99;" type="checkbox" CHECKED="checked" runat="server" value="on"/>

Side note: While valid in HTML, id values starting with digits are very difficult to work with in CSS; best to avoid them.

Community
  • 1
  • 1
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • @Sean: There you go. Works on IE8, even with intranet sites. I'm so glad IE is better now. :-) – T.J. Crowder May 13 '15 at 12:28
  • Thank you. But would the above still work if i changed the first line to `document.getElementsByTagName("input");` – Sean May 13 '15 at 12:45
  • @Sean: That'll return you a list. You'll have to loop through the list (it has a `length` property, and you index into it like an array, starting with 0, to get each element). But if you do that for each element, sure, it'll work. – T.J. Crowder May 13 '15 at 12:52
  • @Sean: Enh, I went ahead and added an example loop. :-) – T.J. Crowder May 13 '15 at 12:56
0

Never parse HTML elements by regex. See this question for some fun.

If you have an HTML element you can access all of it's attributes either via .getAttribute or in case of CSS style attributes using for example .style.top for the top attribute.

The problem in your case is probably that you are placing your tabindex property inside the style attribute. According to this page, you should set it as a separate attribute, so you can get it afterwards by

document.getElementById("1").getAttribute("tabindex");
Community
  • 1
  • 1
Dropout
  • 13,653
  • 10
  • 56
  • 109
0

First, you should use getElementById which is more appropriate in complex scenarios. If you want to access the raw string value of your attribute you can use:

document.getElementById("1").getAttribute("style")

and then process it as you wish (using search, substr, etc.)

Chuck
  • 998
  • 8
  • 17
  • 30
dcremo
  • 11
  • 1