HTML Label name instead of ID? - javascript

I am making website where I am created a lot of labels that are assigned in output as here
Use fiddle link at the end of the post
<!-- lets say that I want to make a kind of board to show some game clans or... whatever -->
<label class='team' name='ally'>Madcowz</label><BR>
<label class='team' name='ally'>Fluffy Unicorns</label><BR>
<label class='team' name='enemy'>Blue bastards</label><BR><BR>
<b>JS stuff:</b>
<div id='printSomeOutputHere'></div>
<!-- The problem is that the NAME tag does not exist for label in this case: -->
<!-- I can't use ID because ID should be unique values -->
<script>
var teams = $(".team");
for(i=0; i<teams.length; i++)
{
document.getElementById('printSomeOutputHere').innerHTML += teams[i].name + ": " + teams[i].textContent;
document.getElementById('printSomeOutputHere').innerHTML += "<BR>";
}
</script>
Fiddle:
http://jsfiddle.net/cusnj74g/
name attribute is undefined, so how can I mark these labels with same name if I can't use (I can, but I should not) ID

A couple of points:
You seem to know that name is not a valid attribute for label elements. So don't use it, use data-name instead.
You're using label elements incorrectly. There are two ways you use label: A) By putting the input, select, or textarea it relates to inside it (<label><input type="checkbox"> No spam please</label>), or by using the for attribute to associate it with one of those elements elsewhere in the document (<label for="no-spam-please">No spam please</label>...<input id="no-spam-please" type="checkbox">). Having a label with no control in it and no for is fairly pointless; just use a span.
You're using jQuery in one place, but not in others. I suggest that if you're going to have a library on your page, it's best to get full use out of it. In this case, to access the attribute, you'd use $(teams[i]).attr("name") or better, $(teams[i]).attr("data-name") if you're using a data-* attribute (see #1 above). (Some may tell you to use .data to access the attribute; don't, that's not what it's for. But you might consider looking at what it's for and whether that helps you.)
.innerHTML += "content" is an anti-pattern. It makes the browser loop through all elements within the element you're doing it to to build a string, then append the string on the right with it, then parse the result, and delete all existing elements within the element and replace them with the parsed result. Instead, consider .insertAdjacentHTML("beforeend", "content")
You don't declare i anywhere, which means your code falls prey to The Horror of Implicit Globals. Declare i, or use any of several other ways to loop that don't require an index counter.
Your output will be fairly hard to read, recommend breaking it up (perhaps a div for each team?).
textContent is not reliable cross-browser, some browsers use innerText instead. (And there are differences in how whitespace is treated between them.) Since you're using jQuery, use text.
...but yes, the code would work if you used .getAttribute("name") rather than .name. Browsers make access to even invalid attributes available through getAttribute. They just don't necessarily create reflected properties for them.
Here's a version with the various comments above applied:
var output = $("#printSomeOutputHere");
$(".team").each(function() {
var $this = $(this);
output.append("<div>" + $this.attr("data-name") + ": " + $this.text() + "</div>");
});
<span class='team' data-name='ally'>Madcowz</span><BR>
<span class='team' data-name='ally'>Fluffy Unicorns</span><BR>
<span class='team' data-name='enemy'>Blue bastards</span><BR><BR>
<b>JS stuff:</b>
<div id='printSomeOutputHere'></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
...or to avoid repeated appends we could use map and join:
$("#printSomeOutputHere").append(
$(".team").map(function() {
var $this = $(this);
return "<div>" + $this.attr("data-name") + ": " + $this.text() + "</div>";
}).get().join("")
);
<span class='team' data-name='ally'>Madcowz</span><BR>
<span class='team' data-name='ally'>Fluffy Unicorns</span><BR>
<span class='team' data-name='enemy'>Blue bastards</span><BR><BR>
<b>JS stuff:</b>
<div id='printSomeOutputHere'></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

From https://developer.mozilla.org/en-US/docs/Web/API/Element.name:
[The name property] only applies to the following elements: <a>, <applet>, <button>, <form>, <frame>, <iframe>, <img>, <input>, <map>, <meta>, <object>, <param>, <select>, and <textarea>.
Since you're using jQuery I would use something like:
for(var t in teams){
$('#printSomeOutputHere').get(0).innerHTML +=
teams[t].getAttribute("name")
+ ": "
+ teams[t].text()
+ "<BR />";
}

Use getAttribute instead:
teams[i].getAttribute('name')

Why not use multiple classes:
<label class='team ally'>Madcowz</label><BR>
<label class='team ally'>Fluffy Unicorns</label><BR>
<label class='team enemy'>Blue bastards</label><BR><BR>
And the JS:
<script>
var outEl = document.getElementById('printSomeOutputHere');
var teams = $(".team");
for(i=0; i<teams.length; i++)
{
outEl.innerHTML +=
(teams[i].hasClass('ally')? 'ally':'enemy') + ": " +
teams[i].textContent;
}
</script>

Related

Passing variables to jquery .css() function

I'm trying to setup some hyperlinks to set inline styles for various elements on a webpage. So far I have been able to store the element and attribute settings in hidden span elements and pass them to an alert dialog. However when I try to set these styles using the css function it is not working or throwing any errors.
HTML:
<a class="styleswitch">Boxed
<span class="elementselector" style="display:none">#page</span>
<span class="styleattributes" style="display:none">"width": "1000px"</span>
</a>
<a class="styleswitch">Wide
<span class="elementselector" style="display:none">#page</span>
<span class="styleattributes" style="display:none">"width": "100%"</span>
</a>
jQuery:
jQuery(document).ready(function(){
jQuery('a.styleswitch').click(function(){
var element_selector = jQuery(this).find("span.elementselector").contents().text(),
style_attributes = jQuery(this).find("span.styleattributes").contents().text();
// alert('Set ' + element_selector + ' to ' + style_attributes + '');
jQuery(element_selector).css( style_attributes );
return false;
});
You are passing a string to the .css() method, this means you are using it as a getter and not a setter.
I would suggest using HTML5 data-* attributes, here data-styles is a string representation of an object, by using jQuery .data() method you will have an object:
<a data-styles='{ "width": "1000px", "prop": "value" }'
data-selector="#page"
class="styleswitch">
Boxed
</a>
JavaScript:
$('a.styleswitch').on('click', function() {
var data = $(this).data();
$(data.selector).css(data.styles);
});
http://jsfiddle.net/7t4Jb/
Change jQuery(element_selector).css( style_attributes );
to ==> jQuery(element_selector).css( {style_attributes} );
and it should work.
There are 2 ways to implement css in jquery:
.css("width","px")
or
.css({"width":"px"})
What you were doing wrong was trying to implement css with the second way but with no {}.
Hope i helped you.
With this:
jQuery(element_selector).css( JSON.parse("{" + style_attributes + "}"));
Yes, it works.
Another option:
var styleParts = style_attributes.split(":");
jQuery(element_selector).css( styleParts[0].replace(/"/g, ''), styleParts[1]);
The replace is just to remove the double quotes from the style name.
However, in a future you may want to add more style rules (not just width), so I'd suggest you to add the brackets to the style rule (to become it JSON), so you'd have:
<span class="styleattributes" style="display:none">
{"width": "100%", "backgroundColor": "red"}
</span>
If you do this change, you'd read the style like this:
jQuery(element_selector).css( eval(style_attributes) );
(I'm using eval instead JSON.parse here because I assume you'll edit those css by hand and eval isn't as strict as JSON.parse).
Hope this helps. Cheers
Storing stuff like that in hidden <span> attributes is problematic because the browser still pays attention to the contents. A better (well, safer; some people don't like it for reasons I don't really understand) way to stash stuff like that is to use <script> tags with a non-JavaScript "type" attribute:
<a class="styleswitch">Boxed
<script type=text/my-selector class="elementselector">#page</script>
<script type=text/css-styles class="styleattributes">{ "width": "1000px" }</script>
</a>
The browser will completely ignore that (except for any embedded closing </script> tags). You can still fetch the contents from jQuery:
jQuery(document).ready(function(){
jQuery('a.styleswitch').click(function(){
var element_selector = jQuery(this).find(".elementselector").html(),
style_attributes = jQuery(this).find(".styleattributes").html());
// alert('Set ' + element_selector + ' to ' + style_attributes + '');
jQuery(element_selector).css( JSON.parse(style_attributes) );
return false;
});
Note that I modified the style attribute block to be a JSON structure, so that it can be parsed and turned into a JavaScript object in your "click" handler.
edit I don't know who the downvoters are, but this is a really common practice for doing things like storing HTML templates and JSON blocks. All browsers worth worrying about (including mobile browsers) completely ignore the contents of <script> blocks with non-JavaScript "type" attributes. That means that the contents can contain HTML fragments without causing any problems.

How to apply css rule to a Javascript expression?

$("#confirm_text").text("Are you sure you want " +this.name +" "+ this.type +"?");
The whole phrase is white, but I want to make this.name and this.type orange. JS method fontcolor doesn't work. Any way to do this?
Try this :
"Are you sure you want <span style='color: orange'>" +this.name +" "+ this.type +"</span> ?"
Here you can see demo : http://jsfiddle.net/2pRzX/
this may work.
"Are you sure you want " +<span class="orange">this.name</span> +" "+ <span class="orange">this.type</span> +"?"
and apply css:
.orange{
color:orange;
}
I usually use < span class="orange"> this.name < /span> for this case.
In css .orange{color:orange;}
You have to put the text in some kind of HTML element, like <span>. Either you do it with innerHTML, which is the simpler method, or by creating the elements one by one.
Using jQuery (updated answer)
As the question was updated, I updated my answer to fit the new question.
Instead of .text, you can use the .html method which works like element.innerHTML = (see below in the old answer). It parses HTML code and inserts it into the element. Note that you should enclose the string in single quotes so that you can use double quotes without escaping them.
$("#confirm_text").html('Are you sure you want <span style="color:orange">' + this.name + ' ' + this.type + '?');
Using plain JavaScript (old answer)
This answer is outdated because the question has changed and jQuery rather than plain JS is required. I leave this here for later reference.
innerHTML
When you add HTML code to an existing element in the DOM, the browser will parse the string and create new elements. You can include the <span> tag in the string and the browser will create an element.
var targetDIV = document.getElementById("targetDIV");
// Add the text with innerHTML
targetDIV.innerHTML = 'Are you sure you want <span style="color:orange;">' + this.name + ' ' + this.type + '</span>?';
Creating the elements
Sometimes you can't just use innerHTML, especially if there is already text in the target element. This is an alternative:
var targetDIV = document.getElementById("targetDIV");
// Append the first peace of text
targetDIV.appendChild(document.createTextNode("Are you sure you want "));
// Create the span element
var orange = document.createElement("span");
// Change its text-color
orange.style.color = "orange";
// Add the text to the span
orange.appendChild(document.createTextNode(this.name + " " + this.type));
// Append the span to the target element
targetDIV.appendChild(orange);
// Append the question mark
targetDIV.appendChild("?");
Which to use?
In most cases, you can use either of these methods. I always use the second one, though, because I have the feeling that it is the "cleaner" one. You have more control over what happens, you can change things by adding/removing/changing lines instead of modifying a large string. You also don't have to check whether your HTML is valid. But as I said, both methods work.
Try this:
"Are you sure you want <span style='color: orange'>" +this.name +" "+ this.type +"</span>?"
You can add <span> </span> tags around the name and type values, and add an colour using CSS.
Example:
http://jsfiddle.net/BAhUG/

html: text and createElement

i have difficulty understanding the below code snippet. I am trying to understand where the value attribute is assigned to, however i only see the property attribute.
<html:text indexed="true" name="<%=(String)
currentItr.next()%>" property="<%=(String) currentItr.next()%>"/>
because i am slightly more familiar with HTML DOM, i was able to create the element i want using below:
object<%=i%> = document.createElement('
<input type="text" name="<%=name%>' + '[' +
sectionId + '].mySpecialList[' + row[id] + '].
<%=curProp%>" id=' + sectionId +
'size="<%=curItr.next()%>" value="<%=curItr.next()%>">');
which i know i can grab and access using the following:
var obj = document.forms["myForm"].elements["mySpecialList[0].mySmallList[0].someProperty"];
what is the html:struts equivalent of the createElement bit? Because when i use the html:text code snippet, i am unable retrieve or parse the value attribute.
for example: the <html:text> tag seems to automatically create an element with name, value and size. however, when i try to access the same element in javascript, i get the element's column name instead, and not the value
It's unreadable and you should not use scriptlets, use JSTL for that.
<html:text property="propertyNameOfYourBean"/>
For list you should use <c:forEach> tag.

Get a value from an input textbox

Okay. So I have this code
<input id="suspect" value="" type="text">
<input id="reason" value="" type="text">
<textarea></textarea>
var suspect = $('input#suspect').text();
var reason = $('input#reason').text();
$('textarea').val('' + suspect + ' and ' + reason + '')
Then I put something in both of those 2 inputs and then the textarea recieves no value from the inputs. How to fix that problem ?
Because when you set the variables there's no text inside the elements from which you're trying to recover the entered-text (incidentally, for inputs you're looking for .val()). If you bind to the focus event:
$('textarea').focus(
function(){
var suspect = $('#suspect').val(),
reason = $('#reason').val();
$(this).val('' + suspect + ' and ' + reason + '');
});
JS Fiddle demo.
Also, in this case (since you've placed the JavaScript after the elements in the DOM, albeit you've omitted the <script></script> tags) you might be okay not using the $(document).ready() event handler, but I'd normally suggest wrapping jQuery in such, just to be sure that events are being bound after the elements to which they're being bound exist in the DOM.
References:
focus().
val().
.text() -- Gets the text inside the elements
.val() -- Gets the value of the elements
Since the text is stored inside the value, therefore you should use .val() instead of .text().
var suspect = $('input#suspect').val(),
reason = $('input#reason').val();
$("textarea").val(suspect+" and "+reason);
If you want instant change try the keyboard events
$(window).keyup(function() {
var suspect = $('input#suspect').val();
var reason = $('input#reason').val();
$('textarea').val('' + suspect + ' and ' + reason + '');
});
see here: http://jsfiddle.net/TtAVS/
​
You probably want to use val() here instead of text(), and there also needs to be some kind of event (like a click) that causes the data to be extracted from the inputs and put into the textarea.
It also might be worth noting that since id's are unique,
var suspect = $('#suspect').val();
var reason = $('#reason').val();
are sufficient as selectors and (I find) easier to read.
should use .val() to get value from the input box

JQuery html() vs. innerHTML

Can I completely rely upon jQuery's html() method behaving identical to innerHTML? Is there any difference between innerHTML and jQuery's html() method? If these methods both do the same, can I use jQuery's html() method in place of innerHTML?
My problem is: I am working on already designed pages, the pages contains tables and in JavaScript the innerHTML property is being used to populate them dynamically.
The application is working fine on Firefox but Internet Explorer fires an error: unknown runtime exception. I used jQuery's html() method and IE's error has disappeared. But I'm not sure it will work for all browsers and I'm not sure whether to replace all innerHTML properties with jQuery's html() method.
Thanks a lot.
To answer your question:
.html() will just call .innerHTML after doing some checks for nodeTypes and stuff. It also uses a try/catch block where it tries to use innerHTML first and if that fails, it'll fallback gracefully to jQuery's .empty() + append()
Specifically regarding "Can I rely completely upon jquery html() method that it'll perform like innerHTML" my answer is NO!
Run this in internet explorer 7 or 8 and you'll see.
jQuery produces bad HTML when setting HTML containing a <FORM> tag nested within a <P> tag where the beginning of the string is a newline!
There are several test cases here and the comments when run should be self explanatory enough. This is quite obscure, but not understanding what's going on is a little disconcerting. I'm going to file a bug report.
<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
<script>
$(function() {
// the following two blocks of HTML are identical except the P tag is outside the form in the first case
var html1 = "<p><form id='form1'><input type='text' name='field1' value='111' /><div class='foo' /><input type='text' name='field2' value='222' /></form></p>";
var html2 = "<form id='form1'><p><input type='text' name='field1' value='111' /><div class='foo' /><input type='text' name='field2' value='222' /></p></form>";
// <FORM> tag nested within <P>
RunTest("<FORM> tag nested within <P> tag", html1); // succeeds in Internet Explorer
RunTest("<FORM> tag nested within <P> tag with leading newline", "\n" + html1); // fails with added new line in Internet Explorer
// <P> tag nested within <HTML>
RunTest("<P> tag nested within <FORM> tag", html2); // succeeds in Internet Explorer
RunTest("<P> tag nested within <FORM> tag with leading newline", "\n" + html2); // succeeds in Internet Explorer even with \n
});
function RunTest(testName, html) {
// run with jQuery
$("#placeholder").html(html);
var jqueryDOM = $('#placeholder').html();
var jqueryFormSerialize = $("#placeholder form").serialize();
// run with innerHTML
$("#placeholder")[0].innerHTML = html;
var innerHTMLDOM = $('#placeholder').html();
var innerHTMLFormSerialize = $("#placeholder form").serialize();
var expectedSerializedValue = "field1=111&field2=222";
alert( 'TEST NAME: ' + testName + '\n\n' +
'The HTML :\n"' + html + '"\n\n' +
'looks like this in the DOM when assigned with jQuery.html() :\n"' + jqueryDOM + '"\n\n' +
'and looks like this in the DOM when assigned with innerHTML :\n"' + innerHTMLDOM + '"\n\n' +
'We expect the form to serialize with jQuery.serialize() to be "' + expectedSerializedValue + '"\n\n' +
'When using jQuery to initially set the DOM the serialized value is :\n"' + jqueryFormSerialize + '\n' +
'When using innerHTML to initially set the DOM the serialized value is :\n"' + innerHTMLFormSerialize + '\n\n' +
'jQuery test : ' + (jqueryFormSerialize == expectedSerializedValue ? "SUCCEEDED" : "FAILED") + '\n' +
'InnerHTML test : ' + (innerHTMLFormSerialize == expectedSerializedValue ? "SUCCEEDED" : "FAILED")
);
}
</script>
</head>
<div id="placeholder">
This is #placeholder text will
</div>
</html>
If you're wondering about functionality, then jQuery's .html() performs the same intended functionality as .innerHTML, but it also performs checks for cross-browser compatibility.
For this reason, you can always use jQuery's .html() instead of .innerHTML where possible.
innerHTML is not standard and may not work in some browsers. I have used html() in all browsers with no problem.
Given the general support of .innerHTML these days, the only effective difference now is that .html() will execute code in any <script> tags if there are any in the html you give it. .innerHTML, under HTML5, will not.
From the jQuery docs:
By design, any jQuery constructor or method that accepts an HTML string — jQuery(), .append(), .after(), etc. — can potentially execute code. This can occur by injection of script tags or use of HTML attributes that execute code (for example, <img onload="">). Do not use these methods to insert strings obtained from untrusted sources such as URL query parameters, cookies, or form inputs. Doing so can introduce cross-site-scripting (XSS) vulnerabilities. Remove or escape any user input before adding content to the document.
Note: both .innerHTML and .html() can execute js other ways (e.g the onerror attribute).
"This method uses the browser's innerHTML property." - jQuery API
http://api.jquery.com/html/
Here is some code to get you started. You can modify the behavior of .innerHTML -- you could even create your own complete .innerHTML shim. (P.S.: redefining .innerHTML will also work in Firefox, but not Chrome -- they're working on it.)
if (/(msie|trident)/i.test(navigator.userAgent)) {
var innerhtml_get = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerHTML").get
var innerhtml_set = Object.getOwnPropertyDescriptor(HTMLElement.prototype, "innerHTML").set
Object.defineProperty(HTMLElement.prototype, "innerHTML", {
get: function () {return innerhtml_get.call (this)},
set: function(new_html) {
var childNodes = this.childNodes
for (var curlen = childNodes.length, i = curlen; i > 0; i--) {
this.removeChild (childNodes[0])
}
innerhtml_set.call (this, new_html)
}
})
}
var mydiv = document.createElement ('div')
mydiv.innerHTML = "test"
document.body.appendChild (mydiv)
document.body.innerHTML = ""
console.log (mydiv.innerHTML)
http://jsfiddle.net/DLLbc/9/

Categories