Execute script after clicking in field

Hi, I have this script that extracts the year 2010 from field “Titolo” to field “Prima data” of this page. It woks fine, I simply would like it to be executed after clicking in field “Prima data” (I think with an addEventListener), could you help me, please? Thank you!

I tried adding this addEventListener, but it isn’t working:

// loading text
const titoloText = document.querySelector('#dsArea0').textContent;
console.log("Text:", titoloText)

// extract the year
const year = findYear(titoloText);
console.log("year:", year); // verify

// populate the year.
const primaData = document.querySelector('input[name="annoPbb1"]');
primaData.value = year;
console.log(primaData.value); // verify

// extraction function
function findYear(str) {
  const strArray = str.split(" ");
  for (let i = 0; i < strArray.length; i++) {
    const currentElement = strArray[i];
    if (currentElement.includes(".")) {
      const yearPoint = currentElement.split(".");
      const year = yearPoint[0];
      if (year > 1800) {
        console.log("Found:", year); // set the year to what you need
        return year;
      }
    }
  }
}

// attach the event listener to the click event of the primaData input field
primaData.addEventListener('click', findYear(str));

In the code you posted primaData is out of scope for the event listener.

Try it like this:

function populateYear() {
  ...
}

function findYear(str) {
  ...
}

const primaData = document.querySelector('input[name="annoPbb1"]');
const str = // something
primaData.addEventListener('click', findYear(str));

Does that make a difference?

Thanks, I tried your suggestion, but field “Prima Data” isn’t populated:

function populateYear() {
  // loading text
  const titoloText = document.querySelector('#dsArea0').textContent;
  console.log("Text:", titoloText);

  // extract the year
  const year = findYear(titoloText);
  console.log("year:", year); // verify

  // populate the year.
  const primaData = document.querySelector('input[name="annoPbb1"]');
  primaData.value = year;
  console.log(primaData.value); // verify
}

// extraction function
function findYear(str) {
  const strArray = str.split(" ");
  for (let i = 0; i < strArray.length; i++) {
    const currentElement = strArray[i];
    if (currentElement.includes(".")) {
      const yearPoint = currentElement.split(".");
      const year = yearPoint[0];
      if (year > 1800) {
        console.log("Found:", year); // set the year to what you need
        return year;
      }
    }
  }
}

const primaData = document.querySelector('input[name="annoPbb1"]');
const str = primaData.addEventListener('click', findYear);

Approaching this slightly differently, could you maybe explain a bit more about what you are trying to achieve?

You have a “Titolo” field and that contains “*Leopardi / Pietro Citati. - Milano : Mondadori, 2010. - 436 p. ; 23 cm”

When you click in the “Prima data” field then it should remove the 2010 from the “Titolo” field and insert it into the “Prima data” field.

Did I get that right so far?

Almost correct. After clicking in “Prima data” field the script should copy 2010 from “Titolo” field and insert it into the “Prima data” field, without removing 2010 from “Titolo” field.

You suggested to add after two functions:

const primaData = document.querySelector('input[name="annoPbb1"]');
const str = // something
primaData.addEventListener('click', findYear(str));

Do you mean this (if so it’s not working)?

const primaData = document.querySelector('input[name="annoPbb1"]');
const str = primaData.addEventListener('click', findYear(str));

Thanks again!

Ok, so expanding on that, would it be correct to say that we need to copy whatever year is in the Titolo field to the Prima data field, the first time we click on the Prima data field?

In the example you posted that would obviously be 2010, but I’m assuming that this is only one record and that you have different records with different years.

Did I get that right? If so, can you give a couple more examples of what you might expect to find in the Titolo field for other records. Will there only ever be one year?

Nope. the str parameter needs to be set in the same scope as the event listener, otherwise it will be null and you don’t need to pass it to the function.

Ok, got it. This will work:

(function() {
  'use strict';

  function findYear(str) { ... }

  const titoloText = document.querySelector('#dsArea0').textContent;
  const primaData = document.querySelector('input[name="annoPbb1"]');
  const year = findYear(titoloText);

  primaData.addEventListener('click', function() {
    this.value = year;
    console.log('Yeah, baby!');
  }, { once: true });
})();

I added a console log so that you can see that the event listener only fires once.

Thanks, unfortunally I get undefined when I click in primaData field, even if I remove , { once: true }

Weird. How are you running the userscript? I am running it using Tampermonkey against the page you provided.

Here is the complete script:

// ==UserScript==
// @name         New Userscript
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  try to take over the world!
// @author       You
// @match        https://smartissimo.w3spaces.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=w3spaces.com
// @grant        none
// ==/UserScript==

(function() {
  'use strict';

  const titoloText = document.querySelector('#dsArea0').textContent;
  const primaData = document.querySelector('input[name="annoPbb1"]');
  const year = findYear(titoloText);

  primaData.addEventListener('click', function() {
    this.value = year;
    console.log("Yeah, baby!");
  }, { once: true });

  function findYear(str) {
    const strArray = str.split(" ");
    for (let i = 0; i < strArray.length; i++) {
      const currentElement = strArray[i];
      if (currentElement.includes(".")) {
        const yearPoint = currentElement.split(".");
        const year = yearPoint[0];
        if (year > 1800) {
          return year;
        }
      }
    }
  }
})();

This works for me exactly as expected, which means that something else is going on in your code.

Do you see any errors in the console?

Yes, that’s correct, the userscript (TamperMonkey or other) works for that saved page, but not for the original one (protected). I think because when the original page loads, Titolo field is still empty, then I manually type in Titolo field, and then click on primaData, where the script should be executed.
P.S. I’m getting undefined when I click in primaData field, while the console returns ‘Yeah, baby!’

Can you DM me the page you are testing against so that I can access it too?

It’s kinda hard to offer much more help if we are looking at different pages.

Can I send you a video?

Nah, it’d be better to be able to inspect the page source, look in the console etc.

If you can’t send me the creds (maybe create a throwaway guest account), then no worries, but like I said it is then a bit difficult to offer advice.

I’ll try some solutions with chatGPT and let you know if I solve, thanks very much indeed!

Ok. Good luck.

1 Like

I tried to wrap the script in a DOMContentLoaded event listener, like so:

document.addEventListener('DOMContentLoaded', function() {
  //script here
});

This should ensure that the script won’t run until the DOM has finished loading, including the element with ID “dsArea0”. Unfortunally it wasn’t the solution… :frowning:

What about trying @run-at document-end. This ensures the script will be injected when or after the DOMContentLoaded event was dispatched.

I don’t think it’ll make a difference, but might be worth a try.

Thanks again, I added @run-at document-end to TamperMonkey’s metadata, but I’m still getting undefined. :frowning:

Can you not create a temporary login for me? Or make the page available in some way shape or form?