Implemented functions
- Full screen click event √
- ,
- Rolling event √
- ,
- Scripts and events are editable √
- Visualization of scripts and events √
- Import/Export √
- Batch import/export √
- TAB parameter Call script √ of another TAB
Social Security website pit
I said before that this plug-in is for the personnel management personnel, but I thought I could almost be used by others, so I asked the personnel department for Ukey for practical operation
But I never expected that the government website should be JSP pages, but also with iframe, some or dynamic loading and dynamic creation, and the use of HTML native SELECT tag, I was really helpless. I have no choice but to bite the bullet.
Functions that need to be implemented
- Layer
The recording and execution of the above events in layer <iframe>
How to bind the event in iframe in the first place
- The second argument to jquery specifies which element to look for
input
$('input', doc).on('input', input)
Copy the code
- Binding this
contentWindow
For the iframewindow
The doc object is iframedocument
object
doc.addEventListener('click', onclick.bind(contentWindow), true)
Copy the code
Then get the real mouse coordinates
/** * this = contentWindow * @param ev */ function onclick (ev) { let {x, y} = getPosition_Iframe(ev, Let delay = new Date().getTime() -window.startTime if (delay > 5 &&! window.running) { window.startTime += delay let event = { x, y, clientX: ev.clientX, clientY: ev.clientY, type: 'click', tagName: ev.target.tagName, time: delay } chrome.runtime.sendMessage({ type: 'add-event', event: Event}) console.log('onclick', event, ev)} */ function getPosition_Iframe (event = {}, contentWindow) { var parentWindow = contentWindow.parent; var tmpLocation = contentWindow.location; var target = null; var left = 0; var top = 0; while (parentWindow ! = null && typeof (parentWindow) ! = 'undefined' && tmpLocation.pathname ! = parentWindow.location.pathname) { for (var x = 0; x < parentWindow.frames.length; x++) { if (tmpLocation.pathname == parentWindow.frames[x].location.pathname) { target = parentWindow.frames[x].frameElement; break; } } do { left += target.offsetLeft || 0; top += target.offsetTop || 0; target = target.offsetParent; } while (target) tmpLocation = parentWindow.location; parentWindow = parentWindow.parent; } let xy = {x: left + (event.clientX || 0), y: top + (event.clientY || 0)} return xy }Copy the code
Modifying the Event Object
The difference between event objects
Event = {x: ev.clientx, y: ev.clienty, type: 'click', tagName: ev.target.tagName, time: Delay} // modified event // xy represents the mouse click coordinates in the main window // clientX,clientY represents the mouse click coordinates in the iframe event = {x, y, clientX: ev.clientX, clientY: ev.clientY, type: 'click', tagName: ev.target.tagName, time: delay }Copy the code
toiframe
The binding event
Generic binding methods
Function bindEvent (doc, contentWindow) {function bindEvent (doc, contentWindow) {function bindEvent (doc, contentWindow) {function bindEvent (doc, contentWindow) { AddEventListener ('click', onclick.bind(contentWindow), true) $('input', doc).on(' keyUp ', onkeyup) $('input', doc).on('keydown', onkeydown) $('input', doc).on('input', input) $('input', doc).on('compositionstart', compositionstart) $('input', doc).on('compositionend', compositionend) $('textarea', doc).on('keyup', onkeyup) $('textarea', doc).on('keydown', onkeydown) $('textarea', doc).on('input', input) $('textarea', doc).on('compositionstart', compositionstart) $('textarea', doc).on('compositionend', AddEventListener ('mousemove', throttle(setScrollWatcher. Bind (contentWindow)), true)}Copy the code
Calling the binding method
Let iframes = new Set() function bind () {window.starttime = new Date().gettime ( bindEvent(document, window) $('iframe').each((index, Iframe) => {ifames. Add (iframe) // Add the event let iframeContentWindow = iframe.contentWindow let doc = iframeContentWindow.document doc.removeEventListener('click', onclick.bind(iframeContentWindow), true) bindEvent(doc, IframeContentWindow) // Add event $(iframe).on('load', function (event) { iframes.add(iframe) iframeContentWindow = iframe.contentWindow doc = iframeContentWindow.document doc.removeEventListener('click', onclick.bind(iframeContentWindow), true) bindEvent(doc, IframeContentWindow)})}) // Bind ('DOMNodeInserted') to dynamically generated iframe event $(document). throttle(() => { $('iframe').each((index, iframe) => { if (! iframes.has(iframe)) { let iframeContentWindow = iframe.contentWindow let doc = iframeContentWindow.document doc.removeEventListener('click', onclick.bind(iframeContentWindow), true) bindEvent(doc, iframeContentWindow) } }) }, 500)) console.log('bind.js already running ')}Copy the code
performevent
object
let focusTarget = null function startEvent (item, i) { let target = null switch (item.type) { case 'click': let click target = document.elementFromPoint(item.x, If (target.tagName === 'iframe ') {// The document of iframe uses clientX,clientY to fetch target = target.contentWindow.document.elementFromPoint(item.clientX, item.clientY) click = new MouseEvent('click', { clientX: item.clientX, clientY: item.clientY, bubbles: true, cancelable: true }) } else { click = new MouseEvent('click', { clientX: item.x, clientY: item.y, bubbles: true, cancelable: True})} target. DispatchEvent (click) / / to get ready for the next INPUT event if (item. TagName = = = 'INPUT' | | item. TagName = = = 'TEXTAREA') { target.focus && target.focus() focusTarget = target } else if (item.tagName === 'SELECT') { focusTarget = target } else {focusTarget = NULL} break} console.log(' Automation -${I}-${item.type} wait ${item.time} milliseconds')}Copy the code
Highlighting is similar to this
<select> Select events
Bind the SELECT event
Select is really a weird DOM, and everything on the web doesn’t work perfectly, either it doesn’t open the dropdown or it doesn’t open in the right place. But I found a way to do it through testing. I noticed that the coordinates returned after clicking Option are negative! This is done in the click event ~ modified onclick method
/** * this = contentWindow * @param ev */ function onclick (ev) { let {x, y} = getPosition_Iframe(ev, this) let delay = new Date().getTime() - window.startTime if (delay > 5 && ! Window.running) {window.startTime += delay let event // The native <select> event is too strange, So put set the select worth the time to click on the < option >, the current support radio if (ev) target) tagName = = = 'select' && ev. ClientX < 0 && ev. ClientY < 0) {if (ev) target) selectedOptions) {/ / get to select the value of the selected let val = [] for (let the option of ev. The target. The selectedOptions) { val.push(option.value) } if (val.length === 0) { val = '' } else if (val.length === 1) { val = val[0] } event = { type: 'set - select - value', / / a new event type key: "', value: val, time delay} chrome. Runtime. SendMessage ({type: 'add-event', event: event }) } } else { event = { x, y, clientX: ev.clientX, clientY: ev.clientY, type: 'click', tagName: ev.target.tagName, time: delay } chrome.runtime.sendMessage({ type: 'add-event', event: event }) } console.log('onclick', event, ev) } }Copy the code
Perform event
The InputEvent event is simulated in the same way as input
Case 'set-select-value': If (focusTarget) {// https://stackoverflow.com/questions/23892547/what-is-the-best-way-to-trigger-onchange-event-in-react-js let prototype = window.HTMLSelectElement.prototype let nativeInputValueSetter = Object.getOwnPropertyDescriptor(prototype, "value").set; nativeInputValueSetter.call(focusTarget, item.value); let inputEvent = new InputEvent('input', {bubbles: true}) focusTarget.dispatchEvent(inputEvent) } breakCopy the code
Demonstration effect
www.bilibili.com/video/BV1aU…