How do you set the display value of any DOM element? - javascript

Sometimes I want to update the value of a random DOMNode but I don't really know what type of element it is for sure. I am assuming I will need some block of code that checks to see what type of node it is.
if(el.tagName == 'input' ) el.value = "foo";
if(el.tagName == 'div') el.innerHTML = "foo";
Or even if certain properties exist:
var value = "foo";
if(el.value != "undefined" && el.value != value) {
el.value = value;
}
if(el.innerHTML != "undefined" && el.innerHTML != value) {
el.innerHTML = value;
}
The el.nodeType does list several basic types, but they are just basic node types.
What is the best way to update any type of elements display?
Update: #dfsq had a good idea.
el["value" in el ? "value" : "innerHTML"] = value;
However, it doesn't seem to work with just any element:
["value" in document.createElement('li')] // true
Update 2 strict type checking might be a solution:
document.createElement('input').value
""
document.createElement('li').value
0
document.createElement('div').value
undefined
document.createElement('textarea').value
""
Note: No jQuery solutions unless you want to point out how jQuery does it

Seems type checking on the el.value is the way to go:
var els = ['p', 'div', 'li', 'a', 'input', 'textarea'];
for (var i in els) {
var el = document.createElement(els[i]); el.value = 'foo'; console.log(el.value);
}
jsfiddle
el[typeof el.value === "string" ? "value" : "innerHTML"] = value;

Related

how to check null in javaScript function?

I want to check null and empty id in JavaScript function,but if syntax isn't work ?
var id = "<%=Request["Id"]%>";
if (id !== "")
if (id !== null)
{var id = "<%=new Guid(Request["ID"].ToString())%>";
window.location = "/Controller/Action.aspx?Id=" + id; }
With javascript,
If you are trying to test for not-null (any value that is not explicitly NULL) this should work for you:
if( myVar !== null ) {
// your code
}
If you are only interested to test for not-empty (null value, zero number, empty string etc..) then try:
if( !myVar ) {
// your code
}
If you want to test for if a variable is defined at all (which I believe is what you are trying to achieve) then you can do it like:
if( typeof myVar !== 'undefined' ) {
// your code
}
Please let me know if it works for you.
Read into binary logic:
var id = "<%=Request["Id"]%>";
if (id !== "" && id != null) {
var id = "<%=new Guid(Request["ID"].ToString())%>";
window.location = "/Controller/Action.aspx?Id=" + id;
}
Then again, var id = "<%=Request["Id"]%>"; will never be null, only empty string, so perhaps you can drop that check altogether.

string objects comparison always returning false

Here is the code that I am executing:
filterIssues: function(objectKey, text){
var view = this;
var keys = objectKey.split(".");
var attributeKey = keys[0];
var attributeName;
if (keys.length > 1){
attributeName = keys[1];
}
view.issues.each(function(issue){
var value = issue.get(attributeKey);
console.log(text);
if (value === undefined || value === null){
issue.trigger("hide");
return;
}
if (attributeName !== undefined){
value = value[attributeName];
}
if(value !== undefined){
var matchedText = value.substring(0, text.length - 1);
if ( matchedText === text){
issue.trigger("show");
console.log(value);
return;
}
}
issue.trigger("hide");
});
}
The matchedText == text always returns false.
This is what I get when I play around with the console:
> matchedText
"sande"
> text
"sande"
> typeof(text)
"string"
> typeof(matchedText)
"string"
> matchedText === text
false
> matchedText == text
false
I do realize that and === will always check if both the objects are the same and I have read
JavaScript equal operations anomalies and Javascript string equality.
Is there something wrong in the code that I am overlooking?
I think you are misusing the subString() method. If you use subString(), use the length without -1.
Well I eventually found out what was the problem. Thanks for your responses and I believe you might not have come across the answer for the lack of information.
The problem lied in the text value that I was passing to the function. The text contained a "" at the end and that's why comparison just did not work.

GWT/CSS - styling part of a label

Is there a way to style part of the text in a label - change color, boldness, size, etc?
Use HTML widget instead of Label. Then:
HTML label = new HTML();
label.setHtml("Brown <span class=\"brown\">fox</span>");
I was a little bored, and I thought I might be able to offer something useful, so, that said, I offer this:
function elemStyle(el, needle, settings) {
// if there's no 'el' or 'needle' arguments, we quit here
if (!el || !needle) {
return false;
}
else {
// if 'el' has a nodeType of 1, then it's an element node, and we can use that,
// otherwise we assume it's the id of an element, and search for that
el = el.nodeType == 1 ? el : document.getElementById(el);
// if we have a 'settings' argument and it's an object we use that,
// otherwise we create, and use, an empty object
settings = settings && typeof settings === 'object' ? settings : {};
// defining the defaults
var defaults = {
'class': 'presentation',
'elementType': 'span'
},
// get the text from the 'el':
haystack = el.textContent || el.innerText;
// iterate over the (non-prototypal) properties of the defaults
for (var prop in defaults) {
if (defaults.hasOwnProperty(prop)) {
// if the 'settings' object has that property set
// we use that, otherwise we assign the default value:
settings[prop] = settings[prop] || defaults[prop];
}
}
// defining the opening, and closing, tags (since we're using HTML
// as a string:
var open = '<' + settings.elementType + ' class="' + settings.class + '">',
close = '</' + settings.elementType + '>';
// if 'needle' is an array (which is also an object in JavaScript)
// *and* it has a length of 2 (a start, and stop, point):
if (typeof needle === 'object' && needle.length === 2) {
var start = needle[0],
stop = needle[1];
el.innerHTML = haystack.substring(0, start) + open + haystack.substring(start, stop) + close + haystack.substring(stop);
}
// otherwise if it's a string we use regular expressions:
else if (typeof needle === 'string') {
var reg = new RegExp('(' + needle + ')');
el.innerHTML = haystack.replace(reg, open + '$1' + close);
}
}
}
The above is called like so:
// a node-reference, and a string:
elemStyle(document.getElementsByTagName('label')[0], 'Input');​
JS Fiddle demo.
// a node-reference, and a start-stop array:
elemStyle(document.getElementsByTagName('label')[0], [6, 8]);​
JS Fiddle demo.
// an id (as a string), and a string to find, with settings:
elemStyle('label1', 'Input', {
'elementType' : 'em'
});​
JS Fiddle demo.
This could definitely do with some error-catching (for example if an array is passed into the function that's less, or more, than two-elements nothing happens, and no error is returned to the user/developer; also if the el variable is neither a node-reference or an id, things go wrong: Uncaught TypeError: Cannot read property 'textContent' of null).
Having said that, I felt dirty, so I added in a simple error-check, and reporting, if the el doesn't resolve to an actual node in the document:
el = el.nodeType == 1 ? el : document.getElementById(el);
// if 'el' is null, and therefore has no value we report the error to the console
// and then quit
if (el === null) {
console.log("You need to pass in either an 'id' or a node-reference, using 'document.getElementById(\"elemID\")' or 'document.getElementsByTagName(\"elemTag\")[0].");
return false;
}
References:
document.getElementById().
JavaScript regular expressions.
Node.nodeType.
string.replace().
String.substring().
typeof variable.

Ways of comparing Text Content between HTML Elements

As the title says, I am looking for a way of comparing the Text content of an HTML Element with another HTML Elements's Text content and only if they are identical, alert a message. Any thoughts? Greatly appreciate it!
(Posted with code): For example, I can't equalize the remItem's content with headElms[u]'s content.
else if (obj.type == 'checkbox' && obj.checked == false) {
var subPal = document.getElementById('submissionPanel');
var remItem = obj.parentNode.parentNode.childNodes[1].textContent;
alert("You have disselected "+remItem);
for (var j=0; j < checkSum.length; j++) {
if (remItem == checkSum[j]) {
alert("System found a match: "+checkSum[j]+" and deleted it!");
checkSum.splice(j,1);
} else {
//alert("There were no matches in the search!");
}
}
alert("Next are...");
alert("This is the checkSum: "+checkSum);
alert("Worked!!!");
var headElms = subPal.getElementsByTagName('h3');
alert("We found "+headElms.length+" elements!");
for (var u=0; u < headElms.length; u++){
alert("YES!!");
if (remItem == headElms[u].textContent) {
alert("System found a matching element "+headElms[u].textContent+" and deleted it!");
}
else {
alert("NO!!");
alert("This didn't work!");
}
}
}
var a = document.getElementById('a');
var b = document.getElementById('b');
var tc_a = a ? a.textContent || a.innerText : NaN;
var tc_b = b ? b.textContent || b.innerText : NaN;
if( tc_a === tc_b )
alert( 'equal' );
Using NaN to ensure a false result if one or both elements don't exist.
If you don't like the verbosity of it, or you need to do this more than once, create a function that hides away most of the work.
function equalText(id1, id2) {
var a = document.getElementById(id1);
var b = document.getElementById(id2);
return (a ? a.textContent || a.innerText : NaN) ===
(b ? b.textContent || b.innerText : NaN);
}
Then invoke it...
if( equalText('a','b') )
alert( 'equal' );
To address your updated question, there isn't enough info to be certain of the result, but here are some potential problems...
obj.parentNode.parentNode.childNodes[1] ...may give different element in different browsers
"System found a matching element ... and deleted it!" ...if you're deleting elements, you need to account for it in your u index because when you remove it from the DOM, it will be removed from the NodeList you're iterating. So you'd need to decrement u when removing an element, or just iterate in reverse.
.textContent isn't supported in older versions of IE
Whitespace will be taken into consideration in the comparison. So if there are different leading and trailing spaces, it won't be considered a match.
If you're a jQuery user....
var a = $('#element1').text(),
b = $('#element2').text();
if (a === b) {
alert('equal!');
}
The triple equals is preferred.
To compare two specific elements the following should work:
<div id="e1">Element 1</div>
<div id="e2">Element 2</div>
$(document).ready(function(){
var $e1 = $('#e1'),
$e2 = $('#e2'),
e1text = $e1.text(),
e2text = $e2.text();
if(e1text == e2text) {
alert("The same!!!");
}
});
I will highly recommend using jQuery for this kind of comparison. jQuery is a javascript library that allows you to draw values from between HTML elements.
var x = $('tag1').text();
var y = $('tag2').text();
continue js here
if(x===y){
//do something
}
for a quick intro to jQuery...
First, download the file from jQuery.com and save it into a js file in your js folder.
Then link to the file. I do it this way:
Of course, I assume that you're not doing inline js scripting...it is always recommended too.
A simple getText function is:
var getText = (function() {
var div = document.createElement('div');
if (typeof div.textContent == 'string') {
return function(el) {
return el.textContent;
}
} else if (typeof div.innerText == 'string') {
return function(el) {
return el.innerText;
}
}
}());
To compare the content of two elements:
if (getText(a) == getText(b)) {
// the content is the same
}

Clean global search and replace using JavaScript?

I am coding a little bookmarket to convert all the devises in the current page to another. I heavily relies on regexp, and I use Jquery to easy the work.
For now, I do that like a big fat pig, replacing all the body :
$("body").children().each(function(){
var $this = $(this);
var h = $.html().replace(/eyes_hurting_regexp/g, "my_super_result");
$this.html(h);
});
It works fine on static page, but if js events are involves, it's an Apocalypse.
The only way I can think of is to go trough all the node, check if it contains text only, then replace the text. On heavy HTML markup, I'm worried about the perfs.
Any idea out here ?
Unfortunately, going through each text node, step-by-step, is the only reliable way to do this. This has worked for me in the past: (demo)
function findAndReplace(searchText, replacement, searchNode) {
if (!searchText || typeof replacement === 'undefined') {
// Throw error here if you want...
return;
}
var regex = typeof searchText === 'string' ?
new RegExp(searchText, 'g') : searchText,
childNodes = (searchNode || document.body).childNodes,
cnLength = childNodes.length,
excludes = 'html,head,style,title,link,meta,script,object,iframe';
while (cnLength--) {
var currentNode = childNodes[cnLength];
if (currentNode.nodeType === 1 &&
(excludes + ',').indexOf(currentNode.nodeName.toLowerCase() + ',') === -1) {
arguments.callee(searchText, replacement, currentNode);
}
if (currentNode.nodeType !== 3 || !regex.test(currentNode.data) ) {
continue;
}
var parent = currentNode.parentNode,
frag = (function(){
var html = currentNode.data.replace(regex, replacement),
wrap = document.createElement('div'),
frag = document.createDocumentFragment();
wrap.innerHTML = html;
while (wrap.firstChild) {
frag.appendChild(wrap.firstChild);
}
return frag;
})();
parent.insertBefore(frag, currentNode);
parent.removeChild(currentNode);
}
}
I modified the script for my own needs and put the new version here in case somebody would need the new features :
Can handle a replace callback function.
External node blacklist.
Some comments so the code won't hurt someone else eyes :-)
function findAndReplace(searchText, replacement, callback, searchNode, blacklist) {
var regex = typeof searchText === 'string' ? new RegExp(searchText, 'g') : searchText,
childNodes = (searchNode || document.body).childNodes,
cnLength = childNodes.length,
excludes = blacklist || {'html' : '',
'head' : '',
'style' : '',
'title' : '',
'link' : '',
'meta' : '',
'script' : '',
'object' : '',
'iframe' : ''};
while (cnLength--)
{
var currentNode = childNodes[cnLength];
// see http://www.sutekidane.net/memo/objet-node-nodetype.html for constant ref
// recursive call if the node is of type "ELEMENT" and not blacklisted
if (currentNode.nodeType === Node.ELEMENT_NODE &&
!(currentNode.nodeName.toLowerCase() in excludes)) {
arguments.callee(searchText, replacement, callback, currentNode, excludes);
}
// skip to next iteration if the data is not a text node or a text that matches nothing
if (currentNode.nodeType !== Node.TEXT_NODE || !regex.test(currentNode.data) ) {
continue;
}
// generate the new value
var parent = currentNode.parentNode;
var new_node = (callback
|| (function(text_node, pattern, repl) {
text_node.data = text_node.data.replace(pattern, repl);
return text_node;
}))
(currentNode, regex, replacement);
parent.insertBefore(new_node, currentNode);
parent.removeChild(currentNode);
}
}
Example of callback function :
findAndReplace(/foo/gi, "bar", function(text_node, pattern, repl){
var wrap = document.createElement('span');
var txt = document.createTextNode(text_node.data.replace(pattern, repl));
wrap.appendChild(txt);
return wrap;
});
Thanks again, J-P, for this very helpful piece of code.

Categories

Resources