Hi Thierry,
MyEditbox.SelStart
returns always 0
.
Is it operational in FiC ?
- MyEditbox.wcPropSave = "SelStart,SelLength,SelText"
Yes it's operational however there may be a bug somewhere
Any test case we can work on?
Hi Thierry,
I need to retrieve the value of selstart.
How to do ?
Thanks in advance
Hi Vincent,
Unless we have a bug, .selStart
and .selLength
are set in any event occurring on a textbox
or an editbox
(see selS
and selL
in the screenshot below)
Thank you Thierry.
I was not sufficiently precise. When I leave a text box to click a button, I need to retrieve the cursor position
in the text.
In web mode, I don't know how to proceed
You can:
- implement
textbox.LostFocus()
- add
selStart, selLength
totextbox.wcPropSave
- in
button.click()
code, gettextbox.selStart
Thanks Thierry, but I get this:
Textbox.LostFocus()
IF ...
STORE THIS.SelStart TO Mvalproc
Do you have this code? Or can you try it?
procedure textbox.init
wcPropSaveEdit(this, 'selStart')
return dodefault()
procedure textbox.lostfocus
if thisForm.wlHTMLgen
return
endif
&& just to get .selStart updated by FoxinCloud
procedure commandButton.click
if thisForm.wlHTMLgen
return
endif
wMessageBox(this.Parent.textbox.selStart)
With your code:
can you set a breakpoint just before wMessageBox()
and see the value of .selStart
?
Always the same, 0
OK, will do a test case on my side and will report.
Thanks Thierry, I am waiting for ...
To be sure, can you check .selStart
in .lostFocus()
?
procedure textbox.lostFocus
if thisForm.wlHTMLgen
return
endif
wMessageBox(this.selStart)
LostFocus is not intercepted, I get nothing
FoxInCloud.js
does not send the .blur()
event (for .lostFocus()
) because the value has not changed.
This is a standard FoxinCloud behaviour that you can override by setting FoxInCloud.inputAlwaysBlur = true
in xxx.js
.
You can use this method for testing…
if it's satisfactory, we'll implement awTxt.wlAlwaysBlur
that will override the behaviour for a given class or instance (FoxInCloud.inputAlwaysBlur
is application-wide).
After modification, lostfocus() is interpreted correctly.
But the selstart remains at 0
Hi Vincent,
Added awTxt.wlAlwaysBlur
property, built a test form similar to your need, tested, and observed the following:
- FoxinCloud Server successfully sets
textbox.selStart
to theselS
value received from the browser at.lostFocus()
- FoxinCloud Server successfully saves this value in the form state table for user (
<userID>_<formID>_old.dbf
) - For a reason yet unknown,
.selStart
returns to 0 before or during thebutton.click()
event
Using a breakpoint in textbox.selStart_Assign()
, could not figure out where and how this 0 value gets set.
So far I have no clue how to preserve the .selStart
value across requests.
We probably can implement the button.click()
event specifically by adding the input.selStart
value read in the browser as a parameter.
Hi Thierry,
Thanks for your research.
From what I understand, the searched value can only be retrieved in the properties of the html page.
For this reason, saving textbox.selStart in a public variable in the lostFocus() does not work either ...
This code works for me:
procedure commandButton.click
lparameters nSelStart
if thisForm.wlHTMLgen
return Textmerge([jQuery.proxy(FoxInCloud.DOMEvent, FoxInCloud, jQuery("#<<this.Parent.textBox.wcID>>").prop('selectionStart'), false, event)()])
endif
thisForm.wMessageBox(, '';
+ '.selStart=' + Cast(m.nSelStart as M);
)
For me 2 😃
Big thanks
Fine! 😃
In case you also need .selLength
, we'll have to change the parameter into an object with 2 properties.
Just let us know!
Not necessary, thanks ...
Hi Thierry,
Actually, I also need selLength.
Can you tell us how to get the 2 values (selStart and selLength) ?
Thank you
Please try this code:
procedure commandButton.click
lparameters oSel
if thisForm.wlHTMLgen
local lcJS
text to lcJS textmerge noshow flag 1 pretext 3
var $input = jQuery("#<<this.Parent.textBox.wcID>>")
, oSel = {
selStart: $input.prop('selectionStart')
, selLength: $input.prop('selectionEnd')-$input.prop('selectionStart')
};
jQuery.proxy(FoxInCloud.DOMEvent, FoxInCloud, oSel, false, event)();
endtext
return m.lcJS
endif
thisForm.wMessageBox(, '';
+ 'textbox.selStart=' + Cast(m.oSel.selStart as M) + chr(13);
+ 'textbox.selLength=' + Cast(m.oSel.selLength as M);
)
Nice, thank you very much !
Small addition: the disappearance of the selection when you lose focus (default behavior) is not very "visual".
So I would have liked to be able to select the text again during a setFocus on the Editbox like this:
.SelStart = m.oSel.selStart
.SelLength = m.oSel.selLength
I saved the 2 properties concerned, but the text is not selected
I share my code (switch between lower and uppercase):
LOCAL MvalMatrice, Mselection, Mselection_inv
WITH THISFORM.PageFrame1.Page1.Matrice
MvalMatrice = .Value
oSel.selLength = m.oSel.selLength + 1
Mselection = ALLTRIM (SUBSTR (m.MvalMatrice, EVL (m.oSel.selStart, 1), m.oSel.selLength), 1, Chr(13))
DO CASE
CASE EMPTY (m.Mselection)
THISFORM.wMessageBox ("", "Pas de texte sélectionné dans la matrice en cours", 64, _SCREEN.Caption)
RETURN
CASE ISUPPER (RIGHT (m.Mselection, 1)) .AND. ISUPPER (LEFT (m.Mselection, 1))
Mselection_inv = LOWER (m.Mselection)
OTHERWISE
Mselection_inv = UPPER (m.Mselection)
ENDCASE
.Value = STRTRAN (m.MvalMatrice, Mselection, Mselection_inv)
*.SelStart = m.oSel.selStart
*.SelLength = m.oSel.selLength
.SetFocus
THISFORM.wcScriptJSadd(TEXTMERGE('jQuery("#<<.wcID>>")[0].setSelectionRange(<<oSel.selStart>>, <<oSel.selStart + oSel.selLength>>);'))
ENDWITH
Unfortunately the focus
does not work with the last instruction
Maybe
THISFORM.wcScriptJSadd(TEXTMERGE('jQuery("#<<.wcID>>").focus()[0].setSelectionRange(<<oSel.selStart>>, <<oSel.selStart + oSel.selLength>>);'))
not better, with or without .Focus
However, in the Firefox console, both syntaxes work
Looks like the second request is ignored
However, in the Firefox console, both syntaxes work
which syntaxes? please share explicitly the code you refer to.
Looks like the second request is ignored
What you call the 'second request' is unclear… please expand on details like the URL and the full server response.
THISFORM.wcScriptJSadd(TEXTMERGE('jQuery("#<<.wcID>>").focus()[0].setSelectionRange(<<oSel.selStart>>, <<oSel.selStart + oSel.selLength>>);'))
and
THISFORM.wcScriptJSadd(TEXTMERGE('jQuery("#<<.wcID>>")[0].setSelectionRange(<<oSel.selStart>>, <<oSel.selStart + oSel.selLength>>);'))
<IntuiCat>
<Result>
<v>true</v>
<t>boolean</t>
</Result>
<script>
jQuery("#genermat_scx-pageframe1-page1-matrice")[0].setSelectionRange(15, 26); jQuery('#genermat_scx-pageframe1-page2-lstmatrice').html('<option>Option1</option><option>Option2</option>');jQuery('#genermat_scx-pageframe1-page2-lstmatrice').prop('selectedIndex', -1);
</script>
<PCHTML>
<r>
<c>genermat_scx-pageframe1-page1-matrice</c>
<c>value</c>
<c>S</c>
<c>kljqdslkjqsdlk lkmlkmlkqsd klmjlmkqsdmklqsdml</c>
</r>
</PCHTML>
<script_>
window.setTimeout(function(){true && !FoxInCloud.aReqsPend.length && !FoxInCloud.focusEvent && jQuery('#genermat_scx-pageframe1-page1-matrice').focus();}, 500);
</script_>
<UserID>5XI0IFVHY</UserID>
<reqID>1141_5XJ0RXMJC-001</reqID>
<ServerVersion>2.31.0-beta.5</ServerVersion>
<ServerTimeStamp>{^2020-09-23 02:20:16 PM}</ServerTimeStamp>
<AppTime>0.012</AppTime>
<ServerTime>1.356800</ServerTime>
</IntuiCat>
Response:
<?xml version='1.0' encoding='UTF-8' standalone='yes'?><IntuiCat>
<Result><v>true</v><t>boolean</t></Result>
<script>jQuery("#genermat_scx-pageframe1-page1-matrice")[0].setSelectionRange(15, 26);</script>
<PCHTML>
<r>
<c>genermat_scx-pageframe1-page1-matrice</c>
<c>value</c>
<c>S</c>
<c>kljqdslkjqsdlk
LKMLKMLKQSD
klmjlmkqsdmklqsdml</c>
</r>
</PCHTML>
<script_>window.setTimeout(function(){true && !FoxInCloud.aReqsPend.length && !FoxInCloud.focusEvent && jQuery('#genermat_scx-pageframe1-page1-matrice').focus();}, 500);</script_>
<UserID>5XI0IFVHY</UserID>
<reqID>1141_5XJ0RUFBX-001</reqID>
<ServerVersion>2.31.0-beta.5</ServerVersion>
<ServerTimeStamp>{^2020-09-23 02:20:16 PM}</ServerTimeStamp>
<AppTime>0.023</AppTime>
<ServerTime>1.195800</ServerTime></IntuiCat>
Thanks
Testing .focus()
in console is difficult because console tend to take focus over the HTML content.
However you can observe what graphical effect happens when running each of these instructions in the console:
jQuery("#genermat_scx-pageframe1-page1-matrice")[0].setSelectionRange(15, 26);
jQuery("#genermat_scx-pageframe1-page1-matrice").focus()[0].setSelectionRange(15, 26);
jQuery("#genermat_scx-pageframe1-page1-matrice")[0].setSelectionRange(15, 26);jQuery("#genermat_scx-pageframe1-page1-matrice").focus();
Can you see any difference?
The three commands have the same effect, selecting the text
What I don't understand is why we only see one POST request and not two
I tried something else. After saving SelStart and SelLenght in the button.click(), I put that into .Matrice.GotFocus():
IF (Type('m.thisForm.wlHTMLgen') == 'L' AND m.thisForm.wlHTMLgen)
RETURN TEXTMERGE('jQuery("#<<THIS.wcID>>")[0].setSelectionRange(<<THIS.SelStart>>, <<THIS.SelStart + THIS.SelLength>>);')
ENDIF
It does not work. On suspend, the values of SelStart and SelLenght are OK.
But this works (in the same method):
IF (Type('m.thisForm.wlHTMLgen') == 'L' AND m.thisForm.wlHTMLgen)
RETURN TEXTMERGE('jQuery("#<<THIS.wcID>>")[0].setSelectionRange(1, 5);')
ENDIF
And I don't see a POST request for this selection.
Lost there ...
your code
procedure ebx.gotFocus
IF (Type('m.thisForm.wlHTMLgen') == 'L' AND m.thisForm.wlHTMLgen)
RETURN TEXTMERGE('jQuery("#<<THIS.wcID>>")[0].setSelectionRange(<<THIS.SelStart>>, <<THIS.SelStart + THIS.SelLength>>);')
ENDIF
…
This code generates a static JavaScript in genermat_scx.htm
; THIS.SelStart
and THIS.SelLength
are evaluated once at initial HTML/CSS/JS generation, not dynamically at run time.
Also, Event executes this JavaScript code without sending a request to the server. To send a request to the server, you need to return .T.
or return "jQuery.proxy(FoxInCloud.DOMEvent, …)"
(see documentation in aw*.gotFocus()
)
You can try this:
procedure cmd.click
…
.SetFocus
THISFORM.wcScriptJSadd(TEXTMERGE('jQuery("#<<.wcID>>").data('oSel', {selStart: <<oSel.selStart>>, selEnd: <<oSel.selStart + oSel.selLength>>});'))
ENDWITH
procedure ebx.gotFocus
IF (Type('m.thisForm.wlHTMLgen') == 'L' AND m.thisForm.wlHTMLgen)
local lcJS
text to lcJS textmerge noshow flags 1 pretext 3
var oSel = jQuery(this).data('oSel');
if (oSel) this.setSelectionRange(oSel.selStart, oSel.selEnd);
endtext
RETURN m.lcJS
ENDIF
Great, it works well !
I still have to reset selStart and selEnd to 0 so as not to have the selection at each (other focus)
Like that:
IF (Type('m.thisForm.wlHTMLgen') == 'L' AND m.thisForm.wlHTMLgen)
LOCAL lcJS
TEXT TO lcJS TEXTMERGE NOSHOW FLAGS 1 PRETEXT 3
var oSel = jQuery(this).data('oSel');
if (oSel) this.setSelectionRange(oSel.selStart, oSel.selEnd);
if (oSel) jQuery(this).data('oSel', {selStart: 0, selEnd: 0});
ENDTEXT
RETURN m.lcJS
ENDIF
you can group instructions in a single if
:
IF (Type('m.thisForm.wlHTMLgen') == 'L' AND m.thisForm.wlHTMLgen)
LOCAL lcJS
TEXT TO lcJS TEXTMERGE NOSHOW FLAGS 1 PRETEXT 3
var $this = jQuery(this), oSel = $this.data('oSel');
if (oSel) {
this.setSelectionRange(oSel.selStart, oSel.selEnd);
$this.data('oSel', {selStart: 0, selEnd: 0});
}
ENDTEXT
RETURN m.lcJS
ENDIF