Trouble selecting object ID with wildcard - javascript

I'm using multiple instances of jwplayer on my page that generate random keys onto the end of the player ID every time the page loads. Example: jwplayer_ad1_012 and on next refresh jwplayer_ad1_123.
I'm trying to select the player and make it play(I am aware of autoplay) by using the javascript $("object[id^='jwplayer_ad1_']").jwplayer().play(); and that's throwing up an error. I tried to assign $("object[id^='jwplayer_ad1_']") to a var and use testvar.jwplayer().play(); and that didn't work either as console says
Uncaught TypeError: $(...).jwplayer is not a function so i did window.alert(testvar); to make sure the var was being set and the alert just said [object Object]
Can I have some insight to what I'm doing wrong?

I don't believe jwplayer is a jQuery plugin, but you're trying to call it like one.
This page suggests that in order to use jwplayer, you call the jwplayer function and pass it the id of the element to use, or an index (0 = the first one).
So if you want to play the first one, simply:
jwplayer(0).play();
or (apparently 0 is the default):
jwplayer().play();
If you want one of the others, you can use a higher index.
If you wanted to do it by id instead, you could find the id:
var id = $("object[id^='jwplayer_ad1_']").attr("id");
...and then do this:
if (id) { // Did we find one (the above returns `undefined` if there weren't any)
jwplayer(id).play();
}
...but that's a very roundabout way.

Related

WHY do I get an empty object when searching by element or xpath _____ HTMLSession, requests-html

I just want to verify the element exists somehow. Trying to print it so I can compare against a string or something.
Here is the problematic code.
session = HTMLSession()
r = session.get('https://www.walmart.com/ip/Sony-PlayStation-5-Video-Game-Console/994712501')
r.html.render(timeout=20)# this call executes the js in the page
oos=r.html.xpath('/html/body/div[1]/div[1]/div/div[2]/div/div[1]/div[1]/div[1]/div/div/div/div/div[3]/div[5]/div/div[3]/div/div[2]/div[1]/section/div[2]/div/div/div/div/div')
print(oos)
#print returns []
I try to print(oos.text) and I get a callback error
#'list' object has no attribute 'text'
also tried print(oos.full_text) same error
'list' object has no attribute 'full_text'
Seems like its a list? So I tried to iterate through it.
for i in oos:
print(i)
#Prints absolutely nothing!
Pretty sure the element doesn't exist. Based on an examination of print(html) I believe I am being redirected to a capthcha page.
Therefore I am going to assume that the [] is essentially an empty list and all code is more or less doing what it's supposed to.

Stuck with simple calculation from form elements

I'm using a script template to create chunks of code when a user clicks a button, this works fine, but I want to be able to calculate a total within these cloned regions so I have a in-line onBlur statement as follows
onblur = "multiply.call(this, this.form.elements.Qty{{ID}}.value, this.form.elements.Cost{{ID}}.value, this.form.elements.Total{{ID}})"
As the cloning function updates ID to a value this evaluates to
onblur = "multiply.call(this, this.form.elements.Qty1.value, this.form.elements.Cost1.value, this.form.elements.Total1)"
My function is
function multiply(one, two, three) {
console.dir(three);
document.getElementById(three).value = (parseFloat(one) + parseFloat(two)).toFixed(2); // error here
};
If I display one and two they have the values from the form, however I get an error writing back to the for of Uncaught TypeError: Cannot set property 'value' of null.
The console shows the ID of the element three as Total1
I think this might be something to do with the jQuery clone and the DOM not being updated. The values are passed OK, but the object might not be.
Any ideas?
document.getElementById(three) returns no match (thus the undefined).
You're passing an element to your function multiply as parameter three, and you're later using it as a string representing the ID of it.
If three is verified to be an element, don't call document.getElementById(three).value in first place, but directly three.value.

What is the browser neutral replacement for HTMLFormElement's all method?

I'm using an institutional (ie, any fix will have to be on my side) website that is IE specific, but I want to use it with Safari. The website mostly works, but at one point I get the following error in my console:
Uncaught TypeError: Object #<HTMLFormElement> has no method 'all'
When I dig into the Javascript the error is coming from:
function fnFocus() {
var frmCtl = document.frmAddEditAdultPosition ;
if(frmCtl !=null) {
var ctlFN = frmCtl.all("txtFirstName") ;
ctlFN.focus() ;
}
}
Calls to the all method are scattered throughout the code.
My plan, is to use proxypy to fix the Javascript as it comes in. I'm assuming that the all method is something IE specific, but I don't know what I should replace it with.
The elements collection:
frmCtl.elements["txtFirstName"] // Might be another collection if there are duplicate fields of that name
or getElementsByName:
frmCtl.getElementsByName("txtFirstName") // Always a collection
or querySelector:
frmCtl.querySelector('[name="txtFirstName"]') // Gets the first match
or querySelectorAll:
frmCtl.querySelectorAll('[name="txtFirstName"]') // Always a collection

live function with out arguments in jQuery

I wanna select some item by jQuery which has been added after loading page,so I wanna use live() function.I used it before for clicking like following code:
$("selector").live('click')
but now when I wanna use it in another function.
but It will not work with out argument,like it live()
for e.g followin code will alert test (work)
var pos_eq=Math.abs($('.myList').css("left").replace("px","")/$('.myList').children('li').eq(0).css('width').replace("px","")) + 1;
alert("test");
but this will not.
var pos_eq=Math.abs($('.myList').live().css("left").replace("px","")/$('.myList').live().children('li').eq(0).css('width').replace("px","")) + 1;
alert("test");
how can I solve it?
You want a function, not a variable. It looks like you are trying to keep pos_eq up to date after elements have been added to the page. Having a variable auto-update when the DOM changes in the way you are trying to do is not possible with JavaScript. What you can do is use a function instead of a variable. This way whenever the value is accessed you are getting the latest value because it is computed on demand:
function pos_eq() {
var list = $('.myList');
var left = parseInt(list.css("left"));
var width = parseInt(list.children('li').eq(0).css('width'));
return Math.abs(left / width) + 1;
}
I broke your code up into multiple statements to make it more readable. You would use this function the same as you used the variable, but instead add parens to the end to invoke the function:
alert(pos_eq);
alert(pos_eq());
To get a set of objects at the time you need them, just do $("selector"). That will do a query at that time and get the set of objects. There is no need to use .live() in order to query objects on the page. It does not matter whether the objects were part of the original page or were added dynamically later. When you do $("selector"), it will search the contents of the current page and get you the objects that are currently in the page that match the selector.
There is no way to do a live selector query and save it and have it automatically update in jQuery or any other library I know of. The way you solve that issue with a dynamic page is that you just do a new query when you need current results.
The description of live() is: Attach a handler to the event for all elements which match the current selector, now and in the future. It does not give you a live node list despite its name. jQuery does not have any method that returns a live node list(such as those returned by getElementsByTagName etc.) as far as I know.

onchange attribute won't call function

I have an HTML document (here), which creates an iframe-based media player for a collection of songs within albums (I just used letters to define these albums and songs in the mymusic array, for simplicity).
Focusing on the top 3 iframes, the way I have set out the user interaction is to generate the HTML for forms of available albums and songs using Javascript, and write them to the iframes in the body. If you run it and make a selection in the Albums menu, you will see that the options in the Songs menu correspond with the mymusic array, so this works.
However, when I choose a song, the function nowplaying(trackindex,albumindex) should be called using an onchange event in the Songs form, the same way as in the form generated using showinitial() ... but the function does not get called.
I have ruled out the coding of nowplaying itself as a cause, because even when I change nowplaying to alert("hello"), it does not get called. So this leads me to think the problem is with the onchange attribute in "anything", but I can't see the problem. The way I coded it is no different to before, and that worked fine, so why won't this work?
Any help would be much appreciated!
Firebug is your friend....
i is not defined
function
onchange(event) {
parent.nowplaying(this.SelectedIndex,
i); }(change )
onchange is getting called, but i is not defined when calling nowplaying.
This is the result of this line:
p+="<html><head></head><body><form><select onchange='parent.nowplaying(this.SelectedIndex,i);' size='";
which is using "i" in the string, when it should append it as a variable:
p+="<html><head></head><body><form><select onchange='parent.nowplaying(this.SelectedIndex," + i + ");' size='";
To clarify, i is defined when anything(i) is called, but you aren't writing i into the code, just the letter "i". When nowplaying(this.SelectedIndex,i) is called, i is no longer defined, because you aren't inside of the anything() function anymore. You need to expand i when you append the html to p, so that the value is there and not the variable i.
function anything(i){
p+="...<select onchange='parent.nowplaying(this.SelectedIndex,i);'...";
Your onchange event handler is set from a string. When run, it will not have access to i, which is a local variable from the anything function that has long since gone away.
The simple fix would be:
p+="...<select onchange='parent.nowplaying(this.SelectedIndex,'+i+');'...";
which turns the current value of i at string-making time into an integer literal inside the string.
However, it's not generally a good idea to be creating code from strings. It's normally better to write the event handler as a normal function object:
// You will need the below workaround to get the iframe document in IE too
//
var iframe= document.getElementById('songs');
var idoc= 'contentDocument' in iframe? iframe.contentDocument : iframe.contentWindow.document;
idoc.open();
idoc.write(s);
idoc.close();
idoc.getElementsByTagName('select')[0].onchange= function() {
// This is a closure. The 'i' variable from the parent 'anything' function is
// still visible in here
//
parent.nowplaying(this.selectedIndex, i);
};
However you would generally want to avoid setting handlers from one frame on a different one. I'm not really sure what the iframes are gaining you here other than headaches. Why not just simply use positioned divs with overflow? You can still rewrite their content through innerHTML if you need to... though I would prefer to populate them using DOM methods, to avoid all the HTML-injection problems your current script has.

Categories

Resources