Skip to content
speezepearson edited this page Dec 1, 2015 · 3 revisions

Sometimes, you might want to create a new kind of element. Suppose I hadn't defined the List class -- how would you make a List for yourself?

The answer involves a lot of HTML. Basically, every Element is just a wrapper around some HTML tag, which is the tag displayed in the browser. You write an Element subclass which defines methods that modify the HTML tag. It's that simple.

To succeed here, you'll need to be familiar with HTML (at least enough to write the HTML to display your element), and the DOM API (the most useful pieces are on the Element and Document).

Tags

Every element has an HTML tag associated with it. The tag is created by Element.__init__, which must be given a tag_name (e.g. "ol" for a list or "span" for a piece of text). The tag is an instance of xml.dom.minidom.Element.

Each element has complete control over its tag, and may do anything it likes to the tag or any descendant of the tag, with the following exceptions:

  • do not modify the element's tag's id or style attributes, or any attributes beginning with on (used for event-handling)
  • do not modify your children's tags, or their descendants

For example, a List instance with two children would have a tag that looks like

<ol>
  <li>
    <someTag for-first-child> ... </someTag>
  </li>
  <li>
    <someTag for-second-child> ... </someTag>
  </li>
</ol>

The List instance is free to modify the ol or li tags in any way, including inserting or deleting tags; but it must treat the two someTag tags as black boxes.

After modifying an element's tag, the element's mark_dirty() method should be called. If the element is in a GUI being viewed in a browser, e.mark_dirty() will make sure the browser's version of the tag is up to date.

Styling

If you want to do CSS stuff, use the Element's css attribute. e.css is a dict-like object that, when modified, will modify the HTML tag and mark the tag as dirty.

Event-Handling

I recently overhauled the event-handling framework, and still have to document it. Stay tuned. Sorry!

Example

Using what we know so far, let's implement a List element.

First, we need to figure out what the HTML should look like. Any HTML dabbler will know that it should look like

<ol>
  <li>
    <tag-for-first-child />
  </li>
  <li>
    <tag-for-second-child />
  </li>
  ...
</ol>

Now, let's define a SimpleList class, which supports appending and deletion of child elements.

class SimpleList(Element):
  def __init__(self, **kwargs):
    super(SimpleList, self).__init__(tag_name="ol", **kwargs)

  def append(self, new_child):
    # add a new item to our HTML list tag
    li = self.tag.ownerDocument.createElement('li')
    self.tag.appendChild(li)
    li.appendChild(new_child.tag)

    # make sure the tag gets redrawn
    self.mark_dirty()

  def delete(self, old_child):
    # remove the item containing the child from our HTML list tag
    self.tag.removeChild(old_child.tag.parentNode)

    # make sure the tag gets redrawn
    self.mark_dirty()

That's it! You now know everything there is to know about defining your own elements.

Clone this wiki locally