Remove elements from a open Webbrowser with JavaScript - javascript

I am trying to remove all the elements with the class "RemoveByMe", by executing javascript on an open browser. I previously created those elements myself.
I'm calling that javascript from Python: Selenium controls the browser, and sends the javascript to the open browser. But I think the problem relies on the javascript side, reasons on the next lines.
The python code for executing each script is:
Browser.execute_script("script here")
So far I have tried the following javascript code:
$('.RemoveByMe').remove();
This one gives the following error message:
#WebDriverException: Message: u'$ is not defined' ; Stacktrace:
at anonymous
This error seems to come from the python side, so I have tested more javascript code:
var DocElements = document.getElementsByTagName('RemoveByMe');for(var i = 0; i < DocElements.length; i++){DocElements[i].parentNode.removeChild(DocElements[0]);}
This one doesnt throw any errors (confirming that the python side is working), but still doesnt remove the elements. (javascript is not being able to remove them)
All of the tested javascript code works in some websites, but it doesnt in some others.
That makes me think that the problem resides in the website, preventing the javascript from removing elements. (Although I could successfully add them)
How could I skip that prevention?

First one obviously seems that jQuery is not defined.
The 2nd one looks close though you would need document.getElementsByClassName('RemoveByMe') ... instead of by getElementsTagName as you want to get elements by a CSS class.

$('.RemoveByMe').remove();
That snippet is jQuery Code, a Javascript Library.
A solution for your problem you can find in this thread:
Remove all elements of a certain class with JavaScript

Related

How to run on the page typed js

I'm currently working on a project which requires me to run by the user typed javascript in the form of a string.
I've tried adding an empty <script> tag to the html and appending the string (containing the users freshly typed (after the page was loaded) javascript) to this script tag but this doesn't work. (since the code inside the script tag will be run immediately after the page is loaded).
So I tried a different approach. I wrapped the js string inside of a function like so:
function runCode() { userString }
This is what the string I now append to the empty script tag looks like:
var code = "function runCode() { "+ userString +" }"
However this still doesn't work. The code (userString) shows up in the script tag according to the chrome dev tools, but trying to run the function causes the following error:
Uncaught ReferenceError: runCode is not defined
Does somebody know how this works? What is the proper way for me to do this?
Some background:
The project I'm working on is an online tool to draw using js. The goal here is to use the two.js library and link it to a modified textarea. (codemirror) Clicking the button will take your typed in code and use it to modify the two.js canvas on the other half of the screen.
This will make it easier to draw using the library, since you don't have to set up all the html, css and js files yourself, but instead you can focus on the code.
Note: The js you type into the textarea can by any valid js, so simple things as alerts, or even jQuery lines will work just fine.
Use eval() function.
However be aware that this is by design a HUGE hole of security.
You have to use eval(). Extract the user input from an onclick event and pass it into eval like so:
eval(userString)

Jquery image bookmarklet not working in Django

Im working through Django By Example and in one chapter a Jquery bookmarklet is built within a Django app so that a user can easily save jpg images from a website into their user profile area within the Django app.
Im not an experienced JS or Jquery programmer but I did some JS some years back and can read the code however the tutorial does give exact instructions on what to do which I have followed and although I have managed to get the bookmarklet button to appear in my bookmarks bar in Chrome, nothing happens when I click it when browsing a webpage with jpg images.
This is my local Django dashboard where the bookmarklet button is added to the bookmarks bar and this part works fine
and this is what it should look like when clicked on, this is the part where nothing happens for me
these are the relevant js files
https://github.com/davejonesbkk/bookmarks/blob/master/images/templates/bookmarklet_launcher.js
https://github.com/davejonesbkk/bookmarks/blob/master/images/static/js/bookmarklet.js
the only thing I can see that is different with these compared to the files that came with the book is the indentation is a bit off but for some reason the indentation does seem to have changed a bit when I uploaded to Git and they dont look like that locally. Is indentation important in JS?
I followed the same book with the same examples but didn't had any trouble. Make sure your dashboard.html file is referring to the correct javascript file. If nothing works try to add the bookmark manually, you can see how that's done over here http://www.howtogeek.com/189358/beginner-geek-how-to-use-bookmarklets-on-any-device/ it'll sure to work.
And answer to your last question, Indentation is not as important in JavaScript as it's in Python, as python doesn't use any curly braces "{}" or semi-colons ";". But you can write your entire javascript code in a single line and it'll work because your using curly braces everywhere to tell which line of code ends where.
I agree with all the above. In addition, the following:
Error I noticed in the book:
In bookmarklet-launcher.js the js function being called from bookmarklet.js is called myBookmarklet(), however there is no function called this way in bookmarklet.js. So, you may want to use the same name in both js files.
Practically speaking however, the bookmarklet will always work because, not finding a myBookmarklet function in memory, bookmarklet-launcher.js appends the bookmarklet.js script to the body element and, being bookmarklet.js a self-invoking function, its content executed (without the need it to being called). There are some additional interesting technicalities here (the key function in bookmarklet.js is not self invoking but it will anyway be always called because of the script checking whether jQuery is present...) but ok, this is more relevant for those busy with the mentioned book (Django 2 by example).
Check whether bookmarkled, once you click on it, is added to the
current webpage:
2.1. Open devtools (F12 on Chrome) and check e.g. in the html head element whether you find the newly added link element containing the css attribute and/or in the body element whether you find the script element containing the reference to the bookmarklet.js file.
2.2. Alternative: Add an alert message on top of the bookmarklet.js script so that it will be launched if it is correctly loaded. Example:
(function(){
alert('bookmarkled loaded!');
var jquery_version =...
Make sure you're trying to use it on a HTTP site only. Since you're serving from same protocol. HTTPS site would always tell say: There is a problem loadingbyour jquery. That's how I solved mine.
dude.I have solved the problems I met like you.
The most important thing is that noticing the syntax error(without warnings),mainly caused by ignoring blank.
for example, in the line:
jQuery('#bookmarklet .images').append('<img src="'+image_url+'"/>');
between #bookmarklet and .images should lie a blank space,because of jquery syntax rules(meaning to search tag with id of bookmarklet and search tag with class equaling images within result previously).
Another two places worth notice are codes containing #bookmarklet .images a and #bookmarklet #close,requiring blank spaces between filter condition.
That's where I found I made mistaks mainly after studying syntax of jquery.
You'd better compare your codes with codes already loaded up to github by someone to make sure there are no more little errors(such as spelling).

Selenium + PhantomJS in Python 2.7, file upload

I've been struggling with this function for a few hours now and I can't get it to work in any way shape or form.
Assume my element location and image path are correct at all times. (Seriously, I've been going over this for the past 4 hours, it's not the element location and it's not the file path.)
What I started with was a sendkeys to the input element. This gave no error but caused the script to hang for ever; it wouldn't get past it and no images were being uploaded.
I literally tried every single possible variation of the sendkeys method listed on the first 4 pages of Google when looking for "Python PhanthomJS Selenium upload file sendkeys". Back to the drawing board.
Currently I am looking into executing a bit of JavaScript through Python to upload the file, though I have no idea how to go about this.
The page which I am trying to upload to has its form set to hidden and only shows a button which opens an upload dialog on normal browsers. I feel this is why sendkeys was not working.
Can anyone give me some input or suggestions as what to try next? Or how to execute some JavaScript from Python?
EDIT:
I learned how to execute JavaScript while using selenium in python and it saved my day.
To anyone coming here from google or whatever with the same problem, let me explain what I did:
The fact that my .send_keys() was hanging when sending keys to the input[file=input] element had me wondering before I made the topic but since the webdriver was still able to find the element I wasn't thinking too much of it and shrugged it off as something random. Later however I came with a suggestion that because it had a css type display: hidden !important the webdriver might have been able to find it, but not interact with it, and for some reason selenium just decided to hang itself instead of crashing / giving an error.
With that in mind I started browsing the docs and found the .execute_script() command, turns out we can use this to run a piece of JavaScript through the webdriver. Why I wanted this, is to see if the class styling had anything to do with it at all, how you ask? Well we can use the following line of code to change the class attribute of the input[type=file] element: document.querySelector("input").className="". This is not the most elegant solution since we are basically deleting the entire class responsible for the display: hidden !important styling. If the class were to hold more important data I'd suggest changing the class instead of renaming it to "" or deleting.
Moving on and trying it out, it showed the input button just like I hoped it would! After this I simply re-tried sending the keys and found no problems at all. There is no need for a click, submit or anything. driver.find_element_by_css_selector('input[type=file]').send_keys('path/to/file') However I did note that the way you structure the path seems to be pretty important. For example I am testing on windows and path/to/file did not upload or select any image for me, using path\\to\\file however, worked completely fine.
tldr:
driver.execute_script('document.querySelector("input")').className=""
followed by:
driver.find_element_by_css_selector('input[type=file]').send_keys('path/to/file')
Is what worked for me, and if you are in any alike situation your
variation on the script should upload the image as intended.

Replacing or removing javascript

I have some HTML and javascipt that is generated automatically through a URL. This html and javascipt is generated using Smarty templates. Unfortunately, this code that is generated uses a bunch of jQuery, but the references to the jQuery libraries aren't included in the code and so generate errors. I can't change this. Below is an example of the first part of that javascript that generates the error 'Uncaught Reference Error: cj is not defined'
<script type="text/javascript">
cj( function() {
var element_date = "#birth_date_display";var element_time = "#birth_date_time";var time_format = cj( element_time ).attr('timeFormat');
cj(element_time).timeEntry({ show24Hours : time_format, spinnerImage: '' });
var currentYear = new Date().getFullYear();var alt_field = '#birth_date';cj( alt_field ).hide();var date_format = cj( alt_field ).attr('format');var altDateFormat = 'mm/dd/yy';
switch ( date_format ) {
case 'dd-mm':
case 'mm/dd':
altDateFormat = 'mm/dd';
break;
}
What I can do though, is add code onto the end of the file. So I am able to load the relevant libraries and simply enter the same javascript code again, and it works fine.
The problem I am running into is that I am trying to do some styling of the page using jQuery also after the fact. The line below is giving me the problem. Everything gets wrapped fine, but my javascript file just exits on this row,
$("#editrow-email-Primary, #editrow-phone-1-1, #editrow-birth_date").wrapAll("<div class='grid-group personal' />");
again with the same error 'Uncaught reference error: cj is not defined. It is the editrow-birth_date div that most of the previous javascript is for as it uses the jQuery UI datepicker. The funny thing is, simply appending the same javascript and jQuery at the end of the file works fine, until I just to .wrapAll. Then it seems to be trying to run something again in the original javascript and generating a new error and exiting.
I'm completely stuck here, and I don't even know how to properly explain what I think is going on. Is there a way that I can remove the original javascript from the code on the fly so that it can't be executed anymore? I don't think so, but I am hoping so as I feel like that would solve my problem.
Wrap pulls all of that HTML out of the page and sticks it in HTML built from the param for wrapAll and then you stick the whole bundle back on the page which means you're slapping that same script file back onto the page I assume. Any time a script tag is dropped into a page, all of its JS executes. Now I'm going to edit and make some other suggestions when I've figured wtf is going on with this app but that's your problem with the bonus firing.
Additional:
Okay, so I don't know what Smarty is. Whenever I see a Smarty-related question, something horrifying is going on so I don't even want to know. If you have any control over the app in general, you should be able to add Script tags before jQuery happens. Ideally before this tag gets appended. At the very least, add an empty function called cj before this happens to avoid the errors and then figure where the real cj is so you can plug it back in.
But regardless, if you don't have control of at least most of the HTML, get a stick and hit somebody with it until they promise to stop making horrifying technology choices and restore control of the HTML to you, the guy who is supposed to be working with the damned HTML and JavaScript to get things running.
Or show them this. I've been at this six years now. These kinds of problems should not be allowed to happen. Technology that robs us of control of our own app gets crumpled up like a paper ball and tossed over your shoulder because you will never get that time back.

How to use page-mod to modify element loaded by JavaScript

I'm creating firefox addon to add onclick event to the specific button. ("input" element)
The button is placed in http://example.com/welcome#_pg=compose
but when I open the page, following error occures:
TypeError: document.querySelector("#send_top") is null
#send_top is id of the button which I want to modify. So, the button is not found.
This error occurs because http://example.com/welcome and http://example.com/welcome#_pg=compose is completely different pages.
In this case, the addon seems loading http://example.com/welcome but there is no button whose '#send_top' ID.
When #_pg=compose anchor is added, the button is loaded by JavaScript.
How can I load http://example.com/welcome#_pg=compose to modify the button?
Three thoughts to help you debug this:
to correctly match the url you should consider using a regular expression instead of the page-match syntax - this might allow you to react to the anchors in a more predictable way
I've found that when using content scripts with pages that are heavily modified by JS, you can run into timing issues. A hacky workaround might be to look for the element you want and, if it isn' there, do a setTimeout for a 100 milliseconds or so and then re-check. Ugly, yes, but it worked for some example code I used with the new twitter UI, for example.
You can use the unsafeWindow variable in your content script to directly access the page's window object - this object will contain any changes JS has made to the page and is not proxied. You should use unsafeWindow with great caution however as its use represent a possible security problem. In particular, you should never trust any data coming from unsafeWindow, ever.

Categories

Resources