Edittext .characters property in CS2

Does the .characters property work in CS2?
dlg.add ("statictext", undefined, "Search: ");
var someEditText = dlg.add ("edittext", undefined, "");
someEditText.characters = 50;
The third line doesn't seem to change the width as would be expected.
Is there a better way around this rather than adding spaces to the empty string of the editText to pad it out a bit?

This should work...
someEditText.preferredSize = [50, 20];

Similar Messages

  • Is there a way to change the LUt extension form .CUBE to .cube. on export. TX

    Is there a way to change the LUt extension form .CUBE to .cube. on export with this script in photoshop For MAC:
    Chris Cox wrote:
    The file extensions are written by the export plugin.  (which incidentally has a comment that two studios wanted all caps extensions, but I failed to write down which ones in the comments)
    To change the filenames, you'd want to add something at the end of doExportLUTs() that uses the supplied path and substitutes the desired extensions, then renames the file.
    Thank you
    // Export Color Lookup Tables automation in JavaScript
    // IN_PROGRESS - why can't ColorSync Utility open any profile with a grid of 160 or larger?
    // 150 works, 160 fails -- sent samples in email to Apple on Nov 8, 2013; they are investigating
    // DEFERRED - right to left filenames (Arabic) come out wrong because of appending "RGB" and file extensions
    // This seems to be a bug in JavaScript's handing of strings, not sure we can solve it easily.
    // It might possibly be handled by checking bidi markers in UTF8 stream and adding custom handling for appending text/extensions.
    @@@BUILDINFO@@@ ExportColorLookupTables.jsx 1.0.0.0
    // BEGIN__HARVEST_EXCEPTION_ZSTRING
    <javascriptresource>
    <name>$$$/JavaScripts/ExportColorLookupTables/Menu=Color Lookup Tables...</name>
    <menu>export</menu>
    <enableinfo>true</enableinfo>
    <eventid>9AA9D7D6-C209-494A-CC01-4E7D926DA642</eventid>
    </javascriptresource>
    // END__HARVEST_EXCEPTION_ZSTRING
    #target photoshop
    const appUIState = app.displayDialogs;
    app.displayDialogs = DialogModes.NO; // suppress all app dialogs
    app.bringToFront(); // make Photoshop the frontmost app, just in case
    // on localized builds we pull the $$$/Strings from a .dat file
    $.localize = true;
    // from Terminology.jsx
    const classApplication = app.charIDToTypeID('capp');
    const classProperty = app.charIDToTypeID('Prpr');
    const enumTarget = app.charIDToTypeID('Trgt');
    const eventGet = app.charIDToTypeID('getd');
    const eventSet = app.charIDToTypeID('setd');
    const kcolorSettingsStr = app.stringIDToTypeID("colorSettings");
    const kDither = app.charIDToTypeID('Dthr');
    const keyTo = app.charIDToTypeID('T   ');
    const typeNULL = app.charIDToTypeID('null');
    const typeOrdinal = app.charIDToTypeID('Ordn');
    const kFloatWindowStr = app.stringIDToTypeID("floatWindow");
    const typePurgeItem = app.charIDToTypeID('PrgI');
    const enumClipboard = app.charIDToTypeID('Clpb');
    const eventPurge = app.charIDToTypeID('Prge');
    const keyExportLUT = app.charIDToTypeID( "lut " );
    const keyFilePath = app.charIDToTypeID( 'fpth' );
    const keyDescription = app.charIDToTypeID( 'dscr' );
    const keyCopyright = app.charIDToTypeID( 'Cpyr' );
    const keyDataPoints = app.charIDToTypeID( 'gPts' );
    const keyWriteICC = app.charIDToTypeID( 'wICC' );
    const keyWrite3DL = app.charIDToTypeID( 'w3DL' );
    const keyWriteCUBE = app.charIDToTypeID( 'wCUB' );
    const keyWriteCSP = app.charIDToTypeID( 'wCSP' );
    const kScriptOptionsKey = "9AA9D7D6-C209-494A-CC01-4E7D926DA642"; // same as eventID above
    const sGridMin = 7; // these must match the slider range defined in the dialog layout
    const sGridMax = 256;
    const sGridDefault = 32;
    // our baseline UI configuration info
    var gSaveFilePath = ""; // overwritten by document path
    var gDescription = ""; // overwritten by document name
    var gCopyright = ""; // "Adobe Systems Inc., All Rights Reserved";
    var gGridPoints = sGridDefault;
    var gDoSaveICCProfile = true;
    var gDoSave3DL = true;
    var gDoSaveCUBE = true;
    var gDoSaveCSP = true;
    gScriptResult = undefined;
    // start doing the work...
    main();
    app.displayDialogs = appUIState; // restore original dialog state
    gScriptResult; // must be the last thing - this is returned as the result of the script
    function readOptionsFromDescriptor( d )
      if (!d)
      return;
      if (d.hasKey(keyFilePath))
      gSaveFilePath = d.getString( keyFilePath ); // will be overridden by UI
      if (d.hasKey(keyDescription))
      gDescription = d.getString( keyDescription ); // will be overridden always
      if (d.hasKey(keyCopyright))
      gCopyright = d.getString( keyCopyright );
      if (d.hasKey(keyDataPoints))
      var temp = d.getInteger( keyDataPoints );
      if (temp >= sGridMin && temp <= sGridMax)
      gGridPoints = temp;
      if (d.hasKey(keyWriteICC))
      gDoSaveICCProfile = d.getBoolean( keyWriteICC );
      if (d.hasKey(keyWrite3DL))
      gDoSave3DL = d.getBoolean( keyWrite3DL );
      if (d.hasKey(keyWriteCUBE))
      gDoSaveCUBE = d.getBoolean( keyWriteCUBE );
      if (d.hasKey(keyWriteCSP))
      gDoSaveCSP = d.getBoolean( keyWriteCSP );
    function createDescriptorFromOptions()
      var desc = new ActionDescriptor();
      desc.putString( keyFilePath, gSaveFilePath ); // will be overridden by UI
      desc.putString( keyDescription, gDescription ); // will always be overridden by document name
      desc.putString( keyCopyright, gCopyright );
      desc.putInteger( keyDataPoints, gGridPoints );
      desc.putBoolean( keyWriteICC, gDoSaveICCProfile );
      desc.putBoolean( keyWrite3DL, gDoSave3DL );
      desc.putBoolean( keyWriteCUBE, gDoSaveCUBE );
      desc.putBoolean( keyWriteCSP, gDoSaveCSP );
      return desc;
    function doExportUI()
      // DEFERRED - it might be nice to be able to run without UI
      //  Right now we can't, but someone could modify the script if they so desire
      const sDescription = localize("$$$/AdobeScript/Export3DLUT/Description=Description:");
      const sCopyright = localize("$$$/AdobeScript/Export3DLUT/Copyright=Copyright:");
      const sQuality = localize("$$$/AdobeScript/Export3DLUT/Quality=Quality");
      const sGridPoints = localize("$$$/AdobeScript/Export3DLUT/GridPoints=Grid Points:");
      const sFormatsToSave = localize("$$$/AdobeScript/Export3DLUT/Formats=Formats");
      const sOpenButton = localize("$$$/JavaScripts/psx/OK=OK");
      const sCancelButton = localize("$$$/JavaScripts/psx/Cancel=Cancel");
      const strTextInvalidType = localize("$$$/JavaScripts/Export3DLUT/InvalidType=Invalid numeric value. Default value inserted.");
      const strTextInvalidNum = localize("$$$/JavaScripts/Export3DLUT/InvalidNum=A number between 7 and 256 is required. Closest value inserted.");
      const strNoExportsSelected = localize("$$$/JavaScripts/Export3DLUT/NoExportTypesSelected=No export types were selected.");
      const strExportPrompt = localize("$$$/JavaScripts/Export3DLUT/ExportColorLookup=Export Color Lookup");
      const strUntitledLUT = localize("$$$/JavaScripts/Export3DLUT/UntitledLUTFilename=untitled.lut");
      const sSaveICC = localize("$$$/AdobeScript/Export3DLUT/ICCProfile=ICC Profile");
      // these are not localized, since they refer to file format extensions
      const sSave3DL = "3DL";
      const sSaveCUBE = "CUBE";
      const sSaveCSP = "CSP";
      // strings similar to JPEG quality
      const sPoor = localize("$$$/AdobeScript/Export3DLUT/Poor=Poor");
      const sLow = localize("$$$/AdobeScript/Export3DLUT/Low=Low");
      const sMedium = localize("$$$/AdobeScript/Export3DLUT/Medium=Medium");
      const sHigh = localize("$$$/AdobeScript/Export3DLUT/High=High");
      const sMaximum = localize("$$$/AdobeScript/Export3DLUT/Maximum=Maximum");
      const ui = // dialog resource object
      "dialog { \
      orientation: 'row', \
      gp: Group { \
      orientation: 'column', alignment: 'fill', alignChildren: 'fill', \
      description: Group { \
      orientation: 'row', alignment: 'fill', alignChildren: 'fill', \
      st: StaticText { text:'Description:' }, \
      et: EditText { characters: 30, properties:{multiline:false}, text:'<your description here>' } \
      copyright: Group { \
      orientation: 'row', alignment: 'fill', alignChildren: 'fill', \
      st: StaticText { text:'Copyright:' }, \
      et: EditText { characters: 30, properties:{multiline:false}, text:'<your copyright here>' } \
      qual: Panel { \
      text: 'Quality', \
      orientation: 'column', alignment: 'fill', alignChildren: 'fill', \
      g2: Group { \
      st: StaticText { text:'Grid Points:' }, \
      et: EditText { characters:4, justify:'right' } \
      drp: DropDownList {alignment:'right'} \
      sl: Slider { minvalue:7, maxvalue:256, value: 32 }, \
      options: Panel { \
      text: 'Formats', \
      orientation: 'column', alignment: 'fill', alignChildren: 'left', \
      ck3DL: Checkbox { text:'3DL', value:true }, \
      ckCUBE: Checkbox { text:'CUBE', value:true } \
      ckCSP: Checkbox { text:'CSP', value:true } \
      ckICC: Checkbox { text:'ICC Profile', value:true } \
      gButtons: Group { \
      orientation: 'column', alignment: 'top', alignChildren: 'fill', \
      okBtn: Button { text:'Ok', properties:{name:'ok'} }, \
      cancelBtn: Button { text:'Cancel', properties:{name:'cancel'} } \
      const titleStr = localize("$$$/AdobeScript/Export3DLUT/DialogTitle/ExportColorLookupTables=Export Color Lookup Tables");
      var win = new Window (ui, titleStr ); // new window object with UI resource
        // THEORETICALLY match our dialog background color to the host application
        win.graphics.backgroundColor = win.graphics.newBrush (win.graphics.BrushType.THEME_COLOR, "appDialogBackground");
      // poor, low, medium, high, max
      var MenuQualityToGridPoints = [ 8, 16, 32, 64, 256 ];
      function GridPointsToQualityMenuIndex( num )
      var menu = MenuQualityToGridPoints;
      var menuItems = menu.length;
      if (num <= menu[0])
      return 0;
      if (num >= menu[ menuItems-1 ])
      return (menuItems-1);
      for (var i = 0; i < (menuItems-1); ++i)
      if ((num >= menu[i]) && (num < menu[i+1]))
      return i;
      return 0; // just in case of a logic failure
      // insert our localized strings
      var drop = win.gp.qual.g2.drp; // for easier typing
      drop.add('item', sPoor ); // 0
      drop.add('item', sLow ); // 1
      drop.add('item', sMedium ); // 2
      drop.add('item', sHigh ); // 3
      drop.add('item', sMaximum ); // 4
      drop.selection = drop.items[2]; // Medium
      win.gp.description.st.text = sDescription;
      win.gp.copyright.st.text = sCopyright;
      win.gp.qual.text = sQuality;
      win.gp.qual.g2.st.text = sGridPoints;
      win.gp.options.text = sFormatsToSave;
      win.gp.options.ck3DL.text = sSave3DL;
      win.gp.options.ckCUBE.text = sSaveCUBE;
      win.gp.options.ckCSP.text = sSaveCSP;
      win.gp.options.ckICC.text = sSaveICC;
      win.gButtons.okBtn.text = sOpenButton;
      win.gButtons.cancelBtn.text = sCancelButton;
      // set starting parameters
      win.gp.description.et.text = gDescription;
      win.gp.copyright.et.text = gCopyright;
      win.gp.options.ckICC.value = gDoSaveICCProfile;
      win.gp.options.ck3DL.value = gDoSave3DL;
      win.gp.options.ckCUBE.value = gDoSaveCUBE;
      win.gp.options.ckCSP.value = gDoSaveCSP;
      // global flag/hack to keep the UI pretty
      var gGlobalPreventChanges = false;
      with (win.gp.qual)
      sl.value = gGridPoints;
      g2.et.text = gGridPoints;
      drop.selection = drop.items[ GridPointsToQualityMenuIndex(gGridPoints) ];
      // global flag is ugly, but recursive change calls are uglier
      g2.et.onChange = function () {  if (gGlobalPreventChanges) { return; }
      gGlobalPreventChanges = true;
      var val = Number(this.text);
      this.parent.parent.sl.value = val;
      drop.selection = drop.items[ GridPointsToQualityMenuIndex(val) ];
      gGlobalPreventChanges = false; };
      sl.onChanging = function () {   if (gGlobalPreventChanges) { return; }
      gGlobalPreventChanges = true;
      var val = Math.floor(this.value);
      this.parent.g2.et.text = val;
      drop.selection = drop.items[ GridPointsToQualityMenuIndex(val) ];
      gGlobalPreventChanges = false; };
      // DEFERRED - we should also set the value if the same menu item is selected again (reset)
      // but the JSX toolkit doesn't support that
      drop.onChange = function()
      if (gGlobalPreventChanges) { return; }
      gGlobalPreventChanges = true;
      var theSelection = this.selection.text;
      if (theSelection != null) { // only change if selection made
      var theSelectionIndex = this.selection.index;
      var newGridPoints = MenuQualityToGridPoints[ theSelectionIndex ];
      win.gp.qual.g2.et.text = newGridPoints;
      win.gp.qual.sl.value = newGridPoints;
      gGlobalPreventChanges = false;
      win.onShow = function ()
      this.qual.sl.size.width = 128;
      this.layout.layout(true);
      win.gButtons.cancelBtn.onClick = function () { this.window.close(2); };
      // validate inputs when the user hits OK
        var gInAlert = false;
      win.gButtons.okBtn.onClick = function ()
      if (gInAlert == true)
      gInAlert = false;
      return;
      var gridText = win.gp.qual.g2.et.text;
      var w = Number(gridText);
      var inputErr = false;
      if ( isNaN( w ) )
      if ( DialogModes.NO != app.playbackDisplayDialogs )
      gInAlert = true;
      alert( strTextInvalidType );
      gInAlert = false;
      win.gp.qual.g2.et.text = sGridDefault;
      win.gp.qual.sl.value = sGridDefault;
      drop.selection = drop.items[ GridPointsToQualityMenuIndex(sGridDefault) ];
      return false;
      if ( (w < sGridMin) || (w > sGridMax) )
      if ( DialogModes.NO != app.playbackDisplayDialogs )
      gInAlert = true;
      alert( strTextInvalidNum );
      gInAlert = false;
      if ( w < sGridMin)
      inputErr = true;
      drop.selection = drop.items[ GridPointsToQualityMenuIndex(sGridMin) ];
      win.gp.qual.g2.et.text = sGridMin;
      win.gp.qual.sl.value = sGridMin;
      return false;
      if ( w > sGridMax)
      inputErr = true;
      drop.selection = drop.items[ GridPointsToQualityMenuIndex(sGridMax) ];
      win.gp.qual.g2.et.text = sGridMax;
      win.gp.qual.sl.value = sGridMax;
      return false;
      if (inputErr == false)
      win.close(true);
      return;
      win.center(); // move to center the dialog
      var ret = win.show();  // dialog display
      if (2 == ret)
      return false; // user cancelled
      // user hit OK, copy values from dialog
      gDescription = win.gp.description.et.text;
      gCopyright = win.gp.copyright.et.text;
      gGridPoints = win.gp.qual.sl.value;
      gDoSave3DL = win.gp.options.ck3DL.value;
      gDoSaveCUBE = win.gp.options.ckCUBE.value;
      gDoSaveCSP = win.gp.options.ckCSP.value;
      gDoSaveICCProfile = win.gp.options.ckICC.value;
      // if no files are going to be saved, then we have zero work to do
      if ((false == gDoSaveICCProfile) && (false == gDoSave3DL) &&
      (false == gDoSaveCUBE) && (false == gDoSaveCSP) )
      // tell the user that no formats were selected
      alert( strNoExportsSelected );
      gScriptResult = 'cancel'; // quit, returning 'cancel' (dont localize) makes the actions palette not record our script
      return false;
      // prompt user for directory and output base filename
      // default to directory and filename of current document
      var currentDocumentPath
      try
      // if the file has no path (not saved), then this throws
      var documentPath = app.activeDocument.fullName.fsName; // Get the OS friendly file path and name
      documentPath = documentPath.replace(/\....$/,''); // remove extension, if there is one
      documentPath = documentPath + ".lut"; // add dummy extension
      currentDocumentPath = File ( documentPath );
      catch (e)
      // if there was no document path, default to user's home directory
      var defaultName = "~/" + strUntitledLUT;
      currentDocumentPath = File(defaultName);
      var fname = currentDocumentPath.saveDlg(strExportPrompt);
      if (fname == null)
      return false;
      gSaveFilePath = fname.fsName;
      return true;
    function doExportLUTs( path )
      const keyUsing     = charIDToTypeID( 'Usng' );
      const eventExport = charIDToTypeID( 'Expr' );
      var desc = new ActionDescriptor();
      var desc2 = new ActionDescriptor();
      desc2.putString( keyFilePath, path );
      desc2.putString( keyDescription, gDescription );
      desc2.putInteger( keyDataPoints, gGridPoints );
      // assemble the full copyright string, if needed
      var copyrightAssembled = gCopyright;
      if (gCopyright != "")
      var theDate = new Date();
      // the year is from 1900 ????
      var theYear = (theDate.getYear() + 1900).toString();
      // Localization team says to just use the year
      var dateString = theYear;
      copyrightAssembled = localize("$$$/JavaScripts/Export3DLUT/Copyright=(C) Copyright ") + dateString + " " + gCopyright;
      desc2.putString( keyCopyright, copyrightAssembled );
      // select output format
      desc2.putBoolean( keyWriteICC, gDoSaveICCProfile );
      desc2.putBoolean( keyWrite3DL, gDoSave3DL );
      desc2.putBoolean( keyWriteCUBE, gDoSaveCUBE );
      desc2.putBoolean( keyWriteCSP, gDoSaveCSP );
        desc.putObject( keyUsing, keyExportLUT, desc2 );
      try
      var resultDesc = executeAction( eventExport, desc, DialogModes.NO );
      catch (e)
      if ( e.number != 8007 ) { // don't report error on user cancel
      var str = localize("$$$/JavaScripts/Export3DLUT/ExportLUTFailed=Unable to run the Export Color Lookup plugin because ");
      alert( str + e + " : " + e.line );
      gScriptResult = 'cancel'; // quit, returning 'cancel' (dont localize) makes the actions palette not record our script
      return false;
      return true;
    function doRenderGrid( points )
      // call the grid rendering plugin to do the work
        const keyRenderGrid = charIDToTypeID( "3grd" );
      const keyDataPoints2 = charIDToTypeID( 'grdP' );
      var args = new ActionDescriptor();
        args.putInteger( keyDataPoints2, points);
      try
      var result = executeAction( keyRenderGrid, args, DialogModes.NO );
      catch (e)
      if ( e.number != 8007 ) { // don't report error on user cancel
      var str = localize("$$$/JavaScripts/Export3DLUT/RenderGridFailed=Unable to render color grid because ");
      alert( str + e + " : " + e.line );
      gScriptResult = 'cancel'; // quit, returning 'cancel' (dont localize) makes the actions palette not record our script
      return false;
      return true;
    function resizeDocumentInPixels( width, height )
      var myDocument = app.activeDocument;
      var originalRulerUnits = app.preferences.rulerUnits;
      app.preferences.rulerUnits = Units.PIXELS;
      myDocument.resizeCanvas( width, height, AnchorPosition.MIDDLECENTER)
      app.preferences.rulerUnits = originalRulerUnits;
    function GetColorSettings()
      var desc1 = new ActionDescriptor();
      var ref1 = new ActionReference();
      ref1.putProperty( classProperty, kcolorSettingsStr );
      ref1.putEnumerated( classApplication, typeOrdinal, enumTarget );
      desc1.putReference( typeNULL, ref1 );
      var result = executeAction( eventGet, desc1, DialogModes.NO );
      var desc2 = result.getObjectValue( kcolorSettingsStr );
      return desc2;
    function GetColorConversionDitherState()
      var settings = GetColorSettings();
      if (settings.hasKey(kDither))
      return settings.getBoolean( kDither );
      else
      return null;
    function ConvertTo16Bit()
      const eventConvertMode = charIDToTypeID( 'CnvM' );
      const keyDepth = charIDToTypeID( 'Dpth' );
      var modeDesc16Bit = new ActionDescriptor();
      modeDesc16Bit.putInteger( keyDepth, 16 );
      var result = executeAction( eventConvertMode, modeDesc16Bit, DialogModes.NO );
    // state = true or false
    function SetColorConversionDither( state )
      var desc1 = new ActionDescriptor();
      var ref1 = new ActionReference();
      ref1.putProperty( classProperty, kcolorSettingsStr );
      ref1.putEnumerated( classApplication, typeOrdinal, enumTarget );
      desc1.putReference( typeNULL, ref1 );
      var desc2 = new ActionDescriptor();
      desc2.putBoolean( kDither, state );
      desc1.putObject( keyTo, kcolorSettingsStr, desc2 );
      executeAction( eventSet, desc1, DialogModes.NO );
    function PurgeClipboard()
      var desc1 = new ActionDescriptor();
      desc1.putEnumerated( typeNULL, typePurgeItem, enumClipboard );
      var result = executeAction( eventPurge, desc1, DialogModes.NO );
    // This helps us avoid resizing existing document views in tabbed document mode.
    // This is new functionality, and will not work in older Photoshop versions.
    function MoveDocumentToNewWindow()
      var desc1 = new ActionDescriptor();
      var result = executeAction( kFloatWindowStr, desc1, DialogModes.NO );
    function main()
      try
      var tempDoc = null;
      var tempDoc2 = null;
      // do basic troubleshooting first
      // make sure there is a document
      if (!app.activeDocument)
        gScriptResult = 'cancel'; // quit, returning 'cancel' (dont localize) makes the actions palette not record our script
      return;
      // check the document mode
      var mode = app.activeDocument.mode;
      if (mode != DocumentMode.RGB
      && mode != DocumentMode.LAB
      && mode != DocumentMode.CMYK)
      var str = localize("$$$/JavaScripts/Export3DLUT/UnsupportedColorMode=Could not export Color Lookup Tables because only RGB, LAB, and CMYK color modes are supported.");
      alert(str);
        gScriptResult = 'cancel'; // quit, returning 'cancel' (dont localize) makes the actions palette not record our script
      return;
      // check the document depth, for safety
      var depth = app.activeDocument.bitsPerChannel; // an object, not a number - why? I have no idea...
      var bitsPerChannel = 1;
      if (depth == BitsPerChannelType.EIGHT)
      bitsPerChannel = 8;
      else if (depth == BitsPerChannelType.SIXTEEN)
      bitsPerChannel = 16;
      else if (depth == BitsPerChannelType.THIRTYTWO)
      bitsPerChannel = 32;
      else
      var str = localize("$$$/JavaScripts/Export3DLUT/UnsupportedImageDepth=Could not export Color Lookup Tables because only 8, 16, and 32 bits/channel are supported.");
      alert(str);
        gScriptResult = 'cancel'; // quit, returning 'cancel' (dont localize) makes the actions palette not record our script
      return;
      // Check layer types: background plus adjustments only
      // For now, don't check each layer - a multiply solid layer still works as a color adjustment, as does selective blending
      // Users will get odd results from other layer types (layer masks, pixel layers, etc.)
      try
      app.activeDocument.backgroundLayer.visible = true;
      catch (e)
      if (activeDocument.layers.length == 1)
      alert( localize("$$$/JavaScripts/Export3DLUT/NoAdjustmentLayers=Could not export Color Lookup Tables because this document has no adjustment layers.") );
      else
      alert( localize("$$$/JavaScripts/Export3DLUT/NoBackground=Could not export Color Lookup Tables because this document has no background.") );
        gScriptResult = 'cancel'; // quit, returning 'cancel' (dont localize) makes the actions palette not record our script
      return;
      // look for last used params via Photoshop registry, getCustomOptions will throw if none exist
      try
      var desc = app.getCustomOptions(kScriptOptionsKey);
      readOptionsFromDescriptor( desc );
      catch(e)
      // it's ok if we don't have any existing options, continue with defaults
      // set some values from the document
      gDescription = app.activeDocument.name;
      // ask the user for options, bail if they cancel at any point
      if ( doExportUI() == false)
        gScriptResult = 'cancel'; // quit, returning 'cancel' (dont localize) makes the actions palette not record our script
      return;
      // we're good to go, so save our parameters for next time
      app.putCustomOptions(kScriptOptionsKey, createDescriptorFromOptions() );
      // remove file extension from filePath, if there is one
      gSaveFilePath = gSaveFilePath.replace(/\....$/,'');
      // calculate the size of image we need
      var width = gGridPoints * gGridPoints;
      var height = gGridPoints;
      if (mode == DocumentMode.CMYK)
      height = gGridPoints*gGridPoints;
      // duplicate the user document so we don't mess it up in any way
      tempDoc = app.activeDocument.duplicate("temporary");
      // make the temporary document active
      app.activeDocument.name = tempDoc;
      // to avoid resizing existing document views in tabbed mode
      MoveDocumentToNewWindow();
      // convert 8 bit documents to 16 bit/channel for improved quality of merged adjustments
      if (bitsPerChannel == 8)
      ConvertTo16Bit();
      depth = BitsPerChannelType.SIXTEEN;
      // resize the temporary canvas to our target size
      resizeDocumentInPixels( width, height )
      // select background layer
      tempDoc.activeLayer = tempDoc.backgroundLayer;
      // render lookup base grid
      var worked = doRenderGrid( gGridPoints );
      if (worked != true)
      tempDoc.close( SaveOptions.DONOTSAVECHANGES );
      return; // error should have already been shown, and there is not much we can do
      // do not flatten here -- the export automatically gets flattened data
      // and we may need layers for LAB->RGB conversion below
      // export the chosen formats
      worked = doExportLUTs( gSaveFilePath );
      if (worked != true)
      tempDoc.close( SaveOptions.DONOTSAVECHANGES );
      return; // error should have already been shown, and there is not much we can do
      // for LAB documents to export 3DLUT (which are inherently RGB), we have to do additional work
      // As a bonus, this works for CMYK as well!
      if ( mode != DocumentMode.RGB )
      var filePath = gSaveFilePath + "RGB";
      var oldDitherState = GetColorConversionDitherState();
      try
      SetColorConversionDither(false);
      const targetProfileName = "sRGB IEC61966-2.1";
      // new document temp2 in sRGB, matching depth of original
      var originalRulerUnits = app.preferences.rulerUnits;
      app.preferences.rulerUnits = Units.PIXELS;
      tempDoc2 = app.documents.add( width, gGridPoints, 72, "temp2",
      NewDocumentMode.RGB, DocumentFill.WHITE,
      1.0, depth, targetProfileName );
      app.preferences.rulerUnits = originalRulerUnits;
      // make the new doc active
      app.activeDocument.name = tempDoc2;
      // to avoid resizing existing document views in tabbed mode
      MoveDocumentToNewWindow();
      // insert grid
      worked = doRenderGrid( gGridPoints );
      if (worked == true)
      tempDoc2.selection.selectAll();
      tempDoc2.activeLayer = tempDoc2.backgroundLayer;
      tempDoc2.selection.copy();
      tempDoc2.close( SaveOptions.DONOTSAVECHANGES );
      tempDoc2 = null;
      // make sure temp1 is active
      app.activeDocument.name = tempDoc;
      // resize for RGB grid
      resizeDocumentInPixels( width, gGridPoints );
      tempDoc.selection.selectAll();
      tempDoc.paste(true);
      PurgeClipboard(); // so we don't leave an odd, large item on the clipboard
      tempDoc.selection.deselect();
      tempDoc.flatten();
      // convert temp1 to sRGB
      tempDoc.convertProfile( targetProfileName, Intent.RELATIVECOLORIMETRIC, true, false );
      // export the chosen formats
      worked = doExportLUTs( filePath );
      // at this point we still have to clean up, even if the call failed, so fall through
      else
      tempDoc2.close( SaveOptions.DONOTSAVECHANGES );
      catch (e)
      if ( e.number != 8007 ) { // don't report error on user cancel
      var str = localize("$$$/JavaScripts/Export3DLUT/UnableToConvertRGB=Unable to convert image to RGB because ");
      alert( str + e + " : " + e.line );
      if (tempDoc2 != null) tempDoc2.close( SaveOptions.DONOTSAVECHANGES );
      gScriptResult = 'cancel'; // quit, returning 'cancel' (dont localize) makes the actions palette not record our script
      // always reset the dither state
      SetColorConversionDither( oldDitherState );
      PurgeClipboard(); // so we don't leave an odd, large item on the clipboard
      } // if not RGB
      // always close temp document without saving
      tempDoc.close( SaveOptions.DONOTSAVECHANGES );
      catch (e)
      if ( e.number != 8007 ) { // don't report error on user cancel
      var str = localize("$$$/JavaScripts/Export3DLUT/UnableToExport=Unable to export LUT because ");
      alert( str + e + " : " + e.line );
      // always close temp document without saving
      if (tempDoc != null) tempDoc.close( SaveOptions.DONOTSAVECHANGES );
      gScriptResult = 'cancel'; // quit, returning 'cancel' (dont localize) makes the actions palette not record our script

    Hi blabla12345,
    (untested and without warranty)
    replace this line:
    const sSaveCUBE = "CUBE";
    with this:
    const sSaveCUBE = "cube";
    Have fun

  • Convert old cs4 script to illustrator cc

    This is a big ask, but I found this script to remove redundant points at github.com/mekkablue/Glyphs-Scripts
    Each time I run, it seems to work, it shows how many points it has removed, but then illustrator crashes, with no kind of error notice.
    If I run it via extendscript toolkit it jumps to the following bit of code
    var docRef=app.activeDocument;
    I would really love to get this to work, if anyone is willing to help me.
      RemovetRedundantPoints.jsx
      A Javascript for Adobe Illustrator
      Author:
      Jim Heck
      [email protected]
      Purpose:
      Remove anchorpoints on selected path that are coincident in location.
      Finds and optionally removes redundant points from each selected PathItem.
      Useful for cleaning up after Offset Path and Outline Stroke commands in CS3.
      To Use:
      Select the paths, including compound paths to be affected. If no path is
      selected, the script will run for all paths in the document that are not
      locked. Run the script.
      Rights:
      This work is licensed under the Creative Commons Attribution 3.0 United States
      License. To view a copy of this license, visit
      http://creativecommons.org/licenses/by/3.0/us/
      or send a letter to Creative Commons, 171 Second Street, Suite 300,
      San Francisco, California, 94105, USA.
      Version History:
      1.8 120108 More fixes to the logic for keeping only a single point.
      The direction handles for the remaining point are now correctly calculated
      based on relative angle and distance to the original anchor to which a
      handle related. Also if a SMOOTH point is remaining, the angle of the
      two direction handles has been tweaked to be exactly 180 degrees for
      consistency with the definition of a SMOOTH point.
      1.7 120106 Change the way direction handles and PointType are handled
      when keeping only one point. Retract handles less than 0.5 points to keep
      consistent angles for SMOOTH point types. If keepLeadingPoint or
      keepTrailingPoint is specified, try to keep the PointType of that point.
      In the absence of other indicators, base PointType on the point (leading
      or trailing) that has an extended handle.
      1.6.1 090914 Tweak defaults to make sense for my work style
      1.6 090411 Fix a bug in creating a temporary path. Fix a bug in
      findRedundantPoints(), when searching backwards, the tolerance was always
      applied against the first point on the path instead of the adjacent point
      along the path. Change selection options so that there is more control over
      which points are processed on a given path. The new options allow for ignoring
      selection of points, restricting processing to only selected points, or
      processing redundant points if at least one of them is selected. Correct count
      of redundant points removed when both leading and trailing points retained.
      1.5 090404 Change default action to remove. Fix a major performance issue
      in the docGetSelectedPaths() routine. Searching through all the paths in very
      complex files takes a LONG time. Instead, search the document groups array.
      BETA: Lots of hacking on the removeRedundantPoints() routine to improve the
      look of the resulting curve when applied to the oxbow problem.
      1.4.1 090331 Fix a bug in removeRedundantPoints(), needed to compare absolute
      error to a tolerance. Also, loosen up the error criteria so less smooth
      points are mischaracterized as corners. Tolerance is now 0.02 radians,
      which is about 1.15 degrees. For some reason, the redundant points on
      arbitrary (non-geometric) outlined paths have lots of slop in the
      direction handles.
      1.4 090331 Add options to control which points are left on removal, leading,
      trailing or both. If neither is retained, the redundant point positions
      are averaged. If both are retained, intermediate points are removed, and
      inward facing control handles are synthesized (see comments below).
      Switched to using the atan2 function instead of atan for calculating theta.
      Fixed bugs in docGetSelectedPaths(). CompoundPathItem objects don't seem
      to have properly formed pathItems arrays when they contain what appear to
      be groups of paths. Also, layer objects can contain layers.
      1.3.1 090327 Limit user entered tolerance value to something sane.
      1.3 090327 Add user controls to specify a tolerance in points for identifying
      redundant points.
      1.2.3 090327 Improve results dialog verbiage.
      1.2.2 090326 Bug fix. Observe proper unlocking and locking order for
      handling of locked objects.
      1.2.1 090326 Minor bug fixes including, restricting selection only option
      to not be allowed with selection function.
      1.2 090326 Add option to remove only redundant points sets with at least one
      selected point. Fix broken option to remove locked redundant points.
      Add results dialog OK button.
      1.1 090325 Improve select action to work across selection or entire document.
      Handle nested layers in docGetSelectedPaths(). Clean whitespace.
      1.0.1 090325 Minor bug fix.
      1.0 090311 Initial release.
    * Function: getPairTheta
    * Description:
    * Return the angle relative to the X axis from the line formed between
    * two points, which are passed in as arguments. The angle is measured
    * relative to point A (as if A were relocated to the origin, and the angle
    * is measured to the X axis itself). The arguments are expected to be
    * arrays of two numbers (X, Y) defining the point. The return value is in
    * radians (PI to -PI)
    function getPairTheta(pairA,pairB){
      var deltaX=pairB[0]-pairA[0];
      var deltaY=pairB[1]-pairA[1];
      /*alert("deltaX="+deltaX+" deltaY="+deltaY);*/
      return(Math.atan2(deltaY, deltaX));
    * Function: getPairDistance
    * Description:
    * Return the distance between two points. The arguments are expected to be
    * arrays of two numbers (X, Y) defining the point. The return value is the
    * distance in units relative to the inputs.
    function getPairDistance(pairA,pairB){
      var deltaX=pairB[0]-pairA[0];
      var deltaY=pairB[1]-pairA[1];
      return(Math.sqrt((deltaX*deltaX)+(deltaY*deltaY)));
    * Function: findRedundantPoints
    * Description:
    * Find all sets of redundant points for the input path. A redundant point
    * is defined as one that has the same anchor location as a neighboring point.
    * The arguments are a path to work on, the tolerance in points to apply to
    * determine a point is redundant, and a boolean to indicate that only
    * groups of redundant points where at least one point is selected should
    * be considered. The return value is an Array of Arrays containing the
    * indicies of the redundant pathPoint objects found in the path.
    function findRedundantPoints(path, tolerance, anySelected, allSelected){
      var anchorDistance = 0;
      var redundantPointSets = new Array();
      var redundantPoint = new Array();
      var selectedRedundantPointSets = new Array();
      var selectedRedundantPoint = new Array();
      var i = 0;
      var j = 0;
      var k = 0;
      var index;
      var selected = false;
      if(path.pathPoints.length > 1) {
      * The first path point may be coincident with some at the end of the path
      * so we check going backwards first. Redundant points pushed on the
      * front of the array so they stay in order leftmost to rightmost.
      redundantPoint.push(0);
      index = 0;
      for (i=path.pathPoints.length-1; i>0; i--) {
      * Get distance and round to nearest hundredth of a point.
      * If points are closer than the tolerance, consider them
      * coincident.
      anchorDistance = getPairDistance(path.pathPoints[index].anchor, path.pathPoints[i].anchor);
      anchorDistance = roundToPrecision(anchorDistance, 0.01);
      if (anchorDistance < tolerance) {
      redundantPoint.unshift(i);
      else {
      break;
      index = i;
      * If we haven't used up all the points, start searching forwards
      * up to the point we stopped searching backwards. Test the
      * current point against the next point. If the next point matches push
      * its index onto the redundantPoint array. When the first one doesn't match,
      * check if the redundantPoint array has more than one index. If so add it
      * to the redundantPointSets array. Then clean the redundantPoint array
      * and push on the next point index.
      if(i > 0) {
      for (j=0; j<i; j++) {
      anchorDistance = getPairDistance(path.pathPoints[j].anchor, path.pathPoints[j+1].anchor);
      anchorDistance = roundToPrecision(anchorDistance, 0.01);
      if (anchorDistance < tolerance) {
      redundantPoint.push(j+1);
      else {
      if (redundantPoint.length > 1) {
      redundantPointSets.push(redundantPoint);
      redundantPoint = [];
      redundantPoint.push(j+1);
      * Push the last redundantPoint array onto the redundantPointSets array if
      * its length is greater than one.
      if (redundantPoint.length > 1) {
      redundantPointSets.push(redundantPoint);
      if (anySelected) {
      for (i=0; i<redundantPointSets.length; i++) {
      var currentPointSet = redundantPointSets[i];
      selected = false;
      for (j=0; j<currentPointSet.length; j++) {
      if (path.pathPoints[currentPointSet[j]].selected ==
      PathPointSelection.ANCHORPOINT) {
      selected = true;
      if (selected) {
      selectedRedundantPointSets.push(currentPointSet);
      else if (allSelected) {
      for (i=0; i<redundantPointSets.length; i++) {
      var currentPointSet = redundantPointSets[i];
      for (j=currentPointSet.length-1; j>=0; j--) {
      var currentPoint = path.pathPoints[currentPointSet[j]];
      if (currentPoint.selected == PathPointSelection.ANCHORPOINT) {
      selectedRedundantPoint.unshift(currentPointSet[j]);
      else {
      break;
      if (j > 0) {
      for (k=0; k<j; k++) {
      var currentPoint = path.pathPoints[currentPointSet[k]];
      if (currentPoint.selected == PathPointSelection.ANCHORPOINT) {
      selectedRedundantPoint.push(currentPointSet[k]);
      else {
      if (selectedRedundantPoint.length > 1) {
      selectedRedundantPointSets.push(selectedRedundantPoint);
      selectedRedundantPoint = [];
      if (selectedRedundantPoint.length > 1) {
      selectedRedundantPointSets.push(selectedRedundantPoint);
      selectedRedundantPoint = [];
      else {
      selectedRedundantPointSets = redundantPointSets;
      return(selectedRedundantPointSets);
    * Function: countRedundantPoints
    * Description:
    * Count the number of redundant points given a redundantPointSets array as
    * the first parameter.
    function countRedundantPoints(redundantPointSets, doKeepLeadingPoint, doKeepTrailingPoint) {
      var i = 0;
      var redundantPoints = 0;
      var pointsKept = 1;
      if (doKeepLeadingPoint && doKeepTrailingPoint) {
      pointsKept = 2;
      for (i=0; i<redundantPointSets.length; i++) {
      redundantPoints += redundantPointSets[i].length - pointsKept;
      return (redundantPoints);
    * Function: countSelectedPoints
    * Description:
    * Count the number of selected anchor points given a path as the first parameter.
    function countSelectedPoints(path) {
      var i = 0;
      var selectedPoints = 0;
      for (i=0; i<path.pathPoints.length; i++) {
      if (path.pathPoints[i].selected == PathPointSelection.ANCHORPOINT) {
      selectedPoints++;
      return (selectedPoints);
    * Function: removeRedundantPoints
    * Description:
    * Remove redundant points from a path input as the first parameter. The
    * second input parameter should be an array of arrays containing the
    * indicies of redundant points, as returned from function
    * findRedundantPoints(). From each set of indicies, the first point is
    * retained, and the subsequent points are removed from the path. Care is
    * taken to preserve the proper leftDirection and rightDirection handles,
    * as well as the proper PointType for the remaining point. Returns
    * the number of points removed.
    function removeRedundantPoints(path, redundantPointSets, keepLeadingPoint, keepTrailingPoint, keepAveragedPoint){
      var i = 0;
      var j = 0;
      var pointsToRemove = new Array();
      var tempLayer;
      var tempPath;
      * For each array of redundant point indicies in array redundantPointSets,
      * modify the leadingPoint to have all the properties needed to properly
      * describe the set of coincident points.
      for (i=0; i<redundantPointSets.length; i++) {
      var x = 0;
      var y = 0;
      var currentPointSet = redundantPointSets[i];
      var leadingPoint = path.pathPoints[currentPointSet[0]];
      var trailingPoint = path.pathPoints[currentPointSet[currentPointSet.length-1]];
      if (keepLeadingPoint && keepTrailingPoint) {
      * JAH 090401 REVISIT COMMENT WHEN DONE
      * If we are keeping two points, the leftDirection of the leading point
      * and rightDirection of the trailing point are already fixed. We have to
      * synthesize the inward facing handles, and choose pointType of the two points.
      * To allow easy manipultion of the inner handles without disturbing the fixed
      * handles, make the points PointType.CORNER. For the direction handles, make
      * them parallel to their respective paired handle, and extend them half the
      * distance between the two remaining points.
      var averagedPoint;
      var theta;
      var deltaX;
      var deltaY;
      var pairDistance;
      var leftDistance;
      var rightDistance;
      var firstRemovedIndex = 1;
      if (currentPointSet.length > 2) {
      averagedPoint = path.pathPoints[currentPointSet[1]];
      else {
      tempLayer = app.activeDocument.layers.add();
      tempLayer.name = "Temp";
      tempPath = tempLayer.pathItems.add();
      averagedPoint = tempPath.pathPoints.add();
      if( currentPointSet.length <= 2 || !keepAveragedPoint ) {
      * Use just the leading and trailing points. Create inward facing
      * direction handles for the two endpoints based on the relationship
      * of the angles between each endpoint and the average point.
      * For each endpoint, calcualte the angle of the endpoint to the
      * average point, and the endpoint to the other endpoint. Combine
      * the angles. The base angle for the inward facing direction handle
      * is the angle that points it towards the average point. Add to this
      * angle, a multiple of the difference between the angle just mentioned,
      * and the angle to the other endpoint. Adding this difference angle
      * will bias the curve towards the average point. Finally, set the
      * length of the direction handle as the distance from the endpoint
      * to the average point multiplied by a factor.
      var thetaAverage;
      var thetaPair;
      var tweakThetaToOppositeEndpoint = 1.0;
      var tweakPairDistance = 0.5;
      * Since the leading and trailing points will have direction handles pointing
      * in different directions, these points must be corner points by necessity.
      leadingPoint.pointType = PointType.CORNER;
      trailingPoint.pointType = PointType.CORNER;
      * Create new average point.
      for (j=0; j<currentPointSet.length; j++) {
      x += path.pathPoints[currentPointSet[j]].anchor[0];
      y += path.pathPoints[currentPointSet[j]].anchor[1];
      x /= currentPointSet.length;
      y /= currentPointSet.length;
      averagedPoint.anchor = Array(x, y);
      averagedPoint.leftDirection = Array( averagedPoint.anchor[0], averagedPoint.anchor[1]);
      averagedPoint.rightDirection = Array( averagedPoint.anchor[0], averagedPoint.anchor[1]);
      averagedPoint.pointType = PointType.CORNER;
      /* Calcualte new leading point rightDirection */
      pairDistance = getPairDistance(leadingPoint.anchor, averagedPoint.anchor);
      thetaAverage = getPairTheta(leadingPoint.anchor, averagedPoint.anchor);
      thetaPair = getPairTheta(leadingPoint.anchor, trailingPoint.anchor);
      theta = thetaAverage + tweakThetaToOppositeEndpoint * (thetaAverage - thetaPair);
      /*alert("thetaAverage="+thetaAverage+" thetaPair="+thetaPair" theta="+theta);*/
      deltaX = Math.cos(theta) * tweakPairDistance * pairDistance;
      deltaY = Math.sin(theta) * tweakPairDistance * pairDistance;
      leadingPoint.rightDirection = Array(leadingPoint.anchor[0]+deltaX, leadingPoint.anchor[1]+deltaY);
      /* Calcualte new trailing point leftDirection */
      pairDistance = getPairDistance(trailingPoint.anchor, averagedPoint.anchor);
      thetaAverage = getPairTheta(trailingPoint.anchor, averagedPoint.anchor);
      thetaPair = getPairTheta(trailingPoint.anchor, leadingPoint.anchor);
      theta = thetaAverage + tweakThetaToOppositeEndpoint * (thetaAverage - thetaPair);
      /*alert("thetaAverage="+thetaAverage+" thetaPair="+thetaPair" theta="+theta);*/
      deltaX = Math.cos(theta) * tweakPairDistance * pairDistance;
      deltaY = Math.sin(theta) * tweakPairDistance * pairDistance;
      trailingPoint.leftDirection = Array(trailingPoint.anchor[0]+deltaX, trailingPoint.anchor[1]+deltaY);
      else {
      * Use just the leading and trailing points, along with a third point added
      * at the average of all the removed points. This point will act to anchor
      * the curve at the average point. It will also allow the leading and
      * trailing points to be smooth points, allowing for a continuous
      * curve through them.
      * The inward facing direction handles for the two endpoints will be
      * shortened extensions of the outward facing direction handles for these
      * points. The length of the handles will be a multiple of the
      * distance from the direction handle to the average point.
      * For the average point, the direction handles will be parallel to the
      * angle formed by the angle between the two endpoints. The length
      * of the direction handles for this point will be a different multiple
      * of the length from each endpoint to the average point.
      var thetaAverage;
      var thetaPair;
      var tweakPairDistanceForAveraged = 0.5;
      var tweakPairDistanceForEndpoint = 0.25;
      * Since the leading and trailing points will have direction handles that
      * are parallel, make them smooth points.
      leadingPoint.pointType = PointType.SMOOTH;
      trailingPoint.pointType = PointType.SMOOTH;
      /* We will be keeping one more point, the averaged point. */
      firstRemovedIndex = 2;
      * Create new average point.
      for (j=0; j<currentPointSet.length; j++) {
      x += path.pathPoints[currentPointSet[j]].anchor[0];
      y += path.pathPoints[currentPointSet[j]].anchor[1];
      x /= currentPointSet.length;
      y /= currentPointSet.length;
      averagedPoint.anchor = Array(x, y);
      averagedPoint.leftDirection = Array( averagedPoint.anchor[0], averagedPoint.anchor[1]);
      averagedPoint.rightDirection = Array( averagedPoint.anchor[0], averagedPoint.anchor[1]);
      averagedPoint.pointType = PointType.SMOOTH;
      /* Calcualte new averaged point leftDirection */
      pairDistance = getPairDistance(leadingPoint.anchor, averagedPoint.anchor);
      theta = getPairTheta(leadingPoint.anchor, trailingPoint.anchor);
      /*alert("theta="+theta);*/
      if (theta > 0) {
      theta += Math.PI;
      else {
      theta += -Math.PI;
      deltaX = Math.cos(theta) * tweakPairDistanceForAveraged * pairDistance;
      deltaY = Math.sin(theta) * tweakPairDistanceForAveraged * pairDistance;
      averagedPoint.leftDirection = Array(averagedPoint.anchor[0]+deltaX, averagedPoint.anchor[1]+deltaY);
      /* Calcualte new averaged point rightDirection */
      pairDistance = getPairDistance(trailingPoint.anchor, averagedPoint.anchor);
      theta = getPairTheta(trailingPoint.anchor, averagedPoint.anchor);
      /*alert("theta="+theta);*/
      if (theta > 0) {
      theta += Math.PI;
      else {
      theta += -Math.PI;
      deltaX = Math.cos(theta) * tweakPairDistanceForAveraged * pairDistance;
      deltaY = Math.sin(theta) * tweakPairDistanceForAveraged * pairDistance;
      averagedPoint.rightDirection = Array(averagedPoint.anchor[0]+deltaX, averagedPoint.anchor[1]+deltaY);
      /* Calculate direction handles for leading and trailing points */
      pairDistance = getPairDistance(leadingPoint.anchor, trailingPoint.anchor);
      leftDistance = getPairDistance(leadingPoint.anchor, leadingPoint.leftDirection);
      if (leftDistance > 0) {
      theta = getPairTheta(leadingPoint.anchor, leadingPoint.leftDirection);
      /*alert("theta="+theta);*/
      if (theta > 0) {
      theta += Math.PI;
      else {
      theta += -Math.PI;
      pairDistance = getPairDistance(leadingPoint.anchor, averagedPoint.anchor);
      deltaX = Math.cos(theta) * tweakPairDistanceForEndpoint * pairDistance;
      deltaY = Math.sin(theta) * tweakPairDistanceForEndpoint * pairDistance;
      leadingPoint.rightDirection = Array(leadingPoint.anchor[0]+deltaX, leadingPoint.anchor[1]+deltaY);
      else {
      leadingPoint.rightDirection = leadingPoint.anchor;
      rightDistance = getPairDistance(trailingPoint.anchor, trailingPoint.rightDirection);
      if (rightDistance > 0) {
      theta = getPairTheta(trailingPoint.anchor, trailingPoint.rightDirection);
      if (theta > 0) {
      theta += Math.PI;
      else {
      theta += -Math.PI;
      pairDistance = getPairDistance(trailingPoint.anchor, averagedPoint.anchor);
      deltaX = Math.cos(theta) * tweakPairDistanceForEndpoint * pairDistance;
      deltaY = Math.sin(theta) * tweakPairDistanceForEndpoint * pairDistance;
      trailingPoint.leftDirection = Array(trailingPoint.anchor[0]+deltaX, trailingPoint.anchor[1]+deltaY);
      else {
      trailingPoint.leftDirection = trailingPoint.anchor;
      * Push all points other than the leading and trailing onto the pointsToRemove array
      * for later removal. We can't remove them while we are working with later sets.
      for (j=firstRemovedIndex; j<currentPointSet.length-1; j++) {
      pointsToRemove.push(currentPointSet[j]);
      else {
      * If we are only keeping one point, we will work with the leading point.
      * First, calculate the relative distances and angles of the direction handle for
      * the leadingPoint leftDirection handle and the trailingPoint rightDirection
      * handle. These values will be used to help properly construct the remaining
      * point.
      var leftDistance = getPairDistance(leadingPoint.anchor, leadingPoint.leftDirection);
      var rightDistance = getPairDistance(trailingPoint.anchor, trailingPoint.rightDirection);
      var leftTheta = getPairTheta(leadingPoint.anchor, leadingPoint.leftDirection);
      var rightTheta = getPairTheta(trailingPoint.anchor, trailingPoint.rightDirection);
      * If we are keeping the leadingPoint, calculate a relative rightDirection handle
      * based on the trailingPoint rightDistance and rightTheta. If we are keeping the
      * trailingPoint, copy its anchor and rightDirection handle to the leadingPoint,
      * and calculate a relative leftDirection handle based on the leadingPoint
      * leftDistance and leftTheta. If we are to keep neither leading or trailing point,
      * average the position of all the redundant points and calcuate direction handles
      * based on the appropriate values.
      if (keepLeadingPoint) {
      x = leadingPoint.anchor[0] + (Math.cos(rightTheta) * rightDistance);
      y = leadingPoint.anchor[1] + (Math.sin(rightTheta) * rightDistance);
      leadingPoint.rightDirection = Array(x, y);
      else if (keepTrailingPoint) {
      leadingPoint.anchor = trailingPoint.anchor;
      leadingPoint.rightDirection = trailingPoint.rightDirection;
      x = leadingPoint.anchor[0] + (Math.cos(leftTheta) * leftDistance);
      y = leadingPoint.anchor[1] + (Math.sin(leftTheta) * leftDistance);
      leadingPoint.leftDirection = Array(x, y);
      else {
      for (j=0; j<currentPointSet.length; j++) {
      x += path.pathPoints[currentPointSet[j]].anchor[0];
      y += path.pathPoints[currentPointSet[j]].anchor[1];
      x /= currentPointSet.length;
      y /= currentPointSet.length;
      leadingPoint.anchor = Array(x, y);
      x = leadingPoint.anchor[0] + (Math.cos(leftTheta) * leftDistance);
      y = leadingPoint.anchor[1] + (Math.sin(leftTheta) * leftDistance);
      leadingPoint.leftDirection = Array(x, y);
      x = leadingPoint.anchor[0] + (Math.cos(rightTheta) * rightDistance);
      y = leadingPoint.anchor[1] + (Math.sin(rightTheta) * rightDistance);
      leadingPoint.rightDirection = Array(x, y);
      * If the distance for a handle is less than half a point and rounds to zero,
      * retract that handle fully by setting that direction handle equal to the anchor
      * point. This will keep angles consistent for smooth points.
      if (Math.round(leftDistance) == 0) {
      leadingPoint.leftDirection = leadingPoint.anchor;
      if (Math.round(rightDistance) == 0) {
      leadingPoint.rightDirection = leadingPoint.anchor;
      * Handle the PointType in a minimal manner. If keeping the leadingPoint or keeping
      * the trailingPoint, keep the PointType of that point if possible. If both handles
      * are extended, measure the angles of the two direction handles. If both handles
      * have the same angle relative to the X axis within a tolerance, the PointType
      * can be SMOOTH, otherwise it must be CORNER. If the point type is SMOOTH, ensure
      * the direction handles are corrected to be exactly 180 degrees apart.
      * If not specifically keeping the leading or trailing point and only one handle is
      * extended, base the pointType on the the leadingPoint if only the left handle is
      * extended and the trailingPoint if only the right handle is extended. 
      if (Math.round(leftDistance) > 0 && Math.round(rightDistance) > 0) {
      var absdiff = Math.abs(leftTheta-rightTheta);
      var error = Math.PI - absdiff;
      /*alert("leftTheta="+leftTheta+" rightTheta="+rightTheta+" absdiff="+absdiff+" error="+error);*/
      if (Math.abs(error) < 0.02) {
      if (keepTrailingPoint) {
      leadingPoint.pointType = trailingPoint.pointType;
      else if (!keepLeadingPoint) {
      leadingPoint.pointType = PointType.SMOOTH;
      if (leadingPoint.pointType == PointType.SMOOTH) {
      if (keepTrailingPoint) {
      x = leadingPoint.anchor[0] + (Math.cos(Math.PI + rightTheta) * leftDistance);
      y = leadingPoint.anchor[1] + (Math.sin(Math.PI + rightTheta) * leftDistance);
      leadingPoint.leftDirection = Array(x, y);
      else {
      x = leadingPoint.anchor[0] + (Math.cos(Math.PI + leftTheta) * rightDistance);
      y = leadingPoint.anchor[1] + (Math.sin(Math.PI + leftTheta) * rightDistance);
      leadingPoint.rightDirection = Array(x, y);
      else {
      leadingPoint.pointType = PointType.CORNER;
      else if (keepTrailingPoint) {
      leadingPoint.pointType = trailingPoint.pointType;
      else if (!keepLeadingPoint && rightDistance > 0) {
      leadingPoint.pointType = trailingPoint.pointType;
      * Push all other points onto the pointsToRemove array for later removal. We can't
      * remove them while we are working with later sets.
      for (j=1; j<currentPointSet.length; j++) {
      pointsToRemove.push(currentPointSet[j]);
      * Sort the pointsToRemove array and then remove the points in reverse order, so the indicies
      * remain coherent during the removal.
      pointsToRemove.sort(function (a,b) { return a-b });
      for (i=pointsToRemove.length-1; i>=0; i--) {
      var pointToRemove = path.pathPoints[pointsToRemove[i]];
      pointToRemove.remove();
      if (tempPath) {
      tempPath.remove();
      if (tempLayer) {
      tempLayer.remove();
      return (pointsToRemove.length);
    * Function: selectRedundantPoints
    * Description:
    * Select redundant points on a path input as the first parameter. The
    * second input parameter should be an array of arrays containing the
    * indicies of redundant points, as returned from function
    * findRedundantPoints(). If there are redundant points, deselect all points
    * on the path and select the ANCHORPOINT of each redundant point. If there
    * are no redundant points on the path, do nothing.
    function selectRedundantPoints(path, redundantPointSets){
      var i = 0;
      var j = 0;
      if (redundantPointSets.length > 0) {
      for (i=0; i<path.pathPoints.length; i++) {
      path.pathPoints[i].selected = PathPointSelection.NOSELECTION;
      for (i=0; i<redundantPointSets.length; i++) {
      var currentPointSet = redundantPointSets[i];
      for (j=0; j<currentPointSet.length; j++) {
      path.pathPoints[currentPointSet[j]].selected = PathPointSelection.ANCHORPOINT;
    * Function: unlockPath
    * Description:
    * For a path input as the first parameter, unlock the path and any locked
    * parent object. Return an array of objects that have been unlocked.
    function unlockPath(path){
      var unlockedObjects = new Array();
      var parentObjects = new Array();
      var currentObject = path;
      var i = 0;
      while (currentObject.typename != "Document") {
      parentObjects.unshift(currentObject);
      currentObject = currentObject.parent;
      for (i=0; i<parentObjects.length; i++) {
      if (parentObjects[i].locked) {
      parentObjects[i].locked = false;
      unlockedObjects.unshift(parentObjects[i]);
      return unlockedObjects;
    * Function: lockObjects
    * Description:
    * For a set of objects as the first parameter, lock each object.
    function lockObjects(objects){
      var i = 0;
      for (i=0; i<objects.length; i++) {
      objects[i].locked = true;
    * Function: docGetSelectedPaths
    * Description:
    * Get all the selected paths for the docRef argument passed in as
    * a parameter. The second parameter is a boolean that controls if compound
    * path items are included (default true), and the third parameter is a
    * boolean that controls if locked objects are included (default false).
    * Returns an array of paths.
    function docGetSelectedPaths(docRef, includeCompound, includeLocked){
      var qualifiedPaths = new Array();
      var i = 0;
      var j = 0;
      var nextPath = null;
      var currentSelection = new Array();
      var nextSelection = docRef.selection;
      if (includeCompound == null) {
      includeCompound = true;
      if (includeLocked == null) {
      includeLocked = false;
      do {
      currentSelection = nextSelection;
      nextSelection = [];
      for(i=0; i<currentSelection.length; i++){
      var currentObject=currentSelection[i];
      if (currentObject.typename == "PathItem") {
      if (includeLocked || !(currentObject.locked ||
      currentObject.layer.locked)) {
      qualifiedPaths.push(currentObject);
      else if (currentObject.typename == "CompoundPathItem") {
      if (includeCompound &&
      (includeLocked || !(currentObject.locked ||
      currentObject.layer.locked))) {
      * For more complex compound paths (e.g. concentric circular bands),
      * in CS3 the CompoundPathItem object's pathItems array is empty.
      * Inspection of the paths in a document shows the paths contained
      * in the CompoundPathItem have groups as parents. To get around
      * this seeming bug, in addition to using the pathItems array,
      * which still contains individual paths, we also search through
      * all the groups in the document adding paths whose parent
      * is the CompoundPathItem object.
      * WARNING this takes non-negligible time in large documents.
      for (j=0; j<currentObject.pathItems.length; j++) {
      qualifiedPaths.push(currentObject.pathItems[j]);
      for (j=0; j<docRef.groupItems.length; j++) {
      if (docRef.groupItems[j].parent == currentObject) {
      nextSelection.push(docRef.groupItems[j]);
      else if (currentObject.typename == "GroupItem") {
      for (j=0; j<currentObject.pathItems.length; j++){
      nextSelection.push(currentObject.pathItems[j]);
      for (j=0; j<currentObject.compoundPathItems.length; j++){
      nextSelection.push(currentObject.compoundPathItems[j]);
      for (j=0; j<currentObject.groupItems.length; j++){
      nextSelection.push(currentObject.groupItems[j]);
      else if (currentObject.typename == "Layer") {
      for (j=0; j<currentObject.pathItems.length; j++){
      nextSelection.push(currentObject.pathItems[j]);
      for (j=0; j<currentObject.compoundPathItems.length; j++){
      nextSelection.push(currentObject.compoundPathItems[j]);
      for (j=0; j<currentObject.groupItems.length; j++){
      nextSelection.push(currentObject.groupItems[j]);
      for (j=0; j<currentObject.layers.length; j++){
      nextSelection.push(currentObject.layers[j]);
      } while (nextSelection.length > 0);
      return qualifiedPaths;
    * Function: docGetAllPaths
    * Description:
    * Get all the paths for the docRef argument passed in as a parameter.
    * The second parameter is a boolean that controls if compound path items are
    * included (default true), and the third parameter is a boolean that controls
    * if locked objects are included (default false). Returns an array of paths.
    function docGetAllPaths(docRef, includeCompound, includeLocked) {
      var qualifiedPaths = new Array();
      var i = 0;
      var nextPath = null;
      if (includeCompound == null) {
      includeCompound = true;
      if (includeLocked == null) {
      includeLocked = false;
      for (i=0; i<docRef.pathItems.length; i++) {
      nextPath = docRef.pathItems[i];
      if (!includeCompound && nextPath.parent.typename == "CompoundPathItem") {
      continue;
      if (!includeLocked && (nextPath.layer.locked == true || nextPath.locked == true)) {
      continue;
      qualifiedPaths.push(nextPath);
      return qualifiedPaths;
    * Function: roundToPrecision
    * Description:
    * Round a number input as the first parameter to a given precision. The
    * second input parameter is the precision to round to (typically a power of
    * 10, like 0.1). Returns the rounded value.
    function roundToPrecision(value, precision) {
      var result;
      result = value / precision;
      result = Math.round(result);
      result = result * precision;
      return (result);
    * Main code
    var dlgInit = new Window('dialog', 'Redundant Path Points');
    doInitDialog(dlgInit);
    var exitError;
    var tolerance = 1 * (dlgInit.tolerancePnl.editText.text);
    var doAnalyze = dlgInit.functionPnl.doAnalyze.value;
    var doRemove = dlgInit.functionPnl.doRemove.value;
    var doSelect = dlgInit.functionPnl.doSelect.value;
    var doKeepLeadingPoint = dlgInit.removalPnl.doKeepLeadingPoint.value;
    var doKeepTrailingPoint = dlgInit.removalPnl.doKeepTrailingPoint.value;
    var doKeepAveragedPoint = dlgInit.removalPnl.doKeepAveragedPoint.value;
    var includeCompound = dlgInit.optionPnl.includeCompound.value;
    var includeLocked = dlgInit.optionPnl.includeLocked.value;
    var ignoreSelected = dlgInit.selectionPnl.ignoreSelected.value;
    var anySelected = dlgInit.selectionPnl.anySelected.value;
    var allSelected = dlgInit.selectionPnl.allSelected.value;
    var docRef=app.activeDocument;
    var pathsToProcess = new Array();
    var i = 0;
    var j = 0;
    var totalPaths = 0;
    var totalPointsWithRedundancy = 0;
    var totalPointsToRemove = 0;
    var totalPointsRemoved = 0;
    var totalPointsStarting = 0;
    var totalPointsRemaining = 0;
    var totalPointsSelected = 0;
    var redundantPointSets = new Array();
    var unlockedObjects = new Array();
    try {
      if (exitError != 0) {
      throw("exit");
      exitError = 99;
      if (docRef.selection.length > 0) {
      pathsToProcess = docGetSelectedPaths(docRef, includeCompound, includeLocked);
      else {
      var doAll = confirm("Run script for all paths in document?");
      if (doAll) {
      pathsToProcess = docGetAllPaths(docRef, includeCompound, includeLocked);
      if (doSelect) {
      if (includeLocked) {
      exitError = 2;
      throw("exit");
      if (!ignoreSelected) {
      exitError = 3;
      throw("exit");
      docRef.selection = null;
      for (i=0; i<pathsToProcess.length; i++) {
      redundantPointSets = findRedundantPoints(pathsToProcess[i], tolerance, anySelected, allSelected);
      totalPaths++;
      totalPointsWithRedundancy += redundantPointSets.length;
      totalPointsToRemove += countRedundantPoints(redundantPointSets, doKeepLeadingPoint, doKeepTrailingPoint);
      totalPointsStarting += pathsToProcess[i].pathPoints.length;
      totalPointsSelected += countSelectedPoints(pathsToProcess[i]);
      if (doRemove) {
      if (includeLocked) {
      unlockedObjects = unlockPath(pathsToProcess[i]);
      else {
      unlockedObjects = [];
      totalPointsRemoved += removeRedundantPoints(pathsToProcess[i], redundantPointSets, doKeepLeadingPoint, doKeepTrailingPoint, doKeepAveragedPoint);
      if (unlockedObjects.length > 0) {
      lockObjects(unlockedObjects);
      if (doSelect) {
      selectRedundantPoints(pathsToProcess[i], redundantPointSets);
      totalPointsRemaining += pathsToProcess[i].pathPoints.length;
      var dlgResults = new Window('dialog', 'Redundant Path Points');
      doResultsDialog(dlgResults,
      totalPaths,
      totalPointsWithRedundancy,
      totalPointsToRemove,
      totalPointsRemoved,
      totalPointsStarting,
      totalPointsRemaining,
      totalPointsSelected,
      tolerance);
    catch(er)
      if (exitError == 2) {
      alert("Select function not supported in conjunction with 'Include Locked Items' option.");
      if (exitError == 3) {
      alert("Select function supported only with 'Ignore' selection restriction.");
      if (exitError == 99) {
      alert("ACK! Unexplained error\n");
    * Dialog Code
    * Function: doInitDialog
    function doInitDialog(dlgInit) {
      var defaultTolerance = 5.0;
      var maxSliderTolerance = 5;
      /* Add radio buttons to control functionality */
      dlgInit.functionPnl = dlgInit.add('panel', undefined, 'Function:');
      (dlgInit.functionPnl.doAnalyze = dlgInit.functionPnl.add('radiobutton', undefined, 'Analyze' )).helpTip = "Find and count redundant points.";
      (dlgInit.functionPnl.doRemove = dlgInit.functionPnl.add('radiobutton', undefined, 'Remove' )).helpTip = "Find and remove redundant points.";
      (dlgInit.functionPnl.doSelect = dlgInit.functionPnl.add('radiobutton', undefined, 'Select' )).helpTip = "Find and select redundant points.\nWARNING:Manual removal of selected redundant points can change the shape of your curves.\nTips:Hiding bounding box helps to see which points are selected. Modify selection as desired and rerun script to remove specific redundant points.";
      dlgInit.functionPnl.doRemove.value = true;
      dlgInit.functionPnl.orientation='row';
      /* Add radio buttons to control point selection */
      dlgInit.selectionPnl = dlgInit.add('panel', undefined, 'Point Selection State:');
      (dlgInit.selectionPnl.ignoreSelected = dlgInit.selectionPnl.add('radiobutton', undefined, 'Ignore')).helpTip="Process redundant points on a path regardless of their selection state.";
      (dlgInit.selectionPnl.allSelected = dlgInit.selectionPnl.add('radiobutton', undefined, 'All')).helpTip="Process redundant points on a path only if each of them is selected.";
      (dlgInit.selectionPnl.anySelected = dlgInit.selectionPnl.add('radiobutton', undefined, 'Any')).helpTip="Process redundant points on a path if any one of them is selected.";
      dlgInit.selectionPnl.allSelected.value = true;
      dlgInit.selectionPnl.orientation='row';
      /* Add a checkbox to control options */
      dlgInit.optionPnl = dlgInit.add('panel', undefined, 'Other Options:');
      (dlgInit.optionPnl.includeCompound = dlgInit.optionPnl.add('checkbox', undefined, 'Include Compound Path Items?')).helpTip="Work on compound path items.";
      (dlgInit.optionPnl.includeLocked = dlgInit.optionPnl.add('checkbox', undefined, 'Include Locked Items?')).helpTip="Work on locked items or items in locked layers.";
      dlgInit.optionPnl.includeCompound.value = true;
      dlgInit.optionPnl.includeLocked.value = false;
      dlgInit.optionPnl.alignChildren='left';
      dlgInit.optionPnl.orientation='column';
      /* Add a slider and edit box for user entered tolerance */
      dlgInit.tolerancePnl = dlgInit.add('panel', undefined, 'Tolerance (in PostScript points):');
      (dlgInit.tolerancePnl.slide = dlgInit.tolerancePnl.add('slider', undefined, defaultTolerance, 0.01, maxSliderTolerance)).helpTip="Use slider to set a tolerance value in hundredths of a point.";
      (dlgInit.tolerancePnl.editText = dlgInit.tolerancePnl.add('edittext', undefined, defaultTolerance)).helpTip="Enter a tolerance value. Values greater then 5.0 or more precise than 1/100 point can be manually entered here.";
      dlgInit.tolerancePnl.editText.characters = 5;
      dlgInit.tolerancePnl.orientation='row';
      dlgInit.tolerancePnl.slide.onChange = toleranceSliderChanged;
      dlgInit.tolerancePnl.editText.onChange = toleranceEditTextChanged;
      /* Add a panel control removal options */
      dlgInit.removalPnl = dlgInit.add('panel', undefined, 'Removal Options:');
      (dlgInit.removalPnl.doKeepLeadingPoint = dlgInit.removalPnl.add('checkbox', undefined, 'Keep Leading Point' )).helpTip = "Keep the leading point (lowest path index, lowest prior to origin cross for closed path).";
      (dlgInit.removalPnl.doKeepTrailingPoint = dlgInit.removalPnl.add('checkbox', undefined, 'Keep Trailing Point' )).helpTip = "Keep the trailing point (highest path index, highest following origin cross for closed path).";
      (dlgInit.removalPnl.doKeepAveragedPoint = dlgInit.removalPnl.add('checkbox', undefined, 'Keep Averaged Point' )).helpTip = "Keep an averaged point to help smooth transitions.";
      dlgInit.removalPnl.keepTips = dlgInit.removalPnl.add('statictext', undefined, 'Keeping neither will cause position of remaining point to be averaged. Keeping both will anchor two ends of a segment while removing intermediate redundant points. An averaged point helps smooth transitions.', {multiline:'true'} );
      dlgInit.removalPnl.doKeepLeadingPoint.value = false;
      dlgInit.removalPnl.doKeepTrailingPoint.value = false;
      dlgInit.removalPnl.doKeepAveragedPoint.value = false;
      dlgInit.removalPnl.alignChildren='left';
      dlgInit.removalPnl.orientation='column';
      /* Add execution buttons */
      dlgInit.executeGrp = dlgInit.add('group', undefined, 'Execute:');
      dlgInit.executeGrp.orientation='row';
      dlgInit.executeGrp.buildBtn1= dlgInit.executeGrp.add('button',undefined, 'Cancel', {name:'cancel'});
      dlgInit.executeGrp.buildBtn2 = dlgInit.executeGrp.add('button', undefined, 'OK', {name:'ok'});
      dlgInit.executeGrp.buildBtn1.onClick= initActionCanceled;
      dlgInit.executeGrp.buildBtn2.onClick= initActionOk;
      dlgInit.frameLocation = [100, 100];
      dlgInit.alignChildren='fill';
      dlgInit.show();
      return dlgInit;
    function initActionCanceled() {
      exitError = 1;
      dlgInit.hide();
    function initActionOk() {
      var proceed = true;
      exitError = 0;
      if (dlgInit.tolerancePnl.editText.text > 5.0) {
      proceed = confirm("Tolerance entered greater than 5.0 PostScript points. Proceed?");
      if (proceed) {
      dlgInit.hide();
    function toleranceSliderChanged() {
      dlgInit.tolerancePnl.editText.text = roundToPrecision(dlgInit.tolerancePnl.slide.value, 0.01);
    function toleranceEditTextChanged() {
      if (dlgInit.tolerancePnl.editText.text > 5000) {
      dlgInit.tolerancePnl.editText.text = 5000;
      dlgInit.tolerancePnl.slide.value = roundToPrecision(dlgInit.tolerancePnl.editText.text, 0.01);
    * Function: doResultsDialog
    function doResultsDialog(dlgResults,
      totalPaths,
      totalPointsWithRedundancy,
      totalPointsToRemove,
      totalPointsRemoved,
      totalPointsStarting,
      totalPointsRemaining,
      totalPointsSelected,
      tolerance) {
      /* Add static text to display results */
      dlgResults.resultsPnl = dlgResults.add('panel', undefined, 'Results:');
      dlgResults.resultsPnl.totalPaths = dlgResults.resultsPnl.add('group');
      dlgResults.resultsPnl.totalPaths.txt = dlgResults.resultsPnl.totalPaths.add('statictext', undefined, 'Paths processed: ');
      dlgResults.resultsPnl.totalPaths.txt.alignment = 'right';
      dlgResults.resultsPnl.totalPaths.val = dlgResults.resultsPnl.totalPaths.add('statictext', undefined, totalPaths);
      dlgResults.resultsPnl.totalPaths.val.characters = 10;
      dlgResults.resultsPnl.totalPaths.val.helpTip = "The number of paths processed.";
      dlgResults.resultsPnl.totalPointsSelected = dlgResults.resultsPnl.add('group');
      dlgResults.resultsPnl.totalPointsSelected.txt = dlgResults.resultsPnl.totalPointsSelected.add('statictext', undefined, 'Total points selected: ');
      dlgResults.resultsPnl.totalPointsSelected.txt.alignment = 'right';
      dlgResults.resultsPnl.totalPointsSelected.val = dlgResults.resultsPnl.totalPointsSelected.add('statictext', undefined, totalPointsSelected);
      dlgResults.resultsPnl.totalPointsSelected.val.characters = 10;
      dlgResults.resultsPnl.totalPointsSelected.val.helpTip = "The total number of points initially selected.";
      dlgResults.resultsPnl.separator0 = dlgResults.resultsPnl.add('panel');
      dlgResults.resultsPnl.totalPointsWithRedundancy = dlgResults.resultsPnl.add('group');
      dlgResults.resultsPnl.totalPointsWithRedundancy.txt = dlgResults.resultsPnl.totalPointsWithRedundancy.add('statictext', undefined, 'Points with redundancy: ');
      dlgResults.resultsPnl.totalPointsWithRedundancy.txt.alignment = 'right';
      dlgResults.resultsPnl.totalPointsWithRedundancy.val = dlgResults.resultsPnl.totalPointsWithRedundancy.add('statictext', undefined, totalPointsWithRedundancy);
      dlgResults.resultsPnl.totalPointsWithRedundancy.val.characters = 10;
      dlgResults.resultsPnl.totalPointsWithRedundancy.val.helpTip = "The number of points with redundancy.";
      dlgResults.resultsPnl.totalPointsToRemove = dlgResults.resultsPnl.add('group');
      dlgResults.resultsPnl.totalPointsToRemove.txt = dlgResults.resultsPnl.totalPointsToRemove.add('statictext', undefined, 'Redundant points to remove: ');
      dlgResults.resultsPnl.totalPointsToRemove.txt.alignment = 'right';
      dlgResults.resultsPnl.totalPointsToRemove.val = dlgResults.resultsPnl.totalPointsToRemove.add('statictext', undefined, totalPointsToRemove);
      dlgResults.resultsPnl.totalPointsToRemove.val.characters = 10;
      dlgResults.resultsPnl.totalPointsToRemove.val.helpTip = "The number of redundant points that would be removed.";
      dlgResults.resultsPnl.totalPointsRemoved = dlgResults.resultsPnl.add('group');
      dlgResults.resultsPnl.totalPointsRemoved.txt = dlgResults.resultsPnl.totalPointsRemoved.add('statictext', undefined, 'Redundant points removed: ');
      dlgResults.resultsPnl.totalPointsRemoved.txt.alignment = 'right';
      dlgResults.resultsPnl.totalPointsRemoved.val = dlgResults.resultsPnl.totalPointsRemoved.add('statictext', undefined, totalPointsRemoved);
      dlgResults.resultsPnl.totalPointsRemoved.val.characters = 10;
      dlgResults.resultsPnl.totalPointsRemoved.val.helpTip = "The number of redundant points that were removed.";
      dlgResults.resultsPnl.separator1 = dlgResults.resultsPnl.add('panel');
      dlgResults.resultsPnl.totalPointsStarting = dlgResults.resultsPnl.add('group');
      dlgResults.resultsPnl.totalPointsStarting.txt = dlgResults.resultsPnl.totalPointsStarting.add('statictext', undefined, 'Total points starting: ');
      dlgResults.resultsPnl.totalPointsStarting.txt.alignment = 'right';
      dlgResults.resultsPnl.totalPointsStarting.val = dlgResults.resultsPnl.totalPointsStarting.add('statictext', undefined, totalPointsStarting);
      dlgResults.resultsPnl.totalPointsStarting.val.characters = 10;
      dlgResults.resultsPnl.totalPointsStarting.helpTip = "The total number of points before processing.";
      dlgResults.resultsPnl.totalPointsRemaining = dlgResults.resultsPnl.add('group');
      dlgResults.resultsPnl.totalPointsRemaining.txt = dlgResults.resultsPnl.totalPointsRemaining.add('statictext', undefined, 'Total points remaining: ');
      dlgResults.resultsPnl.totalPointsRemaining.txt.alignment = 'right';
      dlgResults.resultsPnl.totalPointsRemaining.val = dlgResults.resultsPnl.totalPointsRemaining.add('statictext', undefined, totalPointsRemaining);
      dlgResults.resultsPnl.totalPointsRemaining.val.characters = 10;
      dlgResults.resultsPnl.totalPointsRemaining.val.helpTip = "The total number of points after processing.";
      dlgResults.resultsPnl.alignChildren='right';
      dlgResults.resultsPnl.orientation='column';
      dlgResults.note = dlgResults.add('group');
      dlgResults.note.txt = dlgResults.note.add('statictext', undefined, 'Combined results across paths qualified based on options');
      dlgResults.tolerance = dlgResults.add('group');
      dlgResults.tolerance.txt = dlgResults.tolerance.add('statictext', undefined, "Tolerance applied (in PostScript points): ");
      dlgResults.tolerance.val = dlgResults.tolerance.add('statictext', undefined, tolerance);
      /* Add execution buttons */
      dlgResults.executeGrp = dlgResults.add('group', undefined, 'Execute:');
      dlgResults.executeGrp.orientation='row';
      dlgResults.executeGrp.buildBtn1= dlgResults.executeGrp.add('button',undefined, 'OK', {name:'ok'});
      dlgResults.executeGrp.buildBtn1.onClick= resultsActionOk;
      dlgResults.frameLocation = [100, 100];
      dlgResults.show();
    function resultsActionOk() {
      exitError = 0;
      dlgResults.hide();

    you have said you are using cc.
    is it fully up to date?
    are you not using cc2014?
    when run from ESTK are you sure it is pointing to the correct illustrator?

  • Batch HDR Merging/Toning Script

    I've seen a number of different posts on these forums about trying to do this and I never really found a complete and suitable solution. It also has really annoyed me that adobe never implemented this (and it's not possible to do with actions because the action just runs a script and you can't record the HDR toning settings, the dialog always pops up, its in the script). So I finally had some time to get my hands dirty with ExtendScript and I have created a fully featured script complete with UI that allows batch creation of HDR tonned images in photoshop.
    The code I got working from various snipets of code I found around the 'net and single stepping through the MergeToHDR.jsx script that is built into photoshop.
    This has only been partially tested on photoshop CC on a mac. Hopefully I made it portable enough and it will work on windows and older versions. I don't think the MergeToHDR script has changed much in the last several versions (and that is mainly what I call to do the work) so I think it should work. If you have issues please let me know.
    My motivation for this script was coming up with a way to do batch HDR toning for timelapse and so this script's features lean toward using it for that end. I really didn't want to buy another separate program for doing this like photomatix, when I knew it should at least be possible to do in photoshop.
    I uploaded the script to github:
    https://github.com/davidmilligan/PhotoshopBatchHDR/blob/master/Batch%20HDR.jsx
    How to use:
    Drop the script in the '[photoshop folder]/presets/scripts' folder and restart photoshop if it is already running.
    The script should appear as a menu item under File>Automate>Batch HDR...
    A dialog will appear where you specify all the settings for the batch
    Input Section:
    Click browse and select the source folder that contains the images to be merged/toned
    Specify "Number of Brackets" this is how many separate images to group into a single HDR output image (the script will group the images in the source folder in order based on this parameter). You can use a value of 1, which means each image in the source folder is separate and will be toned and output. (I find that many times when shooting RAW, 14 bits is ample to capture the full dynamic of the scene, so I do not waste storage space and shutter acutations using more than one exposure, just make sure to ETTR, also post-processing with this script will be faster)
    If there are other files in your source folder (for example .xmp files) that you need to exclude you can specify a filte. For example: *.cr2
    Typically for timelapse you are using a tripod and do not need to have photoshop align the images, but I provided that capability for anyone who might need it b/c it was easy to enable. Note that enabling this will make the process MUCH slower.
    Toning Section:
    These settings are all the same as the photoshop HDR toning dialog for "Local Adaptation"
    To preview what your toning settings will look like you can select any file(s) in your sequence by clicking "Select File(s)..." under "Preview". The file(s) you select will open and merge (if more than one file). When that's finished you can click the "Update Preview" button to apply the current toning settings and see what they will look like (I can't do the fast, automatic previews like the builtin dialog, sorry - somebody from adobe want to show me how to do this?)
    You can see what the settings will look like at another point in your sequence by clicking the "Select File(s).." button again. (I recommend previewing a shot near the beginning, middle, and end of your sequence)
    The dialog prevents you from using anything in photoshop while its open so I provided a zoom to allow you to zoom in on the preview
    The tone curve you must enter as a comma separated list of points (sorry, ScriptUI is not really adequate to create the graphical histogram overlay for the curves like in the builtin dialog). The points are grouped into x,y pairs so for example: x1,y1,x2,y2,etc. Typically you will start with 0,0 and end with 255,255 (note that 255 is the max, full white). Like the curves tool, x represents the input and y represents the output
    Output Section:
    Click browse and select a folder for the script to save the output files to
    The rest of this section should be self explanitory. NOTE: If you select to output 32bit files, the toning will not be applied, the files will simply be merged into a 32bit HDR image and saved.
    Once you have specified the input and output folders the OK button should be enabled, when you are ready, click OK to start the process
    Go watch a movie or take a nap, this is going to take a while. The script will display a progress window showing you how far along the proces is (the photoshop progress windows may occasionally appear on top of it, I usually just move them up a little so I can see both)
    Limitations:
    Only the local adaptation method is supported. It's really the only one I ever use, and I didn't really feel like implementing the other ones, but feel free to modify the script yourself to add this support
    You canot load or save presets from the builtin toning dialog. The format of the preset files is binary and would require reverse engineering of the format and it would be very difficult to read to the files in javascript anyway. If it were xml, it would be much easier, alas it is not. Feel free to grab a hex editor and do this yourself. For now you'll just have to copy all of the values of a preset by hand into the dialog if you want to use a preset. If I have more time this is something I might work on.
    Preview is slow because it has to do the actual full toning, I don't know a way to do the fast real time previews like the builtin dialog.
    I don't think the "Cancel" button on the progress window really works, once running, the script is too busy to register a click, anybody know how I might fix this?
    There may potentially be some ways to improve performance of this script in certain scenarios, IDK, but I'm just glad it works
    You're welcome Adobe, you can send me a check at:
    [REDACTED]
    [REDACTED]
    [REDACTED]
    Please hit me up with comments/suggestions,
    David

    Thank you for your script, it's very useful.
    I just changed a few things :
    The Checkboxes didn't work so I changed them :
    alignCheckBox.onChanged by alignCheckBox.onClick
    deghostCheckBox.onChanged by deghostCheckBox.onClick
    smoothEdgesBox.onChange by smoothEdgesBox.onClick
    And for best alignment, I changed :
    mergeToHDR.mergeFilesToHDR( currentFileList, false, hdrDeghosting ? kMergeToHDRDeghostBest : kMergeToHDRDeghostOff );
    by :
    mergeToHDR.mergeFilesToHDR( currentFileList, mergeToHDR.useAlignment, hdrDeghosting ? kMergeToHDRDeghostBest : kMergeToHDRDeghostOff );
    And lastly :
    My language is french so I had to modify loadPreset function because my own preset file contains the string "P a r   d é f a u t" in place of "D e f a u l t" so that the data is shifted.
    Here is the code :
    #target photoshop
    Batch HDR Script by David Milligan
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    // BEGIN__HARVEST_EXCEPTION_ZSTRING
    <javascriptresource>
    <name>Batch HDR...</name>
    <menu>automate</menu>
    </javascriptresource>
    // END__HARVEST_EXCEPTION_ZSTRING
    //these lines import the 'Merge To HDR.jsx' script that is built in to photoshop, we will make calls to that script and some of the scripts that it includes
    var runMergeToHDRFromScript = true;
    var g_ScriptFolderPath = app.path + "/"+ localize("$$$/ScriptingSupport/InstalledScripts=Presets/Scripts");
    var g_ScriptPath = File( g_ScriptFolderPath+'/Merge To HDR.jsx' );
    $.evalFile( g_ScriptPath );
    //$.level = 2;
    //default settings:
    mergeToHDR.useAlignment = false;
    mergeToHDR.useACRToning = false;
    var numberOfBrackets = 3;
    var userCanceled = false;
    var sourceFolder;
    var outputFolder;
    var saveType = "JPEG";
    var jpegQuality = 10;
    var progress;
    var statusText;
    var progressWindow;
    var fileMask = "*";
    var outputFilename = "hdr_output_";
    var hdrRadius = 100;
    var hdrStrength = 0.5;
    var hdrGamma = 1.0;
    var hdrExposure = 0.0;
    var hdrDetail = 100;
    var hdrShadow = 0;
    var hdrHighlights = 0;
    var hdrVibrance = 20;
    var hdrSaturation = 30;
    var hdrSmooth = false;
    var hdrDeghosting = true;
    var hdrCurve = "0,0,255,255";
    var estTimeRemaining = "";
    var previewDoc;
    var originalDoc;
    function main()
        promptUser();
        //make sure user didn't cancel
        if(sourceFolder != null && outputFolder != null && sourceFolder.exists && outputFolder.exists && numberOfBrackets > 0)
            initializeProgress();
            var files =  sourceFolder.getFiles(fileMask);
            var currentFileList = new Array();
            for(var index = 0;  index < files.length; index++)
                if((index % numberOfBrackets) == numberOfBrackets - 1)
                    var start = new Date();
                    progress.value = 100 * index / files.length;
                    currentFileList.push(files[index]);
                    if(userCanceled) break;
                    if(numberOfBrackets > 1)
                        statusText.text = "Merging files "+(index-numberOfBrackets+2)+" - "+(index+1)+" of "+files.length + estTimeRemaining;
                        //for braketed exposures use the mergeToHDR script to merge the files into a single 32 bit image
                        mergeToHDR.outputBitDepth= 32;
                        mergeToHDR.mergeFilesToHDR( currentFileList, mergeToHDR.useAlignment, hdrDeghosting ? kMergeToHDRDeghostBest : kMergeToHDRDeghostOff );
                        statusText.text = "Toning files "+(index-numberOfBrackets+2)+" - "+(index+1)+" of "+files.length+ estTimeRemaining;
                    else
                        statusText.text = "Loading file "+(index+1)+" of "+files.length+ estTimeRemaining;
                        //otherwise just open the file
                        doOpenFile(files[index]);
                        statusText.text = "Toning file "+(index+1)+" of "+files.length+ estTimeRemaining;
                    progress.value = 100 * (index + numberOfBrackets / 2 ) / files.length;
                    if(userCanceled) break;
                    if(app.activeDocument != null)
                        //apply the actual tone mapping to the HDR image to get it back down to 8 bits
                        doHDRToning();
                    //save the result and close
                    //TODO: add leading zeros to index in filename
                    if(numberOfBrackets > 1)
                        statusText.text = "Saving result "+(index-numberOfBrackets+2)+" - "+(index+1)+" of "+files.length+ estTimeRemaining;
                    else
                        statusText.text = "Saving result "+(index+1)+" of "+files.length+ estTimeRemaining;
                    if(userCanceled) break;
                    doSaveFile(outputFolder.absoluteURI + "/" + outputFilename + ZeroPad(Math.round((index + 1)/numberOfBrackets), 5) );
                    activeDocument.close(SaveOptions.DONOTSAVECHANGES);
                    //reset our file list
                    currentFileList = new Array();
                    //calculate time remaining
                    var end = new Date();
                    var timeElapsed = end.getTime() - start.getTime();
                    var mins = timeElapsed / 60000 * ((files.length - index - 1) / numberOfBrackets);
                    estTimeRemaining = " | Remaining: " + ZeroPad((mins / 60).toFixed(0),2) + ":" + ZeroPad((mins % 60).toFixed(0),2);
                else
                    currentFileList.push(files[index]);
            progressWindow.hide();
    function doOpenFile(filename)
        const eventOpen = app.charIDToTypeID('Opn ');
        var desc = new ActionDescriptor();
        desc.putPath( typeNULL, new File( filename ) );
        desc.putBoolean( kpreferXMPFromACRStr, true ); //not sure what this does or if it is needed
        executeAction( eventOpen, desc, DialogModes.NO );
        //if we don't convert the image to 32bit the mergeToHDR script will not tone our image when we call it, it will simply downconvert it to 8 bit
        convertTo32Bit ();
    function convertTo32Bit()
        var idCnvM = charIDToTypeID( "CnvM" );
        var desc6 = new ActionDescriptor();
        var idDpth = charIDToTypeID( "Dpth" );
        desc6.putInteger( idDpth, 32 );
        var idMrge = charIDToTypeID( "Mrge" );
        desc6.putBoolean( idMrge, false );
        var idRstr = charIDToTypeID( "Rstr" );
        desc6.putBoolean( idRstr, false );
        executeAction( idCnvM, desc6, DialogModes.NO );
    function doSaveFile(filename)
        if(saveType == "JPEG")
            var jpgSaveOptions = new JPEGSaveOptions();
            jpgSaveOptions.embedColorProfile = true;
            jpgSaveOptions.formatOptions = FormatOptions.STANDARDBASELINE;
            jpgSaveOptions.matte = MatteType.NONE;
            jpgSaveOptions.quality = jpegQuality;
            activeDocument.saveAs(new File(filename), jpgSaveOptions, true /*Save As Copy*/, Extension.LOWERCASE /*Append Extention*/);
        else if(saveType == "TIFF")
            var tifSaveOptions = new TiffSaveOptions();
            tifSaveOptions.embedColorProfile = true;
            activeDocument.saveAs(new File(filename), tifSaveOptions, true /*Save As Copy*/, Extension.LOWERCASE /*Append Extention*/);
        else if(saveType == "TIFF LZW")
            var tifSaveOptions = new TiffSaveOptions();
            tifSaveOptions.embedColorProfile = true;
            tifSaveOptions.imageCompression = TIFFEncoding.TIFFLZW;
            activeDocument.saveAs(new File(filename), tifSaveOptions, true /*Save As Copy*/, Extension.LOWERCASE /*Append Extention*/);
        else if(saveType == "TIFF ZIP")
            var tifSaveOptions = new TiffSaveOptions();
            tifSaveOptions.embedColorProfile = true;
            tifSaveOptions.imageCompression = TIFFEncoding.TIFFZIP;
            activeDocument.saveAs(new File(filename), tifSaveOptions, true /*Save As Copy*/, Extension.LOWERCASE /*Append Extention*/);
        else
            activeDocument.saveAs(new File(filename), undefined, true /*Save As Copy*/, Extension.LOWERCASE /*Append Extention*/);
    function doHDRToning()
        //TODO: Reverse engineer the HDR Preset file format and allow user to select a preset file and create the ActionDescriptor from the file
        //create the ActionDescriptor that describes the HDR toning settings to use
        var hdDesc = new ActionDescriptor;
        hdDesc.putInteger( stringIDToTypeID( 'version' ), 6 );//I'm not sure what this does
        hdDesc.putInteger(  kmethodStr, 3 );// the toning method to use, 3 = local adaptation
        hdDesc.putDouble( stringIDToTypeID( 'radius' ), hdrRadius );
        hdDesc.putDouble( stringIDToTypeID( 'threshold' ), hdrStrength );// strength
        hdDesc.putDouble( stringIDToTypeID( 'center' ), hdrGamma );// gamma
        hdDesc.putDouble( stringIDToTypeID( 'brightness' ), hdrExposure );// exposure
        hdDesc.putDouble( stringIDToTypeID( 'detail' ), hdrDetail );
        hdDesc.putDouble( stringIDToTypeID( 'shallow' ), hdrShadow );
        hdDesc.putDouble( stringIDToTypeID( 'highlights' ), hdrHighlights );
        hdDesc.putDouble( stringIDToTypeID( 'vibrance' ), hdrVibrance );
        hdDesc.putDouble( stringIDToTypeID( 'saturation' ), hdrSaturation);
        hdDesc.putBoolean( stringIDToTypeID( 'smooth' ), hdrSmooth );
        hdDesc.putBoolean( stringIDToTypeID( 'deghosting' ), hdrDeghosting );
        //create the tone curve
        var cDesc = new ActionDescriptor;
        cDesc.putString( stringIDToTypeID( 'name' ), 'Default');
        var cList = new ActionList;
        var points = hdrCurve.split(',');
        for(var i = 0; i < points.length; i++)
            if(i % 2 == 1)
                var pDesc = new ActionDescriptor;
                pDesc.putDouble( stringIDToTypeID( 'horizontal' ), points[i-1] );
                pDesc.putDouble( stringIDToTypeID( 'vertical' ), points[i] );
                pDesc.putBoolean( keyContinuity , false );// ?????
                cList.putObject( charIDToTypeID( 'Pnt ' ), pDesc );
        cDesc.putList( stringIDToTypeID( 'curve' ), cList );
        hdDesc.putObject( kclassContour, classShapingCurve, cDesc );
        //call the script that actually invokes the toning plugin
        convertFromHDRNoDialog( outputBitDepth, hdDesc );
    function initializeProgress()
        progressWindow = new Window("palette { text:'Batch HDR Progress', \
            statusText: StaticText { text: 'Processing Images...', preferredSize: [350,20] }, \
            progressGroup: Group { \
                progress: Progressbar { minvalue: 0, maxvalue: 100, value: 0, preferredSize: [300,20] }, \
                cancelButton: Button { text: 'Cancel' } \
        statusText = progressWindow.statusText;
        progress = progressWindow.progressGroup.progress;
        progressWindow.progressGroup.cancelButton.onClick = function() { userCanceled = true; }
        progressWindow.show();
    function promptUser()
        var setupWindow = new Window("dialog { orientation: 'row', text: 'Batch HDR', alignChildren:'top', \
            leftGroup: Group { orientation: 'column', alignChildren:'fill', \
                inputPanel: Panel { text: 'Input', \
                    sourceGroup: Group { \
                        sourceBox: EditText { characters: 40, text: '' }, \
                        sourceBrowse: Button { text: 'Browse' } \
                    bracketGroup: Group{ \
                        bracketLabel: StaticText { text: 'Number of Brackets: ' }, \
                        bracketBox: EditText { characters: 2 }, \
                        filterLabel: StaticText { text: 'File Filter: ' }, \
                        filterText: EditText { characters: 5 }, \
                        alignCheckBox: Checkbox { text: 'Align' }\
                        deghostCheckBox: Checkbox { text: 'Deghost' }\
                toningPanel: Panel { text: 'Toning', orientation:'row', alignChildren:'top' } ,\
                outputPanel: Panel { text: 'Output', \
                    outputGroup: Group { \
                        outputBox: EditText { characters: 40, text: '' }, \
                        outputBrowse: Button { text: 'Browse' } \
                    outputOptionsGroup: Group { \
                        outputFilenameLabel: StaticText { text: 'Filename Format: ' }, \
                        outputFilenameText: EditText { characters: 10 }, \
                        outputFilenamePost: StaticText { text: '00001.jpg' }, \
                    saveSettingsGroup: Group { \
                        saveTypeLabel: StaticText { text: 'Save As: ' }, \
                        saveDropDown: DropDownList { }, \
                        jpegQualityLabel: StaticText { text: 'JPEG Quality (1-10): ' }, \
                        jpegQualityText: EditText { characters: 2}, \
                        outputBitDepthLabel: StaticText { text: 'Bit Depth', enabled:false }, \
                        outputBitDepthDropDown: DropDownList { enabled:false }, \
            rightGroup: Group { orientation: 'column', alignChildren:'fill', \
                okButton: Button { text: 'OK', enabled: false } \
                cancelButton: Button { text: 'Cancel' } \
        generateToningPanel(setupWindow.leftGroup.toningPanel);
        //shortcut variables
        var sourceBox = setupWindow.leftGroup.inputPanel.sourceGroup.sourceBox;
        var sourceBrowse = setupWindow.leftGroup.inputPanel.sourceGroup.sourceBrowse;
        var bracketBox = setupWindow.leftGroup.inputPanel.bracketGroup.bracketBox;
        var filterText = setupWindow.leftGroup.inputPanel.bracketGroup.filterText;
        var alignCheckBox = setupWindow.leftGroup.inputPanel.bracketGroup.alignCheckBox;
        var outputBox = setupWindow.leftGroup.outputPanel.outputGroup.outputBox;
        var outputBrowse = setupWindow.leftGroup.outputPanel.outputGroup.outputBrowse;
        var outputFilenameText = setupWindow.leftGroup.outputPanel.outputOptionsGroup.outputFilenameText;
        var saveDropDown = setupWindow.leftGroup.outputPanel.saveSettingsGroup.saveDropDown;
        var jpegQualityText = setupWindow.leftGroup.outputPanel.saveSettingsGroup.jpegQualityText;
        var jpegQualityLabel = setupWindow.leftGroup.outputPanel.saveSettingsGroup.jpegQualityLabel;
        var outputBitDepthDropDown = setupWindow.leftGroup.outputPanel.saveSettingsGroup.outputBitDepthDropDown;
        var outputBitDepthLabel = setupWindow.leftGroup.outputPanel.saveSettingsGroup.outputBitDepthLabel;
        var okButton = setupWindow.rightGroup.okButton;
        var cancelButton = setupWindow.rightGroup.cancelButton;
        var toningPanel = setupWindow.leftGroup.toningPanel;
        var deghostCheckBox = setupWindow.leftGroup.inputPanel.bracketGroup.deghostCheckBox;
        //set default values
        bracketBox.text = numberOfBrackets;
        filterText.text = fileMask;
        //mergeToHDR.useAlignment = true;
        alignCheckBox.value = mergeToHDR.useAlignment;
        deghostCheckBox.value = hdrDeghosting;
        outputFilenameText.text = outputFilename;
        jpegQualityText.text = jpegQuality;
        saveDropDown.add("item", "JPEG");
        saveDropDown.add("item", "TIFF");
        saveDropDown.add("item", "TIFF LZW");
        saveDropDown.add("item", "TIFF ZIP");
        saveDropDown.add("item", "PSD");
        saveDropDown.selection = 0;
        outputBitDepthDropDown.add("item", "8");
        outputBitDepthDropDown.add("item", "16");
        outputBitDepthDropDown.add("item", "32");
        outputBitDepthDropDown.selection = 0;
        //event handlers
        sourceBox.onChange = function()
            sourceFolder = new Folder(sourceBox.text);
            okButton.enabled = sourceFolder != null && outputFolder != null && sourceFolder.exists && outputFolder.exists;
        sourceBrowse.onClick = function()
            sourceFolder = Folder.selectDialog ("Select the source folder");
            if(sourceFolder != null)
                sourceBox.text = sourceFolder.fullName;
            okButton.enabled = sourceFolder != null && outputFolder != null && sourceFolder.exists && outputFolder.exists;
        bracketBox.onChange = function() { numberOfBrackets = bracketBox.text; };
        filterText.onChange = function() { fileMask = filterText.text; };
        alignCheckBox.onClick = function() { mergeToHDR.useAlignment = alignCheckBox.value; };
        deghostCheckBox.onClick = function() { hdrDeghosting = deghostCheckBox.value; };
        outputBox.onChange = function()
            outputFolder = new Folder(outputBox.text);
            okButton.enabled = sourceFolder != null && outputFolder != null && sourceFolder.exists && outputFolder.exists;
        outputBrowse.onClick = function()
            outputFolder = Folder.selectDialog ("Select the output folder");
            if(outputFolder != null)
                outputBox.text = outputFolder.fullName;
            okButton.enabled = sourceFolder != null && outputFolder != null && sourceFolder.exists && outputFolder.exists;
        outputFilenameText.onChange = function() { outputFilename = outputFilenameText.text; };
        saveDropDown.onChange = function()
            saveType = saveDropDown.selection.text;
            jpegQualityText.enabled = saveDropDown.selection.text == "JPEG";
            jpegQualityLabel.enabled = saveDropDown.selection.text == "JPEG";
            if(saveDropDown.selection.text == "JPEG")
                outputBitDepthDropDown.selection = 0;
            outputBitDepthDropDown.enabled = saveDropDown.selection.text != "JPEG";
            outputBitDepthLabel.enabled = saveDropDown.selection.text != "JPEG";
        jpegQualityText.onChange = function() { jpegQuality = jpegQualityText.text; };
        outputBitDepthDropDown.onChange = function()
            outputBitDepth = outputBitDepthDropDown.selection.text;
            toningPanel.enabled = outputBitDepth != 32;
        okButton.onClick = function() { setupWindow.hide(); cleanUpPreviews(); };
        cancelButton.onClick = function() { sourceFolder = null, setupWindow.hide(); cleanUpPreviews(); };
        saveDropDown.onChange();
        outputBitDepthDropDown.onChange();
        setupWindow.show();
    function cleanUpPreviews()
        if(originalDoc != null)
            originalDoc.close(SaveOptions.DONOTSAVECHANGES);
            originalDoc = null;
        if(previewDoc != null)
            previewDoc.close(SaveOptions.DONOTSAVECHANGES);
            previewDoc = null;
    function generateToningPanel(toningPanel)
        var leftToningGroup = toningPanel.add("group{orientation:'column',alignChildren:'fill'}");
        var rightToningGroup = toningPanel.add("group{orientation:'column',alignChildren:'fill'}");
        var presetGroup = leftToningGroup.add("group{orientation:'row'}");
        var presetDropDown = presetGroup.add("dropdownlist");
        var loadPresetButton = presetGroup.add("button", undefined, "Load Preset");
        var edgePanel = leftToningGroup.add("panel",undefined,"Edge Glow");
        var radiusSlider = createSliderControl(edgePanel.add("group"), "  Radius: ", "px", 0, 500, 0, hdrRadius, function(newValue){ hdrRadius = newValue; });
        var strengthSlider = createSliderControl(edgePanel.add("group"), "Strength: ", "", 0, 4.0, 2, hdrStrength, function(newValue){ hdrStrength = newValue; });
        var edgeGroup = edgePanel.add("group");
        var smoothEdgesBox = edgeGroup.add("checkbox",undefined, "Smooth Edges");
        var detailPanel = leftToningGroup.add("panel",undefined,"Tone and Detail");
        var gammaSlider = createSliderControl(detailPanel.add("group"), "  Gamma: ", "", 0.1, 2.0, 2, hdrGamma, function(newValue){ hdrGamma = newValue; });
        var exposureSlider = createSliderControl(detailPanel.add("group"), "Exposure: ", "", -5.0, 5.0, 2, hdrExposure, function(newValue){ hdrExposure = newValue; });
        var detailSlider = createSliderControl(detailPanel.add("group"), "     Detail: ", "%", -300, 300, 0, hdrDetail, function(newValue){ hdrDetail = newValue; });
        var advancedPanel = leftToningGroup.add("panel",undefined,"Advanced");
        var shadowSlider = createSliderControl(advancedPanel.add("group"), "  Shadow: ", "%", -100, 100, 0, hdrShadow, function(newValue){ hdrShadow = newValue; });
        var highlightSlider = createSliderControl(advancedPanel.add("group"), " Highlight: ", "%",  -100, 100, 0, hdrHighlights, function(newValue){ hdrHighlights = newValue; });
        var vibranceSlider = createSliderControl(advancedPanel.add("group"), "  Vibrance: ", "%",  -100, 100, 0, hdrVibrance, function(newValue){ hdrVibrance = newValue; });
        var saturationSlider = createSliderControl(advancedPanel.add("group"), "Saturation: ", "%",  -100, 100, 0, hdrSaturation, function(newValue){ hdrSaturation = newValue; });
        var toningCurvePanel = leftToningGroup.add("panel{text:'Toning Curve',alignChildren:'fill'}");
        var curveBox = toningCurvePanel.add("edittext", undefined, hdrCurve);
        //right side (preview panel)
        var previewGroup = rightToningGroup.add("panel", undefined, "Preview");
        var selectPreviewButton = previewGroup.add("button",undefined,"Select File(s)...");
        var previewButton = previewGroup.add("button",undefined,"Update Preview");
        var zoomGroup = previewGroup.add("group");
        zoomGroup.add("statictext",undefined, "zoom");
        var zoomBox = zoomGroup.add("edittext { text: '100', characters: 3, enabled: false } ");
        var previewZoomSlider = previewGroup.add("slider { minvalue: 10, maxvalue: 200, value: 100, enabled: false }");
        //default values
        smoothEdgesBox.value = hdrSmooth;
        previewButton.enabled = app.documents.length > 0;
        var presetFiles = getPresetFiles();
        var updateSliders = function()
            radiusSlider(hdrRadius);
            strengthSlider(hdrStrength);
            smoothEdgesBox.value = hdrSmooth;
            exposureSlider(hdrExposure);
            gammaSlider(hdrGamma);
            detailSlider(hdrDetail);
            shadowSlider(hdrShadow);
            highlightSlider(hdrHighlights);
            vibranceSlider(hdrVibrance);
            saturationSlider(hdrSaturation);
            curveBox.text = hdrCurve;
        if(presetFiles.length > 0)
            for(var f in presetFiles)
                presetDropDown.add("item", presetFiles[f].displayName.replace(".hdt",""));
            presetDropDown.selection = 0;
            loadPreset(presetFiles[0]);
            presetDropDown.onChange = function()
                loadPreset(presetFiles[presetDropDown.selection.index]);
                updateSliders();
        //event handlers
        loadPresetButton.onClick = function()
            loadPreset(null);
            updateSliders();
        smoothEdgesBox.onClick = function () { hdrSmooth = smoothEdgesBox.value; };
        curveBox.onChange = function () { hdrCurve = curveBox.text; };
        selectPreviewButton.onClick = function()
            var selectedFiles = File.openDialog("Select file(s) to load for preview", function(){return true;}, true);
            if(selectedFiles != null)
                cleanUpPreviews();
                if(selectedFiles instanceof Array)
                    if(selectedFiles.length > 1)
                        mergeToHDR.outputBitDepth= 32;
                        mergeToHDR.mergeFilesToHDR( selectedFiles, false, -2 );
                    else
                        doOpenFile(selectedFiles[0].fullName);
                else
                    doOpenFile(selectedFiles.fullName);
                originalDoc = app.activeDocument;
                previewButton.enabled = originalDoc != null;
                zoomBox.text = getZoomLevel();
                previewZoomSlider.value = getZoomLevel();
        previewButton.onClick = function()
            if(originalDoc != null)
                var tempOutputBitDepth = outputBitDepth;
                outputBitDepth = 16;
                if(previewDoc != null)
                    previewDoc.close(SaveOptions.DONOTSAVECHANGES);
                previewDoc = originalDoc.duplicate("HDR Preview");
                app.activeDocument = previewDoc;
                setZoomLevel(previewZoomSlider.value);
                convertTo32Bit();
                doHDRToning();
                outputBitDepth = tempOutputBitDepth;
                waitForRedraw();
                zoomBox.enabled = previewDoc != null;
                previewZoomSlider.enabled = previewDoc != null;
        zoomBox.onChange = function()
            if(previewDoc != null)
                previewZoomSlider.value = zoomBox.text;
                setZoomLevel(previewZoomSlider.value);
        previewZoomSlider.onChange = function()
            if(previewDoc != null)
                zoomBox.text = previewZoomSlider.value.toFixed(0);
                setZoomLevel(previewZoomSlider.value);
        updateSliders();
    function createSliderControl(group,label,postLabel,min,max,round,value,onValueChanged)
        var ignoreChange = false;
        group.add("statictext", undefined, label);
        var slider = group.add("slider",undefined,value,min,max);
        slider.alignment = "fill";
        var box = group.add("edittext",undefined,value);
        box.characters = 6;
        group.add("statictext", undefined, postLabel);
        slider.onChange = function()
            if(!ignoreChange)
                ignoreChange = true;
                box.text = slider.value.toFixed(round);
                onValueChanged(slider.value);
                ignoreChange = false;
        box.onChange = function()
            if(!ignoreChange)
                ignoreChange = true;
                slider.value = box.text;
                onValueChanged(box.text);
                ignoreChange = false;
        return function(newValue)
            slider.value = newValue;
            box.text = newValue.toFixed(round);
    //forces a redraw while a script dialog is active (for preview)
    var waitForRedraw = function()
        var desc = new ActionDescriptor();
        desc.putEnumerated(charIDToTypeID("Stte"), charIDToTypeID("Stte"), charIDToTypeID("RdCm"));
        executeAction(charIDToTypeID("Wait"), desc, DialogModes.NO);
    function getZoomLevel()
        var ref = new ActionReference();
        ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
        var desc = executeActionGet(ref);
        return Number(desc.getDouble(stringIDToTypeID('zoom'))*100).toFixed(1);
    function setZoomLevel( zoom )
        if(zoom < 1 ) zoom =1;
        var ref = new ActionReference();
        ref.putEnumerated( charIDToTypeID("capp"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );
        var getScrRes = executeActionGet(ref).getObjectValue(stringIDToTypeID('unitsPrefs')).getUnitDoubleValue(s tringIDToTypeID('newDocPresetScreenResolution'))/72;
        var docRes = activeDocument.resolution;
        activeDocument.resizeImage( undefined, undefined, getScrRes/(zoom/100), ResampleMethod.NONE );
        var desc = new ActionDescriptor();
        ref = null;
        ref = new ActionReference();
        ref.putEnumerated( charIDToTypeID( "Mn  " ), charIDToTypeID( "MnIt" ), charIDToTypeID( 'PrnS' ) );
        desc.putReference( charIDToTypeID( "null" ), ref );
        executeAction( charIDToTypeID( "slct" ), desc, DialogModes.NO );
        activeDocument.resizeImage( undefined, undefined, docRes, ResampleMethod.NONE );
    function ZeroPad(number,numZeros)
        var result = number.toString();
        while(result.length < numZeros)
            result = "0" + result;
        return result;
    var getPresetFiles = function()
        var presetFolder = new Folder(app.path + "/Presets/HDR Toning");
        return presetFolder.getFiles("*.hdt");
    var loadPreset = function(presetFile)
        if(presetFile == null)
            presetFile = File.openDialog("Select Preset","*.hdt");
        if(presetFile != null)
            var tmpStr = new String();
            var binaryData = new Array();
            presetFile.encoding = "BINARY";
            presetFile.open('r');
            while(!presetFile.eof)
                var ch = presetFile.readch();
                if ( ch.charCodeAt(0) == 0 ){
                    tmpStr += ' ';
                else {
                    tmpStr += ch;
                binaryData.push(ch.charCodeAt(0));
            presetFile.close();
            if(binaryData.length >= 40)
                // init start position for reading datas
                // start position for english version ( string "D e f a u l t" is in the preset file )
                var startPos = 38;
                if ( tmpStr.search ("P a r   d é f a u t") > -1 ){
                    // start position for french preset file version ( string "P a r   d é f a u t" is in the preset file ) (==> + 6 bytes)
                    startPos = 44;
                // if your preset file can't be read, try this : open it in notepad to see the string "D e f a u l t" in your language and add the code here to set startPos to 38 + diff between the length of ("D e f a u l t") and length of ("D e f a u l t" in your language)
                var curvePointCount = getUInt16(binaryData, startPos);
                if(binaryData.length >= 104 + curvePointCount * 4)
                    var curvePointStr = "";
                    for(var i = 0; i < curvePointCount; i++)
                        curvePointStr += getUInt16(binaryData, startPos + 4 + i * 4) + "," + getUInt16(binaryData, startPos + 2 + i * 4) + ((i < curvePointCount - 1) ? "," : "");
                    hdrCurve = curvePointStr;
                    hdrStrength =  getFloat32(binaryData,8);
                    hdrRadius = getFloat32(binaryData, startPos + 10 + 5 * curvePointCount);
                    hdrExposure = getFloat32(binaryData, startPos + 34 + 5 * curvePointCount);
                    hdrSaturation = getFloat32(binaryData, startPos + 38 + 5 * curvePointCount);
                    hdrDetail = getFloat32(binaryData, startPos + 42 + 5 * curvePointCount);
                    hdrShadow = getFloat32(binaryData, startPos + 46 + 5 * curvePointCount);
                    hdrHighlights = getFloat32(binaryData, startPos + 50 + 5 * curvePointCount);
                    hdrGamma = getFloat32(binaryData, startPos + 54 + 5 * curvePointCount);
                    hdrVibrance = getFloat32(binaryData, startPos + 58 + 5 * curvePointCount);
                    hdrSmooth = getUInt16(binaryData, startPos + 62 + 5 * curvePointCount) != 0;
                else
                    alert("Error Loading File", "Error", true);
            else
                alert("Error Loading File", "Error", true);
    function getUInt16(byteArray,offset)
        return byteArray[offset] * 0x100 + byteArray[offset + 1];
    function getUInt32(byteArray,offset)
        return byteArray[offset] * 0x1000000 + byteArray[offset + 1] * 0x10000 + byteArray[offset + 2] * 0x100 + byteArray[offset + 3];
    function getFloat32(byteArray,offset)
        var bytes = getUInt32(byteArray,offset);
        var sign = (bytes & 0x80000000) ? -1 : 1;
        var exponent = ((bytes >> 23) & 0xFF) - 127;
        var significand = (bytes & ~(-1 << 23));
        if (exponent == 128)
            return sign * ((significand) ? Number.NaN : Number.POSITIVE_INFINITY);
        if (exponent == -127) {
            if (significand == 0) return sign * 0.0;
            exponent = -126;
            significand /= (1 << 22);
        } else significand = (significand | (1 << 23)) / (1 << 23);
        return sign * significand * Math.pow(2, exponent);
    main();

  • What's simpler than mail merge?

    I have a Pages '09 document which will be used again and again by multiple people. Rather than make them perform a find and replace for each string like, "<%FirstName%>, <%LastName%>, <%Email%>" I wish I could attach a form to the file so that when someone openned it they would have to populate a few text fields one time and upon submition the find and replace would happen for all the various placeholder texts.
    The mail merge feature would be great if I needed a form letter but I don't. The benefit of mail merge would be creating several copies of a pages document populated by the data from rows a numbers file. I don't want to have to teach people how to change the data in a numbers file and make sure that they have it in the proper location on their machine.
    Does anyone know of a simple way to do this? I've looked at several applescript options but the find and replace scripts seem to only apply to body text. My document has body text, text boxes, tables and other types of text that I need replaced.
    Any answers would be greatly appreciated. Even if they are complicated. I'm comfortable trying to figure out Applescript or Automator if those are the only option but I definitely need a push in the right direction.
    Thanks.
    Pete

    Here is the edited script.
    --[SCRIPT open_a_Pages_custom_template_and_fill_fields]
    Enregistrer le script en tant que Script ou Application : open_a_Pages_custom_template_and_fill_fields.xxx
    déplacer le fichier ainsi créé dans le dossier
    <VolumeDeDémarrage>:Users:<votreCompte>:Library:Scripts:
    Aller au menu Scripts, choisir “open_a_Pages_custom_template_and_fill_fields”
    --=====
    L’aide du Finder explique:
    L’Utilitaire AppleScript permet d’activer le Menu des scripts :
    Ouvrez l’Utilitaire AppleScript situé dans le dossier Applications/AppleScript.
    Cochez la case “Afficher le menu des scripts dans la barre de menus”.
    Sous 10.6.x,
    aller dans le panneau “Général” du dialogue Préférences de l’Éditeur Applescript
    puis cocher la case “Afficher le menu des scripts dans la barre des menus”.
    --=====
    Save the script as a Script or an Application : open_a_Pages_custom_template_and_fill_fields.xxx
    Move the newly created file into the folder:
    <startup Volume>:Users:<yourAccount>:Library:Scripts:
    Go to the Scripts Menu, choose “open_a_Pages_custom_template_and_fill_fields”
    --=====
    The Finder’s Help explains:
    To make the Script menu appear:
    Open the AppleScript utility located in Applications/AppleScript.
    Select the “Show Script Menu in menu bar” checkbox.
    Under 10.6.x,
    go to the General panel of AppleScript Editor’s Preferences dialog box
    and check the “Show Script menu in menu bar” option.
    --=====
    Yvan KOENIG (VALLAURIS, France)
    2011/04/29 -- modified at 23:00:06 according to OP's request
    --=====
    true = open a predefined custom template
    false = open the custom template selected thru Choose From List
    property use_predefined_template : true
    Edit this property to fit your needs. You may change the strings or their number.
    The unique requirement is to keep the first two and the last two characters.
    property field_names : {"<%Error Title%>", "<%Error Type%>", "<%Unit ID%>"} --
    --=====
    on run
              my activateGUIscripting()
      run script do_your_duty
      --my do_your_duty()
    end run
    --=====
    script do_your_duty
      --on do_your_duty()
              local templates_loc, myTemplates_loc, chemin_des_modeles, le_modele, mon_modele
              local nb_chiffres, entire_contents, indx, chemin_de_mes_modeles, noms_de_mes_modeles, le_conteneur, i, un_element, le_titre, mon_choix
              set field_values to {}
              repeat with i from 1 to count of field_names
                        set field_name to item i of field_names
                        set le_prompt to "Enter the string to fill the field " & field_name
                        set maybe to text returned of (display dialog le_prompt default answer (text 3 thru -3 of field_name))
                        copy maybe to end of field_values
              end repeat
    Grab the localized names of the templates folders *)
              tell application "Pages"
                        my close_palettes()
                        set templates_loc to localized string "Templates"
                        set myTemplates_loc to localized string "My Templates"
              end tell -- to application a
    Define the path to the folder storing custom templates *)
              set chemin_des_modeles to "" & (path to library folder from user domain) & "Application Support:iWork:Pages:" & templates_loc & ":" & myTemplates_loc & ":"
              if use_predefined_template then
    Here, use a predefined custom template
                        set le_modele to "merge_in_it.template" --<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
                        set mon_modele to chemin_des_modeles & le_modele
              else
    Here, use a Choose from list dialog to define the template to use
                        set nb_chiffres to 3 (* 
    2 = allow 99 templates
    3 = allow 999 templates *)
    Grab the list of every items stored in the folder *)
                        tell application "Finder"
                                  set entire_contents to entire contents of folder chemin_des_modeles
                        end tell
    Build two lists. One contain the path to every custom templates.
    The other contain the names of these templates and the names of subfolders *)
                        set indx to 1
                        set chemin_de_mes_modeles to {}
                        set noms_de_mes_modeles to {}
                        set le_conteneur to ""
                        tell application "System Events"
                                  repeat with i from 1 to count of entire_contents
                                            set un_element to item i of entire_contents as text
                                            try
                                                      if type identifier of disk item un_element is in {"com.apple.iwork.Pages.template", "com.apple.iwork.Pages.sfftemplate"} then
                                                                if name of container of disk item un_element is not le_conteneur then
                                                                          set le_conteneur to name of container of disk item un_element
                                                                          copy (text 1 thru nb_chiffres of "---") & space & le_conteneur to end of noms_de_mes_modeles
                                                                end if
                                                                copy un_element to end of chemin_de_mes_modeles
                                                                copy text -nb_chiffres thru -1 of ("00" & indx) & space & name of disk item un_element to end of noms_de_mes_modeles
                                                                set indx to indx + 1
                                                      end if
                                            end try
                                  end repeat
                        end tell
                        if my parleAnglais() then
                                  set le_titre to "Pages’s custom templates"
                        else
                                  set le_titre to "Modèles personnalisés de Pages"
                        end if
    Choose the template to use.
    If you select a subfolder name, the script beep and ask one more time *)
                        repeat
                                  set mon_choix to choose from list noms_de_mes_modeles with title le_titre
                                  if mon_choix is false then error number -128
                                  try
                                            set mon_choix to text 1 thru nb_chiffres of (item 1 of mon_choix) as integer
                                            exit repeat
                                  on error
                                            beep 1
                                  end try
                        end repeat
                        set mon_modele to (item mon_choix of chemin_de_mes_modeles)
              end if
    Create a new document from the selected template *)
              tell application "Pages"
      open file mon_modele
                        tell document 1
                        end tell
                        repeat with i from 1 to count of field_names
                                  my Rechercher_Remplacer(item i of field_names, item i of field_values)
                        end repeat
              end tell -- Pages
      --end do_your_duty
    end script
    --=====
    on parleAnglais()
              local z
              try
                        tell application "Pages" to set z to localized string "Cancel"
              on error
                        set z to "Cancel"
              end try
              return (z is not "Annuler")
    end parleAnglais
    --=====
    on activateGUIscripting()
      (* to be sure than GUI scripting will be active *)
              tell application "System Events"
                        if not (UI elements enabled) then set (UI elements enabled) to true
              end tell
    end activateGUIscripting
    --=====
    on Rechercher_Remplacer(avant, |après|)
              local nom_du_dialog
              tell application "Pages" to activate
              tell application "System Events" to tell application process "Pages"
      keystroke "f" using {command down}
                        set nom_du_dialog to title of window 1
                        tell window nom_du_dialog to tell (first UI element whose role is "AXTabGroup")
                                  set value of first text area of first scroll area to avant
                                  set value of first text area of last scroll area to |après|
                                  if (count of checkbox) = 0 then
    Simple dialog *)
                                            set {X_bouton, Y_bouton} to position of last button
                                  else
    Advanced dialog *)
                                            set {X_bouton, Y_bouton} to position of button -3
                                  end if
                        end tell -- window nom_du_dialog…
                        click at {X_bouton + 5, Y_bouton + 5}
      keystroke "w" using {command down} -- Close the dialog
              end tell -- System Events…
              return
    end Rechercher_Remplacer
    --=====
    on close_palettes()
              local w, buttonX, buttonY, buttonW, buttonH
              tell application "Pages" to activate
              tell application "System Events" to tell application process "Pages"
                        set frontmost to true
                        repeat with w from (count of windows) to 1 by -1
                                  tell window w
                                            if (subrole is not "AXStandardWindow") then
                                                      tell first button to set {{buttonX, buttonY}, {buttonW, buttonH}} to {position, size}
                                                      click button 1 at {buttonX + (buttonW div 2), buttonY + (buttonH div 2)}
                                            end if
                                  end tell
                        end repeat
              end tell
    end close_palettes
    --=====
    --[/SCRIPT]
    Yvan KOENIG (VALLAURIS, France) vendredi 29 avril 2011 23:01:47
    Please :
    Search for questions similar to your own before submitting them to the community

  • Easy one! -- Phone number translator

    -- I'm writing a scirpt to translate those pesky alpha-numeric phone numbers into regular numeric phone numbers.
    -- I'm still unfamiliar with list manipulation, so I need help with the inner statements.
    set thePhoneNumber to "1-800-MY-APPLE"
    set thePhoneNumberLIST to the characters of thePhoneNumber
    set exceptions to "1234567890()- " -- chars that should be left alone
    set phoneDialKeysLIST to {",ABC,DEF,GHI,JKL,MNO,PQRS,TUV,WXYZ"}
    set x to 0
    repeat with theChar in thePhoneNumberLIST
    set x to x + 1
    if theChar is not in exceptions then -- Translate every non-exception
    -- Here's where I need help
    --Pseudo code:
    -- replace item x of thePhoneNumberLIST with the number of the item of phoneDialKeysLIST that contains theChar
    else
    -- do nothing
    end if
    end repeat
    log thePhoneNumberLIST

    property number_List : "1234567890()- " -- Valid characters.
    property letter_List : {"", "ABC", "DEF", "GHI", "JKL", "MNO", "PQRS", "TUV", "WXYZ"} -- Invalid characters.
    set phone_Number to "1-800-MY-APPLE" -- Phone number to test, and if needed - convert.
    set phoneNumberItems to the characters of phone_Number -- Create a list of characters.
    set newPhoneNumber to ""
    repeat with i in phoneNumberItems -- Cycle through phone number.
    if (number_List contains i) then
    set newPhoneNumber to (newPhoneNumber & i) -- Add a valid character to 'newPhoneNumber'.
    else
    repeat with j from 1 to (count letter_List) -- Cycle through invalid character list, to determine character position.
    -- Append numerical equivalent to end of 'newPhoneNumber'.
    if ((item j of letter_List) contains i) then set newPhoneNumber to (newPhoneNumber & j)
    end repeat
    end if
    end repeat
    newPhoneNumber -- Translated phone number.
      Mac OS X (10.4.4)  

  • File saveAsOpen and Base64 encoding...

    In order to send the activeDocument to a web service, i need to save is as a file image, and send in an xml format.
    Thus, i also need to encode it in Base64.
    At this point everything is OK.
    But between the saveAs of the file, its reopening, and its encoding, its corrupted.
    I receive an error on the Mongrel server.
    The Base64 encoder seems to work well, the rest of the code seem to be also ok, so I think my problem is either I do not save it correctly, either i do not reopen it correctly...
    Please save me :(
    Here is the code :
              /* STEP 1 : save current document as image file (temporary) */
              var docRef = activeDocument;
              var filepath=app.path.toString()+"/"+docRef.name+".jpg";//create the image file in the installation folder of Photoshop
              var file = new File(filepath);
              //var options = new ExportOptionsSaveForWeb();
              //options.format = SaveDocumentType.PNG;
              var options = new JPEGSaveOptions();
              options.quality=8;
              docRef.saveAs (file, options, true, Extension.LOWERCASE);
              //docRef.exportDocument (file, ExportType.SAVEFORWEB , options);
              file.close();
    /* I code here dialogBox and httpCOnenction object creation
    that do not need to be written here
    (but if you think it's important, i can give you the full script)
              var f= new File(filepath);
              f.open();
              var buffer = f.read(f.length);
              f.close();
    I build an HttpConnection object called "send"
    */                 send.request='"+f.name+""+f.length+""+base64encode(buffer)+"';
    Here is the Server error :
    Exception working with image: Not a JPEG file: starts with 0xc7 0xff `/var/folders/Nz/NzlixjchF+WAvFkZK9vVRU+++TM/-Tmp-/test599-0.jpg'

    Let's give you everything in fact, it will be more simple (by the way the code is suppose to become OpenSource)<br /><br />I work on Mac, Photoshop CS3 (10.0.1)<br />I use JavaScript<br />HTTP request received by a Mongrel server (Ruby on Rails)<br /><br />// Copyright 2008. Studio Melipone. All rights reserved. <br />// Licence GNU LGPL<br />// Send the active document to the UpShot web service (http://upshotit.com)<br />//  The document is sent as a .png file, as a draft on the user's account.<br />// Therefore you must have a document opened and Adobe Bridge installed to perform this script.<br /><br />/*<br />     <javascriptresource><br />          <name>UpShot</name><br />          <type>automate</type><br />          <about><br />          Script for Upshot <br />          Copyright 2008 Studio Melipone <br />          http://upshotit.com <br />          </about><br />          <enableinfo>true</enableinfo><br />     </javascriptresource>     <br />*/<br /><br />#target photoshop<br />#include "Base64.jsx"<br /><br />app.bringToFront();<br /><br />if( documents.length==0)// is a document opened ?<br />     alert("There are no Photoshop documents opened !")<br />else {<br />          /*********************************************/<br />          /* STEP 1 : save current document as image file (temporary) */<br />          /******************************************/<br />          var docRef = activeDocument;<br />          var filepath=app.path.toString()+"/"+docRef.name+".jpg";//create the image file in the installation folder of Photoshop<br />          var file = new File(filepath);<br />          //var options = new ExportOptionsSaveForWeb();<br />          //options.format = SaveDocumentType.PNG;<br />          var options = new JPEGSaveOptions();<br />          options.quality=8;<br />          docRef.saveAs (file, options, true, Extension.LOWERCASE);<br />          //docRef.exportDocument (file, ExportType.SAVEFORWEB , options);<br />          file.close();<br />          <br />          /********************************************************/<br />          <br />     // Only Bridge can use HttpConnection, so we test if it is installed<br />     var bridgeTarget = BridgeTalk.getSpecifier(getAppSpecifier("bridge")); <br />                    <br />     if( !bridgeTarget ) { <br />          alert("Adobe Bridge not installed, needed to continue."); <br />     } <br />     else {     <br />          preferences.rulerUnits = Units.PIXELS;<br />          displayDialogs = DialogModes.NO;<br />          <br />          /**********************************/<br />          /* STEP 2 : retrieve user's login & password */<br />          /*******************************/<br />          <br />          res = "dialog { text: 'UpShot authentication', \<br />                         info: Panel { orientation: 'column', alignChildren:'right', \<br />                                             text: 'Please Identify Yourself', \<br />                                             login: Group { orientation: 'row', \<br />                                                  s: StaticText { text:'Login :' }, \<br />                                                  e: EditText { characters: 30 } \<br />                                             }, \<br />                                             passwd: Group { orientation: 'row',  \<br />                                                  s: StaticText { text:'Password :' }, \<br />                                                  e: EditText { characters: 30, properties:{noecho: true} }, \<br />                                             } \<br />                                   }, \<br />                         buttons: Group { orientation: 'row', \<br />                                        okBtn: Button { text:'OK', properties:{name:'ok'} }, \<br />                                        cancelBtn: Button { text:'Cancel', properties:{name:'cancel'} } \<br />                         } \<br />                    }"; <br />          <br />          dlg = new Window (res); <br />          dlg.center(); <br />          dlg.show(); <br /><br />          var login = dlg.info.login.e.text;//retrieve the values given in the form<br />          var pass = dlg.info.passwd.e.text;<br /><br />          /******************************/<br />          /* STEP 3 : send image through Bridge */<br />          /***************************/<br />          var f= new File(filepath);<br />          f.open();<br />          var buffer = f.read(f.length);<br />          f.close();<br />          <br />          alert("file size "+file.length);<br />          alert("f size "+f.length);<br />          alert("BUF "+buffer);<br />          alert(base64encode("B64 "+base64encode(buffer)));<br />          <br />          // create a new BridgeTalk message object <br />          var bt = new BridgeTalk; <br />          // target the Adobe Bridge application <br />          bt.target  = bridgeTarget; <br />          //p173 of Javascript Tools Guide for CS3 for http message<br />          bt.body = "\<br />               if(!ExternalObject.webaccesslib ) {\<br />                    ExternalObject.webaccesslib = new ExternalObject('lib:webaccesslib');\<br />               }\<br />               var http = new HttpConnection('http://127.0.0.1:3000/en/users/get_id.xml') ; \<br />               var idfile = new File('"+app.path.toString()+"/id.xml') ;\<br />               http.response = idfile ; \<br />               http.username = '"+login+"';\<br />               http.password = '"+pass+"';\<br />               http.mime='text/xml';\<br />               http.responseencoding='utf8';\<br />               http.execute();\<br />               http.response.close();\<br />               http.close();\<br />               idfile.open();\<br />               var send = new HttpConnection('http://127.0.0.1:3000/en/users/'+idfile.read()+'/upshots') ; \<br />               send.method = 'POST';\<br />               send.username = '"+login+"';\<br />               send.password = '"+pass+"';\<br />               send.mime='text/xml';\<br />               send.requestheaders=['Host','http://localhost:3000'];\<br />               send.requestheaders=['Accept','*/*'];\<br />               send.requestheaders=['Content-Type','text/xml'];\<br />               send.request='<upshot><title>titleforyourimage</title><file_name>"+f.nam e+"</file_name><size>"+f.length+"</size><javafile>"+base64encode(buffer)+"</javafile></ups hot>';\<br />               send.execute();\<br />               idfile.toSource();\<br />          ";<br />          <br />          bt.onResult = function(result) { <br />               object = bt.result = eval(result.body);<br />               //file.remove();<br />               //object.remove();<br />               //bridge.quit ();<br />               return eval(result.body); <br />          } ;<br />          <br />          bt.onError = function( message ) { <br />               var errCode = parseInt (message.headers ["Error-Code"]); <br />               throw new Error (errCode, message.body); <br />          } ;<br />                    <br />          //send the message ( also launch the targetted application)<br />          bt.send(10);<br />     <br />     /**********************************************/<br />     /* STEP 4: Once all done, delete the image previously created */<br />     /*******************************************/<br />     }<br />}<br /><br />//////////////////////////////////////////////////////////////////<br />/////////////////////////////////////////////////////////////////<br />/*functions from http://www.ps-scripts.com/bb/viewtopic.php?t=1282 */<br />//////////////////////////////////////////////////////////////<br />/////////////////////////////////////////////////////////////<br /><br />function getAppSpecifier(appName) {<br /><br />   if (isCS2()) {<br />      if (appName == 'photoshop') {<br />         return 'photoshop-9.0';<br />      }<br />      if (appName == 'bridge') {<br />         return 'bridge-1.0';<br />      }<br />      // add other apps here<br />   }<br /><br />   if (isCS3()) {<br />      if (appName == 'photoshop') {<br />         return 'photoshop-10.0';<br />      }<br />      if (appName == 'bridge') {<br />         return 'bridge-2.0';<br />      }<br />      // add other apps here<br />   }<br /><br />   return undefined;<br />};<br /><br />function isCS2() {<br />   var appName = BridgeTalk.appName;<br />   var version = BridgeTalk.appVersion;<br /><br />   if (appName == 'photoshop') {<br />      return version.match(/^9\./) != null;<br />   }<br />   if (appName == 'bridge') {<br />      return version.match(/^1\./) != null;<br />   }<br /><br />   return false;<br />};<br />function isCS3() {<br />   var appName = BridgeTalk.appName;<br />   var version = BridgeTalk.appVersion;<br /><br />   if (appName == 'photoshop') {<br />      return version.match(/^10\./) != null;<br />   }<br />   if (appName == 'bridge') {<br />      return version.match(/^2\./) != null;<br />   }<br /><br />   return false;<br />};

  • Alignment of dynamically changing StaticText element

    Having a little trouble centering a dynamically changing StaticText element whose parent container has its alignChildren property set to 'center'. As the text of the element changes, new strings that are assigned to it are truncated to the length of the string the element initially held. If I initially place a string of blank characters that is longer in length than any anticiapted text string the element will ever hold, when the text is updated it is offeset to the left by the number of characters of the initial string that are in excess of the length of the string newly assigned to it. Any ideas or suggestions would be very much appreciated.

    Set the initial size of the StaticText with the  "characters" property, which will reserve width so it is the proper width.
    Also set "justify" to "center" so that it will always be centered within that space.
    Note that "characters" is an initial creation property only, and cannot be set after the object has been created.

  • Help! 'Package for Print' Script

    Hi all,
    I have a specific 'Package For Print' script, that needs a small modification, and and I was hoping someone could help me.
    Essentially, I need to OMIT 'Include PDF' option when packaging, since this makes things a bit wonky on my script (see below).
    Let me know if you need to see the script, and I'll post it.
    Thank you.

    Here you go, and thank you. I know notes are also included in it. Sorry about this.
    //Package the active document and setup the dockets folder structure.
    //The active document shouldn't have been saved (has no name), so provide a name
    //taken from the first and only link.  After creating the dockets folder structure,
    //close and delete the original file and open the file in the docket's originals
    //folder.
    #target InDesign
    //Constants
    const PROOF_PREFIX = 'Proof_';
    const OUTPUT_SUFFIX = ' Folder';
    const ORIGINALS_FOLDER = 'Originals';
    const PRINT_FOLDER = 'Print';
    const DIGITAL_PROOF_FOLDER = 'Digital Proof';
    const CLIENT_FOLDER = 'Client Provided Files';
    const DEFAULT_MAC_DOCKETS = '/Users/parham/Desktop';
    const PDF_PROFILE = 'Linx_Proof'
    function Err() {}
    //Use a more user-friendly version than throwing an error.
    Err.FatalError = function (msg) {
      alert(msg, 'Fatal Error', true);
      exit();
    function makeShowUI(runtime) {
      var doc = runtime.doc;
      var window = (function () {
      var windowDef = "Window {\
      type: 'dialog', \
      properties: { \
      resizeable: false, \
      closeButton: true, \
      maximizeButton: false, \
      minimizeButton: false \
      text: 'Dockets Package', \
      orientation: 'column', \
      var w = new Window(windowDef);
      //Folder name
      w.add("StaticText { text:'New Folder Name', alignment: 'left' }");
      var defaultName = doc.name;
      if (defaultName.slice(-5) == '.indd') {
      var origlength = defaultName.length;
      defaultName = defaultName.substr(0, origlength - 5);
      w.folderText = w.add("EditText { alignment: 'left', characters: 30, justify: 'left', " +
      "text:'" + defaultName + OUTPUT_SUFFIX + "'}");
      //Destination dir
      w.add("StaticText { text:'Save To', alignment: 'left' }");
      var dirGroup = w.add("Group { orientation: 'row', alignment: 'fill' }");
      w.dirText = dirGroup.add("EditText { characters: 30, justify: 'left', " +
      "text:'" + DEFAULT_MAC_DOCKETS + "'}");
      w.dirBrowseBtn = dirGroup.add("Button { text: 'Browse...' }");
      w.dirBrowseBtn.textBox = w.dirText;
      //Package Options
      w.options = w.add("Panel { orientation: 'column', alignment: 'fill', \
      text: 'Package Options', alignChildren: 'left'}");
      w.options.fonts = w.options.add("Checkbox { text: 'Copy Fonts' }");
      w.options.links = w.options.add("Checkbox { text: 'Copy Linked Graphics' }");
      w.options.profiles = w.options.add("Checkbox { text: 'Copy Color Profiles' }");
      w.options.update = w.options.add("Checkbox { text: 'Update Graphic Links In Package' }");
      w.options.hiddenContent = w.options.add("Checkbox { text: 'Include Fonts and Links From Hidden and Non-Printing Content' }");
      w.options.ignore = w.options.add("Checkbox { text: 'Ignore Preflight Errors' }");
      w.options.report = w.options.add("Checkbox { text: 'Create Report' }");
      w.options.fonts.value = true;
      w.options.links.value = true;
      w.options.profiles.value = true;
      w.options.update.value = true;
      w.options.hiddenContent.value = true;
      w.options.ignore.value = true; //Parham's request for true
      w.options.report.value = false; //Saeed's request for false (no instructions)
      //Digital Proof
      w.proof = w.add("Panel { orientation: 'column', alignment: 'fill', \
      text: 'Digital Proof', alignChildren: 'left'}");
      w.proof.make = w.proof.add("Checkbox { text: 'Make PDF Proof' }");
      w.proof.viewAfter = w.proof.add("Checkbox { text: 'View PDF' }");
      w.proof.make.value = false;
      w.proof.viewAfter.value = false;
      //OK / Cancel
      var buttonDef = "Group { orientation: 'row', alignment: 'right', alignChildren: 'right' }";
      w.bg = w.add(buttonDef);
      var okDef = "Button { text: 'OK', alignment: 'right' }";
      var cancelDef = "Button { text: 'Cancel', alignment: ['right', 'center'] }";
      w.okBtn = w.bg.add(okDef);
      w.cancelBtn = w.bg.add(cancelDef);
      return w;
      runtime.window = window;
      window.dirBrowseBtn.onClick = (function () {
      var result = Folder.selectDialog('Choose destination directory');
      if (null !== result) {
      //Replace string with selected path
      this.textBox.text = result.fullName;
      return window.show();
    function deleteFolder(folder) {
      if (!folder.exists) {
      return;
      var children = folder.getFiles();
      for (var i = 0, im = children.length; i < im; i++) {
      if (children[i] instanceof Folder) {
      deleteFolder(children[i]);
      } else {
      children[i].remove();
      folder.remove();
    //Main path
    try {
      var a = app.activeDocument;
    } catch (e) {
      Err.FatalError("No document open");
    var runtime = {};
    var doc = app.activeDocument;
    runtime.doc = doc;
    if (doc.saved) {
      //Document has already been saved (already has a name), so stop.
      Err.FatalError("Document has already been saved");
    //Ensure at least one link, since multipaged PDFs end up as more than 1 link.
    if (doc.links.length < 1) {
      Err.FatalError("Document has " + doc.links.length + " links.");
    //Save the existing file in a temporary place, same dir as first link.
    //Take the name from the first link
    var link = doc.links.firstItem();
    var defaultName = link.name;
    if (defaultName.slice(-4) == '.pdf') {
      var origlength = defaultName.length;
      defaultName = defaultName.substr(0, origlength - 4);
    } else {
      //Placed item is not a pdf, as per Parham's request, don't warn about it.
      //Just take the filename best guess and go with it.
    // if (confirm('Linked item is not a PDF.  Package anyways?',
    // true, 'Package non-PDF')) {
      //break on the last '.'
      var lastIndex = defaultName.lastIndexOf('.');
      if (lastIndex > -1) {
      defaultName = defaultName.substr(0, lastIndex);
      } else {
      defaultName = defaultName;
    // } else {
    // alert('Did not package.');
    // exit();
    //filePath should be a File, but is actually a string, so make a file.
    var linkFile = new File(link.filePath);
    var origFile = new File(linkFile.path + '/' + defaultName + '.indd');
    if (origFile.exists) {
      //Folder already exists, get user to confirm
      if (confirm("File " + defaultName + '.indd already exists.  Replace?',
      true, 'Replace File')) {
      //Erase the temp file
      origFile.remove();
      } else {
      alert('Did not overwrite existing files, did not package.');
      exit();
    doc.save(origFile);
    if (2 == makeShowUI(runtime)) {
      //User pressed cancel
      exit();
    //Main code, do the packaging and make the directories.
    //But first check for existing folder.
    var folderName = runtime.window.folderText.text;
    var destinationPath = runtime.window.dirText.text;
    if (destinationPath.slice(-1) == '/') {
      var newFolderPath = destinationPath + folderName;
    } else {
      var newFolderPath = destinationPath + '/' + folderName;
    var outputRoot = new Folder(newFolderPath);
    if (outputRoot instanceof Folder && outputRoot.exists) {
      //Folder already exists, get user to confirm
      if (confirm('Dockets folder ' + folderName + ' already exists.  Replace?',
      true, 'Replace Folder')) {
      //Erase the destination directory
      //Get all contained files + folders, then delete them.
      deleteFolder(outputRoot);
      } else {
      alert('Did not overwrite existing files.');
      exit();
    } else if (outputRoot instanceof File) {
      //Destination folder exists as a file, fail.
      Err.FatalError('File named ' + folderName + ' already exists, cannot make folder.');
    //Destination doesn't exist, create it.
    if (!outputRoot.create()) {
      Err.FatalError('Error creating folder ' + folderName);
    //We have an empty directory, now do the packaging and everything else.
    var printFolder = new Folder(newFolderPath);
    printFolder.changePath(PRINT_FOLDER);
    if (!printFolder.create()) {
      Err.FatalError('Error creating Print folder.');
    var digitalProofFolder = new Folder(newFolderPath);
    digitalProofFolder.changePath(DIGITAL_PROOF_FOLDER);
    if (!digitalProofFolder.create()) {
      Err.FatalError('Error creating Digital Proof folder.');
    var clientFolder = new Folder(newFolderPath);
    clientFolder.changePath(CLIENT_FOLDER);
    if (!clientFolder.create()) {
      Err.FatalError('Error creating Client folder.');
    var originalsFolder = new Folder(newFolderPath);
    originalsFolder.changePath(ORIGINALS_FOLDER);
    if (!originalsFolder.create()) {
      Err.FatalError('Error creating Originals folder.');
    //Do the package
    var f = runtime.window.options;
    if (doc.packageForPrint(originalsFolder, f.fonts.value, f.links.value, f.profiles.value, f.update.value, f.hiddenContent.value, f.ignore.value, f.report.value, false, true)) {
    } else {
      Err.FatalError('Failed to package.');
    //Do the PDF proof
    if (runtime.window.proof.make.value) {
      var proofname = PROOF_PREFIX + doc.name;
      if (proofname.slice(-5) == '.indd') {
      var origlength = proofname.length;
      proofname = proofname.substr(0, origlength - 5);
      proofname = proofname + '.pdf';
      var proofFile = new File(digitalProofFolder.fullName + '/' + proofname);
      if (proofFile.exists) {
      Err.FatalError('Digital proof already exists.');
      } else {
      var exportProfile = app.pdfExportPresets.itemByName(PDF_PROFILE);
      //We get an object even if the profile doesn't exist, have to check isValid
      if (!exportProfile.isValid) {
      Err.FatalError('PDF profile ' + PDF_PROFILE + " doesn't exist, digital proof not created.");
      //Explicitly set to export all pages.
      app.pdfExportPreferences.pageRange = PageRange.ALL_PAGES;
      //Set view preference
      app.pdfExportPreferences.viewPDF = runtime.window.proof.viewAfter.value;
      doc.exportFile(ExportFormat.PDF_TYPE, proofFile, false, exportProfile);
    //Open the Originals folder .indd, close the current file and delete it.
    var newFile = new File(originalsFolder.fullName + '/' + doc.name);
    if (!app.open(newFile)) {
      Err.FatalError("Failed to open packaged .indd");
    doc.close();
    origFile.remove();

  • OnClick register problem

    would you please help me in this regards
    in nav bar have a button when click the button open a dialog box. threr have a three buttons.
    when click any one i need to catch that event and close the parent dialog box.
    // Set up the navigation bar
        function buildNavbar(doc)
            // retrieve the predefined NavBar object
            // the type defaults to "scriptui"
            var bottombar = doc.navbars.filesystem.bottom;
            // display it
            bottombar.visible = true;
            // set the height
            bottombar.height = 50;
            // add a ScriptUI display frame
            bottombar.pathPanel = bottombar.add( "panel", [5,5, 480,35], undefined);  // bounds = [left, top, right, bottom]
            // add UI components to the frame
            bottombar.pathPanel.browseField = bottombar.pathPanel.add( "statictext",[3, 3, 395, 22],"");
            bottombar.pathPanel.browseBtn = bottombar.pathPanel.add( "button",[400, 3, 465, 22],"Log In");
            bottombar.pathPanel.browseField.text = doc.thumbnail.path;
            // add the button's event handler, which navigates to the log in form
            bottombar.pathPanel.browseBtn.onClick = function()
                res = "dialog { \
                    info: Panel { orientation: 'column', alignChildren:'right', \
                                    text: 'Log In Info', \
                                    name: Group { orientation: 'row', \
                                                    s: StaticText { text:'User ID:' }, \
                                                    e: EditText { characters: 30 } \
                                    addr: Group { orientation: 'row', \
                                                    s: StaticText { text:'Password:' }, \
                                                    e: EditText { characters: 30, properties:{noecho:true}} \
                            buttons: Group { orientation: 'row', \
                                                      testBtn: Button { text:'Test' }, \
                                                okBtn: Button { text:'OK', properties:{name:'ok'} }, \
                                                cancelBtn: Button { text:'Cancel', properties:{name:'cancel'} } \
                win = new Window (res);
                win.center();
                win.show();
                //$.writeln( win.info.name.e.text);
                $.writeln( win.buttons.okBtn.text);
                $.writeln( win.buttons.okBtn.properties.name.text);
                 // add the button's event handler, which navigates to the log in form
                win.buttons.testBtn.onClick = function()
                    alert('here');
            win.buttons.okBtn.onClick = function()
                    alert('here2');

    win.show(); should be after the onClick events....
    // Set up the navigation bar
    function buildNavbar(doc){       
            // retrieve the predefined NavBar object
            // the type defaults to "scriptui"
            var bottombar = doc.navbars.filesystem.bottom;
            // display it
            bottombar.visible = true;
            // set the height
            bottombar.height = 50;
            // add a ScriptUI display frame
            bottombar.pathPanel = bottombar.add( "panel", [5,5, 480,35], undefined);  // bounds = [left, top, right, bottom]
            // add UI components to the frame
            bottombar.pathPanel.browseField = bottombar.pathPanel.add( "statictext",[3, 3, 395, 22],"");
            bottombar.pathPanel.browseBtn = bottombar.pathPanel.add( "button",[400, 3, 465, 22],"Log In");
            bottombar.pathPanel.browseField.text = doc.thumbnail.path;
            // add the button's event handler, which navigates to the log in form
            bottombar.pathPanel.browseBtn.onClick = function(){
                res = "dialog { \
                    info: Panel { orientation: 'column', alignChildren:'right', \
                                    text: 'Log In Info', \
                                    name: Group { orientation: 'row', \
                                                    s: StaticText { text:'User ID:' }, \
                                                    e: EditText { characters: 30 } \
                                    addr: Group { orientation: 'row', \
                                                    s: StaticText { text:'Password:' }, \
                                                    e: EditText { characters: 30, properties:{noecho:true}} \
                            buttons: Group { orientation: 'row', \
                                                      testBtn: Button { text:'Test' }, \
                                                okBtn: Button { text:'OK', properties:{name:'ok'} }, \
                                                cancelBtn: Button { text:'Cancel', properties:{name:'cancel'} } \
                win = new Window (res);          
                //$.writeln( win.info.name.e.text);
                $.writeln( win.buttons.okBtn.text);
                $.writeln( win.buttons.okBtn.properties.name.text);
                 // add the button's event handler, which navigates to the log in form
                win.buttons.testBtn.onClick = function(){
                    alert('here');
            win.buttons.okBtn.onClick = function(){
                win.close(0);
                    alert('here2');
             win.center();
            win.show();
    buildNavbar(app.documents[0]);

  • Script lines to stop machine from sleeping while a script is running

    I have a long script (in time that is) and sometimes the machine goes to sleep while it is running, thus halting the script. Is there a line I can add to a script that keeps the machine awake while the script runs?

    so is there a way around is? how do I stop the computer going to sleep while the script runs? Or how do I protect password etc if using a script with a password in it?
    There are a number of approaches. One is to encrypt/obfuscate the password within the script, decoding it on the fly.
    Another is to store the password in the user's keychain and have the script retrieve it from there at runtime (this requires a lot more coding to capture the password on the first run, save it to the keychain and retrieve it later).
    Another option may be to edit sudoers to allow the target command to be run without authentication, although this opens a whole slew of other potential issues, of course.
    Of the three, for a program I don't expect to distribute, I'd probably go for the first option. Note that there are many ways of doing this, ranging from the trivial to the herculean - you'll need to decide how much is appropriate for your needs. One very simple approach (not recommended for high security needs) is just to put your password in a list - the data format of the list makes it more difficult than a string to extract from a read-only script, but it's only one line of AppleScript:
    property pw: {"p", "a", "s", "s", "w", "o", "r", "d"}
    set my_pw to pw as text
    You could get a little more complex by reordering the characters:
    property pw: {"d", "r", "o", "w", "s", "s", "a", "p"}
    set my_pw to reverse of pw as text
    Taking it on a step further, there are all kinds of encryption/transformation algorithms you can apply to further mask the data. Most common algorithms can be translated into AppleScript if needed.

  • Script Lines for testpattern

    Hi
    I'm Looking for a Script to generate lines for testpattern. I Need diagonal Lines for each corner
    Thanks

    so is there a way around is? how do I stop the computer going to sleep while the script runs? Or how do I protect password etc if using a script with a password in it?
    There are a number of approaches. One is to encrypt/obfuscate the password within the script, decoding it on the fly.
    Another is to store the password in the user's keychain and have the script retrieve it from there at runtime (this requires a lot more coding to capture the password on the first run, save it to the keychain and retrieve it later).
    Another option may be to edit sudoers to allow the target command to be run without authentication, although this opens a whole slew of other potential issues, of course.
    Of the three, for a program I don't expect to distribute, I'd probably go for the first option. Note that there are many ways of doing this, ranging from the trivial to the herculean - you'll need to decide how much is appropriate for your needs. One very simple approach (not recommended for high security needs) is just to put your password in a list - the data format of the list makes it more difficult than a string to extract from a read-only script, but it's only one line of AppleScript:
    property pw: {"p", "a", "s", "s", "w", "o", "r", "d"}
    set my_pw to pw as text
    You could get a little more complex by reordering the characters:
    property pw: {"d", "r", "o", "w", "s", "s", "a", "p"}
    set my_pw to reverse of pw as text
    Taking it on a step further, there are all kinds of encryption/transformation algorithms you can apply to further mask the data. Most common algorithms can be translated into AppleScript if needed.

  • The File name property is not valid. The file name is a device or contains invalid characters

    I have an SSIS task that has run successfully for years. They just moved the dtsx to a new server and now it is failing. 
    Issue:
    The task has a data flow that writes a raw file destination. It then has a subsequent data flow that reads the raw file destination. 
    The path and name of the raw file is passed to each of the data flows via the same variable. 
    The raw file resides in a folder on the server in the same path that the dtsx resides in. 
    The task fails with the "The File name property is not valid. The file name is a device or contains invalid characters" error when trying to access the raw file.
    What we have done to troubleshoot:
    1. I ran the task successfully on my local machine so it is definitely a server issue.
    2. The first thing we were seeing was that it failed trying to write to the raw file. The task is set to "Create Always". 
    3. We saw that the dba's copied over the entire directory structure from the old server which included a previously created raw file, so we deleted the raw file.
    4. We reran the task and it successfully wrote a new raw file but then failed on reading the raw file with the same error as above.
    5. We reran the task AGAIN and this time it failed trying to write the raw file throwing the same error as above.
    6. The dba looked at the directory and the account that performs the task has full control.
    7. The dba looked at the raw file that was created and verified that the account that performs the task has full control of the file and that it is the owner of the file.
    Summary:
    The task fails when trying to access the file EXCEPT when the file does not exist. In that situation it can write the file but subsequently fails in accessing it again.

    Hi Whalensdad,
    Based on my research, the issue can be caused by the following reasons:
    There are some invalid characters in the File name at package runtime. In this scenario, just as Russ said, could you please post the value that is in the File name variable? Also use a Script Task with Messagebox.show to show the variable values at runtime.
    May be it changes to others at run time.
    The account runs the package not having access to all the folders in the path. Since you are moving the dtsx file from one server to the current server, do you also move the raw file to the same folder in the current server? Does the user runs the package
    have access to all the folders in the path? To solve this, please ensure that the user has access to all folders and the raw file in the path on the current server.
    Thanks,
    Katherine Xiong
    If you have any feedback on our support, please click
    here.
    Katherine Xiong
    TechNet Community Support
    Please see the response above. I can't use a message box on a server so I logged the values to the database. The resource account has full control to the folder. I haven't been able to get the DBA to check the SQL Agents permissions, but I was always under
    the impression that if you use "Run As" on the task, it will not use the SQL Agent but the account you identify it to "Run As". The "Run As" account has full control on the folder and file.

  • "Highlight Property Value" dialogue box won't go away! Help! CS2

    Have a page that I'm working on, now every 5 seconds or so a box pops up "Highlight Property Value" asking me to enter name and value of CSS property. No amount of canceling or entering data gets rid of it.
    Never have seen this box in all my years of GoLive.
    Tried quitting and reopening GL, but still there.
    CS2 on Leopard.

    Installed as another user-set to admin, but this means I cannot work on any of my existing sites (since they are assigned to the other user- got error message). really hard to troubleshoot this way.
    Created a new page and did as many quick tasks I I could think of, but did not get the box.
    Logged out and then back in as original user to work on another site and was able to do a few tasks before the box popped up again. Once the box pops up, it's regularly every 5 seconds in all modes source, preview or layout
    I had had Leopard installed for a few weeks before this problem started.
    Could I have missed purging the offending Adobe file in the last reinstall I did on the main user?
    Is there an Apple pref that might have something to do with it?
    Prefs were easy, but it seems as though CS3 and CS2 Suites have some common named files in the Library. I am installing from the Suite disks. If I completely remove all the files that the CS2 deinstall instructions say to delete, can I be assured that I won't be deleting a critical CS3 file of the same name?
    Would love to disable that highlight function any way possible -I've never used it.

  • Unicode characters not displayed in text property

    I am developing a web application with Flex Builder. I write
    the text for each label using a font called Dhivehi which is
    written from left to right, and then copy the text and paste it in
    the label property called text.
    However in the source code view the text property of the
    label shows
    text=""
    The issue is that when rendered the text is rversed. So I
    want to run a function once the application is loaded, to reverse
    the text in the label, so that the text will appear in it's
    original way.
    any help will be very much appreciated

    Hi,
    I have a strange problem here with Windows.Forms.RichTextBox, when I assign a .ToString() value of sting builder to a rich text box’s .Rtf Property the Unicode characters containing in string builder gets converted to ???? symbols in .Rtf property of rich
    text box.
    Could you please let me know if Rich text box’s .Rtf property can hold Unicode characters? or is there any other way to store the Unicode characters in rich text box?
    Thanks & Regards,
    Tabarak
    Hello,
    To clarify and help you get proper solution, I would recommend you share a rtf string or even a simple sample which could reproduce that issue with us.
    We will based on that sample to help you.
    Regards,
    Carl
    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click
    HERE to participate the survey.

Maybe you are looking for

  • URL link in Reader won't open unless a browser is already open

    I have an issue on a Windows 7 PC using IE8 and Adobe Reader 9.3. While viewing a PDF file in Reader, and clicking on a URL link in the PDF, nothing happens unless a browser window is already open. It doesn't matter if the browser is Firefox or IE8,

  • HAI SD EXPERS KINDLY LET ME KNOW

    HERE ARE SOME INT QUESTIONS , KINDLY LET ME KNOW THE ANSWERS 1.In a sales order, if you want to give rs 10000 more than the credit limit to your customer how do you process this scenario 2.Mention some latest tickets L1 solved in ur support project 3

  • Links in template not working with index page

    Forgive me, I'm a beginner. I have a site I've built using a template with a header, footer and a side navigation bar. I need to be able to update the navigation bar regularly. The template is in the "templates" folder, most pages are in a "pages" fo

  • Error? on Example 16-7 XMLFOREST: Generating Elements with Attribute and Ch

    Error in example on page http://download-east.oracle.com/docs/cd/B19306_01/appdev.102/b14259/xdb13gen.htm#i1028612 Example 16-7 XMLFOREST: Generating Elements with Attribute and Child Elements Example appears as SELECT XMLElement("Emp",              

  • AQ adapter error

    Im trying to publish data to the B2B AQ from BPEL...im getting the following exception while publishing the object in the queue. [ Enqueue_ptt::Enqueue(Transaction-841) ] - Using JCA Connection Pool - max size = <unbounded> <2009-03-17 10:01:18,900>