Annotation of kupu/doc/LIBRARIES.txt, revision 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>