Plone Mockup is an attempt to separate Plone, the user interface, from Plone, the server. It leverages Patterns to create a library of rich interaction patterns triggered by CSS classes and configured via HTML5 data attributes.
The mockup is a fully functional prototype of Plone and its bundles. As it is realised entirely in HTML5 and Javascript, it can be run in a browser without the need for a full Plone installation; therefore making it easy to showcase Plone's UI or developing a new theme. Using diazo it is possible to integrate other backends alongside (or instead of) Plone.
Use it now!
The only requirements to bootstrap Plone mockup are git and npm .
Make sure you use latest version of nodejs
and npm.
Then check out the repository from GitHub:
git clone git://github.com/plone/mockup.git
And bootstrap your environment:
cd mockup
make bootstrap
To build all bundles just do:
make
And you can run tests with:
make test
Right now tests are
.
See it in action!
Here are all the interactions we have, listed in alphabetical order:
Bundles
TODO
Current CMFPlone ECMA scripts status: Google doc for keeping track of current status of CMFPlone/ecma_scripts stuff
Patterns
Patterns are a set of conventions to configure interaction via markup. If you have developed some Javascript interaction (for example, a dropdown menu) it's quite likely that you've already used the basic concept behind patterns.
Basically, almost every jQuery plugin expects a certain kind of markup to be present, and then expects you to initialize the widget by picking out the root element of the widget and pass some options to it. For example you might have this very basic markup for a datetime widget:
<input id="foo" />
And then you are expected to call some Javascript to initialize it (and set options):
$('#foo').datetime({
format: 'mmmm d, yyyy',
formatSubmit: 'yyyy-mm-dd'
});
Then you might find it a little bit tedious
to call that Javascript for every date widget that's there,
so you mark all the <input /> tags
that you want to turn into datepickers with a specific CSS class,
and call that line of code just once when the DOM is loaded.
<input id="date-picker-1" class="date-picker" /> <input id="date-picker-2" class="date-picker" />
$(document).ready(function() {
$('input.date-picker').datetime({
format: 'mmmm d, yyyy',
formatSubmit: 'yyyy-mm-dd'
});
});
If you got at this stage already in your Javascript code, you are already using the basic idea behind patterns.
Why is Patterns better than this?
Patterns has of course more to offer than just this basic approach:
automatic binding (and re-binding after reloads),
taking the options from the DOM via data-* attributes,
and a unified, coherent approach.
Is this related to Patternslib?
- TL;DR
- Yes. But we provide a different set of interactions.
- Long story kept long
- TODO
Automatic binding
Automatic binding relieves us of the problem of initializing a widget from the markup. In our initial example, we actually had to manually bind the initialization routine to the page loading (therefore, when the page is loaded, all the elements marked as interactive widgets will be initialized). This works fine as long as we don't start replacing parts of the DOM with HTML coming from the backend or, say, Javascript templates.
If we start doing that, and especially if the replaced parts of the DOM contains one or more interactive widgets, we have to rebind them all, which is quite a tedious thing to code.
Patterns instead, will automatically initialize, upon page loading, all the interactive widgets it find in the document, and you can also tell it to rebind all the widgets it finds in a particular section of the page, when for example we have replaced the content of that section:
define([
'jquery',
'js/patterns/base',
'jam/Patterns/src/registry'
], function($, Base, registry, undefined) {
// Stuff etc
var rerender($element) {
$element.load(
'http://example.com/my-html',
function(response.status, request) {
// Rebinds every pattern found in the AJAX-loaded HTML
registry.scan($element);
}
);
}
});
This is a great improvement over the "manual" way, where rebinding could take tens of lines of code or even more for complex examples: here, we're down to one line that will always work even if we have no idea of which widgets will get in.
Pattern options
Patterns can take options in two ways: from the DOM or via the jQuery interface. It is highly recommended to use the DOM interface, since it offers a lot more flexibility compared to the jQuery approach. Also, if we wish to use the automatic binding and rebinding functionality, the DOM approach is more straightforward and hassle-free.
If we put options in the DOM,
we have to use HTML5 data attributes.
It's not necessary to put the options directly on the root node
of the widget
(the one with the pat-* class),
since Patterns will also scan all the parents of that node
from the bottom upwards,
so we can for example put the options just once
on the <body /> tag
and have all the widgets use the same set of options:
<body data-datetime-format="d-mmmm-yyyy@HH:MM"
data-datetime-ampm="true"
data-datetime-pickadateMonthSelector="false">
<!-- Both widgets use the same options -->
<input class="pat-datetime" />
<input class="pat-datetime" />
<body>
But if we need to override some options for a certain widget (or an entire DOM section) we can just put it on the node or on whatever DOM element wraps the section:
<body data-datetime-format="d-mmmm-yyyy@HH:MM"
data-datetime-ampm="true">
<input class="pat-datetime" /> <!-- There's a month dropdown here -->
<div data-datetime-pickadateMonthSelector="false">
<input class="pat-datetime" /> <!-- but no month dropdown here! -->
<input class="pat-datetime" /> <!-- And here as well -->
</div>
<body>
jQuery interface
Patterns can also be used as a jQuery plugin, passing options as with any other jQuery plugin:
$('.pat-datetime').patternDatetime({
pickadateYearSelector: true
});
In this case the options passed to the jQuery function will take precedence over the ones defined in the DOM, although the parents will still be scanned and the options defined there will be picked up if they are not overridden in the jQuery call:
{
showAMPM: true,
format: "d-mmmm-yyyy@HH:MM",
pickadateMonthSelector: false,
pickadateYearSelector: true
}
Making a pattern
TODO
Testing the pattern
TODO