How to select specified element with CasperJS? - javascript

I want to select first <span> and second <span> , then get their innerText.
Bur i try to use xpath or document.querySelector , they are no working. I console.log my array show null.
// I want to select first <span>
function getDate() {
var date = document.querySelector('div.movie_intro_info_r li').selectedIndex = 1;
return Array.prototype.map.call(date, function (e) {
return e.innerHTML;
});
};
// I want to select second <span>
function getMovieLength() {
var movieLength = document.querySelectorAll(x('//*[#class="movie_intro_info_r"]/span[2]'));
return Array.prototype.map.call(movieLength, function (e) {
return e.innerText;
});
};
casper.then(function () {
casper.each(movieHref, function (casper, url) {
casper.thenOpen(url, function () {
casper.waitForSelector('div.btn_gray_info.gabtn', function () {
console.log('wait for element');
});
releaseDate[urlCount] = this.evaluate(getDate);
console.log(releaseDate[urlCount]);// show null
movieLength[urlCount] = this.evaluate(getMovieLength);
console.log(movieLength[urlCount]);// show null
urlCount++;
});
});
});
How can I just select specified element and get its innerText?

Your code is a bit too complex for what you are trying to do. You should consider using the fetchText method with CSS selectors:
var casper = require('casper').create();
casper.start('YOUR_URL', function () {
this.echo(this.fetchText('.movie_intro_info_r > span:first-of-type'));
this.echo(this.fetchText('.movie_intro_info_r > span:nth-of-type(2)'));
}).run();

Related

Javascript create looping variables

my javascript variables
var select1 = document.getElementById('status-kehadiran1');
select1.onchange = function () {
select1.classList.remove("hijau");
select1.classList.remove("merah");
select1.classList.add(this.options[this.selectedIndex].className);
}
var select2 = document.getElementById('status-kehadiran2');
select2.onchange = function () {
select2.classList.remove("hijau");
select2.classList.remove("merah");
select2.classList.add(this.options[this.selectedIndex].className);
}
var select3 = document.getElementById('status-kehadiran3');
select3.onchange = function () {
select3.classList.remove("hijau");
select3.classList.remove("merah");
select3.classList.add(this.options[this.selectedIndex].className);
}
var select4 = document.getElementById('status-kehadiran4');
select4.onchange = function () {
select4.classList.remove("hijau");
select4.classList.remove("merah");
select4.classList.add(this.options[this.selectedIndex].className);
}
var select5 = document.getElementById('status-kehadiran5');
select5.onchange = function () {
select5.classList.remove("hijau");
select5.classList.remove("merah");
select5.classList.add(this.options[this.selectedIndex].className);
}
var select6 = document.getElementById('status-kehadiran6');
select6.onchange = function () {
select6.classList.remove("hijau");
select6.classList.remove("merah");
select6.classList.add(this.options[this.selectedIndex].className);
}
var select7 = document.getElementById('status-kehadiran7');
select7.onchange = function () {
select7.classList.remove("hijau");
select7.classList.remove("merah");
select7.classList.add(this.options[this.selectedIndex].className);
}
var select8 = document.getElementById('status-kehadiran8');
select8.onchange = function () {
select8.classList.remove("hijau");
select8.classList.remove("merah");
select8.classList.add(this.options[this.selectedIndex].className);
}
var select9 = document.getElementById('status-kehadiran9');
select9.onchange = function () {
select9.classList.remove("hijau");
select9.classList.remove("merah");
select9.classList.add(this.options[this.selectedIndex].className);
}
var select10 = document.getElementById('status-kehadiran10');
select10.onchange = function () {
select10.classList.remove("hijau");
select10.classList.remove("merah");
select10.classList.add(this.options[this.selectedIndex].className);
}
is there a way to create a looping for those variable to make it more simple?
my html select elements
because i have 10 select element with different id
view
the purpose of each variable is to change the text color of each select when there is a change of selected option
i hope you can understand my explanation
Don't use IDs, use a common selector instead for all of those selects - such as [name^="pertemuan"] (name attribute starts with pertemuan):
for (const select of document.querySelectorAll('[name^="pertemuan"]')) {
select.addEventListener('change', () => {
select.classList.remove("hijau", "merah");
select.classList.add(select.options[select.selectedIndex].className);
});
}
You could drop the ids and move status-kehadiran to the selects class list. The you can select all of them with .querySelectorAll() and loop over them with .forEach()
document.querySelectorAll('.status-kehadiran')
.forEach(function(select) {
select.addEventListener('change', function() {
this.classList.remove('hijau', 'merah');
this.classList.add(this.selectedOptions[0].className);
});
});
As mentioned by others you can use query selector with name and ids, but you can also assign them a common class and use -
document.getElementsByClassName('.name of class')
.forEach(function(select) {
select.addEventListener('change', function() {
this.classList.remove('hijau', 'merah');
this.classList.add(this.selectedOptions[0].className);
});
});
You can first select all the elements with ids using Document.querySelectorAll() and then loop through them and attach the event (change) one by one using EventTarget.addEventListener().
You can try the following way:
//you can select by exact id
//var sel = document.querySelectorAll('#status-kehadiran1, #status-kehadiran2, #status-kehadiran3, #status-kehadiran4, #status-kehadiran5, #status-kehadiran6, #status-kehadiran7, #status-kehadiran8, #status-kehadiran9, #status-kehadiran10');
//you can select by id startsWith selector by matching the common part of each id
var sel = document.querySelectorAll('[id^=status-kehadiran]');
sel.forEach(function(el){
el.addEventListener('change', function(){
el.classList.remove("hijau", "merah"); //you can remove multiple class separating them with comma
el.classList.add(el.options[el.selectedIndex].className);
});
});

Count not updating on click

I have two multiselect menus where I'm trying to get a total of how many children are present in each multiselct on load, then update the numbers, based on a click event which will push from one to the other, or vice versa.
The onload portion is working fine. I'm getting the results I'd expect and the counts are accurate.
The problem I'm having is updating both counts once the click event triggers. My counts never change.
Here's my code along with a fiddle:
var activeUser = $('.activeUsers');
var eligibleUser = $('.eligibleUsers');
var availableUserCount = $("#availableUsers option").length;
var eligibleUserCount = $("#eligibleUsers option").length;
activeUser.html(availableUserCount);
eligibleUser.html(eligibleUserCount);
$('#availableUsers').click(function () {
return !$('#availableUsers option:selected').remove().appendTo('#eligibleUsers');
activeUser.length(function() {
return availableUserCount();
});
eligibleUser.length(function() {
return eligibleUserCount();
});
});
$('#eligibleUsers').click(function () {
return !$('#eligibleUsers option:selected').remove().appendTo('#availableUsers');
activeUser.length(function() {
return availableUserCount();
});
eligibleUser.length(function() {
return eligibleUserCount();
});
});
http://jsfiddle.net/mujaji/8gkLyfe3/3/
What am I doing wrong?
There seems to be 3 problems with your code.
You are using return in the fist line of the click event. So the following code will never be executed (Get rid of that and only return if you cannot find any options)
There is no method called length for a div element. (Use .text() instead)
When you are returning the length inside the function return availableUserCount(); it will return you the cached value. (You need to reselect the element again)
So your code should technically look like this (further refactoring can still be made)
var activeUser = $('.activeUsers');
var eligibleUser = $('.eligibleUsers');
var availableUserCount = $("#availableUsers option").length;
var eligibleUserCount = $("#eligibleUsers option").length;
activeUser.html(availableUserCount);
eligibleUser.html(eligibleUserCount);
$('#availableUsers').click(function () {
!$('#availableUsers option:selected').remove().appendTo('#eligibleUsers');
activeUser.text(function() {
return $("#availableUsers option").length;
});
eligibleUser.text(function() {
return $("#eligibleUsers option").length;
});
});
$('#eligibleUsers').click(function () {
!$('#eligibleUsers option:selected').remove().appendTo('#availableUsers');
activeUser.text(function() {
return $("#availableUsers option").length;
});
eligibleUser.text(function() {
return $("#eligibleUsers option").length;
});
});
Check Fiddle
$("#availableUsers option").length doesn't dynamically change with the number of options. Once you set it up top, it's 40 forever. This does what you want:
$('#availableUsers').click(function () {
$('#availableUsers option:selected').remove().appendTo('#eligibleUsers');
activeUser.text($("#availableUsers option").length);
eligibleUser.text($("#eligibleUsers option").length);
});
Although it's not efficient to re-query every time when you could do
availableUserCount--; eligibleUserCount++;
And keep track of it manually.
Best solution (sic) :D
/*JQUERY FUNCTIONS*/
var activeUser = $('.activeUsers');
var eligibleUser = $('.eligibleUsers');
var eligibleUserCount = function(){eligibleUser.html($("#eligibleUsers option").length)};
var availableUserCount = function(){activeUser.html($("#availableUsers option").length)};
eligibleUserCount();
availableUserCount();
$('#availableUsers').click(function () {
$('#availableUsers option:selected').remove().appendTo('#eligibleUsers');
availableUserCount();
eligibleUserCount()
});
$('#eligibleUsers').click(function () {
$('#eligibleUsers option:selected').remove().appendTo('#availableUsers');
availableUserCount();
eligibleUserCount()
});
http://jsfiddle.net/8gkLyfe3/5/
Using return in the first line of the functions prevents any other code from executing in that block.
Check out my fiddle for a functionalized way to perform this
function setUserCounts(){
availableUserCount = $("#availableUsers option").length;
eligibleUserCount = $("#eligibleUsers option").length;
activeUser.html(availableUserCount);
eligibleUser.html(eligibleUserCount);
}
http://jsfiddle.net/8gkLyfe3/6/
Essentially, we add this function and then call it from within the click handlers, while also removing the

focusin event using on not firing

I am attempting to perform some action on the foucsin of the textbox. However, for some reason the event never fires.
$(".ddlAddListinTo li").click(function () {
var urlstring = "../ActionTypes";
$.post(urlstring, function (data) {
$(window.open(urlstring, 'Contacts', 'width=750, height=400')).load(function (e) {
// Here "this" will be the pop up window.
$(this.document).find('#txtAutocompleteContact').on({
'focusin': function (event) {
alert('You are inside the Contact text box of the Contacts Popup');
}
});
});
});
});
When doing it that way, you generally have to find the body or use contents() to access the contents, as in
$(this.document).contents().find('#txtAutocompleteContact')
but in this case using a little plain javascript seems more appropriate :
$(".ddlAddListinTo li").on('click', function () {
var urlstring = "../ActionTypes";
$.post(urlstring, function (data) {
var wind = window.open(urlstring, 'Contacts', 'width=750, height=400');
wind.onload = function() {
var elem = this.document.getElementById('txtAutocompleteContact');
$(elem).on('focus', function() {
alert('You are inside the Contact text box of the Contacts Popup');
});
}
});
});

Panel Visibility via JS

The tutorial at http://www.asp.net/web-forms/tutorials/ajax-control-toolkit/getting-started/creating-a-custom-ajax-control-toolkit-control-extender-vb gives a nice example of a custom extender based on a textbox and a button. Basically the button remains disabled until at least one character is typed into the textbox. If the text is removed from the textbox the button is disabled again.
I am trying to modify this so that the extender is based on a textbox and panel. Again I want the panel to become visible when text is present in a textbox.
This is how I amended code...
Type.registerNamespace('CustomExtenders');
CustomExtenders.ShowHidePanelBehavior = function (element) {
CustomExtenders.ShowHidePanelBehavior.initializeBase(this, [element]);
this._targetPanelIDValue = null;
}
CustomExtenders.ShowHidePanelBehavior.prototype = {
initialize: function () {
CustomExtenders.ShowHidePanelBehavior.callBaseMethod(this, 'initialize');
// Initalization code
$addHandler(this.get_element(), 'keyup',
Function.createDelegate(this, this._onkeyup));
this._onkeyup();
},
dispose: function () {
// Cleanup code
CustomExtenders.ShowHidePanelBehavior.callBaseMethod(this, 'dispose');
},
// Property accessors
//
get_TargetPanelID: function () {
return this._targetPanelIDValue;
},
set_TargetPanelID: function (value) {
this._targetPanelIDValue = value;
},
_onkeyup: function () {
var e = $get(this._targetPanelIDValue);
if (e) {
var visibility = ("" == this.get_element().style.value);
e.visibility = 'visible';
}
}
}
CustomExtenders.ShowHidePanelBehavior.registerClass('CustomExtenders.ShowHidePanelBehavior', Sys.Extended.UI.BehaviorBase);
When run the panel will not appear. No errors are produced.
Where have I gone wrong...
Try this code:
_onkeyup: function () {
var panel = $get(this.get_TargetPanelID());
if (panel) {
var visibilityValue = ("" == this.get_element().value) ? "hidden" : "visible";
panel.style.visibility = visibilityValue;
}
}

Is it possible to bind to the Click event and not use an anonymous function -- I just want to call a named function

I have the following code. The first attempt at binding to click event does not work. The second way does. The first shows the alert "CheckBox1" during Page_Load. The second one shows the alert "CheckBox4" during the proper time -- during clicks.
$(document).ready(function () {
$(document.getElementById(checkBox1ID)).click( SetCheckBox1State(this.checked) );
$(document.getElementById(checkBox4ID)).click(function () { SetCheckBox4State(this.checked) });
});
function SetCheckBox1State(checked) {
alert("CheckBox2");
var radNumericTextBox1 = $find(radNumericTextBox1ID);
var wrapperElement = $get(radNumericTextBox1._wrapperElementID);
var label = $(wrapperElemenet.getElementsByTagName("label")[0]);
if (checked) {
radNumericTextBox1.enable();
label.addClass("LabelEnabled");
label.removeClass("LabelDisabled");
}
else {
radNumericTextBox1.disable();
label.addClass("LabelDisabled");
label.removeClass("LabelEnabled");
}
}
function SetCheckBox4State(checked) {
alert("CheckBox4");
var radNumericTextBox2 = $find(radNumericTextBox2ID);
var wrapperElement = $get(radNumericTextBox2._wrapperElementID);
var label = $(wrapperElemenet.getElementsByTagName("label")[0]);
if (checked) {
radNumericTextBox2.enable();
label.addClass("LabelEnabled");
label.removeClass("LabelDisabled");
}
else {
radNumericTextBox2.disable();
label.addClass("LabelDisabled");
label.removeClass("LabelEnabled");
}
}
Am I doing something improper? I'd rather not use an anonymous function...but maybe this just how things work?
This code:
.click( SetCheckBox1State(this.checked) );
Assigns the .click() function to be the output of this function: SetCheckBox1State(this.checked).
You will have to get rid of the argument (make it internal) and just pass the function name:
.click( SetCheckBox1State );

Categories