librelist archives

« back to archive

Overriding how page headers and article pages are rendered

Overriding how page headers and article pages are rendered

From:
James Abbott
Date:
2011-07-15 @ 14:40
Hi -

is there a way to override this point in page.haml:

%article(role="main")
  ~ @page.to_html(self)

so that one could have control over the article heading (allowing
extra CSS classes and nested elements?) Here's the desired output:

            <article role='main'>
                <h1 class="title" id='nesta_095_released'>
                    <span class="hand"></span>
                    <span>Nesta 0.9.5 released</span>
                </h1>
                <p>...</p>

(The markup will make sense when I release the theme I'm working on).

Also, I would like to style the above bit for category pages
differently from article pages (which the above snippet is).
Currently, both article page and category page headers are generated
by the same haml (above). What I'd like to have
for category pages is something along the lines of:

            <article role='main' class="category">
                <h1 id='awesomeness'>Awesomeness</h1>
                <p>
                    This is a page about awesomeness.
                </p>

Currently, I can target all these elements using CSS3 selectors:

article>h1+p

Trouble is, the above works for both kinds of articles - regular and
category pages - and doesn't allow for differentiated styling. To do
that, I'd need:

article>h1.title
article.category>h1
article.category>h1+p

Cheers,
James

Re: [nesta] Overriding how page headers and article pages are rendered

From:
Graham Ashton
Date:
2011-07-16 @ 14:03
On 15 Jul 2011, at 15:40, James Abbott wrote:

> is there a way to override this point in page.haml:
> 
> %article(role="main")
>  ~ @page.to_html(self)
> 

Not really. The Markdown or Textile processor runs .to_html on the entire 
contents of the document (once the metadata has been stripped off), so you
don't get a chance to inject anything into the DOM.

You could write an alternative version of .to_html, but that might not be 
the cleanest approach.

> so that one could have control over the article heading (allowing
> extra CSS classes and nested elements?) Here's the desired output:
> 
>            <article role='main'>
>                <h1 class="title" id='nesta_095_released'>
>                    <span class="hand"></span>
>                    <span>Nesta 0.9.5 released</span>
>                </h1>


Have you considered adding span.hand with JavaScript on page load? 
Obviously I'm not sure what it's for, but it looks like it might be the 
kind of DOM content that's there for presentational reasons, rather than 
semantic reasons?

> Also, I would like to style the above bit for category pages
> differently from article pages (which the above snippet is).

Have you thought about adding a class to the body element to denote 
whether to apply styles for an article, or for a category?

It's quite easy to do by adding a metadata key to control the class that 
should be added to the body tag.

In an action in the theme's app.rb you can set an instance variable like 
this (shortly after @page has been set):

  @body_class = @page.date.nil ? 'category' : 'article'

Access that in your layout, and you're home and dry. I'd look at writing 
some JavaScript to add the span.hand based on a similar rule, if it's 
there for presentational reasons.

Hope that helps...

Graham

Re: [nesta] Overriding how page headers and article pages are rendered

From:
James Abbott
Date:
2011-07-18 @ 13:22
>
> Have you considered adding span.hand with JavaScript on page load?
> Obviously I'm not sure what it's for, but it looks like it might be the kind
> of DOM content that's there for presentational reasons, rather than semantic
> reasons?
>

Yes, the span.hand is there for decorative reasons, and I wrap the text in
the title in an extra span to replicate the effect that links have on the
normal flow:

                 <h1>
>                    <a href='/blog/version-0-9-5'>Nesta 0.9.5 released</a>
>                  </h1>
>

If I use JavaScript it'll be only as the last resort, maybe I'll rethink the
design instead. I'm not a huge fan of using JS for styling purposes. Anyway,
this issue isn't as important as the next one:

Have you thought about adding a class to the body element to denote whether
> to apply styles for an article, or for a category?
>

Using class on the body is a good solution, I didn't think of that (although
I've been using it a lot). There is one important caveat though. If I'm not
mistaken, this code:

@body_class = @page.date.nil ? 'category' : 'article'

would mark all pages that aren't articles as "category pages". But I want to
make a further distinction within those latter ones (let's call them static
pages). There are static pages that are category pages and there are static
pages that are "leaf pages", ie are end points in terms of content (they
only feature their own content). What I want to be able to do is to style
them differently.

Here's an example of a category page and a "leaf page" and their respective
styles:

http://www.alistapart.com/topics/code/css/
http://www.alistapart.com/articles/css-floats-101/

The design communicates very clearly kind of page it is - a gateway to other
pages or an article - that's the effect I want to replicate.

Cheers,
James

PS. Maybe one could add a metadata field to Nesta (the tag "Category"),
which, when set, would add make the body classes look like this:

<body class="category page">

This would work on top of this:

@body_class = @page.date.nil ? 'page' : 'article'

So one would have both

<body class="page">
and
<body class="category page">

for each appropriate case? The HTML looks very semantic, and would allow me
to style these two very efficiently.

PPS. "CSS3 selectors" in my previous email was rubbish. Those are CSS 2.1
selectors.







On Sat, Jul 16, 2011 at 4:03 PM, Graham Ashton <graham@effectif.com> wrote:
> On 15 Jul 2011, at 15:40, James Abbott wrote:
>
>> is there a way to override this point in page.haml:
>>
>> %article(role="main")
>>  ~ @page.to_html(self)
>>
>
> Not really. The Markdown or Textile processor runs .to_html on the entire
contents of the document (once the metadata has been stripped off), so you
don't get a chance to inject anything into the DOM.
>
> You could write an alternative version of .to_html, but that might not be
the cleanest approach.
>
>> so that one could have control over the article heading (allowing
>> extra CSS classes and nested elements?) Here's the desired output:
>>
>>            <article role='main'>
>>                <h1 class="title" id='nesta_095_released'>
>>                    <span class="hand"></span>
>>                    <span>Nesta 0.9.5 released</span>
>>                </h1>
>
>
> Have you considered adding span.hand with JavaScript on page load?
Obviously I'm not sure what it's for, but it looks like it might be the kind
of DOM content that's there for presentational reasons, rather than semantic
reasons?
>
>> Also, I would like to style the above bit for category pages
>> differently from article pages (which the above snippet is).
>
> Have you thought about adding a class to the body element to denote
whether to apply styles for an article, or for a category?
>
> It's quite easy to do by adding a metadata key to control the class that
should be added to the body tag.
>
> In an action in the theme's app.rb you can set an instance variable like
this (shortly after @page has been set):
>
>  @body_class = @page.date.nil ? 'category' : 'article'
>
> Access that in your layout, and you're home and dry. I'd look at writing
some JavaScript to add the span.hand based on a similar rule, if it's there
for presentational reasons.
>
> Hope that helps...
>
> Graham
>

Re: [nesta] Overriding how page headers and article pages are rendered

From:
Graham Ashton
Date:
2011-07-19 @ 16:48
On 18 Jul 2011, at 14:22, James Abbott wrote:

> There are static pages that are category pages and there are static 
pages that are "leaf pages", ie are end points in terms of content (they 
only feature their own content). What I want to be able to do is to style 
them differently.

I suspect that a category page (in the context of your design) is only a 
category page if it has some other pages or articles assigned to it. If 
so, why not set the class on the body tag as a function of whether or not 
any articles (or non-article pages) are assigned to it?

A @page that isn't an article, and that has no other pages assigned to it,
will return true to both these tests:

  @page.pages.empty?
  @page.articles.empty?

Have a browse of the methods in models.rb that defines those methods and 
it should be fairly clear how they work:

https://github.com/gma/nesta/blob/master/lib/nesta/models.rb#L266

Re: [nesta] Overriding how page headers and article pages are rendered

From:
James Abbott
Date:
2011-07-20 @ 13:17
>
> A @page that isn't an article, and that has no other pages assigned to it,
> will return true to both these tests:
>
>  @page.pages.empty?
>  @page.articles.empty?
>

Brilliant - that's exactly what I needed. Wasn't aware that these methods
existed.

I've imported app.rb into the root directory and am defining @body_class in
the get '*' method:

      @page = Nesta::Page.find_by_path(File.join(parts))
>       raise Sinatra::NotFound if @page.nil?
>       @title = @page.title
>       @body_class = @page.date.nil ? 'page' : 'article'
>       @body_class = "foo"
>

In layout.haml:

%body{:class => "#{@body_class}"}
>

For some reason, my layout.haml doesn't access this variable - the above
code generates a body element with an empty class in the HTML output:

 <body class=''>

I'm probably doing something wrong in terms of what goes into app.rb. How
much of it should be removed - I guess there's no need to re-include all the
methods I don't redefine?

/ James


On Tue, Jul 19, 2011 at 6:48 PM, Graham Ashton <graham@effectif.com> wrote:

> On 18 Jul 2011, at 14:22, James Abbott wrote:
>
> > There are static pages that are category pages and there are static pages
> that are "leaf pages", ie are end points in terms of content (they only
> feature their own content). What I want to be able to do is to style them
> differently.
>
> I suspect that a category page (in the context of your design) is only a
> category page if it has some other pages or articles assigned to it. If so,
> why not set the class on the body tag as a function of whether or not any
> articles (or non-article pages) are assigned to it?
>
> A @page that isn't an article, and that has no other pages assigned to it,
> will return true to both these tests:
>
>  @page.pages.empty?
>  @page.articles.empty?
>
> Have a browse of the methods in models.rb that defines those methods and it
> should be fairly clear how they work:
>
> https://github.com/gma/nesta/blob/master/lib/nesta/models.rb#L266
>

Re: [nesta] Overriding how page headers and article pages are rendered

From:
Graham Ashton
Date:
2011-07-20 @ 13:55
On 20 Jul 2011, at 14:17, James Abbott wrote:

> I'm probably doing something wrong in terms of what goes into app.rb.

Probably best to post your entire app.rb file.

> How much of it should be removed - I guess there's no need to re-include
all the methods I don't redefine?

Sinatra will stop on the first block of routing code it finds that matches
the current request. Nesta is configured to load actions in ./app.rb 
before it looks in the theme's app.rb, and finally in the default app.rb 
file that ships with Sinatra.

The net result is that any catch all "route" in ./app.rb will prevent the 
routes in the other app.rb files from getting looked at, so it's a good 
idea to copy all the routes over.

This has nothing to do with your @body_class problem though.

I'd try raising an exception next to where @body_class was assigned, just 
to check whether your code is getting executed (or use the ruby-debug or 
pry gems to stop the interpreter in it's tracks so you can have a poke 
about).

Re: [nesta] Overriding how page headers and article pages are rendered

From:
Graham Ashton
Date:
2011-07-20 @ 14:02
On 20 Jul 2011, at 14:55, Graham Ashton wrote:

> default app.rb file that ships with Sinatra.

Oops, I obviously meant "that ships with Nesta".

Re: [nesta] Overriding how page headers and article pages are rendered

From:
James Abbott
Date:
2011-07-20 @ 15:07
>
> Probably best to post your entire app.rb file.
>

Sure:
https://gist.github.com/1095120

/ James

On Wed, Jul 20, 2011 at 3:55 PM, Graham Ashton <graham@effectif.com> wrote:

> On 20 Jul 2011, at 14:17, James Abbott wrote:
>
> > I'm probably doing something wrong in terms of what goes into app.rb.
>
> Probably best to post your entire app.rb file.
>
> > How much of it should be removed - I guess there's no need to re-include
> all the methods I don't redefine?
>
> Sinatra will stop on the first block of routing code it finds that matches
> the current request. Nesta is configured to load actions in ./app.rb before
> it looks in the theme's app.rb, and finally in the default app.rb file that
> ships with Sinatra.
>
> The net result is that any catch all "route" in ./app.rb will prevent the
> routes in the other app.rb files from getting looked at, so it's a good idea
> to copy all the routes over.
>
> This has nothing to do with your @body_class problem though.
>
> I'd try raising an exception next to where @body_class was assigned, just
> to check whether your code is getting executed (or use the ruby-debug or pry
> gems to stop the interpreter in it's tracks so you can have a poke about).
>

Re: [nesta] Overriding how page headers and article pages are rendered

From:
Graham Ashton
Date:
2011-07-20 @ 16:02
On 20 Jul 2011, at 16:07, James Abbott wrote:

> Probably best to post your entire app.rb file.
>  
> Sure:
> https://gist.github.com/1095120

There's no need to include the entire contents of the default one; the 
intent in app.rb is just to redefine things that need redefining. It 
doesn't have to do wholesale replacement, but can just do addition.

Try this:

https://gist.github.com/1095235/a4e05d9c016f9bc332b057dab4b36564b1573379

Add a helpers block back in if you need to add helpers, otherwise there's no need.

No idea if that'll fix it for you, but it's well worth a go.

All the `get '/path' do` blocks before the default route are only in there
so that the default route doesn't try (and fail) to respond to things it 
doesn't know how to handle.

This area of Nesta (or rather, extending its routing actions like this) 
could be improved, but I haven't come up with a clean approach yet.

Re: [nesta] Overriding how page headers and article pages are rendered

From:
James Abbott
Date:
2011-07-21 @ 07:05
Excellent; it works now. Those paths at the top were the problem - the code
in the default route didn't run at all, otherwise @body_class = "foo" would
have worked.

I kept getting a weird NilClass exception until I realized it was not
page.date.nil but page.date.nil?, and then everything fell into place:

      @body_class = @page.date.nil? ? 'page' : 'article'
>       @body_class = 'category ' + @body_class unless (@page.pages.empty?
> and @page.articles.empty?)
>

This is great - it allows for a much fine-grained styling of various pages'
headers.

Regarding replicating the non-default routes in the custom app.rb, I can see
what you mean but can't see how this could be solved. The only thing that
comes to mind is to have a bunch of routes that would have priority no
matter what app.rb was executed - custom, Nesta's, or Sinatra's. These could
be extracted in a separate file and loaded before any other of these routes,
after which the mechanism would fall back to normal. Would this be possible
given the good practices for Sinatra?

/ James

On Wed, Jul 20, 2011 at 6:02 PM, Graham Ashton <graham@effectif.com> wrote:

> On 20 Jul 2011, at 16:07, James Abbott wrote:
>
> > Probably best to post your entire app.rb file.
> >
> > Sure:
> > https://gist.github.com/1095120
>
> There's no need to include the entire contents of the default one; the
> intent in app.rb is just to redefine things that need redefining. It doesn't
> have to do wholesale replacement, but can just do addition.
>
> Try this:
>
> https://gist.github.com/1095235/a4e05d9c016f9bc332b057dab4b36564b1573379
>
> Add a helpers block back in if you need to add helpers, otherwise there's
> no need.
>
> No idea if that'll fix it for you, but it's well worth a go.
>
> All the `get '/path' do` blocks before the default route are only in there
> so that the default route doesn't try (and fail) to respond to things it
> doesn't know how to handle.
>
> This area of Nesta (or rather, extending its routing actions like this)
> could be improved, but I haven't come up with a clean approach yet.
>
>

Re: [nesta] Overriding how page headers and article pages are rendered

From:
Graham Ashton
Date:
2011-07-21 @ 10:51
On 21 Jul 2011, at 08:05, James Abbott wrote:

> Excellent; it works now. Those paths at the top were the problem

Did some of the docs give you the impression that you should just copy the
file in wholesale? If so, I want to fix that pronto.

> have a bunch of routes that would have priority no matter what app.rb 
was executed - custom, Nesta's, or Sinatra's. These could be extracted in 
a separate file and loaded before any other of these routes, after which 
the mechanism would fall back to normal.

It doesn't really work like that.

Think of the routing blocks as a stack. Every time you define a new one it
gets inserted at the bottom of the stack. When a request comes in Sinatra 
starts at the top of the stack, looking for a block of code that can 
handle the current request. If it comes across a block that can handle it 
executes the code, and that's it. There's no way for a routing block to 
say "hey, I can't do this after all". I think this is a good design. It's 
only routes with wildcards in them that eat up all the incoming requests, 
and they therefore need to be defined last.

I have had an idea while working out how to explain that to you though, 
and I may give it a try.

Re: [nesta] Overriding how page headers and article pages are rendered

From:
James Abbott
Date:
2011-07-21 @ 12:26
>
> Did some of the docs give you the impression that you should just copy the
> file in wholesale?
>

It was more the absence of clear-cut instructions that made me do it.
Initially, I tried to model my app.rb on this gist which had previously
appeared in this mailing list:

https://gist.github.com/920566

That didn't work however, so I copied it wholesale. Failing that, I asked
here.

Think of the routing blocks as a stack. Every time you define a new one it
> gets inserted at the bottom of the stack.
>

If a new route gets inserted at the bottom I suppose that makes it a queue
and not a stack? (Stack = add to top, remove from top). If each new route
was inserted at the bottom then the wildcard route would be evaluated ahead
of all others - because app.rb gets read and executed from top to bottom,
just like any other program? It is possible that I totally misinterpret your
explanation. I just wondered if there was not an "object-oriented" way of
organizing these routes. So that one could "mix in" special routes into
Nesta's default app.rb as a module. Then, I if define my own app.rb I only
need to declare in it those routes I plan to override. The special routes
would be inherited as the parent app.rb's mixin.

/ James


On Thu, Jul 21, 2011 at 12:51 PM, Graham Ashton <graham@effectif.com> wrote:

> On 21 Jul 2011, at 08:05, James Abbott wrote:
>
> > Excellent; it works now. Those paths at the top were the problem
>
> Did some of the docs give you the impression that you should just copy the
> file in wholesale? If so, I want to fix that pronto.
>
> > have a bunch of routes that would have priority no matter what app.rb was
> executed - custom, Nesta's, or Sinatra's. These could be extracted in a
> separate file and loaded before any other of these routes, after which the
> mechanism would fall back to normal.
>
> It doesn't really work like that.
>
> Think of the routing blocks as a stack. Every time you define a new one it
> gets inserted at the bottom of the stack. When a request comes in Sinatra
> starts at the top of the stack, looking for a block of code that can handle
> the current request. If it comes across a block that can handle it executes
> the code, and that's it. There's no way for a routing block to say "hey, I
> can't do this after all". I think this is a good design. It's only routes
> with wildcards in them that eat up all the incoming requests, and they
> therefore need to be defined last.
>
> I have had an idea while working out how to explain that to you though, and
> I may give it a try.
>

Re: [nesta] Overriding how page headers and article pages are rendered

From:
Graham Ashton
Date:
2011-07-21 @ 12:44
On 21 Jul 2011, at 13:26, James Abbott wrote:

> It was more the absence of clear-cut instructions that made me do it. 

Fair point.

> If a new route gets inserted at the bottom I suppose that makes it a 
queue and not a stack?

Everything in your own app.rb file goes in at the top. It has to, 
otherwise you wouldn't be able to override anything as the default route 
in Nesta's internal app.rb file would gobble up all requests. I'll need to
add API to allow you to say "treat this as my default route", which you 
can't do as it stands.

Re: [nesta] Overriding how page headers and article pages are rendered

From:
Graham Ashton
Date:
2011-07-21 @ 12:44
On 21 Jul 2011, at 13:26, James Abbott wrote:

> It was more the absence of clear-cut instructions that made me do it. 

Fair point.

> If a new route gets inserted at the bottom I suppose that makes it a 
queue and not a stack?

Everything in your own app.rb file goes in at the top. It has to, 
otherwise you wouldn't be able to override anything as the default route 
in Nesta's internal app.rb file would gobble up all requests. I'll need to
add API to allow you to say "treat this as my default route", which you 
can't do as it stands.

Deploying Incremental Gems to Heroku

From:
Brad Weslake
Date:
2011-07-19 @ 18:35
Hi all,

I've been playing around with Nesta in order to design a new website to be
hosted on Heroku:

	https://github.com/etc/bweslake

—and have found myself wanting to take advantage of some of the 
incremental changes that Graham has been making for version 0.9.6.  For 
example, I've written a menu style that highlights the current page.  I 
was able to make the changes go into effect on my local machine by pulling
Graham's changes from Github, rebuilding the Nesta gem locally, and 
restarting the site locally.  But I'm not sure how to do the same thing on
Heroku.  I gather that since the Nesta version of the rebuilt version is 
still 0.9.5, bundler doesn't think that anything needs to updated 
remotely.  How to change this?

I'm new at all this, so this may be a silly question.  Any advice appreciated!

Brad.

Re: [nesta] Deploying Incremental Gems to Heroku

From:
Graham Ashton
Date:
2011-07-19 @ 18:44
On 19 Jul 2011, at 19:35, Brad Weslake wrote:

> I've been playing around with Nesta...and have found myself wanting to 
take advantage of some of the incremental changes that Graham has been 
making for version 0.9.6.

Okay, I'll stop putting off releasing 0.9.6 (sorry folks, things have been busy).

I've got a patch to incorporate (I've not tried it yet, but if it looks 
good and goes in it'll make .scss files work by default) and then 0.9.6 
will be out. 

In the meantime, you can get bundler to build you the latest version from 
the master branch on GitHub by putting this in your Gemfile:

  gem 'nesta', :git => 'git://github.com/gma/nesta.git'

Until 0.9.6 comes out I see no reason why the code on master shouldn't be 
extremely stable.

Re: [nesta] Deploying Incremental Gems to Heroku

From:
Brad Weslake
Date:
2011-07-19 @ 19:32
> Okay, I'll stop putting off releasing 0.9.6 (sorry folks, things have 
been busy).

No need to apologise—as no doubt others are, I'm grateful for all your 
work on this.

> In the meantime, you can get bundler to build you the latest version 
from the master branch on GitHub by putting this in your Gemfile:
> 
>  gem 'nesta', :git => 'git://github.com/gma/nesta.git'

Perfect, thanks!

In case there are others as relatively clueless as me on here, I'll note 
that if you want to do this you need to run "bundle install" and then 
commit the updated Gemfile.lock before pushing to Heroku.

Brad.