Pages: 1
Print
Author Topic: Moving Rows and Columns for CALS Table  (Read 2673 times)
MrPaul
Member

Posts: 29


« on: April 05, 2013, 03:17:39 PM »

I am implementing the "Move row or column" functionality for a CALS table and am wondering about setting the enable/disable state of the following options in my dialog based on the current selection, before actually calling the internal built in functions.

- Move row up
- Move row down
- Move column left
- Move column right

Basically, if you're anywhere in the first row (or in the thead element if there's one), you shouldn't be able to move the row up so that option should be disabled. If you're in the left most column, you shouldn't be able to select "Move column left", etc. I want the dialog to display the states the same way that Author does it, but with XMAX v6.

Is there a quick way to achieve this functionality?

Thanks in advance.
« Last Edit: April 05, 2013, 03:21:35 PM by mrpaul » Logged
Derek Read
Program Manager (XMetaL)
Administrator
Member

Posts: 2621



WWW
« Reply #1 on: April 05, 2013, 04:21:17 PM »

There are no APIs that let you ask "Can the current row be moved up?" (etc...) so I think you will need to implement some logic based on the current user's selection in this case.

This type of logic would probably do it:
1. Create a Range from ActiveDocument.Selection.
2. Check to see if the Range is inside a table using InContextOfType. If it is true then continue, otherwise everything should be disabled (or you should have already checked this before even launching your own dialog)...
3. Move the Range backwards (or into the parent depending on which APIs you prefer) until you get to a row.
4. Check to see if the selection has a previousSibling that is also a row (that's a DOM call so you'd need to also convert the Range to a node to use that, otherwise you could continue moving the Range but I think using previousSibling is probably better).
« Last Edit: April 08, 2013, 11:42:56 AM by Derek Read » Logged
MrPaul
Member

Posts: 29


« Reply #2 on: April 08, 2013, 12:35:50 PM »

I'm not sure I understand your steps 3 and 4. When you talk about moving the range backwards, do you mean using ActiveDocument.Range.MoveUp()? Do I need to move up more than once to check if it has a row above the current selection or will MoveUp always go to the previous row, even if the selection is in the top most tbody row (row 2a in my example) and the table has a header?

Code:
<TableGroup>
  <table>
    <tgroup cols="3">
      <colspec colnum="1" colname="col1" colwidth="*" />
      <colspec colnum="2" colname="col2" colwidth="*" />
      <colspec colnum="3" colname="col3" colwidth="*" />
      <thead>
        <row>
          <entry colname="col1">header 1a</entry>
          <entry colname="col2">header 1b</entry>
          <entry colname="col3">header 1c</entry>
        </row>
      </thead>
      <tbody>
        <row>
   <entry colname="col1">row 2a</entry>
           <entry colname="col2">row 2b</entry>
           <entry colname="col3">row 2c</entry>
         </row>
<row>
  <entry colname="col1">row 3a</entry>
  <entry colname="col2">row 3b</entry>
  <entry colname="col3">row 3c</entry>
        </row>
      </tbody>
    </tgroup>
  </table>
</TableGroup>

I'm also unsure about what you mean for checking that previousSibling is also a row. Could you provide an example?

I have something like this:

Code:
var rng = ActiveDocument.Range;
rng.MoveUp();
if (Selection.IsEqual(rng)) {
// cannot move row up
else {
// can move row up
}

I was hoping that rng.MoveUp() would stay put when the selection is in "header 1a" in my example, but it still seems to change so this code always falls into the else...

Logged
Derek Read
Program Manager (XMetaL)
Administrator
Member

Posts: 2621



WWW
« Reply #3 on: April 08, 2013, 02:36:47 PM »

The user's selection is most likely going to be inside an entry or one of its children (if allowed by your DTD -- most DTD define paragraph-like and formatting-like elements for use inside entry, such as <para>, <bold>, etc). You need to check if the current row has a row before it. I think something similar to the following may be close to what you are looking for:

Code:
//XMetaL Script Language JScript:
//Assumptions:
//   We are working with CALS tables that use lowercase element names.
//   The document is valid.

var rng = ActiveDocument.Range;
//Check if we're in a table cell:
if(rng.InContextOfType("tablecell")) {
var nd = rng.ContainerNode;
var emergencyBreak = 0;
//If we're not already in a row then move to a parent that is:
while(nd.nodeName != "row") {
nd = nd.parentNode;
emergencyBreak++;
if(emergencyBreak > 20) {
//Something has probably gone wrong.
//"emergencyBreak" is my way of saying I threw this code together but YOU need to test it.
//Once all potential cases are handled properly this is probably not necessary.
break;
}
}
//Check if the row has a row before it:
var prevSibling = nd.previousSibling;
if(prevSibling) {
//The following check may be redundant:
if (prevSibling.nodeName == "row") {
//...your code for enabling / disabling stuff goes here...
Application.Alert("has row before...");
}
}
//Check if the row has a row before it:
var nextSibling = nd.nextSibling;
if(nextSibling) {
//The following check may be redundant:
if (nextSibling.nodeName == "row") {
//...your code for enabling / disabling stuff goes here...
Application.Alert("has row after...");
}
}
}

You would need to have similar code to check for "columns". In that case check to see if the current entry has a previousSibling.
« Last Edit: April 08, 2013, 02:47:35 PM by Derek Read » Logged
Pages: 1
Print
Jump to: