4 Replies Latest reply on Feb 20, 2014 4:00 PM by sparksaflying

    Updatable city map with directory list


      Here's the scenario. A city has a business district that needs a printable aerial view map (llustrated) with numbers indicating each business. These numbers will correspond to a key/directory that will list the number and name of business. The map is updated frequently as businesses come and go. I want the map to renumber itself when making edits. For example, if the business marked as "4." needs to be deleted from the map, the rest of the indicators would renumber themselves and the directory would then renumber itself as well (so that the list doesn't have a missing number). Is this feesible within InDesign?

        • 1. Re: Updatable city map with directory list
          Trevorׅ Adobe Community Professional

          You can do it easily

          1) add the map to the page (THE LABELS MUST NOT BE PART OF THE MAP)

          2) create a map label paragraph style "Map Labels" and include in it a numbered list "Map Lables List"

          _Untitled-57 @ 75%_2014-02-20_08-23-48.png

          3) Setup an object style call it Map Labels set the paragraph style to Map Labels,

          Set the fill, corner etc. options as desired.


          4) Make a text Frame and Put in it the name of the place and apply the Map Labels object style to it.

          5) Use copy and Paste to add a label for all the places you need.

          5B) Important! and a bit tough do the copy and paste in the Ideal Order of the list

          In the example below Europe was coppied last, so it go numbered 3, a more desired order (left to right, top to bottom) might have been USA, Europe, Africa


          6) set up a new object style and set the colors to None call it Invisible

          7) After you have finished labeling all the place names select all the page items (Ctrl / Comand A) and run this little snippet


          var selection = app.selection,
                l = selection.length;
          while (l--) if (selection[l].hasOwnProperty ('contents')   && selection[l].appliedObjectStyle = "Map Labels") {
              selection[l].name = selection[l].contents;
              selection[l].insertLabel("Map Labels", "1");
          app.activeWindow.activePage.insertLabel("Map", "1"); // Label Page for future reference


          You now have named all your textFrames and they can be refered to asfor example myDoc.textFrames.itemByName("USA")

          And you can identify them as map lables by using textFrame[x].extractLabel("Map Labels") == 1;

          8) Save a copy of the doc in case you mess up in the future.

          9) Make a character style "Place names" and apply in your document  only on the names you want labeled on your map.

          i.e. you have have a some text(s) somewhere in the document

          The USA is realy ......

          Africa is ......

          10 Now each time you have different references run the following script and the map labels will be updated


          _Untitled-57 @ 125%_2014-02-20_10-47-59.png




          // Labeling script
          // by Trevor (www.creative-scripts.com coming soonish custom and readymade scripts for adobe indesign and other products)
          app.doScript("labelMap()", ScriptLanguage.javascript, undefined, UndoModes.ENTIRE_SCRIPT, "Lable Map");
          function labelMap() {
              var doc = app.activeDocument;
                          app.findTextPreferences = app.changeTextPreferences = null;
                          app.findTextPreferences.appliedCharacterStyle = "Place Names";
              var myPageId = checkForObjectByLabel(doc.pages, "Map");
              if (myPageId === false) {alert("No Map\rBye"); exit();};
              myPageId = myPageId[0];
              var mapPage = doc.pages.itemByID(myPageId),
                    mapLabels = checkForObjectByLabel (mapPage.textFrames, "Map Labels"),
                    l = mapLabels.length, label, lableFrame;
              while  (l--) {
                  lableFrame = mapPage.textFrames.itemByID(mapLabels[l]);
                  if (!lableFrame.isValid) continue;
                  lableFrame.applyObjectStyle (doc.objectStyles.itemByName("Invisible"), true);
                  lableFrame.contents = "";
              // Find names
              var myFinds = doc.findText();
              l = myFinds.length;
              while (l--) {
                  label = myFinds[l].contents;
                  lableFrame = mapPage.textFrames.itemByName(label);
                  if (!lableFrame.isValid) continue;
                  lableFrame.contents = label;
                  lableFrame.applyObjectStyle (doc.objectStyles.itemByName("Map Labels"), true);
          function checkForObjectByLabel (obj, label, from, to) {
              from = from || 0;
              if (obj .hasOwnProperty('length')) obj = obj[0];
              var parent = obj.parent;
              var co = obj.constructor.name;
              co = co[0].toLowerCase() + co.substr (1, co.length) + "s";    
              var objects = (from != undefined && to != undefined) ? parent[co].itemByRange (from, to) : parent[co].everyItem();
              var objectsLabels = objects.extractLabel(label);
              var reg = /1/g;
              objectsLabels = ("," + objectsLabels.join()).replace (/,1/g, "1");
              reg.lastIndex = 0;
              var n = 0;
              var ids = [];
              var found = true;
              while (found = reg.exec (objectsLabels)) ids[n++] = parent[co] [(reg.lastIndex = found.index + 1) - 1 + from].id;
              return (ids.length > 0) && ids;
          • 2. Re: Updatable city map with directory list
            Marc Autret Level 4

            Coming from http://forums.adobe.com/message/6138731#6138731


            Hi Trevor,


            Great contribution!


            Regarding checkForObjectByLabel() I see a few minor issues:


            1. The line

            co = co[0].toLowerCase() + co.substr (1, co.length) + "s";

            won't work in every case. (Think about Story => stories, etc.)


            2. The test

            (from != undefined && to != undefined)

            is not relevant. What you need instead is the syntax 'undefined' != typeof x

            However, a stronger check is to make sure that from and to are both integers, as follows:

            (from===~~from && to===~~to )


            Now I must confess I haven't investigated on the use you make of /1/g in browsing objectLabels, but I suppose this is just related to this specific project (?)




            • 3. Re: Updatable city map with directory list
              Trevorׅ Adobe Community Professional

              Hi Marc,


              Thanks for feedback, really appreciated.


              I was aware that the function in it's current form wouldn't work for every case. If needed then one could check the parent hasOwnProperty (x) and if not try the different plural forms 'es' as in swatches change the 'y' to 'ies' as in stories would probably cover almost all of them.  Depending on the need making the function more or less generic.


              My real doubt was if there was a better way to access the object type so the object could be referred to without playing string games.


              I like your stricter integer test of the from and to but I'm a bit confused about what's wrong with the from != undefined test in contrast to the 'undefined' != typeof from


              The purpose of the test is to check if the function call includes values for from and to (use itemByRange) or whether they are undefined (use everyItem) and I can't see a case where the test would fail.


              I could have just used itemByRange (from || 0, to || -1) maybe that ways better, hard to tell I didn't think of it before, one would have to know how the peformace of range (0,-1) compares to everyItem(), I have some vague memory that there might be cases where the range fails to get everyItem().


              Regarding the /1/g method I think it's a very effective way of checking for labels.


              Let's say I have a document (which I have) with about 28,000 rectangles in it and let's say I have 3 labeled ones, if I were to go the conventional path then I would loop though them checking for the label (SLOW) so instead I can use insertLabel ("label name", "1") the "1" can be any single character then by using

              "," everyItem().extractLabel("label name").join(",") + "," (the "," can be any single character other than 1) I'll get a long string that look something like ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, ,,,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,


              Using the /1/g is going to give me the index of the rectangles which I can then get the ID's from for future reference. (could also just return and array of the object themselves and not the id's)


              I developed the method for an idleTask that I needed to be as quick as possible I haven't done the speed test but I think the regex's are processed very fast, you should know from your indexMatic script.


              I have a script that generates a document which I check to see is not open from a previously occasion I can label it and in no time see if it's there (1 is found) or not (no 1's)


              With the little snippet at the top the map textFrames are labeled and there for the second script to process for the years to come.


              Sorry for babbling, once again thanks,



              • 4. Re: Updatable city map with directory list
                sparksaflying Level 1

                Wow. This is interesting. Looks like I have my work cut out for me I'll try to run through this and see what comes of it. Thank you very much for the hearty replies!