PhantomJS: Cannot get Element - javascript

I have a PhantomJS script based on this one: http://code-epicenter.com/how-to-login-amazon-using-phantomjs-working-example/
It works very well, I can, for example, populate the login page and click on the "submit" button with code that looks like this:
function(){
console.log('Step 3');
page.evaluate(function() {
document.getElementById("username-pulldown").value="username";
document.getElementById("password-pulldown").value="password";
document.getElementById("login-pulldown" ).click();
});
},
Later-on, however, I try to execute this:
function(){
console.log('Step 7');
page.evaluate(function(){
document.getElementById("content_text").value += "SomeTextIWannaAdd";
//console.log(document.documentElement.innerHTML);
document.getElementByName("button");
});
},
I get this error message:
Step 7
ERROR: TypeError: undefined is not a function (evaluating
'document.getElementByName("button")')
TRACE:
-> undefined: 3
-> : 8
phantomjs://code/EditWiki.js:48 in onError
The html element i want to get looks as follows:
<button name="button" type="submit" class="button -highlight -with-icon icon-checkmark">Save</button>
The rest of the innerHTML: https://pastebin.com/j5cCDxEU

The document object doesn't have a getElementByName method, only has getElementsByName method (plural).
Use querySelector instead to query by attribute name:
document.querySelector('[name="button"]')
To query all button tags you can use getElementsByTagName:
document.getElementsByTagName('button')
To query all buttons with a class name use getElementsByClassName:
document.getElementsByClassName('.button')
To emit a click event you can do:
document.querySelector('[name="button"]').click()
If using selectors that return an array such as getElementsByTagName or getElementsByClassName then you can grab the first one and then click:
document.getElementsByClassName('.button')[0].click()

Getting element by name is much error prone as there may be multiple 'buttons' try selecting the element by either xpath or id/class name.

Related

What is the error OpenQA.Selenium.WebDriverException : javascript error: document.getElementByName is not a function

I got a error in executing the below line of code
driver = new ChromeDriver(#"C:\Users\hp\Documents\Driver");
driver.Navigate().GoToUrl("http://demo.guru99.com/v3/");
IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
js.ExecuteScript("document.getElementByName('uid').value ='mngr303517'");
js.ExecuteScript("document.getElementByName('password').value='ujudysY'");
js.ExecuteScript("document.getElementByName('btnLogin').click()");
I got the error At line 3
document.getElementByName is not a function (Session info: chrome=87.0.4280.141)
what is the reason for it?
The JavaScript method is document.getElementsByName(...) (plural - Elements not Element).
This method returns a collection of elements, not a single element.
js.ExecuteScript("document.getElementsByName('uid')[0].value ='mngr303517'");
Be sure to access the [0] index of the collection before calling the value property.
It might be a little cleaner to use document.querySelector instead:
js.ExecuteScript(#"document.querySelector(""[name='uid']"").value ='mngr303517'");
js.ExecuteScript(#"document.querySelector(""[name='password']"").value='ujudysY'");
js.ExecuteScript(#"document.querySelector(""[name='btnLogin']"").click()");

Validate dynamic input form elements using Validator Plugin Jquery

I am using this http://jqueryvalidation.org/ jquery validation plugin.
HTML dynamic form will be like this
<form name="baby_book" id="baby_book">
<input name="form_elements[16]" id="form_elements[16]">
<input name="form_elements[17]" id="form_elements[17]">
<input name="form_elements[18]" id="form_elements[18]">
<a class="myfont baby_book_save" href="javascript:void(0)" onclick="validatefilesizeform('save')" >Save</a>
</form>
My JS Code will be like this
<script type="text/javascript">
var validator="";
$(document).ready(function(){
var max_length_rules= <?php echo json_encode($valid_rules); ?>;
validator=$("#baby_book").validate();
$.each(max_length_rules,function(k,v){
$.each(v, function(key, value){
$('input[id="'+key+'"]').rules('add',"required");
});
});
});
function validatefilesizeform(type)
{
if(type == 'save')
{
document.baby_book.sec_submit.value="save";
if(validator.form())
{
document.baby_book.submit();
}
}
</script>
While applying dynamic rules like that it doesn't validate the form.
In console it displays this error
Uncaught TypeError: Cannot read property 'form' of undefined
Can anyone help me how to add dyanmic rules . Thanks.
That's because when the browser finds the validatefilesizeform('save') in the onclick attribute, it evaluates that expression, i.e runs the function. With this syntax you're asigning the result of that evaluation to the onclick event, which is not what you want.
The Cannot read property 'form' of undefined error happens because in that moment the $(document).ready() callback has not yet been executed, and, when the function tries to execute validator.form(), that variable is already undefined. It will be initialized later, inside the $(document).ready().
To get the expected behavior, and avoid the error, you must change the onclick handler to this one:
`onclick="function() { validatefilesizeform('save') }"`
In this case you're registering a function as the value for the onclick attribute. And this function will be evaluated when the control is clicked.
To make it even more clear:
// This is the value returned by the function evaluation:
validatefilesizeform('save')
// This is a function
function() { validatefilesizeform('save'); }
So the second is a function that can be evaluated. The first one evaluates the function. Handlers should always be functions, and not values.

Trying to test whether element has attribute without directly assessing the element

Trying to create query object on clicks on various buttons by sending attributes on html called "attr-{{foo}}" which get their name from an ng-repeat or some other means. I wanted on controller that first tests if the element has all attributes that map onto the keys of the query object in the scope, and continue this if else chain down to having only one attribute; however, when I tried this, I would get the error "cannot find .value of 'null'", as I was testing with
(below you will find a snippet that is representative of my controller)
vm.openFoos = function (event) {
if (event.target.attributes.getNamedItem('attr-foo').value &&
!event.target.attributes.getNamedItem('attr-bar').value) {
var obj = {
foo: event.currentTarget.attributes.getNamedItem('attr-foo').value,
name: $routeParams.name
} else if {
(event.target.attributes.getNamedItem('attr-foo').value &&
event.target.attributes.getNamedItem('attr-bar').value) {
var obj = {
foo: event.currentTarget.attributes.getNamedItem('attr-foo').value,
name: $routeParams.name,
bar: event.currentTarget.attributes.getNamedItem('attr-bar').value
}
}
data.getReviews(obj)
.success(function (data){$log.debug(data)}).error(function(e){$log.debug(e)});
};
This works if I click on elements with both attr-foo and attr-bar (as by the convention of this testing from most strict case of having attributes to least, I know if I had written the if statements in reverse I would get the error "cannot find value of null". Sample HTML:
<span class="one" ng-click="vm.openFoos($event) attr-foo="foooo">Click FOOO</span>
<span class="two" ng-click="vm.openFoos($event) attr-foo="fo" attr-bar="bar">Click FOO BAR</span>
Clicking span.one throws the error "cannot find value of null" but clicking span.two works fine.
I do not want to write a controller for each instance of the combinations of keys in my query appearing on various html attributes; however, I'm getting this error.
instead of using
if (event.currentTarget.attributes.getNamedItem('attr-thing').value ....
use
if (event.currentTarget.attributes.getNamedItem('attr-thing') ....
When
event.currentTarget.attributes.getNamedItem('attr-thing')
does not exist, obviously one cannot take the value of it!
Could you be looking for hasOwnProperty?
object.hasOwnProperty("attrname"); // Yields true or false.

Uncaught TypeError: Cannot read property 'ownerDocument' of undefined

I'm teaching myself AJAX to AJAXify my site. In my template, I have the following JS code to get some JSON data from a view then append the data to a div.
function filter(type) {
$.getJSON(
'/activity_stream/global-activity-stream/',
{xhr: "true", filter: type},
function(data) {
$('.mainContent').children().remove();
$(data).appendTo('.mainContent');
});
}
$(".btn").click(function () {
filter("recent");
});
}
I think my view is returning proper JSON but now data is not being added to the .mainContent div.
It gives this error:
Uncaught TypeError: Cannot read property 'ownerDocument' of undefined.
Make sure you're passing a selector to jQuery, not some form of data:
$( '.my-selector' )
not:
$( [ 'my-data' ] )
I had a similar issue.
I was using jQuery.map but I forgot to use jQuery.map(...).get() at the end to work with a normal array.
The same issue came up for me inside of $elms.each().
Because:
the function you pass to .each(Function) exposes (at least) two arguments; the first being the index and the second being the element in the current element in the list, and
because other similar looping methods give current the element in the array before the index
you may be tempted to do this:
$elms.each((item) => $(item).addClass('wrong'));
When this is what you need:
$elms.each((index, item) => $(item).addClass('wrong'));
In case you are appending to the DOM, make sure the content is compatible:
modal.find ('div.modal-body').append (content) // check content
If you use ES6 anon functions, it will conflict with $(this)
This works:
$('.dna-list').on('click', '.card', function(e) {
console.log($(this));
});
This doesn't work:
$('.dna-list').on('click', '.card', (e) => {
console.log($(this));
});
In my case, this error happened because my HTML had a trailing linebreak.
var myHtml = '<p>\
This should work.\
But does not.\
</p>\
';
jQuery('.something').append(myHtml); // this causes the error
To avoid the error, you just need to trim the HTML.
jQuery('.something').append(jQuery.trim(myHtml)); // this works

Getting 'this' object in javascript without using the word 'this'

What I am trying to do is getting the same result as clicking on this following submit button.
<input id="submit_http:" class="add_submit" type="button" onclick="return dex.forms.form_ajax_submit(this,function(res) { alert('posting failed'); },function(res) { alert('posting success'); });" value="Next" name="submit_http:">
I was trying to do it like that:
$('.NextButton').click(function () {
dex.forms.form_ajax_submit(document.getElementsByName('submit_http:'),
function(res) {
alert('posting failed');
},
function(res) {
alert('posting success');
});
});
But looks like document.getElementsByName is not returning the same result
as the submit button 'this'
How can I solve this issue?
The only actual mistake you made was using the function document.getElementsByName, because it returns an array of elements (as indicated by the plural). What you need is a single element.
Either access the first element of the array by using:
document.getElementsByName('submit_http:')[0]
or use the already recommended and more precise function:
document.getElementById('submit_http:')
document.getElementsByName('submit_http:') will return an array of elements that have that name. If you want to get your submit button, you want to use document.getElementsByName('submit_http:')[0].
While Anthony Grist is correct, in your case, since you already have an id for your input, you could do document.getElementById('submit_http:') (which returns a single element).
generally, we use a "self" variable for this. Before the submit, do that :
var self = this;
then use "self" into your callback

Categories