Hello, I have a javascript that presently work fine on any Windows based machine but I would like to know if it would be possible to edit the script to allow it to work on Macs too. This script works with Adobe Acrobat for bookmarking PDF files. Any assistance would be greatly appreciated, thanks in advance. /* Bookmarker * A tool to link the bookmarks in a file to a set of files representing tabs in a * bound volume, according to the alphanumeric tab identifiers contained in each * bookmark title, and then process each linked file, to give it the same title and * bookmarks to all the others. */ var BMdoc = null, BMdigits = 2, BMleadnum, BMhierarchy, BMtabs; var BMcurtab, BMdoctab, BMcollapsed = 0; var BMmarks = new Array(); var BMnetwmarks = new Array(); var BMfilenames = new Array(); var BMscripts = new Array(); var CANCEL=2, ALERTNO=3, ALERTYES=4, BMBOLD=2; // Generate a bookmark script that opens filename and closes its own document function BMopenScript( filename ) { var s = "if( this.external ) this.getURL( '"+filename+"' ); else { "; s += "var old = this, f = app.openDoc( '"+filename+"', this ); "; s += "if( f && f!=old ) old.closeDoc(); }"; return s; } // Prompt user for a file, making sure it has an extension and exists function BMaskFile( question, answer ) { var filename, f, r; do { filename = app.response( question, "Open", answer ); if( !filename ) return null; if( filename.indexOf('.') == -1 ) filename += ".pdf"; try { f = app.openDoc( filename, BMdoc ); } catch(e) { r = app.alert( '"'+filename+'" not found. Use anyway?', 2, 3 ); } } while( !f && r==ALERTNO ); if( !f && r==CANCEL ) return null; if(f) f.closeDoc( true ); return filename; } // Assemble a bookmark interactively function specialBM( q ) { BMfilenames[BMtabs] = BMaskFile( q, BMfilenames[BMtabs] || '' ); if( BMfilenames[BMtabs] ) { BMscripts[BMtabs] = BMopenScript( BMfilenames[BMtabs] ); console.println( BMmarks[BMtabs].name.substring(0,64)+ " linked to " +BMfilenames[BMtabs] ); BMmarks[BMtabs].setAction( BMscripts[BMtabs] ); return BMfilenames[BMtabs++]; } return null; } // Assign bookmarks to open corresponding files, according to leading number of // bookmark name, which is followed by a period. // Files shoould be named tabXX.pdf, with only as many digits as needed for the // highest tab in place of the exes, with leading zeros as placeholders function assignBookmarks( root, prefix, supertab, first ) { if( !root.children ) return; var i = 0; if( root.style == BMBOLD ) { // Bold tabs signify a separate index with differing filenames do { prefix = app.response( 'How do the filenames for sub-tabs of "' +root.name+ '" begin?', "Prefix", prefix ); } while( !prefix ); first = true; } if( first ) { // first bookmarks may be assigned manually while( i < root.children.length ) { BMmarks[BMtabs] = root.children; if( !specialBM( 'Enter filename for bookmark "'+BMmarks[BMtabs].name+ '" or hit cancel to process this and the rest automatically.' ) ) break; assignBookmarks( root.children[i++], prefix, null, true ); } } while( i < root.children.length ) { BMmarks[BMtabs] = root.children; BMfilenames[BMtabs] = null; BMscripts[BMtabs] = ''; var tab = BMmarks[BMtabs].name.substring( 0, BMmarks[BMtabs].name.indexOf('.') ), no = null; if( tab && tab.length <= (BMdigits+6 + (BMleadnum ? (BMdigits+1):0)) ) { //possible valid tab no? var len = 0, alpha = false; no = parseInt( tab, 10 ); if( isNaN(no) ) { no = parseInt( tab.substring( 1, BMdigits+2 ), 10 ); // try skipping initial letter alpha = !isNaN(no); if( alpha ) len++; } if( !isNaN(no) ) { if( no < 0 ) { len++; no = -no; // provision for a dash } no += ''; // convert to string len += no.length; while( no.length < BMdigits ) no = '0' + no; //leading zeros if( alpha ) no = tab.charAt(0) + no; //leading letter } else no = ''; if( no && BMleadnum ) { len++; // decimal or dash separator var pt = parseInt( BMmarks[BMtabs].name.substring( len, len+BMdigits ), 10); pt += ''; len += pt.length; while( pt.length < BMdigits ) pt = '0' + pt; no += '_' + pt; } var dot = BMmarks[BMtabs].name.indexOf( '.', len ); if( dot > len && dot <= len+4 ) no += BMmarks[BMtabs].name.substring( len, dot ); // trailing letter(s) if( no ) { if( BMhierarchy && supertab ) no = supertab + no; BMfilenames[BMtabs] = prefix + no + ".pdf"; BMscripts[BMtabs] = BMopenScript( BMfilenames[BMtabs] ); console.println( BMmarks[BMtabs].name.substring(0,64)+" linked to "+BMfilenames[BMtabs] ); } } if( !BMfilenames[BMtabs] ) console.println( BMmarks[BMtabs].name.substring(0,64)+" is inactive." ); BMmarks[BMtabs].setAction( BMscripts[BMtabs++] ); assignBookmarks( root.children[i++], prefix, no || supertab, false ); } } // Check to make sure the files corresponding to bookmark titles exist, and offer the // user an opportunity to make unmatched bookmarks inactive, or re-assign them. function precheckBM() { var i, f, t = app.thermometer; t.duration = BMtabs; t.begin(); for( i = 0; i < BMtabs; i++ ) { t.value = i; if( !BMfilenames ) continue; if( t.cancelled ) break; t.text = "Checking tab " + BMmarks.name; try { f = app.openDoc( BMfilenames, BMdoc ); } catch(e) { if( app.alert( '"'+BMfilenames+'" could not be found for tab '+BMmarks.name+ "\nShould this tab be made inactive?", 2, 2 ) == ALERTYES ) { BMfilenames = null; BMscripts = ''; console.println( BMmarks.name.substring(0,64)+" CONVERTED TO INACTIVE." ); BMmarks.setAction(''); continue; } BMfilenames = BMaskFile( "Enter alternate filename for tab "+BMmarks.name+ "\nor cancel the process and revise the bookmark title(s).", BMfilenames ); if( !BMfilenames ) { t.end(); return false; } BMscripts = BMopenScript( BMfilenames ); console.println( BMmarks.name.substring(0,64)+" RE-LINKED to " + BMfilenames ); BMmarks.setAction( BMscripts[i] ); continue; } f.closeDoc( true ); } t.end(); return true; } // Copy all bookmarks names and scripts from a source tree to a destination root function cloneBMTree( src, dest, list ) { if( !src.children ) return; var i; for( i = 0; i < src.children.length; i++ ) { dest.createChild( src.children[i].name, BMscripts[BMcurtab], i ); dest.children[i].color = src.children[i].color; dest.children[i].style = src.children[i].style; if( list ) list[BMcurtab] = dest.children[i]; BMcurtab++; cloneBMTree( src.children[i], dest.children[i], list ); } dest.open = (BMdoctab < BMcurtab || BMdoctab - BMcollapsed < 24); if( !dest.open ) BMcollapsed += i; // Collapse tabs above the current document's if it's far down } // Clone bookmarks to all linked files function procBMfiles( clear, clone, networkDoc ) { var tabDoc, errors = 0, t = app.thermometer; t.duration = BMtabs; t.begin(); for( BMdoctab = 0; BMdoctab < BMtabs; BMdoctab++ ) { t.value = BMdoctab; if( !BMfilenames[BMdoctab] ) continue; if( t.cancelled ) break; t.text = "Processing tab " + BMmarks[BMdoctab].name; try { tabDoc = app.openDoc( BMfilenames[BMdoctab], BMdoc ); } catch(e) { if( app.alert( '"'+BMfilenames[BMdoctab]+'" could not be found. Would you like to continue?', 0, 2 ) == ALERTYES ) { errors--; continue; } else break; } tabDoc.addScript( "Bookmarked", "this.disclosed = true; this.pane = 'B';" ); // make accessible and navigable tabDoc.info.Title = BMmarks[BMdoctab].name; // set title to match bookmark name tabDoc.zoomType = zoomtype.fitP; // initial view tabDoc.layout = "SinglePage"; if( clear ) tabDoc.bookmarkRoot.remove(); if( clone ) { BMcurtab = BMcollapsed = 0; cloneBMTree( BMdoc.bookmarkRoot, tabDoc.bookmarkRoot, null ); } if( app.viewerVersion >= 7 ) app.execMenuItem( "Save", tabDoc ); // v7 allows specification of focus else app.execMenuItem( "Save" ); // but it's probably unnecessary. Much faster than doc's saveAs method var tabPath = tabDoc.path; tabDoc.closeDoc(); if( networkDoc ) { if( BMdoctab < 2 ) //Counting on there being one title page in stub, followed by instruction page(s) BMnetwmarks[BMdoctab].setAction( "this.pageNum = "+ BMdoctab +";" ); else { var pg = networkDoc.numPages; if( app.viewerVersion >= 7 ) app.beginPriv(); networkDoc.insertPages( pg-1, tabPath ); // append the tab files in order if( app.viewerVersion >= 7 ) app.endPriv(); BMnetwmarks[BMdoctab].setAction( "this.pageNum = "+ pg +";" ); // and bookmark their first pages } } } t.end(); return (errors || BMdoctab); } function runBookmarker() { if( app.viewerVersion < 6 ) { app.alert( "ABA Bookmarker requires Acrobat version 6 or later." ); return; } if( app.viewerVersion >= 7 ) app.beginPriv(); if( app.activeDocs.length == 0) { app.alert( "Please have the bookmarks file open before launching Bookmarker." ); return; } if( app.activeDocs.length > 1 ) { app.alert( "Only the bookmarks file should be open when you launch Bookmarker.\n" + "Please close other files and try again." ); return; } if( BMdoc != app.activeDocs[0] ) BMdoc = app.activeDocs[0]; if( app.viewerVersion >= 7 ) app.endPriv(); var prefix; do { prefix = app.response( "How do tab filenames begin (before the tab number)?\n" + "(You can later use a different prefix for sub-tabs of bold tabs.)", "Prefix", "tab" ); } while( !prefix ); do { var r = app.response( "How many digits are in the greatest bookmark numbers, not including letters?\n" + "(Filenames must be padded consistently with zeros.)", "Digits", BMdigits ); BMdigits = parseInt( r, 10 ); } while( !BMdigits ); BMleadnum = ( app.alert( 'Do the tabs have a leading number? (e.g. "1.1", "1-1")'+ '\nIf so, filenames should take the form "tab01_01.pdf"', 2, 2 ) == ALERTYES ); BMhierarchy = ( app.alert( "Are tabs arranged hierarchically?\n" + '(e.g. tab "1" under tab "A" links to tabA01.pdf)', 2, 2 ) == ALERTYES ); var proc = app.alert( "Process linked files?", 2, 3 ); if( proc == CANCEL ) return; proc = ( proc == ALERTYES ); var clear, clone, networkDoc = null; if( proc ) { clear = ( app.alert( "Clear existing bookmarks from linked files?", 2, 2 ) == ALERTYES ); clone = ( app.alert( "Clone bookmarks to linked files?\n" + "(Only the links created by Bookmarker will be preserved!)", 2, 2 ) == ALERTYES ); if( app.alert( "Would you like a copy for the network, contained in one PDF?", 2, 2 ) == ALERTYES ) { do { var name=app.response( "Enter the name of a file containing just the title and instruction pages.", "File for system disk", '' ); if( name == '' ) break; if( !name ) return; if( name.indexOf('.') == -1 ) name += ".pdf"; try { networkDoc = app.openDoc( name, BMdoc ); } catch(e) { app.alert( '"'+name+'" not found.' ); } } while( !networkDoc ); if( networkDoc && networkDoc.numPages > 20 ) { if( app.alert( "This file appears to contain more than just the title and instruction pages."+ "\nAre you sure you'd like to append the tab files to it?", 2, 2 ) == ALERTNO ) { app.alert( "In that case, delete all but the title and instruction pages from this file, "+ "save, close, and re-run Bookmarker.", 3 ); return; } } } } BMtabs = 0; console.clear(); assignBookmarks( BMdoc.bookmarkRoot, prefix, null, true ); if( !proc ) { app.alert( BMtabs + " bookmarks were found and linked.", 3 ); console.show(); return; } if( !precheckBM() ) return; if( networkDoc ) { networkDoc.bookmarkRoot.remove(); BMdoctab = BMcurtab = 0; cloneBMTree( BMdoc.bookmarkRoot, networkDoc.bookmarkRoot, BMnetwmarks ); } var e = procBMfiles( clear, clone, networkDoc ); if( e == BMtabs ) app.alert( e+" bookmarks were found and linked successfully, " + "and their respective files have been given titles.", 3 ); else if( e > 0 ) app.alert( 'The bookmark titled "'+BMmarks[e].name+'" appears to be invalid.' ); else app.alert( -e + " bookmarks appear to be invalid." ); } // INITIALIZAION SCRIPT if( app.viewerVersion >= 5 ) app.addMenuItem({ cName: "ABA Bookmarker", cParent: "Tools", nPos: 0, cExec: "runBookmarker();" }); else app.alert( "ABA Bookmarker requires Acrobat version 6 or later." ); if( app.viewerVersion >= 7 ) app.trustedFunction( runBookmarker );[/i][/i][/i][/i][/i][/i][/i][/i][/i]