[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