FoxInCloud
Problem replacing HTML in wcHTMLGen
Gravatar is a globally recognized avatar based on your email address. Problem replacing HTML in wcHTMLGen
  Paul
  All
  Dec 10, 2019 @ 08:58pm

Hi,

I have some controls nested like this :
container1
..container2
....button1, button2, ...

The buttons are added dynamically during runtime (different for each user).
I want to replace FiC's HTML for the buttons with my own HTML, so I put this in button.wcHTMLGen() :

LPARAMETERS toHTMLgen AS awHTMLgen OF awHTML.prg, tlInnerHTML && {en} doc in Parent Code {fr} doc dans le code parent

Local MetroUIHTML

Text to MetroUIHTML textmerge noshow pretext 2
	<button type="button" id="<<this.wcID>>" class="bg-orange tile-medium" title="<<this.ToolTip>>" tabindex="20" data-role="tile" data-role-tile="true"><<this.Caption>></button>
Endtext
this.wcHTML = MetroUIHTML
nodefault

But at runtime I continue to get the FiC HTML instead.
What am I doing wrong?

Also, I want to include this HTML in only the form with the buttons (to make the buttons work using the MetroUI framework) :

<script type="text/javascript" charset="utf-8" src="/awScripts/bower/jquery/dist/jquery.min.js?2.30.0-beta.4"></script>
<script type="text/javascript" src="Extensions/vendor/Metro-UI-CSS-master/build/js/metro.js"></script>
<link href="Extensions/vendor/Metro-UI-CSS-master/build/css/metro.css" rel="stylesheet">
<link href="Extensions/vendor/Metro-UI-CSS-master/build/css/metro-icons.css" rel="stylesheet">

I can put it in xxxserver.cawJSinc(), which works (not sure about the stylesheets, I think so), but I would like to know if there might be a better place for it. Maybe a better place just for the stylesheets?

Thanks
Paul

Gravatar is a globally recognized avatar based on your email address. re: Problem replacing HTML in wcHTMLGen
  Vincent H.
  Paul
  Dec 11, 2019 @ 12:28am

Hi,

  1. You can do directly: TEXT TO THIS.wcHTML ... and supress your NODEFAUT

  2. I think it's the right place. Example: RETURN DODEFAULT (m.tcJSadd + ", metro.js")

Gravatar is a globally recognized avatar based on your email address. re: Problem replacing HTML in wcHTMLGen
  FoxInCloud Support - Thierry N.
  Paul
  Dec 11, 2019 @ 02:10am

buttons are added dynamically during runtime (different for each user)

FoxInCloud generates the form's HTML upon first demand, the same for all users; if container.wlContentDynamic, HTML of content is replaced on each user request. However this dynamic HTML replacement is meant for display only and does not (yet) support user events, and your buttons must have some.

The solution is to generate ALL buttons for ALL users and to hide/show those that each user needs (I understand metroUI is responsive and uses dynamic positioning like Bootstrap, not absolute positioning like VFP and FoxInCloud's classic rendering mode)

procedure button.Init
…
wcPropSaveEdit(this, 'Visible')
return dodefault()

procedure form.Init
&& after .wlInitFirst section
for each button in container.controls foxobject
  button.Visible = function(User)
  button.Left = ?? && for desktop mode
endfor

This way the buttons' events will be properly implemented.

button.wcHTMLGen()

Your implementation should work even if, like Vincent pointed out, your code can be more simple. Also, you need to implement the button's events.

LPARAMETERS toHTMLgen AS awHTMLgen OF awHTML.prg, tlInnerHTML && {en} doc in Parent Code {fr} doc dans le code parent

local cEvents
cEvents = m.toHTMLgen.cEvents() && better outside of textmerge()
this.wcHMTL = textmerge([<button type="button" id="<<this.wcID>>" class="bg-orange tile-medium" title="<<this.ToolTip>>" tabindex="20" data-role="tile" data-role-tile="true"<<m.cEvents>>><<this.Caption>></button>])

xxxProcess.cawJSinc()

That's the way to go: .cawJSinc() for JS, .cawCSSinc() for CSS; please note:

  • these are xxxProcess methods, not xxxServer
  • you can load the library only for the master forms that need it (not applicable to child forms)
PROTECTED FUNCTION cawJSinc && <script></script>+ tags {en} for FoxInCloud, application, form [, custom] {fr} De FoxInCloud, de l'application, du formulaire[, spécifiques]
LPARAMETERS ;
  tcJSAdd; && [''] {en} Application, current form[, and custom] {fr} JS files URLs (UTF-8 encoded) {fr} URL des fichiers JS de l'application et du formulaire courant (encodés en UTF-8)
, toForm as awFrm of aw.vcx; && {en} Reference to form && {fr} Référence au formulaire
, tcForm; && {en} .Name of form {fr} Nom du formulaire

&& if inlist(m.tcForm, 'form1', 'form2', …) && possible optimization

return dodefault("Extensions/vendor/Metro-UI-CSS-master/build/js/metro.js," + m. tcJSAdd)

PROTECTED FUNCTION cawCSSinc
LPARAMETERS ;
  tcCSSadd;
, toForm as awFrm of aw.vcx; && {en} Reference to form && {fr} Référence au formulaire
, tcForm; && {en} .Name of form {fr} Nom du formulaire

&& if inlist(m.tcForm, 'form1', 'form2', …) && possible optimization

return dodefault(''; && loads custom CSS before the form's CSS
 + "Extensions/vendor/Metro-UI-CSS-master/build/css/metro.css,"
 + "Extensions/vendor/Metro-UI-CSS-master/build/css/metro-icons.css,"
 + m. tcCSSAdd;
)
Gravatar is a globally recognized avatar based on your email address. re: Problem replacing HTML in wcHTMLGen
  Paul
  FoxInCloud Support - Thierry N.
  Dec 11, 2019 @ 04:37pm

Thanks,

I found the cause of my problem : I am also replacing the HTML of the container via container.wcHTMLGen() and did not put a =dodefault() there.

I understand what you are saying about the dynamic buttons, but the dynamic buttons work correctly already without me having to do what you have suggested, with events.
I see that Form.htm contains only the HTML of the container and the button HTML is injected later via ajax.

What I am trying to do now is strip away the outer container, or at least remove its height, width etc, as it is constraining the MetroUI buttons. Can I do something to simply remove it from the HTML, or at least remove its position attributes?

Gravatar is a globally recognized avatar based on your email address. re: Problem replacing HTML in wcHTMLGen
  FoxInCloud Support - Thierry N.
  Paul
  Dec 12, 2019 @ 02:55am

the dynamic buttons work correctly already without me having to do what you have suggested, with events

My bad, since we moved from PrototypeJS to jQuery, as jQuery automatically removes the event handlers when removing elements, we now support events on dynamic contents without memory leak.

Having events implemented without executing m.toHTMLgen.cEvents()? Can't figure how it's possible…

However there's a limitation: in a multi-user environment, the server does not destroy and recreate the contained buttons for each user; in other words you will run in scenarios where an event on the button (say .click()) occurs on an ID for a button that is not instantiated on the server. You can implement the event on the parent container instead (eg. .btnClick()) and implement the button click this way:

procedure button.click()
lparameters nButton, nShift, nXcoord, nYcoord
it thisForm.wlHTMLgen
 return textmerge([FoxInCloud.MethExec(];
  + [this] && {en} event or event source object
  + [, "<<this.Parent.wcID>>"] && {en} id of HTML object matching VFP object holding the method
  + [, "btnClick"] && {en} method
  + [, <<this.btnID>>] && {en} Value to be passed as method parameter - undefined for none
  + [)];
  )
endif
return this.Parent.btnClick(this.btnID) && new property

procedure container.btnClick(btnID)
do case
case m.btnID == 1
…
endcase

Form.htm contains only the HTML of the container

I guess it contains no button at .wlInitFirst

strip away the outer container, or at least remove its height, width etc.

You need it positioned but not dimensioned so that its width and height adapt to its content. Here is what you can do:

procedure button.wcHTMLgen
LPARAMETERS toHTMLgen AS awHTMLgen OF awHTML.prg, tlInnerHTML && {en} doc in Parent Code {fr} doc dans le code parent

local cStyle, cHTML
cStyle = m.toHTMLgen.cStyle('position') && better outside of textmerge()
cHTML  = m.toHTMLgen.getHTML_(.T.) && inner HTML only && not sure it's useful is your case
this.wcHMTL = textmerge([<div id="<<this.wcID>>"<<m.cStyle>>><<m.cHTML>></div>])
Gravatar is a globally recognized avatar based on your email address. re: Problem replacing HTML in wcHTMLGen
  Paul
  FoxInCloud Support - Thierry N.
  Dec 12, 2019 @ 06:44pm

Yes, I have tried setting the container to a simple div, but FiC always injects both the position and dimension elements automatically.
Even the code you have suggested still results in all style elements being present!

Gravatar is a globally recognized avatar based on your email address. re: Problem replacing HTML in wcHTMLGen
  FoxInCloud Support - Thierry N.
  Paul
  Dec 13, 2019 @ 01:16am

No, FoxInCloud injects nothing after you set .wcHTML.

Please provide more details such as the HTML/CSS/JS generated for this container, and where you see the dimensions specified.

Gravatar is a globally recognized avatar based on your email address. re: Problem replacing HTML in wcHTMLGen
  Paul
  FoxInCloud Support - Thierry N.
  Dec 15, 2019 @ 10:50pm

You are quite right; I had =dodefault() at the end of the code and that was causing the generation of the additional tags.

The next thing I would to do is take those dynamic buttons inside the containers and use them in a custom HTML page.
In a quick test I did not get the buttons being generated - is this something I can achieve?

i.e. the form HTML is replaced by :

toHTMLgen.getHTML_()
this.wcHTML = "some new HTML"

and I use the same ID's on the divs (containers) that would normally be present in the standard FiC page.
Do you think this should work?

Thanks.

Gravatar is a globally recognized avatar based on your email address. re: Problem replacing HTML in wcHTMLGen
  FoxInCloud Support - Thierry N.
  Paul
  Dec 16, 2019 @ 05:28am

In a quick test I did not get the buttons being generated

What did your test do exactly?

use the same ID's on the divs (containers) that would normally be present in the standard FoxinCloud page

can't understand what you expect; can you post a screenshot or anything else visual?

Do you think this should work?

Don't have the slightest idea of what you expect; this code sample may help you:

* ------------------------------------------------------------
protected procedure wFormStandardPage_Output_ && {fr} page standard FoxInCloud pour un formulaire
lparameters ;
  tcTitle; && [''] <title> contents
, tcHTML; && [''] {en} HTML of page contents {fr} HTML du contenu de la page (formulaire[s])
, tcScript; && [''] {en} Script for page's form(s) {fr} Script du ou des formulaires figurant dans la page
, toForm as awFrm of aw.vcx; && {en} Reference to form && {fr} Référence au formulaire
, tcForm; && {en} .Name of form {fr} Nom du formulaire

if m.tcForm == "xx"
  this.oHTML.oControl = m.toForm.container
  tcHTML = this.oHTML.getHTML()
  text to tcHTML …
  endtext
endif

return dodefault(;
  m.tcTitle; && [''] <title> contents
, m.tcHTML; && [''] {en} HTML of page contents {fr} HTML du contenu de la page (formulaire[s])
, m.tcScript; && [''] {en} Script for page's form(s) {fr} Script du ou des formulaires figurant dans la page
, m.toForm as awFrm of aw.vcx; && {en} Reference to form && {fr} Référence au formulaire
, m.tcForm; && {en} .Name of form {fr} Nom du formulaire
)
Gravatar is a globally recognized avatar based on your email address. re: Problem replacing HTML in wcHTMLGen
  Paul
  FoxInCloud Support - Thierry N.
  Dec 16, 2019 @ 04:52pm

I have a form that works fine in FiC :
.form
..container
....container (.wlContentDynamic = .T.)
......code that adds dynamic controls per user
All good.

What I want to achieve is replace the "page/form level" HTML with something else, but keep the ability (HTML, AJAX, whatever) to have the dynamic buttons added per user to a div of the replacement page.

So, I replace the page HTML as I have done elsewhere :

function form.wcHTMLGen
toHTMLgen.getHTML_() && this generates the standard JS for the form
this.wcHTML = "some new HTML"

(This code does not call dodefault(), since calling that would render the standard HTML instead of the custom HTML. The problem is though that somewhere in the parent code the "event binding" of the dynamic controls is normally set up.)

In the custom HTML I create a div for each container using the same ID as the standard HTML - I was hoping that this would be sufficient to keep the dynamic content working. Alas not - the divs are present in the page but I assume the "trigger" for the AJAX dynamic system is not present.
I have done this before to bind the FiC events to controls in custom HTML, but I guess this is a different concept.

So, what can I do to achieve this please?
(I don't quite understand where your sample code would fit)
If this is not possible then ok, at least I know what I can and cannot do.

You may ask - why not alter the Foxpro form to achieve what I want?
Yes, that would be appropriate in many circumstances, but in this scenario I want to produce a very different "fancy HTML5" look and it seems easier to simply create new HTML.

Thanks
Paul

Gravatar is a globally recognized avatar based on your email address. re: Problem replacing HTML in wcHTMLGen
  FoxInCloud Support - Thierry N.
  Paul
  Dec 17, 2019 @ 07:27am

Hi Paul,

State maintenance/visual change detection and HTML generation are completely independent processes; IOW .wlContentDynamic and .wlContentChanged work regardless of how you generate the page's HTML, as long as the HTML elements such as <div> have id="<<this.wcID>>" (case sensitive).

If it does not work in your case, it requires some debugging.

FWIW .getHTML_() returns the generated HMTL and accepts a boolean 1rst parameter to generate inside HTML only. By using this feature you can just wrap the 'innerHTML' inside your form's 'fancy HTML5'.

© 1996-2020