Safari, Javascript & XPath - I'm stumped!

Hi all,

I’ve been using KM for years for extremely simple tasks, but I’m now working in an environment where I am working extensively with a Salesforce database in Safari, and I’d like to find a way to automate the following actions:

  1. select a phone number from one of five fields, then (ideally) select a menu item from a contextual menu that will take the highlighted phone number and pass it to my phone to dial

  2. Click a button on the safari page to initiate the logging of a given phone call as I’m on the call.

Keep in mind that I have absolutely no experience with Javascript and minimal experience with Applescript; what I’ve been able to do I’ve done through searching the web for code snippets and a bunch of trial and error.

I’m afraid that I may have to kludge the first task, as from what I’ve seen, KM doesn’t have any way to cleanly call the contextual menu, but in any case, I need to be able to highlight the text before i can even tackle that problem. I’ve been able to highlight the filed I want with this code…

var ta = document.getElementById(“con13_ilecell”);
ta.focus();

…but I can’t figure out how to actually select the contents of the field. Note that adding “ta.select();” doesn’t change anything here.

Ideally what I’m looking for is a way to emulate what happens if I use the mouse to move the cursor to the end of the phone number and then click-drag across it to highlight the number.

As for the second issue, my sense is that this is fairly simple to do thanks to the “Click Chrome or Safari Item at Xpath” action; however, I can’t for the life of me figure out what the data is that I need to plug in to the Path field to actually result in a button-click. I pulled what I believe should be the right Path for the object in question through Chrome’s developer tools…

//*[@id=“003G000002fDkfP_RelatedHistoryList”]/div[1]/div/div[1]/table/tbody/tr/td[2]/input[1]

…but it’s not working.

Any input would be much appreciated. I’ve scoured the posts related to these topics on the forums, and done some Google searches as well, but I’ve been unable to decipher anything that I can implement.

Thanks!

Adam

I usually just triple-click (or click and drag) to select a phone number. Given that you have 5 fields to choose from, how to you expect to automate which field to select?

IAC, I have used this Macro for a long time to dial the selected phone number:

If you will post at least a screenshot of the web page where you want to select the phone number, and the criteria for selecting the field to select, I'll try to make further suggestions.

I'll duplicate the macro 5 times, modify as necessary and assign each a unique hot key; option-command-H for home, option-command-B for business, etc.

I'll send you the screenshots privately.

I would not duplicate the macro -- that quickly becomes a maintenance nightmare. :smile:

Instead, use one macro with multiple triggers. At the beginning of the macro set a KM Variable to `%TriggerValue%, and then setup a Switch/Case Action to branch on each case.

The Salesforce web page may be a very complicated Javascript-driven web page that does not lend itself well to standard web DOM commands. But we won't know till we try.

Can you use Chrome for some testing/development work?

Bring up the Salesforce page in Chrome, and right click on one of the phone fields.
This will display the HTML code for that HML element. Can you then do a tight screencapture of just the HTML code and post it?

Good advice re the multiple triggers, thanks.

Here are a couple of screenshots that will hopefully give you what you're after.

This first one is from a contact's main page:

This second one is from a report, with each row on the report representing a single client. I might be working out of this sort of report if I want to blast through calls to a number of clients quickly. The tricky thing here is that the same HTML element appears to be used row after row, so I'm not sure how I'd select a specific row using the macro.

Thanks, but I'm looking for the HTML code shown in the Chrome Developer tool, like this:

One possible approach is that if all of the phone fields have the same HTML Class, then we could do something like this:

var phoneList = document.getElementsByClassName("phone-class");
var mobileElem = phoneList[0]

Of course, there are many other approaches. It all depends on the actual HTML of your page.

OK, let me know if this gives you what you're after:

Main Contact Page Phone Field:

Multi-Contact Report Phone Field:

Did the stuff i posed last week provide you with any insight?

Thanks!

Adam

Looks like the phone number is directely in a Table "td" element, but it has an ID:

Have you tried using this ID to get the element, and set focus?

Yes.

As I said in the first post, I’ve been able to highlight a given phone number field with this code…

var ta = document.getElementById(“con13_ilecell”);
ta.focus();

…but I can’t figure out how to actually select the contents of the field. Note that adding “ta.select();” doesn’t change anything here. Obviously, the (5) fields each have a slightly different ID, so the one I originally referenced is “con13”, but the code snippet I sent references one of the others.

The way the system works, the “Click to Call” extension passes selected text to the dialer when the CTC menu item is initiated via the contextual menu, and the dialer then sends the call to my Cisco VOIP phone. If something other than a full phone number is selected, then the dialer chokes.

When i execute the code above, the field itself is shaded light blue, but the contents of the field are not selected, so they are not passed to the dialer when I initiate the “CTC” menu item; the extension acts as if I have selected nothing and initiated the CTC command, so no call is ever dialed.

You might try this:

  function fnSelect(objId) {
    fnDeSelect();
    if (document.selection) {
    var range = document.body.createTextRange();
           range.moveToElementText(document.getElementById(objId));
    range.select();
    }
    else if (window.getSelection) {
    var range = document.createRange();
    range.selectNode(document.getElementById(objId));
    window.getSelection().addRange(range);
    }
  }
 
  function fnDeSelect() {
    if (document.selection) document.selection.empty(); 
    else if (window.getSelection)
                window.getSelection().removeAllRanges();
  }

fnSelect("con13_ilecell");   // or whatever the Element ID is

I have not tested this. Got the script from here:
JavaScript: Select text in a DIV, SPAN, or table cell

You can test this after running the above script by doing a manual COPY, then PASTE somewhere else.

THAT WORKS, A THOUSAND THANKS!!!

Now, a couple of questions:

  1. You had recommended that I not duplicate this and assign different triggers to Home #, Work #, etc. How would you set this up as a single macro that triggers a different field selection based on different triggers?

  2. What about the other question above regarding how to find and click a button or other element on a page using XPath (or some other method)?

…And another one - I was thinking that what I would do to get to the menu item in the contextual menu would be to simulate control-clicking the mouse, then have KM type “CTC” and return to initiate the command. That works, as long as the mouse is directly over the field that your code just selected. However, if the mouse is somewhere else, control-clicking it deselects the phone number that the script selected, so nothing gets sent to the dialer.

How would I make sure that the mouse is positioned over the selected number when I call the contextual menu, given that the size and placement of the window is likely to change (which would prevent me from using mouse coordinates to get this done)?

Thanks again!

Just use the %TiggerValue% token to read the actual trigger used, and then setup a Switch/Case Action based on that.

Here's an example.

WARNING!: This macro, unlike most that I post, comes with preset Triggers:
CTRL-KeyPad1
CTRL-KeyPad2

##Macro Library   [KM] How to Process Multiple Triggers [Example]


####DOWNLOAD:
<a class="attachment" href="/uploads/default/original/2X/9/9fa312aa8aa4ed733a7a55bf961c9e318abf40c5.kmmacros">[KM] How to Process Multiple Triggers [Example].kmmacros</a> (5.0 KB)

---

###ReleaseNotes

TBD

---

<img src="/uploads/default/original/2X/0/09c2fc721e044508c4ea10b794f46271f9094125.png" width="511" height="882">

Instead, try using my Macro, posted above, to initiate a phone call via hotkey after the phone field is selected.

OR

Call my macro as a sub-macro.

That is left as an exercise for the student to work out. :smile:
I'm sure you can do it -- just takes a bit of research and trial and error.
Entering test code in the JavaScript Console is a great way to test ideas and develop new techniques.

OK, I’ve used the [WEB] Click on Link Using XPath [Example] script you posted and the YouTube XPath video you uploaded to get the button clicked, and when I run the macro, it does indeed work. However, it also throws the following error up in a separate window, with the title “Keyboard Maestro - JavaScript in Safari Results”:

The output of the text script is:
osascript: OpenScripting.framework - scripting addition “/Users/codogBC/Library/ScriptingAdditions/24U Appearance OSAX.osax” cannot be used with the current OS because it has no OSAXHandlers entry in its Info.plist.
OK

Do you know what is causing that and how I would go about fixing it?

Thanks again for all your help!

I'm not sure that will work, as my company has built a proprietary Safari extension to initiate a call through our VOIP phones. As I recall, your macro is designed to call using an iPhone, right? I assume that won't work with a Cisco VOIP phone, but let me know if I'm mistaken.

This is an anomaly with KM and the Mac scripting under Yosemite.
You just need to uncheck the "Include Errors" (click on the gear icon):

Yes, my macro dials the phone using your iPhone via FaceTime.

Ask your company IT dept if there is a way to call their custom Safari extension via JavaScript or hotkey or other means, other than via a right-click.

Better yet, ask them to provide a new version that will dial the currently selected number.