class Top(Container): BLUEPRINT = BluePrint( MobileNavigation.BLUEPRINT, # Layout alternatives backgroundColor=Color('#fff'), doc_backgroundColor='Top background color.', )
class Page(Component): u"""The **Page** component builds the content of a single page, dependent on the parameters in the url.""" # Get Constants->Config as class variable, so inheriting classes can redefine values. C = Component.C BLUEPRINT = BluePrint( name='Untitled', doc_name=u'Name of the page.', class_=C.CLASS_PAGE, doc_pageClass= u'Class of the page. Default is the result of **self.getClassName()** or C.CLASS_PAGE', ) def reset(self): u"""Gets called prior to every page build. Can be redefined by inheriting theme classes. Default behavior is to do nothing.""" pass def buildBlock(self, b): u""" Make the builder *b* open the page and open the block. Then call the builder for all enclosed components. Make the builder *b* close the block and close the page. """ b.page(self) for component in self.components: component.build( b) # Dispatch the type of building to be done here. # Allow the components to build the JavaScript they need. for component in self.components: component.buildJS(b) b._page(self)
class ItemGroup(Group): u"""The **ItemGroup** implements a group with automatic responsive behavior for groups of items. Defined by a range of widths, a group of items is scaled to stay on the same line. If the screen width changes, then then the **clear** attribute is shifted value, so the line break takes place between another set of items.""" # Get Constants->Config as class variable, so inheriting classes can redefine values. C = Group.C BLUEPRINT = BluePrint( # Selection stuff start=0, count= 12, # Index of first and last selected thumbnail for this component # Layout stuff colWidth=12, # Group stuff groupBackgroundColor=None, # Background image of the item row. # Range of items in one row and the corresponding widths #itemRange=range(3, 6), #mediaWidths=(C.M_MOBILE_MAX) columns=5, ) def buildBlockRow(self, b): s = self.style b.div(class_=self.C.CLASS_ROW, width=s.rowWidth or Perc(100)) mediaStyles = Media(max=self.C.M_MOBILE_MAX, display=s.mobileRowDisplay or self.C.BLOCK, float=self.NONE, minwidth=0, width=self.C.AUTO, paddingleft=0, paddingright=0, margin=0) for index in range(s.count): # Build all child components of the generic group. #print index, s.columns, index % s.columns, index % s.columns == s.columns-1 colIndex = index % s.columns classIndex = '%s%d' % (s.class_ or 'itemGroup', colIndex) if index % s.columns == 0: clear = self.C.BOTH else: clear = self.C.NONE b.div( class_=(self.C.CLASS_ITEM, classIndex), width=Perc(100 / s.columns), float=self.C.LEFT, clear=clear, media=mediaStyles, ) for component in self.components: saveItemStart = component.style.itemStart component.style.itemStart = index component.build(b) component.style.itemStart = saveItemStart b._div(comment=self.C.CLASS_ITEM) b._div(comment=self.C.CLASS_ROW)
class TagCloud(Component): # Get Constants->Config as class variable, so inheriting classes can redefine values. C = Component.C BLUEPRINT = BluePrint() def initialize(self): # Generic builder for all components. To be redefined by inheriting class. components = self.components # Replace by linked components self.components = []
class Theme(Component): # Get Constants->Config as class variable, so inheriting classes can redefine values. C = Component.C TITLE = 'Redefine cls.TITLE in inheriting theme class.' BLUEPRINT = BluePrint() def __repr__(self): return '<Theme: %s>' % (self.selector or self.name) def reset(self): u"""Gets called prior to every page render. Can be redefined by inheriting theme classes. Default behavior is to do nothing.""" pass def getMatchingTemplate(self, builder): u""" Find the page template in self.components that has the best name match with currently available parameters in **self.e.form**. Unquote the url parameters and remove the spaces to create potential template names. Then match them against the available template components of **self**. """ urlNames = set() for urlName in builder.getParamNames(): urlNames.add(urllib.unquote(urlName).replace(' ', '')) for component in self.components: if component.template in urlNames or component.name in urlNames: return component # Could not find a match, answer the default template. # If no default component exists, then answer self. # This happens if there is only one page in the site. return self.getComponent(self.C.TEMPLATE_DEFAULT) or self def getTemplates(self): u"""Answer the list of templates of this theme.""" return self.components def buildBlock(self, builder): u"""Build the current page of this theme.""" builder.theme(self) # Make the builder open the site. for component in self.components: component.build( builder) # Make all components of the theme build themselves. builder._theme(self) # Make the builder close the site. def handlePost(self): pass def getClassName(self): return None # Selector does not show, just the style block.
class FeaturedByTextList(FeaturedBase): # Get Constants->Config as class variable, so inheriting classes can redefine values. C = FeaturedBase.C BLUEPRINT = BluePrint( # Selection stuff start=0, count=6, # Index of first and last selected feature for this component # Layout stuff colWidth=4, # Default amount of columns for this component # Category stuff in h5 categoryColor=Color('#828487'), categorySize=Em(0.9), categoryLineHeight=Em(1.2), categoryWeight=C.NORMAL, categoryMarginTop=Em(1), categoryDisplay=C.BLOCK, # Name stuff in h2 nameColor=Color('#4080D0'), nameSize=Em(1.4), nameWeight=C.NORMAL, nameDisplay=C.BLOCK, nameMarginBottom=Em(0.2), nameMarginTop=Em(0.2), nameLineHeight=Em(1.2), # Topic stuff topicColor=Color('#202020'), # Mobile stuff mobileDisplay=C.NONE, mobilePaddingTop=Em(2), mobilePaddingBottom=Em(0.5), mobilePaddingLeft=Em(0.5), mobilePaddingRight=Em(0.5), mobileMarginTop=Em(2), mobileMarginBottom=Em(0.5), mobileMarginLeft=Em(0.5), mobileMarginRight=Em(0.5), mobileFloat=C.NONE, ) def buildFeatured(self, b, data): s = self.style for item in data.items: if item.category: b.a(href='/%s-%s' % (self.C.PARAM_CATEGORY, item.category), class_=self.C.CLASS_CATEGORYTHUMB) b.h5(fontsize=s.categorySize, fontweight=s.categoryWeight, lineheight=s.categoryLineHeight, color=s.categoryColor, margintop=s.categoryMarginTop, display=s.categoryDisplay) b.text(item.category) b._h5() b._a() b.a(href='/%s-%s' % (self.C.PARAM_ARTICLE, item.id), class_=self.C.CLASS_NAME) b.h2(fontsize=s.nameSize, fontweight=s.nameWeight, lineheight=s.nameLineHeight, color=s.nameColor, marginbottom=s.nameMarginBottom, display=s.nameDisplay, margintop=s.nameMarginTop) b.text(item.name) b._h2() b._a() if isinstance(item.topic, basestring): b.text(item.topic) elif item.topic is not None: # Test on element. Topic elements need to be defined in global style. self.buildElement(b, item.topic)
class Graph(Component): # Get Constants->Config as class variable, so inheriting classes can redefine values. C = Component.C BLUEPRINT = BluePrint( # Layout stuff ) def buildBlock(self, b): colClass = TX.col2Class('graph') s = self.style b.block(self) b.div(class_=colClass, float=s.graphFloat or self.LEFT, width=s.graphWidth or Perc(100)) b._div(comment=colClass) b._block(self)
class Footer(Container): # Get Constants->Config as class variable, so inheriting classes can redefine values. C = Container.C BLUEPRINT = BluePrint( # Layout stuff colDisplay=C.BLOCK, colClear=C.BOTH, colMarginBottom=Em(0.5), colColor=None, colMarginRight='1.8%', colMarginLeft=0, colFloat=C.LEFT, colMinHeight=1, # Layout stuff colWidth=12, # Default amount of columns for this component # Mobile stuff mobileDisplay=C.NONE, mobilePaddingTop=Em(2), mobilePaddingBottom=Em(0.5), mobilePaddingLeft=Em(0.5), mobilePaddingRight=Em(0.5), mobileMarginTop=Em(2), mobileMarginBottom=Em(0.5), mobileMarginLeft=Em(0.5), mobileMarginRight=Em(0.5), mobileFloat=C.NONE, mobileWidth=C.AUTO, ) def buildBlock(self, b): s = self.style colClass = self.getColClass(s.colWidth) b.block(self) b.div(class_=colClass, float=s.logoFloat, marginleft=s.marginLeft, marginright=s.marginRight, margintop=s.marginTop, marginbottom=s.marginBottom) b._div(comment=colClass) b._block(self)
class FeaturedByImage(FeaturedBase): u"""The @FeaturedByImage@ feature component, shows a featured article by its poster image on full width of the component. If there is no poster image defined in the article meta data, then the first image in the article is used here. The image is a link to the article page. Respectively the binary flags @BluePrint@ *showLevel*, *showTitle* and *showTopic* will enable the level of the article (as defined in the article source @$level@), the article title (@$title@) and topic (@$topic), of set to @True@.""" # Get Constants->Config as class variable, so inheriting classes can redefine values. C = FeaturedBase.C BLUEPRINT = BluePrint(FeaturedBase.BLUEPRINT, # Selection stuff start=0, doc_start=u'Index of first selected item to feature.', count=3, doc_count=u'Number of selected items to feature.', # Container component layout stuff width=Perc(30), doc_width=u'Overall width of the component.', widthMobile=Perc(100), doc_widthMobile=u'Overall width of the component for mobile.', backgroundColor=None, doc_backgroundColor=u'Background color of the component.', display=C.BLOCK, doc_display=u'Display status of the component', displayMobile=C.BLOCK, doc_displayMobile=u'Display status of the component for mobile.', float=C.LEFT, doc_float=u'Float status of the component.', floatMobile=C.LEFT, doc_floatMobile=u'Float status of the component for mobile.', padding=0, doc_padding=u'Padding of the component content.', # Item/article stuff itemDisplay=C.BLOCK, doc_itemDisplay=u'Display type of the item/article image cell.', itemBackgroundColor=Color('#E0E0E0'), doc_itemBackgroundColor=u'Background color of the item/article image cell.', itemClear=C.NONE, doc_itemClear=u'Floating clear of item/article image cell.', itemMarginBottom=Em(0.5), doc_itemMarginBottom=u'Margin bottom of item/article image cell.', itemWidth=Perc(100), doc_itemWidth=u'Width of item/article image cell.', itemPadding=Padding(Em(0.35)), doc_itemPadding=u'Padding of the item/article image cell.', # Level showLevel=False, doc_showLevel=u'Boolean flag to show the level field of the article.', levelFormat='%s level', doc_levelFormat=u'Python string pattern as level indicator. Takes level string as parameter.', genericLevel=None, doc_genericLevel=u'Generic level flag, overruling the article level field.', levelColor=Color('#222'), doc_levelColor=u'Color of the level indicator.', levelSize=Em(0.8), doc_levelSize=u'Font size of the level indicator.', levelWeight=C.BOLD, doc_levelWeight=u'Font weight of the level indicator.', levelMarginTop=Em(0.2), doc_levelMarginTop=u'Margin top of the level indicator.', levelMarginBottom=Em(0.2), doc_levelMarginBottom=u'Margin bottom of the level indicator.', # Title showTitle=True, doc_showTitle=u'Boolean flag to show the title of the article.', titleColor=('#444'), doc_titleColor=u'Color of the article title.', titleSize=Em(1.1), doc_titleSize=u'Font size of the article title.', titleWeight=C.NORMAL, doc_titleWeight=u'Font weight of the article title.', titleLineHeight=Em(1.2), doc_titleLineHeight=u'Line height of the article title.', # Topic showTopic=True, doc_showTopic=u'Boolean flag to show the topic of the article.', topicColor=Color('#444'), doc_topicColor=u'Color of the article topic.', topicSize=Em(0.8), doc_topicSize=u'Font size of the article topic.', topicWeight=C.NORMAL, doc_topicWeight=u'Font weight of the article topic.', topicLineHeight=Em(1.2), doc_topicLineHeight=u'Line height of the article topic.', ) # Col stuff ??? NOT USED ''' colWidth=8, doc_colWidth=u'Default amount of columns for this component.', colMarginRight=Perc(1.8), doc_colMarginRight=u'Div.col margin right.', colMarginLeft=0, doc_colMarginLeft=u'Div.col margin left.', colFloat=C.LEFT, doc_colFloat=u'Div.col float', colMinHeight=1, doc_colMinHeight=u'Div.col minimal height.', colDisplay=C.BLOCK, doc_colDisplay=u'Div.col display type.', # Mobile stuff mobileDisplay=C.NONE, mobilePaddingTop=Em(2), mobilePaddingBottom=Em(0.5), mobilePaddingLeft=Em(0.5), mobilePaddingRight=Em(0.5), mobileMarginTop=Em(2), mobileMarginBottom=Em(0.5), mobileMarginLeft=Em(0.5), mobileMarginRight=Em(0.5), mobileFloat=C.NONE, mobileWidth=C.AUTO, ''' def buildFeatured(self, b, articles): s = self.style b.div(class_=self.getClassName(), width=s.width, backgroundcolor=s.backgroundColor, display=s.display, float=s.float, padding=s.padding, media=Media(max=self.C.M_MOBILE_MAX, width=s.widthMobile, display=s.displayMobile, float=s.floatMobile), ) for article in articles.items: if article.poster: self.buildFeaturedImage(b, article) b._div() def buildFeaturedImage(self, b, article): s = self.style b.div(class_=self.C.CLASS_FEATUREDITEM, display=s.itemDisplay, backgroundcolor=s.itemBackgroundColor, padding=s.itemPadding, clear=s.itemClear, marginbottom=s.itemMarginBottom, margintop=s.itemMarginTop, width=s.itemWidth, ) b.a(href='/%s-%s' % (self.C.PARAM_ARTICLE, article.id)) b.img(class_=(self.C.CLASS_AUTOWIDTH, 'featuredImage'), src=article.poster) if s.showLevel or s.genericLevel: b.h5(class_=self.C.CLASS_LEVEL, color=s.levelColor, fontsize=s.levelSize, fontweight=s.levelWeight, margintop=s.levelMarginTop, marginbottom=s.levelMarginBottom) # Format the level indicator b.text(s.levelFormat % (article.level or s.genericLevel)) b._h5() if s.showTitle: b.h4(class_=self.C.CLASS_TITLE, color=s.titleColor, fontsize=s.titleSize, fontweight=s.titleWeight, lineheight=s.titleLineHeight) b.text(article.title) b._h4() if s.showTopic and article.topic is not None: # Elements must be defined in global style b.h5(class_=self.C.CLASS_TOPIC, color=s.topicColor, fontsize=s.topicSize, fontweight=s.topicWeight, lineheight=s.topicLineHeight) if isinstance(article.topic, basestring): b.text(article.topic) else: self.buildElement(b, article.topic) b._h5() b._a() b._div(comment=self.C.CLASS_FEATUREDITEM)
class FeaturedByText(FeaturedBase): u"""The @FeaturedByText@ feature component, shows a featured article by summary. Respectively the binary flags @BluePrint@ *showPoster*, *showLevel*, *showTitle* and *showTopic* will enable the level of the article (as defined in the article source @$level@), the article title (@$title@) and topic (@$topic), of set to @True@.""" # Get Constants->Config as class variable, so inheriting classes can redefine values. C = FeaturedBase.C BLUEPRINT = BluePrint(FeaturedBase.BLUEPRINT, # Selection stuff # Index of first and amount of selected features for this component start=0, count=1, itemRandom=True, # Label stuff '#828487' label=None, labelSize=Em(2), labelColor='red', labelMarginBottom=Em(0.5), labelMarginTop=Em(0.3), labelLineHeight=Em(1.4), # Poster showPoster=True, posterWidth='40%', # Layout stuff colWidth=8, # Default amount of columns for this component # Level stuff, handle local fontsize and lineheight here, related to the item size showLevel=True, genericLevel='Generic', # Show generic level if level is omitted in data. levelColor='#6294D0', levelSize=LEVELSIZE, levelLineHeight=Em(1.4), levelWeight=C.BOLD, levelMarginTop=Em(0.5), # Category stuff in h5 showCategory=False, categoryColor=CATEGORYCOLOR, categorySize=CATEGORYSIZE, categoryLineHeight=Em(1.2), categoryWeight=C.BOLD, # Name stuff in h2 nameSize=Em(3.2), nameLineHeight=Em(1), nameWeight=None, # Default inheriting from the main weight. nameColor=NAMECOLOR, nameMarginBottom=Em(0.2), nameMarginTop=0, nameDisplay=C.BLOCK, # Author stuff in h6 authorSize=AUTHORSIZE, authorWeight=C.NORMAL, authorColor=AUTHORCOLOR, doc_authorColor=u'Author name color.', authorDisplay=C.BLOCK, authorLineHeight=Em(1.4), # Summary stuff summaryColor=SUMMARYCOLOR, summarySize=Em(1.2), summaryLineHeight=Em(1.4), summaryMarginTop=Em(0.4), summaryMarginBottom=Em(0.5), # Mobile stuff mobileDisplay=C.NONE, mobilePaddingTop=Em(2), mobilePaddingBottom=Em(0.5), mobilePaddingLeft=Em(0.5), mobilePaddingRight=Em(0.5), mobileMarginTop=Em(2), mobileMarginBottom=Em(0.5), mobileMarginLeft=Em(0.5), mobileMarginRight=Em(0.5), mobileFloat=C.NONE, mobileWidth=C.AUTO, ) def buildFeatured(self, b, articles): s = self.style b.div(class_=self.getClassName(), width=s.width, backgroundcolor=s.backgroundColor, display=s.display, float=s.float, padding=s.padding, media=Media(max=self.C.M_MOBILE_MAX, width=s.widthMobile, display=s.displayMobile, float=s.floatMobile), ) for article in articles.items: self._buildFeaturedText(b, article) b._div() def _buildFeaturedText(self, b, data): u"""Build the featured item. If @self.style.itemRandom@ is **True**, then select a random item from the list. If there is no **data.item** available, then ignore this method.""" return # TODO: fix this if not data.items: return s = self.style if s.itemRandom: item = choice(data.items) else: item = data.items[0] if s.label: b.h2(fontsize=s.labelSize, color=s.labelColor, margintop=s.labelMarginTop, marginbottom=s.labelMarginBottom, lineheight=s.labelLineHeight, media=( Media(min=self.C.M_TABLET_MIN, max=self.C.M_TABLET_MAX, fontsize=s.tabletLabelSize, color='red'), Media(max=self.C.M_MOBILE_MAX, color='blue') )) b.text(s.label) b._h2() b.a(href='/%s-%s' % (self.C.PARAM_ARTICLE, item.id), class_=self.C.CLASS_NAME) b.h2(fontsize=s.nameSize, fontweight=s.nameWeight, lineheight=s.nameLineHeight, color=s.nameColor, marginbottom=s.nameMarginBottom, display=s.nameDisplay, margintop=s.nameMarginTop) b.text(item.name) b._h2() b._a() if s.showPoster: b.a(href='/%s-%s' % (self.C.PARAM_ARTICLE, item.id), class_=self.C.CLASS_NAME) b.img(width=s.posterWidth, src=item.poster, float=self.C.LEFT, padding=0, margin=Margin(Em(0.5), Em(0.5), 0, 0), media=Media(max=self.C.M_MOBILE_MAX, display=self.C.NONE) ) b._a() if s.showLevel: b.h5(class_=self.C.CLASS_LEVEL, color=s.levelColor, fontsize=s.levelSize, fontweight=s.levelWeight, margintop=s.levelMarginTop, lineheight=s.levelLineHeight) b.text(item.level or s.genericLevel) b.text(' level') b._h5() if item.author: # Test on text b.a(href='/%s-%s' % (self.C.PARAM_AUTHOR, item.author), class_=self.C.CLASS_AUTHOR) b.h5(fontsize=s.authorSize, fontweight=s.authorWeight, color=s.authorColor, lineheight=s.authorLineHeight, display=s.authorDisplay) b.text('By %s' % item.author) b._h5() b._a() if s.showCategory and item.category: # Text on text b.a(href='/%s-%s' % (self.C.PARAM_CATEGORY, item.category), class_=self.C.CLASS_CATEGORY) b.h5(fontsize=s.categorySize, fontweight=s.categoryWeight, lineheight=s.categoryLineHeight, color=s.categoryColor, margintop=Em(1), display=self.C.BLOCK) b.text(item.category) b._h5() b._a() if item.summary is not None: # Test on element. Summary elements tag must be defined by generic style. b.div(class_='featuredSummary', clear=self.C.BOTH, float=self.C.LEFT, width=Perc(100), color=s.summaryColor, fontsize=s.summarySize, lineheight=s.summaryLineHeight, margintop=s.summaryMarginTop, marginbottom=s.summaryMarginBottom) if isinstance(item.summary, basestring): b.text(item.summary) else: self.buildElement(b, item.summary) b._div()
class FeaturedByDiapText(FeaturedByText): u"""As FeaturedByText, but default on a dark background.""" # Get Constants->Config as class variable, so inheriting classes can redefine values. C = FeaturedByText.C BLUEPRINT = BluePrint(FeaturedBase.BLUEPRINT, # Selection stuff # Index of first and amount of selected features for this component start=0, count=10, itemRandom=True, doc_itemRandom=u'Choose random from the selected items.', # Label stuff label=None, doc_label=u'Label string.', labelSize=Em(2.2), doc_labelSize=u'Label size.', labelColor=Color('#828487'), doc_labelColor=u'Label color.', labelMarginBottom=Em(0.5), labelMarginTop=Em(0.3), # Poster showPoster=True, posterWidth='40%', # Layout stuff colWidth=8, # Default amount of columns for this component # Level stuff, handle local fontsize and lineheight here, related to the item size showLevel=True, genericLevel='Generic', # Show generic level if level is omitted in data. levelColor=Color('#6294D0'), levelSize=LEVELSIZE, levelWeight=C.BOLD, levelMarginTop=Em(0.5), # Category stuff in h5 showCategory=False, categoryColor=CATEGORYCOLOR, categorySize=Em(1.8), categoryLineHeight=Em(1.2), categoryWeight=C.BOLD, # Name stuff in h2 nameSize=Em(1.8), nameLineHeight=Em(1.1), nameWeight=None, # Default inheriting from the main weight. nameColor=Color('#E1E1E1'), nameMarginBottom=Em(0.2), nameMarginTop=0, nameDisplay=C.BLOCK, # Author stuff in h6 authorSize=AUTHORSIZE, authorWeight=C.NORMAL, authorColor=Color('#B2B4B7'), # Inheriting from the main color as default authorDisplay=C.BLOCK, authorLineHeight=Em(1.4), # Summary stuff summaryColor=C.WHITE, summaryMarginTop=Em(0.4), summaryMarginBottom=Em(0.5), # Tablet stuff tabletLabelSize=Em(1.5), # Mobile stuff mobileDisplay=C.NONE, mobilePaddingTop=Em(2), mobilePaddingBottom=Em(0.5), mobilePaddingLeft=Em(0.5), mobilePaddingRight=Em(0.5), mobileMarginTop=Em(2), mobileMarginBottom=Em(0.5), mobileMarginLeft=Em(0.5), mobileMarginRight=Em(0.5), mobileFloat=C.NONE, )
class SocialMedia(Column): # Get Constants->Config as class variable, so inheriting classes can redefine values. C = Column.C BLUEPRINT = BluePrint( # layout colWidth=4, # Twitter # https://dev.twitter.com/docs/tweet-button twitterAccount=None, twitterLabel='Tweet', # FaceBook # https://developers.facebook.com/docs/plugins/share-button/ facebookAccount=None, # Mobile mobileDisplay=C.NONE, ) def buildColumn(self, b): u"""Build the social media component.""" s = self.style if not self.C.useOnline(): b.text('No Social Media links when off-line.') elif s.twitterAccount or s.facebookAccount: b.div(class_=self.C.CLASS_SOCIALMEDIA, display=self.C.BLOCK, float=s.float or self.C.LEFT, width=s.width or Perc(100), media=Media(max=self.C.M_MOBILE_MAX, display=s.mobileDisplay)) # getUrl does not seem to work with twitter. Script only tests http or https. if s.twitterAccount: b.div(id="twitter", float=self.C.LEFT) b.a(href="https://twitter.com/share", data_href=b.getUrl(), class_="twitter-share-button", data_lang="en", data_via="doingbydesign", data_count="none", data_related="anywhere") b.text(s.twitterLabel) b._a() b.script() b.text( """!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?'http':'https';if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+'://platform.twitter.com/widgets.js';fjs.parentNode.insertBefore(js,fjs);}}(document, 'script', 'twitter-wjs');""" ) b._script() b._div() if s.facebookAccount: b.div(id="fb-root", float=self.C.LEFT) b._div() b.script() b.text("""(function(d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = "//connect.facebook.net/en_US/all.js#xfbml=1"; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk')); """) b._script() b.div(class_="fb-share-button", float=self.C.LEFT, data_href=b.getUrl(), data_type="button_count") b._div() b._div()
class Footer(Container): BLUEPRINT = BluePrint(MobileNavigation.BLUEPRINT, # Layout alternatives )
class PosterHead(Column): u"""The @PosterHead@ component, shows a featured article by its poster image on full width of the component, and adding the title and the text a overlay with shadow. If there is no poster image defined in the article meta data, then the first image in the article is used here. The poster image is a link to the article page. Respectively the binary flags @BluePrint@ *showLevel*, *showTitle* and *showTopic* will enable the level of the article (as defined in the article source @$level@), the article title (@$title@) and topic (@$topic), of set to @True@.""" # Get Constants->Config as class variable, so inheriting classes can redefine values. C = Column.C BLUEPRINT = BluePrint( Column.BLUEPRINT, # Container component layout stuff width=Perc(100), doc_width=u'Overall width of the component.', # Showings showSubtitle=True, doc_showSubtitle= u'Show the $subtitle if it exists in the article. Otherwise show $topic.', ) def buildColumn(self, b): if b.isType(('css', 'sass')): self.buildPosterStyle(b) else: self.buildPoster(b) def buildPosterStyle(self, b): s = self.style b.div( class_=self.getClassName(), width=s.width, backgroundcolor=s.backgroundColor, display=s.display, float=s.float, padding=s.padding, media=Media(max=self.C.M_MOBILE_MAX, width=s.widthMobile, display=s.displayMobile, float=s.floatMobile), ) b.div( class_=self.C.CLASS_FEATUREDITEM, display=s.itemDisplay, backgroundcolor=s.itemBackgroundColor, padding=Em(1.6), #style='background-repeat:no-repeat;background-size:cover;', clear=s.itemClear, marginbottom=s.itemMarginBottom, margintop=s.itemMarginTop, media=Media(max=self.C.M_MOBILE_MAX, #style='background-size:auto' ), ) b.h1(color=Color('white'), fontfamily='Georgia', fontsize=Em(4), fontweight=self.C.BOLD, textshadow=Shadow()) b._h1() if s.showSubtitle: b.h2(color=Color('yellow'), fontsize=Em(2), fontweight=self.C.BOLD, textshadow=Shadow()) b._h2() b._div(comment=self.C.CLASS_FEATUREDITEM) b._div() def buildPoster(self, b): s = self.style article = self.adapter.getArticle(id=b.getCurrentArticleId()) if article.poster: b.div(class_=self.getClassName()) b.div( class_=self.C.CLASS_FEATUREDITEM, style= 'background:url(%s);background-repeat:no-repeat;background-size:cover;' % article.poster) b.h1() b.text(article.title) b._h1() # If style subtitle flag is set, then show the $subtitle or $topic if one of them exists in the article. if s.showSubtitle and (article.subtitle or article.topic): b.h2() b.text(article.subtitle or article.topic) b._h2() b._div(comment=self.C.CLASS_FEATUREDITEM) b._div()
class ExampleColumn(Column): # Get Constants->Config as class variable, so inheriting classes can redefine values. C = Column.C BLUEPRINT = BluePrint( # Page stuff pageBackgroundColor=Color('#EEE'), doc_pageBackgroundColor=u'Page background color.', # Responsive stuff minWidth=300, doc_minWidth='Column minimal width.', minWidthMobile=0, doc_minWidthMobile=u'Column minimal width for mobile.', maxWidth=700, doc_maxWidth='Column maximal width.', maxWidthMobile=C.AUTO, doc_maxWidthMobile='Column maximal width for mobile', # Column stuff fontFamlily=BODYFAMILY, doc_fontFamily=u'Column body font family.', fontSize=Em(1), doc_fontSize=u'Column body font size.', fontSizeMobile=Em(1.2), doc_fontSizeMobile=u'Column body font size for mobile.', lineHeight=Em(1.4), doc_lineHeight=u'Column body leading.', margin=Margin(0, C.AUTO, 0, C.AUTO), doc_margin=u'Column margin.', marginMobile=0, doc_marginMobile=u'Column margin mobile', color=Color('#222'), doc_color='Column text color.', backgroundColor=Color('#FFF'), doc_backgroundColor='Column background color.', width=Perc(50), doc_width=u'Column width.', widthMobile=C.AUTO, doc_widthMobile= u'Column width for mobile, shoud always be “auto” with the row construction.', padding=Em(2), doc_padding=u'Column margin in the page.', paddingMobile=Em(1.4), doc_paddingMobile=u'Column margin in the page for mobile.', # h1 h1FontFamily=HEADFAMILY, doc_h1FontFamily=u'Column h1 font family.', h1FontSize=Em(1.6), doc_h1FontSize=u'Column h1 font size', h1LineHeight=Em(1.1), doc_h1LineHeight=u'Column h1 leading', h1Color=Color('#666'), doc_h1Color=u'Column h1 color.', h1MarginBottom=Em(0.5), doc_h1MarginBottom=u'Column h1 margin bottom', # h2 h2FontFamily=HEADFAMILY, doc_h2FontFamily=u'Column h2 font family.', h2FontSize=Em(1.4), doc_h2FontSize=u'Column h2 font size', h2LineHeight=Em(1.2), doc_h2LineHeight=u'Column h2 leading', h2Color=Color('#888'), doc_h2Color=u'Column h2 color.', h2Style=C.ITALIC, doc_h2Style=u'Column h2 style', h2MarginTop=Em(1), doc_h2MarginTop=u'Column h2 margin top', h2MarginBottom=Em(0.5), doc_h2MarginBottom=u'Column h2 margin bottom', # p textIndent=Em(1), doc_textIndent=u'Indent of first line of paragraph.', textFirstIndent=0, doc_textFirstIndent=u'Indent of first paragraph after another element.', # p.end textLastIndent=0, doc_textLastIndent=u'Indent of last paragraph before another element', textEndMarginTop=Em(0.5), doc_textEndMarginTop= u'Margin top of last paragraph before another element.', textEndMarginBottom=Em(0.5), doc_textEndMarginBottom= u'Margin bottom of last paragraph before another element.', # img imgMarginTop=Em(0.5), doc_imgMarginTop=u'Image margin top', imgMarginBottom=Em(0.5), doc_imgMarginBottom=u'Image margin bottom', # blockquote.pullQuote pullQuoteFontFamily=BODYFAMILY, doc_pullQuoteFontFamily=u'Pull quote font family.', pullQuotePadding=Margin(Em(0.5), Em(1)), doc_pullQuotePadding=u'Pull quote padding.', pullQuoteSize=Em(1.2), doc_pullQuoteSize=u'Pull quote font size.', pullQuoteLineHeight=Em(1.3), doc_pullQuoteLineHeight=u'Pull quote line height.', pullQuoteMarginTop=Em(0.5), doc_pullQuoteMarginTop=u'Pull quote margin top.', pullQuoteMarginBottom=Em(0.5), doc_pullQuoteMarginBottom=u'Pull quote margin bottom', pullQuoteStyle=C.ITALIC, doc_pullQuoteStyle=u'Pull quote style', pullQuoteBackgroundColor=Color('#EEE'), doc_pullQuoteBackgroundColor=u'Pull quote background color.', pullQuoteColor=Color('#333'), doc_pullQuoteColor=u'Pull quote color.', pullQuoteBorder=None, doc_pullQuoteBorderu= 'Pull quote border.', #Border('solid', 2, Color('#E1E2E2')), ) def buildBlock(self, b): u"""Build the column. Note that although the "div" suggest that it is just HTML building there, the method get called both with <b>b</b> as CssBuilder and as HtmlBuilder. Each builder will filter out the appropriate attributes and translates it into its own syntax. The HTML tags generated by the article are set in CSS by the empty statements.""" s = self.style # Get compile style from cascading blue prints of inheriting classes. b.div( class_=s.classColumn, color=s.color, margin=s.margin, width=s.columnWidth, maxwidth=s.maxWidth, minwidth=s.minWidth, backgroundcolor=s.backgroundColor, fontfamily=s.fontFamily, fontsize=s.fontSize, lineheight=s.lineHeight, padding=s.padding, # Remove margins on mobile, showing the column on full screen width. media=Media(max=self.C.M_MOBILE_MAX, margin=s.marginMobile, float=self.C.NONE, fontsize=s.fontSizeMobile, lineheight=s.lineHeight, padding=s.paddingMobile, width=s.widthMobile, maxwidth=s.maxWidthMobile, minwidth=s.minWidthMobile), ) # Since the self.adapter.getArticle answers an article that already # includes XHTML tags, we cannot do the styling there. In order to # define the unique CSS styles, a blank document content is created # for the CssBuilder to evaluate, so we have all the definitions inside # div.column, in case they are used in the article. # Note that this is in conflict with the purpose of components, who # should not know about the type of builder that they are talking to. # In future this will be solved by supplying more default style parameters # to the component, that include the styles of tags that are not used # in the main building. # See also the code for components/article, which includes a _model.txt # document for this purpose. if b.isType(self.C.TYPE_CSS): self.buildCssColumnTemplate(b) else: data = self.adapter.getArticle(index=4, selector=self.C.SELECTOR_FEATURED) # Build the headline without style attribute, as these are already defined # in the self.buildCssColumnTemplate call. b.h1(fontfamily=s.h1FontFamily, fontsize=s.h1FontSize, lineheight=s.h1LineHeight) b.text(data.headline) b._h1() if data.poster: # Build the image that came with the featured article, if it exists. # Make it class autowidth to solve the width="100%" incompatibility # between browsers. b.img(src=data.poster, class_=s.imgClass, maxwidth=s.imgMaxWidth, minwidth=s.imgMinWidth, margintop=s.imgMarginTop, marginbottom=s.imgMarginBottom) # Output the rest of the featured article. b.text(data.item) # Add some more volume to the blurb article. data = self.adapter.getArticles(count=4) for article in data.items: b.h2(fontfamily=s.h2FontFamily, fontsize=s.h2FontSize, lineheight=s.h2LineHeight) b.text(article.headline) b._h2() b.text(article.text) # Add reference about the content of this page b.hr() b.div(class_='colophon', fontsize=Em(0.8), color=s.color, fontfamily=BODYFAMILY, lineheight=Em(1.4)) b.text( 'The text and image selection on this page is blurb, created by Filibuster.' ) b._div() # Add reference to sponsored Webtype webfonts. b.a(href='//webtype.com', color=s.color, fontfamily=BODYFAMILY, fontsize=Em(0.8), lineheight=Em(1.4), target='external') b.text( 'The typefaces in this example %s and %s are sponsored by <Webtype>' % (BODYFAMILY, HEADFAMILY)) b._a() b._div() def buildCssColumnTemplate(self, b): u"""Build the single CSS for all expected tags in an article that is answered by <b>self.adapter</b>. We cannot check on that here, since the content may vary and even is hidden by e.g. calls to a PHP adapter.""" s = self.style b.h1(fontfamily=s.h1FontFamily, color=s.h1Color, fontsize=s.h1FontSize, lineheight=s.h1LineHeight, marginbottom=s.h1MarginBottom) # Headling made by BlurbAdapter b._h1() b.h2(fontfamily=s.h2FontFamily, fontstyle=s.h2Style, color=s.h2Color, fontsize=s.h2FontSize, lineheight=s.h2LineHeight, margintop=s.h2MarginTop, marginbottom=s.h2MarginBottom) # Headling made by BlurbAdapter b._h2() b.img(margintop=s.imageMarginTop, marginbottom=s.imageMarginBottom) b.p(textindent=s.textIndent, fontfamily=BODYFAMILY) # Main paragraphs have an indent. b._p() b.p(class_='start', textindent=s.textFirstIndent) # The start paragraph (the element before was not a <p>) has no indent. b._p() b.p(class_='end', marginbottom=s.textLastMarginBottom, margintop=s.textLastMarginTop, textindent=s.textLastIndent) # Mark the end paragraph (the element after is not a <p>) in case something # special needs to be done, e.g. change the marginbottom. # @@@ TODO: Mark as p.end preceding <blockquote> too. b._p() # Italic blockquotes with an indent and backgroundcolor. b.blockquote(class_=self.C.CLASS_PULLQUOTE, padding=s.pullQuotePadding, fontsize=s.pullQuoteSize, fontfamily=s.pullQuoteFontFamily, fontstyle=s.pullQuoteStyle, lineheight=s.pullQuoteLineHeight, margintop=s.pullQuoteMarginTop, marginbottom=s.pullQuoteMarginBottom, border=s.pullQuoteBorder, backgroundcolor=s.pullQuoteBackgroundColor, color=s.pullQuoteColor) b._blockquote()
class SvgExample(Component): C = Component.C BLUEPRINT = BluePrint( height=Px(250), doc_height=u'Svg canvas height', width=Perc(100), doc_width=u'Svg canvas width', ) def build_html(self, b): u"""Do all as build for CSS.""" # if b.isType('scss'): # If generating CSS, there are no selected banners. Add some fake data here for 2 columns. self.demoSvgDrawing1(b) self.demoSvgDrawing2(b) def draw(self, b, drawingId): u"""Simple direct draw if used inside the liquid of a text columns, e.g. through XML transformer part of a builder.""" hook = 'demoSvgDrawing%s' % drawingId if hasattr(self, hook): b.div(class_='svgDemo') getattr(self, hook)(b) b._div() def demoSvgDrawing1(self, b): # Draw a responsive image in SVG, only in #b.div(class_='svgDemo', display=C.BLOCK, margintop=Em(0.5), marginbottom=Em(0.5), # media=Media(max=C.M_MOBILE_MAX, display=C.NONE)) s = self.style b.svg(width=s.width, height=s.height) b.rect(width=Perc(100), height=50, fill=LinearGradient('left', '#000', 0, '#FFF', 100)) b.rect(y=50, width=Perc(100), height=200, fill='green') # Perspective line b.line(x1=30, y1=Perc(100), x2=Perc(50), y2=50, stroke='yellow', strokewidth=3) b.line(x1=Perc(70), y1=Perc(100), x2=Perc(50), y2=50, stroke=Color('yellow'), strokewidth=3, display=self.C.NONE) b.ellipse(x=80, y=150, rx=40, ry=10, fill='black', fillopacity=0.2) b.filter('frozenLiquid') b.circle(x=80, y=80, r=40, strokewidth=3, stroke='black', fill='red', fillopacity=0.5) b.circle(x=80, y=80, r=20, fill=Color('green'), fillopacity=0.5) b._filter() b.circle(x=65, y=65, r=10, fill=Color('white'), fillopacity=0.2) b.ellipse(x=Perc(50), y=Perc(50), rx=40, ry=10, fill='black', fillopacity=0.5) b.circle(x=Perc(50), y=50, r=40, strokewidth=3, stroke='black', fill=Color('red'), fillopacity=0.5) b.circle(x=Perc(50), y=50, r=20, fill=Color('green'), fillopacity=0.5) b.circle(x=Perc(48), y=35, r=10, fill=Color('white'), fillopacity=0.6) #b.text('Xierpa3', fill='#FFF', fontsize=45, fontfamily='Verdana', x=100, y=100) b._svg() def demoSvgDrawing2(self, b): # Draw a responsive image in SVG #b.div(class_='svgDemo', display=C.NONE, margintop=Em(0.5), marginbottom=Em(0.5), # media=Media(max=C.M_MOBILE_MAX, display=C.BLOCK)) s = self.style b.svg(width=s.width, height=s.height) b.rect(width=Perc(100), height=100, fill=Color('cyan')) b.rect(y=100, width=Perc(100), height=150, fill=Color('green')) # Polygons don't work in %, so they cannot be positioned responsive to the container width b.rect(x=Perc(5), y=20, width=Perc(8), height=200, fill=Color('yellow'), fillopacity=0.5) b.filter('blur', blur=4) b.rect(x=Perc(20), y=20, width=Perc(5), height=200, fill=Color('yellow')) b._filter() # Neon b.filter('neon') b.rect(x=Perc(35), y=20, rx=12, ry=12, width=32, height=200, fill=self.C.NONE, stroke='red', strokewidth=6) b._filter() b.filter('neon') b.rect(x=Perc(50), y=20, rx=16, ry=16, width=32, height=200, fill=self.C.NONE, fillopacity=0.5, stroke=Color('blue'), strokewidth=20) b._filter() b.filter('frozenLiquid' ) # @@@ Should not change the overall color of the image. b.rect(x='68%', y=20, rx=16, ry=16, width=32, height=200, fill=Color('#D0D0D0'), fillopacity=0.5, stroke=Color('blue'), strokewidth=20) b._filter() b._svg()
class Article(ArticleColumn): u"""The Article component is the main medium to display article content. >>> from xierpa3.builders.htmlbuilder import HtmlBuilder >>> from xierpa3.adapters.textilefileadapter import TextileFileAdapter >>> from xierpa3.sites import doingbydesign >>> # Root path where to find the article Simples wiki file for this example page. >>> articleRoot = TX.module2Path(doingbydesign) + '/files/articles/' >>> adapter = TextileFileAdapter(articleRoot) >>> len(adapter.getArticles()) >>> adapter.getArticles().chapters[0].title >>> adapter.getArticles() >>> a = Article(adapter=adapter) >>> a.style.colWidth, a.style.gutter (8, 8) >>> b = HtmlBuilder() >>> a.build(b) >>> b.getResult() """ # Get Constants->Config as class variable, so inheriting classes can redefine values. C = ArticleColumn.C # Default parameters for the article layout, to make sure that the default # behavior makes reasonable good typography. Each of these values can be redefined # by changing the BluePrint parameters in the Article() constructor call. # These values can be change either through inheriting from the Article class, # or by altering the BluePrint values in the Article(...) constructor call. CHAPTERCOLOR = Color('#202020') SUMMARYCOLOR = CHAPTERCOLOR CHAPTERTITLECOLOR0 = Color('#1F1F1F') CHAPTERTITLECOLOR1 = CHAPTERTITLECOLOR0 H1COLOR = Color('#333') H2COLOR = Color('#828487') BACKGROUNDCOLOR = Color('#fff') AUTHORCOLOR = H2COLOR CATEGORYCOLOR = H2COLOR LABELCOLOR = H2COLOR LEADCOLOR = H2COLOR NAMECOLOR = Color('#66696C') TITLECOLOR = NAMECOLOR # Define the basic blue print style for this type of component. BLUEPRINT = BluePrint( # Layout stuff width=Perc(70), doc_colWidth=u'Relative width for the article text column.', gutter=8, doc_gutter=u'Gutter width between columns.', backgroundColor=Color(BACKGROUNDCOLOR), doc_backgroundColor= u'Background color of the component. Default is white.', paddingleft=Em(2), doc_paddingleft=u'General article padding', # Chapter behavior splitChapters=False, doc_splitChapters= u'Boolean flag if the chapters should be listening to url chapter index.', # Poster showPoster=False, doc_showPoster= u'Boolean flag if the poster image should be shown at start of the article.', # Blog response blogResponse=True, doc_blogResponse= u'Boolean flag if a blog response form should be added if @article.blogresponse@ is also @True@.', # Title stuff on the first chapter page of the article titleSize=Em(3.2), doc_titleSize= u'Title font size on the first chapter page of an article.', titleLineHeight=Em(1.2), doc_titleLineHeight= u'Title leading on the first chapter page of an article.', titleColor=TITLECOLOR, doc_titleColor=u'Title color on the first chapter page of an article.', # Name stuff on the second+ chapter page of the article nameSize=Em(2), doc_nameSize=u'Name font size on the second+ page of an article.', nameLineHeight=Em(1.2), doc_nameLineHeight=u'Name leading on the second+ page of an article.', nameColor=NAMECOLOR, doc_nameColor=u'Name color on the second+ page of an article.', # Author stuff authorSize=Em(1), doc_autorSize=u'Author font size near article title.', authorColor=AUTHORCOLOR, doc_authorColor=u'Author color near article title.', # Category stuff categorySize=Em(0.8), doc_categorySize=u'Article category font size.', categoryLineHeight=Em(1.2), doc_categoryLineHeight=u'Article category leading.', categoryColor=NAMECOLOR, doc_categoryColor=u'Article category color.', categoryWeight=None, doc_categoryWeight= u'Article category weight.', # Default to inherit from the default weight. # Chapter stuff chapterColor=CHAPTERCOLOR, doc_chapterColor=u'Chapter color.', chapterSize=Em(1.2), doc_chapterSize=u'Chapter font size.', chapterSizeMobile=Em(2), doc_chapterSizeMobile=u'Chapter font size for mobile.', chapterLineHeight=Em(1.4), doc_chapterLineHeight=u'Chapter leading.', chapterLineHeightMobile=Em(1.4), doc_chapterLineHeightMobile=u'Chapter leading for mobile.', # Chapter lead stuff leadSize=Em(1.4), doc_leadSize=u'Chapter lead font size.', leadLineHeight=Em(1.4), doc_leadLineHeight=u'Chapter lead leading.', leadMarginTop=Em(0.5), doc_leadMarginTop=u'Chapter lead margin top.', leadMarginBottom=Em(0.5), doc_leadMarginBottom=u'Chapter lead margin bottom.', leadColor=LEADCOLOR, doc_leadColor=u'Chapter lead color.', leadWeidth=None, doc_leadWeight=u'Chapter lead font weight.', leadStyle=None, doc_leadStyle=u'Chapter lead font style.', # Chapter first page chapterTitleSize0=Em(1.5), doc_chapterTitleSize0=u'Chapter title font size on first page.', chapterTitleColor0=CHAPTERTITLECOLOR0, doc_chapterTitleColor0=u'Chapter title color on first page.', chapterTitleMarginTop0=Em(1), doc_chapterTitleMarginTop0=u'Chapter title margin top on first page.', chapterTitleMarginBottom0=Em(0.5), doc_chapterTitleMarginBottom0= u'Chapter title margin bottom on first page.', # Chapter other pages chapterTitleSize1=Em(2.5), doc_chapterTitleSize1=u'Chapter title font size on second+ page.', chapterTitleColor1=CHAPTERTITLECOLOR1, doc_chapterTitleColor1=u'Chapter title color on second+ page.', chapterTitleMarginTop1=Em(1), doc_chapterTitleMarginTop1=u'Chapter title margin top on second+ page.', chapterTitleMarginBottom1=Em(0.5), doc_chapterTitleMarginBottom1= u'Chapter title margin bottom on second+ page.', # H1 h1Size=Em(2.5), doc_h1Size=u'Article h1 font size.', h1FontSize=None, doc_h1FontStyle=u'Article h1 font style.', h1FontWeight=None, doc_h1FontWeight=u'Article h1 font weight.', h1LineHeight=Em(1.4), doc_h1LineHeight=u'Article h1 leading.', h1PaddingTop=Em(1), doc_h1PaddingTop=u'Article h1 padding top.', h1PaddingBottom=0, doc_h1PaddingBottom=u'Article h1 padding bottom.', h1Color=H1COLOR, doc_h1Color=u'Article h1 color in article.', # H2 h2Size=Em(2), doc_h2Size=u'Article h2 font size.', h2LineHeight=Em(1.4), doc_h2LineHeight=u'Article h2 leading.', h2PaddingTop=Em(1), doc_h2PaddingTop=u'Article h2 padding top.', h2PaddingBottom=0, doc_h2PaddingBottom=u'Article h2 padding bottom.', h2Color=H2COLOR, doc_h2Color=u'Article h2 color in article.', # H3 h3Size=Em(2), doc_h3Size=u'Article h3 font size.', h3LineHeight=Em(1.4), doc_h3LineHeight=u'Article h3 leading.', h3PaddingTop=Em(1), doc_h3PaddingTop=u'Article h3 padding bottom.', h3PaddingBottom=0, doc_h3PaddingBottom=u'Article h3 color.', # Chapter p stuff articleSize=Em(1.1), doc_articleSize=u'Article p font size.', articleLineHeight=Em(1.6), doc_articleLineHeight=u'Article p leading.', articlePPIndent=Em(1), doc_articleInden=u'Article p + p indent.', articleIndent=0, doc_Indent=u'Article regular p indent.', # Bullet list bulletType='disc', doc_bulletType=u'Article bullet type', bulletLineHeight=Em(1.4), doc_bulletLineHeight=u'Article bullet line height', bulletPosition=C.OUTSIDE, doc_bulletPosition= u'Article bullet position. One of (inside, outside).', bulletPaddingLeft=Em(1), doc_bulletPaddingLeft=u'Article bullet padding left.', bulletMarginBottom=0, doc_bulletMarginBottom=u'Article bullet margin bottom.', bulletMarginTop=Em(0.5), doc_bulletMarginTop=u'Article bullet margin top.', bulletItemMarginBottom=Em(0.5), doc_bulletItemMarginBottom=u'Article bullet item margin bottom.', # Ordered list numberedListType='decimal', doc_numberedListType=u'Article numbered list type', numberedListLineHeight=Em(1.4), doc_numberedListLineHeight=u'Article numbered list line height', numberedListPosition=C.OUTSIDE, doc_numberedListPosition= u'Article numbered list position. One of (inside, outside).', numberedListPaddingLeft=Em(1), doc_numberedListPaddingLeft=u'Article numbered list padding left.', numberedListMarginBottom=0, doc_numberedListMarginBottom=u'Article numbered list margin bottom.', numberedListMarginTop=Em(0.5), doc_numberedListMarginTop=u'Article numbered list margin top.', numberedListItemMarginBottom=Em(0.5), doc_numberedListItemMarginBottom= u'Article numbered list item margin bottom.', # Image block imgMarginTop=Em(1), doc_imgMarginTop=u'Image margin top.', imgMarginBottom=Em(0.8), doc_imgMarginBottom=u'Image margin bottom.', imgPaddingTop=None, doc_imgPaddingTop=u'Image padding top.', imgPaddingBottom=None, doc_imgPaddingBottom=u'Image padding bottom.', imgPaddingLeft=None, doc_imgPaddingLeft=u'Image padding left.', imgPaddingRight=None, doc_imgPaddingRight=u'Image padding right.', imgBackgroundColor=None, doc_imgBackgroundColor=u'Image background color.', # Image caption captionFontFamily=None, captionFontStyle=C.ITALIC, captionFontSize=Em(0.9), captionMarginTop=Em(0.5), # Plain Textile image with class autoWidth, not indenting. # Full width, growing until maximal size of image. Then centered on column width. imgAutoWidthMarginLeft=C.AUTO, doc_imgAutoWidthMarginLeft=u'img.autoWidth margin left.', imgAutoWidthMarginRight=C.AUTO, doc_imgAutoWidthMarginRight=u'img.autoWidth margin right.', imgAutoWidthTextIndent=0, doc_imgAutoWidthTextIndent=u'img.autoWidth text indent.', imgAutoWidthDisplay=C.BLOCK, doc_imgAutoWidthDisplay=u'img.autoWidth display.', # Code preFontFamily='Courier', doc_preFontFamily=u'Font family of pre code blocks.', preFontSize=Em(0.8), doc_preFontSize=u'Font size of pre code blocks.', prePaddingLeft=Em(1), doc_prePaddingLeft=u'Padding left of pre code blocks.', prePaddingTop=Em(0.5), doc_prePaddingTop=u'Padding top of pre code blocks.', prePaddingBottom=Em(0.5), doc_prePaddingBottom=u'Padding bottom of pre code blocks.', preMarginTop=Em(0.5), doc_preMarginTop=u'Margin left of pre code blocks.', preMarginBottom=Em(0.5), doc_preMarginBottom=u'Margin bottom of pre code blocks.', preColor=Color(0), doc_preColor=u'Color of pre code blocks.', preBackgroundColor=Color('#DDD'), doc_preBackgroundColor=u'Background color of pre code blocks.', ) def buildBlock(self, b): self.buildColumn(b) def buildColumn(self, b): u"""Build the article column. The article data is derived from the adapter by matching with the hard coded url pattern (@$url@ field in the article source) or with the @b.getCurrentArticleId()@, which is @/article-[articleId]@ in the url of the page.""" s = self.style article = self.adapter.getArticle(id=b.getCurrentArticleId(), url=b.e.path) b.div( class_=self.getClassName(), width=s.width, float=self.C.LEFT, paddingRight=s. gutter, #marginright=s.gutter, # Gutter between main column and article side bar. paddingleft=Em(2), paddingtop=Em(2), paddingright=Em(2), backgroundcolor=Color('#fff'), marginright=0, media=Media(max=self.C.M_MOBILE_MAX, width=self.C.AUTO, float=self.C.NONE, paddingleft=Em(1), paddingright=Em(1), paddingtop=Em(1), marginright=0), ) if article is None: # If not article defined, then this must be a call for building the CSS. # Make the switch to run as style builder. self.buildArticleStyle(b) else: self.buildArticleData(b, article) # Build blog response form, if required. if s.blogResponse and article is not None and article.blogresponse == 'True': b.div(class_=self.C.CLASS_BLOGRESPONSE, width=Perc(100), backgroundcolor=Color('#888')) # TODO: Add blog response form here. b.text('[Develop Blog Response here] ' * 20) b._div(comment=self.C.CLASS_BLOGRESPONSE) b._div() def buildArticleData(self, b, article): u"""Build the article. If there is a "/chapter-2" url parameter defined and it is in the range of available chapters, then show that chapter. Other values are cropped to min and max index of the chapter list.""" s = self.style #b.element(tag='img', class_=self.C.CLASS_AUTOWIDTH, margintop=Em(1), marginbottom=Em(1)) if b.isType(('css', 'sass')): if article is None: # No specific article id specified, use _mode.txt file # as model for calculating the SASS/CSS article = self.adapter.getModelData() self.buildArticleTop( b, article, 0) # Separate CSS for first chapter and the rest. self.buildArticleTop(b, article, 1) self.buildArticleStyle( b) # Build the CSS style template of an article here elif article is None: b.text('Cannot find article') elif b.e.form[self.C.PARAM_EDIT]: # and b.e.isLoggedIn(): if article.source is not None: b.div(class_=self.C.CLASS_CHAPTER, width=self.C.NONE, contenteditable=self.C.TRUE, float=self.C.NONE) # Form and button bar is already generated by the page. b.text(article.source.replace('\n', '<br/>\n')) b._div() else: b.error('Cannot find source of article "%s"' % article.id) elif article.chapters: # Collect the chapter indices to show. If splitting chapter, we need a list of # the one chapter index that is indicated by the url with /chapter-2 if s.splitChapters: chapterIndices = [self.getChapterIndex(b, article)] else: chapterIndices = range(len(article.chapters)) # Build the chapters in the index list for chapterIndex in chapterIndices: # Build the top of the article, making a difference between the first chapter # and the chapters with index >= 1 self.buildArticleTop(b, article, chapterIndex) b.div(class_=self.C.CLASS_CHAPTER, width=self.C.NONE, float=self.C.NONE) chapter = self.adapter.getChapterByIndex(chapterIndex, article=article) if isinstance( chapter, basestring ): # Chapter result can be converted to plain output. b.text(chapter) elif chapter is not None: # Still a tree object. Build the element nodes. self.buildElement( b, chapter ) # Render the indexed chapter element as builder calls. b._div(comment=self.C.CLASS_CHAPTER) elif article.text: b.text(article.text) def buildArticleTop(self, b, article, chapterIndex): u"""Build the top of the article: type, title, author, etc. on the first page, if index is **0**. For all other pages build a smaller version of the top.""" s = self.style class_ = self.C.CLASS_ARTICLETOP b.div( class_=class_, float=self.C.LEFT, width=Perc(100), paddingtop=Em(0.5), media=Media(max=self.C.M_MOBILE_MAX, width=self.C.AUTO, float=self.C.NONE, paddingleft=0, paddingright=0), ) if article is not None: # Poster image if chapterIndex == 0 and s.showPoster: b.img(class_=self.C.CLASS_AUTOWIDTH, src=article.poster, marginleft=self.C.AUTO, marginright=self.C.AUTO) # Article category if chapterIndex == 0 and article.category: # Text on text b.a(href='/%s-%s' % (self.C.PARAM_CATEGORY, article.category)) b.h5(fontsize=s.categorySize, lineheight=s.categoryLineHeight, color=s.categoryColor, fontweight=s.categoryWeight, margintop=Em(1), display=self.C.BLOCK) b.text(', '.join(article.category)) b._h5() b._a() # Article title or name (on respectively the first chapter page or the rest of the pages. title = article.name or article.title if title: if chapterIndex == 0: # Show large title on the chapter first page of the article b.h2(class_='articleTitle0', fontsize=s.titleSize, lineheight=s.titleLineHeight, color=s.titleColor, marginbottom=Em(0.2), display=self.C.BLOCK) b.text(title) b._h2() else: # Show smaller title on the rest of the pages b.h2(class_='articleTitle1', fontsize=s.nameSize, lineheight=s.nameLineHeight, color=s.nameColor, marginbottom=Em(0.2), display=self.C.BLOCK) b.text(title) b._h2() # Author if chapterIndex == 0 and article.author: # Test if there is an author defined. b.h5(fontsize=s.authorSize, fontweight=s.authorWeight, authorcolor=s.authorColor, display=self.C.BLOCK) b.a(href='/%s-%s' % (self.C.PARAM_AUTHOR, article.author)) b.text('By %s' % article.author) b._a() if article.authorEmail: b.text(' ' + article.authorEmail) b._h5() # Chapter title """ chapterTitle = self.adapter.getChapterTitleByIndex(chapterIndex, articleData) if chapterTitle: if chapterIndex == 0: # Show large title on the chapter first page of the article b.h3(class_='chapterTitle0', fontsize=s.chapterTitleSize0, color=s.chapterTitleColor0, margintop=s.chapterTitleMarginTop0, marginbottom=s.chapterTitleMarginBottom0) b.text(chapterTitle) b._h3() else: # Other chapter pages b.h3(class_='chapterTitle1', fontsize=s.chapterTitleSize1, color=s.chapterTitleColor1, margintop=s.chapterTitleMarginTop1, marginbottom=s.chapterTitleMarginBottom1) b.text(chapterTitle) b._h3() """ b._div(comment=class_) def buildArticleStyle(self, b): s = self.style # SVG demo b.div(class_=self.C.CLASS_CHAPTER, color=s.chapterColor) # TODO: Should move from here. Make sure that svgExamples get SCSS builder calls. #b.div(class_='svgDemo', margintop=Em(0.5), marginbottom=Em(0.5)) #b._div() # h1 b.h1( fontsize=s.h1Size, lineheight=s.h1LineHeight, fontweight=s.h1FontSize, fontstyle=s.h1FontStyle, fontfamily=s.h1FontFamily, color=s.h1Color, paddingtop=s.h1PaddingTop, paddingbottom=s.h1PaddingBottom, ) b._h1() # <h2> b.h2( fontsize=s.h2Size, lineheight=s.h2LineHeight, fontweight=s.h2FontSize, fontstyle=s.h2FontStyle, fontfamily=s.h2FontFamily, color=s.h2Color, paddingtop=s.h2PaddingTop, paddingbottom=s.h2PaddingBottom, ) b._h2() # <h3> b.h3( fontsize=s.h3Size, lineheight=s.h3LineHeight, fontweight=s.h3FontSize, fontstyle=s.h3FontStyle, fontfamily=s.h3FontFamily, color=s.h3Color, paddingtop=s.h3PaddingTop, paddingbottom=s.h3PaddingBottom, ) b._h3() # <h4> b.h4( fontsize=s.h4Size, lineheight=s.h4LineHeight, fontweight=s.h4FontSize, fontstyle=s.h4FontStyle, fontfamily=s.h4FontFamily, color=s.h4Color, paddingtop=s.h4PaddingTop, paddingbottom=s.h4PaddingBottom, ) b._h4() # <p> b.p(fontsize=s.articleSize, lineheight=s.articleLineHeight, textindent=s.articleIndent) self._buildPStyle(b) b._p() # <p> <p> b.p(selectorPath='p + p', textindent=s.articlePPIndent) b._p() # <p class="... first"> #b.p(class_=self.C.CLASS_FIRST, textindent=s.articleIndent) #b._p() # <p class="... last"> b.p(class_=self.C.CLASS_LAST) b._p() # <lead> b.p(class_=self.C.CLASS_LEAD, fontsize=s.leadSize, lineheight=s.leadLineHeight, fontweight=s.leadWeight, fontstyle=s.leadStyle, color=s.leadColor, marginbottom=s.leadMarginBottom, margintop=s.leadMarginTop, textindent=s.articleIndent) self._buildPStyle(b) b._p() # ** b.b(fontweight=self.C.BOLD) b._b() # <blockquote> b.blockquote(borderleft=s.blockQuoteBorderLeft or Border('solid', '4px', '#CCC'), margin=s.blockQuoteMargin or Margin(Em(1.5), 10), lineheight=s.blockQuoteLineHeight or Em(1.4), fontstyle=s.blockQuoteStyle or self.C.ITALIC, padding=s.blockQuotePadding or Padding(Em(0.5), 10), color=s.blockQuoteColor or Color('#828487')) b._blockquote() # <em> b.em(fontstyle=s.emFontStyle, fontweight=s.emFontWeight, color=s.emColor, fontfamily=s.emFontFamily) b._em() # <pre> b.pre( fontstyle=s.preFontStyle, fontweight=s.preFontWeight, fontsize=s.preFontSize, color=s.preColor, fontfamily=s.preFontFamily, paddingtop=s.preMarginTop, paddingbottom=s.prePaddingBottom, paddingleft=s.prePaddingLeft, paddingright=s.prePaddingRight, backgroundcolor=s.preBackgroundColor, margintop=s.preMarginTop, marginbottom=s.preMarginBottom, ) b._pre() # <div class="imgBlock"><img/><div class="caption">...</div></div> b.div( class_=self.C.CLASS_IMAGEBLOCK, backgroundcolor=s.imgBackgroundColor, margintop=s.imgMarginTop, marginbottom=s.imgMarginBottom, paddingtop=s.imgPaddingTop, paddingbottom=s.imgPaddingBottom, paddingleft=s.imgPaddingLeft, paddingright=s.imgPaddingRight, ) b.img() b.div(class_=self.C.CLASS_CAPTION, fontfamily=s.captionFontFamily, fontsize=s.captionFontSize, color=s.captionColor, fontstyle=s.captionFontStyle, margintop=s.captionMarginTop) b._div() # .caption b._div() # .imageBlock # <img> Plain Textile img tag, generated by !(autoWidth)--url--! b.img(class_=self.C.CLASS_AUTOWIDTH, marginleft=s.imgAutoWidthMarginLeft, marginright=s.imgAutoWidthMarginRight, margintop=s.imgMarginTop, marginbottom=s.imgMarginBottom, textindent=s.imgAutoWidthTextIndent, display=s.imgAutoWidthDisplay) # <ul><li>...</li></ul> b.ul(liststyletype=s.bulletType, liststyleimage=s.bulletImage, lineheight=s.bulletLineHeight, liststyleposition=s.bulletPosition, paddingleft=s.bulletPaddingLeft, marginbottom=s.bulletMarginBottom, margintop=s.bulletMarginTop) self._buildLiStyle(b) b._ul() # <ol><li>...</li></ol> b.ol(liststyletype=s.numberedListType, liststyleposition=s.numberedListPosition, paddingleft=s.numberedListPaddingLeft, lineheight=s.numberedListLineHeight, marginbottom=s.numberedListMarginBottom, margintop=s.numberedListMarginTop) self._buildLiStyle(b) b._ol() b._div() # Article chapter def _buildLiStyle(self, b): u"""Private method. Build the style parameters of a bullet list.""" # <li> in side article XML s = self.style b.li(marginbottom=s.bulletItemMarginBottom) b._li() def _buildPStyle(self, b): u"""Private method. Build the style parameters of a paragraph tag.""" # <footnote> inside article XML s = self.style b.sup(class_=self.C.CLASS_FOOTNOTE, top=s.footnoteTop or Em(-0.5), fontsize=s.footnoteFontSize or Em(0.8), position=s.footnotePosition or self.C.RELATIVE, verticalalign=s.footnoteVerticalAlign or self.C.BASELINE) b._sup() b.em(fontweight=s.emWeight or self.C.BOLD) b._em()
class FeaturedByText(FeaturedBase): u"""The @FeaturedByText@ feature component, shows a featured article by summary. Respectively the binary flags @BluePrint@ *showPoster*, *showLevel*, *showTitle* and *showTopic* will enable the level of the article (as defined in the article source @$level@), the article title (@$title@) and topic (@$topic), of set to @True@.""" # Get Constants->Config as class variable, so inheriting classes can redefine values. C = FeaturedBase.C LEVELSIZE = Em(0.9) LEVELCOLOR = Color('#6294D0') TEXTCOLOR = Color('#FFFFFF') LINKCOLOR = Color('#4692BD') AUTHORSIZE = Em(1.2) CATEGORYSIZE = Em(1.4) AUTHORCOLOR = Color('#828487') CATEGORYCOLOR = AUTHORCOLOR LABELCOLOR = AUTHORCOLOR NAMECOLOR = Color('#66696C') SUMMARYCOLOR = Color('#202020') BLUEPRINT = BluePrint( FeaturedBase.BLUEPRINT, # Alternative layout selectors showPoster=True, doc_showPoster= u'Boolean flag to indicate if the poster of the article should be shown.', showSummary=True, doc_showSummary= u'Boolean flag to indicate that summary should be shown if it exists.', showLevel=True, doc_showLevel= u'Boolean flag to show the intended reader level for this article.', showCategory=True, doc_showCategory= u'Boolean flag to indicate if the category of this article should be shown.', showAuthor=True, doc_showAuthor= u'Boolean flag to indicate if the author of this article should be shown.', # Selection stuff start=0, doc_start=u'Index of first selected item to feature.', count=3, doc_count=u'Number of selected items to feature.', # Label stuff '#828487' label=None, labelSize=Em(2), labelColor='red', labelMarginBottom=Em(0.5), labelMarginTop=Em(0.3), labelLineHeight=Em(1.4), # Poster, select by @showPoster posterWidth=Perc(40), doc_posterWidth=u'Width of the poster thumnail.', posterAlign=C.LEFT, doc_posterAlign= u'Alignment of the poster image, C.LEFT or C.RIGHT. Default is left.', # Layout stuff colWidth=8, doc_colWidth=u'Default amount of columns for this component', backgroundColor=None, doc_backgroundColor= u'Background color of the whole component. Default is to inherit.', paddingTop=Em(2), paddingBottom=Em(2), paddingLeft=Em(1), paddingRight=Em(1), # Level stuff, handle local fontsize and lineheight here, related to the item size genericLevel= 'Generic', # Show generic level if level is omitted in data. #General style stuff colorBodyText=TEXTCOLOR, linkColor=LINKCOLOR, levelColor=LEVELCOLOR, levelSize=LEVELSIZE, levelLineHeight=Em(1.4), levelWeight=C.BOLD, levelMarginTop=Em(0.5), # Category stuff in h5 categoryColor=CATEGORYCOLOR, categorySize=CATEGORYSIZE, categoryLineHeight=Em(1.2), categoryWeight=C.BOLD, # Name stuff in h2 nameSize=Em(3.2), nameLineHeight=Em(1), nameWeight=None, # Default inheriting from the main weight. nameColor=NAMECOLOR, nameMarginBottom=Em(0.2), nameMarginTop=0, nameDisplay=C.BLOCK, # Author stuff in h6 authorSize=AUTHORSIZE, authorWeight=C.NORMAL, authorColor=AUTHORCOLOR, doc_authorColor=u'Author name color.', authorDisplay=C.BLOCK, authorLineHeight=Em(1.4), # Summary stuff summaryColor=SUMMARYCOLOR, summarySize=Em(1.2), summaryLineHeight=Em(1.4), summaryMarginTop=Em(0.4), summaryMarginBottom=Em(0.5), # Mobile stuff mobileDisplay=C.NONE, mobilePaddingTop=Em(2), mobilePaddingBottom=Em(0.5), mobilePaddingLeft=Em(0.5), mobilePaddingRight=Em(0.5), mobileMarginTop=Em(2), mobileMarginBottom=Em(0.5), mobileMarginLeft=Em(0.5), mobileMarginRight=Em(0.5), mobileFloat=C.NONE, mobileWidth=C.AUTO, ) def buildFeatured(self, b, articles): s = self.style b.div( class_=self.getClassName(), color=s.colorBodyText, backgroundcolor=s.backgroundColor, display=s.display, float=s.float, paddingtop=s.paddingTop, paddingleft=s.paddingLeft, paddingright=s.paddingRight, media=Media(max=self.C.M_MOBILE_MAX, width=s.widthMobile, display=s.displayMobile, float=s.floatMobile), ) for article in articles: self._buildFeaturedArticle(b, article) b._div() def _buildFeaturedArticle(self, b, article): u"""Build the featured article.""" s = self.style if s.label: b.h2(fontsize=s.labelSize, color=s.labelColor, margintop=s.labelMarginTop, marginbottom=s.labelMarginBottom, lineheight=s.labelLineHeight, media=(Media(min=self.C.M_TABLET_MIN, max=self.C.M_TABLET_MAX, fontsize=s.tabletLabelSize, color='red'), Media(max=self.C.M_MOBILE_MAX, color='blue'))) b.text(s.label) b._h2() b.a(href='/%s-%s' % (self.C.PARAM_ARTICLE, article.id), color=s.linkColor, class_=self.C.CLASS_NAME) b.h2(fontsize=s.nameSize, fontweight=s.nameWeight, lineheight=s.nameLineHeight, color=s.nameColor, marginbottom=s.nameMarginBottom, display=s.nameDisplay, margintop=s.nameMarginTop) b.text(article.name) b._h2() b._a() if s.showPoster and article.poster: b.a(href='/%s-%s' % (self.C.PARAM_ARTICLE, article.id), class_=self.C.CLASS_NAME) b.img(width=Perc(100), src=article.poster, float=s.posterAlign, padding=0, margin=Margin(Em(0.5), Em(0.5), 0, 0), media=Media(max=self.C.M_MOBILE_MAX, display=self.C.NONE)) b._a() if s.showLevel and (article.level or s.genericLevel): b.h5(class_=self.C.CLASS_LEVEL, color=s.levelColor, fontsize=s.levelSize, fontweight=s.levelWeight, margintop=s.levelMarginTop, lineheight=s.levelLineHeight) b.text(article.level or s.genericLevel) b.text(' level') b._h5() if s.showAuthor and article.author: b.a(href='/%s-%s' % (self.C.PARAM_AUTHOR, article.author), class_=self.C.CLASS_AUTHOR) b.h5(fontsize=s.authorSize, fontweight=s.authorWeight, color=s.authorColor, lineheight=s.authorLineHeight, display=s.authorDisplay) b.text('By %s' % article.author) b._h5() b._a() if s.showCategory and article.category: for category in article.category: b.a(href='/%s-%s' % (self.C.PARAM_CATEGORY, category), class_=self.C.CLASS_CATEGORY) b.h5(fontsize=s.categorySize, fontweight=s.categoryWeight, lineheight=s.categoryLineHeight, color=s.categoryColor, margintop=Em(1), display=self.C.BLOCK) b.text(category) b._h5() b._a() if s.showSummary and article.summary is not None: # Test on element. Summary elements tag must be defined by generic style. b.div(class_='featuredSummary', clear=self.C.BOTH, float=self.C.LEFT, width=Perc(100), color=s.summaryColor, fontsize=s.summarySize, lineheight=s.summaryLineHeight, margintop=s.summaryMarginTop, marginbottom=s.summaryMarginBottom) if isinstance(article.summary, basestring): b.text(article.summary) else: self.buildElement(b, article.summary) b._div() if b.e.form[self.C.PARAM_DEBUG]: b.text( ` article `)
class Logo(Component): # Get Constants->Config as class variable, so inheriting classes can redefine values. C = Component.C BLUEPRINT = BluePrint( # Layout stuff colWidth=4, doc_colWidth=u'Default amount of columns for this component.', maxWidth=Perc(100), doc_maxWidth=u'Maximal width of the component', minWidth=Perc(100), doc_minWidth=u'Minimal width of the component', # Logo stuff width=280, doc_logoWidth=u'Logo width', height=C.AUTO, doc_height=u'Logo height', marginTop=0, doc_marginTop=u'Logo margin top', marginLeft=0, doc_marginLeft=u'Logo margin left', marginRight=Perc(1.8), doc_marginRight=u'Logo margin right', fontSize=Em(2.9), doc_fontSize=u'Logo font size', marginBottom=0, doc_marginBottom=u'Logo margin bottom', logoFloat=C.LEFT, doc_logoFloat=u'Logo div float', # H2 h2FontFamily=C.LOGOFAMILY, doc_h2FontFamily=u'h2 font family', h2Size=Em(2.8), doc_h2Size=u'h2 size', h2LineHeight=Em(1.4), doc_h2LineHeight=u'h2 leading', h2Weight=C.BOLD, doc_h2Weight=u'h2 weight', h2Style=None, doc_h2Style=u'h2 style', h2PaddingTop=Em(0.2), doc_h2PaddingTop=u'h2 padding top', h2PaddingBottom=Em(0.2), doc_h2PaddingBottom=u'h2 padding bottom', h2Color=Color('#323A47'), doc_h2Color=u'h2 color', ) def buildBlock(self, b): s = self.style colClass = self.getColClass(s.colWidth) b.block(self) b.div(class_=colClass, float=s.logoFloat, marginleft=s.marginLeft, marginright=s.marginRight, margintop=s.marginTop, marginbottom=s.marginBottom) # @url: url of href link. If None no link is made # @src: url of the image source. data = self.adapter.getLogo() if data.url: b.a(href=data.url) if data.src: b.img(src=data.src, width=s.width, maxwidth=s.maxWidth, height=s.height) else: b.h2( fontsize=s.h2Size, lineheight=s.h2LineHeight, fontweight=s.h2Weight, fontstyle=s.h2Style, color=s.h2Color, paddingtop=s.h2PaddingTop, paddingbottom=s.h2PaddingBottom, ) b.text(data.text) b._h2() if data.url: b._a() b._div(comment=colClass) b._block(self)
class Component(object): u""" The Component describes the abstract behavior of components on the page. """ # Get Constants->Config as class variable, so inheriting classes can redefine values. C = Constants # Root default style template. To be cascaded by inheriting classes. BLUEPRINT = BluePrint( # Default behavior of images, use class autowidth to cover differences between browsers. imgClass=C.CLASS_AUTOWIDTH, doc_imgClass=u'Image class, set default to AUTOWIDTH.', imgMaxWidth=Perc(100), doc_imgMaxWidth=u'Image maximal width', imgMinWidth=0, doc_imgMinWidth=u'Image minimal width', ) TAGNAME = 'div' # By default every component has a root div element. BUILD_CSS = True # Default behavior of every component is to build in CSS. STYLE_DEFAULT = { } # Default style source, optionally redefined by inheriting classes. ADAPTER = BlurbAdapter() # Unless defined otherwise by inheriting classes. def __init__(self, components=None, style=None, id=None, parent=None, name=None, css=None, fonts=None, prefix=None, class_=None, type=None, contentID=None, repeat=1, title=None, url=None, template=None, editable=False, adapter=None, selector=None, **kwargs): # The class name of the components is used as class names in SASS/CSS # Initialize the self.style, as selector and id are stored there. self.style = style # If style is None, then use a copy of the self.BLUEPRINT style. self.style.add( kwargs ) # Overwrite further initialize self.style from rest of arguments self.style.title = title # Page or other component title self.style.component = self # Add the weakref reference to self for the root style. # Adapter for reading content/data self.adapter = adapter # If None, then "parent.adapter or self.ADAPTER" is used # CSS and Fonts urls self.css = css # Set the css path list for this component (can be empty list or None) self.fonts = fonts # Set the css path list for this component (can be empty list or None) # The optional id is the #id in HTML must be unique in the page. Stored as self.style.id. # Has no default value, so not all HTML elements will have id attribute. self.id = id # Used overruling the otherwise calculated self.selector self.selector = selector # Used as class name when constructing selector (amongst other choices). # Take class_ or class component. Stored as self.style.class_ self.class_ = class_ # self.name is used to identity components. Always answers something. Does not have to be unique. self.name = name # Forced title of the browser window or generated document or table of content. # If kept None, then the self.adapter will be queried for the title. # This allows both the definition of static names (per page template) or the usage # of page titles that depend on the current url. # If the self.adapter answers None as title, then use self.TITLE self.title = title # Prefix of class and selector, stored as self.style.prefix. Shows in CSS selector as myPrefix.class self.prefix = prefix # Cache for the unique ID based on the content tree, so components can be compared. self._uid = None self.template = template # Optional template match with URL parameter self.contentID = contentID # Optional unique id to query content from the self.adapter self.parent = parent # Weakref to parent component self.repeat = repeat # TODO: Make this work. Repeat count for repeating this component in output self.url = url # Default is not to have a URL. Page attribute define URL automatic from name. self.editable = editable # Is content of the component editable? self.type = type # Type of the website, taking TYPES[self.type] from this pool # Child components of self. Default is self.baseComponents self.initializeComponents(components) # Allow inheriting class to (re)define other stuff when inheriting class redefined initialize() # Default behavior is to do nothing here. self.initialize() def __repr__(self): return '<%s: %s>' % (self.__class__.__name__, self.selector or self.name) def _getInheritedClasses(self): u"""Private method. Answer the list of inherited parent classes by this component.""" return list(inspect.getmro(self.__class__)) def _getInheritedClassNames(self): u"""Private method. Answer the list of inherited class names by this component.""" names = [] for cls in self._getInheritedClasses(): names.append(cls.__name__) return names @classmethod def getRootDir(cls): u"""Answer the default root directory path, e.g. to store example files and cached SASS/CSS.""" return TX.asDir(cls.C.PATH_EXAMPLES + cls.getPythonClassName().lower() + '/') # Expand user path to full directory path. @classmethod def getClassName(cls): u"""Answers the class name of the *cls* as capitalized name.""" name = cls.__name__ return name[0].lower() + name[1:] @classmethod def getPythonClassName(cls): u"""Answer the Python class name of @self@.""" return cls.__name__ def isLast(self, component): u"""Allow components to test the parent if they are last.""" return self.components and self.components[-1] is component def getColClass(self, col): u"""Answer the colClass, based on the numeric *col* value and if the component is the last in the parent list of child components.""" colClass = TX.col2Class(col) if self.parent is None or self.parent.isLast(self): colClass = (colClass, self.C.CLASS_LAST) return colClass def getTitle(self, path): u"""Answer the page title as defined in the style or answered by @self.adapter@. The adapter can use the @path@ argument to fine-tune the title.""" pageTitle = self.style.title articleTitle = self.adapter.getPageTitle(path=path) if pageTitle and articleTitle: return '%s | %s' % (pageTitle, articleTitle) return pageTitle or articleTitle def getFavIcon(self, builder): u"""Call back from the builder to answer the favIcon url. This method can be redefined by inheriting classes if the favIcon is depending on the content and status of a page. Defautl is to answer style value @self.style.favIcon@.""" if self.style and self.style.favIcon: return self.style.favIcon return None # self.className Answer self.style.className or otherwise class name is directly derived from the object class. def _get_className(self): u"""Get method of property @self.className@. Use the property instead of this method.""" # @@@ Clean this up, so self.className is used everywhere instead of self.getClassName() or self.class_ return self.style.className or self.getClassName() className = property(_get_className) def getPrefixClass(self, prefix2=None): u"""Answers the extended class name @self.prefix + self.prefix2 + self.class_@. If @self.class_@ is not defined, and @self.prefix + self.prefix2@ are defined, then always add the class name of the component.""" name = [] prefix = self.prefix if prefix: name.append(prefix) if prefix2: name.append(prefix2) name.append(self.getClassName()) return ' '.join(name) def initializeComponents(self, components): u""" Sets the self.components. If components is None, then use the result of @self.baseComponents()@. If *components* is a single component, then make it into a list. """ if components is None: components = self.baseComponents() elif not isinstance(components, (list, tuple)): components = [components] self.components = components # Create parent weakrefs in the components to self def initialize(self): u"""Called by every component when the constructor finished. This allows inheriting component classes to adjust default settings. Inheriting classes need to redefine the method. Default behavior is to do nothing.""" pass def readFile(self, path): u"""Generic method to read from local file system. Answer None if the file does not exist.""" if os.path.exists(path): f = open(path, 'rb') s = f.read() f.close() return s return None def getRootPath(self): u"""Answer the file path of @from xierpa3 import components@.""" from xierpa3 import components return components.__path__[0] def baseComponents(self): """To be redefined by inheriting classes to answer the default child components of the component.""" return [] def isEmpty(self): """Answer the boolean flag if this component has any attributes or child components.""" return len(self.components) == 0 and self.style.isEmpty() def isEmptyCss(self): u"""Answer the boolean flag if this component will generate CSS content. This is different from the regular @self.isEmpty@, since there may be components with content that have @self.BUILD_CSS@ set to @False@. When @self.BUILD_CSS is True@ it still should build if there is CSS content that has set @self.BUILD_CSS@ to @True@. """ if not self.style.isEmpty(): return False for component in self.components: if not component.isValidCss(): return False if not self.BUILD_CSS: # It must be empty. return True return False def isValidCss(self): u"""Answer the boolean flag of there is valid CSS for this component. If not @self.isEmptyCss()@ then answer @False@. Otherwise answer of there is a @self.selector@ in the component.""" if self.isEmptyCss(): return False return bool(self.selector) def isComponent(self, name): """Answer the boolean flag if this is a component where @name == self.name@.""" return name == self.name or ( name in self.class_ or [] ) # Compare with self._name or class names def getComponent(self, name): """Answer the child component that matches *name.*""" for component in self.components: if component.isComponent(name): return component return None def build(self, b): u""" Test on the type of building to be done here by builder *b*. Normally the plain @self.buildBlock@ will be called, but it is possible to catch the call by implementing a method, dedicated for a particular kind of builder. @self.buildBlock_[builder.ID]@ will then called instead. E.g. @self.buildBlock_css(b)@ will force the CSS builder to call that method instead of the regular @self.buildBlock(b)@. Note that this only should be exceptional situation where there is no way to make the builder call abstract. Normally components should not be aware which builder they are talking to. """ hook = 'buildBlock_' + b.ID if hasattr(self, hook): buildBlock = getattr(self, hook) else: buildBlock = self.buildBlock # Not special dispatch, use generic method instead. buildBlock(b) def buildBlock(self, b): u""" Generic builder *b* for all child components of @self@. Can be redefined by an inheriting class. """ b.block(self) for component in self.components: component.build(b) b._block(self) def buildAjaxDict(self, site=None, d=None): u"""Answer the ajax result dictionary that gets sent back as json.""" if d is None: d = {} if site is None: site = self for component in self.components: component.buildAjaxDict(site, d) return d def buildJS(self, b): u""" Will be called for every component in the tree, so each is allows to build its own Javascript at the end of a document. Default behavior is to ignore this for other than the HtmlBuilder and the just call the child components. Inheriting component classes that want to export Javascript need to redefined this method.""" if b.isType('html'): for component in self.components: component.buildJS(b) # D O C U M E N T A T I O N def buildDocumentation(self, b): u"""Builder of the documentation of self. It is the main method generating this documentation page.""" b.page(self) b.div(class_=self.C.CLASS_DOCUMENTATION, width=Perc(100)) self.buildDocumentationBlock(b) b._div(comment=self.C.CLASS_DOCUMENTATION) b._page(self) def buildDocumentationBlock(self, b, processed=None): u"""Recursive call to build the documentation of @self@ and its child components, using builder *b*. It is the method generating the documentation for this component. The information extracted includes the level of inheritance of the component, the general description, as defined in the class doc string, a list of child components, a table with the available cascaded method and the component style, which cascades from the parent class @BLUEPRINT@ definitions.""" if processed is None: processed = set() if self in processed: return processed.add(self) name = self.getPythonClassName() b.h1(color='red', fontfamily='Verdana', fontsize=14) b.text('Component %s' % name) b._h1() # Doc string as class descriptor, if is exists. if self.__doc__: b.text(textile.textile(self.__doc__)) b.p() if self.components: componentList = [] for component in self.components: componentList.append(component.name) if len(componentList) > 1: componentLabel = 'components' else: componentLabel = 'component' b.text('This **%s** instance contains %d child %s: **%s**.' % (name, len(componentList), componentLabel, ', '.join(componentList))) else: b.text('**%s** has no child components.' % name) b._p() # Inheritance b.p() b.text(u'**%s** → %s' % (name, u' → '.join(self._getInheritedClassNames()[1:]))) b._p() # Show the component style b.h2() b.text('Style from cascaded BluePrints') b._h2() b.table(width=Perc(100)) b.tr() for class_, label, width in (('name', 'Name', Perc(25)), ('value', 'Value', Perc(25)), ('description', 'Description', Perc(50))): b.th(class_=class_, width_html=width) b.text(label) b._th() b._tr() for key, value in sorted(self.style.items()): b.tr() b.td(class_='name') b.text(key) b._td() b.td(class_='value', textalign=self.C.RIGHT) if value is None: b.span(style='color:#888;') b.text('(Inherited)') b._span() elif isinstance(value, Color): b.text('%s' % value) b.span(style='background-color:%s;' % value) b.text(' ' * 4) b._span() elif isinstance(value, (tuple, list)): b.text( ` value `) elif not isinstance(value, basestring): b.text('%s' % value) elif value.startswith('//'): b.img(src=value, width=50) # Show the image elif len(value) > 50: b.text(value[:50] + '...') else: b.text(value) b._td() b.td(class_='description') doc = self.style.getDoc(key) if doc is not None: b.text(textile.textile(doc)) b._td() b._tr() b._table() # Attributes of this component b.h2() b.text('Attributes') b._h2() b.table(width=Perc(100)) b.tr() b.th() b.text('Name') b._th() b.th() b.text('Attributes') b._th() b.th() b.text('Description') b._th() b._tr() for name, value in self.__dict__.items(): if name.startswith('_'): continue b.tr() b.td(class_='name') b.text(name) b._td() b.td(class_='value') b.text( ` value `) b._td() b.td(class_='description') b.text('...') b._td() b._tr() b._table() # Methods of this component b.h2() b.text('Methods') b._h2() b.table(width=Perc(100)) b.tr() b.th(class_='name') b.text('Name') b._th() b.th(clas_='value') b.text('Arguments') b._th() b.th(class_='description') b.text('Description') b._th() b._tr() for name, method in inspect.getmembers(self.__class__, predicate=inspect.ismethod): if name.startswith('__'): continue b.tr() b.td(class_='name') b.text(name) b._td() b.td(class_='value') args, varargs, keywords, defaults = inspect.getargspec(method) for index, arg in enumerate(args): if arg == 'self': continue b.text(arg) if defaults is not None and index < len(defaults): b.text('=%s' % defaults[index]) b.br() #b.text(varargs) if keywords: b.text('**%s' % keywords) b.br() #b.text(`defaults`) b._td() b.td(class_='description') if method.__doc__: b.text(textile.textile(method.__doc__)) b._td() b._tr() b._table() # Show recursively the rest of the components for component in self.components: component.buildDocumentationBlock(b, processed) # X M L R E N D E R I N G def buildElement(self, b, element): u"""Recursive rendering of the etree element, using the document methods in the builder as defined in the @DocumentBuilderPart@ class. The elements are translated to the standard tag behavior of the builder.""" b.docTagElement(element) b.text(element.text) # Plain text output of the element for child in element: # Recursively render all element children. self.buildElement(b, child) b._docTagElement(element) b.text(element.tail) # Plain text output of the element tail # A T T R I B U T E S # self.hashedID def _get_hashedID(self): u"""Get-only property @self.hashedID@. Answer the calculated unique ID based on the content. This ID can be compared between components to decide if they are identical. This is used by the CSS builder to decide of styles can be skipped then they are identical. Note that the value is cache, so alterations to the content of children don't reflect in the ID, once it is established. """ if self._hashedID is None: m = hashlib.md5() if self.selector: m.update(self.selector) for media in self.media: m.update(media.hashedID) for style in (self.styles or []): m.update(style.hashedID) self._hashedID = m.digest() return self._hashedID hashedID = property(_get_hashedID) # self.name def _get_name(self): """Set/Get property @self.name@. Answer one of @self._name or self.id or self.class_ or self.getClassName()@. The name attribute is for text identification of an element. It is not guaranteed to be unique.""" name = self._name or self.id or self.class_ if name is None: # Still None? # Same as self.getClassName(), but that method answers None for some component classes. name = self.__class__.__name__ name = name[0].lower() + name[1:] # First letter as lower case return name def _set_name(self, name): """Set/Get property @self.name@. Set @self._name@ to *name*.""" self._name = name name = property(_get_name, _set_name) # self.oge def _get_urlName(self): """Get-only property @self.urlName@. Answer the url safe version of @self.name@.""" return TX.name2UrlName(self.name) urlName = property(_get_urlName) # self.url def _get_url(self): u"""Set/Get property @self.url@. Answer the url of this component. Otherwise answer @None@.""" if self._url is None: return TX.label2ParamId(self.name) return self._url def _set_url(self, url): u"""Set/Get property @self.url@. Set the @self._url@ to *url*.""" self._url = url url = property(_get_url, _set_url) # self.style def newStyle(self, selector=None, d=None): u"""Answer a new style with @selection@ and attributes defined in the optional *d* dictionary. using *selector*.""" if d is None: d = {} return Style(selector, **d) def baseStyle(self): u"""Answer the base style for this component, before the BluePrint parameters are copied into it. This can be cone by inheriting classes defining htis method. Default behavior is just to answer the result of @self.newStyleI()@.""" return self.newStyle() def addStyle(self, selector=None, **kwargs): u"""Add the *selector* and style attributes @**kwargs@ to @self.style@.""" return self.style.addStyle(selector, **kwargs) def addMedia(self, selector=None, **kwargs): u"""Add the *selector* media style, defined in @**kwargs@ to @self.style@.""" self.style.addMedia(selector=selector, **kwargs) def _get_style(self): u"""Set/Get property @self.style@. If it doesn't exist yet, create the default style from self.copyBluePrint. If not defined yet, then create a new instance of @Style@, initialized by the aggregation of the cascading @self.BLUEPRINT@ of the inherited classes.""" if self._style is None: self._style = self.baseStyle( ) # Allow theme to define the base style. # Get the list of classes that self is inheriting from. inheritedClasses = self._getInheritedClasses() inheritedClasses.reverse() for inheritedClass in inheritedClasses: if hasattr(inheritedClass, 'BLUEPRINT'): self._style.addBluePrint(inheritedClass.BLUEPRINT) self._style.addBluePrint(self.BLUEPRINT) return self._style def _set_style(self, style): u"""Set/Get property @self.style@. Set the @self._style@ to *style*.""" assert style is None or isinstance(style, Style) self._style = style style = property(_get_style, _set_style) # self.css def _get_css(self): u"""Set/Get property @self.css@. Answer the list of CSS URLs for this component. If there is a parent, then answer the css of the parent, Otherwise answer the default list.""" css = self.style.css if css is None and self.parent: return self.parent.css return ['css/style.css'] def _set_css(self, urls): u"""Set/Get property @self.css@. Set the list of CSS URLs for this component to *urls*. If there is a parent, then answer the css of the parent, Otherwise answer the default list.""" assert urls is None or isinstance(urls, (tuple, list)) self.style.css = urls css = property(_get_css, _set_css) # self.fonts def _get_fonts(self): u"""Set/Get property @self.font@. Answer the list of web font urls for this component. If there is a parent, then answer the fonts of the parent. Otherwise answer the default list.""" fonts = self.style.fonts if fonts is None and self.parent: return self.parent.fonts return fonts def _set_fonts(self, urls): u"""Set/Get property @self.font@. Set the list of web font urls for this component to *urls*.""" if urls is None: urls = [] assert isinstance(urls, (tuple, list)) self.style.fonts = urls fonts = property(_get_fonts, _set_fonts) # self.prefix def _get_prefix(self): u"""Set/Get property @self.prefix@. Answer the prefix of class.""" return self.style.prefix def _set_prefix(self, prefix): u"""Set/Get property @self.prefix@. Set the prefix of class to *prefix*.""" self.style.prefix = prefix prefix = property(_get_prefix, _set_prefix) # self.class_ Answer the self._class. This value can be None. def _get_class_(self): u"""Set/Get property @self.class_@. Answer the class name of @self@. Use the property instead of this method.""" return self.style.class_ def _set_class_(self, class_): u"""Set/Get property @self.class_@. Set the class name of @self@ to *class_*. Use the property instead of this method.""" self.style.class_ = class_ class_ = property(_get_class_, _set_class_) # self.prefixClass def _get_prefixClass(self): u"""Get-only property @self.prefixClass@ Answer the result of @self.getPrefixClass()@. Use the property instead of this method.""" return self.getPrefixClass() prefixClass = property(_get_prefixClass) # self.id def _get_id(self): u"""Set/Get property @self.id@. Answer the id of @self@. Use the property instead of this method.""" return self.style.id def _set_id(self, id): u"""Set/Get property @self.id@. Set the id of @self@ to *id*. Use the property instead of this method.""" self.style.id = id id = property(_get_id, _set_id) # self.adapter def _get_adapter(self): u"""Property @self.adapter@ Answer the adapter of @self@. Although it may be change during the course of development (and also force otherwise), a component keeps the instance of the adapter. The reason is that we want caching to be done by the adapter. Builders are only created temporary, so they should not hold the adapter. Use the property instead of this method.""" if self._adapter is not None: return self._adapter if self.parent is not None: return self.parent.adapter return self.ADAPTER # Use default adapter of this component def _set_adapter(self, adapter): u"""Set the adapter for this component. This allows various components to have their own adapter. If not defined, the component will take the adapter of its parent. If the parent adapter is @None@, then don’t overwrite the adapter of the builder during runtime. Use the property instead of this method.""" self._adapter = adapter adapter = property(_get_adapter, _set_adapter) # self.components def addComponent(self, component): u"""Add *component* to the @self.component@ list of children.""" if isinstance(component, basestring): from text import Text component = Text(component) component.parent = self self._components.append(component) def _set_components(self, components): u"""Get/Set property @self.components@. Set the @self._components@ to *components*. If *components* is not a tuple or a list, then convert the single component into a list first. Set the @component.parent@ to self for every component in the list. Use the property instead of this method.""" if isinstance(components, basestring): from text import Text components = [Text(components)] elif not isinstance(components, (list, tuple)): components = [components] # Set weakref to parent (self) if we have components if components is not None: for component in components: component.parent = self self._components = components def _get_components(self): u"""Get/Set property @self.components@. Answer @self._components@. Use the property instead of this method.""" return self._components components = property(_get_components, _set_components) # self.parent Parent component def _set_parent(self, parent): u"""Get/Set property @self.parent@. Set @self._parent to the weakref of *parent*. Use the property instead of this method.""" if parent is not None: self._parent = weakref.ref(parent) else: self._parent = None def _get_parent(self): u"""Get/Set property @self.parent@. Answer the converted weakref of @self._parent@ if it exists and if it is a valid reference. Answer @None@ otherwise. Use the property instead of this method.""" if self._parent is not None: return self._parent() return None parent = property(_get_parent, _set_parent) # self.text Collect all text from the component nodes def _get_text(self): u"""Get/Set property @self.text@. Answer the plain text of the @self@ and recursively called from all child components. Use the property instead of this method.""" text = [] for component in self.components: t = component.text if t: text.append(t) return ' '.join(text) def _set_text(self, text): u"""Get/Set property @self.text@. Reset @self.components@ to a list with a @Text(text) instance inside. Use the property instead of this method.""" self.components = [] self.addComponent(text) # Create Text instance if text is a string text = property(_get_text, _set_text) # self.parents Answer the list of parent components def _get_parents(self): u"""Get-only property @self.parents@. Answer the list of parents. If there is no parent, answer an empty list. Use the property instead of this method.""" parent = self.parent if parent is not None: return parent.parents + [parent] return [] parents = property(_get_parents) # self.pages def _get_pages(self): u"""Get-only property @self.pages@. Answer a list with all components that have a URL. Normally this is a page, but it can also be another type of component. Don't drill down. Use the property instead of this method.""" pages = [] for component in self.root.components: if component.url: pages.append(component) return pages pages = property(_get_pages) # self.root def _get_root(self): u"""Get-only property @self.root@. Answers the root component of the @self.parents@. Use the property instead of this method. """ parents = self.parents if parents: return parents[0] return self root = property(_get_root) # self.media Get the media from self.style def _get_media(self): u"""Get-only property @self.media@. Answers the collected media from @self.style@. If empty or @self.style@ does not exist, answer an empty list. Use the property instead of this method.""" style = self.style if style: return style.media return [] media = property(_get_media) # self.selector Construct the style selector of this component: #id, style.selector or class name. def _set_selector(self, selector): u"""Get/Set property @self.selector@. Stores the (CSS) *selector* in @self.style. Use the property instead of this method.@ """ if isinstance(selector, (list, tuple)): selector = ' '.join(selector) self.style.selector = selector def _get_selector(self): u"""Get/Set property @self.selector@. If @self.style@ doesn’t support a selector, then @None@ is answered. In this case the selector block opening and block close must be omitted by the caller. Just the component block will be processed. Otherwise the (CSS) selector is defined in order by @self.style.selector@, @self.getClassName()@. Use the property instead of this method. """ selector = self.style.selector if selector is None: class_ = self.class_ or self.getClassName() if isinstance(class_, (tuple, list)): class_ = class_[-1] if class_ is not None: selector = self.TAGNAME + '.' + class_ return selector selector = property(_get_selector, _set_selector)
class SimpleTypeSpecimenColumn(Column): # Get Constants->Config as class variable, so inheriting classes can redefine values. C = Column.C MAXWIDTH = Px(1100) # Load @fontface fonts for this example from www.webtype.com SPECIMENFAMILY = '"Benton Modern RE"' BODYFAMILY = '"Benton Sans RE", Verdana, sans' HEADFAMILY = SPECIMENFAMILY + ', Georgia, serif' BLUEPRINT = BluePrint( # Column stuff fontFamily=BODYFAMILY, doc_fontFamily=u'Column main font family', width=MAXWIDTH, doc_width=u'Column width.', widthMobile=Perc(100), doc_widthMobile=u'Column width for mobile.', minWidth=0, doc_minWidth=u'Column minimal width.', minWidthMobile=0, doc_minWidthMobile=u'Column minimal width for mobile.', maxWidth=MAXWIDTH, doc_maxWidth=u'Column maximal width.', maxWidthMobile=C.AUTO, doc_maxWidthMobile=u'Column maximal width for mobile.', margin=Margin(0, C.AUTO, 0, C.AUTO), doc_margin=u'Column margin.', marginMobile=0, doc_marginMobile=u'Column margin for mobile.', padding=0, doc_padding='Column padding.', fontSize=Em(1), doc_fontSize=u'Column main font size.', lineheight=Em(1.4), doc_lineheight=u'Column main leading.', color=Color(0), doc_color=u'Column text color, default is black.', backgroundColor=Color('#FFF'), doc_backgroundColor='Column background color, default is white.', # Row rowPadding=Em(2), doc_rowPadding=u'Row padding.', # Speciment stuff specimentSizeIndicator=13, doc_specimenSizeIndicator=u'Size of the size indicator.', specimentSmall=18, doc_specimentSmall=u'Smallest font size of the specimen.', specimenLarge=37, doc_specimenLarge=u'Largest font size of the specimen.', specimenWidth=Perc(100), doc_specimenWidth=u'Specimen line width.', specimentLineHeight=Em(1.2), doc_specimentLineHeight= u'Specimen line height, relative to waterfall font size.', # Size label sizeLabelColor=Color('#888'), doc_sizeLabelColor='Size label color, default is mid-gray.', # h1 h1FontFamily=HEADFAMILY, doc_h1FontFamily=u'h1 font family.', h1FontSize=Em(2), doc_h1FontSize=u'h1 font size', h1LineHeight=Em(1.4), doc_h1LineHeight=u'h1 leading', h1MarginBottom=Em(0.5), doc_h1MarginBottom=u'h1 margin bottom', ) def buildBlock(self, b): u"""Build the specimen column""" s = self.style # Copy from inherited BluePrints with redefined user attributes. b.div( class_=self.C.CLASS_COLUMN, color=s.color, margin=s.margin, width=s.width, maxwidth=s.maxWidth, minwidth=s.minWidth, backgroundcolor=s.backgroundColor, padding=s.padding, fontfamily=s.fontFamily, fontsize=s.fontSize, lineheight=s.lineheight, # Remove margins on mobile, showing the column on full screen width. media=Media(max=self.C.M_MOBILE_MAX, margin=s.marginMobile, width=s.widthMobile, maxwidth=s.maxWidthMobile, minwidth=s.minWidthMobile), ) # Add div.row to allow padding, without making the main column div # grow outside the parent boundaries. b.div(class_=self.C.CLASS_ROW, padding=s.rowPadding) b.h1(fontfamily=s.h1FontFamily, fontsize=s.h1FontSize, lineheight=s.h1LineHeight, marginbottom=s.h1MarginBottom) b.text('WebType ' + self.SPECIMENFAMILY[1:-1]) b._h1() for n in range(s.specimentSmall, s.specimenLarge): b.div(class_='specimen%02d' % n, width=s.specimenWidth, fontsize=Px(n), lineheight=s.specimentLineHeight, fontfamily=self.HEADFAMILY) b.span(class_='size%02d' % n, fontsize=Px(s.specimentSizeIndicator), color=s.sizeLabelColor, fontfamily=self.BODYFAMILY) b.text('%d px' % n) b._span() b.text(u'ABCDEFGHIJKLM abcdefghijklm €$@#123') b._div() # Add reference to sponsored Webtype webfonts. b.hr() b.a(href='//webtype.com', color=s.color, fontfamily=self.BODYFAMILY, fontsize=Em(0.8), lineheight=Em(1.4), target='external') b.text( 'The typefaces in this example %s and %s are sponsored by <Webtype>' % (self.BODYFAMILY, self.HEADFAMILY)) b._a() # Close the row b._div(comment=self.C.CLASS_ROW) b._div()
class Container(Component): u"""The *Container* is the generic component that holds most other components on a page. Containers are always two-layered: a container @div@ to position on a page with a row @div@ inside that handles the responsive behavior of the content.""" # Get Constants->Config as class variable, so inheriting classes can redefine values. C = Component.C BLUEPRINT = BluePrint( # Page/Column paddingLeft=10, doc_paddingLeft=u'Padding left of main container.', paddingRight=10, doc_paddingRight=u'Padding right of main container.', # Style backgroundColor=('#fff'), doc_backgroundColor=u'Background color of the container.', # Row rowWidth=Perc(100), doc_rowWidth=u'Default width of a row inside a container.', rowMargin=Margin(0, C.AUTO), doc_margin= u'Row margin. This makes the main container (page) center on maxwidth.', rowMinWidth=C.M_MOBILE_MAX, doc_rowMinWidth= u'Minimum width of the row inside a container. Default is %d.' % C.M_MOBILE_MAX, rowMinWidthMobile=0, doc_rowMinWidthMobile= u'Minimum width of the row inside a container for mobile.', rowMaxWidth=C.MAXWIDTH, doc_rowMaxWidth= u'Maximum width of the row inside a container. Default is %d.' % C.MAXWIDTH, rowMaxWidthMobile=Perc(100), doc_rowMaxWidthMobile= u'Maximum width of the row inside a container for mobile.', rowOverflow=C.HIDDEN, doc_rowOverflow= u'Default overflow hidden inside a row inside a container.', rowFloat=C.NONE, doc_rowFloat=u'Default float none inside a row inside a container.', ) def buildBlock(self, b): u"""Build the container-div with a row-div inside.""" s = self.style b.div(class_=self.getClassName(), paddingleft=s.paddingLeft, paddingright=s.paddingRight, backgroundcolor=s.backgroundColor, media=Media(max=self.C.M_MOBILE_MAX, paddingleft=0, paddingright=0)) b.div( class_=self.C.CLASS_ROW, width=s.rowWidth, margin=s.rowMargin, float=s.rowFloat, overflow=s.rowOverflow, maxwidth=s.rowMaxWidth, minwidth=s.rowMinWidth, media= # Container row has width 100% in media! Media(max=self.C.M_MOBILE_MAX, width=Perc(100), minwidth=s.rowMinWidthMobile, maxwidth=s.rowMaxWidthMobile, float=s.rowFloat), ) for component in self.components: component.build(b) b._div(comment='.' + self.C.CLASS_ROW) # Comment class at end of row b._div(comment='.' + self.getClassName()) # Comment the class at end of container
class FeaturedByImageList(FeaturedBase): u"""The *FeaturedByImageList* feature component builds a vertical list if thumbnails, level and optional names of the selected article chapters.""" # Get Constants->Config as class variable, so inheriting classes can redefine values. C = FeaturedBase.C LEVELSIZE = Em(0.9) LEVELCOLOR = Color('#6294D0') NAMECOLOR = Color('#A32C2D') BLUEPRINT = BluePrint( FeaturedBase.BLUEPRINT, showLevel=False, doc_showLevel=u'Boolean flag to show the level field of the article.', showName=False, doc_showName=u'Boolean flag to show the name field of the article.', showTopic=True, doc_showTopic=u'Boolean flag to show the topic of the article.', # Selection stuff start=0, doc_start=u'Index of first selected item to feature.', count=3, doc_count=u'Number of selected items to feature.', # Col block stuff colDisplay=C.BLOCK, doc_colDisplay=u'Column display type.', colClear=C.BOTH, doc_colClear='Column float clear.', colMarginBottom=Em(0.5), doc_colMarginBottom='Column margin bottom.', colColor=None, doc_colColor=u'Column color', colMarginRight=Perc(1.8), doc_colMarginLeft=u'Column margin left.', colMarginLeft=0, colFloat=C.LEFT, colMinHeight=1, # Layout stuff colWidth=4, doc_colWidth=u'Default amount of columns for this component.', # Item stuff itemClear=C.NONE, itemDisplay=C.LEFT, itemWidth=Perc(55), # Thumbnail image stuff thumbDisplay=C.BLOCK, # Level stuff, handle local fontsize and lineheight here, related to the item size genericLevel='Generic', doc_genericLevel= u'Show this generic level name if level attitbute is undefined in adapter data.', levelColor=Color(LEVELCOLOR), doc_levelColor=u'Level color.', levelSize=LEVELSIZE, doc_levelSize=u'Level font size.', levelWeight=C.BOLD, doc_levelWeight=u'Level font weight.', levelMarginTop=Em(0.5), doc_levelMarginTop=u'Level margin top.', # Optional name stuff, handle local fontsize and lineheight here, related to the item sizes nameColor=Color(NAMECOLOR), nameSize=Em(0.9), nameLineHeight=Em(1.2), nameWeight=C.BOLD, # Mobile stuff mobileDisplay=C.NONE, mobilePaddingTop=Em(2), mobilePaddingBottom=Em(0.5), mobilePaddingLeft=Em(0.5), mobilePaddingRight=Em(0.5), mobileMarginTop=Em(2), mobileMarginBottom=Em(0.5), mobileMarginLeft=Em(0.5), mobileMarginRight=Em(0.5), mobileFloat=C.NONE, mobileWidth=C.AUTO, ) def buildFeatured(self, b, articles): s = self.style for article in articles: if not article.poster: continue # Only show articles that have some kind of poster image. b.div( class_=self.CLASS_FEATURED_ITEM, display=s.itemDisplay, clear=s.itemClear, marginbottom=s.itemMarginBottom, width=s.itemWidth, ) b.a(href='/%s-%s' % (self.C.PARAM_ARTICLE, article.id)) if s.showLevel: b.h5(color=s.levelColor, fontsize=s.levelSize, fontweight=s.levelWeight, margintop=s.levelMarginTop) b.text(article.level or s.genericLevel) b.text(' level') b._h5() b.img(class_=self.C.CLASS_AUTOWIDTH, width=Perc(60), src=article.poster) if s.showName: b.h4(color=s.nameColor, fontsize=s.nameSize, fontweight=s.nameWeight, lineheight=s.nameLineHeight) b.text(article.name) b._h4() if s.showTopic and article.topic is not None: # Elements must be defined in global style b.text(article.topic) b._a() if b.e.form[self.C.PARAM_DEBUG]: b.text( ` article `) b._div(comment=self.CLASS_FEATURED_ITEM)
class SpringGraph(Container): # Get Constants->Config as class variable, so inheriting classes can redefine values. C = Container.C BLUEPRINT = BluePrint() def buildSpringGraph(self, id, root, width, height, **args): self.text( """<!--[if lte IE 8]><script type="text/javascript" src="excanvas.js"></script><![endif]-->""" ) self.script(src='http://s3.amazonaws.com/data.xierpalib.com/_root/' + self.C.PATH_SPRINGGRAPH_JS) self.script() self.output(""" function init_graph_%(id)s() { g = new Graph(document.getElementById("_ctx")); """ % {'id': id}) # Build the nodes, edges and set of unique node models nodesd, edgesjs = self.getSpringGraphNode(root, **args) self.output("""var nodes = {""") first = True for nodeid, nodeparams in nodesd.items(): if not first: self.output(',\n') first = False self.output(""" "%s": %s""" % (nodeid, self.TX.args2JsArguments(**nodeparams))) self.output("""};\n""") # Generate list with edges and build list with used unique nodes self.output("""var edges = [""") first = True for nodeid1, nodeid2, edgeparams in edgesjs: if not first: self.output(',\n') first = False self.output( """["%s", "%s", %s]""" % (nodeid1, nodeid2, self.TX.args2JsArguments(**edgeparams))) self.output('];\n') self.output(""" for (var id in nodes) { g.addNode(id, nodes[id]); } for (var i=0; i < edges.length; i++) { var n1 = g.nodeset[edges[i][0]]; var n2 = g.nodeset[edges[i][1]]; g.addEdge(n1, n2, edges[i][2]); } for (var i=0; i < g.nodes.length; i++) { var n = g.nodes[i]; n.radius = n.radius + n.radius * n.weight; } for (var i=0; i < g.nodes.length; i++) { var e = g.nodes[i].edges(); if (e.length == 1) { e[0].length *= 8; } } g.prune(0); g.layout.k = 2.0; // Force constant (= edge length). g.layout.force = 0.05; // Repulsive strength. g.layout.repulsion = 150; // Repulsive radius. g.betweennessCentrality(); g.eigenvectorCentrality(); g.loop({frames:500, fps:20, ipf:4, weighted:0.5, directed:false}); }""") self._script() self.style() self.output( """.node-label { margin-left:12px;font: %(labelsize)spx sans-serif; }""" % {'labelsize': args.get('labelsize') or 11}) self._style() self.div(style="width:%(width)spx; height:%(height)spx;" % { 'width': width, 'height': height }) self.canvas(id="_ctx", width=width, height=height) self._canvas() self._div() self.script() self.output('init_graph_%(id)s();' % {'id': id}) self._script() def getSpringGraphNode(self, root, nodesd=None, edgesjs=None, **args): nodesd = nodesd or {} edgesjs = edgesjs or [] label = root.label or root.name or root.id if root.isRoot(): d = { 'label': label, 'radius': args.get('rootradius', 10), 'fill': args.get('rootfill', 'rgba(240,240,240,0.7)') } else: d = { 'label': label, 'radius': args.get('rootradius', 4), 'fill': args.get('fill', 'rgba(220,220,220,0.7)') } nodesd[root.id] = d for node in root.getNodes(): edgesjs.append((root.id, node.id, { 'stroke': args.get('stroke', 1) })) self.getSpringGraphNode(node, nodesd, edgesjs, **args) return nodesd, edgesjs
class FeaturedByDiapText(FeaturedByText): u"""As FeaturedByText, but default on a dark background.""" # Get Constants->Config as class variable, so inheriting classes can redefine values. C = FeaturedByText.C LEVELSIZE = Em(0.9) AUTHORSIZE = Em(1.2) CATEGORYSIZE = Em(1.4) AUTHORCOLOR = Color('#828487') CATEGORYCOLOR = AUTHORCOLOR LABELCOLOR = AUTHORCOLOR NAMECOLOR= Color('#66696C') SUMMARYCOLOR= Color('#E0E0E0') BACKGROUNDCOLOR = Color('#202020') LEVELCOLOR = Color('#6294D0') NAMECOLOR = Color('#E1E1E1') AUTHORCOLOR = Color('#B2B4B7') # Inherit from the super class blueprint, and then change some of the parameters. BLUEPRINT = BluePrint(FeaturedByText.BLUEPRINT, # Layout alternatives showPoster=True, doc_showPoster=u'Boolean flag to indicate if the poster of the article should be shown.', showCategory=True, doc_showCategory=u'Boolean flag to indicate if the category of this article should be shown.', # Selection stuff # Index of first and amount of selected features for this component start=0, doc_start=u'Index of first selected item to feature.', count=10, doc_count=u'Number of selected items to feature.', itemRandom=True, doc_itemRandom=u'Choose random from the selected items.', # Label stuff label=None, doc_label=u'Label string.', labelSize=Em(2.2), doc_labelSize=u'Label size.', labelColor=Color('#828487'), doc_labelColor=u'Label color.', labelMarginBottom=Em(0.5), labelMarginTop=Em(0.3), # Poster posterWidth='40%', doc_posterWidth=u'Width of the poster image, to allow text to flow around.', # Layout stuff colWidth=8, # Default amount of columns for this component backgroundColor=Color(BACKGROUNDCOLOR), doc_backgroundColor=u'Background color of the component. Default is a dark gray.', # Level stuff, handle local fontsize and lineheight here, related to the item size showLevel=True, genericLevel='Generic', # Show generic level if level is omitted in data. levelColor=Color(LEVELCOLOR), doc_levelColor=u'Color of the level indicator.', levelSize=LEVELSIZE, levelWeight=C.BOLD, levelMarginTop=Em(0.5), # Category stuff in h5 categoryColor=CATEGORYCOLOR, categorySize=Em(1.8), categoryLineHeight=Em(1.2), categoryWeight=C.BOLD, # Name stuff in h2 nameSize=Em(1.8), nameLineHeight=Em(1.1), nameWeight=None, # Default inheriting from the main weight. nameColor=Color(NAMECOLOR), nameMarginBottom=Em(0.2), nameMarginTop=0, nameDisplay=C.BLOCK, # Author stuff in h6 authorSize=AUTHORSIZE, authorWeight=C.NORMAL, authorColor=Color(AUTHORCOLOR), # Inheriting from the main color as default authorDisplay=C.BLOCK, authorLineHeight=Em(1.4), # Summary stuff summaryColor=C.WHITE, summaryMarginTop=Em(0.4), summaryMarginBottom=Em(0.5), # Tablet stuff tabletLabelSize=Em(1.5), # Mobile stuff mobileDisplay=C.NONE, mobilePaddingTop=Em(2), mobilePaddingBottom=Em(0.5), mobilePaddingLeft=Em(0.5), mobilePaddingRight=Em(0.5), mobileMarginTop=Em(2), mobileMarginBottom=Em(0.5), mobileMarginLeft=Em(0.5), mobileMarginRight=Em(0.5), mobileFloat=C.NONE, )
class FeaturedByImage(FeaturedBase): u"""The @FeaturedByImage@ feature component, shows a featured article by its poster image on full width of the component. If there is no poster image defined in the article meta data, then the first image in the article is used here. The image is a link to the article page. Respectively the binary flags @BluePrint@ *showLevel*, *showTitle* and *showTopic* will enable the level of the article (as defined in the article source @$level@), the article title (@$title@) and topic (@$topic), of set to @True@.""" # Get Constants->Config as class variable, so inheriting classes can redefine values. C = FeaturedBase.C LEVELSIZE = Em(0.9) AUTHORSIZE = Em(1.2) CATEGORYSIZE = Em(1.4) AUTHORCOLOR = Color('#828487') CATEGORYCOLOR = AUTHORCOLOR LABELCOLOR = AUTHORCOLOR NAMECOLOR = Color('#66696C') SUMMARYCOLOR = Color('#202020') BLUEPRINT = BluePrint( FeaturedBase.BLUEPRINT, # Layout selection parameters. showPoster=True, doc_showPoster= u'Boolean flag to indicate if the poster of the article should be shown.', showLevel=False, doc_showLevel=u'Boolean flag to show the level field of the article.', showTitle=True, doc_showTitle=u'Boolean flag to show the title of the article.', showHeadline=True, doc_showHeadline=u'Boolean flag to show the headline of the article.', showTopic=True, doc_showTopic=u'Boolean flag to show the topic of the article.', # Selection stuff start=0, doc_start=u'Index of first selected item to feature.', count=3, doc_count=u'Number of selected items to feature.', # Container component layout stuff width=Perc(30), doc_width=u'Overall width of the component.', widthMobile=Perc(100), doc_widthMobile=u'Overall width of the component for mobile.', backgroundColor=None, doc_backgroundColor=u'Background color of the component.', display=C.BLOCK, doc_display=u'Display status of the component', displayMobile=C.BLOCK, doc_displayMobile=u'Display status of the component for mobile.', float=C.LEFT, doc_float=u'Float status of the component.', floatMobile=C.LEFT, doc_floatMobile=u'Float status of the component for mobile.', padding=0, doc_padding=u'Padding of the component content.', # Item/article stuff itemDisplay=C.BLOCK, doc_itemDisplay=u'Display type of the item/article image cell.', itemBackgroundColor=Color('#E0E0E0'), doc_itemBackgroundColor= u'Background color of the item/article image cell.', itemClear=C.NONE, doc_itemClear=u'Floating clear of item/article image cell.', itemMarginBottom=Em(0.5), doc_itemMarginBottom=u'Margin bottom of item/article image cell.', itemPadding=Padding(Em(0.5)), doc_itemPadding=u'Padding of the item/article image cell.', # Level levelFormat='%s level', doc_levelFormat= u'Python string pattern as level indicator. Takes level string as parameter.', genericLevel=None, doc_genericLevel= u'Generic level flag, overruling the article level field.', levelColor=Color('#222'), doc_levelColor=u'Color of the level indicator.', levelSize=Em(0.8), doc_levelSize=u'Font size of the level indicator.', levelWeight=C.BOLD, doc_levelWeight=u'Font weight of the level indicator.', levelMarginTop=Em(0.2), doc_levelMarginTop=u'Margin top of the level indicator.', levelMarginBottom=Em(0.2), doc_levelMarginBottom=u'Margin bottom of the level indicator.', # Title titleFontFamily=None, doc_titleFontFamily=u'Font family of the article title.', titleColor=('#444'), doc_titleColor=u'Color of the article title.', titleSize=Em(1.1), doc_titleSize=u'Font size of the article title.', titleWeight=C.NORMAL, doc_titleWeight=u'Font weight of the article title.', titleLineHeight=Em(1.2), doc_titleLineHeight=u'Line height of the article title.', # Headline headlinePaddingTop=Em(0.1), doc_headlinePaddingTop=u'Padding between image and headline.', headlineFontFamily=None, doc_headlineFontFamily=u'Font family of the article headline.', headlineColor=('#444'), doc_headlineColor=u'Color of the article headline.', headlineSize=Em(1.8), doc_headlineSize=u'Font size of the article headline.', headlineWeight=C.NORMAL, doc_headlineWeight=u'Font weight of the article headline.', headlineLineHeight=Em(1.2), doc_headlineLineHeight=u'Line height of the article headline.', # Topic topicColor=Color('#444'), doc_topicColor=u'Color of the article topic.', topicSize=Em(0.8), doc_topicSize=u'Font size of the article topic.', topicWeight=C.NORMAL, doc_topicWeight=u'Font weight of the article topic.', topicLineHeight=Em(1.2), doc_topicLineHeight=u'Line height of the article topic.', ) def buildFeatured(self, b, articles): s = self.style b.div( class_=self.getClassName(), width=s.width, backgroundcolor=s.backgroundColor, display=s.display, float=s.float, padding=s.padding, media=Media(max=self.C.M_MOBILE_MAX, width=s.widthMobile, display=s.displayMobile, float=s.floatMobile), ) for article in articles: if s.showPoster and article.poster: self.buildFeaturedImage(b, article) b._div() def buildFeaturedImage(self, b, article): s = self.style b.div( class_=self.C.CLASS_FEATUREDITEM, display=s.itemDisplay, backgroundcolor=s.itemBackgroundColor, padding=s.itemPadding, clear=s.itemClear, marginbottom=s.itemMarginBottom, margintop=s.itemMarginTop, ) b.a(href='/%s-%s' % (self.C.PARAM_ARTICLE, article.id)) b.img(class_=(self.C.CLASS_MAXWIDTH, 'featuredImage'), height=s.AUTO, src=article.poster) if s.showLevel or s.genericLevel: # Format the level indicator b.h5(class_=self.C.CLASS_LEVEL, color=s.levelColor, fontsize=s.levelSize, fontweight=s.levelWeight, margintop=s.levelMarginTop, marginbottom=s.levelMarginBottom) b.text(s.levelFormat % (article.level or s.genericLevel)) b._h5() if s.showTitle and article.title: # Format the article title b.h4(class_=self.C.CLASS_TITLE, fontfamily=s.titleFontFamily, color=s.titleColor, fontsize=s.titleSize, fontweight=s.titleWeight, lineheight=s.titleLineHeight) b.text(article.title) b._h4() if s.showHeadline and article.headline: # Format the article headline b.h4(class_=self.C.CLASS_HEADLINE, fontfamily=s.headlineFontFamily, color=s.headlineColor, fontsize=s.headlineSize, fontweight=s.headlineWeight, lineheight=s.headlineLineHeight, paddingtop=s.headlinePaddingTop) b.text(article.headline) b._h4() if s.showTopic and article.topic is not None: # Elements must be defined in global style b.h5(class_=self.C.CLASS_TOPIC, color=s.topicColor, fontsize=s.topicSize, fontweight=s.topicWeight, lineheight=s.topicLineHeight) if isinstance(article.topic, basestring): b.text(article.topic) else: self.buildElement(b, article.topic) b._h5() b._a() b._div(comment=self.C.CLASS_FEATUREDITEM)
class ArticleSideBar(ArticleColumn): u"""The *ArticleSideBar* class implements a component that can show meta information of the current article, such as the chapter navigation (if the boolean flag @self.style.splitChapters@ is set to @true@), or links to the @article.featured@ articles. The standard functions in the @ArticleSideBar@ can be turned on/off by boolean style flags. E.g. @self.style.showChapterNavigation@.""" # Get Constants->Config as class variable, so inheriting classes can redefine values. C = ArticleColumn.C BLUEPRINT = BluePrint( homeLink=True, doc_homeLink= u'If True, add the link to the home page above the list of featured articles.', # Layout stuff # TODO: 70%+20% doesn't add to 100, but cannot be larger. Margins adding up? width=Perc(20), doc_width=u'Width of the main column inside the row.', widthMobile=Perc(100), doc_widthMobile=u'Width of the main column inside the row for mobile.', # Column padding=Em(0.35), doc_padding=u'Padding of the main column container.', backroundColor=Color('white'), doc_backgroundColor=u'Background color of side bar container.', # Chapter navigation showChapterNavigation=False, doc_showChapterNavigation= u'Boolean flag to indicate that chapter navigation must be shown. If the article source has chapters, but the main article component @article.style.splitChapters@ is @False@, then in-page navigation will be made.', chapterLabel='Chapters', doc_chapterLabel=u'Title of chapter navigation, shown as h2 heading.', chapterNameSize=Em(1.2), doc_chapterNameSize=u'Font size of chapter title.', showChapterSummaryOnMax=10, # Not show summary if more than 10 chapters mobileChapterButtonColor=Color(C.WHITE), doc_mobileChapterButtonColor=u'Color of chapter button for mobile.', mobileChapterButtonBackgroundColor=Color('#444'), doc_mobileChapterButtonBackgroundColor= u'Background color of chapter button for mobile.', ) def getArticleUrlId(self, b): u"""Answer the url parameter of the current page from @b.e.form[self.C.PARAM_ARTICLE]@.""" return b.e.form[self.C.PARAM_ARTICLE] # /article-xxx def buildColumn(self, b): u"""Build meta information from the article. @@@ Add to style that calling site can change the order.""" s = self.style article = self.adapter.getArticle(id=b.getCurrentArticleId(), url=b.e.path) b.div( class_=self.getClassName(), width=s.width, float=self.C.LEFT, backgroundcolor=s.backroundColor, padding=s.padding, media=Media(max=self.C.M_MOBILE_MAX, width=s.widthMobile, display=self.C.BLOCK, float=self.C.NONE), ) if article is None: self.buildArticleSideBarStyle(b) else: # There is a valid article selection self.buildArticleFeatures(b, article) if s.showChapterNavigation: # If chapters are split, then add the chapter navigation here. #self.buildMobileChapterNavigation(b, articleData) self.buildChapterNavigation(b, article) #if s.showFootNotes: # self.buildFootNotes(b, article) b._div(comment=self.getClassName()) def buildArticleFeatures(self, b, article): u"""Build the links to the featured article of the current article as stored in @article.featured@.""" s = self.style featuredArticles = [] if article is not None and article.featured: for featured in article.featured: featuredArticle = self.adapter.getArticle(id=featured) # Check if found and not referring to current article. if not featuredArticle in (None, article): featuredArticles.append(featuredArticle) if s.homeLink: b.p() b.a(href='/index') b.text('Home') b._a() b._p() # If there are featured articles if featuredArticles: b.h3() b.text('Featured') b._h3() for featuredArticle in featuredArticles: b.p() b.a(href='%s-%s' % (self.C.PARAM_ARTICLE, featuredArticle.id)) b.text(featuredArticle.title) b._a() b._p() def buildArticleSideBarStyle(self, b): u"""Build the styles for the articles side bar. # @@@ Clean up, using model for article side bar?""" s = self.style # <h2>Featured</h2> b.h3() b._h3() # <ul><li>...</li></ul> b.ul() b.li(backgroundcolor=s.mobileChapterButtonColor) # <a>Chapter name</a> b.h2(fontsize=Em(2), lineheight=Em(1.2), marginbottom=Em(0.2), margintop=Em(0.2)) b.a(fontsize=s.summaryNameSize, color=s.mobileChapterButtonColor) b._a() b._h2() b._li() b._ul() b._div(comment=self.C.CLASS_MOBILECHAPTERNAVIGATION ) # Article mobile chapter navigation # <div class="chapterNavigation"> b.div(class_=self.C.CLASS_CHAPTERNAVIGATION, marginbottom=Em(0.5), display=s.mobileContainerDisplay, media=Media(max=self.C.M_MOBILE_MAX, display=self.C.NONE)) b.h4(fontsize=Em(1.1)) b._h4() b.ul() b.li() # <a>Chapter name</a> # TODO: h2 margintop not working? b.a(fontsize=s.summaryNameSize, color=s.summaryNameColor) b.h2(fontsize=s.chapterNameSize, color=s.chapterNameColor, lineheight=Em(1.2), marginbottom=Em(0.2), margintop=Em(0.4)) b._h2() b._a() b._li() b._ul() def buildMobileChapterNavigation(self, b, article): s = self.style chapters = article.chapters if chapters and len(chapters) > 1: b.div(class_=self.C.CLASS_MOBILECHAPTERNAVIGATION) b.ul() for index, chapter in enumerate(chapters): b.li() b.a( class_=self.C.CLASS_NAME, href='/%s-%s/%s-%s' % (self.C.PARAM_ARTICLE, article.id, self.C.PARAM_CHAPTER, index), ) chapterTitle = chapter.find( './meta/title') # @@@ Add this as adapter query if chapterTitle is None: # No title, add a default chapter title (not in the right style) b.text('Chapter %d' % index) else: self.buildElement(b, chapterTitle) b._a() b._li() b._ul() b._div() def buildChapterNavigation(self, b, article): u"""If there is more than one chapter in the article, automatically create a chapter navigation in the sidebar. The title and the summary are links to a page of the same article, for the defined chapter index.""" s = self.style chapters = article.chapters if chapters and len(chapters) > 1: b.div(class_=self.C.CLASS_CHAPTERNAVIGATION) b.h4() b.text(s.chapterLabel) b._h4() b.ul() for index, chapter in enumerate(chapters): b.li(margintop=Em(0.5)) b.a( class_=self.C.CLASS_NAME, href='/%s-%s/%s-%s' % (self.C.PARAM_ARTICLE, article.id, self.C.PARAM_CHAPTER, index), ) # TODO: derive chapter title in the proper way from <h2> using re chapterTitle = chapter.find('./meta/title') if chapterTitle == -1: # No title, add a default chapter title (not in the right style) b.text('Chapter %d' % (index + 1)) else: self.buildElement(b, chapterTitle) if len(chapters) < s.showChapterSummaryOnMax: summary = chapter.find( './meta/summary') # @@@ Add this as adapter query if summary != -1: self.buildElement(b, summary) b._a() b._li() b._ul() b._div() # .chapterNavigation def XXXbuildFootNotes(self, b, article): u"""Build the list of footnotes with links to the position in the article where they are defined.""" s = self.style chapterIndex = self.getChapterIndex(b, article) if article.footnotes: footnotes = article.footnotes[ chapterIndex] # Get footnotes of this chapter if footnotes: b.div(class_=self.C.CLASS_FOOTNOTES) b.h4() b.text(s.footnoteLabel) b._h4() b.ol( ) # Not displaying the index number here, how to solve with style? for index, footnote in enumerate(footnotes): b.li(fontsize=Em(0.9), color='red') b.a(href='#fnref:footnoteRef%d' % (index + 1), name='fnref:footnote%d' % (index + 1)) # Hard copy the index number, as <ol> doesn't show now. b.text( '%d | %s %s' % (index + 1, footnote.text, s.footnoteArrow or u'↩')) # Process element, instead of plain text. b._a() b._li() b._ol() b._div() # .footnotes
class DbDMobileNavigation(MobileNavigation): BLUEPRINT = BluePrint(MobileNavigation.BLUEPRINT, # Layout alternatives )
class Logo(Component): # Get Constants->Config as class variable, so inheriting classes can redefine values. C = Component.C BLUEPRINT = BluePrint( # Layout stuff colWidth=4, doc_colWidth=u'Default amount of columns for this component.', maxWidth=Perc(100), doc_maxWidth=u'Maximal width of the component', minWidth=Perc(100), doc_minWidth=u'Minimal width of the component', # Logo data can be set as through text/style attribute or through the adapter. # The optional url creates a link from the logo, e.g. to the home page. text=None, doc_text=u'Optional text of the logo. Otherwise query the adapter.', src=None, doc_src=u'Optional src for logo image. Otherwise query the adapter.', url=None, doc_url=u'Optional url for logo link. Otherwise query the adapter.', # Logo stuff width=280, doc_logoWidth=u'Logo width', backgroundColor=None, doc_backgroundColor=u'Background color of the logo component.', height=C.AUTO, doc_height=u'Logo height', marginTop=0, doc_marginTop=u'Logo margin top', marginLeft=0, doc_marginLeft=u'Logo margin left', marginRight=Perc(1.8), doc_marginRight=u'Logo margin right', marginBottom=0, doc_marginBottom=u'Logo margin bottom', logoFloat=C.LEFT, doc_logoFloat=u'Logo div float', # H2 heading, in case style.text is defined and not style.src (for an image) fontFamily=C.LOGOFAMILY, doc_fontFamily=u'h2 font family', fontSize=Em(2.9), doc_fontSize=u'h2 Logo font size', lineHeight=Em(1.4), doc_lineHeight=u'h2 leading', fontWeight=C.BOLD, doc_fontWeight=u'h2 font weight', fontStyle=None, doc_fontStyle=u'h2 font style', paddingTop=Em(0.2), doc_paddingTop=u'h2 padding top', paddingBottom=Em(0.2), doc_paddingBottom=u'h2 padding bottom', color=Color('#323A47'), doc_color=u'h2 color', ) def buildBlock(self, b): s = self.style colClass = self.getColClass(s.colWidth) b.div(class_=colClass, float=s.logoFloat, marginleft=s.marginLeft, backgroundcolor=s.backgroundColor, marginright=s.marginRight, margintop=s.marginTop, marginbottom=s.marginBottom) # @text: text to show instead of the logo image. # @url: url of href link. If None no link is made # @src: url of the image source. data = self.adapter.getLogo() if s.text: data.text = s.text data.src = None if s.src: data.src = s.src data.text = None if s.url: data.url = s.url if data.url: b.a(href=data.url) if data.src: b.img(src=data.src, width=s.width, maxwidth=s.maxWidth, height=s.height) else: b.h2( fontsize=s.fontSize, lineheight=s.lineHeight, fontfamily=s.fontFamily, fontWeight=s.h2Weight, fontStyle=s.h2Style, color=s.color, paddingtop=s.paddingTop, paddingbottom=s.paddingBottom, ) b.text(data.text) b._h2() if data.url: b._a() b._div(comment=colClass)
class MobileNavigation(Navigation): u"""The **MobileNavigation** only shows in mobile screen mode.""" # Get Constants->Config as class variable, so inheriting classes can redefine values. C = Navigation.C BLUEPRINT = BluePrint( colWidth=12, # Display stuff display=C.NONE, doc_display=u'Display type', displayMobile=C.BLOCK, doc_displayMobile=u'Display type for mobile.', # Container stuff width=None, doc_width=u'Mobile navigation container width.', minWidth=0, doc_minWidth=u'Mobile navigation container minimal width', # Navigation stuff backgroundColor=Color('#323A47'), doc_backgroundColor='Mobile navigation background color.', fontSize=Em(1.4), doc_fontSize=u'Mobile navigation font size.', lineHeight=Em(1.1), doc_lineHeight=u'Mobile navigation leading.', marginLeft=0, doc_marginLeft=u'Mobile navigation margin left.', marginRight=0, doc_marginRight=u'Mobile navigation margin right.', paddingLeft=0, doc_paddingLeft=u'Mobile navigation padding left.', # Row rowClass=C.CLASS_12COL, doc_rowClass=u'Class of the row.', # Item stuff start=0, doc_start= u'Start of the index of selected pages. Suggestion to the adapter.', count=20, doc_count=u'Preferred/max amount of pages, suggestion to the adapter.', menuHeight=Px(44), doc_menuHeight=u'Menu height.', menuMargin=0, doc_menuMargin=u'Menu margin.', menuBackgroundColor=Color('#323A47'), doc_menuBackgroundColor=u'Menu background color.', menuZIndex=Z(1000), doc_menuZIndex='Menu Z index', menuBorderBottom=Border('1 solid white'), doc_menuBorderBottom=u'Menu border bottom.', menuWidth=Perc(100), doc_menuWidth=u'Menu width.', # Nav stuff navWidth=Perc(30), doc_navWidth='Navigation width.', navDisplay=C.INLINEBLOCK, doc_navDisplay=u'Navigation display type.', navZIndex=Z(1000), doc_navZIndex='Navigation Z index.', # List item stuff listFontSize=None, # Menu menuType=C.LIST, doc_menuType= u'Default is plain navigation list. Set to “menu” for menu.', menuListBackgroundColor=Color('#828487'), menuIconUrl= '//data.doingbydesign.com.s3.amazonaws.com/_images/menu_icon.png', doc_menuIconUrl=u'Url of the menu icon', # Link stuff linkColor=C.WHITE, doc_linkColor=u'Link color', ) def buildBlock(self, b): s = self.style menuArticles = self.adapter.getMenu( id=self.C.ID_HOME) # Get data for home page from adapter. b.div(class_=(self.C.CLASS_CONTAINER, self.className), display=s.display, backgroundcolor=s.backgroundColor, width=s.width, marginleft=s.marginLeft, marginright=s.marginRight, paddingleft=s.paddingLeft, paddingright=s.paddingRight, media=(Media(max=self.C.M_MOBILE_MAX, display=s.displayMobile), )) b.snippet(self, 'navigation-mobile' ) # Allow PHP to create a snippet file from this block. colClass = self.getColClass(s.colWidth) #b.text(data.loop) # In case there is PHP looping code. Skip for CSS b.div(class_=colClass, width=self.C.AUTO, float=self.C.NONE, marginleft=Em(0.5), marginright=Em(0.5), paddingleft=Em(0.5), paddingright=Em(0.5)) b.div(id=self.C.ID_MOBILENAVWRAP, width=s.navWidth, display=s.navDisplay, zindex=s.navZIndex) b.div(id=self.C.ID_MENUICON, class_=self.C.CLASS_MENU, color=Color(self.C.WHITE), height=26, width=56, paddingtop=Em(0.6), cursor='pointer', display=self.C.INLINEBLOCK, marginright=0, top=0, left=0, fontsize=Px(13)) b.img(src=s.menuIconUrl, padding=0, margin=0, verticalalign=self.C.MIDDLE, maxwidth=Perc(50), height=self.C.AUTO) b._div(comment='#' + self.C.ID_MENUICON) # #menu-icon if menuArticles is None: b.error('No items in the adapter') else: b.ul(id=self.C.ID_NAV, backgroundcolor=s.menuListBackgroundColor, display=self.C.NONE, clear=self.C.BOTH, position=self.C.ABSOLUTE, top=s.menuHeight - 5, width=Perc(100), zindex=Z(2000), padding=0, margin=0, liststyletype=self.C.NONE, left=0, textalign=self.C.CENTER) homeArticle = self.adapter.getArticle(id=self.C.ID_HOME) for menuArticle in menuArticles: url = menuArticle.url if url is None: url = '/%s-%s' % (self.C.PARAM_ARTICLE, menuArticle.id) b.li(fontsize=s.listFontSize, paddingtop=Em(1.2), width=Perc(100), liststyletype=self.C.NONE, borderbottom=Border('1 solid white'), height=36, backgroundcolor=Color('#4890BC')) b.a(href=url, color=Color('#E8E8E8')) b.text( menuArticle.name or 'Untitled' ) # Show full name, otherwise use b.text(menu.tag or menu.name) b._a() b._li() b._ul() b._div(comment=self.C.ID_MOBILENAVWRAP) #b.a(href='/home', color='#E8E8E8') #b.text('Doing by Design') #b._a() b._div(comment=self.C.CLASS_12COL) #b.text(data._loop) # In case there is PHP looping code. Skip for CSS b._snippet(self) # In case PHP saved this block as snippet. b._div() # Final comment is automatic from component.selector