Need: Find a way to add a valid tag/attribute/property to a normal html control.
What I have is some javascript/jquery adding a click event to a link that will show or hide a div. The idea is to do this using $(document).ready and an anonymous method to create the method called by onClick at the page load. When clicked, a div will be shown with some text. This is all well and good except I can't figure out how to set up the text so that this can be done on the page load. What I'd like is something like:
HI
so that I can do this:
$(document).ready
(
function()
{
$("..showItLink").click
(
function(event)
{
var containerPosition;
var createdDiv;
//see if the div already exists
createdDiv = $(this).children(".postComment");
if (createdDiv.length == 0)
{
//This is where the attribute is used so that the CreateDiv
//method can take the textToShow and fill the div's innerText
//with it V V V V V V
createdDiv = CreateDiv(this.textToShow, "postComment");
$(this).append(createdDiv);
$(this).children(".postComment").hide();
}
$(createdDiv).toggle();
event.preventDefault();
}
);
}
);
Now besides not being xhtml valid (meh), this only works in IE. Firefox just says it doesn't exist. (this.textToShow) I could use something like rel or rev, but that seems just as hackish. I was wondering if there is a valid way of doing this.
Solution from answer below
comment = $(".showItLink").attr("comment");
...
createdDiv = CreateDiv(comment, "postComment");
Paired with:
<a href="http://www.theironical.com" class="showItLink" comment="hihihi" >HI</a>
If you're using JQuery, just get and set the attributes with .attr().
Get: this.attr("textToShow")
Set: this.attr("textToShow", value)
The way you add an attribute to an html control is by using the
element.setAttribute("attributeName", "attributeValue") where "element" is the element you want to add the attribute to.
To get an attribute you use getAttribute("attributeName");
You can't get away with adding custom attributes to HTML elements whilst still being valid. It will generally work in current browsers, but it's a bit fragile in that if you happen to pick a name that is in use (now or in the future) as an HTML or JavaScript property by any browser, the clash will stop it from working.
HTML5 proposes attributes whose names start with “data-” as valid extension mechanisms. You could also consider namespaced elements in XHTML; this still isn't technically “valid XHTML” by the DTD but at least it is safe from collisions.
<a href="..." class="showItLink" textToShow="This is the text to show">HI
I suggest using the ‘title’ attribute for this particular purpose.
The best way to do this kind of thing is to hide the text in another element and then toggle that element. Try something like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>clear test</title>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$("#show-it").click(function() {
$("#message").toggle();
});
});
</script>
</head>
<body>
<div>
<a id="show-it" href="javascript:void(0);">show it</a>
<div id="message" style="display:none;"> hidden message</div>
hello world
</div>
</body>
</html>
If your textToShow attribute was an expando property, then this.textToShow would not return undefined, but since it is a custom attribute, you need to use jQuery's this.attr("textToShow") or the standard DOM this.getAttribute("textToShow").
Related
I try to clone subnode of HTML, filter the clone and plonk it elsewhere in the page.
I try this:
var emailTemplate = $("#email-post")[0];
$("#tempStoreEmailTemplate").val(emailTemplate.outerHTML);
$(tempStoreEmailTemplate).find('.num6:hidden').remove();
$("#iframe-textarea").val(tempStoreEmailTemplate.val)//.outerHTML
<div id="tempStoreEmailTemplate" hidden></div>
I tried both tempStoreEmailTemplate.val and tempStoreEmailTemplate.outerHTML in the last line. .outerHTML shows this text
<div id="tempStoreEmailTemplate" hidden=""></div>
.val shows nothing.
The expected result would be to see the textual representation of the modified subnode. Do you know what is wrong?
HTML nesting with #email-post looks like this:
<h4>Email Preview</h4>
<!-- Card -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional //EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:v="urn:schemas-microsoft-com:vml" id="email-post">
<head>
This is likely to do with how you are storing the temporary block - using .val() puts it in the value attribute, which is useful in input fields... Not so much in divs. If, however, you were to append the temporary block:
var emailTemplate = $("#email-post") //If you are using the ID tag correctly, this selector will only retrieve one element, you don't need to specify [0]
$("#tempStoreEmailTemplate").append($(emailTemplate))
It places a copy of the entire sub-tree matched by #email-post into the element matched by #tempStoreEmailTemplate as a child; for instance:
<div id="tempStoreEmailTemplate" hidden>
<div id="email-post">
...
</div>
</div>
This allows you to do your filter:
$('#tempStoreEmailTemplate').find('.num6:hidden').remove();
And then to place the filtered HTML into your textarea, you can just do this:
$("#iframe-textarea").val($('#tempStoreEmailTemplate').html())
Which would put the following into your textarea:
<div id="email-post">
...
</div>
EDIT to add: You may have to alter how you're hiding #tempStoreEmailTemplate, if the current solution doesn't work then you may have to alter the div to:
<div id="tempStoreEmailTemplate" style="display:none;">
</div>
I need to get the object of second level html element in my page.
<html>
<div id="out">
jasoidjisa
<html>
<head>//This object
<div id="in">
hihisdhi
</div>
</head>
</html>
</div>
<script>
alert(document.getElementsByTagName('html'));
</script>
Help me to access this html element via js
HTML is a reserved tag name and so you can't use it in the manner in which you have used it here. Which particular value from above are you trying to get exactly ? It might make sense to use the <div> tag with a class or I'd to identify it instead. If you specify which value you are specifically looking to get I can write up a theoretical solution.
vsank7787 was totally correct. Maybe you could use iFrames instead of nested html inside a HTML document since html is a reserved keyword.
I have a situation with sample code as follows:
<html>
<head>
<title>Untitled Document</title>
</head>
<body>
<p>
<h1>The header</h1>
<div>
matter ia always matter matter ia <strong>bold matter</strong> matter matter <em>italics matter</em>matter ia <em><strong>bold italics matter</strong></em>lways matter
</div>
</p>
</body>
</html>
I am just trying to retrieve the specific tags like body->p->div->em->strong when I click on "bold italics matter" using jQuery. Is there any standard method to retrieve as per the click event?
If you wan to get the tag name of the element which is clicked, then you can use:
$('*').click(function(e) {
e.stopPropagation();
console.log($(this).prop('tagName'));
});
Fiddle Demo
I'm not completely sure about what you are trying to accomplish. If you are trying to retrieve the tag itself that the text is contained in, i would recommend that you put a <span> tag in around the the text in question and do an onclick="function()" or simply put the onclick right on the <strong> tag.
As far the the JQuery/Javascript goes, if you want to retrieve the content, it looks like
var foo = document.getElementById.innerHTMl("id");
However, this requires you to have an id in your tags which is probably the best, if not
'standard' method of retrieving the content that is within the tag.
After reading your comments, i am editing this post:
The best way to get the parent elements is to use the JQUery .parent() function. I'd imagine that you would just recursively state something like this:
var foo = $("nameofelement").parent();
I hope this is more of what your looking for.
Thanks for contributing everybody. At last I made it myself with the following code.
$(document.body).click(function(e){
var Tags=[], Target=e.target, stat_msg="";
Tags.push(Target.tagName);
while($(Target).parent().get(0).tagName!=="BODY")
{
Tags.push($(Target).parent().get(0).tagName);
Target=$(Target).parent();
}
Tags.push("BODY");
for(i=Tags.length;i>0;i--)
stat_msg=stat_msg+Tags[i-1]+" ";
alert(stat_msg);
});
I am in the process of AJAX-ing a WordPress theme with a persistent music player. Wordpress uses dynamic classes on the <body> tag. The basic structure is as follows:
<html>
<head>
</head>
<body class="unique-class-1 unique-class-2 unique-class-3">
<div id="site-container">
<nav class="nav-primary">
Other Page 01
Other Page 02
</nav>
<div class="site-inner">
<p>Site Content Here</p>
</div>
</div>
<div id="music-player"></div>
</body>
</html>
I am currently successfully loading the content of /other-page-01/, /other-page-02/, etc, using load('/other-page-01/ #site-container'). However, I need to extract all <body> classes from the AJAX loaded page and replace the current page's <body> classes with them dynamically.
Note: Replacing the entire <body> element is not an option due to the persistent <div id="music-player">. I've tried jQuery.get(), but couldn't get it to work.
How do I extract the <body> classes from the AJAX requested page and replace the current page's <body> classes with them?
I am not very familiar with jQuery or Javascript, so the exact code would be extremely helpful. Any help is greatly appreciated.
Thanks,
Aaron
My typical solution would have been to tell you to throw the AJAX code in to a jQuery object and then read it out like normal:
$(ajaxResult).attr('class');
Interestingly though, it appears you can't do this with a <body> element.
I'd say the easiest solution (if you have control over the resulting HTML) is to just use some good ol' regex:
var matches = ajaxResult.match(/<body.*class=["']([^"']*)["'].*>/),
classes = matches && matches[1];
I say "if you have control over the resulting HTML", because this relies on the HTML being reasonably well formed.
The other method would involve parsing it as a DOMDocument and then extracting what you need, but this would take a lot more and is usually overkill in simple cases like this.
Convert the body within your returned html to a div with a specific ID, then target that id to get the classes of the body (which is now a div.)
modifiedAjaxResult = ajaxResult.replace(/<body/i,'<div id="re_body"')
.replace(/<\/body/i,'</div');
$(modifiedAjaxResult).filter("#re_body").attr("class");
Of course, if the body has an id, this will conflict with it, so an arbitrary data attribute might be less likely to break.
modifiedAjaxResult = ajaxResult.replace(/<body/i,'<div data-re-id="re_body"')
.replace(/<\/body/i,'</div');
$(modifiedAjaxResult).filter("[data-re-id=re_body]").attr("class");
http://jsfiddle.net/N68St/
Of course, to use this method, you'll have to switch to using $.get instead.
$.get("/other-page-01/",function(ajaxResult){
var modifiedAjaxResult = ajaxResult.replace(/<body/i,'<div data-re-id="re_body"')
.replace(/<\/body/i,'</div');
alert($(modifiedAjaxResult).filter("[data-re-id=re_body]").attr("class"));
// the following line replicates what `.load` was doing.
$(someElement).append( $("<div>").html(ajaxResult).find("#site-container") );
});
(I ask my question again after the first one was terribly formulated)
I face the following problem:
<div class="testA" id="test1"></div>
The above written element is predefined. I now load a xml tree via XMLHttpRequest & Co. delivering the following response:
<response>
<div class="colorSelector" id="0-0">
<div class="gbSelector" id="1-0">
<table style="none" id="2-0"></table>
</div>
</div>
</response>
I now append the first div using
request.responseXML.getElementsByTagName("response")[0]
.getElementsByTagName("div")[0]
into the predefined div
<div class="testA" id="test1">
The final document looks like this (checked using development tools):
<div class="testA" id="test1">
<div class="colorSelector" id="0-0">
<div class="gbSelector" id="1-0">
<table style="none" id="2-0"></table>
</div>
</div>
</div>
When I now try to get the element <div class="colorSelector" id="0-0"> using getElementById("0-0") I get the expected result.
But using getElementsByClassName("colorSelector") returns [].
Did I miss something? Is it probably a leftover of the fact the nodes were of type Element and not HTMLElement?
colorSelector is commented out. JavaScript only works within the DOM, and commented out portions aren't in the DOM.
Since you said that your getElementById("0-0") is successful, then clearly you don't actually have the nodes commented out.
I'm guessing you're doing:
document.getElementById("0-0").getElementsByClassName('colorSelector');
...which will not work because the element selected by ID does not have any descendants with that class.
Since you show HTML comments in the markup, I'd also wonder if you have some different element on the page with the ID "0-0". Take a look for that.
If your nodes are actually commented out, you'll need to first select the comment, and replace it with the markup contained inside:
var container = document.getElementById('test1'),
comment = container.firstChild;
while( comment && comment.nodeType !== 8 ) {
comment = comment.nextSibling;
}
if( comment ) {
container.innerHTML = comment.nodeValue;
}
...resulting in:
<div class="testA" id="test1">
<div class="colorSelector" id="0-0">
<div class="gbSelector" id="1-0">
<table style="none" id="2-0"></table>
</div>
</div>
</div>
...but there again, this doesn't seem likely since your getElementsById does work.
Here's a way to do it for Firefox, Opera, Chrome and Safari. Basically, you just do div.innerHTML = div.innerHTML to reinterpret its content as HTML, which will make that class attribute from the XML file be treated as an HTML class name.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<script>
window.addEventListener("DOMContentLoaded", function() {
var div = document.getElementsByTagName("div")[0];
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (this.readyState === 4 && this.status === 200) {
var doc = this.responseXML;
div.appendChild(document.importNode(doc.getElementsByTagName("response")[0].getElementsByTagName("div")[0], true));
div.innerHTML = div.innerHTML;
alert(document.getElementsByClassName("colorSelector").length);
}
};
req.open("GET", "div.xml");
req.send();
}, false);
</script>
</head>
<body>
<div class="testA"></div>
</body>
</html>
Remove the this.status === 200 if you're testing locally in browsers that support xhr locally.
The importNode() function doesn't seem to work in IE (9 for example). I get a vague "interface not supported" error.
You could also do it this way:
var doc = this.responseXML;
var markup = (new XMLSerializer()).serializeToString(doc.getElementsByTagName("response")[0].getElementsByTagName("div")[0]);
div.innerHTML = markup;
as long as the markup is HTML-friendly as far as end tags for empty elements are concerned.
<!--<div class="colorSelector" id="0-0">
<div class="gbSelector" id="1-0">
<table style="none" id="2-0"></table>
</div>
</div>-->
The above code is gray for a reason: it's a comment. Comments aren't parsed by the browser at all and have no influence on the page whatsoever.
You'll have to parse the HTML, read the comments, and make a new DOM object with the contents of the comment.
Please describe what you are doing with the returned results. There is a significant difference between a nodeList and a node, nodeLists are LIVE.
So if you assign a nodeList returned by getElementsByClassName() (or similar) to a variable, this variable will change when you remove the nodes inside the nodeList from the DOM.
I now append the first div
How do you do that? What you have in the responseXML are XML elements, and not HTML elements.
You shouldn't be able to appendChild them into a non-XHTML HTML document;
actually you shouldn't be able to appendChild them into another document at all, you're supposed to use importNode to get elements from one document to another, otherwise you should get WRONG_DOCUMENT_ERR;
even if you managed to insert them into an HTML due to browser laxness, they're still XML elements and are not semantically HTML elements. Consequently there is nothing special about the class attributes; just having that name doesn't make the attribute actually represent a class. getElementsByClassName won't return elements just because they have attributes with the name class; they have to be elements whose language definition associates the attributes with the concept of classness (which in general means HTML, XHTML or SVG).
(The same should be true of the id attributes; just having an attribute called id doesn't make it conceptually an ID. So getElementById shouldn't be working. There is a way to associate arbitrary XML attributes with ID-ness, which you don't get with class-ness, by using an <!ATTLIST declaration in the doctype. Not usually worth bothering with though. Also xml:id is a special case, in implementations that support XML ID.)
You could potentially make it work if you were using a native-XHTML page by putting suitable xmlns attributes on the content to make it actual-XHTML and not just arbitrary-XML, and then using importNode. But in general this isn't worth it; it tends to be simpler to return HTML markup strings (typically in JSON), or raw XML data from which the client-side script can construct the HTML elements itself.