QWebElement evaluateJavaScript this.click() method don't work - javascript

I have the HTML form in QWebView loaded. This HTML has following two elements:
<button class="submit1" tabindex="1" type="submit" id="submit1">accept</button>
<button class="submit2" tabindex="2" type="submit" id="submit2">decline</button>
In code I have follwing:
QWebView webView;
...
QWebElement button = webView->page()->mainFrame()->documentElement().findFirst("button[id=\"submit1\"]");
button.evaluateJavaScript("this.click();");
And this last line of code don't work for me.
Moreover if I have an element instead of button - JavaScript click() method works fine.

I can't answer the question per-say as its really hard to tell from the info you gave us what is the EXACT problem, but what I can do is give you some guidelines on debugging problems in QWebView.
1) First thing I would check, is if you actually have the button element in hand. try to do this:
QWebView webView;
...
QWebElement button = webView->page()....findFirst("button[id=\"submit1\"]");
if button is not None:
button.evaluateJavaScript("this.click();");
else:
print "Oh dear!"
By this we wanna see if findFirst() actually gets the elements (I believe it does, syntax seems to be fine).
2) Go to the web page you're working on. Does that button actually work? some script might inject a 'disabled' attribute to it, which renders it un-clickable.
3) Try to lock in on the element in some different way:
get it by class:
QWebElement button = webView->page()->mainFrame()->documentElement().findFirst("button[class=submit1]");
Try to lock in on the parent, then get the 1st child:
QWebElement parent = **get the parent element**
button = parent.findAll("button")[0]
Usually I try to avoid using methods like this one, as it is susceptible to crashing in several cases. If this is the only thing working for you, I strongly recommend some 'try\except' to avoid any problems.
small note: you said that if u get an element instead of a button, click() works fine. the reason is that click() does nothing to an
element that isn't clickable or has some kind of behavior attached to
the click() event. So its working by basically doing nothing :)

Related

JS code linked to a "close" button on a modal popup

Unfortunately I cannot post a working code/example because it's part of a huge HTML template and I cannot extract only the interesting part :( sorry for that.
Anyway, I have this popup that I define like this:
<a id='bookShopping' class="popup-text" href="#book-shopping-dialog"></a>
<div id="book-shopping-dialog" class="mfp-dialog mfp-hide">
random popup text...
<button>Close the popup!!!</button>
</div>
and that I call with
<a onclick="document.getElementById('bookShopping').click(); return false;" >PopUp!</a>
The popup itself has a "X" close button on the upper right corner, defined with
<button class="mfp-close">X</button>
I want MY BUTTON, inside the "random text", to be able to close the popup as well.
I tried:
1) Give my button the mfp-close class.
NOPE. My button will jump to the upper right corner
2) Setting the div to display:none and/or display:block
NOPE. The popup will close but IT WILL NEVER REAPPEAR.
So, my last resort would be to call the same code that the "mfp-close" class is calling. My problem is that I can only find the mfp-close class defined in CSS, nothing in JS.
If I try to "inspect" the "X" button, it will not give me any event linked to it, nor any JS associated with its "click".
I know that without the source code is hard to understand, but the general question is: where, in Chrome or Firefox, can I find ALL THE JS CODE EXECUTED when I click on an element?
Thank you in advance.
You appear to be using the Magnific popup jQuery plugin, which has an API including a close() method. You should call that method rather than try to hack around with classes.
http://dimsemenov.com/plugins/magnific-popup/documentation.html
$.magnificPopup.close();

selenium click not working on element with onclick="" and bound event listener

I am using Selenium driver to automatically display webpages from StackOverflow. I want all the comments to be displayed in the browser, so I have code to find the elements at the bottom of the comments lists that are like this:
<a class="js-show-link comments-link " title="expand to show all comments on this post" href="#" onclick="">show <b>7</b> more comments</a>
Once I locate this element, I try a .click() method on it, but nothing happens until about the third click.
(One more thing: after I posted the question, I realize that the .click() method works if I employ it after I manually click on the link, and I reload the page. This is strange. Maybe the page needs to be in the cache?)
This used to work fine a few months ago, but now there is an event listener (a little dark icon with the letters "ev" in it) right next to this element, and the onclick attribute is an empty string.
Would the event listening bind affect the behavior of .click()? Is there a solution? Thanks.
I am using selenium in Python 2.7. Here is my code:
link = u'http://stackoverflow.com/questions/549/the-definitive-guide-to-form-based-website-authentication'
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
firefox_capabilities = DesiredCapabilities.FIREFOX
firefox_capabilities['marionette'] = True
driver = webdriver.Firefox(capabilities=firefox_capabilities)
driver.get(link)
myelement = driver.find_element_by_css_selector('[title="expand to show all comments on this post"]')
myelement.click()

onClick / onclick does not seem to be working as expected in HTML5 / JavaScript

I'm trying to do something very simple - call a function when a button is clicked. I've looked at several examples online, such as W3Schools and (I believe) I am using onclick / onClick correctly it does not seem to be functioning. I have tried several different methods - I'm really not sure what I'm doing wrong.
Method 1
HTML
<button id="buttonAdd" onclick="add()">Add</button>
JavaScript
function add() {
console.log("Test");
}
Result:
Test
When the button is clicked this flashes up in the console.log faster than I can easily see and then disappears.
Method 2
HTML
<button id="add">Add</button>
JavaScript
window.onload = function() {
document.getElementById("add").onclick = add;
}
function add() {
console.log("Test");
}
Result
Test
When the button is clicked this flashes up in the console.log faster than I can easily see and then disappears.
Method 3
HTML
<button id="add">Add</button>
JavaScript
window.onload = function() {
document.getElementById("add").onclick = add();
}
function add() {
console.log("Test");
}
Result
Test
This appears in the console log and remains there, without the button having been clicked.
Issue
I'm generally feeling confused. From what I can tell I am doing what is suggested by examples (the different methods I have tried reflect differences in examples).
Thanks.
Edit
So it seems the issue is the console.log flashing up almost faster than I can see... Does anyone have any idea why this might be? It seems like the page is refreshing itself, but I have no idea why this would be...
Answer
The button was in a form which caused the page to refresh when it was clicked.
the problem is the name of your function. it is the same as the id of the element. do a test an try writing this console.log(add). You will see it logs the DOM node and not the function.
is your button in a form ? because if so, then the form is submited and that's why the the page refreshes. can you post a jsfiddle with your test ?
Regarding Method 1:
I would need to see a bit more of your html structure to say for sure, but it sounds like in Method 1, the function isn't being declared properly in a way that is in scope. That might have to do with the names being the same, as theBrain mentioned or it might caused by some other problem.
Edit: From your response to theBrain, it sounds like you are able to get method 1 to work if you use different names. Given that, you can also prevent the page post by changing the onclick to include a return false value. Either of the following will work:
<button id="buttonAdd" onclick="add(); return false;">Add</button>
or
<button id="buttonAdd" onclick="return add();">Add</button>
coupled with the addition of return false; as the last line of your add() function's code.
Regarding Method 2:
In either case, method 2 is a better way of implementing this, so we can sort of ignore the reasons behind method 1 failing (though having distinctly different names for the function vs the button element would certainly be a good practice; personally, I preface all of my button ids with 'btn_').
The likely reason for the super-fast clearing of the console in both methods is that you do not have a type declared for the button. Different browsers do things differently in the absence of a type (see the tip on the W3Schools Button Tag), and it sounds like yours is treating this as a submit button, which means that it posts back to the page when clicked. You should be able to prevent this behavior by specifying type='button' within the attributes of the button element.
Regarding Method 3:
Finally, method 3 is providing the behavior that it is because your assignment statement is also executing a call to the add() function.
When the button is clicked this flashes up in the console.log faster than I can easily see and then disappears.
This is suspicious – console output is normally not cleared without user interaction.
Could it be that your page just gets reloaded – and therefor the console output “disappears”?
In general, you should not use this kind of “old-school” event handling any more anyway (unless it is for something really small-scale).
Have a look at popuplar JS libraries like jQuery etc. – they simplify event handling (amongst other things) at lot.
Mine was a little different, though I got help from #TheBrain's answer. Name of my javascript method was submit(), which was actually submitting my form. When I changed name of method to submitForm(), it worked.
I think earlier submit() was internally calling Javascript Form's submit() and not my javascript method.
Corrections invited.

Inline Editing But Instance Doesn't Exist

I have my own custom non-jQuery ajax which I use for programming web applications. I recently ran into problems with IE9 using TinyMCE, so am trying to switch to CKeditor
The editable text is being wrapped in a div, like so:
<div id='content'>
<div id='editable' contenteditable='true'>
page of inline text filled with ajax when links throughout the site are clicked
</div>
</div>
When I try to getData on the editable content using the examples in the documentation, I get an error.
I do this:
CKEDITOR.instances.editable.getData();
And get this:
Uncaught TypeError: Cannot call method 'getData' of undefined
So I figure that it doesn't know where the editor is in the dom... I've tried working through all editors to get the editor name, but that doesn't work-- no name appears to be found.
I've tried this:
for(var i in CKEDITOR.instances) {
alert(CKEDITOR.instances[i].name);
}
The alert is just blank-- so there's no name associated with it apparently.
I should also mention, that despite my best efforts, I cannot seem to get the editable text to have a menu appear above it like it does in the Massive Inline Editing Example
Thanks for any assistance you can bring.
Jason Silver
UPDATE:
I'm showing off my lack of knowledge here, but I had never come across "contenteditable='true'" before, so thought that because I was able to type inline, therefore the editor was instantiated somehow... but now I'm wondering if the editor is even being applied to my div.
UPDATE 2:
When the page is loaded and the script is initially called, the div does not exist. The editable div is sent into the DOM using AJAX. #Zee left a comment below that made me wonder if there is some other command that should be called in order to apply the editor to that div, so I created a button in the page with the following onclick as a way to test this approach: (adapted from the ajax example)
var editor,html='';config = {};editor=CKEDITOR.appendTo('editable',config, html );
That gives the following error in Chrome:
> Uncaught TypeError: Cannot call method 'equals' of undefined
> + CKEDITOR.tools.extend.getEditor ckeditor.js:101
> b ckeditor.js:252
> CKEDITOR.appendTo ckeditor.js:257
> onclick www.pediatricjunction.com:410
Am I headed in the right direction? Is there another way to programmatically tell CKEditor to apply the editor to a div?
UPDATE 3:
Thanks to #Reinmar I had something new to try. The most obvious way for me to test to see if this was the solution was to put a button above the content editable div that called CKEDITOR.inlineAll() and inline('editable') respectively:
<input type='button' onclick=\"CKEDITOR.inlineAll();\" value='InlineAll'/>
<input type='button' onclick=\"CKEDITOR.inline('editable');\" value='Inline'/>
<input type='button' onclick=\"var editor = CKEDITOR.inline( document.getElementById( 'editable' ) );\" value='getElementById'/>
This returned the same type of error in Chrome for all three buttons, namely:
Uncaught TypeError: Cannot call method 'equals' of undefined ckeditor.js:101
+ CKEDITOR.tools.extend.getEditor ckeditor.js:101
CKEDITOR.inline ckeditor.js:249
CKEDITOR.inlineAll ckeditor.js:250
onclick
UPDATE 4:
Upon further fiddling, I've tracked down the problem being related to json2007.js, which is a script I use which works with Real Simple History (RSH.js). These scripts have the purpose of tracking ajax history, so as I move forward and back through the browser, the AJAX page views is not lost.
Here's the fiddle page: http://jsfiddle.net/jasonsilver/3CqPv/2/
When you want to initialize inline editor there are two ways:
If element which is editable (has contenteditable attribute) exists when page is loaded CKEditor will automatically initialize an instance for it. Its name will be taken from that element's id or it will be editor<number>. You can find editors initialized automatically on this sample.
If this element is created dynamically, then you need to initialize editor on your own.
E.g. after appending <div id="editor" contenteditable="true">X</div> to the document you should call:
CKEDITOR.inline( 'editor' )
or
CKEDITOR.inlineAll()
See docs and docs.
You can find editor initialized this way on this sample.
The appendTo method has different use. You can initialize themed (not inline) editor inside specified element. This method also accepts data of editor (as 3rd arg), when all other methods (CKEDITOR.inline, CKEDITOR.replace, CKEDITOR.inlineAll) take data from the element they are replacing/using.
Update
I checked that libraries you use together with CKEditor are poorly written and cause errors you mentioned. Remove json2007.js and rsh.js and CKEditor works fine.
OK, so I have tracked down the problem.
The library I was using for tracking Ajax history and remembering commands for the back button, called Real Simple History, was using a script called json2007 which was intrusive and extended native prototypes to the point where things broke.
RSH.js is kind of old, and I wasn't using it to it's full potential anyway, so my final solution was to rewrite the essential code I needed for that, namely, a listener that watched for anchor (hash) changes in the URL, then parsed those changes and resubmitted the ajax command.
var current_hash = window.location.hash;
function check_hash() {
if ( window.location.hash != current_hash ) {
current_hash = window.location.hash;
refreshAjax();
}
}
hashCheck = setInterval( "check_hash()", 50 );
'refreshAjax()' was an existing function anyway, so this is actually a more elegant solution than I was using with Real Simple History.
After stripping out the json2007.js script, everything else just worked, and CKEditor is beautiful.
Thanks so much for your help, #Reinmar... I appreciate your patience and effort.

Removing data attributes from HTML using jQuery

Can't seem to get this one to work...
I have a page that hides certain links. When the DOM is loaded, I'm using jQuery to toggle some of those elements. This is driven by using a data attribute like so:
<div class="d_btn" data-usr='48'>
<div class="hidden_button">
Then, I have the code:
$.each($(".d_btn"), function() {
var btn = $(this).data('usr');
if ( btn == '48' ){
$(this).children('.hidden_button').toggle();
}
The above all works as planned. The problem is that I am trying to remove the data-usr from the class .d_btn once the if statement is evaluated. I've tried the following and nothing works (i.e., after the page is loaded, the source still shows the data-usr attribute:
$(this).removeAttr("data-usr");
$(this).removeData("usr");
I've been working on this for a couple of hours now and...nothing! Help is greatly appreciated!
UPDATE
I've tried the great suggestions of setting the data attribute to an empty string but I'm still not getting the desired result.
To explain a little further, The reason I'm trying to remove the attribute is so when an ajax response adds another item to the page, the previously added items would already have the button either shown or hidden. Upon AJAX response, I'm calling the same function once the DOM is loaded.
Currently, when something is added via AJAX, it toggles all the buttons (showing the ones that were hidden and vice versa.) Ugh...
I'm also fully willing to try alternatives to my approach. Thanks!
UPDATE
Well, the light bulb just flashed and I am able to do what I want to do by just using .show() instead of .toggle()
Anyway, I'd still like to find an answer to this question because the page will be potentially checking hundreds of items whenever something is added - this seems horribly inefficient (even for a computer, hahaha.)
Why don't you set the value to a random value or empty variable instead if removeAttr does not work..
$(this).attr("data-usr" , '');
$(this).prop("data-usr" , '');
Changing the DOM doesn't affect the source. It affects the DOM, which you can view with the Inspector/Developer Tools. Right click => View Source will give you the original source of the page, not the actual current source as modified by JavaScript.
Set it to a blank string:
$(this).attr("data-usr", "");
I second what Kolink said: check the DOM, not the source. (Chrome: Ctrl + Shift + i).
As others have stated. Checking the source will only show the original unedited source for the webpage. What you need to do is check the DOM using developer tools.
I've just checked everything in Chrome's inspector on jsfiddle here and the attribute is definitely being removed as well as the data.

Categories

Resources