jQuery .map won't work properly sometimes - javascript

I built some Chrome extension that uses $(".class").map(..) function, but for some reason sometimes it won't find the element I am looking for..
This is my code:
var videocontent = $(".content").map(function () { if (this.innerHTML.indexOf("id=\"player_wrapper\"") > -1) { return this; } });
if(videocontent.length)
{
// Success
}
else
alert("ERROR");
There are multiple elements with class .content so I use .map to find the correct one.
Once every 10 times it attempts, it will alert an error because it didn't find it for some reason. I was trying multiple things but couldn't find a solution.

$(...).map() isn't designed for searching for element, it is for applying a function to each element of an array to transform it somehow. You want to use $(...).find() instead:
var videocontent = $(".content").find('#player_wrapper');
https://api.jquery.com/find/
And it looks like you are then going up the tree to find it's parent, so:
var videocontent = $(".content").find('#player_wrapper').parent();

Related

Trying to get some buttons do the same thing

I am using Animate to create an animation. I am on the process of getting all the buttons to do what they are supposed to. Right now, I am stuck with the following. I would like to assign multiple buttons the same action, this is because the buttons appear on many different frames, so this is what I have got but I am getting an error.
var btns = ["btncasco","btncasco1","btncasco2"];
btns.forEach( btnsIteratee.bind(this));
function btnsIteratee(item){
this[item].addEventListener("click", function(event){
this.gotoAndStop(0);
});
}
I want to be able to click on any of the referenced button names and make them go to frame 0. Any idea about of what is wrong?
This is the error I get:
"Uncaught TypeError: Cannot read property 'addEventListener' of undefined"
It's a little hard to tell from the small amount of code you have provided what else is going on that could cause unexpected behaviour of this. However. The following:
btns.forEach( btnsIteratee.bind(this));
Could benefit from being bound once, as the reference to this won't change for each instance of the forEach loop. Then having the array item passed in. Something like:
var btns = ["btncasco", "btncasco1", "btncasco2"];
function btnsIteratee(item) {
item.addEventListener("click", function(event) {
this.gotoAndStop(0);
});
}
btnsIteratee = btnsIteratee.bind(this);
btns.forEach(btnsIteratee);
The above is pseudo code as there isn't much provided by your example
thanks for the posts. I finally sorted this out using this chunk of code for each series of buttons.
var btntres = ['btnlumbrera2' , 'btnlumbrera3' ,'btnlumbrera4' ,'btnlumbrera5' ,'btnlumbrera6' ,'btnlumbrera7', 'btnlumbrera8', 'btnlumbrera9', 'btnlumbrera10', 'btnlumbrera11', 'btnlumbrera12', 'btnlumbrera13', 'btnlumbrera14', 'btnlumbrera15', 'btnlumbrera16', 'btnlumbrera17', 'btnlumbrera18'];
btntres.forEach( btnsIteratee3.bind(this) );
function btnsIteratee3(item){
if (this[item] && !this[item].hasEventListener('click')) {
this[item].addEventListener("click", hyandler.bind(this));
} else {
console.log('item no existe', item);
}
function hyandler(event){
this.gotoAndStop(4);
}
}

document.querySelector() on elements not in DOM?

I'm working on a website, with jQuery but I'm trying to not use it anymore. In jQuery you can add an even listener on a element that wasn't on the website or wasn't created yet and no problem. I have elements that are only on the DOM when you're logged in, and I only have one JS file for the whole website.
Problem is, for example, when you're logged in you can't see the "log in" button, it's not even in the DOM, but it still have the event listener in the code, no error on the console, script runs well.
$("#logInButton").on("click", somefunction);
But, using document.querySelector("#logInButton").onclick = somefunction and being logged in already, it throws an error because document.querySelector("#logInButton") is null.
I can do like:
let logInButton = document.querySelector("#logInButton");
logInButton ? logInButton.onclick = somefunction : "";
And it works well, but I know it's not a good practice. Any workaround or improvement to that, not using jQuery?
JSFiddle if what happens. (See console)
And it works well, but I know it's not a good practice.
If having #logInButton on the page is optional, that's perfectly good practice — other than using onclick rather than addEventListener (but that's probably a matter of style). Naturally, you'd have this code in a script linked at the end of the document, just prior to the </body> tag (or trigger it via a DOMContentLoaded callback).
But if you want the equivalent of the jQuery, you need to think in jQuery's "set-based" mindset and use querySelectorAll:
// Not very efficient
document.querySelectorAll("#logInButton").forEach(function() {
// Set up the handler here using `this`
});
Except that jQuery optimizes queries using #id format to a getElementById call (which is dramatically faster) and then uses an if (like yours) to build the set with either one element or zero.
Perhaps in your quest to not use jQuery, you might give yourself a couple of helper functions to take its place, as the DOM API is quite verbose. If you like jQuery's set-based nature, you might even make them set-based:
function MyQuery(selector) {
if (!selector) {
this.data = [];
} else if (typeof selector === "string") {
// (jQuery takes it further than this, search in an unminified version for `rquickExpr`)
var id = /#([\w-]+)/.match(selector);
if (id) {
var e = document.getElementById(id[0]);
this.data = e ? [e] : [];
} else {
this.data = Array.from(document.querySelector(selector));
}
} else {
/* ...handle other things, such as DOM elements or arrays of them...? */
this.data = /*...*/;
}
}
MyQuery.prototype = {
constructor: MyQuery,
on: function(eventName, handler) {
this.data.forEach(function(element) {
element.addEventListener(eventName, handler);
});
return this;
}
// ...etc...
};
function qset(selector) {
return new MyQuery(selector);
}
Then
qset("#logInButton").on("click", /*...*/);
Of course, you might find yourself basically recreating jQuery. But if you keep it lean...
Side note: Using forEach on the return value of querySelectorAll requires an up-to-date browser, or that you polyfill it:
if (typeof NodeList !== "undefined" &&
NodeList.prototype &&
!NodeList.prototype.forEach) {
Object.defineProperty(NodeList.prototype, "forEach", {
value: Array.prototype.forEach
});
}
For truly obsolete browsers (like IE8), you'd have to polyfill Array.prototype.forEach first.
You can do it the same way jQuery does it, using event bubbling.
document.addEventListener('click', function (ev) {
if (ev.target.id === 'someIdHere') {
console.log('click');
}
});

Looping through multiple checkboxes and adding the checked values to an array to write back to Sharepoint

I have a block of code that is supposed to look at which checkboxes are checked and then write the value of those checkboxes to an array so that I can write the data back to Sharepoint. I got it working before when I used an if/else statement, but I need it to be able to handle multiple checkboxes being selected. I did some research and found part of my code from another answer and combined it with some of my code but it doesn't seem to be working and I'm not sure why. None of the other answers I came across seem to be what I'm looking for.
Basically, what I'm asking is, what is the best way to achieve what I'm trying to do?
function addCustomers() {
$(document).ready(function () {
var customers = [];
var ckbox = $('.customer-options');
$('input').on('click', function () {
if (ckbox.is(':checked')) {
customers.push(ckbox).val();
}
else {
}
});
customers.toString();
document.getElementById('mxID04').innerHTML = customers;
});
}
It's not exactly clear what you are trying to do. First, your function contains document.ready which doesn't look right. Then you create some vars which I think you want to fill because at the end you are setting another element's innerHTML to, but in between you've just created a click handler which isn't going to work. Here's what I've put together for testing. I think you should be able to modify my example into what it is you're after
function addCustomers() {
var customers = [];
var ckbox = $('.customer-options');
alert('add handler');
$('input').change(function() {
$('input:checked').each(function() {
customers.push(this);
});
});
}
$( document ).ready(function() {
// alert('here');
addCustomers();
});

What method do use when adding a jquery collection to a jQuery collection?

So I tried this:
var allItems = jQuery();
function additems(items) {
allItems = allItems.pushStack(items);
}
additems(jQuery("#ul1").find("li").first());
additems(jQuery("#ul2").find("li").first());
additems(jQuery("#ul3").find("li").first());
allItems.each(function() {
jQuery("ul1").append(this);
});
She doesn't work in jsFiddle.
What I need is to keep a collection of some <LI> items hopefully in a jQuery object. And i'd like it to use a function passing in a jQuery object. I also need to add to the collection inside a function like what I have above so it can be done at different times in the code.
i know i can get around it by something like:
function additems(items){
items.each(function(){ allItems.pushStack(this);});
}
or by just sending them as a list of HTML <LI> Elements, but I'd rather do it something like the above and I haven't found a clean and efficient way of doing this.
Thanks!
PS: I'd rather not need a plugin.
UPDATE
let me explain more. I have one function that does something and it has an <ul> element from which i can pull out the <li> elements.
I then want to send these elements to another function to keep them for later.
function doSomething1()
{
//Do something
var ulElement = getFromSomewhere();
additems(jQuery(ulElement).find("li"));
// do something else
return;
}
function additems(items)
{
MyObject.allItems.pushStack(items)
}
the jsFiddle was Simplified compared to my code.
new jsfiddle with "#" fixed http://jsfiddle.net/LPkkT/8/
ANSWER
Upon adding Quincy's answer to my fiddle in a way that didn't remove all my code i got:
var allItems = jQuery();
function additems(items) {
allItems = allItems.add(items);
}
additems(jQuery("#ul1").find("li").first());
additems(jQuery("#ul2").find("li").first());
additems(jQuery("#ul3").find("li").first());
allItems.each(function() {
jQuery("ol").append(this);
});
And this works.
Firstly, if you want to select by id, you have to add a '#' in the selector.
And you can add jquery collections using the add() method
var allItems =
jQuery("#ul1").find("li").first()
.add(jQuery("#ul2").find("li").first())
.add(jQuery("#ul3").find("li").first());
allItems.each(function() {
jQuery("ol").append($(this));
});
http://jsfiddle.net/LPkkT/4/
Can't you get the collection of items just by using a jQuery selector?
If you mark your items with a class you can get a collection with one simple selector

JQuery not a function error

While developing with Firebug I keep getting this error.
pages[x].css("z-index",x) is not a function
The function itself works fine but I'm trying to figure out why it keeps flagging this. The function is simultaneously reorganizing the array and the z-indexes.
Can i not access array variables and call functions on them like this or is this something else?
full code:
var pages = $("#use-wrapper").children("div");
pages.children("a.right").click(function(event) {
event.preventDefault();
$(this).parent("div").css("z-index","0");
pages.push($(this).parent("div"));
for(var x = pages.length; x >= 1; --x) {
pages[x] = pages[x-1];
pages[x].css("z-index",x);
}
pages[0] = pages.pop();
});
If you do an alert(pages[x]), you'll find that each pages[x] is a DOM element and not a jQuery object, which is why you get the error that pages[x].css is not a function. You probably want to do:
$(pages[x]).css('z-index', x);
Edit: Even though jQuery lets you access the elements of pages as though it's an array, it's not a true array object, so I doubt that push and pop will work too.

Categories

Resources