| |
| Web Control - Initialization |
|
Private Sub Form_Load()
Dim dum, strT
tboLinkID = Form_fsubMainLinks!anID
web2.Object.Navigate "about:blank"
dum = fWaitTillReady()
web2.Object.Document.DesignMode = "On"
web2.Object.Document.ExecCommand "AbsolutePosition", False, True
web2.Object.Document.ExecCommand "2D-Position", False, True
web2.Object.Document.bgColor = fHexSwap(Hex(14603987))
dum = fWaitTillReady()
If IsNull(Form_fsubMainLinks!tboNoteBig) Then
web2.Object.Document.body.innerHTML = ""
Else
If Form_fsubMainLinks!tglAbs Then
Form_fsubMainLinks!tboAbstract = fRegExp(Form_fsubMainLinks!tboAbstract, "([^;]*);", "<SPAN v2=$1>$1;</SPAN>", True)
web2.Object.Document.body.innerHTML = Form_fsubMainLinks!tboAbstract
Else
Form_fsubMainLinks!tboNoteBig = fRegExp(Form_fsubMainLinks!tboNoteBig, "([^;]*);", "<SPAN v2=$1>$1;</SPAN>", True)
web2.Object.Document.body.innerHTML = Form_fsubMainLinks!tboNoteBig
End If
End If
dum = fWaitTillReady()
End Sub
Private Function fWaitTillReady()
Do While web2.Object.ReadyState <> 4
DoEvents
Loop
End Function
|
To explain. In this example, we'll call the web browser control that was added to the form - web2.
For some of these things, it's best to get a reply, to wait, until the control
has done something.
And calling this little wait til ready routine does that trick.
It has to come back as 4, or else it just continues to wait.
By using the Navigate method to go to a blank page, it won't try to load anything;
or if you prefer, it's loading a blank page.
This is just like a mini-browser.
The all-important DesignMode is switched on, as you can see.
And the hex swap merely takes a hex value with 6 digits and swaps the first two for the last two, swapping
red and blue values in other words, to correct for the way Hex returns its value.
This web control is placed in a popup form. Let's call it, popWebC.
It doesn't have to be a popup. It just is in this example.
The size of this popup and the size of the web2 control
are set in the form's 'design mode'.
You stretch out both form and web browser control to the largest size you might prefer.
Then you will change one of the properties on the control (such as including address bar, etc).
Then save the form.
Now once you popup this form, you're editing a blank page, in this case.
And here it's simply loaded with what is in a particular field showing in the form which pops it up;
that form is named, Form_fsubMainLinks, in this example.
In fact, the unique ID of the underlying record is saved at the start (to a text control on the popup) in order to double-check when
the popup is closed.
The web control doesn't automatically move or update with the underlying form.
The form knows about the web control, as it were, but the web control doesn't know about the form, except
to check for toggle switches.
You could provide a follow-along update, with some more programming.
But there are cases where you don't want this, where you want it unlinked as it were.
So given this approach, and perhaps by mistake, one could open the popup and then lose it behind other windows.
You might forget about it and then move to another record on the form.
And you probably don't want to close the edited result on the new record, a different record, except in some very particular case.
Only one instance of the popup will be open.
So here the same popup serves double duty.
There are a couple of toggles on the form which pops it up.
The popup can be used to edit the field which is linked to a text box, tboNoteBig, which holds the contents of a memo field (very large text field).
Or it can also edit tboAbstract, which is a summary of the longer 'bigger' note.
So before popping anything up, these are toggle buttons
are pressed or released in order to determine which gets edited by the web control.
Again, one toggle is for the big note. The other toggle is for the abstract.
See that, just below.
Now, the control first loads nothing, a blank page.
Then whichever field is loaded into the innerHTML property of the web control.
Edit mode is on. Ready to go.
Whichever field is edited by the web browser control, the same transform is used.
And you can see that this transform is a regular expression (actually another custom routine covering the actual
Microsoft regex).
The purpose of this is just to handle high unicode values.
If you just specify the unicode as a numeric entity (similar to   which is for a space or blank letter, but which have values > 255), while this will look as intended in the web control, which can handle unicode characters directly, you can't save it for next time.
Next time, you will just see a question mark in that spot, instead; that's assuming the underlying fields are incapable of storing unicode, directly.
So this places a span around the unicode character, and saves its 'cell' number, its code, its position in the font file, as an attribute.
When it comes time to save the edited text, then it's easy enough to perform another transform
and get all the unicode once again represented as numeric entities, which themselves are just plain text.
The SPAN is used because it both doesn't change the display and is a legit HTML tag.
It will survive any auto-edit or filtering done by the web control before this reverse transform can be performed.
Other elements conceivably could be automatically removed, and the scheme would not work.
And this also assumes that no other legitimate SPAN has for its first attribute - v2.
As mentioned, in this example, the web control is in a popup window/form:
|
Private Sub tglNoteBig_Click()
If Len(tboNoteBig) > 0 And tglAbs = False Then
DoCmd.OpenForm "popWebC"
Else
tglBigNote = False
End If
End Sub
Private Sub tglAbstract_Click()
If Len(tboNoteBig) > 0 And Len(tboAbstract) > 0 And tglNBig = False Then
DoCmd.OpenForm "popWebC"
Else
tglRheimsSum = False
End If
End Sub
|
If one were curious, in other words. In short, if one toggle is down, then the other is locked out.
And you could transfer one to the other, after the popup is opened, by switching the opener toggle up and the other down,
and then closing/saving the popup. But this is getting a bit too much into a particular
example, rather than the web control itself.
Because this example sets up a web control in a pop-up window/form, sort of a 'zoom view'-plus
for a particular field and text box in an underlying form,
there finally comes the time to close the window.
Edit complete.
As the innerHTML was used to load the web control, so it is read to get the final HTML text:
|
Private Sub Form_Close()
Dim response, strT As String
If tboLinkID <> Form_fsubMainLinks!anID Then
response = MsgBox("This is not the link you started with" & vbCrLf & vbCrLf & "Save it anyway?", vbYesNo, "NOT THE SAME LINK")
If response = vbNo Then Exit Sub
End If
Do While InStr(web2.Object.Document.body.innerHTML, "<font") = 1
web2.Object.Document.body.innerHTML = web2.Object.Document.body.firstChild.innerHTML
Loop
strT = web2.Object.Document.body.innerHTML
Form_fsubMainLinks.sPop fRegExp(strT, "]*).>.*?/SPAN>", "$1;", True)
End Sub
|
But first, the unique id, which was previously saved, is double-checked against the id of the current form record.
If it's a match, if everything is okay, then any leading FONT tags are removed.
And lastly, the regular expression is used to turn those spans back into just the numeric entities for unicode characters.
The edited text is passed to a routine on the main form, which in turn will update the record.
Again, and as suggested above, the use of SPAN to tag unicode during editing also calls to mind something else
of this Microsoft web browser control.
The control, the code, the libraries, are designed on a certain model of HTML, and will not allow just any attribute for any tag.
In some cases, if you add in unexpected attributes, then edit that field, the attribute
will be gone when you save it back.
One trick is just to prefix a space before the value of the attribute.
So if you want to add a class attribute most unexpectedly to something like a line break, <BR>,
it would be - <BR class=" whatever">. Note the leading space before, "whatever".
Then, when it comes time to assemble the final page, a simple regexp or other
text replace routine can be used to remove that leading space from all class attributes.
Since this is HTML markup, there will come a point where you might want to go beyond the built
in commands.
It's recommended that you stick with these for simple markup, like bold (ctrl-b), italic (ctrl-i), simple anchor/hyperlink (ctrl-k), etc.
But you might want to add some elaborate tag and attribute values of your own, to a highlighted
section of text - a range of text.
How do you do that?
You can highlight some text with the mouse.
Then you have to read where in the field that is.
This can be done using the IHTMLTxtRange class:
|
Public Function fTglElement(strElmt As String, flgNest As Boolean, strAttr As String)
Dim txtRng As IHTMLTxtRange
Set txtRng = web2.Document.selection.createRange
If Len(txtRng.HTMLText) > 0 Then
If txtRng.parentElement.tagName = strElmt And Not flgNest Then
txtRng.parentElement.outerHTML = txtRng.parentElement.innerHTML
Else
txtRng.pasteHTML "<" & strElmt & strAttr & ">" & txtRng.HTMLText & "" & strElmt & ">"
End If
DoEvents
End If
End Function
|
The highlight range is found by using the createRange method, as shown.
This object/class, IHTMLTxtRange, has a property where one can double-check
that there actually was a selection.
If greater than zero, there is also another flag, just in this particular routine and example, used to check
if the immediately superior element is just the same as the one to be added, here.
There may be some case where you'd want to nest the same element/tag in the HTML.
But if not, or if you just hit the button one too many times,
then the text is enclosed in the single tag, and whatever list of attributes is included.
You can also just paste in special characters in the same way:
Public Function fSpecialKey(strKey As String)
Dim txtRng As IHTMLTxtRange
Set txtRng = web2.Document.selection.createRange
txtRng.pasteHTML (strKey)
DoEvents
End Function
|
In both cases, it might assume that you've created a button bar in the Office application, with special
buttons for the custom tags, or special characters. But that's beyond the present scope.
Once again, surely more could be added.
It's essentially a simple control.
But there are some references below for both this and the treeview which might provide some further detail and inspiration.
|