# HG changeset patch # User paulb # Date 1122064333 0 # Node ID edcff6139b1904a1059e0fa07551bc07e7fc07a0 # Parent a7ea3c1684c1e479a71631fe955b26a31d02b15c [project @ 2005-07-22 20:32:13 by paulb] Improved and fixed the JavaScript method call description and details. Added a description of the changes required in the Web resource. diff -r a7ea3c1684c1 -r edcff6139b19 docs/in-page-updates.html --- a/docs/in-page-updates.html Fri Jul 22 18:27:00 2005 +0000 +++ b/docs/in-page-updates.html Fri Jul 22 20:32:13 2005 +0000 @@ -128,26 +128,41 @@ added or removed, we add an event attribute on the form field responsible for displaying the type values:

  <p>
Item type:
<select template:element="type" name="{template:list-attribute('type-enum', 'value')}" multiple="multiple"
onchange="requestUpdate('{$application-url}comments', '{template:list-attribute('type-enum', 'value')}',
 '{template:other-elements(../options)}',
'{template:child-attribute('value', template:child-element('comment', 1, template:other-elements(../options)))}',
'/structure/item/options')"
>
<option template:element="type-enum" template:expr="@value-is-set" template:expr-attr="selected"
template:value="@value" value="{@value}" />
</select>
</p>
+ style="font-weight: bold;">onchange="requestUpdate(
'{$application-url}comments',
'{template:list-attribute('type-enum', 'value')}',
'{template:other-elements(../options)}',
'{template:child-attribute('value', template:child-element('comment', 1, template:other-elements(../options)))}',
'/structure/item/options')">
<option template:element="type-enum" template:expr="@value-is-set" template:expr-attr="selected"
template:value="@value" value="{@value}" />
</select>
</p>

This complicated string calls a special update request JavaScript function which triggers the in-page update, and it specifies the following things:

-
    -
  1. The URL which will serve the in-page update requested by this +
    +
    '{$application-url}comments'
    +
    The URL which will serve the in-page update requested by this field. We use a special variable called application-url which will need to be provided to the template when generating the Web -page.
  2. -
  3. The fields which are going to be used in the processing of the +page. This will produce something like the following:
    +
    http://localhost:8080/comments
    +So the request for an in-page update will be sent to this +generated URL. +
    '{template:list-attribute('type-enum', +'value')}'
    +
    The fields which are going to be used in the processing of the update. Since the presence of the comment field depends on a specific type element and its type-enum elements' value attributes, we specify the names of -the fields which yield these values.
  4. -
  5. The region which is to be updated. Here, we recall that we +the fields which yield these values. +
    '{template:other-elements(../options)}'
    +
    The region which is to be updated. Here, we recall that we defined the region using a special reference to the options element holding comment element. Thus, we use a special value which also refers to that element from the context of -the type element.
  6. -
  7. Even when the types are changed, it may be the case that an +the type element. +
    '{template:child-attribute('value', +template:child-element('comment', 1, +template:other-elements(../options)))}'
    +
    Even when the types are changed, it may be the case that an exposed comment field does not disappear (for example, if we already have "Personal" selected but select "Important" in addition), and so we need to provide the details of the field which holds the value of the @@ -159,10 +174,128 @@ being after an update, but not be referenced here in this parameter; therefore, we need to make up the final part of the reference using the special template:child-attribute -and template:child-element functions.
  8. -
  9. Finally, we need to provide some context to the application to +and template:child-element functions. +
    '/structure/item/options'
    +
    Finally, we need to provide some context to the application to tell it something about where in the complete form data structure the -updated information resides. 
  10. -
+updated information resides. + +

Of course, all this is pretty complicated and at some point in the +future, a simplified way of triggering in-page updates will be +introduced.

+

Updating the Web Application

+

To support both normal requests for Web pages and the special +in-page requests, we must make some modifications to the Web +application. First, we must introduce some infrastructure to handle the +requests for the JavaScript files separately from the requests for +pages from our application. Some standard WebStack resources can be +used to help with this, and we add some imports at the top of our +source file:

+
#!/usr/bin/env python

"A very simple example application."

import WebStack.Generic
import XSLForms.Resources
import XSLForms.Utils
import os

# Site map imports.

from WebStack.Resources.ResourceMap import MapResource
from WebStack.Resources.Static import DirectoryResource
+

Then, we define the resource class as before, +but with an additional attribute:

+
# Resource classes.

class VerySimpleResource(XSLForms.Resources.XSLFormsResource):

"A very simple resource providing a hierarchy of editable fields."

resource_dir = os.path.join(os.path.split(__file__)[0], "Resources")
encoding = "utf-8"
template_resources = {
"structure" : ("structure_multivalue_template.xhtml", "structure_output.xsl")
}
transform_resources = {
"types" : ["structure_multivalue_types.xsl", "structure_comments.xsl"]
}
document_resources = {
"types" : "structure_types.xml"
}
in_page_resources = {
"comments" : ("structure_output_comments.xsl", "comment-node")
}
+

This new attribute provides information about the in-page request to +retrieve comment regions of the Web form, and it consists of the +stylesheet filename that will be generated to produce the page +fragments for such comment regions, along with the region marker that +we defined above.

+

The respond_to_form method now also includes some +additional code:

+
    def respond_to_form(self, trans, form):

"""
Respond to a request having the given transaction 'trans' and the given
'form' information.
"""

in_page_resource = self.get_in_page_resource(trans)
parameters = form.get_parameters()
documents = form.get_documents()
+

Here, we find out whether an in-page update is requested, along with +the raw parameters of the request, some of which will be used later on +in the method.

+

The discovery of the form data structure and the addition and +removal of elements happens as before, as does the merging of type +values and the comment field, if applicable:

+
        # Ensure the presence of a document.

if documents.has_key("structure"):
structure = documents["structure"]
else:
structure = form.new_instance("structure")

# Add and remove elements according to the selectors found.

selectors = form.get_selectors()
XSLForms.Utils.remove_elements(selectors.get("remove2"))
XSLForms.Utils.add_elements(selectors.get("add2"), "subitem")
XSLForms.Utils.remove_elements(selectors.get("remove"))
XSLForms.Utils.add_elements(selectors.get("add"), "item")

# Transform, adding enumerations/ranges.

types_xsl_list = self.prepare_transform("types")
types_xml = self.prepare_document("types")
structure = self.get_result(types_xsl_list, structure, references={"types" : types_xml})
+

The significant changes begin when presenting the result of the +request processing:

+
        # Start the response.

trans.set_content_type(WebStack.Generic.ContentType("application/xhtml+xml", self.encoding))

# Define the stylesheet parameters.

stylesheet_parameters = {}

# Ensure that an output stylesheet exists.

if in_page_resource in self.in_page_resources.keys():
trans_xsl = self.prepare_fragment("structure", in_page_resource)
element_path = parameters.get("element-path", [""])[0]
stylesheet_parameters["element-path"] = element_path
else:
trans_xsl = self.prepare_output("structure")
+

Instead of just obtaining a stylesheet for the structure +document, we instead check to see if an in-page update is being +requested and, if so, prepare the stylesheet representing the fragment +of the Web form to be presented. Additionally, we obtain a special element-path +parameter directly from the request parameters; this parameter is added +to a collection of parameters that will be used to control the +stylesheet when making the final Web page output.

+

Another parameter that will be used in stylesheet processing is +the application-url parameter mentioned above. We +obtain the address and port of the Web server environment and add the +result as a simple URL to the application-url +stylesheet parameter. Finally, we send the output to the user but +employing the additional stylesheet parameters to configure the result:

+
        # Add information essential for in-page requests.

if trans.get_server_port() == "80":
stylesheet_parameters["application-url"] = \
"http://%s%s" % (trans.get_server_name(), trans.get_path_without_query())
else:
stylesheet_parameters["application-url"] = \
"http://%s:%s%s" % (trans.get_server_name(), trans.get_server_port(), trans.get_path_without_query())

# Complete the response.

self.send_output(trans, [trans_xsl], structure, stylesheet_parameters)
+

In order to introduce the infrastructure mentioned above which +separates requests for Web pages from requests for JavaScript files, we +need to provide a more sophisticated implementation of the get_site +function:

+
# Site map initialisation.

def get_site():

"Return a simple Web site resource."

# Get the main resource and the directory used by the application.

very_simple_resource = VerySimpleResource()
directory = very_simple_resource.resource_dir

# Make a simple Web site.

resource = MapResource({
# Static resources:
"scripts" : DirectoryResource(os.path.join(directory, "scripts"), {"js" : "text/javascript"}),
# Main page and in-page resources:
None : very_simple_resource
})

return resource
+

What this does is to create a resource for the application, as +before, but then to place the resource into a special WebStack resource +which examines the path or URL on the incoming requests and directs +such requests according to the following scheme:

+ +

Thus, when the user's browser asks for a script file, it gets a +script file; otherwise it gets a Web page showing either all of the +form (if a normal request is received), or a part of the form (if an +in-page request is received).