Guide to making a simple bookmarklet that replicates the functionality of Selenium

I have experience with Selenium, Java/Python, XPaths and I am in search of a simple Javascript bookmarklet that acts as a basic framework for performing similar operations as Selenium on the current webpage. For example, (in pseudocode),

begin
document.click("//button[@class='buy']")
wait 2 seconds
document.entertext("//form[@class='name']", "John Smith")
wait 2 seconds
document.check("//radiobutton[@class='agrees']")
end

Despite numerous Google searches, I have not been able to find any resources that address this particular need.

My reason for requesting this is because I frequently fill out web forms with the same static values every day.

Answer №1

Looking for something similar? You can insert the code below into your index.html file. By clicking a "Test" button, you can replicate the scenario you described — clicking "buy," entering a name two seconds later, and then clicking "agree" another two seconds after that.

<html><head><title>test</title></head>
<body>
<button class="test" onclick="myFunction()">Test</button>
<button class="buy" onclick="unhide_form()">Click me</button>
<form id="main_form" style="display: none">
  <label for="fname">First name:</label><br>
  <input class="name" type="text" id="fname" name="fname" value="" placeholder="Your name"><br>
  <input type="radio" id="agrees" class="agrees" value="agr">
    <label for="agrees">Agrees</label>
  <input type="submit" value="Submit">
</form> 
<script>
async function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}
async function unhide_form() {
    var f = document.getElementById("main_form")
    f.style = "display: block"
}
async function myFunction() {
    document.getElementsByClassName("buy")[0].click()
    await sleep(2000)
    document.getElementsByClassName("name")[0].value = "John"
    await sleep(2000)
    document.getElementsByClassName("agrees")[0].click()
}
</script>
</body></html>

If this isn't sufficient for your specific task, please provide more details such as the site URL, the actions you're automating (fields filled, buttons clicked), and where the process is failing.


UPDATE: I understand now. While navigating JavaScript, I also gained new knowledge in the process :) Here's the code:

function submit_wayback_machine_form(url_to_save) {
    elems = document.evaluate('//*[@id="web-save-url-input"]', document, null, XPathResult.ANY_TYPE, null );
    elem = elems.iterateNext()  
    elem.value = url_to_save    
    
    elems = document.evaluate('//input[starts-with(@value, "SAVE PAGE")]', document, null, XPathResult.ANY_TYPE, null );
    elem = elems.iterateNext()
    elem.click()
}

submit_wayback_machine_form("https://google.com")

I have tested it, and it seems to be functioning correctly: https://i.sstatic.net/n4a5x.png

Additionally, here are some valuable resources I used:

  1. https://developer.mozilla.org/en-US/docs/Web/XPath/Introduction_to_using_XPath_in_JavaScript
  2. For quick testing of XPaths, I recommend the "XPath Helper" Chrome extension: https://chrome.google.com/webstore/detail/xpath-helper/hgimnogjllphhhkhlmebbmlgjoejdpjl

UPDATE 2:

Is there a shortcut in JavaScript to simulate element.click (Xpath)? Why the need for iteration and evaluation?

This is how the process works – we utilize document.evaluate(...) to execute the XPATH expression first and subsequently iterate through the results due to potential multiple matching elements.

To simplify usage slightly, perhaps consider the following functions:

// returns the first matching element
function getFirstElementByXPATH(xpath) {
    elems = document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null);
    elem = elems.iterateNext()
    return elem
}

// returns an array of all matching elements
function getAllElementsByXPATH(xpath) { 
    elems = document.evaluate(xpath, document, null, XPathResult.ANY_TYPE, null)
    results = []
    while (1) {
        elem = elems.iterateNext()
        if (elem != null) {
            results.push(elem)
        } else {
            break
        }
    }
    return results
}

Then, use them like so:

getFirstElementByXPATH("//li/div/button/span").click()
//or
getAllElementsByXPATH("//li/div/button/span")[0].click()
//or
element = getFirstElementByXPATH("//my_custom_expression_1")
element.click()
elements = getAllElementsByXPATH("//my_custom_expression_2")
elements[0].click()
elements[1].value = "abc"

Hoping this provides added convenience!

Answer №2

It typically appears like this:

(() => {
  document.querySelector('.purchase')?.click();
  setTimeout(() => someOtherFunction(), 2000);
  setTimeout(() => document.querySelector('.consents')?.click(), 4000);
})()

However, the specific function of 'some other function' remains unknown and it may fail if there is a page navigation during the process.

Answer №3

If you're tired of inputting the same static values into webforms every day, consider using the Browserflow extension/service instead of a JS bookmarklet.

With Browserflow, I was able to easily scrape data from paginated results and trigger the loading of more results with just the click of a button.

You don't need any JavaScript knowledge to use Browserflow, but you can leverage its capabilities if you want to perform more complex tasks.

Keep in mind that Browserflow is a paid service, although it does offer a limited free tier for users to try out.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Creating a Canvas Viewport Tailored for Multiplayer Gaming

Lately, I've been playing around with the HTML5 Canvas while working on an io game. However, I've hit a roadblock when it comes to handling the viewport. Setting up the viewport itself isn't too complicated, but accurately displaying other p ...

When you select the checkbox button, a textfield and submit button will appear. Once you click the submit button, the checkbox button will be disabled

<td> <input type="checkbox" ng-model="alert.acknowledged" ng-disabled="alert.acknowledged" ng-click="onacknowledgedClick(alert)"></td> <td> <span ng-if="!alert.acknowledgeInProgress">{{alert.acknowledgedComments}}</span&g ...

Making a POST request to a local node.js script

This question might be a beginner one. I'm a newcomer to the world of node.js. Currently, I am working on a script that needs to handle HTTP POST requests. As I am planning to deploy it on Heroku eventually, I wonder how can I test these POST reques ...

Using jQuery to slide elements across the page

I've been attempting to incorporate a sliding effect into my website, but I'm running into an issue where the sliding only occurs on the first click and I can't figure out why. Here is the code snippet I've been using: Html : $("#go ...

The Javascript script is malfunctioning

Is there a way to modify the code so that the second drop-down menu becomes editable when an option is selected from the first drop down menu? The second drop-down menu should remain read-only if no option is selected, and specifically if "default" is ch ...

Unlock the capability to automatically swipe on a React Native TextInput Carousel while the user types

My challenge involves setting up a carousel with either Flatlist or ScrollView (I have tested both options). This Carousel consists of multiple TextInputs. The goal is to achieve the following: There are 4 TextInputs. When the user enters 6 digits in the ...

Is it possible to adjust the maximum time limit for uploaded video files in Vue?

I'm facing an issue while trying to dynamically change the maximum value of a time input field in Vue JavaScript after uploading a video file. Despite setting the attribute `max` on the input element using JavaScript, I am unable to update the max val ...

Navigating pop up websites using Python and Selenium

While collecting data from various websites, I encountered one with a pop-up window (refer to the image below). I have attempted several approaches such as checking for an alert or accessing the driver's windows in order to switch to it and close the ...

Sharing information between functions within the same controller in AngularJS

I have been working on a project which involves the use of AngularJS and MVC. I am retrieving status details data using HTTP POST, and now I need to utilize this data in another function of my controller. Despite passing the data in a scope variable named ...

Verify if the radio element is marked as selected in the AJAX reply

My ajax response contains two radio elements and I need to check if they are checked in the response. I've tried using the code below to check the radio status but it's not working: $('#input[type=radio]').each(function(){ alert($( ...

Moving Cursor Automatically to the End Upon Rejecting Input

I have a form input where users can enter values. I need to validate the inputs to ensure they only contain numbers, dots, and commas. If the input is invalid, I want to prevent it from being stored in the input field. To achieve this, I have implemented ...

What is the best method for converting this API into a JavaScript object?

My goal is to retrieve data from this API: and store it in a JavaScript variable so that when I log the variable inside the browser console, I will see a tree structure related to the API. To better illustrate what I mean, here's an image of the desi ...

The jQuery autocomplete feature is not functioning properly when trying to separate values with commas using JavaScript and JSON

Currently, I am attempting to develop a comma-separated autocomplete text field where the autocomplete JSON data is generated directly from JavaScript. You can view my code below: The JavaScript array: var remark = [ "is under construction", "is ...

Unable to retrieve JSON data using Ajax query

My goal is to retrieve data using the World Bank's API. If you're interested in how to query their database, you can check out this helpful guide. Essentially, to access information about a specific country, you need to use the following URL: ht ...

Can you explain the variances between creating a new date object with input as "2017-01-01" and "2017-1-1" in JavaScript?

When I use new Date("2017-01-01") in the Chrome console, the output displays its hour as 8. However, when using new Date("2017-01-1") and new Date("2017-1-01"), the hour is shown as 0. This brings up the question of how new Date(dateString) actually pars ...

Evaluation of Library (VueJS) - Displaying various components in an individual test case

Just starting out with testing and have a simple question: I am working on testing a checkbox component. I understand the basics, but how can I render multiple components within one it block? Here is my current code. I am stuck on the second test where I ...

Which is better for a web automation bot in Python: Multithreading or Multiprocessing?

I have a script that continuously monitors the prices of specific products on nike.com. Once the price drops, it will automatically initiate multiple instances to log in and purchase the item from different accounts. While I already have the scraping and ...

Guidance on extracting values from an array based on the latest month in Angular

I have a list of data: var dataList = [{ "date": "2022-09-08T04:00:00.000Z", "value": "1.70", }, { "date": "2022-08-24T04:00:00.000Z", "value": "1.20", }, { "date": "2022-08-02T04:00:00.000Z", "value": "0.03", }, { ...

Retrieving data from a promise in a Node API when making a fetch call in React

Currently, I am developing a React application that interacts with a Node/Express REST API located on my local machine. The API responds with a Sequelize object via a simple res.json call, which I am accessing through a custom service. While I plan to stor ...

Accessing an array in JavaScript for a D3 Stacked Bar Chart

Currently, I am utilizing this specific version of a D3 stacked bar chart. As it stands, when a user hovers over a segment of a bar, a tooltip displays the value of that particular segment. Nevertheless, my goal is to incorporate HTML that presents a lis ...