A question of coding haskell with good form, instead of 'it works'.
We want our menu navigation items to have a highlighted CSS class when the user is on that page.
Easy.
Here are my routes:
...
/simple SimpleR GET POST
/search SearchFormR GET POST
/searchresults/#Int/#Text SearchResultsR GET
...
In my hamlet template I have the below. This works perfectly, the link is highlighted when the user is on that page. The route is simple.
<li .nav-item>
<a .nav-link :Just SimpleR == mcurrentRoute:.active href=#{SimpleR}>
Simple page
This link should be highlighted when the user is on either of SearchFormR or SearchResultsR.
<li .nav-item>
<a .nav-link :((Just (SearchResultsR _ _)) == mcurrentRoute) || (Just SearchFormR == mcurrentRoute):.active href=#{SearchFormR}>
Search
This code does not work, because the SearchResultsR route constructor needs the two things passed to it. I cannot write _ _ as I have above, since the constructor needs a literal value. And besides, the result of the constructor will be compared with == to the actual route anyway, it won't match unless both parameters happen to be the exact same.
Without the _ _ I of course get a type error, expecting two more things passed to the SearchResultsR constructor.
That is, I want to check if we are on any SearchResultsR route, not only match SearchResultsR 123 "abc".
My first thought was to make a function to convert the route to a string and then check if that string contains the string of the route, but this is bad, and not the haskell / typesafe way.
My second attempt is using pattern matching:
Foundation.hs:
isThisRouteSearchResultsR :: Maybe (Route App) -> Bool
isThisRouteSearchResultsR (Just (SearchResultsR _ _)) = True
isThisRouteSearchResultsR _ = False
Hamlet template:
<li .nav-item>
<a .nav-link :(isThisRouteSearchResultsR mcurrentRoute) || (Just SearchR == mcurrentRoute) :.active href=#{SearchR}>
Search
But this doesn't seem much better. What if I have a lot more routes that have dynamic parts?
What is the proper way to do this? I looked at haskellers site source code but couldn't find the answer
The answer given by Sibi in the comments (thank you Sibi) is that the second approach in the question is in good form / style.
e.g. in hamlet:
:(isThisRouteSearchResultsROrSearchR mcurrentRoute) :.active
Or could do
:(isThisRouteSearchResultsR mcurrentRoute) || (isThisRouteSearchR mcurrentRoute) :.active
And you define these functions in Foundation.hs (Haskell) as per the question code.
Sibi:
The goal is to usually keep all your logic in the Haskell file and
keep it minimal in the Hamlet file.
Thank you Sibi for your guidance.
Related
How can you display a specific item in an array with Pug? For example:
each answer in answers
li!= answer.Response
Will display each item in the array. But, say I wanted just the the third item or, better yet, pass a variable for a specific index to display. What is the syntax for this?
- const indexIwant = 2;
if answers && answers.length>indexIwant
li=answers[indexIwant]
You need to ensure answers is not null and has at least the number of items to include the indexed item you want.
Another thing: don't use != unless you know exactly what data you are handling.
The simplest way to access a specific index of an array in pug:
-const meals = ["breakfast", "lunch", "dinner"]
-const favoriteDishes = ["coffee & doughnut salad","cheese danish soup","red wine","banana split sandwich"]
-const sides = ["ranch dressing","chutney","ketchup","chocolate sauce"]
p I reckon I will fix myself a hefty helping of #{favoriteDishes[2]} for #{meals[0]} with a side of #{sides[2]}.
Considering that indentation and whitespace is everything in jade / pug, this works :))
I am creating an application where the site menu would be dynamically loaded from JSON file. Each menu may correspond to an action that would be defined inside the ng-click directive. This would look something like this
<li ng-repeat="menuItem in menuContainer.menus" class="{{menuItem.cssClass}}">
<a href="{{menuItem.url}}" ng-click="{{menuItem.clickAction}}">
<i class="{{menuItem.iconClass}}"></i>{{menuItem.name}}
<span class="badge">{{menuItem.subMenus.length}}</span>
</a>`enter code here`
<li>
Now the problem is ng-click does not recognize the clickAction as a function, I believe this is due to linking process. I want to know is there any way to evaluate a string to method. I tried do $eval but it executes the function on load.
How do I do this?
Define methods not as strings, but as functions and replace ng-click="{{menuItem.clickAction}}" to ng-click="menuItem.clickAction()". Another way to define function on $scope, like:
$scope.executeString = function(body){
eval(body);
};
and replace your ng-click to ng-click="executeString(menuItem.clickAction)". Anyway, use eval is antipattern;)
Remember, that ng-click and other directives, like that, takes angular expression as parameter. And if body of you expression is a = b + c than angular convert it in javascript like $scope.a = $scope.b + $scope.c
I am trying to display conditional text in a Pyramid Chameleon template. Basically, checking if the dictionary key 'maxed_out_alerts' is empty (false) or has a string 'yes' in it.
<p tal:condition="not:maxed_out_alerts"><h3>Maxed Out.</h3></p>
<p tal:condition="maxed_out_alerts"><h3>Not Maxed Out</h3></p>
When 'maxed_out_alerts' is an empty string, 'Maxed Out' is only displayed (correctly). However, If 'maxed_out_alerts' contains 'yes' string both 'Maxed Out' and "Not Maxed Out' are displayed (incorrectly).
It seems that the NOT is always evaluated to a true condition. It should display one or the other messages not both. What am I doing wrong? thanks
For TAL conditionals in python you can say python: and then use a python syntax conditional
<p tal:condition="python:len(maxed_out_alerts) > 0"><h3>Maxed Out.</h3></p>
It could help if you save boolean state in a boolean variable. By storing this information in a string you run into such problems you are facing right now. That's what builtin python types are made for - use them.
As a pyramid developer I would advice to move the logic to evaluate the current value of maxed_out_alerts into a string into a view method and pass the computed string in a dictionary to the renderer/template. This way you can even create tests for the view logic - any pyramid tutorial, simple or advanced shows you how to do that.
A good start for any simple logic - imagine logic gets more complicated or you even have to translate the text for the template.
#view_config(name="yourname", renderer='templates/yourtemplate.pt')
def myview(request):
"""
#get boolean state from model
#could be that you want to have it the other way round
#or do it by using python ternary operator - a if test else b
if model['maxed_out_alerts'] == True:
maxed_out_alerts = 'Maxed Out'
else:
maxed_out_alerts = 'Not Maxed Out'
return dict(maxed_out_alerts = maxed_out_alerts)
In your Template
<h3 tal:content="maxed_out_alerts">text for maxed out alerts</h3>
or
<h3>${maxed_out_alerts}</h3>
I'm trying to author a few paragraphs with Jade, but finding it difficult when there are links inside a paragraph.
The best I can come up with, and I'm wondering if there's a way to do it with less markup:
p
span.
this is the start
of the para.
a(href="http://example.com") a link
span.
and this is the rest of
the paragraph.
As of jade 1.0 there's an easier way to deal with this, unfortunately I can't find it anywhere in the official documentation.
You can add inline elements with the following syntax:
#[a.someClass A Link!]
So, an example without going into multiple lines in a p, would be something like:
p: #[span this is the start of the para] #[a(href="http://example.com") a link] #[span and this is the rest of the paragraph]
You can also do nested inline elements:
p: This is a #[a(href="#") link with a nested #[span element]]
You can use a markdown filter and use markdown (and allowed HTML) to write your paragraph.
:markdown
this is the start of the para.
[a link](http://example.com)
and this is the rest of the paragraph.
Alternatively it seems like you can simply ouput HTML without any problems:
p
| this is the start of the para.
| a link
| and this is he rest of the paragraph
I wasn't aware of this myself and just tested it using the jade command line tool. It seems to work just fine.
EDIT:
It seems it can actually be done entirely in Jade as follows:
p
| this is the start of the para
a(href='http://example.com;) a link
| and this is the rest of the paragraph
Don't forget an extra space at the end of para (although you can't see it. and between | and. Otherwise it will look like this para.a linkand not para a link and
Another way to do it:
p
| this is the start of the para
a(href="http://example.com") a link
|
| this is the rest of the paragraph.
Another completely different approach, would be to create a filter, which has first stab at replacing links, and then renders with jade second
h1 happy days
:inline
p this can have [a link](http://going-nowhere.com/) in it
Renders:
<h1>happy days</h1><p>this can have <a href='http://going-nowhere.com/'>a link</a> in it</p>
Full working example: index.js (run with nodejs)
var f, jade;
jade = require('jade');
jade.filters.inline = function(txt) {
// simple regex to match links, might be better as parser, but seems overkill
txt = txt.replace(/\[(.+?)\]\((.+?)\)/, "<a href='$2'>$1</a>");
return jade.compile(txt)();
};
jadestring = ""+ // p.s. I hate javascript's non-handling of multiline strings
"h1 happy days\n"+
":inline\n"+
" p this can have [a link](http://going-nowhere.com/) in it"
f = jade.compile(jadestring);
console.log(f());
A more general solution would render mini sub-blocks of jade in a unique block (maybe identified by something like ${jade goes here}), so...
p some paragraph text where ${a(href="wherever.htm") the link} is embedded
This could be implemented in exactly the same way as above.
Working example of general solution:
var f, jade;
jade = require('jade');
jade.filters.inline = function(txt) {
txt = txt.replace(/\${(.+?)}/, function(a,b){
return jade.compile(b)();
});
return jade.compile(txt)();
};
jadestring = ""+ // p.s. I hate javascript's non-handling of multiline strings
"h1 happy days\n"+
":inline\n"+
" p this can have ${a(href='http://going-nowhere.com/') a link} in it"
f = jade.compile(jadestring);
console.log(f());
If your links come from a data source you can use:
ul
each val in results
p
| blah blah
a(href="#{val.url}") #{val.name}
| more blah
See interpolation
Edit: This feature was implemented and issue closed, see answer above.
I've posted an issue to get this feature added into Jade
https://github.com/visionmedia/jade/issues/936
Haven't had time to implement it though, more +1s may help !
This is the best I can come up with
-var a = function(href,text){ return "<a href='"+href+"'>"+text+"</a>" }
p this is an !{a("http://example.com/","embedded link")} in the paragraph
Renders...
<p>this is an <a href='http://example.com/'>embedded link</a> in the paragraph</p>
Works ok, but feels like a bit of a hack - there really should be a syntax for this!
I did not realize that jade requires a line per tag. I thought we can save space. Much better if this can be understood ul>li>a[class="emmet"]{text}
I had to add a period directly behind a link, like this:
This is your test [link].
I solved it like this:
label(for="eula").lbl.lbl-checkbox.lbl-eula #{i18n.signup.text.accept_eula}
| #{i18n.signup.links.eula}.
As suggested by Daniel Baulig, used below with dynamic params
| <a href=!{aData.link}>link</a>
Turns out there is (now at least) a perfectly simple option
p Convert a .fit file using Garmin Connect's export functionality.
p
| At Times Like These We Suggest Just Going:
a(ui-sref="app") HOME
|
Most simplest thing ever ;) but I was struggling with this myself for a few seconds. Anywho, you need to use an HTML entity for the "#" sign -> #
If you want to in include a link, let's say your/some email address use this:
p
a(href="mailto:me#myemail.com" target="_top") me#myemail.com
In Drupal 6, how do you print a taxonomy term as a CSS body class?
I have found this snippet that lets you print almost every aspect of Drupal content as a body class, but it doesn't include taxonomy terms:
http://www.davidnewkerk.com/book/122
Being able to print taxonomy terms as a body class is essential for theming processes, so I am surprised that a solution is not readily available.
Check what variables are passed to the page template by either doing print_r($vars) or dpm($vars) in your page pre-process function or using the http://drupal.org/project/devel_themer module. The usage of dpm require you to install the devel module.
You will find that some themes will pass $taxonomy as a variable to page.tpl.php . If that is not the case you can find the taxonomy terms in the $node variable which is also available in the page.tpl.php in some themes.
(The above holds true for my fusion based theme acquia marina http://drupal.org/project/acquia_marina ). Once you have these taxonomy terms available you can easily print them out in your body classes.
After much hard work, I found a very easy way to do this.
On Drupal Snippets, there is a snippet that lets you print out the taxonomy terms applied to each page as text.
The only problem is that the snippet will print any spaces or punctuation that are in the taxonmy term, which is no good for body classess.
However, by adding a str_replace command, you can strip out all the spaces and punctuation.
I'm sure there are other people who wants to print taxonmy terms as body classes, so to save them the bother, here is the code that I used with the str_replace command added.
Put the following in template.php:
function getTerm($label, $vid, $link) {
$node = node_load(array('nid'=>arg(1)));
foreach((array)$node->taxonomy as $term){
if ($term->vid == $vid){
if ($link){
$link_set[] = l($term->name, taxonomy_term_path($term));
} else {
$link_set[] = $term->name;
}
}
}
if (!empty($link_set)){
$label = ($label) ? "<strong>$label </strong>" : "";
$link_set = $label.implode(', ', $link_set);
}
$link_set = str_replace(' ', '_', $link_set);
$link_set = str_replace('&', 'and', $link_set);
$link_set = strtolower($link_set);
return $link_set;
}
Put the following in Page.tpl.php:
<body class="taxonomy-<? print getTerm(false, 1, false);?>">
I hope this helps anyone who has the same problem.
Extra tips:
(1)In the code I have posted, the only punctuation that is striped out is the ampersand (i.e. '&').
If you have other punctuation to strip out use the following:
$link_set = str_replace('INSET_PUNCTUATION_HERE', 'INSERT_REPLACEMENT_HERE', $link_set);
Place this command under the other $link_set lines in the code I have posted for template.php.
(2) In the page.tpl.php code I have posted, the "taxonomy-" part places the words taxonomy and a dash before each body class term. You can edit this as you wish to get the results your require.