"thing.appendChild is not a function" for object method - javascript

Apologies for the horrific title; I'm unsure how to summarise this problem in such few characters.
TL;DR Why doesn't $("#canvas").appendChild() work?
I have a prototype Car which, on instantiation, is supposed to create a div inside a div whose id is "canvas".
$(document).ready(function() {
var canvas = $("#canvas");
function Car(speed) {
...
this.domDiv = document.createElement("div");
$(this.domDiv).addClass("car");
this.addToCanvas = function() {
canvas.appendChild(this.domDiv);
};
this.addToCanvas();
...
}
car1 = new Car(0.5);
});
However, I get Uncaught TypeError: canvas.appendChild is not a function, and I don't understand why.

appendChild is a DOM function. append is a jQuery function (canvas is a jQuery object).

I think the correct function is append, rather than appendChild on a jQuery wrapper
canvas.append(this.domDiv);
You would want to use appendChild if you used a host query selector (document.getElementById('canvas')) rather than a jQuery selector ($('canvas'))

Related

creating Vanilla JS equivalent css method of jQuery

I am trying to create a function like the function of jQuery which changes the style of an HTMLElement, probably you have seen it somewhere:
$("button").css("color", "red");
which is pretty handy, so here is what I've tried:
function $(selector, parent=document){
return parent.querySelector(selector);
}
so the above code is the code of the function $ which grabs an HTMLElement from the DOM,this seems to work perfectly.
Now, the next step for me is to define the $ function methods and properties, so the method I want to create is the css method as seen in the previous example:
$.css = function(style, value){
this[style] = value;
}
now after testing the css method it's not working (and of course it will never work, but I'm just trying to deliver my question idea for you).
I know a lot about object-oriented programming in JavaScript, I am comfortable with it, so I have no problem if you posted any answer, I will try my best to understand it.
I've tried a lot to understand what's the magic that the jQuery developers made to create this method.
What do you think the best approach to make it? what about mixins, what if I wanted other functions and not just "$" to inherit this "css" method?
To modify styles, you need to set a CSS property of the style declaration object of an element. For example:
elm.style.color = 'red';
You need to modify your $.css to access the current element(s) in the collection, and access their .style[propertyName] property.
You can put the collection onto a property of the instance, and make sure to put the css method as a prototype of the class:
function collection (selector, parent = document) {
this.elms = parent.querySelectorAll(selector);
}
collection.prototype.css = function(prop, value) {
for (const elm of this.elms) {
elm.style[prop] = value;
}
}
const $ = (...args) => new collection(...args);
$("button").css("color", "red");
<button>a button</button>
<button>a button</button>
Because your $ doesn't use new, you'll either need it to return an instance of a different class (as in the code above), or always use new when calling it, or have $ return its instance created via Object.create, or something like that. There are various methods.
Not sure if this is what you're after, but you could just apply the style inline?
var elem = document.querySelector('#some-element');
//set color to red
elem.style.color = 'red';
//set the background color to a light gray
elem.style.backgroundColor = '#e5e5e5';
//set the height to 225px
elem.style.height = '225px';

How can I make an alias for element.querySelector?

For example, my element is a DOM element div, and within it are other divs.
So I generally use elem.querySelector('.whatever') to find a child within it. But I'd like to rename querySelector to find.
But how can I do this for all DOM elements, is there an easy way? I'd rather not just have "function find(elem, what)", but rather I'd like to do it on the element itself so "elem.find('.whatever')"
You can create a function to achieve the same thing, but will give extra work to the browser
HTMLElement.prototype.find = function(selector){
//or querySelector for one element depends on need
return this.querySelectorAll(selector);
};
elem.find('.whatever');
Warning! Modifying the core prototype is a bad practice.
Another solution from "connexo"
HTMLElement.prototype.find = HTMLElement.prototype.querySelector
You can also create your own version of "jquery" if you are afraid of modifying the core prototype
function $$(element) {
return {
find: function(selector) {
return element.querySelectorAll(selector);
}
}
}
//then just wrap any object
$$(elem).find(selector);
I almost always use the global document.querySelector form, and it's definitely too verbose for my taste.
While not exactly an alias, I really like this simple solution:
function get (selector, context=document) {
return context.querySelector(selector)
}
function getAll (selector, context=document) {
return context.querySelectorAll(selector)
}
// get single element
get("#id")
// get all elements
getAll("nav li")
// all within an element
getAll("li", element)

jQuery throws an error that element.find() is not a function

I have written a small JS to iterate through a set of matched elements and perform some task on each of them.
Here is the code:
var eachProduct = $(".item");
eachProduct.each(function(index, element){
var eachProductContent = element.find(".product-meta").clone();
});
When I console log element it outputs properly and the exact objects. Why should jquery throw this error?
because element is a dom element not a jQuery object
var eachProductContent = $(element).find(".product-meta").clone();
Inside the each() handler you will get the dom element reference as the second parameter, not a jQuery object reference. So if you want to access any jQuery methods on the element then you need to get the elements jQuery wrapper object.
You are calling .find() on a plain JS object, But that function belongs to Jquery object
var eachProductContent = $(element).find(".product-meta").clone();
You can convert it to a jquery object by wrapping it inside $(). And in order to avoid this kind of discrepancies you can simply use $(this) reference instead of using other.
Use $(this) for current Element
var eachProductContent = $(this).find(".product-meta").clone();
you should change "element" to "this":
var eachProduct = $(".item");
eachProduct.each(function(index, element){
var eachProductContent = $(this).find(".product-meta").clone();
});

Why can't javascript/jQuery get parentNode?

Considering that I have an element like this:
<p class="ELP">2/1/2013 - <a id="EL3" class="ELLink" href="/Event htms/Event.cshtml?title=Okmulgee Public Schools County Professional Day&explanation=Okmulgee Public Schools County Professional Day.&dateString=2-1-2013">City Public Schools County Professional Day</a></p>
Why does this JavaScript/jQuery work...:
$(".ELP").click(function (){
var stringDate = $(this).text().substring(0, 8)
console.log(stringDate)
});
Console.log produces: 2/1/2013
...And this JavaScript/jQuery doesn't?
$(".ELLink").click(function (){
var stringDate = $(this).parentNode.text().substring(0, 8)
console.log(stringDate)
});
Console.log produces nothing because of JavaScript error: Uncaught TypeError: Cannot call method 'text' of undefined
Clearly I can see that it is not 'getting' the right element, but why? Isn't the first parent node of my 'a' element the 'p' element? As far as I understand it, there is no (at least no cross-browser/platform compatible) valid css selector for the direct parent node of an element or i would just use that.
What am I not seeing?
The jQuery method is called parent()
$(".ELLink").click(function (){
var stringDate = $(this).parent().text().substring(0, 8)
console.log(stringDate)
});
Because the jQuery object does not have a parentNode property.
var stringDate = $(this.parentNode).text().substring(0, 8);
$(...) does not return DOM elements, it returns an array-like object that references DOM nodes. DOM nodes have parentNode. jQuery instances do not.
If you need to select the immediate parents of the selected elements, you can use parent():
$(this).parent().text()...
Why not use:
var stringDate = $(this).parent().text().substring(0, 8)
Since you're already using jQuery, you can use the parent function.
You need to use parent() not parentNode. Like this:
$(".ELLink").click(function (){
var stringDate = $(this).parent().text().substring(0, 8)
console.log(stringDate)
});

jQuery syntax not setting object property

My jQuery question I beleive is pretty simple, which is driving me insane that I can't get it.
I have an object with a property "content", I want to be able to take that object, manipulate the property "content" with jQuery and then overwrite the value with the new value jQuery creates.
Example:
o.content = "<div><span>hello</span></div>";
$('div', o.content).addClass('test');
At this point I want o.content to be equal to <div class='test'><span>hello</span></div>
I can not for the life of me figure out the syntax. Any help is really appreciated.
This will give you a string <div class="test"><span>hello</span></div> if this is what you want:
$(o.content).addClass('test').wrap('<div>').parent().html();
Parse the html in o.content, add the class, append the parsed html to a new <div>, and get the html of the new div:
o.content = "<div><span>hello</span></div>";
var el = $(o.content).addClass('test');
o.content = $("<div>").append(el).html();
Edit: This assumes you want o.content to still contain a string, rather than a jQuery object. In that case, it's simpler:
o.content = $(o.content).addClass('test');
from the docs of the jquery function, context must be
A DOM Element, Document, or jQuery to use as context
Your context (o.content) is a string. Also, the jQuery function is not able to select the entire context, it can only select elements in that context.
Try this instead:
// make o.content a jquery element, not a string
o.content = $("<div><span>hello</span></div>");
// select on something inside the context (inside the div), not the div itself
$('span', o.content).addClass('test');
http://jsfiddle.net/JfW4Q/
I don't think you can lookup an element from a string like that.. I would rather do it like below,
var content = "<span>hello</span>";
content = $('<div/>', {class: 'test'}).html(content)
DEMO: http://jsfiddle.net/k4e5z/
You want the following
o.content = "<div><span>hello</span></div>";
// Create a jQuery object you can call addClass on
var docFragment = $(o.content);
docFragment.addClass('test');
// Since there's no outerHTML in jQuery, append it to another node
var wrapper = $('div');
docFragment.appendTo(wrapper);
// The HTML of the wrapper is the outerHTML of docFragment
console.log(wrapper.html()); // outputs <div class='test'><span>hello</span></div>
Why not do it all in one line:
var o = {};
o.content = $( "<div></div>" ) // create element
.addClass('test') // add class
.html( '<span>hello</span>' ); // append content
Fiddle: http://jsfiddle.net/kboucher/eQmar/
o.content = $("<div><span>hello</span></div>");
o.content.addClass('test');
o.content is a jQuery object in this example, as opposed to just a string. Here's a demo on jsfiddle: http://jsfiddle.net/cvbsm/1/

Categories

Resources