[JS] Menu Added via Scripting Moves

I've been able to sucessfully add items to the InDesign menu thanks in part to Marijan Tompa's (tomaxxi) blog post http://indisnip.wordpress.com/2010/08/08/create-customized-menu/
My test code (below) creates a new menu, and sucessfully adds two menu items plus a submenu. The submenu is causing me problems. When you first launch InDesign it's created in the proper place (in the middle of the menu). But when you relaunch InDesign, the submenu moves to the top of the menu and never goes back to it's proper position farther down in the menu where it was the first time InDesign was launched.
I've searched high and low in this forum, the web and InDesign's documentation and can't figure out how to keep it from moving (I want the menu to be farther down the menu, not at the top). I hope one of you kind souls will help me to control the position of the submenu (and have it stay there across launches).
Thanks in advance!
Dan
Here's the code I'm working with. This is saved as testMenu.jsx in the Scripts > startup scripts folder.
P.S. I'm testing this in CS5.5 currently, but ideally this solution should work in CS3 and later.
#targetengine "myTestMenu"
var myFolder = Folder(app.activeScript.path);
myFolder = myFolder.parent + '/Scripts Panel/';
var menuItem1Handler = function( /*onInvoke*/ ){
  app.doScript(File(myFolder + 'MyTest1.jsx'));
var menuItem2Handler = function( /*onInvoke*/ ){
  app.doScript(File(myFolder + 'MyTest2.jsx'));
menuInstaller()
function menuInstaller() {
  var menuItem1T = "My Menu Item 1",
       menuItem2T = "My Menu Item 2",
       menuT = "MyTestMenu",
             subT = "Sub Menu",
       subs = app.menus.item("$ID/Main").submenus, sma, mnu;
  var refItem = app.menus.item("$ID/Main").submenus.item("$ID/&Layout");
  subMenu1 = app.scriptMenuActions.item(menuItem1T);
  if( subMenu1 == null ) {
          subMenu2 = app.scriptMenuActions.add(menuItem1T);
  subMenu2 = app.scriptMenuActions.item(menuItem2T);
  if( subMenu2 == null ) {
          subMenu2 = app.scriptMenuActions.add(menuItem2T);
  subMenu2.eventListeners.add("onInvoke", menuItem2Handler);
  mnu = subs.item(menuT);
  if( mnu == null ) {
            mnu = subs.add(menuT, LocationOptions.after, refItem);
  mnu.menuItems.add(subMenu1);
  mnu.menuSeparators.add();
  subsSubs = app.menus.item( '$ID/Main' ).submenus.item( menuT ).submenus;
  mnuSubMenu = subsSubs.item( subT );
  if( mnuSubMenu == null ) {
          mnuSubMenu = subsSubs.add( subT);
  mnu.menuItems.add(subMenu2);

Hey, Marc: I'm going to be sort of blunt. Your code is hard for most people to read because it uses Javascript idioms they are entirely unfamiliar with, which don't make a lot of sense to people not really familiar with the language. And that's what most people here are. Let's take a walk through it:
(function(/*obj|undefined*/HOST)
The comment itself is confusing. Actually, it's even confusing to me.
    HOST || (HOST=$.global);
Tbe || idiom is confusing. Most people don't know what it means offhand.
    // Prevent the current (startup) script from being uselessly rerun
    if( HOST[$.engineName] )
        alert( "This script is automatically executed at startup. You shouldn't run it manually." );
Well, this isn't confusing, but I think it's bad. One of the important things to do is to test what happens when the menus already exist, and that's easiest to do by rerunning the script.
    var MENU_NAME = "My Test Menu",
All caps for a function-local variable? Even using all caps for a globally scoped variable (Crockford) is confusing, but for a function-scope variable? That confuses me!
        FEATURES = [
            { caption: "My Menu Item 1", fileName: 'File-One.jsx', subName: "" },
Use of Objects is justified here, but they are probably confusing.
        FEATURE_LOCATION_PATH = (function()
Anonymous functions...definitely confusing! I'm also not sure what the point of this function heere is. Why not execute the code directly
on the next line?
            try{ f=app.activeScript; }
            catch(_){ f=File(_.fileName); }
Variables named "_"? Confusing!
And this is why anonymous functions are confusing! Not much to be done about it, but why use one where you don't need to. It's not like we're polluting the global namespace here.
    while( i-- )
Use of a while loop is a totally legitimate style choice, but I think it's typically less readable than a for loop. YMMV, of course!
        t = FEATURES[i];
I'm horribly guilty of this, but single-letter variable names are not the most readable.
            (t.action = app.scriptMenuActions.add( t.caption )).
                addEventListener('onInvoke', f);
More parentheses imply more mental gymnastics to understand. Breaking this into two lines,
with t.action=addEventListener... would help readability.
  var s,
        n = FEATURES.length,
        subs = {},
        sub = null;
Wait, a mid-function var block? Gasp! What's up with that? Crockford's right on this. One var statement and all at the top.
I am not sure why we're initializing sub to null -- what's wrong with the good old undefined? This probably doesn't qualify as confusing.
    for( i=0 ; i < n ; ++i )
Caching FEATURES.length in n is good for performance, but it probably doesn't matter here, and makes it more confusing to read. Not by much, but let's say half a confusion point. I would also say that "++i" is harder to read than "i++", maybe to the tune of 0.1 confusion-points, but maybe that's just me. YMMV Extremely.
        sub = (s=t.subName) ?
            ( subs[s] || (subs[s]=mnu.submenus.add( s, LO_END )) ) :
            mnu;
The ternary conditional operator, ?:, is pretty much always hard to read. And it's worse with short-circuit or-ing, ||, or three close-parens in rapid succession. Of course ?: tends to promote extra () as it almost always becomes ()?(): so...
And then it's worth re-emphasizing, basically nobody understands the anonymous function paradigm .
So there we have it, that's why I think your code is confusing to most readers.
(On the other hand Dan's final code ignores my recommendation and still has those abysmal ==null tests in there. What's up with that? )

Similar Messages

  • Can document links be added via scripting?

    Can we add document links through scripting on Master Agreement header page? We are trying to mass update document links for about 3000+ records and hence I need to create a script (one time task) that can add these values on MA header page.
    I am trying to create the document link defintion as follows:
    DocumentLinkDefinitionIBeanIfc dld = (DocumentLinkDefinitionIBeanIfc)
    TypeFactory.createObjectReference(620);
    dld.setDisplayName("Test");
    dld.setInternalName("Test");
    dld.setLinkClassId(509);
    dls.setSystemDefined(new
    Boolean(false));
    dld.setLinkDirectionType(new DocLinkDirectionTypeEnumType(3));
    dld.setLinkDefinitionType(new DocLinkDefinitionTypeEnumType(3));
    and then set this document link defintion to Document Link Bean as follows:
    DocumentLinkIBeanIfc dl = (DocumentLinkIBeanIfc)
    TypeFactory.createObjectReference(509);
    dl.setExtRefDoc("99999");
    dl.setExtRefLine("900");
    dl.setLinkDefinitionObjRef(dld);
    But this is giving me error.
    Let me know if I am doing something wrong.
    Any help will be appreciated.
    -Regards,
    Bindu Sharma

    Hi,
    I create the document link definition between two agreements (variables doc and otherAgreement) using this code:
    documentLinkDef = documentLinkDefHome.findUnique("FCI-CONTRACT RELATED");
    newDocLink = doc.documentLinkList.create();
    newDocLink.linkDefinitionType = new DocLinkDefinitionTypeEnumType(1);
    newDocLink.linkDefinitionObjRef = documentLinkDef.objectReference;
    newDocLink.LinkDocObjRef = otherAgreement.objectReference;
    doc.documentLinkList.add(newDocLink);
    Hope this is helpful
    Francisco

  • How do I enable a Java plug-in via script that was just added to the blocklist?

    I need to enable Java 6u29 that was just added to the blocklist via script because there are several thousand end-nodes involved. Also, I am constrained to Firefox 3.6 due application compatibility issues.

    Probably the only or easiest way to remove or disable the blocklist of older Java versions would be to disable blocklisting by locking the extensions.blocklist.enabled to false via a mozilla.cfg file.<br />
    You are already running a no longer supported Firefox 3.6.x version that won't receive updates.
    You can use a mozilla.cfg file in the Firefox program folder to lock prefs or specify new (default) values.
    Place a file local-settings.js in the defaults\pref folder where you also find the file channel-prefs.js to specify using mozilla.cfg.
    pref("general.config.filename", "mozilla.cfg");
    pref("general.config.obscure_value", 0); // use this to disable the byte-shift
    See:
    *http://kb.mozillazine.org/Locking_preferences
    You can use these functions in mozilla.cfg:
    defaultPref(); // set new default value
    pref(); // set pref, but allow changes in current session
    lockPref(); // lock pref, disallow changes
    lockPref("extensions.blocklist.enabled", false);
    *http://kb.mozillazine.org/extensions.blocklist.enabled

  • Adding Instances via script

    I am really stummped. When adding an instance of an object to a form is done via script is it at all possible to do so even when the form element's min count is set to none at design time?
    I am trying to programmatically add an element when I hit a button like this:
    subform.detail.item.occur.min = "1"; // Is it possible to target nested subforms like this?
    subform.presence = "visible";
    subform, detail and item are subforms stacked on the main form. subform's visibility is hidden while detail and item are visible. only item is a repeating element with it's min count set to none.
    Where exactly should the event trigger? Is it impossible since occur should be placed on the template:ready event. Any help is much appreciated.

    If you set the minimum occurances of a subform to 0, without changing the initial occurances to 1, and their is no data to warrant the subform being there it won't be there. So simply setting it to visible will do nothing because it's not there. You'd have to use the instanceManager to actually create an instance of the subform.. something like:
    subform.detail._item.addInstance(true);
    Chris
    Adobe Enterprise Developer Support

  • Any Advice for 4:3 and 16:9 Menu DVD Authoring / Scripting?

    Hi all,
    Working on my first DVD with both 4:3 and 16:9 menus. I was wondering if anyone has advice, pointers, things to watch out for, tips, etc...
    I want it to be completely automated so I am using scripts to check SPRMS, jump to menus depending, etc and so far so good. But I am encountering a few issues and sure there will be more.
    Here's a question - this is a music concert DVD and each song is a chapter in a track. I have the menu button for each chapter assigned to the Select A Song menu and that track's button is selected.
    How can I keep this functionality but also keep the 4:3/16:9 menu ability? Do I need to write a script for each chapter marker?
    Thanks everybody.
    Jason

    That sure is easier, thanks. I might just finish via scripting to figure it all out but if something doesn't work it's real good to have this way.
    I guess the only drawback is not being able to fully utilize the 16:9 screen real estate. It's probably worth it for most cases.
    Thanks,
    Jason

  • AE appends my filename when setting up a render queue output filename via scripting

    I wrote a script that imports quicktimes and creates comps from them and adds them to the render queue. I'm running into an issue where files with certain names get appended when adding them to the queue. I believe it has something to do with the "." in the name. For example a quicktime named "filename_v25.140504.mov" is used to create a comp named "filename_v25.140504_test_01". This comp is then add to the render queue using the script below.
    var myRQItem = proj.renderQueue.items.add(renderComp);
    var myFile = new File(renderLocation.toString() + "/" + renderComp.name);
    myRQItem.outputModules[1].file = myFile;
    The filename it becomes "filename_v25.mov". It appears to be stripping everything after the last ".". This becomes a problem when I have several comps with names like: "filename_v25.140504_test_01", "filename_v25.140504_test_02", "filename_v25.140504_test_03" etc... since they all get added as "filename_v25.mov".
    Has anyone ran into this issue? Any solutions? Thanks!
    BTW I'm using CC on a mac running 10.9

    I haven't run into that particular issue, but what code are you using to create the comp based on the QuickTime file?  Can you replace the "." with a "_" when the comp is created?  If you can get ahold of the file name as a string, you could split it on the "." character then join the returned array with the "_" character. 
    --Arie

  • ITunes Music Locations - controlling workstations remotely via script?

    I do storage administration at a company with over 2000 users scattered across the globe. Predictably, at least have use iTunes. We redirect the "My Documents" folder to a network location to force the backup of critical project data. This creates a huge problem for us. iTunes defaults to using the My Music folder in My Documents. This means we are storing and backing up at least 1TB of music.
    I have found that iTunes stores its configuration in xml files in the application data directory in the user profile. I cannot readily figure out where in this file the location is recorded.
    Has anyone confronted this problem, and if so, is there a way to control iTunes installs remotely to set the music folder location, via script, GPO or anything at all?

    The library location is indeed stored in the iTunesPrefs.xml file. Look for the key "iTunes Library Location:1".
    But I have a script that almost does what you want. Here is the perl source:
    http://home.comcast.net/~teridon73/itunesscripts/itunesopenlibrary.txt
    Here is a compiled EXE for it:
    http://home.comcast.net/~teridon73/itunesscripts/itunesopenlibrary.zip
    Anyway, the script basically works by setting the library location to a path that you pass to it. It does so by updating the iTunesPrefs.xml file. This file is very small, so you shouldn't need to worry about it!
    Of course, the script only works if the iTunesPrefs.xml file already exists. It would be nice if you could include a template iTunesPrefs.xml in your new user creation/login script. If the path is the same for every user, well, then you're done I guess.
    If not, you can run the script to set the path to what you really want it to be.
    Existing users are a different story. You can run my script to change the library location, of course. But then you also have to move their existing library file and their music back to that location. Well, you don't have to; you can make the users do it themselves! Also, I don't know if that will work as I haven't tested it.
    I haven't fully explained everything, but I don't have time right now. I hope at least I've given you some ideas. Of course the optimum solution is an Apple-provide GPO you could use. You can try asking apple for it via either a bugreport (if you have an ADC account), or the feedback page for iTunes:
    http://www.apple.com/feedback/itunesapp.html
    Rob

  • Embedding full-text index via Script

    Hello Everyone,
    is there possibility to create and embed full-text index into my very long document via scripting Acrobat Pro? I've searched scripting API and there are objects like catalog or index, but both have only several methods and no embeding is mentioned there. Any help is appreciated. Thank you in advance.
    Jan

    try67 wrote:
    You're better off using a real authoring application like InDesign or Word.
    Thanks, but from this statement I am not sure if we are talking about the same thing. I mean index for full-text search - allowing to get immediate results after entering the search phrase, without any delay and (often quite slow) processing of the whole content. Now it is possible to embed it via Acrobat menu. I am asking whether this action has any equivalent in scripting API. I'd like to automate this process as now I have to do it manually via GUI (but luckily for the limited number of documents only).

  • How to get name of the slicer via script

    Hi Gurus,
    I was wondering if we could get the name of the slicer added in IR Query section, via script ??
    That is, I have a bqy connecting to Essbase OLAP.
    Now I am adding a slicer in OLAP Section via script.
    For Ex : ActiveDocument.Sections["Query2"].Slicers.Add('Market.Gen3,Market' , 'Market.LA')
    Now,for some reason, I wanted to retrieve the name of the slicer I added and assign it to a variable. Is this possible ?? I couldn't see any option for this. Please help me out if any one has done this before ?
    Thank You,
    Aji

    Sethil,
    Use your date(let us say Date1) instead of sy-datum.
    CALL FUNCTION 'MONTH_NAMES_GET'
    EXPORTING
    LANGUAGE = SY-LANGU
    IMPORTING
    RETURN_CODE =
    TABLES
    MONTH_NAMES = itab_month
    EXCEPTIONS
    MONTH_NAMES_NOT_FOUND = 1
    OTHERS = 2
    IF SY-SUBRC <> 0.
    MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
    WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
    ENDIF.
    READ TABLE itab_month
    WITH KEY MNR = date1+4(2).
    itab_month-LTX will contain the value you are looking for
    Good luck
    Raghava

  • Tracking menus and buttons via scripting

    I have a main menu page with a few submenus. I want to write a prescript to store a GPRM that tells me what submenu the user has chosen. So far I have...
    the 2 buttons have values of 1024 and 2048 in the SPRM 8.
    prescript for main menu-
    mov GPRM 0, SPRM 8
    div GPRM 0, 1024
    Remote control Menu button script-
    Jump Return to last button-menu1 if(GPRM 0=2)
    Jump Return to last button-menu2 if(GPRM 0=0)
    Scripts for returning to the highlighted button on the respective menu-
    Jump Return to last button-menu1 if(GPRM 1=2)
    Jump Return to last button-menu1 if(GPRM 1=2)
    Jump Return to last button-menu1 if(GPRM 1=3)
    Jump Return to last button-menu1 if(GPRM 1=4)
    Prescript for the track (uses GPRM1 to return to the highlighted button)-
    mov GPRM 1, SPRM 8
    div GPRM1, 1024
    If anybody knows what I'm doing wrong or if i'm overcomplicating things. Please let me know! Thanks

    I usually avoid using pre-scripts in DVDSP because they can interfere with automatic button selection.
    I would simply store the SRPM 8 values in your GPRM on the way to whatever track you are playing. I can't remember if switching VTSes will clear the value of SPRM8 - if not, you can just load SPRM 8 before jumping to the menu.
    Use a stand-alone script with the jump commands specifying the buttons to highlight - be sure to include a simple jump command at the end just in case no valid value winds up in your GPRM.
    SPRM8 can be stored independently of which menu you were on last, so you may also want to use a GPRM to track the menu.
    So each time you jump to a menu, the target will acutally be a script that looks something like this:
    1. Check "whichmenu" GPRM, if returning to the same menu last visited, skip over step 2 to button selection steps, starting with line 4.
    1. Set "whichmenu" GPRM
    3. Jump to menu (default button)
    4. mov SPRM8 to GPRM for "whichbutton"
    5. div "whichbutton"
    6. jump to button 1 on menu if..
    7. jump to button 2 if...
    etc...
    specifying a button on a menu acutally uses the pre-command available for that menu, and usually overrides any pre-script you assign in DVDSP. I don't know how this would act if the button selection is specified in a pre-script.
    Hope this helps -
    Max Average

  • ODI 11g - Work Repository Creation via Script

    Hi!
    Do you have any suggestions how to create work repositories via script?
    My idea is to create all database objects in the schema for the new work repository and insert the repository specific information into the tables
    - SNP_REM_REP (master repository)
    - SNP_CONNECT (master reppository)
    - SNP_LOC_REPW (work repository)
    Am i missing something?
    Thanks in advance & kind regards
    Michael

    Why do you want to do it this way ?
    I dont think your idea is going to work as there are 87 other tables (maybe not all of them) in Work Rep that need to be populated. And only the Work repository creation menu in the Topology would do it for you. There are relationship among those tables that need to be satisfied.
    What version are you on ? In 11g you can write Java code to do the things I mentioned above. Whatever you can click and do in 10g can be done using Java programming in 11g.

  • Adding a script to every topic in an existing WebHelp project

    I've got WebHelp (RH8, but could upgrade if necessary) running on Apache.
    What are my options for adding a script (probably PHP) to every topic?
    In the past, with other HATs, I've put stuff like that in master pages and in skins.
    From a comment in http://forums.adobe.com/message/3939811 I get the impression that nothing I do to a master page will affect existing topics?
    How about skins?
    Any other options besides running a script to make global changes to the source files or output files?
    Obviously if I define the script globally I'd need to use variables or replaceable parameters or the like in the script to customize it for each page. Is Robo helpful for that or should I be looking to the Apache environment for those values?

    Hi there
    Okay... Master Pages... Topic Templates... They are essentially the same thing. RoboHelp 8 began calling them Master Pages.
    For starters, do we want to use Master Pages to create new topics with? Or do we want to define something inside the Master Page and apply it to existing topics?
    My assumption is that you already have topics and simply wish to associate a Master Page with them.
    When you define a Master Page in RoboHelp 8 or 9, it will contain a Body placeholder. Whatever is inside the Body placeholder will end up being copied into any new topics you create that use the Master Page. But that's where it ends with stuff in the Body placeholder. After you create the topic, changes to the Body placeholder inside the Master Page *ARE NOT POPULATED* into the topics created from the Master Page. So you may change the Master Page substantially and the topics associated with it will remain unaffected.
    Note that you may also use a Master Page to populate Headers and Footers across existing topics. You have to do this by editing the Master Page and clicking View > Header or View > Footer in order to bring them into view. And once you do this, you may populate them with information. And using Master Pages in this fashion *DOES* allow subsequent changes to the Master Page to be populated across all topics associated with the Master Page.
    The problem here is this. You are wanting to use the latter feature to populate additional content across topics. So far so good. But you also have a need to make that content customized to each topic, no? And if that's the case, you won't be able to use Master Pages to maintain that content. I suppose you might put it in a Master Page initially just to get the code copied to all topics. But when you make changes to it to individualize it on a per topic basis, RoboHelp will pop up a warning advising the topic content is different and it will ask you what you want to do. Update the Master Page so ALL topics associated see the changed code? Or disconnect from the Master Page and leave your changes as you wish inside the topic.
    Another issue with this is that based on your other post, you need some PHP code above the topic content in a place that occurs before the HTML page is even defined. And that one may prove tricksy to implement. I suppose you might use what I suggested earlier to get the code in the topic, but you will still need to carefully hand edit each topic and move the code to where it should go.
    Hopefully this was helpful... Rick
    Helpful and Handy Links
    RoboHelp Wish Form/Bug Reporting Form
    Begin learning RoboHelp HTML 7, 8 or 9 within the day!
    Adobe Certified RoboHelp HTML Training
    SorcerStone Blog
    RoboHelp eBooks

  • Background saving via script?  CS6/CC?

    Any suggestions out there for getting script to save a file, in the background?
    When you have your preferences set ON to  Edit > Preferences > File handling > Save In Background, and you save a file by selecting File > SaveAs   ... the file saves in the background so you can continue working.  Great! 
    ...BUT...
    When you do that same action via script... activeDocument.saveAs() I get an annoying progress bar,  which inhibits being able to work while the save is running.   This makes an autosave script that is supposed to silently run, saving files in the background every few minutes while I work, kinda useless.
    Any ideas on how to turn that progress bar dialog off?   So Photoshop behaves the same as if I selected SaveAs in the menu??
    I Do have app.displayDialogs = DialogModes.NO;  but it seems to do no good.
    suggestions welcome.

    Thanks for the reply Davide,
    Yes, I've noticed when I run the save process via ANY other way,  (regular action run, DOM ExtendScripted, Action Manger scripted, AS3 CS6)  - it always has the progress bar.
    This just seems to be one of those things that I just can't do automatically the same way as if you just pushed "Cntrl-S". Save in Background - is a great feature.  Now if only it could be done through automation...   Anyone else have any luck?

  • Control BEx Analysis Grid context menu entries via VBA

    Hey Forum,
    I have kind of a tricky question for you. I want to control BEx Analysis Grid context menu entries via VBA, namely the Expand Hierarchy Node function when I right click on a Hierarchy node entry.
    Does anyone know how to access this function via VBA?
    I also thought about adding a BEx button and access it via VBA but I am lacking the correct Button Parameters to expand/collapse a hierarchy node.
    Anyone has a tipp for me?
    Thanks,
    R.

    Hello, DDrazdou and All too
    Did you have any information about requested function?
    I need to call binded transaction in R\3, and meanwhile, I just write wrapping functional module in the R\3, and making RFC call from VBA...
    It seems to work fine, but may be the better(standart) way is posible.
    with best regards, Alex.

  • Sort by Name via script

    Hi everybody,
    I would appreciate if someone could give some clue to sort by name the
    Paragraph Styles, Character Styles, Object Styles and Swatches panels
    via script.
    Thank you all in advance.
    Edson Furman
    [email protected]

    For sorting styles I have used the script listed below -- works in CS3 and CS4 though it's been a while since I last tried. It could be coded more elegantly but it always worked fine as it is. It doesn't take into account any style groups -- I don't know what happens if your documents contain any so you'd better not try.
    As to swatches, these are not so easy to sort. There was some discussion about this at either of these sites:
    http://www.hilfdirselbst.ch/gforum/gforum.cgi?jump=forum%3D4
    http://indesign-faq.de/
    Peter
    #target indesign
    sort_par_styles (app.documents[0]);
    sort_char_styles (app.documents[0]);
    sort_obj_styles (app.documents[0]);
    function sort_par_styles (doc)
        var string_array = sort_par_names (doc);
        for (var i = 0; i < string_array.length; i++)
            doc.paragraphStyles.item (string_array[i]).move (
                LocationOptions.after, doc.paragraphStyles[i+2])
    function sort_par_names (doc)
      var array = doc.paragraphStyles.everyItem().name;
      array.shift (); array.shift ();  // exclude [No p.] and [Basic p/]
      return array.sort (case_insensitive);
    function sort_char_styles (doc)
        var string_array = sort_char_names (doc);
        for (var i = 0; i < string_array.length; i++)
            doc.characterStyles.item (string_array[i]).move (
                LocationOptions.after, doc.characterStyles[i+1])
    function sort_char_names (doc)
      var array = doc.characterStyles.everyItem().name;
      array.shift ();  // exclude [None]
      return array.sort (case_insensitive);
    function sort_obj_styles (doc)
        var string_array = sort_obj_names (doc);
        for (var i = 0; i < string_array.length; i++)
            doc.objectStyles.item (string_array[i]).move (
                LocationOptions.after, doc.objectStyles[i+4])
    function sort_obj_names (doc)
      var array = doc.objectStyles.everyItem().name;
      array.shift (); array.shift (); array.shift ();  array.shift (); // exclude  [None], [Basic Graphics Frame], [Basic Text Frame], [Basic Grid]
      return array.sort (case_insensitive);
    function case_insensitive (a, b)
      return a.toLowerCase() > b.toLowerCase()

Maybe you are looking for