Hi, all. I've been poking around, creating my own theme, and I'd like to
set the class of the body tag. I was going to do this by using Flags, with
something like:
%body{ class: 'main-nav-page' if @page.flagged_as?('main-nav-page') }
which would probably work, but I noticed that the layout file from the
Slate theme
(https://github.com/gma/nesta-theme-slate/blob/master/views/layout.haml)
already has:
%body{ class: @body_class }
How do I set this instance variable for each page? I thought maybe I could
use a simple Sinatra `before` helper, but the `@page` variable isn't set
yet at that point, so I can't check the page's flags. And an `after`
helper has no useful effect on the request's instance variables.
Why do I want this?
My theme has a prominent main nav bar, and having the title of a page
displayed both in the nav bar and on the page itself is repetitive and
unnecessary. Alas, adding a class to the first h1 on the page causes Nesta
to not use it as the page title (that is, it doesn't show up in the
navigation, created from the menu.txt file). This is arguably a bug; I
would be open to fixing this bug in addition to figuring out how to set
@body_class.
Hi Chad,- take a look at how I did this for my theme: https://github.com/abbottjam/nesta-theme-legibilis/blob/master/app.rb It's lines 44 to 56. Cheers, James On Sat, Feb 18, 2012 at 4:24 PM, Chad Ostrowski <hi@chadoh.com> wrote: > Hi, all. I've been poking around, creating my own theme, and I'd like to > set the class of the body tag. I was going to do this by using Flags, with > something like: > > %body{ class: 'main-nav-page' if @page.flagged_as?('main-nav-page') } > > which would probably work, but I noticed that the layout file from the > Slate theme<https://github.com/gma/nesta-theme-slate/blob/master/views/layout.haml>already has: > > %body{ class: @body_class } > > How do I set this instance variable for each page? I thought maybe I could > use a simple Sinatra `before` helper, but the `@page` variable isn't set > yet at that point, so I can't check the page's flags. And an `after` helper > has no useful effect on the request's instance variables. > > *Why do I want this?* > * > * > My theme has a prominent main nav bar, and having the title of a page > displayed both in the nav bar and on the page itself is repetitive and > unnecessary. Alas, adding a class to the first h1 on the pa ge causes Nesta > to not use it as the page title (that is, it doesn't show up in the > navigation, created from the menu.txt file). This is arguably a bug; I > would be open to fixing this bug in addition to figuring out how to set > @body_class. >
Hm, I guess that's an option. I'd rather not totally overwrite nesta's default `get '*'`, though. I'd rather hook into it in some other way, rather than duplicating code and making future Nesta updates more complicated. Thanks for the suggestion, though! I'm gonna stick with doing my calculations in the layout file, for now. On Saturday, February 18, 2012 at 12:36 PM, James Abbott wrote: > Hi Chad,- > > take a look at how I did this for my theme: > > https://github.com/abbottjam/nesta-theme-legibilis/blob/master/app.rb > > It's lines 44 to 56. > > Cheers, > James > > > > On Sat, Feb 18, 2012 at 4:24 PM, Chad Ostrowski <hi@chadoh.com (mailto:hi@chadoh.com)> wrote: > > Hi, all. I've been poking around, creating my own theme, and I'd like to set the class of the body tag. I was going to do this by using Flags, with something like: > > > > %body{ class: 'main-nav-page' if @page.flagged_as?('main-nav-page') } > > > > which would probably work, but I noticed that the layout file from the Slate theme (https://github.com/gma/nesta-theme-slate/blob/master/views/layout.haml) already has: > > > > %body{ class: @body_class } > > > > How do I set this instance variable for each page? I thought maybe I could use a simple Sinatra `before` helper, but the `@page` variable isn't set yet at that point, so I can't check the page's flags. And an `after` helper has no useful effect on the request's instance variables. > > > > Why do I want this? > > > > My theme has a prominent main nav bar, and having the title of a page displayed both in the nav bar and on the page itself is repetitive and unnecessary. Alas, adding a class to the first h1 on the pa ge causes Nesta to not use it as the page title (that is, it doesn't show up in the navigation, created from the menu.txt file). This is arguably a bug; I would be open to fixing this bug in addition to figuring out how to set @body_class.
You're not "totally overwriting" Nesta's default get '*' by sticking in extra two lines of code. It's change by addition, not change by modification - the latter being the least preferred of the two. If you want to put your logic in the view, go ahead. That's an MVC antipattern. Sinatra isn't strictly MVC but calculations in views are, in my opinion, a worse hack than using app.rb for what it is meant to - overriding defaults. / James On Sat, Feb 18, 2012 at 7:03 PM, Chad Ostrowski <hi@chadoh.com> wrote: > Hm, I guess that's an option. I'd rather not totally overwrite nesta's > default `get '*'`, though. I'd rather hook into it in some other way, > rather than duplicating code and making future Nesta updates more > complicated. > > Thanks for the suggestion, though! I'm gonna stick with doing my > calculations in the layout file, for now. > > On Saturday, February 18, 2012 at 12:36 PM, James Abbott wrote: > > Hi Chad,- > > take a look at how I did this for my theme: > > https://github.com/abbottjam/nesta-theme-legibilis/blob/master/app.rb > > It's lines 44 to 56. > > Cheers, > James > > > > On Sat, Feb 18, 2012 at 4:24 PM, Chad Ostrowski <hi@chadoh.com> wrote: > > Hi, all. I've been poking around, creating my own theme, and I'd like to > set the class of the body tag. I was going to do this by using Flags, with > something like: > > %body{ class: 'main-nav-page' if @page.flagged_as?('main-nav-page') } > > which would probably work, but I noticed that the layout file from the > Slate theme<https://github.com/gma/nesta-theme-slate/blob/master/views/layout.haml>already has: > > %body{ class: @body_class } > > How do I set this instance variable for each page? I thought maybe I could > use a simple Sinatra `before` helper, but the `@page` variable isn't set > yet at that point, so I can't check the page's flags. And an `after` helper > has no useful effect on the request's instance variables. > > *Why do I want this?* > * > * > My theme has a prominent main nav bar, and having the title of a page > displayed both in the nav bar and on the page itself is repetitive and > unnecessary. Alas, adding a class to the first h1 on the pa ge causes Nesta > to not use it as the page title (that is, it doesn't show up in the > navigation, created from the menu.txt file). This is arguably a bug; I > would be open to fixing this bug in addition to figuring out how to set > @body_class. > > > >
On 18 Feb 2012, at 18:31, James Abbott wrote: > You're not "totally overwriting" Nesta's default get '*' by sticking in extra two lines of code. It's change by addition, not change by modification - the latter being the least preferred of the two. It's not recommended when there are alternatives though; if (when) we change the default handler anybody who has redefined it won't be able to use the new version (unless they notice, and edit their code). As usual, it's a trade off... -- Graham Ashton Founder, The Agile Planner http://theagileplanner.com | @agileplanner | @grahamashton
Thanks, Graham! That all makes a lot of sense. I didn't realize that I could use custom metadata. Definitely better than using Flags. And yes, given a choice between an MVC antipattern and a DRY antipattern, I'll err towards the MVC one. On Saturday, February 18, 2012 at 2:00 PM, Graham Ashton wrote: > On 18 Feb 2012, at 18:31, James Abbott wrote: > > > You're not "totally overwriting" Nesta's default get '*' by sticking in extra two lines of code. It's change by addition, not change by modification - the latter being the least preferred of the two. > > It's not recommended when there are alternatives though; if (when) we change the default handler anybody who has redefined it won't be able to use the new version (unless they notice, and edit their code). As usual, it's a trade off... > > -- > Graham Ashton > Founder, The Agile Planner > http://theagileplanner.com | @agileplanner | @grahamashton > >
I have a similar question. I'd like to apply the same class, based on the
'style' metadata to the %article in summary.haml
I've tried: %article{ :class => body_class }
But that doesn't work.
Thanks,
Casey
On Feb 18, 2012, at 2:09 PM, Chad Ostrowski wrote:
> Thanks, Graham! That all makes a lot of sense. I didn't realize that I
could use custom metadata. Definitely better than using Flags.
>
> And yes, given a choice between an MVC antipattern and a DRY
antipattern, I'll err towards the MVC one.
> On Saturday, February 18, 2012 at 2:00 PM, Graham Ashton wrote:
>
>> On 18 Feb 2012, at 18:31, James Abbott wrote:
>>
>>> You're not "totally overwriting" Nesta's default get '*' by sticking
in extra two lines of code. It's change by addition, not change by
modification - the latter being the least preferred of the two.
>>
>> It's not recommended when there are alternatives though; if (when) we
change the default handler anybody who has redefined it won't be able to
use the new version (unless they notice, and edit their code). As usual,
it's a trade off...
>>
>> --
>> Graham Ashton
>> Founder, The Agile Planner
>> http://theagileplanner.com | @agileplanner | @grahamashton
>
On 20 Feb 2012, at 05:51, Casey Olson <casey.m.olson@gmail.com> wrote:
> But that doesn't work.
Can you expand on that a bit?
On 18 Feb 2012, at 18:03, Chad Ostrowski wrote: > Hm, I guess that's an option. I'd rather not totally overwrite nesta's default `get '*'`, though. I'd rather hook into it in some other way, rather than duplicating code and making future Nesta updates more complicated. I think, if I'd thought of it at the time, I'd have used a helper in Slate rather than an instance variable. %body{ :body_class => body_class } Then in app.rb you can set it how you want. You'll need to check that @page isn't nil though or it'll blow up when rendering 404 pages, and the like. Here's a simple one. module Nesta class App def helpers def body_class @page && @page.metadata('style') end end end end On one of my sites (where Nesta does the sales site, and other code takes care of what happens when the user logs in) body_class is worked out automatically from the path. Here's the helper's method body: if @page.nil? case request.path when /^\/app/ # user is logged into the app, not a nesta page 'app' else nil end else # nesta is responsible for serving the page cls = request.path.sub(/^\//, '').gsub(/[^\w]+/, '-').sub(/^$/, 'home') cls << " #{@page.metadata('type')}" if @page.metadata('type') cls << " #{@page.template}" unless @page.template == 'page' cls end -- Graham Ashton Founder, The Agile Planner http://theagileplanner.com | @agileplanner | @grahamashton
Of course.
In my app.rb I've added this:
def body_class
@page && @page.metadata('style')
end
On layout.haml:
%body{ :class => body_class }
And summaries.haml looks like this:
- unless pages.empty?
%ol
- pages.each do |page|
%li
%article{ :class => body_class }
...
I'd like the articles on the homepage ( ol li articles ) to have the same
class as the body on their individual page, the class I defined with
"Style" in the metadata.
Currently the individual articles pages' body has the body_class, but the
articles in the ol outputted by summary.haml don't have a class.
Thanks,
Casey
On Feb 18, 2012, at 10:24 AM, Chad Ostrowski wrote:
> Hi, all. I've been poking around, creating my own theme, and I'd like to
set the class of the body tag. I was going to do this by using Flags, with
something like:
>
> %body{ class: 'main-nav-page' if @page.flagged_as?('main-nav-page') }
>
> which would probably work, but I noticed that the layout file from the
Slate theme already has:
>
> %body{ class: @body_class }
>
> How do I set this instance variable for each page? I thought maybe I
could use a simple Sinatra `before` helper, but the `@page` variable isn't
set yet at that point, so I can't check the page's flags. And an `after`
helper has no useful effect on the request's instance variables.
>
> Why do I want this?
>
> My theme has a prominent main nav bar, and having the title of a page
displayed both in the nav bar and on the page itself is repetitive and
unnecessary. Alas, adding a class to the first h1 on the pa ge causes
Nesta to not use it as the page title (that is, it doesn't show up in the
navigation, created from the menu.txt file). This is arguably a bug; I
would be open to fixing this bug in addition to figuring out how to set
@body_class.
On 20 Feb 2012, at 14:26, Casey Olson wrote: > def body_class > @page && @page.metadata('style') > end > > And summaries.haml looks like this: > > - unless pages.empty? > %ol > - pages.each do |page| > %li > %article{ :class => body_class } > ... > > I'd like the articles on the homepage ( ol li articles ) to have the same class as the body on their individ ual page, the class I defined with "Style" in the metadata. That's because your body_class method is using @page (which is the page object for the page that is currently being rendered) to find out what the style metadata is set to. You need to be asking each page inside the loop what their style metadata is set to instead... -- Graham Ashton Founder, The Agile Planner http://theagileplanner.com | @agileplanner | @grahamashton
Thanks Graham, I was under the impression that's what I was doing by including it in the summaries page. Do I need an @article or something similar? I'm confused, and would love to read some relevant documentation that would help me figure this out. Thanks, Casey On Feb 20, 2012, at 9:53 AM, Graham Ashton wrote: > On 20 Feb 2012, at 14:26, Casey Olson wrote: > >> def body_class >> @page && @page.metadata('style') >> end >> >> And summaries.haml looks like this: >> >> - unless pages.empty? >> %ol >> - pages.each do |page| >> %li >> %article{ :class => body_class } >> ... >> >> I'd like the articles on the homepage ( ol li articles ) to have the same class as the body on their individ ual page, the class I defined with "Style" in the metadata. > > That's because your body_class method is using @page (which is the page object for the page that is currently being rendered) to find out what the style metadata is set to. You need to be asking each page inside the loop what their style metadata is set to instead... > > -- > Graham Ashton > Founder, The Agile Planner > http://theagileplanner.com | @agileplanner | @grahamashton > > >
On 21 Feb 2012, at 22:27, Casey Olson wrote: > I was under the impression that's what I was doing by including it in the summaries page. I'm not sure whether you understood what I was saying. > Do I need an @article or something similar? Are you familiar with what the @ on the front of "page" or "article" is doing? > I'm confused, and would love to read some relevant documentation that would help me figure this out. If you want to get a grip of basic ruby, I'd recommend investing 15 minutes in working through these exercises (they start off a bit simple, but I would expect them to show their worth towards the end): http://tryruby.org/ Here's the code again: > - pages.each do |page| > %li > %article{ :class => body_class } Let's go through it line by line. The first one starts with "- " which is Haml speak for "the rest of this line is Ruby code". "pages.each do |page|" will loop over all the objects in the "pages" Array, and assign each one to the "page" variable. The "page" variable is only being set while you're inside that loop. The "body_class" helper didn't look at each "page" variable; it has no idea whatsoever that your "page" variables in the loop exist. It's looking at a different page variable entirely, called "@page". Here's the body_class helper again: > def body_class > @page && @page.metadata('style') > end The "@" in front of "page" refers to an instance variable. What that really means is that it's set once by Nesta before it starts rendering this HTML. @page represents the Markdown, Textile or Haml page that Nesta is currently rendering. So nothing to do with any of the objects in the "pages" list that we called .each on above. So to get the behaviour you're after, you'll want to change the helper so that you can use it inside the loop. That means you'll want to pass the page object into the helper. Like this: def body_class(page) page && page.metadata('style') end I'd probably modify it so that I could use it on the current page in a body tag too (in other words, I'd make the page variable optional): def body_class(page = nil) page = @page if page.nil? page && page.metadata('style') end Then you could continue to do this in your body tags: %body{ :class => body_class } and this inside your loop: - pages.each do |page| %li %article{ :class => body_class(page) } I hope that's a bit clearer. It's certainly more wordy!