Rectangle 27 22

Non-standard tags and JavaScript (via the DOM)

There are a few things about the other answers that are either just poorly phrased or perhaps a little incorrect.

Not necessarily. They're "non-conforming". What's the difference? Something can "not conform" and still be "allowed". The W3C aren't going to send the HTML police to your home and haul you away.

The W3C left things this way for a reason. Conformance and specifications are defined by a community. If you happen to have a smaller community consuming HTML for more specific purposes and they all agree on some new Elements they need to make things easier, they can have what the W3C refers to as "other applicable specifications". (this is a gross over simplification, obviously, but you get the idea)

That said, strict validators will declare your non-standard elements to be "invalid". but that's because the validator's job is to ensure conformance to whatever spec it's validating for, not to ensure "legality" for the browser or for use.

Possibly, but unlikely. (replace "will" with "might") The only way this should result in a rendering issue is if your custom element conflicts with another specification, such as a change to the HTML spec or another specification being honored within the same system (such as SVG, Math, or something custom).

the reason CSS can style non-standard tags

User agents must treat elements and attributes that they do not understand as semantically neutral; leaving them in the DOM (for DOM processors), and styling them according to CSS (for CSS processors), but not inferring any meaning from them

Note: if you want to use a custom tag, just remember a change to the HTML spec at a later time could blow your styling up, so be prepared. It's really unlikely that the W3C will implement the <imsocool> tag, however.

The reason you can access and alter custom elements using JavaScript is because the specification even talks about how they should be handled in the DOM, which is the (really horrible) API that allows you to manipulate the elements on your page.

The HTMLUnknownElement interface must be used for HTML elements that are not defined by this specification (or other applicable specifications).

var wee = document.createElement('wee');
console.log(wee.toString()); //[object HTMLUnknownElement]

(I'm sure this will draw flames, but there's my 2 cents)

Not only does HTML specify how elements should be treated w.r.t. CSS, the CSS spec is, for the most part, document language-agnostic by design as well (this is already kinda-sorta implied in some other answers, but I note it here for convenience). If there's any behavior that is specific to HTML and/or XHTML, it is always indicated, even in informative text (e.g. "an HTML element's ID is specified by the id attribute"), not just normative text (see Backgrounds and Borders 3 for an example).

html - Why does CSS work with fake elements? - Stack Overflow

html css
Rectangle 27 22

Non-standard tags and JavaScript (via the DOM)

There are a few things about the other answers that are either just poorly phrased or perhaps a little incorrect.

Not necessarily. They're "non-conforming". What's the difference? Something can "not conform" and still be "allowed". The W3C aren't going to send the HTML police to your home and haul you away.

The W3C left things this way for a reason. Conformance and specifications are defined by a community. If you happen to have a smaller community consuming HTML for more specific purposes and they all agree on some new Elements they need to make things easier, they can have what the W3C refers to as "other applicable specifications". (this is a gross over simplification, obviously, but you get the idea)

That said, strict validators will declare your non-standard elements to be "invalid". but that's because the validator's job is to ensure conformance to whatever spec it's validating for, not to ensure "legality" for the browser or for use.

Possibly, but unlikely. (replace "will" with "might") The only way this should result in a rendering issue is if your custom element conflicts with another specification, such as a change to the HTML spec or another specification being honored within the same system (such as SVG, Math, or something custom).

the reason CSS can style non-standard tags

User agents must treat elements and attributes that they do not understand as semantically neutral; leaving them in the DOM (for DOM processors), and styling them according to CSS (for CSS processors), but not inferring any meaning from them

Note: if you want to use a custom tag, just remember a change to the HTML spec at a later time could blow your styling up, so be prepared. It's really unlikely that the W3C will implement the <imsocool> tag, however.

The reason you can access and alter custom elements using JavaScript is because the specification even talks about how they should be handled in the DOM, which is the (really horrible) API that allows you to manipulate the elements on your page.

The HTMLUnknownElement interface must be used for HTML elements that are not defined by this specification (or other applicable specifications).

var wee = document.createElement('wee');
console.log(wee.toString()); //[object HTMLUnknownElement]

(I'm sure this will draw flames, but there's my 2 cents)

Not only does HTML specify how elements should be treated w.r.t. CSS, the CSS spec is, for the most part, document language-agnostic by design as well (this is already kinda-sorta implied in some other answers, but I note it here for convenience). If there's any behavior that is specific to HTML and/or XHTML, it is always indicated, even in informative text (e.g. "an HTML element's ID is specified by the id attribute"), not just normative text (see Backgrounds and Borders 3 for an example).

html - Why does CSS work with fake elements? - Stack Overflow

html css
Rectangle 27 36

The Problem: DOM Requires <tbody/> Tags

Firebug, Chrome's Developer Tool, XPath functions in JavaScript and others work on the DOM, not the basic HTML source code.

The DOM for HTML requires that all table rows not contained in a table header of footer (<thead/>, <tfoot/>) are included in table body tags <tbody/>. Thus, browsers add this tag if it's missing while parsing (X)HTML. For example, Microsoft's DOM documentation says

The tbody element is exposed for all tables, even if the table does not explicitly define a tbody element.

The TBODY start tag is always required except when the table contains only one table body and no table head or foot sections.

Excluding JavaScript, most XPath processors work on raw XML, not the DOM, thus do not add <tbody/> tags. Also HTML parser libraries like tag-soup and htmltidy only output XHTML, not "DOM-HTML".

This is a common problem posted on Stackoverflow for PHP, Ruby, Python, Java, C#, Google Docs (Spreadsheets) and lots of others. Selenium runs inside the browser and works on the DOM -- so it is not affected!

Compare the source shown by Firebug (or Chrome's Dev Tools) with the one you get by right-clicking and selecting "Show Page Source" (or whatever it's called in your browsers) -- or by using curl http://your.example.org on the command line. Latter will probably not contain any <tbody/> elements (they're rarely used), Firebug will always show them.

Check if the table you're stuck at really does not contain a <tbody/> element (see last paragraph). If it does, you've probably got another kind of problem.

/tbody

This is a rather dirty solution and likely to fail for nested tables (can jump into inner tables). I would only recommend to to this in very rare cases.

Replace the /tbody axis step by a descendant-or-self step:

//table[@id="example"]//tr[2]/td[1]

If you're not sure in advance that your table or use the query in both "HTML source" and DOM context; and don't want/cannot use the hack from solution 2, provide an alternative query (for XPath 1.0) or use an "optional" axis step (XPath 2.0 and higher).

//table[@id="example"]/tr[2]/td[1] | //table[@id="example"]/tbody/tr[2]/td[1]
//table[@id="example"]/(tbody, .)/tr[2]/td[1]

In addition to what was stated above, for my scraper on these scenarios, I have a flag for "skipFirstRow" which actually works perfectly (for the pages I'm scraping).

I've been searching for a solution for 4 hours, because the data I wanted from a site didn't want to be mine. All the values were easy by their xpaths, however one of the tables returned an error, and the solution was to delete tbody and replace it with an extra /.

dom - Why does my XPath query (scraping HTML tables) only work in Fire...

html dom xpath firebug google-chrome-devtools
Rectangle 27 2

It won't be ignored. It will be added to the DOM as an unknown element. (spec).

JavaScript is not HTML. It will be parsed as if it was JavaScript. Since it isn't valid, it will throw an exception.

Since it is after a <script> tag, before a </script> tag and is a "tag" that isn't </script>: the HTML parser does not treat it as a tag and passes it through to the JavaScript engine. (spec)

Since it is not valid JS, the JS engine will throw an exception.

What happens in HTML to an unknown element - does it affect the rendering of the page?

It gets added to the DOM. From there it can influence the rendering of the page.

In what way can it influence the rendering of the page - i.e. the Browser doesn't recognize it

I tried out embedded javascript - it doesn't throw an exception, but javascript engine ignores whatever is between the tags.

SyntaxError: syntax error 	  <XYZ MY TAG>

non standard tags in HTML, in Javascript and in Javascript embedded in...

javascript html standards
Rectangle 27 2

  • Via the DOM API, copy a reference to a property of a DOM node (the "value" property of the <input> element) to a JavaScript variable.
  • Perform a JavaScript string concatenation operation. At that point, it absolutely does not matter what the string of characters is.
  • Pass the result string to the window.alert(). The "alert()" function always treats its argument strictly as a string. The only "special" character is newline, and all that does is cause text to wrap to a new line.
window.alert("<script>var u_r_so_hacked = true;</script>");

will show the "" tags just like that, angle brackets and all.

are you sure about this quote? "The "alert()" function always treats its argument strictly as a string". It does not - if you just put alert(document.cookie); then the resulting alertbox will have the contents of the cookie for the page (not the string document.cookie). In other words document.cookie is evaluated before being given to alert() for display. This is what I'm trying to understand if it can happen or not with my snippet

Well "document.cookie" is a string. By "treats its argument as a string" I mean that it treats the value of the argument as a string. It's just JavaScript; calling alert with a string constant is no different than calling alert with a variable that refers to a string. And, I repeat, your users can already get all the cookies in their browsers. All of them, without exception. You cannot hide cookie values from your users.

alert("Error in " + document.cookie) is not a string. But alert("You got it " + "document.cookie") is a string. Op had the first one. But indeed a user can already grab all cookies in their browsers. I believe that the good thing here is that there is no way for this code / text to return to the malicious user, thus it's safe.

javascript - Is this vulnerable to dom-based xss? - Stack Overflow

javascript html xss security
Rectangle 27 9

Wrap your code in a DOM Load callback:

Your script is being executed before the body element has even loaded.

There are a couple ways to workaround this.

Wrap your logic in an event listener for DOMContentLoaded.

In doing so, the callback will be executed when the body element has loaded.

document.addEventListener('DOMContentLoaded', function () {
    // ...
    // Place code here.
    // ...
});

Depending on your needs, you can alternatively attach a load event listener to the window object:

window.addEventListener('load', function () {
    // ...
    // Place code here.
    // ...
});
DOMContentLoaded
load

Right now, your <script> element is being loaded in the <head> element of your document. This means that it will be executed before the body has loaded. Google developers recommends moving the <script> tags to the end of your page so that all the HTML content is rendered before the JavaScript is processed.

<!DOCTYPE html>
<html>
<head></head>
<body>
  <p>Some paragraph</p>
  <!-- End of HTML content in the body tag -->

  <script>
    <!-- Place your script tags here. -->
  </script>
</body>
</html>

I think this is more thorough and current than the accepted answer.

google chrome - Why is document.body null in my javascript? - Stack Ov...

javascript google-chrome
Rectangle 27 5

Javascript tags, even if they're loading an external file via the src= attribute, can't be self closing. You may need to add some non-empty content to the DOM element you're creating to force it to be non-self closing. A textnode with a single space would do.

OK changing $script = $document->createElement ( 'script', '' ); to $script = $document->createElement ( 'script', ' ' ); produces <script src="script.js"> </script> Thanks for that. Now how can I get DOmDocument to produce <script src="script.js"></script> i.e. without the extra space?

That I don't know. Wonder if it does that for all tags, or are JS tags buggy? Try creating a <p> with no content and see if that self closes.

For reference, adding a completely empty text node does the job, it doesn't even need to have a space in it.

php - How to use DOMDocument to add script to HTML5 - Stack Overflow

php html5 domdocument
Rectangle 27 9

meta-tags are part of the dom and can be accessed and -i guess- changed, but search-engines (the main consumers of meta-tags) won't see the change as the javascript won't be executed. so unless you're changing a meta-tag (refresh comes to mind) which has implications in the browser, this might be of little use?

+1 - I landed on this question because I was wondering specifically about meta refresh. I am creating an app which uses ajax polling to refresh the data on screen and I want to provide a crude fallback for browsers that do not have javascript enabled. I am thinking that I could accomplish this by creating a meta refresh tag by default and if javascript is enabled, just remove the meta tag. - Now to see if it actually works...

@futtta, the meta description tag is used for bookmark descriptions in Opera, so there is actually a benefit to the user that your meta description can be changed.

jquery - Is it possible to use JavaScript to change the meta-tags of t...

javascript jquery meta-tags
Rectangle 27 9

meta-tags are part of the dom and can be accessed and -i guess- changed, but search-engines (the main consumers of meta-tags) won't see the change as the javascript won't be executed. so unless you're changing a meta-tag (refresh comes to mind) which has implications in the browser, this might be of little use?

+1 - I landed on this question because I was wondering specifically about meta refresh. I am creating an app which uses ajax polling to refresh the data on screen and I want to provide a crude fallback for browsers that do not have javascript enabled. I am thinking that I could accomplish this by creating a meta refresh tag by default and if javascript is enabled, just remove the meta tag. - Now to see if it actually works...

@futtta, the meta description tag is used for bookmark descriptions in Opera, so there is actually a benefit to the user that your meta description can be changed.

jquery - Is it possible to use JavaScript to change the meta-tags of t...

javascript jquery meta-tags
Rectangle 27 13

I'm no expert with DOM or Javascript/Typescript but I think that the DOM-Tags can't handle real javascript object somehow. But putting the whole object in as a string and parsing it back to an Object/JSON worked for me:

interface TestObject {
  name:string;
  value:number;
}

@Component({
  selector: 'app',
  template: `
      <h4>Select Object via 2-way binding</h4>

      <select [ngModel]="selectedObject | json" (ngModelChange)="updateSelectedValue($event)">
        <option *ngFor="#o of objArray" [value]="o | json" >{{o.name}}</option>
      </select>

      <h4>You selected:</h4> {{selectedObject }}
  `,
  directives: [FORM_DIRECTIVES]
})
export class App {
  objArray:TestObject[];
  selectedObject:TestObject;
  constructor(){
    this.objArray = [{name: 'foo', value: 1}, {name: 'bar', value: 1}];
    this.selectedObject = this.objArray[1];
  }
  updateSelectedValue(event:string): void{
    this.selectedObject = JSON.parse(event);
  }
}

Thank you. I haven't tested it, but it looks like it would work. It's still non-obvious and clunky, so I hope that the ng2 team comes up with a more direct approach, but it's a definite option.

updateSelectedValue(event:string)
updateSelectedValue(event: Object)
this.selectedObject = JSON.parse(event.target.value);
stringify()
[ngModel] = "selectedObject | json"
[value]="o | json"
*ngFor="#o of objArray"
*ngFor="let o of objArray"

typescript - How to use select/option/NgFor on an array of objects in ...

typescript angular
Rectangle 27 13

I'm no expert with DOM or Javascript/Typescript but I think that the DOM-Tags can't handle real javascript object somehow. But putting the whole object in as a string and parsing it back to an Object/JSON worked for me:

interface TestObject {
  name:string;
  value:number;
}

@Component({
  selector: 'app',
  template: `
      <h4>Select Object via 2-way binding</h4>

      <select [ngModel]="selectedObject | json" (ngModelChange)="updateSelectedValue($event)">
        <option *ngFor="#o of objArray" [value]="o | json" >{{o.name}}</option>
      </select>

      <h4>You selected:</h4> {{selectedObject }}
  `,
  directives: [FORM_DIRECTIVES]
})
export class App {
  objArray:TestObject[];
  selectedObject:TestObject;
  constructor(){
    this.objArray = [{name: 'foo', value: 1}, {name: 'bar', value: 1}];
    this.selectedObject = this.objArray[1];
  }
  updateSelectedValue(event:string): void{
    this.selectedObject = JSON.parse(event);
  }
}

Thank you. I haven't tested it, but it looks like it would work. It's still non-obvious and clunky, so I hope that the ng2 team comes up with a more direct approach, but it's a definite option.

updateSelectedValue(event:string)
updateSelectedValue(event: Object)
this.selectedObject = JSON.parse(event.target.value);
stringify()
[ngModel] = "selectedObject | json"
[value]="o | json"
*ngFor="#o of objArray"
*ngFor="let o of objArray"

typescript - How to use select/option/NgFor on an array of objects in ...

typescript angular
Rectangle 27 1

There is nothing you need to do. Browsers are expected to ignore unknown tags, and they do, so they see <noindex>foo</noindex> just as foo. Well, not quite. Technically, modern browsers construct an element node (of type HTMLUnknownElement) in the DOM. But the element has no associated default styling and no associated action, so its really a dummy element and represents its content only.

It would be possible to remove such elements nodes using client-side JavaScript, but that would be quite unnecessary.

The only real risk is that some day some specification or some browser or some web-wide indexing robot might start treating noindex as a real element with some defined meaning, possibly with default rendering and default functionality. Then you would be in trouble if these differ from what you expected. But its a rather small risk, and it seems that you dont have a choice.

html - Adobe Search&Promote non-standard tag - Stack Overflo...

html html5 adobe standards standards-compliance
Rectangle 27 1

Firstly, you need to ensure that the tag exists when the javascript is called. I do this by waiting until all elements, images and scripts have been loaded.

Next, you don't need to use an id - you can grab it with any number of methods. The NodeList returned by getElementsByTagName is live and as such, changes size to reflect operations on the collection of elements it represents - this is why there's only one call needed to getElementsByTagName.

I forget the specifics, but I read about it the other day. either querySelector/querySelectorAll may have been the odd one out - returning an array that doesn't change as the document does. Dunno, probably mostly irrelevant here anyway.

Here's a working sample:

EDIT: Code altered. (1) to fire on a button press, so you can see the effect in the DOM viewer of your browser's JS tools. (2) moved the noscript tag to the head

<!doctype html>
<html>
<head>
    <noscript>You appear to have javascript disabled</noscript>
    <script>
    window.addEventListener('load', onDocLoaded, false);
    function onDocLoaded(evt)
    {
    //  nukeNoscripts();
    }

    function nukeNoscripts()
    {
        var tgtTags = document.getElementsByTagName('noscript');
        alert("Num of noscript tags: " + tgtTags.length);
        var tgt = tgtTags[0];
        tgt.parentNode.removeChild(tgt);
        alert("Num of noscript tags: " + tgtTags.length);
    }
    </script>
</head>
<body>
    <button onclick='nukeNoscripts()'>NUKE</button>
</body>
</html>

dom - Remove a noscript tag inside the head tag with JavaScript - Stac...

javascript dom
Rectangle 27 1

Your javascript is executed before the DOM has been loaded. Put all <script>-Tags just before the closing </body> tag.

About Your javascript is executed before the DOM has been loaded., if you place the <script> right before </body> then the DOM is - technically - still not fully loaded at the time the document.getElementById('ii') is exectued. To DOM is still only partially loaded, but it contains the ii element because the <script> tag is placed after the element with the id ii.

javascript - the code is running fine on the web, but why am i getting...

javascript html
Rectangle 27 5

Other than other JavaScript libraries creating these shorthands, I am not aware of any that are built into the language. It would be trivial to map this to your own shorthand:

var $ = document.getElementsByTagName;

// you can then use it like so:
$('SPAN').// and so on

Other than this, there is no built-in array-like access to all of the tags in the document:

While I was unaware that could be done and it's a nifty bit a knowledge to have, I still am curious about how many of these built-in alternatives exist. Two already exist that I know of, as mentioned in my question. I'd like more information on that rather than alternatives.

getElementsByTagName
document
var $ = function () { return document.getElementByTagName.apply(document, arguments); }

Agreed, I am merely pointing out how trivial it would be to create a mapping of this nature.

And let's all agree to standardise on $ being getElementById, right?

mplungian - There is no such "standarisation". In probably the most used javascript library, $ is not getElementById, it is an overloaded identifier that does many things, one of which is to return an object with numeric properties referencing elements matching a supplied selector. It has many other uses and hence meanings.

javascript - Get element by tag name shorthand? - Stack Overflow

javascript dom tags element getelementsbytagname
Rectangle 27 1

I was having a very similar problem with the whitespace between the tab headers. The tab headers are <span> tags, so most browsers render the whitespace as a text node in the DOM. To remove the ignorable whitespace nodes, call a JavaScript function when the page loads, like this:

function fixTabContainer() {
    var tabContainerHeader = $get('<%#TabContainer1.ClientID%>' + '_header');
    var children = tabContainerHeader.childNodes;
    for (var i = 0; i < children.length; i++) {
        if (is_all_ws(children[i])) {
            tabContainerHeader.removeChild(children[i]);
            i--;
        }
    }
}

/**
 * Determine whether a node's text content is entirely whitespace.
 * (From https://developer.mozilla.org/en/whitespace_in_the_dom)
 * @param nod  A node implementing the |CharacterData| interface (i.e.,
 *             a |Text|, |Comment|, or |CDATASection| node
 * @return     True if all of the text content of |nod| is whitespace,
 *             otherwise false.
 */
 function is_all_ws(nod) {
     // Use ECMA-262 Edition 3 String and RegExp features
     return !(/[^\t\n\r ]/.test(nod.data));
 }

The script finds the <div> that holds the tab headers and loops through those header <span> elements. It removes all nodes that contain only ignorable whitespace (which it determines with the second function).

Note: The IE8 DOM unfortunately doesn't include text nodes (it's a known bug).

asp.net - How do you remove the space inserted automatically in Ajax c...

asp.net ajax asp.net-ajax ajaxcontroltoolkit
Rectangle 27 148

It won't validate outside of the <body> or <head> tags. It also won't make much difference unless you're doing DOM manipulations that could break IE before the body element is fully loaded to putting it just before the closing </body>.

<html>
  ....
  <body>
     ....
     <script type="text/javascript" src="theJs.js"></script>
  </body>
</html>

Note that apps like YSlow will actually suggest that you do include your javascript at the end of the page. It may not speed up overall load time but it may load the relevant content first. Still, putting it just inside the </body> tag is best.

@epalla: if you put the script right at the end of the body tag there's no other content left to load by the time it gets there, so there should be little difference between placing it outside or just inside. You then have the added benefit of your page still validating, which was the point I was trying to make in my answer.

Yep, I was agreeing with you since your answer is good. I just wanted to add that there is a reason for putting JS at the bottom of the page instead of in the head as we've done for a long time.

@PHPst: well, invalid code may be subject to side effects in certain browsers. Either way, I don't see how its indentation being one tab-width less than the code above it makes it look any cleaner.

javascript - Is it wrong to place the