Selecting the element from the middle of its content

Having trouble installing Oxygen? Got a bug to report? Post it all here.
SmitaPatil
Posts: 93
Joined: Mon Aug 08, 2022 2:32 pm

Selecting the element from the middle of its content

Post by SmitaPatil »

Hi Team,
We observed that, in oxygen web author, if we select any element from middle of its content as shown in below image
image.png
image.png (4.99 KiB) Viewed 1196 times
If in case user has selected any of the close tag or end tag then Selection should spread for that complete element. as shown in below image.
image.png
image.png (3.86 KiB) Viewed 1196 times
Can you please tell if there is any configuration we need to make to achieve it?
Please let me know if you need any more clarification on it.

Thanks & Regards,
Smita
mihaela
Posts: 490
Joined: Wed May 20, 2009 2:40 pm

Re: Selecting the element from the middle of its content

Post by mihaela »

Hello,

If I understand correctly you want the entire element to be selected when the user selects its start or end tags.

There is no option to activate this behavior, but you can create a JavaScript Plugin that uses the SelectionManager JS API to change the selection in these cases.
The selection manager can be obtained by listening on the workspace object for the EDITOR_LOADED event, like this:

Code: Select all

workspace.listen(sync.api.Workspace.EventType.EDITOR_LOADED, function(e) {
  var editor = e.editor;
  var selectionManager = editor.getSelectionManager ();
}); 
Best Regards,
Mihaela
Mihaela Calotescu
http://www.oxygenxml.com
SmitaPatil
Posts: 93
Joined: Mon Aug 08, 2022 2:32 pm

Re: Selecting the element from the middle of its content

Post by SmitaPatil »

Hi Mihaela,

Thank you so much.
I am trying out in the way you suggested.
Here one help needed. I tried getNodeAtSelectionStart() , getNodeAtAnchor_() , getNodeAtSelectionEnd() methods but it is not giving me the correct node.
But in below screenshot as you can see I have selected cite.query's start tag. I want to get the node for which start or end tag has been selected.
image.png
image.png (52.77 KiB) Viewed 1158 times
If possible can you please let me know if there is method available to get node name if its start or end tag has been selected already?

Thanks & Regards,
Smita
Bogdan Dumitru
Site Admin
Posts: 142
Joined: Tue Mar 20, 2018 5:28 pm

Re: Selecting the element from the middle of its content

Post by Bogdan Dumitru »

Hello Smita,

We've analyzed in depth your requirement and unfortunately, Web Author doesn't have such a configuration option that can be enabled to have only balanced selections.

We've analyzed how would that be implemented with the currently existing API and many questions arise. We propose to analyze it by dividing it into two separate tasks:
  1. the detection mechanism that knows when the selection should be corrected
  2. the actual correction of the selection
Regarding the detection part:
  1. do you consider correcting the selection changed by the mouse too? How do you intend to implement it in order to not break the built-in drag process that changes the selection? We ask because we sense that if you change the selection programmatically while the user has the mouse button pressed and extends the selection, you might break his action and he wouldn't be able to extend it even if he still has the mouse button pressed.
  2. do you consider that if using No Tags view mode, users may accidentally select the whole element when trying to select the last text within an element? That's because the end tag is invisible and the user might easily select it by mistake.
  3. do you consider the case when a user is trying to select the last text within an element with the mouse by dragging the cursor but selects by mistake the end tag while trying to select just the text, then it moves the mouse to have only the text selected? In this case, if the selection is corrected just after the tag is selected the user would be able to correct its selection or it would have to create another one?
  4. do you consider correcting the selection only on demand, when the user explicitly presses a button?
Regarding the correction part:
  1. do you need to correct the selection only with JS API? If not, notice the Java API ro.sync.exml.workspace.api.editor.page.author.WSAuthorEditorPageBase.getBalancedSelection(int, int).
  2. to easily visualize each sync.api.dom.Node you can use the getHtmlNode() non-API method in order to actually see each node in the Elements tab from Developer Tools.
  3. to create a selection around a node notice that you can use sync.api.Selection.createAroundNode
  4. to check whether or not the selection should be fixed we suggest to use sync.api.PositionInformation (sync.api.Selection.getCaretPositionInformation) and write if-s for every possible scenario (when a text node is after the selected end tag, when an element follows the selected end tag, when the element is wrapped in another element, etc.). Notice that you'll have to traverse the document DOM tree by using the "nextSibling", "previousSibling", "parentNode", properties from the sync.api.dom.Node objects etc.
    The code may be somewhat like this:

    Code: Select all

    var selectionManager = workspace.currentEditor.getSelectionManager();
    var caretInformation = selectionManager.getSelection().getCaretPositionInformation();
    if (selectionManager.getSelection().getCaretPositionInformation().isOnStartTag() ) {
      var nodeAtCaret = caretInformation.getNodeOfTag();
      var isJustEndTagSelected = nodeAtCaret.previousSibling.isSameNode(selectionManager.getSelection().getNodeAtSelectionStart());
    } else if (selectionManager.getSelection().getCaretPositionInformation().isOnEndTag()) {
      var isJustEndTagSelected = caretInformation.getNodeOfTag().isSameNode(selectionManager.getSelection().getNodeAtSelectionStart().parentNode);
    } else if (selectionManager.getSelection().getCaretPositionInformation().isOnText()) {
      var nodeAtCaret = selectionManager.getSelection().getNodeAtSelectionEnd(true);
      var isJustEndTagSelected = nodeAtCaret.previousSibling?.isSameNode(selectionManager.getSelection().getNodeAtSelectionStart());
    }
    
Bogdan Dumitru
http://www.oxygenxml.com
Serban
Posts: 2
Joined: Mon Jan 09, 2023 3:43 pm

Re: Selecting the element from the middle of its content

Post by Serban »

Hello Smita,
I found your use case interesting and wanted to see if it can actually be implemented.
I have analysed Bogdan's reply and also made some adjustments. I've managed to reach a potential proof of concept that can help you solve your problem. The following code also contains comments in order to ensure an efficient understanding of each case. You can test it by opening a document, then open the developer tools and run the below script in the console.

Code: Select all

workspace.currentEditor.getSelectionManager().listen(sync.api.SelectionManager.EventType.SELECTION_CHANGED, () => {
  var selectionManager = workspace.currentEditor.getSelectionManager();
  
  // Prerequisite knoledge: The document position (like a caret) reffers the tag or character to the right of it.
  var caretInformation = selectionManager.getSelection().getCaretPositionInformation();
  if (selectionManager.getSelection().getCaretPositionInformation().isOnStartTag() ) {// Check if the selection's caret is on a start tag (a start tag follows the caret)
    // Handles the case when selection ends before a start tag ( <b>abc SEL_START def</b> SEL_END <i>  ... )
    
    // Checks if just an end tag is selected (unbalanced selection) by comparing the element denoted by selection's start position against the previous sibling of the node denoted by the caret position.
    var nodeAtCaret = caretInformation.getNodeOfTag();// Store the node corresponding to the start tag present at the caret position.
    var isJustEndTagSelected = nodeAtCaret.previousSibling?.isSameNode(selectionManager.getSelection().getNodeAtSelectionStart());
    if( isJustEndTagSelected) {
      // Extend the selection to cover the start tag too.
      selectionManager.setSelection(selectionManager.createAroundNode((selectionManager.getSelection().getNodeAtSelectionStart())));
    }
  } else if (selectionManager.getSelection().getCaretPositionInformation().isOnEndTag()) {// Check if the selection's caret is on an end tag (an end tag follows the caret)
    // Handles the case when selection ends before a wrapping element ( <i><b>abc SEL_START def</b> SEL_END </i> 

    var nodeAtCaret = caretInformation.getNodeOfTag();// Store the node corresponding to the end tag present at the caret position.
    var isJustEndTagSelected = nodeAtCaret.isSameNode(selectionManager.getSelection().getNodeAtSelectionStart().parentNode);
    if( isJustEndTagSelected) {
      // Extend the selection to cover the start tag too.
      selectionManager.setSelection(selectionManager.createAroundNode((selectionManager.getSelection().getNodeAtSelectionStart())));
    }
  } else if (selectionManager.getSelection().getCaretPositionInformation().isOnText()) { // Check if the selection caret is on text (a text follows the caret)
    // Handles the case when selection ends before a text node ( <b>abc SEL_START def</b> SEL_END ghi )

    // Checks if just an end tag is selected (unbalanced selection) by comparing the element denoted by selection's start position against the previous sibling of the text node denoted by the caret position.
    var textNodeAtCaret = selectionManager.getSelection().getNodeAtSelectionEnd(true); // Store the text node corresponding at the caret position.
    var isJustEndTagSelected = textNodeAtCaret.previousSibling?.isSameNode(selectionManager.getSelection().getNodeAtSelectionStart());
    if( isJustEndTagSelected) {
      // Extend the selection to cover the start tag too.
      selectionManager.setSelection(selectionManager.createAroundNode((selectionManager.getSelection().getNodeAtSelectionStart())));
    }
  }
});
I hope this will be useful!
Best regards,
Serban
SmitaPatil
Posts: 93
Joined: Mon Aug 08, 2022 2:32 pm

Re: Selecting the element from the middle of its content

Post by SmitaPatil »

Hi Serban,
I have tried it through developer tools.
its working only endtag is selected.
if we select start tag as shown below whole element is not getting selected.
image.png
image.png (4.5 KiB) Viewed 1039 times
and in also it failed even if end tag is selected
I think it can be done by applying same logic as start tag. I will look into it.
as shown in below screenshot cite.query is half way selected. selection could,'t able to spread over cite.query.
image.png
image.png (54.26 KiB) Viewed 1037 times

Thank you.

Thanks & Regards,
Smita
Last edited by SmitaPatil on Tue Jan 17, 2023 8:12 pm, edited 2 times in total.
Serban
Posts: 2
Joined: Mon Jan 09, 2023 3:43 pm

Re: Selecting the element from the middle of its content

Post by Serban »

Hello Smita,
The above code that I posted is just a proof of concept that was designed for selections from left to right. I believe that the functionality for selecting from right to left could be duplicated somehow.

Serban
SmitaPatil
Posts: 93
Joined: Mon Aug 08, 2022 2:32 pm

Re: Selecting the element from the middle of its content

Post by SmitaPatil »

Thanks Serban, I will implement it.
SmitaPatil
Posts: 93
Joined: Mon Aug 08, 2022 2:32 pm

Re: Selecting the element from the middle of its content

Post by SmitaPatil »

.
Post Reply