String literal not being appended to DOM - javascript

I'm trying to make functions that return me an HTML element as a string so I can eventually append them to the DOM and pass them around my functions. I have paragraph, heading, and div's working but cannot for the life of me seem to get links to work.
This is the non-working codepen
The javascript in question is:
function link(href,text,css){
let target = ``;
if(css == null ){
return target;
}
return addStyles(target,css);
}
My addStyles function is:
function addStyles(target,css){
if(css == null ){
return target;
}
let props = Object.keys(css);
props.forEach((prop)=>{
switch(prop){
case 'id':
$(target).attr('id', css[prop]);
break;
case 'class':
let classes = css[prop];
if(Array.isArray(css[prop])){
classes = css[prop].toString().replace(',', ' ');
}
$(target).addClass(classes);
break;
default:
$(target).attr('data-name', 'Timi');
}
});
return target;
}
which for a long time gave me errors but only when calling it from the link function. I tried hard-coding in the href to see if maybe my string literals were giving me the errors but still no avail.
while calling it from this function it works perfectly
function createDiv(css){
let newDiv = $(div);
return addStyles(newDiv,css);
}
I say that the addStyles function works and that I think it's the link() that is giving me problems because createDiv works and appends the DOM with these calls
app.append(createDiv({id: 'testing'}));
app.append(createDiv({class: ['bar', 'snuff']}));
app.append(createDiv()).append(createDiv({class: 'timi'})).append(paragraph('Hey guys!'));
$('#testing').append(heading(1,'Hello'));

your let target = ; is a string. you should use a DOM and manipulate its attribute instead
function link(href,text,css){
let target = document.createElement('a');
let linkText = document.createTextNode(text);
target.appendChild(linkText);
target.href = href;
if(css == null ){
return target;
}
return addStyles(target,css);
}

You forgot to wrap the a tag with bling:
let target = $(``);

The reason your createDiv function is working as expected and your link function isn't is because you haven't wrapped your representation of an html element (the one you pass to addStyles) in a jQuery wrapper like you do in your createDiv function. See my below code for what I've changed to get it to work:
function link(href,text,css){
let target = `${text}`;
if(css == null ){
return target;
}
return addStyles($(target)[0],css);
}
codepen
I'm a little lost actually why we need to add [0] to $(target) but we do. Maybe someone else could chime in about why that is the case with ${text} and not with <div></div>
Edit: disregard above about the [0] and see comments on this answer.

Related

Javascript onclick event not working with variable reference

I am reading some code and trying to replicate the same at my end step by step.
I am attaching an event to a particular button and onclick it should log a statement.
Following is the code that does not work :-
(function(){
var el = function(element){
if(element.charAt['0'] === '#'){
return document.querySelector(element);
}
return document.querySelectorAll(element);
}
var viewer = el('#viewer');
var clear = el('#clear');
console.log(clear);
var clearAll = function(){
console.log('Clearing');
};
//click event
clear.onclick = clearAll;
})();
Above a function is used to get elements.
The below code works
document.getElementById('clear').onclick = clearAll;
or
document.querySelector('#clear').onclick = clearAll;
I do not understand why the above code does not work. Please Help.
"foo".charAt['0'] is undefined because charAt is a function and doesn't have a 0 property.
You need () (to call the function), not [] (to access properties of the object).
You are using charAt as an array while it is a function.
var el = function(element){
if(element.charAt('0') === '#'){
return document.querySelector(element);
}
return document.querySelectorAll(element);
}
See it working https://jsfiddle.net/
Regards,

How to echo something from javascript to div class html

Javascript
function validateForm() {
var result;
var keywords = document.querySelectorAll('#keywords');
[].slice.call(websites).forEach(function(website) {
if (website.value == '') {
website.focus();
HERE I SAY SOMEHOW THE ERROR
result = false;
return true;
}
});
return result;
}
HTML
<div class="error-website">HERE THE ERROR IS GETTING ECHOED</div>
How do i echo website in that div above and how do i add the error in that if condition.
Try:
document.querySelectorAll('.error-website')[0].innerHTML = 'Website';
As NULL and VisioN has pointed , this:
document.querySelector('.error-website').innerHTML = 'Website';
is even faster , because of "querySelector is faster unless the match is the last DomNode in the DOM".
First of all, it would be more appropriate to use an ID not a class; the reason is that classes are meant for, well, classes (i.e. categories) of elements; however, in your case, you are dealing with one single unique element (you'll only have one), so assuming you take my advice and change to the following markup:
<div id="error-website">HERE THE ERROR IS GETTING ECHOED</div>
... it will be as simple as:
document.getElementById('error-website').innerHTML = "whatever <strong>you</strong> <em>like</em>";
$(".error-website").text("Website")
document.getElementById('error-website').innerHTML = ....
if you use an id...
Use DOM document.getElementsByClassName
Eg.
function validateForm() {
var result;
var keywords = document.querySelectorAll('#keywords');
[].slice.call(websites).forEach(function(website) {
if (website.value == '') {
website.focus();
HERE I SAY SOMEHOW THE ERROR
result = false;
return true;
}
});
return result;
var a=validateForm();
if(a){
document.getElementsByClassName("error-website")[0].innerHTML=a;
}
NOTE: getElementsByClassName() does not work in Internet Explorer 5,6,7, and 8

For what reason i can't retrieve element by ID once climbed on his parent?

in html i've a code like this
<body>
<script src="debug.js"></script>
<button id="proof" onclick="debug('result:', this);">proof</button>
</body>
and in javascript:
function debug(msg, e)
{
var log = document.getElementById("debuglog");
if (!log)// If no element with the id "debuglog" exists, create one.
{
log = document.createElement("div"); /
log.id = "debuglog";
log.innerHTML = "<h1>Debug Log</h1>";
document.body.appendChild(log);
}
var pre = document.createElement("pre");
var text = document.createTextNode(msg + e.parentNode.getElementById("proof")); //<--PROBLEM HERE
pre.appendChild(text);
log.appendChild(pre);
}
}
Note that the code works if into the text node i write msg + e.parentNode, once i add .getElementById("proof"), no result is retrieved (i think that the script goes in error in runtime phase).
What i want to do is "navigate" throught the html elements, calling his parents and his childrens
getElementById is a prototype of document, not a prototype of each and every element (inside the document).
So if you want to restrict getElementById to search children of a specific element instead of searching the entire document (in the same way one can do getElementsByTagName using a specific element as the parent) you'll need to add your own proto-type to all elements (but IE does not support prototyping on HTMLElement) or write your own function.
See this page for some suggestions, but keep in mind, an Id should always be unique inside a page, so simply using document.getElementById that is built-in and optimized in the browser is still going to be faster.
Update:
Here is a rewrite of the function I linked to, without the errors and a faster reverse-while loop:
function GetChildById( dNode, id ) {
var i, dResult = null;
if ( dNode.getAttribute('id') === id ) { return dNode; }
i=dNode.childNodes.length;
while ( i-- ) {
if ( dNode.childNodes[i].nodeType === 1 ) {
dResult = GetChildById( dNode.childNodes[i], id );
if ( dResult !== null )
break;
}
}
return dResult;
}
Usage: GetChildById( node, 'id' )
Demo: jsfiddle
But like axel.michel said: don't do that, it's useless.
Since the ID has to be a unique element on a page, you can simply access it by using document.getElementById('YOURID'). It is method of document so your script throws an error. If you want to implement something like this, you have to do it by a custom function:
function youShouldNotDoThis( element, id ) {
var hit = null;
if ( element.getAttribute('id') == id ) {
return element;
}
for ( var i = 0, l = element.childNodes.length; i < l; i++ ) {
if ( element.childNodes[i].nodeType == 1 ) {
hit = youShouldNotDoThis( element.childNodes[i], id );
if ( hit != null ) {
break;
}
}
}
return hit;
}
And in your script fragment:
var whyEver = youShouldNotDoThis(e.parentNode,'proof');
var text = document.createTextNode(msg + whyEver); //<--NO MORE PROBLEM HERE
And again, you should not do this by the Attribute ID, because ID should be unique, but you can easily change this function to scan for something different than ID.

How to recursively search all parentNodes

I want to know, how to find out recursively all parent nodes of an element.
Suppose i have following snippet
<font>Hello</font>
In this I would like to find out whether font tag's parent node is an anchor tag or not.
Now this can be achieved by simply checking .parentNode property. But what if there are following cases like,
<font><b>Hello<b></font>
or
<font><b><u>Hello</u><b></font>
So, basically, how to know if we have reached the top most parent node ?
You can traverse from an element up to the root looking for the desired tag:
function findUpTag(el, tag) {
while (el.parentNode) {
el = el.parentNode;
if (el.tagName === tag)
return el;
}
return null;
}
You call this method with your start element:
var el = document.getElementById("..."); // start element
var a = findUpTag(el, "A"); // search <a ...>
if (a) console.log(a.id);
The following recursive function will return an ascending ordered array, with all the parents nodes for the provided DOM element, until BODY node is reached.
function parents(element, _array) {
if(_array === undefined) _array = []; // initial call
else _array.push(element); // add current element
// do recursion until BODY is reached
if(element.tagName !== 'BODY' ) return parents(element.parentNode, _array);
else return _array;
}
Usage :
var parentsArray = parents( document.getElementById("myDiv") );
You can use jQuery closest() method to get the closest ahref:
$("#your-element").closest("a").css("color", "red");
Or you can have a look at the parentsUntil method:
$("#your-element").parentsUntil("#yourWrapper", "a").first().css("color", "red");
Try it out here: http://www.lunarailways.com/demos/parents.html
I been working on similar thing. Trying to close a div if user clicks outside the div. It needs to loop through all its parent nodes.
have a look at this:
http://jsfiddle.net/aamir/y7mEY/
Here's a shorter one:
function parentByTag(el, tag) {
if(!el || el.tagName == tag) {
return el
} else {
return parentByTag(el.parentElement, tag)
}
}
Returns undefined if not found.

Can I reduce this Javascript code?

Can I reduce
function n()
{
var a;
if(a = document.getElementById('fb0'))
{
a.onclick = i0;
document.getElementById('fb1').onclick = i1;
}
}
to
function n()
{
if(document.getElementById('fb0').onclick = i0)
{
document.getElementById('fb1').onclick = i1;
}
}
I don't have a debugger right now. I know that document.getElementById('fb0') returns a value because the first snippet works fine. But does it need the assignment to be evaluated in the if statement?
No, you can't.
document.getElementById('fb0'), as the function name already says, returns the html element with has the id equal to fb0. After that you are accessing the attribute onclick. But it the get fails it will break the script.
On the first scenario you test if the assignment works, if does it means the element exists and will only execute if it exists.
Those are different behaviors.
Not really; if getElementById('fb0') doesn't return anything your page will get an error, and in the first case it wouldn't.
To check if "document.getElementById('fb0')" returns an element or null, the second version don't do it and an error will be throw if there is no element with id "fb0". The second version is ok if you don't remove the "fb0" element from the DOM at some point.
That would fail if document.getElementById('fb0') were not to exist. document.getElementById('fb0').onclick wouldn't mean much in that case.
If you do a lot of DOM selection by ID, make a shortened version of that method:
function byId( id ) { return document.getElementById(id); };
function n() {
var a;
if(a = byId('fb0')) {
a.onclick = i0;
byId('fb1').onclick = i1;
}
}
In this case, doing the assignment inside the condition doesn't save you any characters. It's the same length to do it with the declaration.
function byId( id ) { return document.getElementById(id); };
function n() {
var a = byId('fb0');
if(a) {
a.onclick = i0;
byId('fb1').onclick = i1;
}
}

Categories

Resources