Download edit
* sources: Note that the Sources link given at tkhtml.tcl.tk is out of date.Documentation edit
Introduction edit
By itself, Tkhtml 3.0 doesn't provide much of the functionality that embedding a web browser would. Tkhtml has no idea that there is anything special about an <a> tag, let alone the "href" attribute, so clicking on a hyper-link does nothing by default. Without extra configuration, Tkhtml doesn't understand the significance of a <style>, <title> or <img> tag.Instead, the widget concentrates on providing interfaces that allow the majority of policy decisions to be made by the user. For example, the widget can be queried for the document node that generated the content at any point in the viewport. When an end-user makes a mouse-click, the script can query the html widget for the relevant document node and decide for itself if a hyper-link should be followed, some javascript executed, the selection cleared, or some other application specific action.If an application designer deems that the contents of any <style> tags in the document should be parsed as CSS style sheets, they configure Tkhtml to pass the contents of each parsed <style> tag to a handler script that in turn passes it back to the Tkhtml style command.Tkhtml doesn't really have too much of a dependancy on HTML either. Most HTML behaviour, i.e. the fact that a <b> tag means use bold font, is configured using a built-in default stylesheet document. Execute the following script if you want to see this document:package require Tkhtml 3.0 html .h .h cget -defaultstyleRight now the parser is a holdover from Tkhtml 2.0 and only recognizes valid html tags. But in the long run it will be possible to display any old XML document formatted using CSS stylesheets.Tkhtml is designed with the expectation that most users will use a megawidget that provides many of these features. A megawidget to support common HTML constructs, Hv3, is being developed and distributed as part of Tkhtml, But Tkhtml is useful by itself as well.
Running the Examples
hv3 is a demo application of Tkhtml 3. starkits are available that wrap Tkhtml into a minimal web browser so you can see how it goes on complicated web pages available via HTTP. There are screenshots there too.A Fancy Label Widget edit
The simplest use of the html widget is as a fancy label widget. For example:# Load the Tkhtml package package require Tkhtml 3.0 # Create and populate an html widget. html .label -shrink 1 .label parse -final { <b>Hello <i>world</i></b> example } # Pack the new html widget pack .label bind .label <KeyPress-q> exit focus .labelThis code creates and packs a somewhat unremarkable label containing the HTML-formatted text. There are no default bindings, those all have to be supplied by the user.The most visible difference between Tkhtml 3.0 and it's predecessor is that Tkhtml supports stylesheets and the "style" attribute. To illustrate:
package require Tkhtml 3.0 # Create and populate an html widget html .button -shrink 1 .button parse -final {<html><div>Exit!</div> Click to Exit :)} .button style { /* This is a CSS style sheet */ div { border:solid 2px; border-color: white grey30 grey30 white; background: grey85; padding: 5px 0px; margin: 0px auto; text-align: center; width: 10ex; } html { background: grey85; font-family: Helvetica; font-weight: bold; padding: 5px; } } # Pack the new html widget pack .button bind .button <1> exit focus .buttonTkhtml 3.0 supports most of the CSS 1.0 properties and selectors, giving the programmer good control over the document layout. A precise description of what is supported and what is not may be found at http://tkhtml.tcl.tk/support.html .
A Geometry Manager edit
Tkhtml is good for more than just static text and borders, it can also manage other Tk widgets. Here's a simple example - this time featuring a real live button, not a fake like before.package require Tkhtml 3.0 # Create and populate an html widget html .manager -shrink 1 .manager parse -final { <html> <div widgetcmd="button .manager.button -text Exit! -command exit" style="margin: auto" /> Click the above button to exit. } # The tricky bit! foreach nodeHandle [.manager search {[widgetcmd]}] { $nodeHandle replace [eval [$nodeHandle attribute widgetcmd]] } # Pack the new html widget pack .managerOnce Tkhtml has parsed a document, it exposes the tree structure to the application via "node-handles". Each node-handle is itself a Tcl command, with a set of sub-commands that can be used to query and manipulate the document node. For example the command:
$nodeHandle attribute widgetcmdreturns the value of the "widgetcmd" attribute of node $nodeHandle. Assuming the variable $nodeHandle contains the node-handle for the <div> in the example above, this command would return the string "button .manager.button -text Exit! -command exit".The command:
$nodeHandle replace $widgettells Tkhtml that instead of drawing content for the node $nodeHandle, map the Tk window $widget into the html display. The other new command introduced here is:
$html search $selectorThis command searches the document tree for nodes that match the criteria specified by $selector. The format for the search criteria is a CSS 1.0 selector. The selector used in the above example, "[widgetcmd]" matches all nodes that have an attribute named "widgetcmd".Here's a more elaborate example of the same idea:
package require Tkhtml 3.0 # Create and populate an html widget html .manager -shrink 1 .manager parse -final { <html> <body> <h1 style="text-align:center">XYZ Company Complaints Interface</h1> <table border=0 align=center style="border:1px solid"> <tr> <td>First Name<span style="color:red">*</span>: <td><div widgetcmd="entry .manager.entry1"> <tr> <td>Last Name<span style="color:red">*</span>: <td><div widgetcmd="entry .manager.entry2"> <tr> <td>Employer: <td><div widgetcmd="entry .manager.entry3"> </table> <hr> <div widgetcmd="text .manager.text" /> <hr> <table border=0 align=center cellpadding=10 style="border:1px solid"><tr> <td><div widgetcmd="button .manager.send -text Send -width 20" /> <td><div widgetcmd="button .manager.cancel -text Cancel -width 20" /> </table> </html> } # Trickery! foreach nodeHandle [.manager search {[widgetcmd]}] { $nodeHandle replace [eval [$nodeHandle attribute widgetcmd]] } .manager.text insert 0.0 "Enter message here." # Pack the new html widget pack .manager -fill both -expand truePlease Note: The code in the above examples executes Tcl scripts embedded in the document passed to the html widget. This is Ok, because in this case the document is embedded in the application itself. There is no way for the html widget to get hold of an external document that may contain malicious scripts. It would be very foolhardy indeed to use the same techniques in an application that might obtain documents from external sources. Cough... internet explorer cough...Tkhtml provides no special support for html forms other than the ability to replace document nodes with Tkhtml windows as demonstrated above. Implementing that sort of thing is up to applications or megawidget frameworks. This allows the same "replace-node" interface to be used for web plugin implementations, or to embed a canvas widget configured to render an embedded SVG image.Tkhtml does provide ways to register scripts for execution:
- When a replacement window is no longer required (e.g. because a newdocument is loaded),
- To configure the colors, fonts etc. of replaced windows according to the document and stylesheets, and
- As soon a document node that matches a specified selector has been parsed (allows for incremental parsing of documents with embedded forms).
Displaying Images edit
Html documents aren't much fun without images. With a little help, Tkhtml can support background-images, list-marker images and images used to replace entire nodes. Here's an example:image create photo idir -data { R0lGODdhEAAQAPIAAAAAAHh4eLi4uPj4APj4+P///wAAAAAAACwAAAAAEAAQAAADPVi63P4w LkKCtTTnUsXwQqBtAfh910UU4ugGAEucpgnLNY3Gop7folwNOBOeiEYQ0acDpp6pGAFArVqt hQQAO/// } image create photo ibg -data { R0lGODdhIAAbAJEAAAAAAP///wAA/wAAACwAAAAAIAAbAAACeoyPqYvgD6Oc LwAhHN758v6BgMVpn1l6KXmqG/q6mQVjNdi+7M3LImvz9UIOYIwolI0eyGbO tks6UzPX8LmSYo8lmpaKXQanXKq4jB63jGqwG8rctsvn63t8nutxWfK+tmSX xlf3NaiRx3eYxKb4p+Tl50joRWF5OVIAADs= } package require Tkhtml 3.0 # Create and populate an html widget html .images -shrink 1 -imagecmd get_image -width 200 .images parse -final { <html> <body style="background-image: url(ibg); color: white ; font-weight:bold"> <img src="idir" width=100 height=50 align=left> Html documents aren't much fun without images. With a little help, Tkhtml can support background-images, list-marker images and images used to replace entire nodes. The example only shows backgrounds and replaced images. </body> </html> } proc get_image {uri} {return $uri} pack .images bind .images <KeyPress-q> exit focus .imagesThe -imagecmd option of the html widget takes a script. When the widget finds an image URI, it appends the URI to the script and executes it. The script should return the name of a Tk image to be used by the html widget. The image may be populated or overwritten by the script at a later time and the widget display is automatically updated.By default, Tkhtml deletes images when it has finished using them but it can be configured to invoke a user-provided script instead. There are also interfaces to ensure that relative URIs can be interpreted unambiguously (for example a relative URI from an external stylesheet may be interpreted differently to a relative URI embedded in the html document itself).Here's a slightly fancier, more complete get_image procedure that will let you specify a Tk image, a file, or a http url. it needs some error checking incase the file or url specified is not actually an image. It has the added bonus of not creating a new Tk image for repeat use of the same file or url.
package require Img package require http proc get_url url { set token [::http::geturl $url] set data [::http::data $token] ::http::cleanup $token return $data } proc get_image uri { #if the 'url' passed is an image name if { [lsearch [image names] $uri] > -1 } { return $uri } # if the 'url' passed is a file on disk if { [file exists $uri] } { #create image using file image create photo $uri -file $uri return $uri } #if the 'url' is an http url. if { [string equal -length 7 $uri http://] } { image create photo $uri -data [get_url $uri] return $uri } }
Please post any bugs you find with Tkhtml at this website:http://tkhtml.tcl.tk/fossil/
Discussion edit
rdt I built this on a Mandrake 2006.0 distro and checked out all these snippets. It's nice. Thanks.See also edit
- tkhtml
- The main page for Tkhtml
JOB - 2017-01-23A TclOO Tkhtml 3.0 megawidget - example of how to render html+css
[fpigorsch] - 2017-08-16 13:35:00http://tkhtml.tcl.tk/ seems to be down. Anyone knows what's going on there?https://github.com/olebole/tkhtml3 has a relatively recent snapshot of the original repo.
ak - 2017-08-22 19:56:12Machines moved, updating the DNS records lagged. Everything should be ok again.