Copy link to clipboard
Copied
Hello such.
My question is simple. it is possible to get bounds of a textRange or TextSelection?
Draw the rectangle already know how to do it, but do not know how I can get the coordinates to draw it. I think it's not possible.
I'm wrong?
I would greatly appreciate your help.
a greeting
The only thing that came to my mind:
Copy link to clipboard
Copied
Copy link to clipboard
Copied
feared. And a part of the text (not the entire text) even if not selected?
Thank you.
a greeting
Copy link to clipboard
Copied
The only thing that came to my mind:
Copy link to clipboard
Copied
Good approach. Extra help when doing this kind of operation is to color the desired text some key color so that when the text is converted to curves, you can easily isolate the bounds of that text by using a fill color as the 'filter' in the code.
Copy link to clipboard
Copied
here's one way of doing it.
// drawRectangleAroundSelectedTextRange
// CarlosCanto
// https://forums.adobe.com/thread/2232244
function main () {
var idoc = app.activeDocument;
var sel = idoc.selection;
if (sel.typename == "TextRange") {
var iframe = sel.parent.textFrames[0];
var dup = iframe.duplicate();
var range = sel;
var rl = range.length;
var story = range.story.textRange.contents;
var sl = story.length;
var rangeStart = range.characterOffset-1; // 1 based
var rangeEnd = rangeStart+rl;
var chars = range.story.textRange.characters;
// remove from end of selected range to end of story
if (rangeEnd < sl) {
var delrange = chars[rangeEnd];
delrange.length = sl-(rangeEnd);
delrange.remove();
}
// remove from beginning of story to beginning of selected range
var dup2 = iframe.duplicate();
delrange = dup2.characters[0];
delrange.length = rangeStart;
delrange.remove();
// remove range itself to get the first part of the text frame
range.remove();
dup2.position = [iframe.position[0]+iframe.width, iframe.position[1]];
// make outlines and draw rectangle
var igroup = dup2.createOutline();
var margins = 1.5;
var ipath = idoc.pathItems.rectangle(igroup.top+margins, igroup.left-margins, igroup.width+margins*2, igroup.height+margins*2);
ipath.filled = false;
ipath.stroked = true;
ipath.move(dup, ElementPlacement.PLACEBEFORE);
// remove duplicates
igroup.remove();
iframe.remove();
}
else {
alert('Select a Text Range and try again');
}
}
main ();
Copy link to clipboard
Copied
Woow much appreciate your response. The problem is that it only works on point text in a single line. Could adapt to mutilinea texts? (Point text and paragraph texts)?
Thank you very much again.
Apologized other question if it is not too much to ask. You could take a look at this post?
Maybe your great knowledge get me out of doubt.
I just want to know if when making a TextRange by script. This can be used manually in the program in some way (removing it with the delete key for example)
Thank you very much
Copy link to clipboard
Copied
you'll have to split your multiline text into single lines first, search the forum, there should be scripts dealing with that, there's one made by Wundes.
check these threads as well
Re: How to divide all textFrames in one-character-per-textFrame?
about the other question, I haven't found an answer either.
Copy link to clipboard
Copied
As another way - the code is written according to the algorithm, which I quoted earlier:
/**
* ai.jsx (c)MaratShagiev m_js@bk.ru 08.11.2016
* makes frame around TextRange.textSelection
* */
//@target illustrator
(function addRectByTxtSel () {
var d = activeDocument,
fr = d.textFrames[0],
re = /\s/gmi,
marg = 2,
col = new CMYKColor (),
selStart = fr.textSelection[0].characterOffset - 1, // first selected char
selLen = fr.textSelection[0].length, // text selection lenght
selEnd = selLen + selStart - 1, // last selected char
fixSelLen, selSpaces,
past, fixPastLen, pastSpaces,
frCurv, gr, rect,
selItems = [];
col.magenta = 100;
col.yellow = 100;
fixSelLen = selLen;
selSpaces = fr.textSelection[0].contents.match (re);
if (selSpaces) {
fixSelLen = selLen - selSpaces.length;
}
past = fr.textRange.characters[selEnd + 1];
past.length = fr.contents.length - selEnd - 1;
fixPastLen = past.length;
pastSpaces = past.contents.match (re);
if (pastSpaces) {
fixPastLen = past.length - pastSpaces.length;
}
frCurv = (fr.duplicate ()).createOutline ();
for (var i = fixPastLen; i < fixPastLen + fixSelLen; i++) {
var obj1 = frCurv.pageItems;
selItems.push (obj1);
}
gr = d.activeLayer.groupItems.add ();
for (var j = 0; j < selItems.length; j++) {
var obj2 = selItems
; obj2.move (gr, ElementPlacement.INSIDE);
}
rect = d.activeLayer.pathItems.rectangle (
gr.position[1] + marg, gr.position[0] - marg, gr.width + marg * 2, gr.height + marg * 2);
rect.filled = false;
rect.strokeColor = col;
gr.remove ();
frCurv.remove ();
} ());
If hyphenation in Illustrator palette is enabled, it is not working correctly (cause the hyphens are not taken in the calculation). But I think it can be fix.
Copy link to clipboard
Copied
Hello, also another way(working with multiline & hyphenation). Code based on Carlos
function main() {
var idoc = app.activeDocument;
var sel = idoc.selection;
if (sel.typename == "TextRange") {
var iframe = sel.parent.textFrames[0];
var dup = iframe.duplicate();
dup.selected = false;
var range = sel;
// log color
var col = range.characterAttributes.fillColor;
//set fill color to blank
range.story.textRange.characterAttributes.fillColor = new NoColor();
//set fill color again
range.characterAttributes.fillColor = col;
//apply outline effect
var effectStr = '<LiveEffect name="Adobe Outline Type">' + '<Dict data=""/>' + '</LiveEffect>';
iframe.applyEffect(effectStr);
iframe.selected = true;
//expand appearance
app.executeMenuCommand('expandStyle');
var igroup = app.selection[0];
var margins = 1.5;
var ipath = idoc.pathItems.rectangle(igroup.top + margins, igroup.left - margins, igroup.width + margins * 2, igroup.height + margins * 2);
ipath.filled = false;
ipath.stroked = true;
ipath.move(dup, ElementPlacement.PLACEBEFORE);
// remove duplicates
igroup.remove();
} else {
alert('Select a Text Range and try again');
}
}
main();