The macosxhints Forums

The macosxhints Forums (http://hintsforums.macworld.com/index.php)
-   OS X Developer (http://hintsforums.macworld.com/forumdisplay.php?f=27)
-   -   applescripting a javascript form (http://hintsforums.macworld.com/showthread.php?t=100814)

djeans 04-17-2009 08:29 AM

applescripting a javascript form
 
I have been scouring the forums trying to figure out how to change a popup box in a javascript web form but haven't had any luck. It's driving me crazy.

There is a webpage that contains a form (in a frame) that I need to set to a certain value. The webpage is on an internal network, so I can't post a URL to the page, unfortunately.

One of my issues, is that I can't figure out how to know what the index # is for the form or for the elements. I have tried scripting it via name, but that isn't working either.

Here is what I have been trying, changing things around a little and trying again, but it's not working.

tell application "Safari"
-- go to appropriate URL to login
open location "url"
delay 8
do JavaScript "window.frames[1]document.forms['locations']['LocationName'].option.selectedIndex = 'Honolulu'" in document 1

end tell


The html source code for the frame is this

<HTML>
<HEAD>
<META NAME="GENERATOR" Content="Microsoft Visual Studio 6.0">
<TITLE></TITLE>
</HEAD>

<SCRIPT LANGUAGE="JavaScript">
function GetRecords()
{
document.locations.action = "LocationPXS.asp";
document.locations.target = "LocationPXS";
document.locations.method = "POST";
document.locations.submit();
}

function AddNew()
{
var c = document.getElementById('LocationName');
var w = c.selectedIndex;
var selected_text = c.options[w].text;
if (selected_text == '--Select--')
{
alert('Please select your location');
return false;
}
document.locations.action = "AddPX.asp";
document.locations.target = "LocationPXS";
document.location.method = "Post";
document.locations.submit();
}

function GetData()
{
document.locations.action = "LocationPXS.asp";
document.locations.target = "LocationPXS";
document.locations.method = "POST";
document.locations.submit();
}
</SCRIPT>

<BODY ONLOAD="GetData()" Language="JavaScript">
<FORM NAME="locations" METHOD=POST ACTION="LocationPXS.asp">

<CENTER>
<IMG src=top.gif><P><Table border =0><TR><TD>Please Select Your Location </TD><TD><SELECT NAME=LocationName OnChange="GetRecords()"><OPTION>--Select--</OPTION><OPTION>--- long list of options -- </SELECT></TD></TR></Table>&nbsp;&nbsp;<INPUT TYPE=BUTTON OnClick="AddNew()" NAME=AddPX Value="Add PX">

</CENTER>
</FORM>
</BODY>
</HTML>

Any help would be greatly appreciated.

Thanks

djeans

acme.mail.order 04-17-2009 09:55 AM

First help I would offer is build in stages - don't add Javascript until the plain form is behaving properly. And a lot of the JS code appears redundant - you don't need JS to simply submit a form, just add the validation handler to the onSubmit action.

Second is don't use Applescript to alter web browsers - it's just not the right tool.

Third, your Javascript isn't going to do anything until you put some id="" attributes in the html. You _can_ do it without, but it's a lot less stress with an id in there.

It looks like you are in the early stages of updating part of the page on a select change?

djeans 04-17-2009 03:01 PM

Not sure I understand, but maybe I should have been more clear about what I'm trying to do.

The web page is on a company intranet site that I have to open every morning and change a drop down box to my city "Honolulu", upon which the form will update the page with information specific to my location.

I'm just looking for a way to script / automate this process with Safari, and have it email me the results automatically, so that the information is in my inbox when I wake up.

I have found other applescripts about automating javascript forms from other sites, but haven't been able to alter them to fit my needs. Was hoping someone could help me out.

D

roncross@cox.net 04-17-2009 04:54 PM

System Events may work
 
Welcome to javascript. Unless you can figure out the documents/elements, it's very difficult.

My advice for now would be to use System Events. You activate this by going to Universal Access and clicking the 'Enable access for assistive devices'

Once that's click, go ahead and do something like the following:
Code:

tell application "System Events"
    tell application process "Safari"
    delay d
click pop up button 1 of group 1 of scroll area 1 of group 2 of window "name_of_your_window"
        delay d
    end tell
end tell


djeans 04-17-2009 05:45 PM

Thanks for the reply.

I was hoping to avoid UI scripting if possible. If that turns out to be the only way, how do I select my city from the list once I have system events click the pop-up?

Thansk

Darron

roncross@cox.net 04-17-2009 06:26 PM

An easy way to do this is to first learn some examples from the Apple website:

http://www.apple.com/applescript/uiscripting/index.html

After you feel comfortable with how it works, then go to the following directory to find the Accessibility Inspector:

To get to the path, you will need to installed the Developer package for this if you haven't done so already.

The path is /Developer/Applications/Utilities/"Accessibility Tools"/"Accessibility Inspector.app"

From there, it will tell you exactly what all the attributes are for a particular element.

Write your script and set it to run whenever you like.

djeans 04-17-2009 08:59 PM

I have tried the UI scripting, and have had some success, except where it comes to selecting the right item from the list.

tell application "Safari"
activate
tell (make new document) to set URL to "url"
delay 5
tell application "System Events" to click pop up button 1 of group 3 of UI element 1 of scroll area 1 of UI element 1 of scroll area 2 of UI element 1 of scroll area 1 of group 3 of window "Main" of process "Safari"

clicks the pop up button, but I haven't discovered the consistent way to select the right item in the list. I have tried using keystroke with the first couple of letters, and it works sometimes, but not always. Can you suggest a better way to select the right item?

Thanks.

D

roncross@cox.net 04-17-2009 09:11 PM

Quote:

Originally Posted by djeans (Post 529312)
I have tried the UI scripting, and have had some success, except where it comes to selecting the right item from the list.

tell application "Safari"
activate
tell (make new document) to set URL to "url"
delay 5
tell application "System Events" to click pop up button 1 of group 3 of UI element 1 of scroll area 1 of UI element 1 of scroll area 2 of UI element 1 of scroll area 1 of group 3 of window "Main" of process "Safari"

clicks the pop up button, but I haven't discovered the consistent way to select the right item in the list. I have tried using keystroke with the first couple of letters, and it works sometimes, but not always. Can you suggest a better way to select the right item?

Thanks.

D

Code:

tell application "System Events"
  tell application "Safari"
        activate
        tell (make new document) to set URL to "url"
        delay 5
      click pop up button 1 of group 3 of UI element 1 of scroll area 1 of UI element 1 of scroll area 2 of UI element 1 of scroll area 1 of group 3 of window "Main"
  end tell
end tell

you don't need to say "Main" of process "Safari" since it is already activated in the 2nd line of the code. It already know that the window is in Safari

djeans 04-18-2009 09:00 AM

Thanks,

but I'm still at a loss for how to change the value of that pop up.

Darron

roncross@cox.net 04-18-2009 10:30 AM

Have you been able to use the Accessibility Inspector? It should be able to pick out the value of the pop up rather easily. Clicking the value would look something like the following:

Code:

click pop up button 2 of group 1 of        scroll area 1 of group 2 of window "name_of_window"
delay d
click menu item "value_of_pop_up" of menu 1 of pop up button 2 of group 1 of                                        scroll area 1 of group 2 of window "name_of_window"

You might have to use trial and error before you figure it out but it can be done. You can also copy and paste the results of the 'accessibility inspector' with the pop up window and post the results back and I may be able to help you out further. To do this select the pop up window with the value of interest and hit command+F7. This will lock the attributes of your selection so you can select it, copy it, paste it back here for review.

hayne 04-18-2009 10:59 AM

I'd like to point out another possibility (for achieving the higher-level goal) - use "Selenium": http://seleniumhq.org/

Quote:

Originally Posted by above web site
Selenium IDE is a Firefox add-on that records clicks, typing, and other actions to make a test, which you can play back in the browser.


mark hunte 04-18-2009 02:31 PM

Quote:

Originally Posted by hayne (Post 529356)
I'd like to point out another possibility (for achieving the higher-level goal) - use "Selenium": http://seleniumhq.org/

That looks pretty cool.

roncross@cox.net 04-18-2009 02:43 PM

Thanks hayne, sounds like a good find. I will have to try it out one day.

djeans 04-18-2009 07:37 PM

I tried using the accessibility inspector, but it's not very clear. I have also tried UI Browser, which is slightly easier to understand.

Here is the Accessibility Inspector window for that popup

<AXApplication: “Safari”>
<AXWindow: “Main”>
<AXGroup>
<AXScrollArea>
<AXWebArea: “”>
<AXScrollArea>
<AXWebArea: “”>
<AXScrollArea>
<AXMenu>
<AXMenuItem: “Honolulu”>

Attributes:
AXRole: “AXMenuItem”
AXRoleDescription: “menu item”
AXParent: “<AXMenu>”
AXEnabled: “1”
AXPosition: “x=827 y=738”
AXSize: “w=169 h=15”
AXTitle: “1136-Honolulu”
AXHelp: “(null)”
AXSelected (W): “1”
AXMenuItemCmdChar: “(null)”
AXMenuItemCmdVirtualKey: “(null)”
AXMenuItemCmdGlyph: “(null)”
AXMenuItemCmdModifiers: “0”
AXMenuItemMarkChar: “

djeans 04-18-2009 07:39 PM

Quote:

Originally Posted by hayne (Post 529356)
I'd like to point out another possibility (for achieving the higher-level goal) - use "Selenium": http://seleniumhq.org/

Thanks for the suggestion.

I installed the plugin, and i was able to record and playback going to the page and selecting the menu item, but I'm not sure how to incorporate that into an applescript.

D

roncross@cox.net 04-18-2009 08:05 PM

Well, you would put it in a script other than applescript. Your Mac has python so you could put the code there and run it.

roncross@cox.net 04-18-2009 08:12 PM

Quote:

Originally Posted by djeans (Post 529401)
I tried using the accessibility inspector, but it's not very clear. I have also tried UI Browser, which is slightly easier to understand.

Here is the Accessibility Inspector window for that popup

<AXApplication: “Safari”>
<AXWindow: “Main”>
<AXGroup>
<AXScrollArea>
<AXWebArea: “”>
<AXScrollArea>
<AXWebArea: “”>
<AXScrollArea>
<AXMenu>
<AXMenuItem: “Honolulu”>

Attributes:
AXRole: “AXMenuItem”
AXRoleDescription: “menu item”
AXParent: “<AXMenu>”
AXEnabled: “1”
AXPosition: “x=827 y=738”
AXSize: “w=169 h=15”
AXTitle: “1136-Honolulu”
AXHelp: “(null)”
AXSelected (W): “1”
AXMenuItemCmdChar: “(null)”
AXMenuItemCmdVirtualKey: “(null)”
AXMenuItemCmdGlyph: “(null)”
AXMenuItemCmdModifiers: “0”
AXMenuItemMarkChar: “

Please post the code that you have so far regarding this so we may have some idea on how to modify it.

djeans 04-18-2009 08:57 PM

Ok, here it is.

It gets to the page and clicks the pop up correctly, but stalls at selecting "Honolulu" and throws up an error that says "Invalid Index"

tell application "Safari"
activate
tell (make new document) to set URL to "https://intranet.locations/"
delay 5
tell application "System Events" to click pop up button 1 of group 3 of UI element 1 of scroll area 1 of UI element 1 of scroll area 2 of UI element 1 of scroll area 1 of group 3 of window "Main" of process "Safari"
tell application "System Events"
click menu item "Honolulu" of menu 1 of pop up button 1 of group 3 of UI element 1 of scroll area 1 of UI element 1 of scroll area 2 of UI element 1 of scroll area 1 of group 3 of window "Main" of process "Safari"
end tell
end tell

djeans 04-22-2009 07:12 PM

Any ideas why the script is giving me the invalid index error?

roncross@cox.net 04-22-2009 09:16 PM

According to the accessibility inspector, Honolulu is not in the pop up, i.e. the Invalid Index error: You might want to do something like the following although I'm not sure if it will work. Again, without having access to the website, it become a process of trial and error. You may want to put some effort into learning python if you are not able to get this to work for you:

Code:

tell Application "System Events"
tell application "Safari"
        activate
tell (make new document) to set URL to "https://intranet.locations/"
        delay 5
click menu item "Honolulu" of menu 1 of scroll area 1 of web area "" of scroll area 1 of web area "" of scroll area 1 of group 1 of window "Main"
end tell
end tell
end tell


djeans 04-22-2009 10:58 PM

error seems to be coming from the get menu part
"System Events got an error: Can’t get menu 1 of pop up button 1 of group 3 of UI element 1 of scroll area 1 of UI element 1 of scroll area 2 of UI element 1 of scroll area 1 of group 3 of window . . . . "

Tried the shorter script above, but it won't compile, with the error
"Expected end of line but found identifier." at the web area part with area highlighted.

I found that if I put in a long enough delay to select a location manually and then add in

get value of pop up button 1 of group 3 of UI element 1 of scroll area 1 of UI element 1 of scroll area 2 of UI element 1 of scroll area 1 of group 3 of window "Main" of application process "Safari"

It returns whichever location that I selected.

I tried changing the get value to set value, but that had no effect.

D

djeans 04-23-2009 04:26 AM

Partial success:

I couldn't get anything to work, so I thought about a different approach. Using a loop and down arrow to scroll through all of the locations until I hit the right one.

Here is the script so far

set menu_item to "Honolulu" as string (* my location *)

tell application "Safari"
activate
tell (make new document) to set URL to "https://intranet.locations/"
delay 5

tell application "System Events"

repeat until value of pop up button 1 of group 3 of UI element 1 of scroll area 1 of UI element 1 of scroll area 2 of UI element 1 of scroll area 1 of group 3 of window "Main" of application process "Safari" is menu_item
tell application "System Events" to click pop up button 1 of group 3 of UI element 1 of scroll area 1 of UI element 1 of scroll area 2 of UI element 1 of scroll area 1 of group 3 of window "Main" of process "Safari"
key code 125 (* down arrow *)
keystroke return (* confirm choice of menu item *)
delay 0.5
end repeat


beep
end tell
end tell

This works, albeit very slowly. For some reason, there is a long pause after the popup button is pressed (about 5 seconds) before it arrows down to the next selection even though there is no delay statement between the two actions.

If you see anything I can change to clean up the code to make it faster, let me know.

The next task will be getting the information that is returned in table form copied into an email - if you have any suggestions in that regard :)

D

tw 04-23-2009 06:49 PM

I don't understand why you're UI scripting this when it's much easier to use Safari's Do Javascript command. write a short javascript in an applescript variable and fire it off, like the following:
Code:

Set JScode to "themenu = document.getElementById('LocationName');
for (i=0; i<themenu.length; i++) {
    if ( themenu.options[i].value == 'Honalulu' ) {
          themenu.selectedIndex = i;
          GetRecords();
    }
}"
tell application "Safari" to do javascript JScode in document 1;

I haven't tested this, of course. you might not need to call GetRecords() explicitly (I don't know if javascript changes register with the onchange handler), and I might have bugs in the javascript (can you set a menu value by setting the selectedIndex property? I don't remember). but still...

djeans 04-23-2009 07:10 PM

tw,

thanks for the reply.

I am not very familiar with javascript, but I did try dropping in your script, but it didn't appear to do anything. Does in need to have a dojavascript in front of it?

Originally I was trying to avoid UI scripting in favor of javascript, but was not having any luck.

Thanks
D

tw 04-23-2009 07:20 PM

it's really hard to debug these things without access to the code. did you check console, or the safari error log (if you have it enabled) to see if it's throwing any errors?

tw 04-23-2009 08:10 PM

ok, a little playing around, and I realized that I had the reference form wrong. try this version instead:

Code:

set JScode to "themenu = window.frames[0].document.forms[0].LocationName
for (i=0; i<themenu.length; i++) {
    if ( themenu.options[i].value == 'Honolulu' ) {
          themenu.selectedIndex = i;
          window.frames[0].GetRecords()
    }
}"
tell application "Safari" to do JavaScript JScode in document 1

assuming that it's the first form on the first frame of the page (and that I spelled Honolulu correctly).

djeans 04-23-2009 08:57 PM

Thanks again for the reply and trying to help.

I tried your new code, with same results. The page has 2 frames, as far as I can tell, with the only form on the page being in the second frame so I did change the frames[0] to frames [1] and tried that as well. Still nothing happening after the page loads.

D

djeans 04-23-2009 08:58 PM

Quote:

Originally Posted by tw (Post 530086)
it's really hard to debug these things without access to the code. did you check console, or the safari error log (if you have it enabled) to see if it's throwing any errors?

Haven't checked those yet, will try and see what comes up.

roncross@cox.net 04-23-2009 08:59 PM

If you know who developed the web page, you might try asking the programming what the elements/documents are for what you are trying to do. Ask them, how do they access this with javascript.

djeans 04-23-2009 09:01 PM

Ok, looked at Safari error log, there is this:

TypeError: Result of expression 'window.frames[1].document' [undefined] is not an object.

tw 04-23-2009 09:45 PM

well, that's not very helpful. :D what does the html of the frames page look like? not the page you posted, which is what goes in the frame, but the outer page...

djeans 04-24-2009 03:14 AM

Ok, here is the html for the main page

<html>
<head>
<title>Main</title>
</head>
<frameset rows='70,*' border='0'>
<frame src='/header.asp' name='Header' marginheight='0' marginwidth='0' scrolling='no' noresize>
<frame src='http://intranet.locations/' name='Report' marginheight='0' marginwidth='0' scrolling='auto'>
</frameset>
</html>

Hope that helps

d

tw 04-24-2009 11:56 AM

alright, do this. copy the following code:
Code:

set JScode to "themenu = window.frames['Report'].document.forms['locations'].LocationName
for (i=0; i<themenu.length; i++) {
        alert( "index " + i + ": " + themenu.options[i].value);
        if ( themenu.options[i].value == 'Honolulu' ) {
                alert("Found Honolulu at index " + i);
                themenu.selectedIndex = i;
                window.frames['Report'].GetRecords()
        }
}"
tell application "Safari" to do JavaScript JScode in document 1

and paste it into the Script editor. then open the web page in Safari, go back to the script editor and click run. it should give you an annoying alert for every list item it finds, and a different one if it finds Honolulu. see it if does anything, and either way tell me what errors you see in Safari and the Script editor, and what the alerts say (they ought to give a menu index number and the value of the menu item).

djeans 04-24-2009 03:51 PM

Quote:

Originally Posted by tw (Post 530160)
alright, do this. copy the following code:
Code:

set JScode to "themenu = window.frames['Report'].document.forms['locations'].LocationName
for (i=0; i<themenu.length; i++) {
        alert( "index " + i + ": " + themenu.options[i].value);
        if ( themenu.options[i].value == 'Honolulu' ) {
                alert("Found Honolulu at index " + i);
                themenu.selectedIndex = i;
                window.frames['Report'].GetRecords()
        }
}"
tell application "Safari" to do JavaScript JScode in document 1

and paste it into the Script editor. then open the web page in Safari, go back to the script editor and click run. it should give you an annoying alert for every list item it finds, and a different one if it finds Honolulu. see it if does anything, and either way tell me what errors you see in Safari and the Script editor, and what the alerts say (they ought to give a menu index number and the value of the menu item).

Gives me an error that says
A property can’t go after this “"”.
with "Index " highlighted when trying to compile. Won't let me run the script.

D

tw 04-24-2009 04:47 PM

Quote:

Originally Posted by djeans (Post 530177)
Gives me an error that says
A property can’t go after this “"”.
with "Index " highlighted when trying to compile. Won't let me run the script.

D

ugh, I hate it when I make stupid errors. the double-quotes - " - on the two lines that have alert statements should be single-quotes.

djeans 04-24-2009 06:19 PM

Ok,

Thanks!

It compiles now, but when run, nothing happens.

Error log returns the same error:
TypeError: Result of expression 'window.frames['Report'].document' [undefined] is not an object.

tw 04-24-2009 07:49 PM

well, I don't know what to tell you. I duplicated the structure of the two pages you posted and the script works fine, so that tells me that something is off in what you sent, or some kind of DOM manipulation is happening in the javascripts that I can't see. the fact that it says the document is not an object tells me that that frame is not loaded when the script runs, but not why...

if it were me, I'd start playing with Safari's Web Inspector (right click on the menu and select 'Inspect Element') to see if I could figure out the correct way to reference the menu and scripts (which is where we're stuck). nothing more I can do on this end, though (except guess), without access to the site.

djeans 04-24-2009 08:17 PM

I think I may have stumbled on something, although I'm not sure if it is the problem, or if it is, if it can be worked around.

found another error that says:
Unsafe JavaScript attempt to access frame with URL https://extranet.mycompany.com/web/t.../px/locations/ from frame with URL http://www.mycompany.com/px/locations/Locations.asp. Domains, protocols and ports must match.

I have edited out my company name out of paranoia, and I could perhaps provide you with a url, but don't want it on the forum, for same paranoia reasons.

I appreciate your help thus far, and understand if you are not interested in helping further, but if you are, let me know and I'll give you a url to test it out via email or private msg.

d

tw 04-24-2009 08:39 PM

you can send me a private message with the info on the forum, no problems. just hover your mouse over my user name and click from the auto-dropdown -menu.

djeans 04-25-2009 05:32 PM

TW, sent you a private message yesterday, but can't find it in my sent messages. Did you get it?

D

thompsonsol 04-26-2009 07:54 AM

Used Keystrokes in the AppleScript?
 
Have you tried using keystrokes and clicks with AppleScripts. I use it to login to Google Mail automatically:
http://applescripts.thompson-solutio...i_mac_os_x.php

Reference Keystroke materials can be found below at:
http://applescripts.thompson-solutio...oard_guide.php

roncross@cox.net 04-26-2009 01:05 PM

Quote:

Originally Posted by djeans (Post 529981)
This works, albeit very slowly. For some reason, there is a long pause after the popup button is pressed (about 5 seconds) before it arrows down to the next selection even though there is no delay statement between the two actions.

If you see anything I can change to clean up the code to make it faster, let me know.

The next task will be getting the information that is returned in table form copied into an email - if you have any suggestions in that regard :)

D

I think you are on the right track. Forget the set menu_item to "Honolulu" as string ....
You might want 5 seconds delay if you are hearing beeps. Once you get the scripts to work, you can reduce the delays.
Code:

tell application "System Events"
tell application "Safari"
        activate
tell (make new document) to set URL to "https://intranet.locations/"
        delay 5
click pop up button 1 of group 3 of UI element 1 of scroll area 1 of UI element 1 of scroll area 2 of UI element 1 of scroll area 1 of group 3 of window "Main"
delay 5
repeat "number of times it takes to get to Honolulu in the popup window"
key code 125
delay 5
end repeat
keystroke return
delay 5
end tell
end tell

In this case, you are putting the key down stroke in the repeat loop for the number of times it takes to get to the Honolulu in the pop up window assuming it is always in the same position. If it's always in the same position, you are good to good, otherwise, I'm afraid that I have run out of ideals...:confused:

Be sure to spell the menu items correctly or else it will cause a beep.


All times are GMT -5. The time now is 05:35 AM.

Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2014, vBulletin Solutions, Inc.
Site design © IDG Consumer & SMB; individuals retain copyright of their postings
but consent to the possible use of their material in other areas of IDG Consumer & SMB.