Annotation of kupu/doc/LIBRARIES.txt, revision 1.1.1.1

1.1       dwinter     1: ================================
                      2: Image and Link Libraries in Kupu
                      3: ================================
                      4: 
                      5: Abstract
                      6: --------
                      7: 
                      8: This document describes the Library feature of the Kupu WYSIWYG
                      9: editor. It defines the behaviour on both the client and the server and
                     10: serves as a specification for the XML protocol that is used for their
                     11: interaction.
                     12: 
                     13: 
                     14: Motivation
                     15: ----------
                     16: 
                     17: Kupu is a visual editor for content management systems, with a target
                     18: audience of regular users without a high technical profile.  For this
                     19: audience, Word is the incumbent.
                     20: 
                     21: In addition to text, Kupu users need a simple, usable, and
                     22: high-performance system for getting images and hyperlinks into their
                     23: pages.  Sometimes they want to *browse* to find these assets.
                     24: Sometimes they want to *search*, particularly for large collections.
                     25: 
                     26: Regarding usability, open source CMS projects don't have many
                     27: browser-side developers with good usability backgrounds.  Since Kupu
                     28: is an oscom.org project, it is a goal to move the UI rendering from
                     29: the server (where talent would be dispersed among projects) to the
                     30: client (where one UI can work for many servers).  Therefore, the Kupu
                     31: Library only requests XML from the CMS, not HTML.
                     32: 
                     33: Note: Though Kupu will work with IE 5.5 sans service packs, Kupu
                     34: requires MS XML 3.0 or higher.  Any IE 5.5 that is up-to-date on
                     35: security updates, and any IE 6 or Mozilla 1.3+ can use the Kupu
                     36: Library.
                     37: 
                     38: 
                     39: Definitions
                     40: -----------
                     41: 
                     42: Library
                     43: 
                     44:   A static or dynamic collection of resources and collections defined
                     45:   at a top level. Libraries have no parents from a UI perspective,
                     46:   where as the collection they represent might have a parent
                     47:   collection.
                     48: 
                     49: Collection
                     50: 
                     51:   A static or dynamic collection of resources and collections,
                     52:   modelled after WebDAV collections.
                     53: 
                     54: Resource
                     55: 
                     56:   A named and URI-locatable object with associated metadata, such as
                     57:   title, description, preview, size, etc.
                     58: 
                     59: 
                     60: Process overview 
                     61: ----------------
                     62: 
                     63: 1. The user opens a drawer in Kupu. Kupu requests a list of available
                     64:    libraries. The server answers with a list of libraries possibly
                     65:    containing URIs at which to get the content listing of each library.
                     66: 
                     67: 2. Upon user request, Kupu loads the contents of a library and present
                     68:    it to the user. Already opened libraries are not reloaded from the
                     69:    server
                     70: 
                     71: 3. A user selects a resource at which point Kupu presents the
                     72:    associated metadata and may optionally load a preview image.
                     73: 
                     74: 4. Double clicking on a collection or selecting a new library triggers
                     75:    step 2 again.
                     76: 
                     77: 5. Clicking on a resource and clicking "Insert" (for an image) or
                     78:    "Link" (for links) updates the document and closes the drawer.
                     79: 
                     80: 6. If the cursor is on a link or image, the drawer allows editing the
                     81:    image/link attributes.
                     82: 
                     83: 
                     84: List of libraries
                     85: -----------------
                     86: 
                     87: Kupu issues a simple HTTP GET request to a URL defined in the
                     88: 'libraries' attribute of the iframe. The server returns XML conforming
                     89: to the following schema::
                     90: 
                     91:  <grammar xmlns="http://relaxng.org/ns/structure/1.0">
                     92: 
                     93:    <start>
                     94:      <ref name="librariesDocumentElement" />
                     95:    </start>
                     96: 
                     97:    <define name="librariesDocumentElement">
                     98:      <element name="libraries">
                     99:        <zeroOrMore>
                    100:          <ref name="library" />
                    101:        </zeroOrMore>
                    102:      </element>
                    103:    </define>
                    104: 
                    105:    <define name="library"
                    106:      <element name="library">
                    107:        <interleave>
                    108:          <ref name="commonToAllItems" />
                    109:          <choice>
                    110:            <ref name="collectionItems" />
                    111:            <ref name="itemsSource" />
                    112:          </choice>
                    113:        </interleave>
                    114:        </element>
                    115:    </define>
                    116: 
                    117:    <define name="commonToAllItems">
                    118:      <attribute name="id">
                    119:        <!-- Must be unique among all libraries, resources and collections. -->
                    120:        <text />
                    121:      </attribute>
                    122: 
                    123:      <interleave>
                    124:        <element name="uri">
                    125:          <text />
                    126:        </element>
                    127: 
                    128:        <optional>
                    129:          <element name="label">
                    130:            <text />
                    131:          </element>
                    132:        </optional>
                    133: 
                    134:        <element name="title">
                    135:          <text />
                    136:        </element>
                    137: 
                    138:        <optional>
                    139:          <element name="icon">
                    140:            <text />
                    141:          </element>
                    142:        </optional>
                    143:      </interleave>
                    144:    </define>
                    145: 
                    146:    <define name="collectionItems">
                    147:      <element name="items">
                    148:        <zeroOrMore>
                    149:          <ref name="collectionItem" />
                    150:        </zeroOrMore>
                    151:        <optional>
                    152:          <element name="uploadbutton" />
                    153:        </optional>
                    154:      </element>
                    155:    </define>
                    156: 
                    157:    <define name="itemsSource">
                    158:      <element name="src">
                    159:        <text />
                    160:      </element>
                    161:    </define>
                    162: 
                    163:    <define name="collectionItem">
                    164:      <choice>
                    165:        <element name="resource">
                    166:          <ref name="commonToAllItems" />
                    167:          <ref name="extraResourceInfo" />
                    168:        </element>
                    169:        <element name="collection">
                    170:          <ref name="commonToAllItems" />
                    171:          <ref name="itemsSource" />
                    172:        </element>
                    173:      </choice>
                    174:    <define>
                    175: 
                    176:    <define name="extraResourceInfo">
                    177:      <interleave>
                    178:        <optional>
                    179:          <element name="preview">
                    180:            <text />
                    181:          </element>
                    182:        </optional>
                    183: 
                    184:        <optional>
                    185:          <element name="size">
                    186:            <text />
                    187:          </element>
                    188:        </optional>
                    189: 
                    190:        <optional>
                    191:          <element name="type">
                    192:            <text />
                    193:          </element>
                    194:        </optional>
                    195:      </interleave>
                    196:    </define>
                    197: 
                    198:  </grammar>
                    199: 
                    200: 
                    201: For example::
                    202: 
                    203:  <libraries>
                    204: 
                    205:    <library id="http://path/to/folder">
                    206:      <title>Current Folder</title>
                    207:      <icon>http://path/to/icon.jpg</icon>
                    208:      <src>http://server/current/folder/resources.kupu</src>
                    209:    </library>
                    210: 
                    211:    <library id="http://path/to/other/someotherfolder">
                    212:      <title>Some Other Folder</title>
                    213:      <icon>http://path/to/icon.jpg</icon>
                    214:      <src>http:/server/other/folder/resources.kupu</src>
                    215:    </library>
                    216: 
                    217:    <library id="recentitems">
                    218:      <title>Recent Items</title>
                    219:      <icon>http://path/to/icon.jpg</icon>
                    220:      <items />
                    221:    </library>
                    222: 
                    223:  </libraries>
                    224: 
                    225: 
                    226: Kupu parses this XML to a DOM managed in JavaScript and displays it
                    227: using an XSLT stylesheet. The DOM tree is stored throughout the whole
                    228: Kupu session.
                    229: 
                    230: 
                    231: Browser-side architecture
                    232: ------------------------------------
                    233: 
                    234: When the drawer is opened, Kupu loads the XML data about the libraries
                    235: into a JS property that holds an XML DOM.  The Sarissa cross-browser
                    236: abstraction for XML (http://sarissa.sf.net) is used.
                    237: 
                    238: As the user clicks, more XML data are loaded if that collection hasn't
                    239: been visited yet.  The loaded XML is then appended into the XML DOM.
                    240: The node that was clicked on has an attribute set to mark it as
                    241: selected.  Kupu then runs an XSLT on the XML DOM to re-generate the
                    242: drawer contents (as HTML), and updates the HTML node with the output.
                    243: The use of XSLT and XPath give increased performance, lower line
                    244: count, and better IE/Mozilla compatibility.
                    245: 
                    246: As an implementation note, XML is extremely compressible.  With
                    247: mod_deflate and other server-compression approaches, at least a
                    248: thousand entries can be encoded in 100 Kb.
                    249: 
                    250: User opens on a library
                    251: -----------------------
                    252: 
                    253: In case a collection or library has been active before, it is
                    254: deselected (by removing the 'selected' attribute on the DOM node). The
                    255: DOM node of the library the user has chosen is selected (by setting
                    256: the 'selected' attribute). Also, visually deselect the before selected
                    257: library (by unsetting a CSS class) and mark the newly selected library
                    258: (with a CSS class).
                    259: 
                    260: In case its <library> element provides the <src> subelement, an HTTP
                    261: GET to that URI is made, the returned XML retrieved, turned into a DOM
                    262: tree and the resulting <items> node of the result appended to the
                    263: library DOM node. That step is not made in case the <library> node
                    264: directly provides the <items> node.
                    265: 
                    266: Now, the XSLT is executed again, presenting the newly selected node
                    267: (by querying for the node with the 'selected' attribute) and its
                    268: contents.
                    269: 
                    270: When a library's contents has to be retrieved with an extra request,
                    271: it is returned according to the following schema (using definitions
                    272: from above)::
                    273: 
                    274:  <grammar xmlns="http://relaxng.org/ns/structure/1.0">
                    275: 
                    276:    <start>
                    277:      <ref name="libraryDocumentElement" />
                    278:    </start>
                    279: 
                    280:    <define name="libraryDocumentElement">
                    281:      <element name="library">
                    282:        <ref name="commonToAllItems" />
                    283:        <ref name="collectionItems" />
                    284:      </element>
                    285:    </define>
                    286: 
                    287:  </grammar>
                    288: 
                    289: 
                    290: For example::
                    291: 
                    292:  <library id="some_unique_id">
                    293:    <title>Current folder</title>
                    294:    <uri>http://server/current/folder</uri>
                    295:    <icon>http://server/folder.ico</icon>
                    296:    <items>
                    297:      <resource id="another_unique_id">
                    298:        <title>Foo img</title>
                    299:        <uri>http://server/current/folder/foo.jpg</uri>
                    300:        <icon>http://server/image.ico</icon>
                    301:      </resource>
                    302:      <collection id="a_collections_unique_id">
                    303:        <title>Some collection</title>
                    304:        <uri>http://server/current/folder/collection</uri>
                    305:        <icon>http://server/folder.ico</icon>
                    306:      </collection>
                    307:    </items>
                    308:  </library>
                    309: 
                    310: 
                    311: User opens a collection
                    312: -----------------------
                    313: 
                    314: Unselect the previously selected collection and try to execute one of
                    315: three cases in order:
                    316: 
                    317:   * The node of selected collection is queried for an attribute
                    318:     'loadedInNode'. If it exists, it refers to an id of a node which
                    319:     already contains that collection's items. Select that node and
                    320:     execute the XSLT to present changes.
                    321: 
                    322:   * The selected collection node does not have a 'loadedInNode'
                    323:     attribute. Therefore, the selected collection's URI is read and the
                    324:     document element's children are queried with an XPath to check
                    325:     whether the collection with that URI was already loaded before and
                    326:     attached to the document element. If so, the selected collection
                    327:     node receives an attribute 'loadedInNode' with the value of the
                    328:     corresponding collection node below the document element, which is
                    329:     selected (by setting the 'selected' attribute). The XSLT is executed
                    330:     to present the changes.
                    331: 
                    332:   * The selected collection node has no 'loadedInNode' attribute and
                    333:     there is no preloaded collection node of that URI. The selected
                    334:     node's <src> subelement is read. An HTTP GET request is made to that
                    335:     URI and the items XML data retrieved and turned into a DOM tree. The
                    336:     <collection> node of that resulting tree is given a new unique ID,
                    337:     appended to the document element of the library DOM tree and
                    338:     selected (by setting the 'selected' attribute). The selected
                    339:     collection node receives an attribute 'loadedInNode' with the value
                    340:     that newly generated id. The XSLT is executed to present the
                    341:     changes.
                    342: 
                    343: When a collection's contents has to be retrieved with an extra
                    344: request, it is returned according to the following schema (using
                    345: definitions from above)::
                    346: 
                    347:   <grammar xmlns="http://relaxng.org/ns/structure/1.0">
                    348: 
                    349:     <start>
                    350:       <ref name="collectionDocumentElement" />
                    351:     </start>
                    352: 
                    353:     <define name="collectionDocumentElement">
                    354:       <element name="collection">
                    355:         <ref name="commonToAllItems" />
                    356:         <ref name="collectionItems" />
                    357:       </element>
                    358:     </define>
                    359: 
                    360:   </grammar>
                    361: 
                    362: This grammar is modeled after the WebDAV response grammar, without
                    363: using the namespace parts of WebDAV. For example::
                    364: 
                    365:   <collection id="some_unique_id">
                    366:     <title>Some folder</title>
                    367:     <uri>http://server/some/folder</uri>
                    368:     <icon>http://server/folder.ico</icon>
                    369: 
                    370:     <items>
                    371:       <resource id="another_unique_id">
                    372:         <title>Foo img</title>
                    373:         <uri>http://server/some/folder/foo.jpg</uri>
                    374:         <icon>http://server/image.ico</icon>
                    375:       </resource>
                    376: 
                    377:       <collection id="a_subfolders_unique_id">
                    378:         <title>Some subfolder</title>
                    379:         <uri>http://server/some/folder/subfolder</uri>
                    380:         <icon>http://server/folder.ico</icon>
                    381:         <src>http://server/some/folder/resources.kupu</src>
                    382:       </collection>
                    383:     </items>
                    384: 
                    385:   </library>
                    386: 
                    387: 
                    388: If a collection's parent collection shall be accessible, then the
                    389: server has to return an entry for it explicitly.
                    390: 
                    391: 
                    392: Searching
                    393: ---------
                    394: 
                    395: For searching, Kupu sends an HTTP POST request to the server (to a
                    396: configurable URI). The server does the search based on the POST form
                    397: values and return the results as if they were the contents of a
                    398: library. The document element of the returned XML, <library>, does not
                    399: have to have a unique id nor an icon subelement.
                    400: 
                    401: The POST request can contain an optional parameter for the size of the
                    402: result set. The server can enforce an upper limit itself, and if the
                    403: request parameter is higher, ignore it. By default, this value is 500.
                    404: 
                    405: Kupu treats the search result as a library, with the exception of
                    406: generating a unique id and icon for it. The search result library is
                    407: attached to the root node of the DOM tree and thus visible and later
                    408: accessible via the library list.
                    409: 
                    410: 
                    411: Implementation on the Plone side
                    412: --------------------------------
                    413: 
                    414: On the Plone side, a set of Page Templates is responsible for
                    415: generating the XML. They are aided by a special tool, KupuLibraryTool.
                    416: 
                    417: In order to use the XML generation for inclusion of media objects,
                    418: such as images and photos, as well as for searching documents that one
                    419: can link to from Kupu, the library tool keeps a mapping from resource
                    420: types to portal types. It provides a management interface in which the
                    421: site administrator can define, which portal types are to be treated as
                    422: collections, as linkable documents, as insertable media objects, etc.
                    423: 
                    424: The library tool also keeps a list of available libraries on the
                    425: site. The site administrator can add, modify, delete and reorder
                    426: libraries in the tool's management interface. The searching aspect of
                    427: Kupu Libraries is handled by the portal catalog.
                    428: 
                    429: Permissions used by the library tool:
                    430: 
                    431: - Kupu: Query libraries
                    432: 
                    433:   This permission is required for all users who want to query
                    434:   libraries from the library tool.
                    435: 
                    436: - Kupu: Manage libraries
                    437: 
                    438:   This permissions is required for all administrators who need to add,
                    439:   edit and delete existing libraries.
                    440: 
                    441: In order to be able to present special previews for resources without
                    442: having to load the resource itself in Kupu, a portal type can provide
                    443: an action called 'kupupreview', pointing to the URL where the object's
                    444: preview can be retrieved. If a portal_type does not provide that
                    445: action, preview is disabled for it.
                    446: 
                    447: Example: Preview action for CMFPhoto showing each photo's thumbnail
                    448: version:
                    449: 
                    450:   - Go to the portal_types tool and click on the 'Photo' portal
                    451:     type. Then click on its 'Actions' tab.
                    452: 
                    453:   - Down below enter information for a new action:
                    454: 
                    455:     Name:       Kupu Preview
                    456:     Id:         kupupreview
                    457:     Action:     string:${object_url}/variant/thumbnail
                    458:     Condition:  [empty]
                    459:     Permission: View
                    460:     Category:   object
                    461:     Visible?    False
                    462: 
                    463:   - Hit the 'Add' button.
                    464: 
                    465: 
                    466: Futures
                    467: -------
                    468: 
                    469:   * Cached XSLT (need Sarissa support for this)
                    470: 
                    471:   * Deeper standards support (WebDAV/DASL)
                    472: 
                    473: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>