Skip to main content
1-Visitor
November 16, 2010
Question

Paste Callback ACL Question

  • November 16, 2010
  • 15 replies
  • 2633 views
Our acl code has a callback for insert_tag that detects the insertion
of specific ID elements, and assigns them a unique @ID attribute
(using the OID) upon insertion. This has worked great for years, and
due to the nature of how we were using the tags, was sufficient for
our needs.

Our new tagsets, however, lend themselves to being copy/pasted in
order to use the previous structure as the basis for new items added.
Unfortunately, the insert_tag callback does not fire on a paste.

So... I was looking into using the paste callback, but it seems that
pasted content does not trigger insert_tag, even if the given tag is
in the buffer. Furthermore, I think it might be better to use the
copy callback, since I would want the ID to remain in the case of a
cut/paste.

Does anyone know offhand if there is any easy way to interrogate the
copy/pasted tags, aside from doing some sort of search across the
actual text in the buffer?

Ultimately, all I'm trying to do is determine if the user is trying to
copy something like <tag id="id_1234"> and to automatically update the
id to something new and unique before it has been committed.

Thanks in advance for any pointers.

keith

    15 replies

    18-Opal
    November 16, 2010
    Hi Keith--

    You might try doing something like this in your paste callback:

    1) Create empty dummy document
    2) Paste content into the dummy document
    3) Do whatever you need to do to clean it up
    4) Select the tweaked content of the dummy document and copy it
    5) Dispose of the dummy document
    6) Paste the tweaked content into the original document

    --Clay
    1-Visitor
    November 16, 2010
    My colleagues and I had to do something like this a few years back. I
    don't recall all the details, but the basic approach we used was to
    have the paste callback paste the buffer into a temporary document,
    walk through and fix up any IDs that already existed in the target
    document, then yank it back into the buffer and proceed with the paste
    into the target document.

    This worked well since it only updated the IDs when absolutely
    necessary to maintain uniqueness, so moving content around in the
    document with cut and paste wouldn't break links.

    We used a sequence number, maintained in an attribute on the document
    element, which was incremented each time we needed a fresh ID, rather
    than an OID-based value. (You don't get clashes with those? Seems
    like it could happen, though probably not often.) However, I think
    the approach could work with that system, as well.

    Let me know if you want more details and I'll see if I can get my
    hands on the code to refresh my memory.

    -Brandon 🙂


    1-Visitor
    November 16, 2010
    On Tue, Nov 16, 2010 at 3:37 PM, Clay Helberg <chelberg@terraxml.com> wrote:
    > You might try doing something like this in your paste callback:

    Yeah... what Clay said. 😉 (The concise typers always seem to win the race.)

    -Brandon 🙂
    berard1-VisitorAuthor
    1-Visitor
    November 16, 2010
    Clay, Brandon... thanks,

    I was afraid that it wouldn't be as straight-forward as I had hoped.

    I might be best to do this using the Java API then. We have most of
    our tag callbacks in ACL so I thought I'd keep it there, but pretty
    much nobody is proficient in ACL here anymore. The rest of our code,
    and all of our XUI is in Java, so that's probably a better place to
    put "new" code anyway.

    I just know that even Java sometimes has to revert to ACL at times
    when there is no alternative, and was hoping on a longshot that there
    was some crafty ACL snippet I could use.

    No worries, thanks for keeping me from going down the wrong path for
    too long. ACL programming is more of a research project than
    productive for me these days, so I'd best leave it to the
    professionals 🙂

    keith

    18-Opal
    November 16, 2010
    Hi Keith--

    I'm sympathetic to your preference for Java, especially if that's what most of your customizations are written in. But ACL isn't really all that tough to pick up, and for certain things it is definitely easier. I happened to be working on a similar thing at the moment, so it's fresh in my mind, which is why I was able to out-type Brandon. 🙂

    In any case, my function to do all of those steps (except for the "Do whatever you need to do to clean it up" step, which is split out to a separate function) is less than 20 lines of code--five of which are comments. I'm probably not quite as good at Java as you are, but I know I'd be hard-pressed to come near that efficiency writing in Java/AOM.

    --Clay
    1-Visitor
    November 16, 2010
    Sounds like you've gotten some good advice, but just to chime in...

    We do something similar (well, we remove IDs on paste, not add them). In our case we add a Javascript listener to the AOMPaste event. The pasted nodes are available from the event object, and we can manipulate them directly using the DOM. In our experience that has worked pretty well.

    -James


    berard1-VisitorAuthor
    1-Visitor
    November 17, 2010
    Clay,

    Man, I definitely regret not getting together with you back when you
    were in the Boston area. Since my cross-country move, I've settled
    in to a house in Middleboro (about 45mins south of beantown) so I'll
    be here for the foreseeable future, but I digress...

    As for preference for Java... it's really the lesser of two evils.
    My company is based in Seattle, and thus a Microsoft shop. My
    background has given me quite a bit of Java experience, but
    unfortunately, it's probably as foreign to my peers as ACL. As for
    Arbortext integration... Java is certainly slower than ACL (we even
    have workarounds to allow our writers to "shut off" parts of the code
    to avoid a signal violation, ugh), but loads faster than the .NET/COM
    bridge.

    So... I guess I'm still open to ACL, but here's a sample of the old
    code I have to work with.... hopefully you feel my pain, and don't go
    "yeah, so?"

    function footnote_traverse(){
    local t;
    local h;
    local cit_counter=0;
    local i;
    local f[];

    oid_find_children( oid_null(), f, "footnote");
    $cit_counter=count(f);
    for($i=1;$i<=$cit_counter;$i++){
    o=$f[$i];
    t=oid_attr(o, "id");
    #h=oid_content(o,10);
    h=oid_xpath_string(o,"para/text()");
    gsub("<para>",",$h);
    gsub("<\/para>",",$h);
    if(length($h)>50){
    $h=substr($h,1,50);
    }

    $ft++;

    $ftLetter = format_footnote_letter($ft);
    $footnote_list_display[$ft]= "$ftLetter. $h";
    $footnote_list_id[$ft]="$t";
    }
    }

    function handle_footnotes(){
    local $foot_id;
    local $td;
    local $first_o;


    $td=";
    $td=oid_attr(oid_first(), "hsim");
    if($td=="){$td=oid_attr(oid_first(), "file_id");}
    $o=oid_current_tag();
    gsub('\(', '_', $o);
    gsub('\'', '', $o);
    gsub('\:', '', $o);
    gsub('\)', '', $o);
    gsub(',', '_', $o);
    $foot_id="f" . "$td". "$o" . ";
    insert_string -sgml "<footnote id="$foot_id"><para>Caret?></para></footnote>";

    set gentext=on;
    }

    Not terrible in the grand scheme of things, but trying to apply that
    to new code, and to avoid the myriad of "global" vars it's less than
    fun. I've also discovered quite a bit of code that has absolutely
    zero entry points, but I'm reluctant to just delete.

    Ah well... I'll take a look at this with fresh eyes in the morning,
    but since most of this is supposed to be "throw-away" code only used
    for an initial data definition and load, I'm hesitant to refactor it
    all or put too much effort into it.

    For now, my Guinness and I will sit back and reflect.

    keith

    berard1-VisitorAuthor
    1-Visitor
    November 17, 2010
    Thanks James,

    I think Java and Javascript are roughly equivalent in speed, since
    Rhino Java calls the Java API, but I could be wrong.

    We have quite a bit of compiled Java code, and a decent method of
    distribution. That said, I'll probably go with a similar solution
    to what you have used with the AOMPaste event.

    keith

    18-Opal
    November 17, 2010
    Hi Keith--

    I don't think I knew you were in Boston, or I definitely would have looked you up while I was there! Next time I'm in town I'll try to let you know and maybe we can get together for a pint.

    I feel your pain with the code. It's never fun to maintain someone else's code, especially when it's uncommented and written in an unfamiliar language. To be fair, I think a lot of the problem with the code samples you included is that it's undocumented. I can work out what it's doing if I stare at it long enough, but it really should have some comments to guide the maintainer about what it's doing and how.

    My advice on refactoring is: if you ever think you'll want to do it, do it now, if you can spare the time. It will be easier when you've been looking at it and it's in the front of your mind than if you wait until 6 months from now and have to figure it all out again from (almost) scratch. If nothing else, maybe take a few minutes and add some comments to capture what you've figured out from staring at it. That way, someday when you or one of your colleagues has to come back and make some changes, you'll have something to start from.

    --Clay
    1-Visitor
    November 17, 2010
    Well, no doubt you'll come up with the right answer. Gotta respect the judgment of a man who reflects over a Guinness.

    Cheers!
    Steve Thompson
    +1(316)977-0515