Bookmarklet to simulate button click in a Google service iframe - javascript

The goal is to add keyboard shortcuts to Google's Google Translator Toolkit. Most functions there have keyboard shortcuts, but these two don't.
The first function is called Merge Down. It fires correctly when this bookmarklet is executed:
javascript:document.evaluate("//div[(#id='gtc-merge-arent')]/div[(#class='modal-dialog
gtc-merge')]/div[(#class='modal-dialog-buttons')]/button[(text()='OK')]", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE,
null).singleNodeValue.click();
The Apply to All function is trickier. Normally you have to click three times to execute this function:
#1 to click the button that makes visible the Repetitions dialog and sets the parameters: what to replace what with.
#2 to click 'Apply to all' and trigger the actual replacement throughout
#3 to hide the dialog element.
I don't want to mess with Google's internal code, so a normal click as if by mouse would be best.
#2 and #3 fire easily enough: same bookmarklet, with a pause:
javascript:(function(pause) {
document.evaluate("//div[(#id='fnrDialogParent')]/div[(#class='modal-dialog gtc-rep-modal-dialog')]/div[(#class='modal-dialog-buttons')]/button[(text()='Apply to all')]", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.click();
setTimeout(() => document.evaluate("//div[(#id='fnrDialogParent')]/div[(#class='modal-dialog gtc-rep-modal-dialog')]/div[(#class='modal-dialog-buttons')]/button[(text()='Exit')]", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue.click(), pause)
})(400);
I can't simulate a click on the Repetitions button, which is supposed to pop up with the two buttons I need to click to finish the job. The button itself is a div with an img inside an iframe. I tried most of the methods I found here for click simulation, the latest being this one, but it doesn't work all the same (the references are taken correctly)
var ifrm = document.querySelectorAll('iframe')[2];<br>
$(ifrm).contents().find('img.jfk-button-img.gtc-img-rep').click();
(The button itself is a div with an img inside. Depending on whether a segment repeats elsewhere or not, the button is either -enabled or -disabled. Here's the HTML code for an enabled button:
<div role="button" class="goog-inline-block jfk-button jfk-button-standard jfk-button-narrow jfk-button-collapse-left jfk-button-collapse-right jfk-button-clear-outline" tabindex="0" id="goog-gtc-repbutton" aria-label="Repeated: 3" data-tooltip="Repeated: 3" style="user-select: none;"><img src="./images/cleardot.gif" class="jfk-button-img gtc-img-rep" style="width: 21px; height: 21px;"></div>

javascript: (function() {
const a = f => new MouseEvent(f, { bubbles: !0 }),
b = f => () => document.querySelector(f).click(),
c = f => `#fnrDialogParent .gtc-rep-modal-dialog .modal-dialog-buttons button[name=${f}]`,
d = { imgSel: (f => () => {
const g = a('mousedown'),
h = a('mouseup'),
i = document.querySelector(f);
i.dispatchEvent(g), i.dispatchEvent(h) })('img.jfk-button-img.gtc-img-rep'), applyToAll: b(c('repDialogReplaceAll')), exit: b(c('repDialogExit')) };
d.imgSel(), d.applyToAll(), d.exit() })();
This is the bookmarklet that answers my question and does the 3 clicks. This answer tipped me off.

Related

HTML - Is it possible to toggle the soft keyboard from a phone device with the press of a button?

I'd like to have a very simple webpage that by pressing a button would bring the soft-input keyboard on a mobile-device to show and have the user be able to press the keys from it.
I am well aware that having a text-input like field would do the job for me but I don't want to use that. I just want to toggle it from the button press. I don't want to have an input field, I'd get the keystrokes from a global window listener
Clicking the button the first time should show it and clicking it the second it time should hide it.
I am also aware that I can do that programatically if I build a native Android App using Kotlin/Java and same goes for an iOS app using the Obj-C/Swift counterparts but in this case I am dealing with a website so only web technologies would apply: HTML5, CSS and vanilla JavaScript
I also know that I can get a similar behavior by hacking an input field inside the DOM.
/*the element is positioned absolutely so it doesnt affect the placement of other elements in the DOM*/
.kbd-hidden {
position:absolute;
top: 0;
left: 0;
opacity: 0;
}
<button onclick="toggle(this)">Click me!</button>
let fakeInput = null
let showingKeyboard=false
function makeKeyboard() {
const input = document.createElement('input', {
'type': 'text'
})
input.addEventListener('input', () => alert('Inputting!'))
document.body.appendChild(input)
input.focus()
input.classList.add('kbd-hidden')
return input
}
function destroyKeyboard(el) {
el.remove()
}
function toggle(event) {
const btn = event.target
showingKeyboard = !showingKeyboard
if(showingKeyboard) {
fakeInput = makeKeyboard()
} else {
destroyKeyboard(fakeInput)
fakeInput = null
}
}

Mapbox - Cannot trigger marker click with "element".click() after clicking on map

I've currently implemented custom markers on the map using the following code:
// extend mapboxGL class so we can edit the click function
class CustomMarker extends mapboxgl.Marker {
// new method onClick, sets _handleClick to a function you pass in
onClick(handleClick) {
this._handleClick = handleClick;
return this;
}
// the existing _onMapClick was there to trigger a popup
// but we are hijacking it to run a function we define
_onMapClick(e) {
const targetElement = e.originalEvent.target;
const element = this._element;
if (this._handleClick && (targetElement === element ||
element.contains((targetElement)))) {
this._handleClick();
}
}
};
const el1 = document.createElement('div');
el1.id = "marker1";
el1.style.marginTop = '-'+(36/2)+'px';
// make a marker and add it to the map
new CustomMarker(el1)
.onClick(() => { //when clicked, define the following function
console.log(1+1);
})
.addTo(map);
I have then added a html button to navigate between markers(i.e next and previous) which then calls something like document.getElementByID("marker1").click() once clicked.
This button works normally and triggers the marker click, however when I click on the mapbox map once (a single click anywhere on the map), document.getElementByID("marker1").click() does not seem to get called when I click the html button. If I drag the map or double click to zoom in after however, the html button starts to work again. Does anyone know why this is happening?
Something very confusing you have made. Actually MapBox Marker does not have click event, but its Element does. So to make things work, you need to use the following:
marker.getElement().addEventListener('click', function(event: PointerEvent) {
event.stopPropagation(); // to prevent map click event from triggering as well
...
});

Language Selection Tracking as an Google Analytics Event on a Website via Google Tag Manager

Our website, https://www.denverhealth.org/, has a language option via the expandable menu on the right, as seen below;
screenshot
When a user selects a language, they are redirected to a Google translated version of the site. I imagine that I should be using the Google Analytics: Universal Analytics with Event selected for the tag. But, I am a bit stuck on the best trigger option, as ideally, our team wants to see both the count and the language selection.
Below, I included HTML code that is powering this menu. Is there a way to track each time a new data-value is selected? In Google Analytics, ideally, our team would like to see Spanish instead of #googtrans(en|ES) but either way works. When I did some testing, using click text as a variable did not work, as that would result in inconsistencies as language names would show up in translated language if the user is selecting the second time. Thank you for your help!
ul class="list"><li data-value="&sc_lang=EN" class="option selected focus">English</li><li data-value="/#googtrans(en|ES)" class="option">Spanish</li><li data-value="/#googtrans(en|af)" class="option">Afrikaans</li><li data-value="/#googtrans(en|sq)" class="option">Albanian</li><li data-value="/#googtrans(en|am)" class="option">Amharic</li><li data-value="/#googtrans(en|ar)" class="option">Arabic</li><li data-value="/#googtrans(en|hy)" class="option">Armenian</li><li data-value="/#googtrans(en|az)" class="option">Azeerbaijani</li><li data-value="/#googtrans(en|eu)" class="option">Basque</li><li data-value="/#googtrans(en|be)" class="option">Belarusian</li><li data-value="/#googtrans(en|bn)" class="option">Bengali</li><li data-value="/#googtrans(en|bs)" class="option">Bosnian</li><li data-value="/#googtrans(en|bg)" class="option">Bulgarian</li><li data-value="/#googtrans(en|ca)" class="option">Catalan</li><li data-value="/#googtrans(en|ceb)" class="option">Cebuano</li><li data-value="/#googtrans(en|zh-CN)" class="option">Chinese (Simplified)</li><li data-value="/#googtrans(en|zh-TW)" class="option">Chinese (Traditional)</li><li data-value="/#googtrans(en|co)" class="option">Corsican</li><li data-value="/#googtrans(en|hr)" class="option">Croatian</li><li data-value="/#googtrans(en|cs)" class="option">Czech</li><li data-value="/#googtrans(en|da)" class="option">Danish</li><li data-value="/#googtrans(en|nl)" class="option">Dutch</li><li data-value="/#googtrans(en|eo)" class="option">Esperanto</li><li data-value="/#googtrans(en|et)" class="option">Estonian</li><li data-value="/#googtrans(en|fi)" class="option">Finnish</li><li data-value="/#googtrans(en|fr)" class="option">French</li><li data-value="/#googtrans(en|fy)" class="option">Frisian</li><li data-value="/#googtrans(en|gl)" class="option">Galician</li><li data-value="/#googtrans(en|ka)" class="option">Georgian</li><li data-value="/#googtrans(en|de)" class="option">German</li><li data-value="/#googtrans(en|el)" class="option">Greek</li><li data-value="/#googtrans(en|gu)" class="option">Gujarati</li><li data-value="/#googtrans(en|ht)" class="option">Haitian Creole</li><li data-value="/#googtrans(en|ha)" class="option">Hausa</li><li data-value="/#googtrans(en|haw)" class="option">Hawaiian</li><li data-value="/#googtrans(en|iw)" class="option">Hebrew</li><li data-value="/#googtrans(en|hi)" class="option">Hindi</li><li data-value="/#googtrans(en|hmn)" class="option">Hmong</li><li data-value="/#googtrans(en|hu)" class="option">Hungarian</li><li data-value="/#googtrans(en|is)" class="option">Icelandic</li><li data-value="/#googtrans(en|ig)" class="option">Igbo</li><li data-value="/#googtrans(en|id)" class="option">Indonesian</li><li data-value="/#googtrans(en|ga)" class="option">Irish</li><li data-value="/#googtrans(en|it)" class="option">Italian</li><li data-value="/#googtrans(en|ja)" class="option">Japanese</li><li data-value="/#googtrans(en|jw)" class="option">Javanese</li><li data-value="/#googtrans(en|kn)" class="option">Kannada</li><li data-value="/#googtrans(en|kk)" class="option">Kazakh</li><li data-value="/#googtrans(en|km)" class="option">Khmer</li><li data-value="/#googtrans(en|ko)" class="option">Korean</li><li data-value="/#googtrans(en|ku)" class="option">Kurdish</li><li data-value="/#googtrans(en|ky)" class="option">Kyrgyz</li><li data-value="/#googtrans(en|lo)" class="option">Lao</li><li data-value="/#googtrans(en|la)" class="option">Latin</li><li data-value="/#googtrans(en|lv)" class="option">Latvian</li><li data-value="/#googtrans(en|lt)" class="option">Lithuanian</li><li data-value="/#googtrans(en|lb)" class="option">Luxembourgish</li><li data-value="/#googtrans(en|mk)" class="option">Macedonian</li><li data-value="/#googtrans(en|mg)" class="option">Malagasy</li><li data-value="/#googtrans(en|ms)" class="option">Malay</li><li data-value="/#googtrans(en|ml)" class="option">Malayalam</li><li data-value="/#googtrans(en|mt)" class="option">Maltese</li><li data-value="/#googtrans(en|mi)" class="option">Maori</li><li data-value="/#googtrans(en|mr)" class="option">Marathi</li><li data-value="/#googtrans(en|mn)" class="option">Mongolian</li><li data-value="/#googtrans(en|my)" class="option">Myanmar (Burmese)</li><li data-value="/#googtrans(en|ne)" class="option">Nepali</li><li data-value="/#googtrans(en|no)" class="option">Norwegian</li><li data-value="/#googtrans(en|ny)" class="option">Nyanja (Chichewa)</li><li data-value="/#googtrans(en|ps)" class="option">Pashto</li><li data-value="/#googtrans(en|fa)" class="option">Persian</li><li data-value="/#googtrans(en|pl)" class="option">Polish</li><li data-value="/#googtrans(en|pt)" class="option">Portuguese</li><li data-value="/#googtrans(en|pa)" class="option">Punjabi</li><li data-value="/#googtrans(en|ro)" class="option">Romanian</li><li data-value="/#googtrans(en|)" class="option">Russian</li><li data-value="/#googtrans(en|sm)" class="option">Samoan</li><li data-value="/#googtrans(en|gd)" class="option">Scots Gaelic</li><li data-value="/#googtrans(en|sr)" class="option">Serbian</li><li data-value="/#googtrans(en|st)" class="option">Sesotho</li><li data-value="/#googtrans(en|sn)" class="option">Shona</li><li data-value="/#googtrans(en|sd)" class="option">Sindhi</li><li data-value="/#googtrans(en|si)" class="option">Sinhala (Sinhalese)</li><li data-value="/#googtrans(en|sk)" class="option">Slovak</li><li data-value="/#googtrans(en|sl)" class="option">Slovenian</li><li data-value="/#googtrans(en|so)" class="option">Somali</li><li data-value="/#googtrans(en|su)" class="option">Sundanese</li><li data-value="/#googtrans(en|sw)" class="option">Swahili</li><li data-value="/#googtrans(en|sv)" class="option">Swedish</li><li data-value="/#googtrans(en|tl)" class="option">Tagalog (Filipino)</li><li data-value="/#googtrans(en|tj)" class="option">Tajik</li><li data-value="/#googtrans(en|ta)" class="option">Tamil</li><li data-value="/#googtrans(en|te)" class="option">Telugu</li><li data-value="/#googtrans(en|th)" class="option">Thai</li><li data-value="/#googtrans(en|tr)" class="option">Turkish</li><li data-value="/#googtrans(en|uk)" class="option">Ukrainian</li><li data-value="/#googtrans(en|ur)" class="option">Urdu</li><li data-value="/#googtrans(en|uz)" class="option">Uzbek</li><li data-value="/#googtrans(en|vi)" class="option">Vietnamese</li><li data-value="/#googtrans(en|cy)" class="option">Welsh</li><li data-value="/#googtrans(en|xh)" class="option">Xhosa</li><li data-value="/#googtrans(en|yi)" class="option">Yiddish</li><li data-value="/#googtrans(en|yo)" class="option">Yoruba</li><li data-value="/#googtrans(en|zu)" class="option">Zulu</li></ul>
Associated javascript below
}
function s(e) {
if (!e) var e = window.event;
var t = decodeURIComponent(this.options[this.selectedIndex].value.toLowerCase().replace(/\//g, '').replace('&', '?')),
n = location.origin + location.pathname + t;
location.assign(n),
location.search || /[?&]sc/.test(t) || location.reload(!0)
}
You can apply click listeners to the list element where language is selected and on each click you can fire GA call.
In your case, code would be like
var languageListElem = document.querySelectorAll('[data-value^="/#googtrans"]')
languageListElem[0].parentNode.onclick = function doLanguageGACollection() { console.log("Do GA collection")}
in function doLanguageGACollection you can write code for triggering GA call.
In the code I have applied click listeners to the parent of all the list elements and indirectly to all the list elements. It is working on your site. Point to note is that you have to apply this click listener on each page load to make it work every time

IOS show keyboard on input focus

I have a problem that i can't fix.
Keyboard doesn't show on input.focus() on IOS
searchMobileToggle.addEventListener('click', function() {
setTimeout(function(){
searchField.focus();
}, 300);
});
I've been looking for a solution with no result, i know this is a frequently unsolved question but i see NIKE (https://m.nike.com/fr/fr_fr/) and FOODSPRING (https://www.foodspring.fr/) doing it on mobile.
So i'm wondering how do they do ?
None of the other answers worked for me. I ended up looking into the Nike javascript code and this is what I came up with as a reusable function:
function focusAndOpenKeyboard(el, timeout) {
if(!timeout) {
timeout = 100;
}
if(el) {
// Align temp input element approximately where the input element is
// so the cursor doesn't jump around
var __tempEl__ = document.createElement('input');
__tempEl__.style.position = 'absolute';
__tempEl__.style.top = (el.offsetTop + 7) + 'px';
__tempEl__.style.left = el.offsetLeft + 'px';
__tempEl__.style.height = 0;
__tempEl__.style.opacity = 0;
// Put this temp element as a child of the page <body> and focus on it
document.body.appendChild(__tempEl__);
__tempEl__.focus();
// The keyboard is open. Now do a delayed focus on the target element
setTimeout(function() {
el.focus();
el.click();
// Remove the temp element
document.body.removeChild(__tempEl__);
}, timeout);
}
}
// Usage example
var myElement = document.getElementById('my-element');
var modalFadeInDuration = 300;
focusAndOpenKeyboard(myElement, modalFadeInDuration); // or without the second argument
Note that this is definitely a hacky solution, but the fact that Apple hasn't fixed this in so long justifies it.
I found a solution, click() didn't work, but i figured it out.
searchMobileToggle.addEventListener('click', function() {
if(mobileSearchblock.classList.contains('active')) {
searchField.setAttribute('autofocus', 'autofocus');
searchField.focus();
}
else {
searchField.removeAttribute('autofocus');
}
});
I was working with vue.js that was removing input autofocus attribute, when the component was loaded.
So i had it on click, but there was another problem, the autofocus only worked once, but combined with focus(), it now work all the time :)
Thanks for your help !
This really drives me/us crazy. It works fine on the Android phone, but something is disabled by the Apple developer. (I understand it's annoying to pop the keyboard when not necessary though).
I accidentally found out that the "popup" module from Semantic-UI fixes this magically.
Note that the solution works for SemanticUI (#semantic-ui team may tell what event makes this work)
Here are how I did:
const [search, setSearch] = useState(false);
const inputRef = useRef(null);
React.useEffect(() => {
if (search) {
inputRef.current.focus();
} else {
inputRef.current.blur();
}
}, [search]);
<div onClick={() => setSearch(true)}>
<Popup
content="Search for Swimmers and Time Standards."
offset={[-500, -1000]}
trigger={<Icon name="search" />}
/>
</div>
{search && <Input ref={inputRef} />}
As you see, I wrapped the trigger Icon with the Popup module, and hide the Popup content by setting the crazy offset. And then it magically works.
See the demo here: https://swimstandards.com/ (check it out on your iPhone)
Angular solution:
on button click we need to create temporary input, append to existing container (close to our input) and focus on it.
btnClicked() {
this.showModal = true;
this.searchBar = this.renderer2.selectRootElement('#searchBar', true);
// 2nd argument preserves existing content
// setting helper field and focusing on it
this.inputHelper = this.renderer2.createElement('input');
this.renderer2.appendChild(this.searchBar, this.inputHelper);
this.inputHelper.focus();
let event = new KeyboardEvent('touchstart',{'bubbles':true});
this.searchBarButton.nativeElement.dispatchEvent(event);
}
after modal/target input is shown, we move focus and remove temporary one:
initiateKeyboard() {
setTimeout(()=> {
this.searchBarInput.nativeElement.focus();
this.renderer2.removeChild(this.searchBar, this.inputHelper);
},180);
}
and template:
<div id="searchBar">
<input type="button" class="button is-link is-light" value="Search" (click)="btnClicked()" (touchstart)="initiateKeyboard()" #searchBarButton>
</div>
You just need to remember that iPhone may zoom screen, so you need to adjust parameters of temporary input.
working solution: https://inputfocus.vercel.app/
Worked in 2022 with ios 16!
OMG, I searched for so long and the above solution won't work for me.
Here is how it worked for me. I wrapped the input in a React FocusLock component. Check this package out: https://www.npmjs.com/package/react-focus-lock
Here is a small example:
<FocusLock>
<Input />
</FocusLock>
There is no legitimate way to do this since iOS kind of wants to only open the keyboard on a user interaction, however you can still achieve this with either using prompt() or using focus() from within a click() event it and will show up.

Is there any event in ionic 3 when alert box is presented to the user

I have a requirement to display the image(help icon) in the ionic alert popup. I am using localization in our application. So what I have done right now is displayed the image using CSS class from translate strings as follows,
"PBMNotConnected": "<div>We didn't detect a PBM connected to your device.</div><p class='pbmAlertInfoBox'>Please select the <span class='infoIcon' (click)='goToHelp()'></span> (info icon) for help.</p>",
Now I am able to see the help icon in the alert box but, I want to bind the click event to that help icon. I have added (click) attribute in translate string but it doesn't work.
Following is the common code for presenting alert popup
/**
* show alert message
* #description pass non translated strings of title, subtitle, message and buttons text
*/
presentAlert(title, subtitle, message, cssClass, okText, hideButtons?:boolean) {
let buttons = [];
if(!hideButtons){
buttons = [this.getTranslate(okText, {})];
}
let alert = this.alertController.create({
title: this.getTranslate(title, {}),
subTitle: subtitle ? this.getTranslate(subtitle, {}) : '',
message: this.getTranslate(message, {}),
cssClass: cssClass,
buttons: buttons,
enableBackdropDismiss: false
});
alert.present();
return alert;
}
and then I have tried to bind the event using following code manually,
let alert = this.popUpService.presentAlert('error', undefined, 'PBMNotConnected', 'custom-popup-ok error', 'ok');
let elements: any = document.getElementsByClassName('.pbmAlertInfoBox .infoIcon');
if(elements.length > 0){
elements[0].click = () => {
this.goToHelp();
}
}
but now, the problem is I don't know when exactly the alert popup opens, so I need your help to know any event available after opening the alert popup.
Thanks in advance.

Categories