[Checkins] SVN: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/ Incomplete addition of addressbook demo

Darryl Cousins darryl at darrylcousins.net.nz
Wed Jul 11 20:30:00 EDT 2007


Log message for revision 77708:
  Incomplete addition of addressbook demo

Changed:
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/README.txt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/__init__.py
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/address.pt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.css
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.pt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.py
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.txt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addresses.pt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/contact.pt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/contact.py
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/dateselect.pt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/email.pt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/emails.pt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/form-macros.pt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/phone.pt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/phones.pt
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/resources.py
  A   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/text-shadow.js
  U   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/skin/skin.py
  U   Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/tests.py

-=-
Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/README.txt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/README.txt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/README.txt	2007-07-12 00:29:59 UTC (rev 77708)
@@ -0,0 +1,9 @@
+================
+Addressbook Demo
+================
+
+The "Addressbook" demo is to demonstrate a complex, form-driven
+UI with several sub-forms and table-integration.
+
+The original doctest is ./addressbook.py.
+


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/README.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/__init__.py
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/__init__.py	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/__init__.py	2007-07-12 00:29:59 UTC (rev 77708)
@@ -0,0 +1 @@
+#


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/address.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/address.pt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/address.pt	2007-07-12 00:29:59 UTC (rev 77708)
@@ -0,0 +1,20 @@
+<div metal:use-macro="macro:form-header" />
+
+<div class="row">
+  <div class="inline" tal:define="widget view/widgets/street">
+    <div metal:use-macro="macro:widget-noerror-row" />
+  </div>
+</div>
+<div class="row">
+  <div class="inline" tal:define="widget view/widgets/city">
+    <div metal:use-macro="macro:widget-noerror-row" />
+  </div>
+  <div class="inline" tal:define="widget view/widgets/state">
+    <div metal:use-macro="macro:widget-noerror-row" />
+  </div>
+  <div class="inline" tal:define="widget view/widgets/zip">
+    <div metal:use-macro="macro:widget-noerror-row" />
+  </div>
+</div>
+
+<div metal:use-macro="macro:form-buttons" />

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.css
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.css	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.css	2007-07-12 00:29:59 UTC (rev 77708)
@@ -0,0 +1,211 @@
+h1 {
+  background-color: #619FDF;
+  border: 1px solid #3B81C8;
+  color: white;
+  padding: 5px 7px 2px 7px;
+  font-weight: bold;
+  margin-bottom: 20px;
+  -moz-border-radius: 3px;
+}
+
+h1 span {
+  text-shadow: 1px 1px 1px black;
+}
+
+h2 {
+  border-top: 2px solid #3B81C8;
+  border-bottom: 2px solid #3B81C8;
+  color: #3B81C8;
+  font-weight: bold;
+  padding: 0;
+  margin: 10px 0px 5px 0px;
+}
+
+h2 span {
+  font-size: 95%;
+  font-weight: normal;
+  text-shadow: 1px 1px 1px #285989;
+}
+
+input, select, textarea {
+  background-color: #FFFFA0;
+}
+
+input[type=submit] {
+  background-color: #619FDF;
+  border: 2px solid #3B81C8;
+  color: white;
+  font-weight: bold;
+  -moz-border-radius: 3px;
+}
+
+span.dateselect .year {
+  width: 6em;
+}
+
+span.dateselect .month {
+  width: 4em;
+}
+
+span.dateselect .day {
+  width: 4em;
+}
+
+hr.separator {
+  height: 2px;
+  color: #3B81C8;
+  background-color: #3B81C8;
+  margin-top: 15px;
+  border: 0;
+}
+
+div.status {
+  color: red;
+}
+
+div#layout {
+  clear: both;
+}
+
+div#contact-table {
+  float: left;
+  margin-right: 20px;
+}
+
+div#contact-form {
+  float: right;
+  border: 2px solid #3B81C8;
+  -moz-border-radius: 3px;
+  padding: 10px;
+  width: 400px;
+}
+
+div.section-content {
+  margin: 0px 10px;
+}
+
+table.contact-list {
+  border-collapse: collapse;
+}
+
+table.contact-list th {
+  background-color: #619FDF;
+  border-top: 1px solid #3B81C8;
+  border-bottom: 1px solid #3B81C8;
+  padding: 3px 5px;
+  text-align: left;
+  color: white;
+}
+
+table.contact-list th a {
+  color: white;
+}
+
+table.contact-list th a:visited {
+  color: white;
+}
+
+table.contact-list th a:hover {
+  color: white;
+}
+
+table.contact-list td {
+  padding: 2px 5px;
+  border-bottom: 1px solid #DBE1E6;
+}
+
+table.contact-list tr.even {
+  background-color: #EDF4F9;
+}
+
+table.contact-list tr.selected {
+  background-color: #FFFFA0;
+}
+
+table.contact-list a {
+  color: black;
+}
+
+table.contact-list a:visited {
+  color: black;
+}
+
+table.contact-list a:hover {
+  color: black;
+}
+
+div#addresses {
+  margin-top: 10px;
+}
+
+div#add-address {
+  margin-top: 10px;
+}
+
+select#form-widgets-addressName {
+  width: 150px;
+}
+
+fieldset.address {
+  background-color: #EDF4F9;
+  border: 1px solid #DBE1E6;
+  margin-top: 7px;
+}
+
+fieldset.address legend {
+  color: #3B81C8;
+}
+
+fieldset.address div.buttons {
+  margin: 0;
+  padding: 0;
+}
+
+div.inline, div.inline div {
+  display: inline;
+}
+
+input.city {
+  width: 12em;
+}
+
+input.state {
+  width: 2em;
+}
+
+input.zip {
+  width: 5em;
+}
+
+
+/* ----[ Phone Styles ]----------------------------------------------------- */
+
+div#phones {
+  margin-top: 20px;
+}
+
+input.countryCode {
+  width: 2em;
+}
+
+input.areaCode {
+  width: 3em;
+}
+
+input.number {
+  width: 9em;
+}
+
+input.extension {
+  width: 6em;
+}
+
+/* ----[ E-Mail Styles ]---------------------------------------------------- */
+
+div#emails {
+  margin-top: 20px;
+}
+
+input.email {
+  width: 20em;
+}

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.pt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.pt	2007-07-12 00:29:59 UTC (rev 77708)
@@ -0,0 +1,8 @@
+<h1><span>Address Book Demo</span></h1>
+
+<div id="layout">
+  <div id="contact-table"
+       tal:content="structure view/table" />
+  <div id="contact-form"
+       tal:content="structure view/form/render" />
+</div>

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.py
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.py	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.py	2007-07-12 00:29:59 UTC (rev 77708)
@@ -0,0 +1,124 @@
+import zope.component
+from zope.app.session.interfaces import ISession
+from zope.app.container.interfaces import IContainer
+
+from z3c.template.interfaces import ILayoutTemplate
+from z3c.formdemo.browser import formatter
+from z3c.form import form, button
+from z3c.form.interfaces import IFormLayer, INPUT_MODE
+from z3c.formdemo.addressbook import interfaces, browser, dateselect
+
+SESSION_KEY = 'mars.formdemo.addressbook'
+
+import grok
+
+import mars.view
+import mars.layer
+import mars.adapter
+from mars.formdemo.layer import IDemoBrowserLayer
+
+mars.layer.layer(IDemoBrowserLayer)
+
+class DateSelectWidget(mars.adapter.AdapterFactory):
+    mars.adapter.factory(dateselect.DateSelectFieldWidget)
+
+class ContactLabel(mars.adapter.AdapterFactory):
+    mars.adapter.factory(button.StaticButtonActionAttribute(
+                        u'Add Contact', 
+                        button=form.AddForm.buttons['add'], 
+                        form=browser.ContactAddForm))
+
+class AddressBook(mars.view.PageletView):
+    grok.context(IContainer)
+    grok.name('addressbook')
+
+    columns = (
+        browser.SelectContactColumn(
+            u'Last Name', lambda i, f: i.lastName, name='lastName'),
+        browser.SelectContactColumn(
+            u'First Name', lambda i, f: i.firstName, name='firstName'),
+        )
+
+    @apply
+    def selectedContact():
+        def get(self):
+            session = ISession(self.request)[SESSION_KEY]
+            return session.get('selectedContact')
+        def set(self, value):
+            session = ISession(self.request)[SESSION_KEY]
+            session['selectedContact'] = value
+        return property(get, set)
+
+    def update(self):
+        # Select a new contact
+        if 'selectContact' in self.request:
+            self.selectedContact = self.context[self.request['selectContact']]
+        # Setup the form
+        if self.selectedContact:
+            self.form = browser.ContactEditForm(self.selectedContact, self.request)
+            self.form.update()
+        if not self.selectedContact:
+            self.form = browser.ContactAddForm(self.context, self.request)
+            self.form.update()
+        # Setup the table
+        rows = [content for content in self.context.values()
+                if interfaces.IContact.providedBy(content)]
+
+        self.table = formatter.SelectedItemFormatter(
+            self.context, self.request, rows,
+            prefix = SESSION_KEY + '.', columns=self.columns,
+            sort_on=[('lastName', False)])
+        self.table.sortKey = 'z3c.formdemo.addressbook.sort-on'
+        self.table.cssClasses['table'] = 'contact-list'
+        self.table.widths = (150, 150)
+        self.table.selectedItem = self.selectedContact
+
+    def __call__(self):
+        self.update()
+        layout = zope.component.getMultiAdapter((self, self.request),
+            ILayoutTemplate)
+        return layout(self)
+
+class AddressBookTemplate(mars.template.TemplateFactory):
+    grok.context(AddressBook)
+    grok.template('addressbook.pt')
+
+class ContactAddTemplate(mars.template.TemplateFactory):
+    grok.context(browser.ContactEditForm)
+    grok.template('contact.pt')
+
+class ContactTemplate(mars.template.TemplateFactory):
+    grok.context(browser.ContactEditForm)
+    grok.template('contact.pt')
+
+class AddressesTemplate(mars.template.TemplateFactory):
+    grok.context(browser.AddressesForm)
+    grok.template('addresses.pt')
+
+class AddressTemplate(mars.template.TemplateFactory):
+    grok.context(browser.AddressForm)
+    grok.template('address.pt')
+
+class PhonesTemplate(mars.template.TemplateFactory):
+    grok.context(browser.PhonesForm)
+    grok.template('phones.pt')
+
+class PhoneTemplate(mars.template.TemplateFactory):
+    grok.context(browser.PhoneForm)
+    grok.template('phone.pt')
+
+class EmailsTemplate(mars.template.TemplateFactory):
+    grok.context(browser.EMailsForm)
+    grok.template('emails.pt')
+
+class EmailTemplate(mars.template.TemplateFactory):
+    grok.context(browser.EMailForm)
+    grok.template('email.pt')
+
+class DateSelectWidgetTemplate(mars.template.WidgetTemplateFactory):
+    grok.context(zope.interface.Interface)
+    grok.template('dateselect.pt')
+    mars.template.widget(dateselect.DateSelectWidget)
+    mars.template.mode(INPUT_MODE)
+    mars.layer.layer(IFormLayer)
+


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.txt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.txt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.txt	2007-07-12 00:29:59 UTC (rev 77708)
@@ -0,0 +1,24 @@
+================
+Addressbook Demo
+================
+
+The purpose of the addressbook demo is to demonstrate a complex, form-driven
+UI with several sub-forms and table-integration.
+
+To start, we need to open a browser and go to the demo applications overview
+screen:
+
+  >>> from z3c.formdemo import testing
+  >>> from z3c.etestbrowser.testing import ExtendedTestBrowser
+  >>> user = ExtendedTestBrowser()
+  >>> user.handleErrors = False
+  >>> user.addHeader('Accept-Language', 'en')
+  >>> skinURL = 'http://localhost:8080/++skin++marsformdemo'
+
+  >>> user.open('http://localhost:8080')
+
+Since all demos are purely public, there is no need to log in. Let's now click
+on the "Address Book" link:
+
+  >>> user.open(skinURL + '/addressbook')
+  >>> print user.contents


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addressbook.txt
___________________________________________________________________
Name: svn:keywords
   + Date Author

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addresses.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addresses.pt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/addresses.pt	2007-07-12 00:29:59 UTC (rev 77708)
@@ -0,0 +1,24 @@
+<fieldset class="address" tal:repeat="form view/addressForms">
+  <legend tal:content="form/title">Name</legend>
+  <div tal:content="structure form/render" />
+</fieldset>
+<div id="add-address">
+  <div class="status"
+         tal:define="status view/status"
+         tal:condition="status">
+    <div class="summary"
+         tal:content="view/status">
+      Form status summary
+    </div>
+  </div>
+  <div>
+    <span class="widget"
+           tal:content="structure view/widgets/addressName/render">
+      <input type="text" size="24" value="" />
+    </span>
+    <span class="buttons">
+      <input tal:repeat="action view/actions/values"
+             tal:replace="structure action/render" />
+    </span>
+  </div>
+</div>

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/contact.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/contact.pt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/contact.pt	2007-07-12 00:29:59 UTC (rev 77708)
@@ -0,0 +1,20 @@
+<div metal:use-macro="macro:form">
+  <metal:block fill-slot="above-buttons">
+    <div id="addresses">
+      <h2><span>Addresses</span></h2>
+      <div class="section-content"
+           tal:content="structure view/addressesForm/render" />
+    </div>
+    <div id="phones">
+      <h2><span>Phone Numbers</span></h2>
+      <div class="section-content"
+           tal:content="structure view/phonesForm/render" />
+    </div>
+    <div id="emails">
+      <h2><span>E-Mail Addresses</span></h2>
+      <div class="section-content"
+           tal:content="structure view/emailsForm/render" />
+    </div>
+    <hr class="separator" />
+  </metal:block>
+</div>

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/contact.py
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/contact.py	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/contact.py	2007-07-12 00:29:59 UTC (rev 77708)
@@ -0,0 +1,74 @@
+__docformat__ = "reStructuredText"
+import zope.interface
+from zope.schema import fieldproperty
+
+from z3c.formdemo.addressbook import interfaces
+
+import grok
+
+class Address(grok.Model):
+    zope.interface.implements(interfaces.IAddress)
+
+    street = fieldproperty.FieldProperty(interfaces.IAddress['street'])
+    city = fieldproperty.FieldProperty(interfaces.IAddress['city'])
+    state = fieldproperty.FieldProperty(interfaces.IAddress['state'])
+    zip = fieldproperty.FieldProperty(interfaces.IAddress['zip'])
+
+    def __init__(self, **data):
+        for name, value in data.items():
+            setattr(self, name, value)
+
+
+class EMails(zope.location.Location, list):
+    pass
+
+class EMail(grok.Model):
+    zope.interface.implements(interfaces.IEMail)
+
+    user = fieldproperty.FieldProperty(interfaces.IEMail['user'])
+    host = fieldproperty.FieldProperty(interfaces.IEMail['host'])
+
+    def __init__(self, **data):
+        for name, value in data.items():
+            setattr(self, name, value)
+
+    @apply
+    def fullAddress():
+        def get(self):
+            return self.user + u'@' + self.host
+        def set(self, value):
+            self.user, self.host = value.split('@')
+        return property(get, set)
+
+
+class Phone(grok.Model):
+    zope.interface.implements(interfaces.IPhone)
+
+    countryCode = fieldproperty.FieldProperty(interfaces.IPhone['countryCode'])
+    areaCode = fieldproperty.FieldProperty(interfaces.IPhone['areaCode'])
+    number = fieldproperty.FieldProperty(interfaces.IPhone['number'])
+    extension = fieldproperty.FieldProperty(interfaces.IPhone['extension'])
+
+    def __init__(self, **data):
+        for name, value in data.items():
+            setattr(self, name, value)
+
+
+class Contact(grok.Model):
+    zope.interface.implements(interfaces.IContact)
+
+    firstName = fieldproperty.FieldProperty(interfaces.IContact['firstName'])
+    lastName = fieldproperty.FieldProperty(interfaces.IContact['lastName'])
+    birthday = fieldproperty.FieldProperty(interfaces.IContact['birthday'])
+
+    addresses = None
+    emails = None
+    homePhone = None
+    cellPhone = None
+    workPhone = None
+
+    def __init__(self, **data):
+        # Save all values
+        for name, value in data.items():
+            setattr(self, name, value)
+


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/contact.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/dateselect.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/dateselect.pt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/dateselect.pt	2007-07-12 00:29:59 UTC (rev 77708)
@@ -0,0 +1,5 @@
+<span class="dateselect">
+  <div tal:replace="structure view/month/render" /> /
+  <div tal:replace="structure view/day/render" /> /
+  <div tal:replace="structure view/year/render" />
+</span>

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/email.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/email.pt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/email.pt	2007-07-12 00:29:59 UTC (rev 77708)
@@ -0,0 +1,5 @@
+<div>
+  <div metal:use-macro="macro:form-header" />
+  <div tal:replace="structure view/widgets/fullAddress/render" />
+  <div tal:replace="structure view/actions/delete/render" />
+</div>

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/emails.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/emails.pt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/emails.pt	2007-07-12 00:29:59 UTC (rev 77708)
@@ -0,0 +1,23 @@
+<div class="row"
+     tal:repeat="form view/emailForms"
+     tal:content="structure form/render" />
+<div id="add-email">
+  <div class="status"
+         tal:define="status view/status"
+         tal:condition="status">
+    <div class="summary"
+         tal:content="view/status">
+      Form status summary
+    </div>
+  </div>
+  <div>
+    <span class="widget"
+           tal:content="structure view/widgets/fullAddress/render">
+      <input type="text" size="24" value="" />
+    </span>
+    <span class="buttons">
+      <input tal:repeat="action view/actions/values"
+             tal:replace="structure action/render" />
+    </span>
+  </div>
+</div>

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/form-macros.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/form-macros.pt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/form-macros.pt	2007-07-12 00:29:59 UTC (rev 77708)
@@ -0,0 +1,14 @@
+<metal:block define-macro="widget-noerror-row">
+<div class="noerror">
+  <div class="label">
+    <label tal:attributes="for widget/id">
+      <span i18n:translate=""
+          tal:content="widget/label">label</span
+      ><span class="required" tal:condition="widget/required">*</span>
+    </label>
+  </div>
+  <div class="widget" tal:content="structure widget/render">
+    <input type="text" size="24" value="" />
+  </div>
+</div>
+</metal:block>

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/phone.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/phone.pt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/phone.pt	2007-07-12 00:29:59 UTC (rev 77708)
@@ -0,0 +1,4 @@
++<input tal:replace="structure view/widgets/countryCode/render" />
+( <input tal:replace="structure view/widgets/areaCode/render" /> )
+<input tal:replace="structure view/widgets/number/render" />
+ext. <input tal:replace="structure view/widgets/extension/render" />

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/phones.pt
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/phones.pt	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/phones.pt	2007-07-12 00:29:59 UTC (rev 77708)
@@ -0,0 +1,4 @@
+<div class="row"
+     tal:repeat="widget view/forms">
+  <div metal:use-macro="macro:widget-row" />
+</div>

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/resources.py
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/resources.py	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/resources.py	2007-07-12 00:29:59 UTC (rev 77708)
@@ -0,0 +1,49 @@
+import zope.interface
+from zope.viewlet.viewlet import CSSViewlet, JavaScriptViewlet
+
+import grok
+
+import mars.resource
+import mars.viewlet
+import mars.layer
+from mars.formdemo.layer import IDemoBrowserLayer
+from mars.formdemo.skin import skin
+from mars.formdemo.addressbook.addressbook import AddressBook
+
+mars.layer.layer(IDemoBrowserLayer)
+
+## CSS resources
+class AddressbookResource(mars.resource.ResourceFactory):
+    """File resource"""
+    grok.name('addressbook.css')
+    mars.resource.file('addressbook.css')
+
+AddressbookCSSViewlet = CSSViewlet('addressbook.css')
+class FormAddressbookCSSViewlet(mars.viewlet.SimpleViewlet, AddressbookCSSViewlet):
+    """css viewlet"""
+    weight = 1000
+    grok.name('addressbook.css')
+    grok.context(zope.interface.Interface)
+    mars.viewlet.view(AddressBook)
+    mars.viewlet.manager(skin.CSSManager)
+
+## Javascript resources
+class TextShadowResource(mars.resource.ResourceFactory):
+    """File resource"""
+    grok.name('text-shadow.js')
+    mars.resource.file('text-shadow.js')
+
+TextShadowViewlet = JavaScriptViewlet('text-shadow.js')
+class FormTextShadowJSViewlet(mars.viewlet.SimpleViewlet, TextShadowViewlet):
+    """css viewlet"""
+    grok.name('addressbook.css')
+    grok.context(zope.interface.Interface)
+    mars.viewlet.view(AddressBook)
+    mars.viewlet.manager(skin.JavaScriptManager)
+
+class NoErrorWidget(mars.macro.MacroFactory):
+ """Name defaults to factory.__name__, 'navigation'"""
+ grok.name('widget-noerror-row')
+ grok.template('form-macros.pt') # required
+ grok.context(zope.interface.Interface) # required if no module context 
+


Property changes on: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/resources.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/text-shadow.js
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/text-shadow.js	                        (rev 0)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/addressbook/text-shadow.js	2007-07-12 00:29:59 UTC (rev 77708)
@@ -0,0 +1,365 @@
+if(window.addEventListener)window.addEventListener('load',textShadows,false);
+else if(window.attachEvent)window.attachEvent('onload',textShadows);
+function setStyles(o,s){
+	var i;
+	s=s.split(';');
+	for(i in s){
+		var p=s[i].split(':');
+		o.style[p[0]]=p[1];
+	}
+}
+function textShadows(){
+	var ua=navigator.userAgent;
+	if(ua.indexOf('KHTML')>=0&&!(ua.indexOf('Safari')>=0))return;
+	var ss=document.styleSheets,a;
+	for(a in ss){
+		var theRules=[],b;
+		if(ss[a].cssRules)theRules=ss[a].cssRules;
+		else if(ss[a].rules)theRules=ss[a].rules;
+		for(b=0; b < theRules.length; b++){
+			var selector=theRules[b].selectorText,r=theRules[b].style.cssText;
+			if(/text-shadow/.test(r)){
+				r=r.replace(/([ ,]) /g,'$1').replace(/.*text-shadow[ :]+/,'').replace(/[ ]*;.*/,'');
+				var shadows=r.split(','),k,els=cssQuery(selector),l;
+				for(l in els){
+					var x=parseInt(els[l].offsetLeft),y=parseInt(els[l].offsetTop),el3=els[l].cloneNode(true);
+					setStyles(el3,'position:absolute;zIndex:50;margin:0');
+					for(k in shadows){
+						var parts=shadows[k].split(' ');
+						var newX=x+parseInt(parts[1]),newY=y+parseInt(parts[2]),rad=parseInt(parts[3]);
+						for(m=0-rad;m<=rad;++m)for(n=0-rad;n<=rad;++n)showShadow(els[l],newX+m,newY+n,parts[0]);
+						var el2=el3.cloneNode(true);
+						setStyles(el2,'left:'+x+'px;top:'+y+'px');
+						els[l].parentNode.appendChild(el2);
+					}
+				}
+			}
+		}
+	}
+}
+function showShadow(el,x,y,color){
+	var el2=el.cloneNode(true);
+	setStyles(el2,'position:absolute;color:'+color+';left:'+x+'px;top:'+y+'px;margin:0;textShadow:none;zIndex:49');
+	el2.style.opacity='.08';
+	el2.style.filter='alpha(opacity=8)';
+	el.parentNode.appendChild(el2);
+}
+
+
+
+/*
+	This work is licensed under a Creative Commons License.
+
+	License: http://creativecommons.org/licenses/by/1.0/
+
+	You are free:
+
+	to copy, distribute, display, and perform the work
+	to make derivative works
+	to make commercial use of the work
+
+	Under the following conditions:
+
+	Attribution. You must give the original author credit
+
+	Author:  Dean Edwards/2004
+	Web:     http://dean.edwards.name/
+*/
+
+/* keeping code tidy! */
+
+/* extendible css query function for common platforms
+
+			tested on IE5.0/5.5/6.0, Mozilla 1.6/Firefox 0.8, Opera 7.23/7.5
+			(all windows platforms - somebody buy me a mac!)
+*/
+
+// -----------------------------------------------------------------------
+//  css query engine
+// -----------------------------------------------------------------------
+
+var cssQuery=function() {
+	var version="1.0.1"; // timestamp: 2004/05/25
+
+	// constants
+	var STANDARD_SELECT=/^[^>\+~\s]/;
+	var STREAM=/[\s>\+~:@#\.]|[^\s>\+~:@#\.]+/g;
+	var NAMESPACE=/\|/;
+	var IMPLIED_SELECTOR=/([\s>\+~\,]|^)([\.:#@])/g;
+	var ASTERISK ="$1*$2";
+	var WHITESPACE=/^\s+|\s*([\+\,>\s;:])\s*|\s+$/g;
+	var TRIM="$1";
+	var NODE_ELEMENT=1;
+	var NODE_TEXT=3;
+	var NODE_DOCUMENT=9;
+
+	// sniff for explorer (cos of one little bug)
+	var isMSIE=/MSIE/.test(navigator.appVersion), isXML;
+
+	// cache results for faster processing
+	var cssCache={};
+
+	// this is the query function
+	function cssQuery(selector, from) {
+		if (!selector) return [];
+		var useCache=arguments.callee.caching && !from;
+		from=(from) ? (from.constructor == Array) ? from : [from] : [document];
+		isXML=checkXML(from[0]);
+		// process comma separated selectors
+		var selectors=parseSelector(selector).split(",");
+		var match=[];
+		for (var i in selectors) {
+			// convert the selector to a stream
+			selector=toStream(selectors[i]);
+			// process the stream
+			var j=0, token, filter, cacheSelector="", filtered=from;
+			while (j < selector.length) {
+				token=selector[j++];
+				filter=selector[j++];
+				cacheSelector += token + filter;
+				// process a token/filter pair
+				filtered=(useCache && cssCache[cacheSelector]) ? cssCache[cacheSelector] : select(filtered, token, filter);
+				if (useCache) cssCache[cacheSelector]=filtered;
+			}
+			match=match.concat(filtered);
+		}
+		// return the filtered selection
+		return match;
+	};
+	cssQuery.caching=false;
+	cssQuery.reset=function() {
+		cssCache={};
+	};
+	cssQuery.toString=function () {
+		return "function cssQuery() {\n  [version " + version + "]\n}";
+	};
+
+	var checkXML=(isMSIE) ? function(node) {
+		if (node.nodeType != NODE_DOCUMENT) node=node.document;
+		return node.mimeType == "XML Document";
+	} : function(node) {
+		if (node.nodeType == NODE_DOCUMENT) node=node.documentElement;
+		return node.localName != "HTML";
+	};
+
+	function parseSelector(selector) {
+		return selector
+		// trim whitespace
+		.replace(WHITESPACE, TRIM)
+		// encode attribute selectors
+		.replace(attributeSelector.ALL, attributeSelector.ID)
+		// e.g. ".class1" --> "*.class1"
+		.replace(IMPLIED_SELECTOR, ASTERISK);
+	};
+
+	// convert css selectors to a stream of tokens and filters
+	//  it's not a real stream. it's just an array of strings.
+	function toStream(selector) {
+		if (STANDARD_SELECT.test(selector)) selector=" " + selector;
+		return selector.match(STREAM) || [];
+	};
+
+	var pseudoClasses={ // static
+		// CSS1
+		"link": function(element) {
+			for (var i=0; i < document.links; i++) {
+				if (document.links[i] == element) return true;
+			}
+		},
+		"visited": function(element) {
+			// can't do this without jiggery-pokery
+		},
+		// CSS2
+		"first-child": function(element) {
+			return !previousElement(element);
+		},
+		// CSS3
+		"last-child": function(element) {
+			return !nextElement(element);
+		},
+		"root": function(element) {
+			var document=element.ownerDocument || element.document;
+			return Boolean(element == document.documentElement);
+		},
+		"empty": function(element) {
+			for (var i=0; i < element.childNodes.length; i++) {
+				if (isElement(element.childNodes[i]) || element.childNodes[i].nodeType == NODE_TEXT) return false;
+			}
+			return true;
+		}
+		// add your own...
+	};
+
+	var QUOTED=/([\'\"])[^\1]*\1/;
+	function quote(value) {return (QUOTED.test(value)) ? value : "'" + value + "'"};
+	function unquote(value) {return (QUOTED.test(value)) ? value.slice(1, -1) : value};
+
+	var attributeSelectors=[];
+
+	function attributeSelector(attribute, compare, value) {
+		// properties
+		this.id=attributeSelectors.length;
+		// build the test expression
+		var test="element.";
+		switch (attribute.toLowerCase()) {
+			case "id":
+				test += "id";
+				break;
+			case "class":
+				test += "className";
+				break;
+			default:
+				test += "getAttribute('" + attribute + "')";
+		}
+		// continue building the test expression
+		switch (compare) {
+			case "=":
+				test += "==" + quote(value);
+				break;
+			case "~=":
+				test="/(^|\\s)" + unquote(value) + "(\\s|$)/.test(" + test + ")";
+				break;
+			case "|=":
+				test="/(^|-)" + unquote(value) + "(-|$)/.test(" + test + ")";
+				break;
+		}
+		push(attributeSelectors, new Function("element", "return " + test));
+	};
+	attributeSelector.prototype.toString=function() {
+		return attributeSelector.PREFIX + this.id;
+	};
+	// constants
+	attributeSelector.PREFIX="@";
+	attributeSelector.ALL=/\[([^~|=\]]+)([~|]?=?)([^\]]+)?\]/g;
+	// class methods
+	attributeSelector.ID=function(match, attribute, compare, value) {
+		return new attributeSelector(attribute, compare, value);
+	};
+
+	// select a set of matching elements.
+	// "from" is an array of elements.
+	// "token" is a character representing the type of filter
+	//  e.g. ">" means child selector
+	// "filter" represents the tag name, id or class name that is being selected
+	// the function returns an array of matching elements
+	function select(from, token, filter) {
+		//alert("token="+token+",filter="+filter);
+		var namespace="";
+		if (NAMESPACE.test(filter)) {
+			filter=filter.split("|");
+			namespace=filter[0];
+			filter=filter[1];
+		}
+		var filtered=[], i;
+		switch (token) {
+			case " ": // descendant
+				for (i in from) {
+					var subset=getElementsByTagNameNS(from[i], filter, namespace);
+					for (var j=0; j < subset.length; j++) {
+						if (isElement(subset[j]) && (!namespace || compareNamespace(subset[j], namespace)))
+							push(filtered, subset[j]);
+					}
+				}
+				break;
+			case ">": // child
+				for (i in from) {
+					var subset=from[i].childNodes;
+					for (var j=0; j < subset.length; j++)
+						if (compareTagName(subset[j], filter, namespace)) push(filtered, subset[j]);
+				}
+				break;
+			case "+": // adjacent (direct)
+				for (i in from) {
+					var adjacent=nextElement(from[i]);
+					if (adjacent && compareTagName(adjacent, filter, namespace)) push(filtered, adjacent);
+				}
+				break;
+			case "~": // adjacent (indirect)
+				for (i in from) {
+					var adjacent=from[i];
+					while (adjacent=nextElement(adjacent)) {
+						if (adjacent && compareTagName(adjacent, filter, namespace)) push(filtered, adjacent);
+					}
+				}
+				break;
+			case ".": // class
+				filter=new RegExp("(^|\\s)" + filter + "(\\s|$)");
+				for (i in from) if (filter.test(from[i].className)) push(filtered, from[i]);
+				break;
+			case "#": // id
+				for (i in from) if (from[i].id == filter) push(filtered, from[i]);
+				break;
+			case "@": // attribute selector
+				filter=attributeSelectors[filter];
+				for (i in from) if (filter(from[i])) push(filtered, from[i]);
+				break;
+			case ":": // pseudo-class (static)
+				filter=pseudoClasses[filter];
+				for (i in from) if (filter(from[i])) push(filtered, from[i]);
+				break;
+		}
+		return filtered;
+	};
+
+	var getElementsByTagNameNS=(isMSIE) ? function(from, tagName) {
+		return (tagName == "*" && from.all) ? from.all : from.getElementsByTagName(tagName);
+	} : function(from, tagName, namespace) {
+		return (namespace) ? from.getElementsByTagNameNS("*", tagName) : from.getElementsByTagName(tagName);
+	};
+
+	function compareTagName(element, tagName, namespace) {
+		if (namespace && !compareNamespace(element, namespace)) return false;
+		return (tagName == "*") ? isElement(element) : (isXML) ? (element.tagName == tagName) : (element.tagName == tagName.toUpperCase());
+	};
+
+	var PREFIX=(isMSIE) ? "scopeName" : "prefix";
+	function compareNamespace(element, namespace) {
+		return element[PREFIX] == namespace;
+	};
+
+	// return the previous element to the supplied element
+	//  previousSibling is not good enough as it might return a text or comment node
+	function previousElement(element) {
+		while ((element=element.previousSibling) && !isElement(element)) continue;
+		return element;
+	};
+
+	// return the next element to the supplied element
+	function nextElement(element) {
+		while ((element=element.nextSibling) && !isElement(element)) continue;
+		return element;
+	};
+
+	function isElement(node) {
+		return Boolean(node.nodeType == NODE_ELEMENT && node.tagName != "!");
+	};
+
+
+	// use a baby push function because IE5.0 doesn't support Array.push
+	function push(array, item) {
+		array[array.length]=item;
+	};
+
+	// fix IE5.0 String.replace
+	if ("i".replace(/i/,function(){return""})) {
+		// preserve String.replace
+		var string_replace=String.prototype.replace;
+		// create String.replace for handling functions
+		var function_replace=function(regexp, replacement) {
+			var match, newString="", string=this;
+			while ((match=regexp.exec(string))) {
+				// five string replacement arguments is sufficent for cssQuery
+				newString += string.slice(0, match.index) + replacement(match[0], match[1], match[2], match[3], match[4]);
+				string=string.slice(match.lastIndex);
+			}
+			return newString + string;
+		};
+		// replace String.replace
+		String.prototype.replace=function (regexp, replacement) {
+			this.replace=(typeof replacement == "function") ? function_replace : string_replace;
+			return this.replace(regexp, replacement);
+		};
+	}
+
+	return cssQuery;
+}();

Modified: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/skin/skin.py
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/skin/skin.py	2007-07-12 00:28:03 UTC (rev 77707)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/skin/skin.py	2007-07-12 00:29:59 UTC (rev 77708)
@@ -36,7 +36,7 @@
     grok.name('ICSS')
     grok.context(zope.interface.Interface)
 
-class JavaScript(mars.viewlet.ViewletManager):
+class JavaScriptManager(mars.viewlet.ViewletManager):
     """javascript viewletmanager"""
     grok.name('IJavaScript')
     grok.context(zope.interface.Interface)

Modified: Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/tests.py
===================================================================
--- Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/tests.py	2007-07-12 00:28:03 UTC (rev 77707)
+++ Sandbox/darrylcousins/mars.formdemo/src/mars/formdemo/tests.py	2007-07-12 00:29:59 UTC (rev 77708)
@@ -15,6 +15,7 @@
                     ('widgets', 'widgets.txt'),
                     ('spreadsheet', 'spreadsheet.txt'),
                     ('wizard', 'wizard.txt'),
+                  #  ('addressbook', 'addressbook.txt'),
                     ):
         suite = functional.FunctionalDocFileSuite(
             os.path.join(*docpath),



More information about the Checkins mailing list