{ // This script finds and/or replaces text in all the selected text layers. // // It presents a UI with two text entry areas, one for a "find" string, // and one for a "replace" string. // // When the user clicks the "Find All" button, then the selection is modified // to include only those text layers that include the "find" string as a text // value. Values in all keyframes will be examined. // // When the user clicks the "Replace All" button, the selection is modified as // in "Find All", and all instances of "find" string are replaced with the // "replace" string. Values in all keyframes will be replaced. // // A button labeled "?" provides a brief explanation. var myFindString = ""; var myReplaceString = ""; // This function is used during "Find All" // It deselects the layer if it is not a text layer, or if it does not // contain the find string. function deselectLayerIfFindStringNotFound(theLayer, findString) { var foundIt = false; // Get the sourceText property, if there is one. var sourceText = theLayer.sourceText; if (sourceText != null) { if (sourceText.numKeys == 0) { // textValue is a TextDocument. Check the string inside if (sourceText.value.text.indexOf(findString) != -1) { foundIt = true; } } else { // Do it for each keyframe: for (var keyIndex = 1; keyIndex <= sourceText.numKeys; keyIndex++) { // textValue is a TextDocument. Check the string inside var oldString = sourceText.keyValue(keyIndex).text; if (sourceText.keyValue(keyIndex).text.indexOf(findString) != -1) { foundIt = true; break; } } } } // Deselect if necessary if (foundIt == false) { theLayer.selected = false; } } // This function is called when the "Find All" button is clicked. // It narrows the set of selected layers within the active comp. // Only text layers containing the "Find String" will remain selected. function onFindAll() { // Show a message and return if there is no find string. if (myFindString == "") { alert("Find string is the empty string. The selection was not changed"); return; } // Start an undo group. By using this with an endUndoGroup(), you // allow users to undo the whole script with one undo operation. app.beginUndoGroup("Find All"); // Get the active comp var activeItem = app.project.activeItem; if (activeItem != null && (activeItem instanceof CompItem)){ // check each selected layer in the active comp var activeComp = activeItem; var selectedLayers = activeComp.selectedLayers; for (var i = 0; i < selectedLayers.length; i++) { deselectLayerIfFindStringNotFound(selectedLayers[i], myFindString); } } app.endUndoGroup(); } // This function takes totalString and replaces all instances of // findString with replaceString. // Returns the changed string. function replaceTextInString(totalString, findString, replaceString) { // Use a regular expression for the replace. // The "g" flag will direct the replace() method to change all instances // of the findString instead of just the first. var regularExpression = new RegExp(findString,"g"); var newString = totalString.replace(regularExpression, replaceString); return newString; } // This function replaces findString with replaceString in the layer's // sourceText property. // The method changes all keyframes, if there are keyframes, or just // the value, if there are not keyframes. function replaceTextInLayer(theLayer, findString, replaceString) { var changedSomething = false; // Get the sourceText property, if there is one. var sourceText = theLayer.sourceText; if (sourceText != null) { if (sourceText.numKeys == 0) { // textValue is a TextDocument. Retrieve the string inside var oldString = sourceText.value.text; if (oldString.indexOf(findString) != -1) { var newString = replaceTextInString(oldString, findString, replaceString); if (oldString != newString) { sourceText.setValue(newString); changedSomething = true; } } } else { // Do it for each keyframe: for (var keyIndex = 1; keyIndex <= sourceText.numKeys; keyIndex++) { // textValue is a TextDocument. Retrieve the string inside var oldString = sourceText.keyValue(keyIndex).text; if (oldString.indexOf(findString) != -1) { var newString = replaceTextInString(oldString, findString, replaceString); if (oldString != newString) { sourceText.setValueAtKey(keyIndex,newString); changedSomething = true; } } } } } // Return a boolean saying whether we replaced the text return changedSomething; } // Called when the "Replace All" button is clicked // Replaces the "Find String" with the "Replace String" everywhere within // the set of selected layers. Does not change the selected flag of any layers. function onReplaceAll() { // Show a message and return if there is no find string. if (myFindString == "") { alert("Find string is the empty string. No changes were made"); return; } // Start an undo group. By using this with an endUndoGroup(), you // allow users to undo the whole script with one undo operation. app.beginUndoGroup("Replace All"); // If we don't make any changes, we'll put up an alert at the end. var numLayersChanged = 0; // Get the active comp var activeItem = app.project.activeItem; if (activeItem != null && (activeItem instanceof CompItem)){ var activeComp = activeItem; // try to apply to every selected layer var selectedLayers = activeComp.selectedLayers; for (var i = 0; i < selectedLayers.length; i++) { var curLayer = selectedLayers[i]; // The method returns true if it changes any text, false otherwise. if (replaceTextInLayer(curLayer, myFindString, myReplaceString) == true) { numLayersChanged++; } } } // Print a message if no layers were affected if (numLayersChanged == 0) { // Note: if you put quotes in the interior of the string, // they must be preceded by a backslash, as in \"blue\" below. alert("The string " + myFindString + " was not found in any of the selected layers. No changes were made"); } app.endUndoGroup(); } // Called when the "Find String" is edited function onFindStringChanged() { myFindString = this.text; } // Called when the "Replace String" is edited function onReplaceStringChanged() { myReplaceString = this.text; } // Called when the "?" button is clicked function onShowHelp() { alert("Find and Replace:\n" + "Click \"Find All\" to narrow the selected layers to include only\n" + "those text layers containing the \"Find String\" in a value or\n" + "keyframe value. Click \"Replace All\" to replace all instances of\n" + "\"Find String\" with \"Replace String\"; replacements are made\n" + "only within selected text layers, and the selection remains\n" + "unchanged. Text is replaced in all values of all keyframes of\n" + "selected text layers."); } // Create and show a floating palette // var my_palette = new Window("palette","Find and Replace"); my_palette.bounds = [300,100,520,200]; // "Find String" label and text entry my_palette.add("statictext", [10, 20, 88, 40], "Find String:"); var findEditText = my_palette.add("edittext", [88,20,210, 40], ""); findEditText.onChange = onFindStringChanged; // "Replace String" label and text entry my_palette.add("statictext", [10, 45, 88, 65], "Replace String:"); var replaceEditText = my_palette.add("edittext", [88,45,210, 65], ""); replaceEditText.onChange = onReplaceStringChanged; // "Find All", "Replace All" and "?" Buttons var findButton = my_palette.add("button", [5, 70, 80,90], "Find All"); var replaceButton = my_palette.add("button", [85, 70,165,90], "Replace All"); var helpButton = my_palette.add("button", [170,70,210,90], "?"); findButton.onClick = onFindAll; replaceButton.onClick = onReplaceAll; helpButton.onClick = onShowHelp; my_palette.show(); }