Skip to content

Commit

Permalink
expose some masonry configuration. use less to write the css
Browse files Browse the repository at this point in the history
  • Loading branch information
toutpt committed Oct 20, 2012
1 parent 026c9fd commit 5c018f5
Show file tree
Hide file tree
Showing 10 changed files with 207 additions and 26 deletions.
28 changes: 27 additions & 1 deletion README.txt
Expand Up @@ -5,7 +5,33 @@ This add-on is inspeared by ContentWellPortlets_. Main differences are:

* You can add as many portlets as you want above and below the content body.
* There is only one manage portlet screen
* Portlets are rendering with the jquery plugin masonry_ v2.0.110927
* Portlets layout can be configured
* Portlets layout can be extended in many ways

Layout
======

Layout is controlled with many axes. The main idea is to force all portlets
in above and below the content to float from left to right.

But portlet has no forced width, so here you have many 'mode' you can configure
per page for above and below. Note 'above' and 'below' portlets can use a
different mode.

Availables modes:
* fixed with 220
* min-max: 220 - 300
* free

The height is not forced. This is where the jquery.masonry plugin comes in
action. Portlets will be moved to build a layout with a minimal height.
You can disable this behavior by just unactivate the corresponding javascript::

<javascript id="++resource++collective.masonry/masonry.js" enabled="False" />


Some mode can force you to review the masonry configuration exposed in the
viewlet configuration.

Credits
=======
Expand Down
2 changes: 1 addition & 1 deletion buildout.cfg
@@ -1,6 +1,6 @@
[buildout]
extends =
https://raw.github.com/collective/buildout.plonetest/master/test-4.1.x.cfg
https://raw.github.com/collective/buildout.plonetest/master/test-4.x.cfg
package-name = collective.masonry
package-extras = [test]

Expand Down
2 changes: 1 addition & 1 deletion collective/masonry/profiles/default/metadata.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<metadata>
<version>1201</version>
<version>1202</version>
<dependencies>
<dependency>profile-collective.js.imagesloaded:default</dependency>
<dependency>profile-collective.js.masonry:default</dependency>
Expand Down
14 changes: 11 additions & 3 deletions collective/masonry/profiles/default/registry.xml
@@ -1,12 +1,20 @@
<registry>
<record name="collective.masonry.vocabulary.mode">
<field type="plone.registry.field.Tuple">
<title>Masonry mode</title>
<title>Masonry modes</title>
<value_type type="plone.registry.field.TextLine" />
</field>
<value>
<element>Fixed width</element>
<element>Fixed width and height</element>
<element>Fixed width 220</element>
<element>Min 220 Max 300</element>
<element>Full width</element>
<element>Width free</element>
</value>
</record>
<record name="collective.masonry.defaultmode">
<field type="plone.registry.field.TextLine">
<title>Masonry default mode</title>
</field>
<value>Fixed width 220</value>
</record>
</registry>
45 changes: 35 additions & 10 deletions collective/masonry/resources/masonry.css
@@ -1,10 +1,35 @@
#portletsAboveContent .portletWrapper{float:left;width:14em;}
#portletsBelowContent .portletWrapper{float:left;width:14em;}
#portletsAboveContent dl.portlet,
#portletsBelowContent dl.portlet{
font-size:100%;
}
#portletsAboveContent dd,
#portletsBelowContent dd{
margin-left: 0;
}
/*global behavior: all portlets are in float*/
#portlets-above .portlet,
#portlets-above .portlet {
float: left;
font-size: 100%;
}
/*Fix for wysiwyg img*/
#portlets-above .portlet img,
#portlets-above .portlet img {
max-width: 100%;
}
/*THEME 1: fixed-width-220*/
#portlets-above .fixed-width-220 .portlet,
#portlets-below .fixed-width-220 .portlet {
width: 220px;
margin: 10px;
}
/*THEME 2: min-220-max-300*/
#portlets-above .min-220-max-300 .portlet,
#portlets-below .min-220-max-300 .portlet {
min-width: 220px;
max-width: 300px;
margin: 10px;
}
/*THEME 3: full width*/
#portlets-above .full-width .portlet,
#portlets-below .full-width .portlet {
width: 100%!important;
margin: 0;
}
/*THEME 4: Width free (means no constraint except margin)*/
#portlets-above .width-free .portlet,
#portlets-below .width-free .portlet {
margin: 0;
}
8 changes: 4 additions & 4 deletions collective/masonry/resources/masonry.js
@@ -1,10 +1,10 @@
$(document).ready(function() {
var $portletAboveContainer = $('#portletsAboveContent');
var $portletBelowContainer = $('#portletsBelowContent');
var $portletAboveContainer = $('#portlets-above');
var $portletBelowContainer = $('#portlets-below');
$portletAboveContainer.imagesLoaded( function() {
$portletAboveContainer.masonry({itemSelector:'.portletWrapper'});
$portletAboveContainer.masonry(masonry_configuration);
});
$portletBelowContainer.imagesLoaded( function() {
$portletBelowContainer.masonry({itemSelector:'.portletWrapper'});
$portletBelowContainer.masonry(masonry_configuration);
});
});
46 changes: 46 additions & 0 deletions collective/masonry/resources/masonry.less
@@ -0,0 +1,46 @@
/*global behavior: all portlets are in float*/
#portlets-above .portlet,
#portlets-above .portlet{
float:left;
font-size:100%;
}
/*Fix for wysiwyg img*/
#portlets-above .portlet img,
#portlets-above .portlet img{
max-width: 100%;
}

/*THEME 1: fixed-width-220*/
#portlets-above .fixed-width-220,
#portlets-below .fixed-width-220{
.portlet{
width: 220px;
margin: 10px;
}
}

/*THEME 2: min-220-max-300*/
#portlets-above .min-220-max-300,
#portlets-below .min-220-max-300{
.portlet{
min-width: 220px;
max-width: 300px;
margin: 10px;
}
}

/*THEME 3: full width*/
#portlets-above .full-width,
#portlets-below .full-width{
.portlet{
width: 100%!important;
margin: 0;
}
}
/*THEME 4: Width free (means no constraint except margin)*/
#portlets-above .width-free,
#portlets-below .width-free{
.portlet{
margin: 0;
}
}
1 change: 1 addition & 0 deletions collective/masonry/templates/portletsabovecontent.pt
@@ -1,6 +1,7 @@
<div id="portlets-above"
i18n:domain="collective.masonry" tal:define="inmanage python:request.get('URL').endswith('@@manage-portlets') or 'portlets++' in request.get('URL')">
<div tal:attributes="class view/get_mode" tal:condition="not:inmanage">
<script tal:replace="structure view/config/masonry_configuration"></script>
<div id="portletsAboveContent" tal:content="structure provider:masonry.above" />
<div class="visualClear"/>
</div>
Expand Down
2 changes: 1 addition & 1 deletion collective/masonry/upgrades.zcml
Expand Up @@ -7,7 +7,7 @@
title="Common upgrade"
description="apply profile"
source="*"
destination="1201"
destination="1202"
handler=".upgrades.common"
profile="collective.masonry:default"/>

Expand Down
85 changes: 80 additions & 5 deletions collective/masonry/viewlets.py
Expand Up @@ -12,7 +12,7 @@
from plone.z3cform import layout
from zope.schema.interfaces import IVocabularyFactory
from plone.registry.interfaces import IRegistry

from persistent.dict import PersistentDict

class RegistryVocabulary(object):
"""vocabulary to use with plone.app.registry"""
Expand Down Expand Up @@ -41,11 +41,20 @@ class IViewletConfiguration(interface.Interface):
belowmode = schema.Choice(title=u"Below mode",
vocabulary="collective.masonry.vocabulary.mode")

columnWidth = schema.Int(title=u"columnWidth", required=False)
gutterWidth = schema.Int(title=u"gutterWidth", default=10)
isFitWidth = schema.Bool(title=u"isFitWidth", default=False)
isResizable = schema.Bool(title=u"isResizable", default=True)


class ViewletConfigurationForm(AutoExtensibleForm, form.EditForm):
"""Form to configure default view"""
schema = IViewletConfiguration

def applyChanges(self, data):
super(ViewletConfigurationForm, self).applyChanges(data)
url = self.context.absolute_url()
self.request.response.redirect('%s/@@manage-portlets' % url)

class ViewletConfigurationFormView(layout.FormWrapper):
form = ViewletConfigurationForm
Expand All @@ -56,24 +65,90 @@ class ViewletConfigurationAdapter(object):

def __init__(self, context):
self.context = context
self._configuration = None
self._default_mode = None

@property
def configuration(self):
if self._configuration is None:
#get on context
self._configuration = getattr(self.context, 'masonry_configuration',
None)
if self._configuration is None:
#load default
config = {}
config["gutterWidth"] = 10
config["isFitWidth"] = False
config["isResizable"] = True
self._configuration = config

return self._configuration

def get_storage(self):
storage = getattr(self.context, 'masonry_configuration', None)
if storage is None:
self.context.masonry_configuration = PersistentDict()
#loads default
config = self.context.masonry_configuration
config["gutterWidth"] = 10
config["isFitWidth"] = False
config["isResizable"] = True
return self.context.masonry_configuration

def get_columnWidth(self):
return self.configuration.get('columnWidth', None)
def set_columnWidth(self, value):
if value:
self.get_storage()['columnWidth'] = value
columnWidth = property(get_columnWidth, set_columnWidth)

def get_gutterWidth(self):
return self.configuration.get('gutterWidth', 10)
def set_gutterWidth(self, value):
self.get_storage()['gutterWidth'] = value
gutterWidth = property(get_gutterWidth, set_gutterWidth)

def get_isFitWidth(self):
return self.configuration.get('isFitWidth', False)
def set_isFitWidth(self, value):
self.get_storage()['isFitWidth'] = value
isFitWidth = property(get_isFitWidth, set_isFitWidth)

def get_isResizable(self):
return self.configuration.get('isResizable', True)
def set_isResizable(self, value):
self.get_storage()['isResizable'] = value
isResizable = property(get_isResizable, set_isResizable)

def get_abovemode(self):
return getattr(self.context, 'masonryabovemode',
self.default_above_mode)
self.default_mode)
def set_abovemode(self, value):
setattr(self.context, 'masonryabovemode', value)
abovemode = property(get_abovemode, set_abovemode)

def get_belowmode(self):
return getattr(self.context, 'masonrybelowmode',
self.default_above_mode)
self.default_mode)
def set_belowmode(self, value):
setattr(self.context, 'masonrybelowmode', value)
belowmode = property(get_belowmode, set_belowmode)

@property
def default_above_mode(self):
return 'Fixed width'
def default_mode(self):
if not self._default_mode:
registry = component.getUtility(IRegistry)
self._default_mode = registry.get('collective.masonry.defaultmode',
'fixed-width-220')
return self._default_mode

def masonry_configuration(self):
config = "{"
for key in self.configuration:
config+="%s: %s," % (key, self.configuration[key])
config+="itemSelector:'.portlet'}"
config = config.replace('True', 'true').replace('False', 'false')
return """<script type="text/javascript">var masonry_configuration = %s</script>""" % config


class PortletsAboveViewlet(ViewletBase):
Expand Down

0 comments on commit 5c018f5

Please sign in to comment.