About this book
Updated to Newscoop 3.5.2
The Newscoop 3 Cookbook is a work in progress and open to your input. Dedicated to Open Source software development, Sourcefabric believes that the software and its documentation are open to the community. The more contributors add to the products, the more errors get caught and fixed, the more features are implemented. We also believe that software improves from good documentation, and documentation improves with the wide use of software.
If you experience the Newscoop 3 Cookbook in its printed form, it might be difficult to see how this book is open to your contribution. If you have come across the Newscoop 3 Cookbook online at FLOSS Manuals, you might get a better idea about how you can participate in improving this documentation. Register, log in and add your knowledge, use cases, your code snippets, comments and best practices to make this a better publication. Working with the online book production platform Booki, the content of this book is continuously evolving. Chances are, the latest PDF, ePub or the online version on the site http://www.flossmanuals.net contains more details than the printed copy.

"All work and no play..." - the Newscoop Cookbook team at work.
Sourcefabric started this publication with a one-week Book Sprint in Schloss Neuhausen, Germany, two hours north of Berlin. Authors for the Newscoop 3 Cookbook include (in reverse alphabetical order): Holman Romero, Ljuba Ranković, Lucian Marin, Micz Flor, Alexei Danilchuk and Douglas Arellanes. Our facilitator, chef, sprintmaster, captain and all-around make-it-happen person was Adam Hyde of FLOSS Manuals. Thanks also go to Katerina Michailidis for her logistical support and to Daniel James for copy and style editing.
If you contribute to this book, you may also want to add yourself as an author here...
Action check on form submission
Edit Subscription Action
The edit_subscription_action object is initialized when a subscription form was submitted. It has the following properties:
- defined: true if a subscription submit action took place
- is_error: true if a subscription submit action took place and the result was an error
- error_code: error code of the subscription submit action; null if no subscription submit action took place
- error_message: error message of the subscription submit action; null if no subscription submit action took place
- ok: true if a subscription submit action took place and the result was success
- is_trial: true if the submitted subscription type was trial
- is_paid: true if the submitted subscription type was paid subscription
Edit User Action
The edit_user_action object is initialized when a user add/edit form was submitted. It has the following properties:
- defined: true if a user data submit action took place
- is_error: true if a user data submit action took place and the result was an error
- error_code: error code of the user data submit action; null if no user data submit action took place
- error_message: error message of the user data submit action; null if no user data submit action took place
- ok: true if a user data submit action took place and the result was success
- type: can take one of the following two values: "add" for user add submit, "edit" for an existing user data edit submit
- name: the user full name as filled in the form
- uname: the user login name as filled in the form
- password: the account password as filled in the form
- passwordagain: the password confirmation
- email: the user email as filled in the form
- city
- str_address
- state
- phone
- fax
- contact
- second_phone
- postal_code
- employer
- position
- interests
- how
- languages
- improvements
- field1
- field2
- field3
- field4
- field5
- text1
- text2
- text3
- country
- title
- gender
- age
- employertype
- pref1
- pref2
- pref3
- pref4
Login Action
The login_action object is defined when a login action takes place. It has the following properties:
- defined: true if a login action took place
- is_error: true if a login action took place and the result was an error
- error_code: error code of the login action; null if no login action took place
- error_message: error message of the login action; null if no login action took place
- ok: true if a login action took place and the result was successful
- user_name: the login name of the user that attempted to log in
- remember_user: true if the remember user flag was set in the login form
Preview Comment Action
The preview_comment_action object is initialized when the preview button is clicked on a comment form. It has the following properties:
- defined: true if a comment preview action took place
- is_error: true if a comment preview action took place and the result was an error
- error_code: error code of the comment preview action; null if no comment preview action took place
- error_message: error message of the comment preview action; null if no comment preview action took place
- ok: true if a comment preview action took place and the result was successful
- subject: the comment subject as filled in the form
- content: the comment content as filled in the form
- reader_email: the comment reader email as filled in the form
Search Articles Action
The seararticles_action object is initialized when a search action takes place. It has the following properties:
- defined: true if a search action took place
- is_error: true if a search action took place and the result was an error
- error_code: error code of the search action; null if no search action took place
- error_message: error message of the search action; null if no search action took place
- ok: true if a search action took place and the result was successful
- searphrase: the phrase for which the search was performed
- searkeywords: an array of keywords for which the search was performed
- matall: true if the match all flag was set
- searlevel: 0 for multiple publication search, 1 for current publication search, 2 for current issue search, 3 for current section search
- submit_button: the submit button text
- template: the template used on search form submission
Submit Comment Action
The submit_comment_action object is initialized when a comment form is submitted. It has the following properties:
- defined: true if a comment submit action took place
- is_error: true if a comment submit action took place and the result was an error
- error_code: error code of the comment submit action; null if no comment submit action took place
- error_message: error message of the comment submit action; null if no comment submit action took place
- ok: true if a comment submit action took place and the result was successful
- subject: the comment subject as filled in the form
- content: the comment content as filled in the form
- reader_email: the comment reader email as filled in the form
Article comments
In this chapter you will learn how to display comments and the comment form, and how to use CAPTCHA or ReCAPTCHA spam protection. Comments are the place for your readers to give their feedback on an article. Comments also reflect the conversation of the community of your publication. Your readers are not only communicating their ideas about the article, but also communicating with each other.
Enabling and disabling comments is set for each publication in the administration interface. Here you can enable or disable comments for publications, for article types and for individual articles. If you switch off comments at the publication level, no comments can be added at all. The next level is article type: if you disable comments here, the option will not appear in the Article Edit screen for articles of this type. If both of these options are enabled, editors can switch commenting off for an individual article.
Listing the most commented articles
Before we dive into article comments, here's a little nugget showing how you can list articles by the number of comments they have, in descending order:
{{ list_articles order="bycomments desc" }}
<p>
{{ $gimme->article->name }},
comments: {{ $gimme->article->comment_count }}
</p>
{{ /list_articles }}
This list_articles function will list the articles inside the current section, by default. To list all articles from an issue use:
{{ list_articles ignore_section="true" order="bycomments desc" }}
For the entire publication, use:
{{ list_articles ignore_section="true" ignore_issue="true" order="bycomments desc" }}
Listing article comments
The following code has been taken from the template pack "The Journal", designed by Woo Themes and available on the Sourcefabric website. If comments are available, you can list them like this:
{{ list_article_comments columns="2" order="bydate desc"}}
{{ if $gimme->current_list->at_beginning }}
<h4>{{ $gimme->article->comment_count }} Response(s) to "{{ $gimme->article->name }}"</h4>
<ol class="commentlist">
{{ /if }}
<li class="comment {{ if $gimme->current_list->column == "1" }}odd{{ else }}even{{ /if }}">
<div class="comment-head cl">
<div class="user-meta">
<strong class="name">{{ $gimme->comment->nickname }}</strong>
{{ $gimme->comment->submit_date|camp_date_format:"%e.%m.%Y at %H:%i" }}
</div>
</div>
<div class="comment-entry">
<p>{{ $gimme->comment->content }}</p>
</div>
</li>
{{ if $gimme->current_list->at_end }}
</ol>
{{ /if }}
{{ /list_article_comments }}
list_article_comments lists the comments. columns="2" is used to add "odd" and "even" classes in the list. order="bydate desc" assures that the newest comment appears on the top of the list. The other values in this example are pretty much self-explanatory.
More properties of the article comment can be printed, like e-mail or unique ID. You can find these properties in the reference part of this Cookbook.
If you want to display the comments only if commenting is enabled, use the above code inside the following IF function:
{{ if $gimme->article->comments_enabled }}
[... code goes here ...]
{{ /if }}
If you want to display the comments only if the reader has access to the content of the article - either because it is available to all, or because the user is logged in and has a subscription to the content - use the above code inside the following IF function:
{{ if $gimme->article->content_accessible }}
[... code goes here ...]
{{ /if }}
You can also combine the two like this:
{{ if $gimme->article->comments_enabled && $gimme->article->content_accessible }}
[... code goes here ...]
{{ /if }}
Creating the form for article comments
The comment form can be styled freely. It is wrapped in {{ comment_form }} which creates the form tag automatically. The HTML inside is limited only by your imagination.
{{ comment_form html_code="id=\"commentform\"" submit_button="SUBMIT" button_html_code="tabindex=\"6\"" }}
<label for="author"><small>Name (required)</small></label>
{{ camp_edit object="comment" attribute="nickname" html_code="id=\"author\" 22\" tabindex=\"1\"" }}
<label for="email"><small>E-mail (will not be published) (required)</small></label>
{{ camp_edit object="comment" attribute="reader_email" html_code="id=\"email\" 22\" tabindex=\"2\"" }}
<input type="hidden" name="f_comment_subject" value="Site comment" />
{{ camp_edit object="comment" attribute="subject" html_code="id=\"comment-subject\" tabindex=\"3\"" }}
<label for="comment"><small>Comment</small></label>
{{ camp_edit object="comment" attribute="content" html_code="id=\"comment\" rows=\"5\" tabindex=\"4\"" }}
<img src="{{ captcha_image_link }}"><br />
<label for="f_captcha_code"><small>Enter the code:</small></label>{{ camp_edit object="captcha" attribute="code" html_code="id=\"comment-code\" tabindex=\"5\"" }}
{{ /comment_form }}
As shown above, the display of the form can be controlled to show up only IF the article allows commenting or IF the user has access to the article.
Spam control with CAPTCHA
To prevent automated spamming, you can add a CAPTCHA image to your comment form. It displays letters which the user needs to type in before posting their comment. Include a CAPTCHA by adding the following lines just before {{ /comment_form }}:
<img src="{{ captcha_image_link }}"><br />
<label for="f_captcha_code"><small>Enter the code:</small></label>{{ camp_edit object="captcha" attribute="code" html_code="id=\"comment-code\" tabindex=\"5\"" }}
When submitting the comment, the string typed by the reader is checked against the CAPTCHA image. If it is not identical, an error can be displayed.
{{ if $gimme->submit_comment_action->is_error }}
{{ $gimme->submit_comment_action->error_message }}
{{ $gimme->submit_comment_action->error_code }}
{{ /if }}
The error code is machine generated and can not be changed. The error message can be changed in the administration interface, in "Localization".
Spam control with ReCAPTCHA Newscoop plugin
Instead of the solution mentioned above, you can use the ReCAPTCHA plugin (which works with Newscoop 3.5.2 and higher). In that case, you only need to use:
<p>
{{ recaptcha }}
</p>
You can read what reCAPTCHA is at http://www.google.com/recaptcha
Then, make sure to create the proper key for your site here:
https://www.google.com/recaptcha/admin/create
Your comment form will look like this

Steps to perform in order to work with this plugin:
- Download the recaptcha plugin from our site (if you installed Newscoop 3.5.2 or higher, you should have this plugin already in your Plugins Manager)
- Install and enable the plugin through the Plugins Manager in the Newscoop administration interface (in the main menu, Plugins -> Manage Plugins)
- Configure the plugin, the options are:
- Enable for comments:
- Enable for subscriptions:
- Enter the public key:
- Enter the private key:
- Include the appropriate template tag within your forms:
comments form:
{{ recaptcha }}
subscriptions form:
{{ recaptcha form='subscriptions' }}
Finally, enable the use of CAPTCHA for your publication in the Publication configure screen.
Checking for errors and article moderation
To go through the process of submitting, checking and giving feedback on article moderation you could structure the template in the following way:
{{ if $gimme->submit_comment_action->defined && $gimme->submit_comment_action->rejected }}
Your comment has not been accepted.
{{ /if }}
{{ if $gimme->submit_comment_action->is_error }}
{{ $gimme->submit_comment_action->error_message }}
{{ $gimme->submit_comment_action->error_code }}
{{ else }}
{{ if $gimme->submit_comment_action->defined }}
{{ if $gimme->publication->moderated_comments }}
Your comment has been sent for approval.
{{ /if }}
{{ /if }}
{{ /if }}
<h2>Leave a Reply</h2>
{{ if $gimme->user->blocked_from_comments }}
You are not allowed to comment.
{{ else }}
{{ comment_form html_code="id=\"commentform\"" submit_button="SUBMIT" button_html_code="tabindex=\"6\"" }}
[...]
{{ /comment_form }}
{{ /if }}
In this example you can also see where and how to place feedback for banned users.
Preview of comments
If you want to allow readers to preview their comments, you need to add the code preview_button="Preview" to {{ comment_form ... }}. "Preview" is the text that will be displayed on the button, but you can change this value.
{{ comment_form html_code="id=\"commentform\"" submit_button="SUBMIT" preview_button="Preview" button_html_code="tabindex=\"6\"" }}
If you add the preview_button, you will see the button show up at the end of the form. If the reader writes a comment and clicks "Preview", the preview can be displayed using the following template code:
{{ if $gimme->preview_comment_action->is_error }}
<p>There was an error previewing the comment:
{{ $gimme->preview_comment_action->error_message }}
</p>
{{ /if }}
{{ if $gimme->preview_comment_action->ok }}
<b>Comment preview</b><br/>
Subject: {{ $gimme->preview_comment_action->subject }}<br/>
Reader e-mail: {{ $gimme->preview_comment_action->reader_email }}<br/>
Content: {{ $gimme->preview_comment_action->content }}
{{ /if }}
A good place to put this code is just above the comment form.
Nested comments: using threads and levels
Comments can be displayed as nested trees.
<ul>
{{ assign var="level" value="1" }}
{{ list_article_comments order="bydate asc" }}
{{ if $gimme->comment->level gt $level }}
{{ assign var="level" value=$gimme->comment->level }}
<ul>
{{ /if }}
{{ if $gimme->comment->level < $level }}
{{ php }}
$gimme = $this->get_template_vars('gimme');
$level = $this->get_template_vars('level');
$count = $level - $gimme->comment->level;
for (; $count > 0; $count --) {
echo "</ul>";
}
{{ /php }}
{{ assign var="level" value=$gimme->comment->level }}
{{ /if }}
<li>{{ if $gimme->comment == $gimme->default_comment }}<b>{{ /if }}
Level: {{ $gimme->comment->level }}
<a href="{{ uri }}#comments">
Subject: {{ $gimme->comment->subject }}, Reader email: {{ $gimme->comment->reader_email }}
</a>
{{ if $gimme->comment == $gimme->default_comment }}</b>{{ /if }}<br/>
Content: {{ $gimme->comment->content }}
</li>
{{ /list_article_comments }}
</ul>
Article object and attachment, comment, location
Article
The article object is set at the beginning of the main template based on the request URL. This object can be changed using the set_article function. The article object has the following properties:
Base properties/functions:
- name: article name
- number: article identifier in the Newscoop database
- author: returns an object corresponding to the first author in the list of authors, with the following properties:
-
- name
- first_name
- last_name
- email
- defined
- authors: returns the complete list of authors for the current article - objects of type author (see above or "Author").
- keywords: text containing the article keywords separated by the Newscoop defined separator (default is comma [,])
- has_keyword (<keyword>): returns true if the given keyword existed in the article keywords list
Example:
{{ if $gimme->article->has_keyword (mp3podcast) }}<span class="audio"></span>{{ /if }}
Important: the command matches parts of the keyword. In the above example keywords "mp3podcast10" and "mp3podcasttalk" both return true.
- type_name: article type name
- type_translated: article type name translated to the environment language
- <date_attribute>: article creation date field (year, month, day etc.)
- creation_date: article creation date; you can customize the date display format by using the filter camp_date_format
- publish_date: article publish date; you can customize the date display format by using the filter camp_date_format
- last_update: time of the last article edit
- template: the full path of the article template file
- type-> <article_type>-> <article_type_attribute>: returns the content of an article field specific to a certain article type (see the "Article Types" chapter in Newscoop for Journalists and Editors); read the chapter Date and e-mail formatting in this Cookbook for formatting the content of type date/time; see also the notes below
- url_name: the article name used in URL display (see the "Creating An Article" chapter in Newscoop for Journalists and Editors)
- translated_to(<language_code>): true if an article translation for the language with the given code existed
- subtitles_count(<field_name>): returns the number of the subtitles in the given content field; the article name is counted as the first subtitle so this function returns a number greater or equal to 1. If the specified field was not a content field it returns null.
- subtitle_url_id(<field_name>): returns the URL parameter which sets the number of the subtitle to be displayed from the field <field_name>
- current_subtitle_no(<field_name>): returns the number of the subtitle which will be displayed through the statement {{ $gimme->article-><field_name> }}; 0 for the default subtitle, 1 for the first subtitle defined in the article content field etc.
- publication: the publication to which this article belongs to - object of type publication (see the chapter "Publication")
- issue: the issue to which this article belongs to - object of type issue (see the chapter "Issue")
- section: the section to which this article belongs to - object of type section
- language: the article language - object of type language (see the chapter "Language")
- owner: the user who created the article - object of type user (see the chapter "User")
- defined: boolean value (true/false) - true if the article was set in the current environment; false otherwise
Comments related properties/functions:
- comments_enabled: true if comments were enabled for the article publication, article type and the current article
- comments_locked: true if comments were locked (meaning they can be listed but no new comments can be posted)
- comment_count: returns the number of the comments posted to the article and approved
Accessibility properties/functions:
- on_front_page: true if article front page flag was set
- on_section_page: true if article section page flag was set
- is_published: true if the article was published
- is_public: true if the article was accessible to the public
- is_indexed: true if the article was indexed by the search engine
- content_accessible: returns true if the content of the article is accessible for reading: either it is public or the reader subscribed to the publication (see also Editing An Article and Creating a Publication chapters in Newscoop for Journalists and Editors)
Attachment related properties/functions:
- has_attachments: true if the article had attached files
- image: returns the image object that was defined in the template environment; if the image was not defined in the environment, returns the first image of the article; if the article didn't have any image attached returns an unset image object
- image_index: returns the index of the current image inside the article; if the image wasn't defined in the environment or it doesn't belong to the article returns null.
- has_image(<image_index>): true if the article had an attached image and it's index was equal to the given index
- image(<image_index>): returns the attached image having the given index; if no such image existed, returns an unset image object. This is a function so the image index is given in between brackets. For example: $gimme->article->image(3)
- image<image_index>: returns the attached image having the given index; if no such image existed, returns an unset image object. This is a property, not a function. For example: $gimme->article->image3
- topics_count: returns the number of topics attached to this article
- has_topics: true if the article had attached topics
- has_topic(<topic_identifier>): true if the article had the specified topic attached to it
Statistics properties/functions:
- reads: returns the number of readers that viewed this article since it was published
- request_object_id: the identifier used in statistics gathering
<date_attribute> may be one of the following:
- year: year (four digits)
- mon: month as a number (1..12)
- mday: day of the month as a number (1..31)
- yday: day of the year (1..366)
- wday: day of the week as a number (0=Sunday..6=Saturday)
- hour: hour (0..23)
- min: minute (two digits)
- sec: seconds (two digits)
- mon_name: name of the month
- wday_name: day of the week
Note regarding the attribute type->[<article_type>->]<article_type_attribute>:
Attributes which are body fields (content) have the following properties:
- all_subtitles: returns the whole content of the body field, not just the current subtitle
- first_paragraph: returns the first paragraph of the current subtitle
- subtitles_count: returns the number of the subtitles in the body field
- subtitle_number: returns the number of the current subtitle: 0 for the default subtitle, 1 for the first subtitle defined in the article content field etc.
- subtitle_is_current: true if the subtitle that would be displayed through the statement {{ $gimme->article-><article_type_attribute> }} is the same as the subtitle defined in the template environment (see also the chapter "Subtitle (subheads in long articles)" and current_subtitle_no(<field_name>) above)
- has_previous_subtitles: true if the current subtitle from this field was not the first subtitle
- has_next_subtitles: true if the current subtitle from this field was not the last subtitle
Example: displaying the first paragraph of the dynamic field "content":
$gimme->article->content->first_paragraph
Note regarding the attribute type->[<article_type>->]<article_type_attribute>:
In Newscoop the table cell containing the image link in article body fields has the class cs_img and the cell containing the caption text has the class caption; this allows the web designer to change the layout of the article images by using a CSS file. The image link has the following structure:
<table border="0" cellspacing="0" cellpadding="0" class="cs_img" align=left>
<tr>
<td align="center">
<img src="/get_img?NrArticle=143&NrImage=1" border="0"
hspace="5" vspace="5">
</td>
</tr>
<tr><td align="center" class="caption">Newscoop team</td></tr>
</table>
Note regarding the attribute type->[<article_type>->]<article_type_attribute>:
The subtitle in the article body fields has the class articlesubhead; this allows the web designer to change the layout of the subtitles by using a CSS file. The subtitle anchor has the following structure:
<span class="articlesubhead">
<a name="a1.250_s1">Version 2.3.0 - 2.3.1</a>
</span>
The structure of the anchor name is:
a<language_identifier>.<article_number>_s<subtitle_number>
Article Attachment
The article attachment object is usually initialized inside a list of article attachments. It is not initialized at the beginning of the template and can not be initialized by other Newscoop functions. The article attachment object has the following properties:
- identifier: the attachment identifier in the Newscoop database (integer value)
- file_name: the name of the attached document
- mime_type: the mime type of the attached document
- extension: the file extension of the attached document
- description: the user filled description field of the attached document in the current language
- size_b: the size of the attached document in bytes
- size_kb: the size of the attached document in kilobytes
- size_mb: the size of the attached document in megabytes
- defined: boolean value (true/false) - true if the attachment was set in the current environment; false otherwise
Examples
Taken from Template Pack "The Custodian" (date 2011-03-15) file "if-audio.tpl"
{{ if ($gimme->attachment->extension == mp3) || ($gimme->attachment->extension == ogg) }}
Taken from Template Pack "The Custodian" (date 2011-03-15) file "if-audio.tpl"
<div class="audio-attachment-description">{{ $gimme->attachment->description }}</div>
Taken from Template Pack "The Custodian" (date 2011-03-15) file "if-audio.tpl"
<audio controls>
<source src="http://{{ $gimme->publication->site }}{{ uri options="articleattachment" }}" type="{{ $gimme->attachment->mime_type }}">
</audio>
Article Comment
The comment object is usually initialized inside a list of article comments. It can be initialized at the beginning of the template from the URL request but can not be initialized by other Newscoop functions. The article comment object has the following properties:
- identifier: the numerical identifier of the article comment from the database
- real_name: the real name of the reader who posted the comment; the reader must be a registered Newscoop user; for anonymous readers this attribute will return an empty string
- nickname: the nickname of the reader who posted the comment
- reader_email: the email of the reader who posted the comment
- anonymous_author: whether the reader is anonymous or not
- submit_date: the date and time the comment was submitted
- subject: the subject of the article comment
- content: the content of the article comment
- content_real: the raw representation of the content
- level: the level of the current comment in the tree structure of the comments
- article: the article where this comment was submitted to - object of type article
- defined: true if the comment object had a valid value
Example
{{ list_article_comments columns="2" order="bydate desc"}}
{{ if $gimme->current_list->at_beginning }}
<h2>{{ $gimme->article->comment_count }} Response(s) to “{{ $gimme->article->name }}”</h2>
<ol class="commentlist">
{{ /if }}
<li class="comment {{ if $gimme->current_list->column == "1" }}odd{{ else }}even{{ /if }}">
<div class="comment-head cl">
<div class="user-meta">
<strong class="name">{{ $gimme->comment->nickname }}</strong> {{ $gimme->comment->submit_date|camp_date_format:"%e.%m.%Y at %H:%i" }}
</div>
</div>
<div class="comment-entry">
<p>{{ $gimme->comment->content }}</p>
</div>
</li>
{{ if $gimme->current_list->at_end }}
</ol>
{{ /if }}
{{ /list_article_comments }}
Article Location
Note: this works only in Newscoop 3.5.0 and newer versions.
Maps require jQuery: In order to use display maps you must include jQuery in the header of your document, with a link like this:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js">
The article "location" object is usually initialized inside a list of articles. It is not initialized at the beginning of the template and can not be initialized by other Newscoop functions. The article location object has the following properties:
- name: the location's name
- latitude: latitude in degrees
- longitude: longitude in degrees
- text: location's text description
- content: location's rich text description
- multimedia: list of multimedia items related to the location, see the "Location Multimedia" object.
Examples
{{ list_article_locations }}
{{ if $gimme->location->enabled }}
{{ $gimme->location->name }}{{ if $gimme->current_list->at_end }}{{ else }}, {{ /if }}
{{ /if }}
{{ /list_article_locations }}
Listing all information for locations in an article
<h2>List article with geolocation information</h2>
<ul>
{{ list_articles}}
{{ list_article_locations }}
{{ if $gimme->location->enabled }}
{{ if $gimme->current_list->at_beginning }}
<ul>
<li>LOCATION DATA FOR: {{ $gimme->article->name }}</li>
<ul>
{{ /if }}
<li>list index: {{ $gimme->current_list->index }}</li>
<li>name: {{ $gimme->location->name }}</li>
<li>latitude: {{ $gimme->location->latitude }}</li>
<li>longitude: {{ $gimme->location->longitude }}</li>
<li>text: {{ $gimme->location->text }}</li>
<li>content: {{ $gimme->location->content }}</li>
<li>multimedia:</li>
<ul>
{{ foreach from=`$gimme->location->multimedia` item=multimediaitem }}
<li>src: {{ $multimediaitem->src }}</li>
<li>type: {{ $multimediaitem->type }}</li>
<li>spec: {{ $multimediaitem->spec }}</li>
<li>width: {{ $multimediaitem->width }}</li>
<li>height: {{ $multimediaitem->height }}</li>
{{ /foreach }}
</ul>
{{ if $gimme->current_list->at_end }}
</ul>
</ul>
{{ /if }}
{{ /if }}
{{ /list_article_locations }}
{{ /list_articles }}
</ul>
Ushahidi compatible KML format. You can use this as a feed to call as a layer in Ushahidi
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://earth.google.com/kml/2.2">
<Document>
<name>{{ $gimme->publication->name }}</name>
<description><![CDATA[ .]]></description>
{{ list_articles}}
{{ list_article_locations }}
{{ if $gimme->location->enabled }}
<Style id="style{{ $gimme->article->number }}-{{ $gimme->current_list->index }}">
<IconStyle>
<Icon>
<href>http://www.sourcefabric.org/javascript/geocoding/markers/marker-gold.png</href>
</Icon>
</IconStyle>
</Style>
{{ /if }}
{{ /list_article_locations }}
{{ /list_articles }}
{{ list_articles}}
{{ list_article_locations }}
{{ if $gimme->location->enabled }}
<Placemark>
<name>{{ $gimme->location->name }} @ {{ $gimme->article->name }}</name>
<description></description>
<styleUrl>#style{{ $gimme->article->number }}-{{ $gimme->current_list->index }}</styleUrl>
<Point>
<coordinates>{{ $gimme->location->longitude }},{{ $gimme->location->latitude }},0.000000</coordinates>
</Point>
</Placemark>
{{ /if }}
{{ /list_article_locations }}
{{ /list_articles }}
</Document>
</kml>
Articles
In this chapter you will learn how to display elements of an article, as well as building article lists. Among all templates, article.tpl is generally the one where most template functions are called, and many sub-templates are included. No surprise, since a lot of things usually show up in an article page:
- title
- authors
- publish date
- intro
- full text
- attachments
- comments
- map
- the list of other articles from the same section
- ...?
Each article has an Article Type, which has a list of fields you set up to reflect the content (like "intro", "twitter", "full_text", "seo_title" and so on). Some of the elements in the list above refer to fields defined in the Article Type, like title, intro or full text. Others are objects related to an article, like attachments, maps or comments. There can also be references to objects independent from the article, which are linked to the article in the Article Edit screen of the administration interface, like authors.
You are advised to use the {{ include }} feature of the template engine to manage all possible shapes and forms an article can take. Chop your article template into sub-templates and call them in when and where you need them. As we already described in a previous chapter on cutting a HTML page into templates, it is much easier to divide a template into pieces and use includes.
You can take a look at the example article.tpl in the template pack "The Journal".
Best practice is to separate the main article content from the other auxiliary parts. That's why we have different template includes like:
{{ include file="set_thejournal/_tpl/article-cont.tpl" }}
{{ include file="set_thejournal/_tpl/article-comments.tpl" }}
{{ include file="set_thejournal/_tpl/article-map.tpl" }}
{{ include file="set_thejournal/_tpl/sidebar-related.tpl" }}
Let's take a look at what is going on inside the _tpl/article-cont.tpl file:

Design delivered by template _tpl/article-cont.tpl
The article title is the most important thing in the Article. It should use either the <h1> or <h2> heading tag (depending on how you decided to mark up your publication name; see more on these issues in the chapter on Search Engine Optimisation):
<h2>{{ $gimme->article->name }}</h2>
You can refer to the publish date and the section where the article came from. Article authors, photographers and other contributors are being mentioned next.
Published on {{ $gimme->article->publish_date|camp_date_format:"%e %M %Y" }}
in <a href="{{ uri options="section" }}">{{ $gimme->section->name }}</a>
<br />
By: {{ list_article_authors }}
{{ $gimme->author->name }} ({{ $gimme->author->type|lower }})
{{ if !$gimme->current_list->at_end }}, {{ /if }}
{{ /list_article_authors }}
Do you map and display locations? Great! Here is how to display them on the page:
Location(s): {{ list_article_locations }}
{{ if $gimme->location->enabled }}{{ $gimme->location->name }}
{{ if $gimme->current_list->at_end }}{{ else }}, {{ /if }}
{{ /if }}
{{ /list_article_locations }}
Now let's start the story. In the following code snippet we will display the introduction from the article, using the Article Field intro. We are also checking if the image with the number 1 is present and present it accordingly. The last line lists the rest of the story, stored in the Article Field full_text.
{{if $gimme->article->has_image(1)}}<img src="{{url options="image 1"}}" alt="{{$gimme->article->image1->description}}" />{{/if}}
<div class="intro">{{ $gimme->article->intro }}</div>
<div class="full_text">{{ $gimme->article->full_text }}</div>
Not that difficult, is it? If you are still with us, go an extra round and check if the content is actually available to the reader, with $gimme->article->content_accessible. If the value returned is TRUE, either the article is available to everybody or the reader is logged in and has the right to access the article. You can find more on subscription management in the section of this Cookbook on Advanced templating.
{{ if $gimme->article->content_accessible }}
{{if $gimme->article->has_image(1)}}<img src="{{url options="image 1"}}" alt="{{$gimme->article->image1->description}}" />{{/if}}
<div class="intro">{{ $gimme->article->intro }}</div>
<div class="full_text">{{ $gimme->article->full_text }}</div>
{{ else }}
<p>This article is accessible only to registered and logged in users!</p>
{{ /if }}
As you can see, the article-cont.tpl sub-template is mostly about the article content itself. The rest are auxiliary, but very important parts. They are also included in the article.tpl template.
Article Comments
Comments are explained in more detail in the following chapter. We believe that they are an essential way to communicate with your audience - and for your audience to communicate among themselves. In "The Journal" template pack, comments look like this:

Screenshot from the comments on "The Journal" template package.
Article Map
To round up the article page, here is the line that displays a map with locations that have been set in the Article Edit page by your journalists. There is more about maps and geolocation in a later chapter.
<div class="widget block"><h3>Map</h3>
{{ map show_locations_list="true" show_reset_link="Show initial Map" width="300" height="250" }}
</div>

Map embedded in article. Locations are handled in the Article Edit screen.
Article Attachments
Journalists can attach files to an article. We also include them in the article.tpl as a separate sub-template article-attachments.tpl. The code snippet below checks if attachments are present, and displays a list if there are.
{{if $gimme->article->has_attachments}}
<ul>
{{list_article_attachments}}
<li>
<a href="{{uri options="articleattachment"}}">
{{$gimme->attachment->file_name}}</a>
[{{ $gimme->attachment->extension }}|{{$gimme->attachment->size_kb}}Kb]
<br />
{{$gimme->attachment->description}}
</li>
{{/list_article_attachments}}
</ul>
{{/if}}
Listing Articles
You can create lists of articles, which is usually done inside a section overview of the content. But it can also be interesting to use this on the article page for "further reading" or "related articles".
Listing articles with list_articles is the most powerful and mostly used statement in Newscoop. You can check the Template Reference at the end of this Cookbook for all function options. Here are just a few examples to give you a taste:
List the last 10 articles:
{{ list_articles length="10" order="byPublishDate desc" ignore_issue="true" ignore_section="true"}}
{{* code goes here *}}
{{ /list_articles }}
Show last published article, of type 'article', from section number 100, regardless of issue:
{{list_articles length="1" constraints="type is article section is 100" ignore_issue="true" order="bypublishdate desc"}}
{{* code goes here *}}
{{/list_articles}}
List the last article from section numbers 100 to 140:
{{ list_sections constraints="number greater_equal 100 number smaller_equal 140" }}
{{ list_articles length="1" ignore_issue="true" order="byPublishDate desc" }}
{{* code goes here *}}
{{/list_articles}}
{{/list_sections}}
List 10 more articles from the same section, ordered by publish date, excluding the one already defined:
{{list_articles length="10" constraints="number not `$gimme->default_article->number`" ignore_issue="true" order="bypublishdate desc"}}
{{* code goes here *}}
{{/list_articles}}
Audio player for attached MP3 files
Newscoop has an easy mechanism for attaching files to articles. In the Article Edit screen, on the right, you can attach files either from the existing file archive or upload new files. In this example we will embed an MP3 player in the page, playing audio files which have been attached to the article.
We offer two different examples of using an embedded Flash player. The first example embeds a player at the end of an article, like this:

Audio player on intex-press.by
The player we're using in this example needs to be placed in this folder:
/templates/_swf/player_mp3_maxi.swf
Any other player and any other folder location is possible. You only need to change the path in the code accordingly.
This code snippet will:
- Check to see if the article has any attachments; if it does, it will list them
- Check to see if the attachment has an extension of "mp3"
- If it is mp3, it will:
-
- Display the attachment's file description
- Call the Flash player and set its values
- Give the Flash player the URI for the article attachment
- Create a download link for the article attachment with its URI, file name and size
{{ if $gimme->article->has_attachments }}
{{ list_article_attachments }}
{{ if $gimme->attachment->extension == "mp3" }}
{{ $gimme->attachment->description }}<br />
<object height="20" width="200" data="/templates/_swf/player_mp3_maxi.swf" type="application/x-shockwave-flash" align="top">
<param value="/templates/_swf/player_mp3_maxi.swf" name="movie" />
<param name="wmode" value="opaque" />
<param value="mp3={{ uri options="articleattachment" }}&showstop=1&showvolume=1&buttonwidth=25&sliderwidth=15&bgcolor1=5EA65E&bgcolor2=365E36" name="FlashVars" />
</object><br />
<a href="{{ uri options="articleattachment" }}" />{{ $gimme->attachment->file_name }}, {{ $gimme->attachment->size_kb }}Kb</a>
{{/if}}
{{/list_article_attachments}}
{{/if}}
Using multiple players
The second example comes from Fluter.de, and involves keywords and multiple players. Here is a screenshot of how the players appear on the page:

Audio players on fluter.de
This example does the following:
- Uses an IF statement to see if the article has the keyword of 'mp3podcast1'
- If it does, Newscoop calls a Flash player
- Newscoop passes the Flash player the URL of the MP3 file
The audio files on Fluter.de are not article attachments. In the editorial workflow of that publication, the audio files are created separately and uploaded to a special location on the server. The code example below will point to the location:
http://www.fluter.de/medien/podcast_audio/
There, the audio files are sorted in subfolders by issue number, which we can retrieve using {{ $gimme->issue->number }}. Each file name contains a combination of issue number and article number, and finishes with the track number, so we can retrieve a specific file using:
podcast_mp3_{{ $gimme->issue->number }}_{{ $gimme->article->number }}_f1.mp3
The publication editor adds a keyword to the article containing the number of the audio files; mp3podcast1 means one file, mp3podcast2 two files, and so on. Depending on this keyword, the template will create one or more players. Here is the code for one player:
{{ if $gimme->article->has_keyword(mp3podcast1) }}
<object type="application/x-shockwave-flash" data="/medien/player/player.swf" width="290" height="24" id="audioplayer1"><param name="movie" value="http://www.fluter.de/audio-player/player.swf" />
<param name="FlashVars" value="playerID=1&bg=0x999999&leftbg=0x74787A&lefticon=0xffffff&rightbg=0x0090f0&rightbghover=0x74787A&righticon=0x000000&righticonhover=0x0090f0&text=0xffffff&slider=0x0090f0&track=0xFFFFFF&border=0xffffff&loader=0xffffff&soundFile=http%3A%2F%2Fwww.fluter.de%2Fmedien%2Fpodcast_audio%2F{{ $gimme->issue->number }}%2Fpodcast_mp3_{{ $gimme->issue->number }}_{{ $gimme->article->number }}_f1.mp3" />
<param name="quality" value="high" />
<param name="menu" value="false" />
<param name="bgcolor" value="#ffffff" />
</object>
{{ /if }}
This approach can be used for any file attachments; you can apply similar methods for PDF attachments or movies, for example. See the section Article object and attachment, comment, location in the Template Reference for more information on working with article attachments.
Managing multiple authors and articles
Newscoop has a built in author management tool in which you can create and edit author accounts, with biographies, pictures and other information. You can also create different kinds of author accounts, for photographers, translators, researchers or other contributors - multiple authors can be assigned to a single article.

The following sample code will explain how to print author information when displaying an article. You can print an author's last and first name, their image URL, full name, author type (photographer, etc.), their email address and biographical text.
<ul>
{{ list_article_authors }}
<li style="clear: left;">
<strong>{{ $gimme->author->last_name }}</strong>, {{ $gimme->author->first_name }}<br />
<img src="{{ $gimme->author->picture->imageurl }}" align="left" width="66px">
{{ $gimme->author->name }}
({{ $gimme->author->type }}):
<a href="mailto:{{ $gimme->author->email }}">{{ $gimme->author->email }}</a>
{{ $gimme->author->biography->text }}
</li>
{{ /list_article_authors }}
</ul>
Author and author biography
Author
Note: this works only in Newscoop 3.5.0 and newer versions.
The article author object is usually initialized inside a list of article authors. It is also always possible to access this object for the current article in the environment (see "Article"). It is not initialized at the beginning of the template and can not be initialized by other Newscoop functions. The article author object has the following properties:
- first_name: the author's first name
- last_name: the author's last name
- name: the author's full name
- email: the author's e-mail address
- type: the author type
- biography: the author biography - see "Author Biography" object
- picture: the author picture - see "Image" object
- defined: boolean value (true/false) - true if the author was set in the current environment; false otherwise
Examples
{{ list_article_authors order="bylastname" }}
<p class="author-head">
{{ $gimme->author->type }}: {{ $gimme->author->name }}
</p>
<p class="author-bio">
<img src="{{ $gimme->author->picture->imageurl }}" class="author-pic">
{{ $gimme->author->biography->text }}
</p>
{{ /list_article_authors }}
{{ if $gimme->article->defined }} by
{{ $gimme->article->author->first_name }}
{{ $gimme->article->author->last_name }}
{{ $gimme->article->author->type }}
{{ /if }}
Author Biography
Note: this works only in Newscoop 3.5.0 and newer versions.
The author biography object is usually initialized within the "Author" object. It is not a main object as it can only be used through the "Author" object. Also, it is not initialized at the beginning of the template and cannot be initialized by other Newscoop functions. The author biography object has the following properties:
- first_name: the translated author's first name
- last_name: the translated author's last name
- name: the translated author's full name
- text: the translated author's biography
- defined: boolean value (true/false) - true if the author biography was set in the current environment; false otherwise
Example
{{ if $gimme->article->defined }} by
{{ $gimme->article->author->biography->name }}
({{ $gimme->article->author->type }})<br />
<p>{{ $gimme->article->author->biography->text }}</p>
{{ /if }}
Basic syntax
The Newscoop template engine was built on Smarty, so the Newscoop template language is actually an extension of the Smarty template language. For details of the Smarty template language please read: http://smarty.net/manual/en/smarty.for.designers.php
All template tags are enclosed within delimiters. By default in Smarty these are the single curly brackets { and } but they can be changed. In Newscoop we use the double curly brackets {{ and }} for template tag delimiters.
For the examples in this Cookbook, we will assume that you are using the default Newscoop delimiters. All content outside of delimiters is displayed as static content, or unchanged. When the template engine encounters template tags, it attempts to interpret them, and displays the appropriate output in their place.
The following sub-chapters, which were copied from the Smarty manual, will familiarize you with the Smarty syntax.
Attributes
Most of the functions take attributes that specify or modify their behaviour. Attributes to Smarty functions are much like HTML attributes. Static values don't have to be enclosed in quotes, but it is recommended for literal strings. Variables may also be used, and should not be in quotes.
Some attributes require boolean values (TRUE or FALSE). These can be specified as either unquoted true, on, and yes; or false, off, and no.
{{include file='header.tpl'}}
{{include file='header.tpl' attrib_name='attrib value'}}
{{include file=$includeFile}}
{{include file=#includeFile# title='Smarty is cool'}}
{{html_select_date display_days=yes}}
{{mailto address='smarty@example.com'}}
<select name='company_id'>
{{html_options options=$companies selected=$company_id}}
</select>
Comments
Template comments are surrounded by asterisks, and then surrounded by the delimiter tags like this:
{{* this is a comment *}}
Comments are NOT displayed in the final output of the template, unlike <!-- HTML comments -->. These are useful for making internal notes in the templates which no one will see.
{{* I am a template comment, I don't exist in the compiled output *}}
<html>
<head>
<title>{{$title}}</title>
</head>
<body>
{{* another single line comment *}}
<!-- HTML comment that is sent to the browser -->
{{* this multiline
comment is
not sent to browser
*}}
{{*********************************************************
Multi line comment block with credits block
@ author: bg@example.com
@ maintainer: support@example.com
@ para: var that sets block style
@ css: the style output
**********************************************************}}
{{* The header file with the main logo and stuff *}}
{{include file='header.tpl'}}
{{* Dev note: the $includeFile var is assigned in foo.php script *}}
<!-- Displays main content block -->
{{include file=$includeFile}}
{{* this <select> block is redundant *}}
{{*
<select name="company">
{{html_options options=$vals selected=$selected_id}}
</select>
*}}
<!-- Show header from affiliate is disabled -->
{{* $affiliate|upper *}}
{{* you cannot nest comments *}}
{{*
<select name="company">
{{* <option value="0">-- none -- </option> *}}
{{html_options options=$vals selected=$selected_id}}
</select>
*}}
{{* cvs tag for a template, below the 36 SHOULD be an american currency
. however its converted in cvs.. *}}
{{* $Id: Exp $ *}}
{{* $Id: *}}
</body>
</html>
Embedding vars in double quotes
Smarty will recognize assigned variables embedded in "double quotes" so long as the variable name contains only numbers, letters, under_scores and square brackets []. See the PHP naming documentation at http://php.net/language.variables for more detail.
With any other characters, for example a .period or $object>reference, then the variable must be surrounded by `backticks`.
You cannot embed modifiers, they must always be applied outside of quotes.
{{func var="test $foo test"}} <-- sees $foo
{{func var="test $foo_bar test"}} <-- sees $foo_bar
{{func var="test $foo[0] test"}} <-- sees $foo[0]
{{func var="test $foo[bar] test"}} <-- sees $foo[bar]
{{func var="test $foo.bar test"}} <-- sees $foo (not $foo.bar)
{{func var="test `$foo.bar` test"}} <-- sees $foo.bar
{{func var="test `$foo.bar` test"|escape}} <-- modifiers outside quotes!
Here are some practical examples:
{{* will replace $tpl_name with value *}}
{{include file="subdir/$tpl_name.tpl"}}
{{* doesn't replace $tpl_name *}}
{{include file='subdir/$tpl_name.tpl'}}
{{* must have backticks as it contains a . *}}
{{cycle values="one,two,`$smarty.config.myval`"}}
{{* same as $module['contact'].'.tpl' in a php script *}}
{{include file="`$module.contact`.tpl"}}
{{* same as $module[$view].'.tpl' in a php script *}}
{{include file="$module.$view.tpl"}}
Escaping Smarty parsing
It is sometimes desirable or even necessary to have Smarty ignore sections it would otherwise parse. A classic example is embedding Javascript or CSS code in a template. The problem arises as those languages use the { and } characters which are also the default delimiters for Smarty.
The simplest thing is to avoid the situation altogether by separating your Javascript and CSS code into their own files and then using standard HTML methods to access them.
Including literal content is possible using literal../literal blocks. Similar to HTML entity usage, you can use ldelim, rdelim or $smarty.ldelim to display the current delimiters.
Functions
Every Smarty tag either prints a variable or invokes some sort of function. These are processed and displayed by enclosing the function and its attributes within delimiters like so: funcname attr1='val1' attr2='val2'.
{{config_load file='colors.conf'}}
{{include file='header.tpl'}}
{{insert file='banner_ads.tpl' title='Smarty is cool'}}
{{if $logged_in}}
Welcome, <font >{{$name}}!</font>
{{else}}
hi, {{$name}}
{{/if}}
{{include file='footer.tpl' ad=$random_id}}
- Both built-in functions and custom functions have the same syntax within templates.
- Built-in functions are the inner workings of Smarty, such as if, section and strip. There should be no need to change or modify them.
- Custom functions are additional functions implemented via plugins. They can be modified to your liking, or you can create new ones. html_options and popup are examples of custom functions.
Math
Math can be applied directly to variable values.
{{$foo+1}}
{{$foo*$bar}}
{{* some more complicated examples *}}
{{$foo->bar-$bar[1]*$baz->foo->bar()-3*7}}
{{if ($foo+$bar.test%$baz*134232+10+$b+10)}}
{{$foo|truncate:"`$fooTruncCount/$barTruncFactor-1`"}}
{{assign var="foo" value="`$foo+$bar`"}}
Variable modifiers
Modifiers can be applied to variables, custom functions or strings. To apply a modifier, specify the value followed by a | (pipe) and the modifier name. A modifier may accept additional parameters that affect its behaviour. These parameters follow the modifier name and are separated by a : (colon). Also, all PHP functions can be used as modifiers implicitly (more below) and modifiers can be combined.
{{* apply modifier to a variable *}}
{{$title|upper}}
{{* modifier with parameters *}}
{{$title|truncate:40:'...'}}
{{* apply modifier to a function parameter *}}
{{html_table loop=$myvar|upper}}
{{* with parameters *}}
{{html_table loop=$myvar|truncate:40:'...'}}
{{* apply modifier to literal string *}}
{{'foobar'|upper}}
{{* using date_format to format the current date *}}
{{$smarty.now|date_format:"%Y/%m/%d"}}
{{* apply modifier to a custom function *}}
{{mailto|upper address='smarty@example.com'}}
{{* using php's str_repeat *}}
{{'='|str_repeat:80}}
{{* php's count *}}
{{$myArray|@count}}
{{* php's shuffle on servers's ip *}}
{{$smarty.server.SERVER_ADDR|shuffle}}
{{* this will uppercase and truncate the whole array *}}
<select name="name_id">
{{html_options output=$myArray|upper|truncate:20}}
</select>
If you apply a modifier to an array variable instead of a single value variable, the modifier will be applied to every value in that array. If you really want the modifier to work on an entire array as a value, you must prepend the modifier name with an @ symbol.
For example:
{{$articleTitle|@count}}
will print out the number of elements in the $articleTitle array using the php count() function as a modifier.
Modifiers are autoloaded from the $plugins_dir or can be registered explicitly with the register_modifier() function. The later is useful for sharing a function between PHP scripts and Smarty templates.
All PHP functions can be used as modifiers implicitly, as demonstrated in the example above. However, using PHP functions as modifiers has two little pitfalls:
First - sometimes the order of the function-parameters is not the desirable one. Formatting $foo with {{"%2.f"|sprintf:$foo}} actually works, but asks for the more intuitive, like {{$foo|string_format:"%2.f"}} that is provided by the Smarty distribution.
Secondly - if $security is enabled, all PHP functions that are to be used as modifiers have to be declared trusted in the MODIFIER_FUNCS element of the $security_settings array
You can apply any number of modifiers to a variable. They will be applied in the order they are combined, from left to right. They must be separated with a | (pipe) character:
{{$articleTitle}}
{{$articleTitle|upper|spacify}}
{{$articleTitle|lower|spacify|truncate}}
{{$articleTitle|lower|truncate:30|spacify}}
{{$articleTitle|lower|spacify|truncate:30:". . ."}}
Variables
Template variables start with the $dollar sign. They can contain numbers, letters and underscores, much like a PHP variable. You can reference arrays by index numerically or non-numerically. Also reference object properties and methods.
Config file variables are an exception to the $dollar syntax and are instead referenced with surrounding #hashmarks#, or via the $smarty.config variable.
{{$foo}} <-- displaying a simple variable (non array/object)
{{$foo[4]}} <-- display the 5th element of a zero-indexed array
{{$foo.bar}} <-- display the "bar" key value of an array, similar to PHP $foo['bar']
{{$foo.$bar}} <-- display variable key value of an array, similar to PHP $foo[$bar]
{{$foo->bar}} <-- display the object property "bar"
{{$foo->bar()}} <-- display the return value of object method "bar"
{{#foo#}} <-- display the config file variable "foo"
{{$smarty.config.foo}} <-- synonym for {{#foo#}}
{{$foo[bar]}} <-- syntax only valid in a section loop, see {{section}}
{{assign var=foo value='baa'}}{{$foo}} <-- displays "baa", see {{assign}}
Many other combinations are allowed:
{{$foo.bar.baz}}
{{$foo.$bar.$baz}}
{{$foo[4].baz}}
{{$foo[4].$baz}}
{{$foo.bar.baz[4]}}
{{$foo->bar($baz,2,$bar)}} <-- passing parameters
{{"foo"}} <-- static values are allowed
{{* display the server variable "SERVER_NAME" ($_SERVER['SERVER_NAME'])*}}
{{$smarty.server.SERVER_NAME}}
Search templates
You can control your search form and search results with templates. This gives you design freedom for the list of results, as well as the complexity and appearance of your search form.
The Search Form
Using the default Newscoop function {{ searform }} creates a form like the following screenshot:

You can use the following code to create the form:
<h3>Search Articles</h3>
{{ searform template="search.tpl" submit_button="Search" html_code="class=\"group\" id=\"search-form\"" button_html_code="id=\"search-button\"" }}
{{ camp_edit object="search" attribute="keywords" html_code="id=\"search-field\"" }}
{{ /searform }}
The search terms are sent to the sub-template specified inside the function: search.tpl. (Note: if your search.tpl file is inside a folder, you need to specify the full path, the same as with the include function. You can also see how different html classes/IDs can be added to the form elements (using html_code and button_html_code; quotes inside need to be escaped), and how the submit_button text is defined (submit_button="Search").
To create a search form which doesn't have a button with text, but an image like the one shown below, you can use the following approach.

<div class="search">
{{ searform template="search.tpl" submit_button=" " html_code="id=\"topSearch\"" button_html_code="class=\"replace\"" }}
<p class="fields">
{{ camp_edit object="search" attribute="keywords" html_code="id=\"s\" }}
</p>
{{ /searform }}
</div><!-- /.search -->
Search results
First, here is the example code for the search results template search.tpl:
<div id="main">
<h1>Search results</h1>
{{ list_searresults length="5" order="bypublishdate desc" constraints="type is news" }}
<div class="post">
<h2 class="post-title"><a href="{{ uri options="article" }}" rel="bookmark" title="{{ $gimme->article->name }}</a></h2>
<p class="post-details">Published on {{ $gimme->article->publish_date|camp_date_format:"%e %M %Y" }} by {{ $gimme->article->author->name }} in <a href="{{ uri options="section" }}">{{ $gimme->section->name }}</a></p>
{{ if $gimme->article->has_image(1) }}<a title="{{ $gimme->article->name }}" href="{{ uri options="article" }}"><img src="{{ uri options="image 1 width 134"}}" alt="{{ $gimme->article->image->description }}" class="woo-image thumbnail"></a>{{ /if }}
<p>{{ $gimme->article->deck }}</p>
</div><!-- /.post -->
{{ if $gimme->current_list->at_end }}
<div class="more_entries">
<div class="alignleft">{{ if $gimme->current_list->has_previous_elements }}<a href="{{ uripath options="template search.tpl" }}?{{ urlparameters options="previous_items" }} ">« Newer Entries</a>{{ /if }}</div>
<div class="alignright">{{ if $gimme->current_list->has_next_elements }}<a href="{{ uripath options="template search.tpl" }}?{{ urlparameters options="next_items" }}">Older Entries »</a>{{ /if }}</div>
</div>
{{ /if }}
{{ /list_searresults }}
{{ if $gimme->prev_list_empty }}
<div class="postinformation">No results found</div>
{{ /if }}
</div><!-- /#main -->
Inside the list of search results, we have a div container of the class "post" which is being repeated as many times as there are results for the search terms. List length is limited to 5, so if there are more than five list elements, a link to the next page is created. The link to the previous page is also created, in case the reader is not on the first page of search results. All of this is done inside an if statement:
{{ if $gimme->current_list->at_end }}
....
{{ /if }}
You can also find a neat pagination example in the advanced section of this manual, where pagination is explained. If no search results were found, Newscoop would display a message like this:
{{ if $gimme->prev_list_empty }}
<div class="postinformation">No results found</div>
{{ /if }}
The parameter prev_list_empty refers to the list just before this statement - which was the search results list. In case the list of search results was empty, this sends an appropriately apologetic message.
Advanced search
Newscoop also offers 'advanced search' options. An advanced search form may appear to your publication's readers like this screenshot:

The code which generates this form is shown below:
{{ searform template="search.tpl" submit_button="Search" button_html_code="id=\"adv-search-button\" class=\"rounded\"" }}
<div class="left">
<div class="form-element">
<label>Search by:</label>
<input class="radio" name="f_searscope" value="content" checked="checked" type="radio">text
<input class="radio" name="f_searscope" value="title" type="radio">title
<input class="radio" name="f_searscope" value="author" type="radio">author
</div>
<div class="form-element">
<label for="adv-search">Keyword:</label>
{{ camp_edit object="search" attribute="keywords" html_code="id=\"adv-search\"" }}
</div>
<div class="form-element">
<label for="adv-select">Issue:</label>
{{ camp_select object="search" attribute="issue" html_code="id=\"adv-select\"" }}
</div>
<div class="form-element">
<label>Date:</label>
<div class="g-left">from {{ camp_edit object="search" attribute="start_date" }}</div>
<div class="g-right">to {{ camp_edit object="search" attribute="end_date" }}</div>
</div>
</div><!-- /.left -->
<div class="right">{{ /searform }}</div>
This form is different than the simple search form earlier in this chapter, as it has more options for filtering the results of the search. Firstly, the reader has the option to narrow their search only to article text, article title, or article author, by selecting the appropriate radio button. The generated HTML for this part of the form looks like this:
<div class="form-element">
<label>Search by:</label>
<input class="radio" name="f_searscope" value="content" checked="checked" type="radio">text
<input class="radio" name="f_searscope" value="title" type="radio">title
<input class="radio" name="f_searscope" value="author" type="radio">author
</div>
Next, the reader has the option to select a particular issue to narrow down their search, and this part of the code is responsible for that feature:
<div class="form-element">
<label for="adv-select">Issue:</label>
{{ camp_select object="search" attribute="issue" html_code="id=\"adv-select\"" }}
</div>
The HTML generated after template parsing is:
<div class="form-element">
<label for="adv-select">:</label>
<select name="f_searissue" id="adv-select">
<option value="0" selected="selected"> </option>
<option value="8">8. Issue 8 (2011-03-18 08:00:08)</option>
....
<option value="1">1. Issue 1 (2010-12-02 08:00:07)</option>
</select>
</div>
The final option is to specify the time frame from which the reader wants to get search results. This is done with inline date choosers:
<div class="form-element">
<label>Date:</label>
<div class="g-left">from {{ camp_edit object="search" attribute="start_date" }}</div>
<div class="g-right">to {{ camp_edit object="search" attribute="end_date" }}</div>
</div>
The HTML that gets generated by this piece of Newscoop code is rather too long for this book. You can style the start and end date fields in CSS with the following id's:
#advanced-search #f_searend_date,
#advanced-search #f_searstart_date {
width: 58px;
}
If you need to style the calendar that pops up when the reader clicks the date chooser field, there is the file javascript/jscalendar/calendar-system.css in your Newscoop installation. Feel free to play with it.
Browser detection and robots (search engines)
For advanced web design, it is helpful to know more about the browser where the site is being displayed. You can also detect if your pages are being grabbed by a search engine robot, and deliver content accordingly. For example, if you are using a subscription model for your publication, you can display more information to the search engine robot than you would to an anonymous reader. This way, the search engines will list your content more descriptively than if they only grabbed the "please subscribe" page.
This chapter will give you some ideas on how to detect the client browser, or search engine robot, and change your templates accordingly. The template reference at the end of this Cookbook provides all the options for the browser object.
This is the kind of information Newscoop can get from a browser or robot:
iPhone browser
- Browser: safari, version 528.16 | Engine: webkit, version 528.18
- Mobile: device: iphone | OS: iphone os | OS version: 3.0
- Bot: no
- Type: mobile = handheld
Google Chrome browser
- Browser: chrome, version 10.0.648.205 | Engine: webkit, version 534.16
- Mobile: no
- Bot: no
- Type: bro = normal browser
Firefox browser
- Browser: firefox, version 3.6.16 | Engine: gecko, version 1.9
- Mobile: no
- Bot: no
- Type: bro = normal browser
Google robot
- Browser: googlebot, version 2.1 | Engine: false, version false
- Mobile: no
- Bot: yes
- Type: bot = web bot
The easy CSS way: classes in the body tag
An easy way to deliver different styles to different browsers is to add classes to the body tag, and then apply changes using CSS. Here some examples of the information you can print in the body tag with Newscoop:
iPhone 3
<body class="webkit mobile safari iphone iphoneos iphoneos3 iphoneos3-0 safari528 safari528-16" >
Firefox 3.6.16
<body class="moz bro gecko firefox firefox3 firefox3-6 firefox3-6-16 gecko1 gecko1-9" >
Internet Explorer 8
<body class="ie bro msie msie8 msie8-0 trident" >
Google Bot 2.1
<body class="google bot googlebot" >
Chrome 10.0.648.205
<body class="webkit bro chrome chrome10 chrome10-0-648-205" >
You can get these rich body tags using the following code snippet. Note: {{ textformat wrap=200 }} is used in this example to list all the classes in one line and avoid line breaks. The first line break would be applied after 200 characters - which is beyond what this code will deliver. Throw out what you don't need. You could also place the template in a separate file and use {{ include }}.
<body class="{{ textformat wrap=200 }}
{{ $gimme->browser->browser_working }}
{{ $gimme->browser->ua_type }}
{{ $gimme->browser }}
{{* mobile device / OS *}}
{{ $gimme->browser->mobile_data.0 }}
{{ $gimme->browser->mobile_data.3|regex_replace:"/\ /":"" }}
{{ strip }}{{ $gimme->browser->mobile_data.3|regex_replace:"/\ /":"" }}
{{ $gimme->browser->mobile_data.4|regex_replace:"/[\.][0-9]*/":"" }}{{ /strip }}
{{ strip }}{{ $gimme->browser->mobile_data.3|regex_replace:"/\ /":"" }}
{{ $gimme->browser->mobile_data.4|regex_replace:"/\./":"-" }}{{ /strip }}
{{* firefox / gecko *}}
{{ $gimme->browser->moz_data.0 }}
{{ strip }}{{ $gimme->browser->moz_data.0 }}
{{ $gimme->browser->moz_data.1|regex_replace:"/[\.][0-9]*/":"" }}{{ /strip }}
{{ strip }}{{ $gimme->browser->moz_data.0 }}
{{ $gimme->browser->moz_data.1|regex_replace:"/[\.][0-9]*$/":""|regex_replace:"/\./":"-" }}{{ /strip }}
{{ strip }}{{ $gimme->browser->moz_data.0 }}
{{ $gimme->browser->moz_data.1|regex_replace:"/\./":"-" }}{{ /strip }}
{{ if $gimme->browser->browser_working == "moz" }}
gecko{{ $gimme->browser->moz_data.2|regex_replace:"/[\.][0-9]*/":"" }}
gecko{{ $gimme->browser->moz_data.2|regex_replace:"/\./":"-" }}
{{ /if }}
{{* internet explorer *}}
{{ if $gimme->browser->browser_working == "ie" }}
{{ strip }}{{ $gimme->browser->browser_name }}
{{ $gimme->browser->webkit_data.2|regex_replace:"/[\.][0-9]*/":"" }}{{ /strip }}
{{ strip }}{{ $gimme->browser->browser_name }}
{{ $gimme->browser->webkit_data.2|regex_replace:"/\./":"-" }}{{ /strip }}
{{ if $gimme->browser->webkit_data.2 > 8 }}chakra{{ else }}trident{{ /if }}
{{ /if }}
{{* chrome *}}
{{ if $gimme->browser->browser_working == "webkit" }}
{{ strip }}{{ $gimme->browser->webkit_data.0 }}
{{ $gimme->browser->webkit_data.1|regex_replace:"/[\.][0-9]*/":"" }}{{ /strip }}
{{ strip }}{{ $gimme->browser->webkit_data.0 }}
{{ $gimme->browser->webkit_data.1|regex_replace:"/\./":"-" }}{{ /strip }}
{{ /if }}
{{ /textformat }}" >
Full template control: browser_detection.tpl
To collect the information listed at the beginning of this chapter, you can use the sub-template browser_detection.tpl. It should be called in the header of your pages, and will return a set of variables that make it easy to manage your templates for different browsers or robots. Here is the code for browser_detection.tpl:
{{* gecko / firefox ***********************************}}
{{ if $gimme->browser->browser_working == "moz" }}
{{ assign var="browserdetect_name" value=`$gimme->browser->moz_data.0` }}
{{ assign var="browserdetect_version" value=`$gimme->browser->moz_data.1` }}
{{ assign var="browserdetect_engineversion" value=`$gimme->browser->moz_data.2` }}
{{ assign var="browserdetect_engine" value="gecko" }}
{{ /if }}
{{* webkit / chrome / safari ***********************************}}
{{ if $gimme->browser->browser_working == "webkit" }}
{{ assign var="browserdetect_engineversion" value=`$gimme->browser->browser_number` }}
{{ assign var="browserdetect_name" value=`$gimme->browser->webkit_data.0` }}
{{ assign var="browserdetect_version" value=`$gimme->browser->webkit_data.1` }}
{{ assign var="browserdetect_engine" value="webkit" }}
{{ /if }}
{{* ie / internet explorer ***********************************}}
{{ if $gimme->browser->browser_working == "ie" }}
{{ assign var="browserdetect_name" value=`$gimme->browser->browser_name` }}
{{ assign var="browserdetect_engineversion" value=`$gimme->browser->webkit_data.2` }}
{{ assign var="browserdetect_version" value=`$gimme->browser->webkit_data.2` }}
{{ if $gimme->browser->webkit_data.2 > 8 }}
{{ assign var="browserdetect_engine" value="chakra" }}
{{ else }}
{{ assign var="browserdetect_engine" value="trident" }}
{{ /if }}
{{ /if }}
{{* bot / search engine ***********************************}}
{{ if $gimme->browser->ua_type == "bot" }}
{{ assign var="browserdetect_name" value=`$gimme->browser->browser_name` }}
{{ assign var="browserdetect_version" value=`$gimme->browser->browser_math_number` }}
{{ assign var="browserdetect_engine" value="false" }}
{{ assign var="browserdetect_engineversion" value="false" }}
{{ /if }}
{{* mobile devices ******************************************}}
{{ if $gimme->browser->ua_type != "mobile" }}
{{ assign var="browserdetect_mobile_device" value="false" }}
{{ assign var="browserdetect_mobile_os" value="false" }}
{{ assign var="browserdetect_mobile_os_number" value="false" }}
{{ else }}
{{ assign var="browserdetect_mobile_device" value=`$gimme->browser->mobile_data.0` }}
{{ assign var="browserdetect_mobile_os" value=`$gimme->browser->mobile_data.3` }}
{{ assign var="browserdetect_mobile_os_number" value=`$gimme->browser->mobile_data.4` }}
{{ /if }}
Save the code snippet above inside the _tpl folder of your template package. If you are using "The Journal" template pack, include it like this:
{{ include file="set_thejournal/_tpl/browser_detection.tpl" }}
If your template package has a different name, adjust the path accordingly. After the template has been called, the information about the browser listed earlier can be displayed by these lines:
<ul>
<li>Browser: {{ $browserdetect_name }}, version {{ $browserdetect_version }}
| Engine: {{ $browserdetect_engine }}, version {{ $browserdetect_engineversion }}</li>
<li>Mobile: {{ if $browserdetect_mobile_device == "false" }}no{{ else }}
device: {{ $browserdetect_mobile_device }} |
OS: {{ $browserdetect_mobile_os }} |
OS version: {{ $browserdetect_mobile_os_number }}
{{ /if }}</li>
<li>Bot: {{ if $gimme->browser->ua_type == "bot" }}yes{{ else }}no{{ /if }}</li>
<li>Type: {{ $gimme->browser->ua_type }} =
{{ if $gimme->browser->ua_type == "bot" }}web bot{{ /if }}
{{ if $gimme->browser->ua_type == "bro" }}normal browser{{ /if }}
{{ if $gimme->browser->ua_type == "bbro" }}simple browser{{ /if }}
{{ if $gimme->browser->ua_type == "mobile" }}handheld{{ /if }}
{{ if $gimme->browser->ua_type == "dow" }}downloading agent{{ /if }}
{{ if $gimme->browser->ua_type == "lib" }}http library{{ /if }}
</li>
Browser
(This chapter is based on the PHP browser detection script by Harald Hope, available under GNU GPL v3 from: http://techpatterns.com/downloads/scripts/browser_detection_php_ar.txt)
The browser object is set at the beginning of the main template based on the request URL. The browser object can be called as follows:
{{ $gimme->browser }} or {{ $gimme->browser->browser_name }}
The above statement returns the full browser name string, if available, otherwise it returns ''. The statement:
{{ $gimme->browser->browser_number }}
returns the browser version number, if available, otherwise it returns ''. The statement:
{{ $gimme->browser->browser_working }}
returns the working shorthand browser name: ie, op, moz, konq, saf, ns4, webkit, and some others. If not shorthand, it will probably just return the full browser name, like lynx. The statement:
{{ $gimme->browser->dom }}
returns true/false if it is a basic dom browser, ie >= 5, opera >= 5, all new mozillas, safaris, or konquerors. The statement:
{{ $gimme->browser->ie_version }}
tests to see what general IE it is. Possible return values:
ie9x - all new msie 9 or greater - note that if in compat mode, 7,8,9 all show as 7
ie7x - all new msie 7 or greater
ie5x - msie 5 and 6, not mac
ieMac - msie 5.x mac release
ie4 - msie 4
old - pre msie 4
The statement:
{{ $gimme->browser->mobile_data }}
returns an array of data about mobiles. Note the browser/os number data is very unreliable so don't count on that. No Blackberry version handling is done explicitly. Make sure to test if this is an array, because if it's not mobile it will be null, not an array listed by array index number:
0 - $mobile_device
1 - $mobile_browser
2 - $mobile_browser_number
3 - $mobile_os
4 - $mobile_os_number
5 - $mobile_server
6 - $mobile_server_number
7 - $mobile_device_number
Note: $mobile_browser only returns if a specifically mobile browser is detected, like minimo. Same for mobile os, with the exception of GNU/Linux. Otherwise the standard script os/browser data is used. $mobile_server is a handheld service like docomo, novarro-vision, etc. Sometimes the string will contain no other usable data than this to determine if it's handheld or not.
{{ if $gimme->browser->ua_type != "mobile" }}
{{ assign var="browserdetect_mobile_device" value="false" }}
{{ assign var="browserdetect_mobile_os" value="false" }}
{{ assign var="browserdetect_mobile_os_number" value="false" }}
{{ else }}
{{ assign var="mobile_data" value=`$gimme->browser->mobile_data` }}
{{ php }}
$mobile_data = $this->get_template_vars('mobile_data');
$this->assign('browserdetect_mobile_device', $mobile_data[0]);
$this->assign('browserdetect_mobile_os', $mobile_data[3]);
$this->assign('browserdetect_mobile_os_number', $mobile_data[4]);
{{ /php }}
{{ /if }}
The statement:
{{ $gimme->browser->moz_data }}
returns array of mozilla / gecko information. Return Array listed by index number:
0 - $moz_type [moz version - the specific brand name that is, eg: firefox)
1 - $moz_number - the full version number of $moz_type (eg: for firefox: 3.6+2b)
2 - $moz_rv - the Mozilla rv version number, math comparison version. This tells you what gecko engine is running in the browser (eg rv: 1.8)
3 - $moz_rv_full - rv number (for full rv, including alpha and beta versions: 1.8.1-b3)
4 - $moz_release_date - release date of the browser
{{ if $gimme->browser->browser_working == "moz" }}
{{ assign var="browser_data" value=`$gimme->browser->moz_data` }}
{{ php }}
$browser_data = $this->get_template_vars('browser_data');
$this->assign('browserdetect_name', $browser_data[0]);
$this->assign('browserdetect_engine', "gecko");
$this->assign('browserdetect_engineversion', $browser_data[2]);
$this->assign('browserdetect_version', $browser_data[1]);
{{ /php }}
{{ /if }}
The statement:
{{ $gimme->browser->os }}
returns which os is being used - win, nt, mac, OR iphone, blackberry, palmos, palmsource, symbian, beos, os2, amiga, webtv, linux, unix. The statement:
{{ $gimme->browser->os_number }}
returns windows versions, 95, 98, ce, me, nt: 4; 5 [windows 2000]; 5.1 [windows xp]; 5.2 [Server 2003]; 6.0 [Windows Vista], 6.1 [Windows 7]. Only win, nt, mac, iphone return os numbers (mac/iphone return 10 if OS X.) OR returns GNU/Linux distro/unix release name, otherwise returns null.
{{ $gimme->browser->run_time }}
The time it takes this script to execute from start to point of returning value. Requires PHP 5 or greater. Returns time in seconds to 8 decimal places: 0.00245687. Run time does not count the time used by PHP to include/parse the file initially. That total time is about 5-10x longer. Because subsequent script run-throughs go very fast, you will see the seconds go from something like 0.00115204 for the first time, to something like 0.00004005 for second and more runs. The statement:
{{ $gimme->browser->safe }}
returns true/false, you can determine what makes the browser be safe lower down, currently it's set for ns4 and pre version 1 mozillas not being safe, plus all older browsers. The statement:
{{ $gimme->browser->true_ie_number }}
returns the true version of msie running, ignoring the compat mode version.
Note that php will turn 7.0 to 8 when adding 1, so keep that in mind in your tests. 7.1 will become 8.1 as expected, however. This test currently only tests for 7.x -> 8.x
FYI: in PHP, 7.0 == 7 is true but 7.0 === 7 is NOT true. If this is null but set, then it is NOT running in compatibility mode. The statement:
{{ $gimme->browser->ua_type }}
returns one of the following:
bot (web bot)
bro (normal browser)
bbro (simple browser)
mobile (handheld)
dow (downloading agent)
lib (http library)
The statement:
{{ $gimme->browser->webkit_data }}
returns array of webkit data. The Return Array is listed by index number:
0 - $webkit_type [webkit version name (Eg. chrome)]
1 - $webkit_type_number [webkit version number (Eg. Chrome's: 1.2)]
2 - $browser_number [the actual webkit version number (Eg. Webkit's: 436)]
{{ if $gimme->browser->browser_working == "webkit" }}
{{ assign var="browser_data" value=`$gimme->browser->webkit_data` }}
{{ assign var="browserdetect_engineversion" value=`$gimme->browser->browser_number` }}
{{ php }}
$browser_data = $this->get_template_vars('browser_data');
$this->assign('browserdetect_name', $browser_data[0]);
$this->assign('browserdetect_engine', "webkit");
$this->assign('browserdetect_version', $browser_data[1]);
{{ /php }}
{{ /if }}
Newscoop sites to get you inspired
Before we get right into Newscoop templates, first we can take a look at what others have achieved. Newscoop's community is diverse and international, and the sites it powers are also quite diverse in their coverage and specialization. Some are daily newspaper sites, some are online portals, some are radio stations, and some are superpowered blogs.
fluter.de

A youth culture portal based in Berlin, http://www.fluter.de has been an active member of the Newscoop community almost since its beginning. Fluter's installation makes effective use of jQuery (notably Superfish pulldown menus - described later in this cookbook). Fluter's 'Mediathek' is also notable - it's an online archive of video and audio that uses Newscoop's media archive and enables site visitors to make their own video playlists.
West Africa Democracy Radio
West Africa Democracy Radio http://www.wadr.org is a news and talk radio network, with content broadcast on FM, satellite, and online. It has more than thirty affiliate stations covering the region. WADR's website makes extensive use of Newscoop's multilinguality, Soundcloud plugin, news ticker, topics, and maps - all of which are documented in this Cookbook.
El Periodico

Guatemala's acclaimed investigative newspaper has two notable sites running on Newscoop - its main site at http://www.elperiodico.com.gt and a sports site at http://deportes.elperiodico.com.gt.

Both sites make extensive use of jQuery; the news site enables readers to customize their home pages, for example. ElPeriodico also provides access to an important archive which serves all articles since the site launched in 2004 (check the chapter Ways to create archives in this book).
El Faro
Central America's first online news site http://www.elfaro.net is updated continuously, every day. El Faro's "Radionoticias" service uses article attachments and a Flash audio player to serve a large amount of audio (see the Cookbook chapter Audio player for attached files). They also make extensive use of photojournalism, based on Newscoop's media archive (see the chapter Working with images).
Gorad.by

Minsk's http://www.gorad.by is an online newspaper which posts about twenty items per day. The Newscoop-powered site uses jQuery slideshows extensively (see the chapter here on Image galleries with jQuery), calendar-based archives (explained in the chapter Calendars with jQuery), and Facebook integration (described in the chapter Working with Facebook).
Kosmoblog

Jakub Gornicki is a leading blogger in Poland, who moved his blog to Newscoop at the beginning of 2011 when he started working with Sourcefabric. Using a new sample template set based on Lucian Marin's "The Journalist" theme adapted for Newscoop, Kosmoblog makes use of Newscoop's multilingual features (he blogs in Polish and English), search engine optimization techniques like keywords in the URL and sitemap (described in the chapter Search Engine Optimization) and Disqus comments (also described later).
You can find a wide-ranging list of sites using Newscoop on the Sourcefabric website:
http://sourcefabric.org/en/products/newscoop_whosusing/
About this book
Updated to Newscoop 3.5.2
The Newscoop 3 Cookbook is a work in progress and open to your input. Dedicated to Open Source software development, Sourcefabric believes that the software and its documentation are open to the community. The more contributors add to the products, the more errors get caught and fixed, the more features are implemented. We also believe that software improves from good documentation, and documentation improves with the wide use of software.
If you experience the Newscoop 3 Cookbook in its printed form, it might be difficult to see how this book is open to your contribution. If you have come across the Newscoop 3 Cookbook online at FLOSS Manuals, you might get a better idea about how you can participate in improving this documentation. Register, log in and add your knowledge, use cases, your code snippets, comments and best practices to make this a better publication. Working with the online book production platform Booki, the content of this book is continuously evolving. Chances are, the latest PDF, ePub or the online version on the site http://www.flossmanuals.net contains more details than the printed copy.

"All work and no play..." - the Newscoop Cookbook team at work.
Sourcefabric started this publication with a one-week Book Sprint in Schloss Neuhausen, Germany, two hours north of Berlin. Authors for the Newscoop 3 Cookbook include (in reverse alphabetical order): Holman Romero, Ljuba Ranković, Lucian Marin, Micz Flor, Alexei Danilchuk and Douglas Arellanes. Our facilitator, chef, sprintmaster, captain and all-around make-it-happen person was Adam Hyde of FLOSS Manuals. Thanks also go to Katerina Michailidis for her logistical support and to Daniel James for copy and style editing.
If you contribute to this book, you may also want to add yourself as an author here...
Who we are
The Newscoop community comes from a diverse and international background of journalists, editors, developers, implementers, trainers, designers, documentation writers and others who care about Free Software and Free Media. The community finds its focus in Sourcefabric http://www.sourcefabric.org, the non-profit foundation which maintains the Newscoop project, as well as other tools and activities related to its mission of providing media organisations with the open source software, tools and support to produce quality journalism.

A last minute photo shoot from the annual "Sourcecamp" community gathering, held in Berlin in 2010, before the participants - who came from 12 countries - got into their trains, planes and automobiles back home.
Newscoop was first released under the name of "Campsite" in 2000. After substantial rewriting, it was renamed to "Newscoop" in January, 2011. Newscoop and Campsite have always been free and open source (always under the GNU General Public License) and will remain so.
About Sourcefabric
Sourcefabric o.p.s. is a not-for-profit organisation based in Prague, Czech Republic, with branches in Berlin, Germany and Toronto, Canada, and satellite offices in Warsaw, Minsk, Cluj, and Guatemala City.
The Sourcefabric partners Sava Tatić, Micz Flor and Douglas Arellanes were among the key people behind an initiative led by the Media Development Loan Fund http://www.mdlf.org to support open source solutions for independent media organizations in emerging democracies. The Media Development Loan Fund's Center for Advanced Media, Prague, or CAMP, consolidated a lot of work that had been happening since 1999 to develop user-centric, financially-viable, multilingual platforms for journalists. Sourcefabric is the continuation of that endeavour, but with greatly expanded aims and a new organisational structure.
Why 'Sourcefabric'?
Both the journalist's 'source' (the origin of information) and the programmer's 'source' (the code on which software is built) are vital to the work we do.
We are concerned with the 'fabric' of these things - their structures, relations and interactions. At the core of our experience and vision is a commitment to enable quality journalism. We do this through open source software and services that address these structures with solutions that are flexible, strong and interwoven; just like fabric.
Resources
In this Cookbook we often refer to the Newscoop template pack called "The Journal". If you are interested in sniffing out some other sneaky tricks in this (or other) template packs, you can go to the Sourcefabric website and download template packs from http://www.sourcefabric.org/en/products/newscoop_templates/
Tools
Before you begin a Newscoop implementation, getting these things together really should be your first steps.
- Working Newscoop installation
- Text editor, preferably one with PHP markup
- Image editor for preparing designs and images (GIMP, Photoshop, etc.)
- Site specification (see the next chapter, Turning your idea into a publication)
The steps to successfully install Newscoop can be found in the "Newscoop for Journalists and Editors" manual at http://manuals.sourcefabric.org
While Newscoop includes a template editor which works perfectly well, you'll probably prefer to work locally on your computer. Good text editors include Gedit on Ubuntu, Kate on Kubuntu, Notepad++ or even Dreamweaver on Windows, and of course command line editors like Emacs, vi, pico and nano.
Turning your idea into a publication
While it's a natural impulse to want to jump right into the more hands-on chapters of the Newscoop Cookbook, you'll save yourself a lot of time and trouble if you approach your Newscoop implementation project in the way we recommend here. These recommendations represent consensus among our community on best practices for Newscoop implementations.
One very important initial step is to understand the human element to the technology you're about to implement - who is involved in the project? You can benefit a lot from understanding who fulfils the following:
- Who makes decisions? Who makes decisions on the site project? Who makes decisions on coverage, articles and resource allocation?
- Who is the technical person? Who's the person in charge of the operation of the site, e-mail accounts and the like?
- Who has which role in the current workflow? How do things get done now, and who does it?
- What is the expected new workflow? How will things work for the staff after the new site project is finished?
- What are the current and expected visitation patterns for readers of your publication?
Being thorough at this stage helps to avoid making incorrect decisions or getting your decisions overturned at a later stage. In the worst case, you could end up with a dysfunctional design, and quite likely a dysfunctional project.
Draft a site specification that goes into as much detail as possible for the implementation, but remains flexible enough in the event of inevitable changes. This site specification, essentially the project's blueprint, should especially take into consideration the following:
When is this project considered a success?
What are the criteria for considering the project a success? For example, is the goal to increase page views or decrease the bounce rate? Is the goal to increase readership among a certain demographic or country?
Does the project do enough to make sure those goals are met?
Are the solutions you're proposing appropriate for the task at hand? If increasing reader time on site is a goal, does the site display enough "additional stories" links?
Do you know enough about the organisation?
Make sure you get as much information as possible on the following:
What do you know about your audience? Has market research been conducted? If so, what does it say? If your publication is using the Google Analytics tool, what does it say? What are the audience's needs, interests and technical capabilities? Needs and interests can also be things that the team can provide, but your users' technical capabilities (especially as delivered by Google Analytics) can help you determine the optimal design and level of interactivity for the project, affecting everything from font size to browser compatibility.
What is the functionality required? As much as you can, list and describe the functionality required in the project. Brief descriptions should suffice, but if you're thorough enough, you'll minimize the inevitable "Uh-oh, we forgot about <$fill_in_the_blank>" moments.
Which functionality is top priority? Which things are "nice-to-have," as opposed to "must-have?" When the success criteria are clear, the answers to these questions should get a lot clearer too. Limited budgets also work pretty well to force clearer prioritization.
Sitemap and features
Get or produce a site map of the existing content structure. What content does the site have, and how is it arranged? How often is the site currently updated? Is there content being created that is going underutilized?
For example, the current site may be a blog publishing 10 items per day, and because it's a blog, items are published in a reverse chronological order with newest articles first. But major stories are getting buried by newer, less-important entries. This would be something to address with the new site structure.
Discuss the proposed new site structure. Does the new site involve multiple languages? Issues and sections, or topics? How often will the site be updated? Will you create a new issue every day/week/month? How many sections will the new site have, and what are their names?
Subscriptions or no subscriptions?
If you plan to use subscriptions on your site, find out as much as you can about the subscription and paywall mechanisms involved. What are the revenue expectations for the new subscription-based site? What are those expectations based on (market research or a snowball's chance in hell)? Are there markets for the content that have not previously been considered? For example, many countries have significant diasporas interested in getting news from home, and they're often willing to pay for quality news. For more on this, see the chapter about contemplating Subscriptions and revenue.
Workflow
What is the content workflow? Who on the staff is responsible for which content? You'll find a lot more on this in the chapter on Planning your workflow.
Mashups, social media and other third-party services
What third party services are involved? List the intended integration with third-party services (if any). Social media, video, audio, comments and other widgets would count here. How complicated will the envisioned integration be?
This Cookbook includes examples and code snippets for Soundcloud, Disqus, YouTube, Vimeo, Flickr, Twitter, Facebook, Gravatar and others.
Custom development to set you apart
What additional custom development is required (if any)? Are you going to do any of this custom development yourself, or will there be another contractor to handle it? If your project requires custom development, it's very important to clearly specify not only the functionality required, but also the ways it will extend or interact with Newscoop's APIs. Also, it's helpful to work closely with the Newscoop core developers, so that they can provide advice and feedback, as well as including any plugins or add-ons in future Newscoop releases.
Final steps and time table
Once the draft of the specification is ready, have all team members go over it and comment, and then when everybody's OK with it, finalize it. If you're in an organization with one or more big bosses, get them to sign off on it. Then your team can make binding time/work estimates for the project.
While such a specification might seem like a lot of work (it usually is), it will give you a much better idea of the overall scope of the project, and will also help you to make a more realistic estimate of the time and labor involved.
Planning your workflow

Newscoop users Nestan Tsetskhladze and Eteri Turadze of Netgazeti.ge in Batumi, Georgia. Photo by Douglas Arellanes (CC-BY)
Who is doing what? And when? What does it require and what depends on it? Who can do it? Who has to do it? And who signs off what's being done? All those questions can be grouped together into one concept: Workflow.
"Workflow" is one of those terms that gets discussed a lot among newsroom technology types, but workflow means many things to many people.
"A workflow consists of a sequence of connected steps. It is a depiction of a sequence of operations, declared as work of a person, a group of persons, an organization of staff, or one or more simple or complex mechanisms" is how Wikipedia describes it.
In Newscoop, workflow refers to the steps that must be taken in order to accomplish a certain task, usually related to publishing content on your site. Inside Newscoop there are three main milestones hardwired into the system which have proven to capture the essence of the article publishing process:
- New - the article has been generated, either by your staff or a citizen journalist
- Submitted - the article has been fact checked, images are added, the sub editor approves
- Published - either manually or automatically, the article goes live
You can fine tune this process in Newscoop with custom switches for Article Types. For more detailed technical information, please see the chapter on Topics, switches and keywords to structure content, as well as the chapter in the manual Newscoop 3 for Journalists and Editors titled Publishing Articles.
But publishing articles is only a small part of the overall workflow of running a site, in fact: Newscoop has built-in publishing automation to do the job for you, once you have lined up the articles. There are a lot more aspects that you will need to consider at the beginning of your site planning, such as:
What are the steps the editors will have to take in order to place an article in the top position on the site? The top position might be determined by most recently published, by having the editor click and drag items in the section, by assigning a topic to an article with a name of "top story", or maybe by attaching a custom switch. All of those approaches are valid and possible, but it's up to you (and your point of contact at the organization) to figure out what's best for their purposes.
Does the proposed workflow correspond to current staff levels? Does the functionality you're planning for the new site require a much larger staff? In other words, who's going to take and prepare all the photos for the very cool JQuery slideshow widget you want to implement? (What, you're a radio station and don't have too many photos in your archive?) Who's going to be in charge of monitoring site comments? Who's in charge of the overnight shift on the site? (Wait, you mean there's going to be an overnight shift?!?)
What are the issues that could lead to staff resistance to the project? While you may think that your slideshow widget is cool, the staff may say "this stupid slideshow widget means my workload is doubled!" The more you can anticipate issues with staffing and work with your point of contact to address them, the better off your project will be.
Who are the staff members capable of taking on the new roles your project introduces? For example, who are the avid social media advocates on the staff, and can they be brought in to take on the publication's social media tasks?
Where are the project's time and work savings for the staff, or will the project mean that everyone will have to stay late every day? Explaining time savings or additional burdens accurately and clearly will make you a lot of friends both on the staff and with the publisher.
Is your proposed workflow too complicated for non-technical staff? For example, when you have a dynamic page layout based on custom switches, are the steps clearly communicated to the staff, and are they clear on how to do it?
What are the ways your proposed workflow can fail? What can you do to simplify things without giving up basic functionality? Often, a proposed design and its accompanying workflow is too complicated for the staff to execute on a regular basis. If the staff can't do it, you'll need to make sure your design and approach doesn't fail.
Keep an open mind
Editors on tight deadlines love things that are simple to use. Well, as simple as possible, anyway. Such solutions never work on live sites!
Instead, try to solve undesired situations by fine-tuning your templates. Try to put yourself in the position of an editor, and predict the possible mistakes they'll make when they have to live with your work on a daily basis. Stay flexible and implement changes soon after the team agrees on them. A website is like a living organism; you'll have to look after it.
Subscriptions and revenue
Newscoop provides the means to manage access to content with subscriptions. A subscription means that parts of your publication are only visible to users who are registered and logged in. By default, subscriptions are disabled - and planning your publication is completely unaffected by this chapter. Just proceed and make your publication. If you change your mind, come back to this chapter later and activate the Newscoop subscription system without changing your publication structure or content. If, on the other hand, you came to Newscoop because it provides an in-built subscription system, by all means, read on.
Because of the ongoing difficulties news organizations face in bringing in revenue, many have turned to subscriptions as a way of making money for their content. There's been a lot of heated debate about subscriptions or "paywalls" around content, but it's important to note that subscription management has been part of the code base in Newscoop since 1999, and has represented a significant source of revenue for many media organizations.
It's also important to point out that subscriptions do not necessarily have to be paid. You may decide that your publication will require that visitors share certain demographic information in return for site access, or you may decide that certain areas of the site are for members only. Or perhaps membership is sponsored by an advertiser, who provides free site access in return for the opportunity to promote their product to subscribers.
Newscoop flexibly supports subscription models. This allows you to switch from free to paid services and back again. Users can register themselves on your publication. The payments made for subscriptions need to be handled by your staff and applied to user profiles. Newscoop currently does not support fully automated transactions, where, for example, a user signs up for a subscription, pays by credit card and then immediately has site access.
Access control for content and features
Newscoop provides a fine-grained way to manage content in relation to subscribers and non-subscribers. You can set content to be subscriber-only:
- For all content in a publication
- For all content in a specific section
- For all content in a specific language
- On an article-by-article basis
- For an IP address range (useful when selling corporate subscriptions or to libraries)
If a reader ventures into an area on your site where they do not have access, you can manage in your templates what they will get to see - or what they will be able to do (like writing comments). Newscoop is very flexible in changing this access on the template level. In another chapter of this Cookbook, you will find the nitty-gritty of templating for subscriber pages. Also, below you will find details of how to administer subscriptions in the administration interface.
When preparing your publication's site map, it's a very good idea to map out which parts of the site - if any - will be visible to subscribers only. It's also important to try to figure out how much of each article you want to display to non-subscribers. According to these decisions you might also plan the fields in an article - there could be a part of the article which is only available to subscribers, like the phone number in classifieds, while everything else is available to all readers.
For our purposes as site implementers, here are some things to consider:
- Is the entire publication for subscribers only?
- Which sections are for subscribers only?
- Which pages are free to non-subscribers? The front page? The section page?
- How much of the article is free to non-subscribers?
- What will your page "sorry, this page is for subscribers only" say, and how will it look?
- What information will you require from your subscribers?
Once you do work out your site's subscription strategy, you should read the chapter about Subscriptions, registration and content access in this Cookbook for specific templating approaches.
Managing subscriptions in the admin interface
The list of subscribers is available in the Newscoop administration interface by clicking on Users in the main navigation menu, then Subscribers:

The subscription management interface includes a search tool which enables you to list readers according to several criteria, including subscription expiry date:

The duration of paid or trial subscriptions is determined by the default time periods set when you created the publication. (You can change these settings for your publication by clicking the Configure icon in the Publication list). During a trial period, the reader has a chance to make a payment, and consequently to have their subscription extended by an administrator.
The publication's administrator is automatically notified by e-mail of all new subscriptions. Subscribers also receive automatically generated e-mail reminders that their subscription will expire in two weeks. The text of the subscription expiry message is created in a Newscoop template. The default system template reads as follows:
"Dear <reader>,
This is an automatically generated e-mail message. Your <subs_type>
subscription (started on <start_date>) to publication <publication> will
expire on <date> (in <number> days).
Please enter the site http://<pub_site> to update subscription."
This file is located in the system_templates folder and is named _subscription_notifier.tpl. It can and should be customized to best suit your needs and style.
IP address access
Publishers often sell corporate or institutional subscriptions, and Newscoop has support for these out of the box. Newscoop's IP based access feature can be used to automatically log in subscribers that have IP (Internet Protocol) addresses in a known range. This means that groups of readers with computers within that IP range do not need account names or passwords to access your subscription-only content.
To create an IP Address subscription, go to the subscriber management page in the administration interface, in the drop-down menu under Users -> Subscribers.
First, create a subscriber account by clicking on the 'Add new subscriber' link, next to the green plus sign icon. Enter an account name, a password, and a full name with an e-mail address and phone number for a contact at the subscribing group or institution. You do not need to inform individual readers using IP address access of the existence of this account name and password; it's only for the subscriber contact.

Once the new subscription account has been created, click on the Add new link in the User IP access list management table on the right hand side of the page.

The form allows the input of a range of consecutive IP addresses. If necessary, more ranges can be added later. The start IP address is the lowest address in the range, while the number of addresses sets the size of the range, including any address ending in zero. For example, if a university library had the range of IP addresses 198.51.100.0 to 198.51.100.63, then you would enter:
- start IP address: 198.51.100.0
- number of addresses: 64

It is not necessary to add anything to the Newscoop templates for IP based subscriptions to work.
It is also possible to search for subscribers based on known IP addresses. In the search box on the Subscriber management page, enter a number in at least one box in the field labelled IP address, starting on the left side. Click the Search button, and the page will display all subscribers that have known IP addresses which match that number (or numbers).
Advertising and Newscoop
The other side of the revenue equation for most online publishers is advertising. For this purpose, we recommend the robust and open source OpenX system http://www.openx.org
Ad insert codes - whether they are served from your own OpenX server, a banner ad display network or a service like Google AdWords - can be included in any template or sub-template, so you have complete flexibility in both placement and size.
You can also build your own templates to manage your banners. All three options are explored in greater detail in the chapter Working with advertising.
Structuring your content
Newscoop's built-in logic for organizing content follows a logical and hierarchical structure derived from print publications. The following structure is built in by default:
- Publication, which consists of chronologically ordered issues
- Issue, which consists of sections
- Sections, which store articles
- Articles, which can be of different Types
- Article Types, which you can build specifically for your publication
You can overrule this structure and change this hierarchy to fit your publication. For example, you could use issues as containers for storing the site's substructure (without chronological importance, for example). Or you could have only one issue with lots of sections. Some situations are best handled with multiple publications, while others might work best with an emphasis on Topics, not Sections.
How you organize your content usually depends on:
- The nature of the content being published
- The workflow inside your team
- The amount of content to be published
- The rate new content is added
Example: Magazine
Let's imagine the website of an existing weekly print magazine. In this Cookbook, we often use the template pack "The Journal" which reflects magazine structure. "The Journal" covers topics like politics, business, science and technology, health, entertainment and sports. In such a situation, it's logical to use the built-in publication > issue > section > article structure in a straightforward way.
In Newscoop, you don't need to create a new issue from scratch every time - just select 'Add new issue' and then 'Use the structure of the previous issue' - you'll get an empty copy of the previous issue with all of its sections, settings and assigned templates.
"The Journal" can be seen at http://journal.templates.sourcefabric.org/
And another example, "Newsport", can be seen at http://newsport.templates.sourcefabric.org/
Example: Radio station site
Newscoop can be used to power a radio station website, where content is bilingual, and where the 'publication' only has one issue. Each radio show has a section, and individual articles can be added into this section when a new episode of the show has been broadcast. Breaking news items are presented on the front page.
Newscoop's Soundcloud plugin can be used to upload individual audio clips and attach them to news articles. Recordings of entire shows can be uploaded and displayed on show articles. In addition, Sourcefabric's Airtime broadcast software can be used to automatically record live shows and upload them to Soundcloud.
An example of this approach can be seen at West Africa Democracy Radio's site at http://www.wadr.org.
Example: Blog
Newscoop can be used as a blogging platform, which is especially suitable for group blogs or blogs with multiple authors and sections. For this purpose you might choose a structure where issues are months, or you could have yearly issues. The website front-end doesn't have to reflect the issue structure, as Newscoop can generate the listing of articles regardless of where they are in the structure; for example, ordering them by publication date.
Inside the blog, you can structure your content with Newscoop Topics. Topics are flexible and could either be used like tags, or in a hierarchical structure like categories or a taxonomy. Find out more about topics later in this manual.
An example of how Newscoop can be used as a high-end multi-lingual blogging platform can be seen in "The Journalist" template from Sourcefabric. The online demo is at http://journalist.templates.sourcefabric.org/
Any other structure logic can be developed and used with Newscoop. It's really a matter of good planning, and analysis of the factors discussed at the beginning of this chapter.
The power of $gimme
Now that you're venturing into the territory of Newscoop, $gimme serves as your map and compass. $gimme is your reliable friend, your eager spy and the keeper of all knowledge. $gimme will give you information and answer your questions. "Give me the name of the article", "Give me the number of the issue", are requests $gimme will follow without even a shrug. Obviously, "give me" is how $gimme got its name. And $gimme speaks a simple language, along the lines of "gimme publication name" or "gimme user email."
$gimme and the Newscoop template language
We like to refer to Newscoop's template language as a programming language for news. $gimme lets you list and arrange articles, display text and multimedia, prepare content for third-party services and include external content. It allows editors total design freedom and doesn't push them into a single way of presenting their stories.
Easy to use, easy to read
The philosophy behind the Newscoop template language (and $gimme) has been to make it as intuitive and easy to use as possible. Here's how you would use $gimme to display the name (or headline) of an article, like "Newscoop 3 Cookbook now in shops":
{{ $gimme->article->name }}
Here's how you would use $gimme to display a section's description, such as "Film Reviews from the Venice Film Festival"
{{ $gimme->section->description }}
Display the date when an issue was published:
{{ $gimme->issue->publish_date }}
Display the file name of an article attachment:
{{ $gimme->article->attachment->file_name }}
Display the caption of an image, like "Work started at Berlin's new airport":
{{ $gimme->image->caption }}
Display the map provider you're using for your site's base maps:
{{ $gimme->map->provider }}
Here are some more examples along the same lines:
{{ $gimme->article->keywords }}
{{ $gimme->article->comment->subject }}
{{ $gimme->publication->default_language }}
{{ $gimme->author->name }}
{{ $gimme->author->biography->text }}
{{ $gimme->image->photographer }}
{{ $gimme->user->name }}
{{ $gimme->user->phone }}
And there's more. In the following chapters you'll see $gimme in action, providing all kinds of information added by editors and journalists.
Separation of Presentation and Content
Web designers use the concept of "separation of presentation and content" every day when developing in HTML and CSS. In the HTML you can emphasize parts of the content with the em element, so whatever is wrapped inside <em> tags is "what" needs to be emphasized. "How" the emphasis is being displayed can be set in the CSS file, assigning font family, size, style, color and so on.
Develop your design without touching any code
The Newscoop template engine gives you maximum flexibility to develop templates in HTML, CSS and JavaScript any way you like. You don't need to think in terms of blocks or widgets, and you can use sample text like "Lorem ipsum" when fine-tuning your layout. Turning your design into a template for Newscoop means to replace the sample text with $gimme. Here is a simple example. Here's the HTML we want to serve:
<div>Media and Journalism</div>
<h2>Newscoop Cookbook released</h2>
Anything web developers need to know about the CMS for professional journalists in one comprehensive desktop reference
Separating content from presentation in the Newscoop template engine, we call in $gimme to give us what we need:
<div>{{ $gimme->section->name }}</div>
<h2>{{ $gimme->article->name }}</h2>
{{ $gimme->article->subtitle }}
Note that $gimme->article->name is wrapped in two curly brackets on either side. There's also a white space between the brackets on either side - while it's not mandatory, it's a good practice to make the template code more readable - but there are no whitespaces in $gimme->article->name. The template engine operates on the simple premise that it finds two opening and closing brackets, takes out anything in between and tries to make sense of it, replacing it with content from the database.
Once the logic is in place, the design can be changed any way you want:
<div class="section">{{ $gimme->section->name }}</div>
<h2 class="title">{{ $gimme->article->name }}</h2>
<span>{{ $gimme->article->subtitle }}</span>
Or you can add even more material to control the design with CSS later:
<div class="wrapper">
<h2 class="title section{{ $gimme->section->number }}">
{{ $gimme->article->name }}</h2>
<span>{{ $gimme->article->subtitle }}</span>
<div class="section">{{ $gimme->section->name }}</div>
</div>
Note how in the <h2> tag, a class is being added here that will change its value depending on the section the article is coming from. The interface designer can develop the look and feel of the site without having to go back to the programmer. Instead, all that needs to be changed is the template.
Watch $gimme at work
On its own, $gimme can pull information out of the content database and place it inside your template. When you set it loose inside Newscoop templates, it advances to become the project leader of your publication; beyond simple retrievals and replacements, $gimme is then in charge of making design decisions. Checking information with $gimme can create the most complex designs in very few lines of code.
To put $gimme into action, you'll use functions from the Newscoop template language. These functions are developed with the news organisation in mind, delivering publication content with simple commands. The functions available are being expanded continuously alongside new features in Newscoop, and an expanding range of features for already existing functionality. A complete Newscoop template design reference is included at the end of this Cookbook.
Now let's take a peek into an actual code snippet using $gimme. In this case you'll see a Newscoop function alongside $gimme. The function is called list_article_authors. Everything inside this function (it has a closing tag like in HTML) is repeated as many times as there are authors who have worked on this article.
The following example - in plain English - would be like asking $gimme: "Could you please list all the authors that worked on this article?"
Lets look at the code step by step and keep telling $gimme what to do.
<ul>
{{ list_article_authors }}
<li style="clear: left;">
For each author, we want the last name and then the first name separated by a comma.
<strong>{{ $gimme->author->last_name }}</strong>,
{{ $gimme->author->first_name }}<br />
Also show their image.
<img src="{{ $gimme->author->picture->imageurl }}" align="left" width="66px" />
Very important, show their full name alongside their work field (author, photographer, etc.), followed by their e-mail and their biography.
{{ $gimme->author->name }} ({{ $gimme->author->type }}):
<a href="mailto:{{ $gimme->author->email }}">
{{ $gimme->author->email }}</a>
{{ $gimme->author->biography->text }}
When you are done, close this list. Thanks.
</li>
{{ /list_article_authors }}
</ul>
You can see how $gimme makes it easy to pull up information in your templates. There is a quite a lot happening in twelve lines of code. We are delivering a list of authors alongside images, biography and e-mail. This will look great in the header of the article.
After this very straightforward example, we'll leap ahead into using maps inside articles (covered in detail later in this Cookbook). The following code will list the name and geo-location information for an article. Note that only "enabled" locations are listed, because the journalist might still be working on the map in the administration interface. Once a location is set to be seen by the public, it shows up using this code:
Location(s):
{{ list_article_locations }}
{{ if $gimme->location->enabled }}
<p>
{{ $gimme->location->name }}<br />
{{ $gimme->location->longitude }}, {{ $gimme->location->latitude }}
</p>
{{ /if }}
{{ /list_article_locations }}
We bet you've already started loving the power of $gimme. Besides $gimme, the Newscoop template language includes a complete set of functions and several other powerful capabilities that are condensed in the Newscoop Template Reference.
There's more...
The Newscoop template language is an extension to a popular and powerful template engine called Smarty, which itself is written in PHP. Smarty is popular among PHP users and developers, and comes with a rich set of functionality you can use in your templates. You will see some examples in this cookbook and find a full reference online at http://www.smarty.net
With every new Newscoop version the template language and $gimme become more powerful. We keep developing and integrating new features, and extending the current ones, but we do also care about backward compatibility, which means we are not going to break your current website.
Once you understand the power of $gimme, you will start getting a sense of the freedom it offers you when building websites. Enjoy!
Best practices for designing your content
Publications can have multiple types of content: editorial copy, interviews, graphics, photos, audio and video recordings, and other digital assets. When designing pages for these types of content, you should keep focussed on the vision and style you want to convey. The importance of good design cannot be valued highly enough, because it creates the readers' emotional response to your publication. This has been proven on numerous occasions where the redesign process dramatically changed a site's traffic, even though the content remained the same.
It will be helpful to keep the potential of the Newscoop template engine in mind when creating your site's design. As a designer, this allows you to not think in boxes, but to think outside the box.
In this chapter, we want to lay down some general guidelines helping you to deliver the best structure possible for your design. This can be seen as a number of steps that a template designer should follow, like defining the grid of the template, and designing sections and pages based on that grid.

The diagram above shows you how to structure the design and also provide a good experience for your readers. Please notice the white space between sections; it can provide room to breathe, and also make clear distinctions between sections.
The template grid and the golden ratio
Typical desktop and laptop computer displays have a resolution of at least 1024x768 pixels. 960 pixels is very close to the minimum limit of monitor resolution and is also divisible by 2, 3, 4, 5, 6, 8, 10, 12, 15, 16, 20, 24, 30, 32, 40, 48, 60, 64, 80, 96, 120, 160, 192, 240, 320 and 480. This makes it a highly flexible base number to work with.
With Newscoop and with most news sites we recommend using a template that is 960 pixels wide. Fluid templates can provide more flexibility, but they defy the purpose of having a grid. A 960-pixel-wide grid (http://960.gs/) can help you divide your design structure into Newscoop's template elements like header, article area, sidebar and footer. This grid can also provide enough space for photographs and videos, things most media outlets use in great quantities.
An important part of defining the template grid is using the golden ratio (http://en.wikipedia.org/wiki/Golden_ratio). The value of the golden ratio is 1.618, but approximations can also be used, such as a ratio of 5:3. The golden ratio is most often found in nature. Nautilus shells are a perfect example; the spirals get smaller and smaller in the same proportion to each other.
Using the golden ratio can provide your readers with a clear perspective over your content. To give you a good example of how the golden ratio can be used for template design, you can set the content area to 600 pixels wide and the sidebar to 360 pixels wide, so that the ratio between the content area and sidebar is pretty close to 1.6 (600 divided by 360).
Aesthetics can be measured and more importantly can be constructed, even built from the ground up. Following a few guidelines can help you make sure you're on the right path to having a publication that not only is compositionally balanced, but also aesthetically pleasing, so that people can enjoy reading each article or part of the site. Designing a template grid doesn't have to be exact math, it's more of an experimentation of ratios and white space along with text and images.
Article design
When putting your design into HTML, you should follow web standards and the common uses of HTML tags. This is important to make your content machine-readable, which will enable search engines to understand your content and rank it higher.
The use of headings (H1, H2, etc.) for titles and subtitles, DT for dialogs, CITE for citations, BLOCKQUOTE for quotations can be seen as limited, but they can provide a very clear definition of the elements that should be designed and then styled in CSS. Usually H1 is kept for the site title, which is positioned in the header area. Remaining headings are used for article titles and subtitles of the other parts of a story.
A good way to design the article content would be using only the inline elements mentioned above and also paragraphs for the text, keeping block tags like DIV only for the presentation layer. You'll find more information on the use of tags and their importance in the chapter titled Search Engine Optimisation (SEO).
The template grid defines what goes inside an article and what goes outside of it. The same conventions established for the site's design can also be used for article design; don't try to reinvent the wheel. The ratios, subdivisions and modularizations should be the same across the entire site.
Comments design
Comments are not only the feedback received for a news story, but also the conversation of the community behind your site. When you design a comments structure you should take into account that people are not only communicating their ideas about the article, but also communicating with each other. Threaded comments reflect this dialogue very well. Adding profile pictures so that each reader has his/her own picture shown next to the comment is also a good idea.
When designing comments and comment forms, you do not have to follow and modify existing HTML structures. Because of Newscoop's advanced templating system, comment submission forms can be designed and styled completely using HTML and CSS.
There's a particular chapter in this manual titled Profile pictures: Gravatar, Facebook, Twitter where you can find more details about how users can set up profile pictures and display their pictures along with their comments.
Designing the other parts of a Newscoop site
Newscoop's header area is the part where the masthead and the main navigation take place. The masthead is your publication's logo or title. It should be the first thing your reader sees. It must be legible, tell people about your publication's intent and convey what they can expect. It's important to remember that while you may have looked at your own publication thousands of times, your readers may have not.
Archive design must have a clear structure, so the reader can quickly identify the article they are looking for. Usually it is shown in reverse chronological order, grouped by years, months or weeks. In Newscoop you can also use calendars to design your archives. More about this can be found in the chapter Calendars with jQuery.
A well-designed search results page can provide readers with a pleasant experience, so they won't be afraid to look for articles published in the past. This manual also has a chapter titled Search Templates, where you can find more information on getting the most out of search results pages. Don't forget that your search results page should display not only the article's name, but also small pieces of supporting information about the articles (developers like to call this "metadata"), like the date it was published, the author's name and the topics assigned to the article.
There's more information about the structure of other parts of Newscoop sites in the chapter Understanding Templates, HTML & CSS.
Typography
Newscoop allows total control over font usage; you can even embed font faces using CSS3. Actually, one of the important parts of the design is not the choice of a single font, but all of the site's typography as a whole.
A principal part of typography is setting the line height. As mentioned before, line height is a good place to make use of the golden ratio. A value of 1.6 em should work just fine, but the recommended value is 1.5 em for the kinds of content mentioned in the beginning of this chapter.
An example of good typography for web design is to set the font size to 13 pixels and the line height to 21 pixels. The ratio between line height and font size is very close to the golden ratio.
Using too many font faces might have major impact on the professionalism a publication conveys. Displaying fewer font faces might be less confusing for the reader. Consider using one font face for titles and a different one for article content.
<link href="http://fonts.googleapis.com/css?family=Droid+Sans" rel="stylesheet" type="text/css" />
The above line of code is an example of how to use Google Web Fonts for embedding new font faces in your design. There are several services that can provide this functionality; some are paid services like TypeKit, and some are available for free like Google Web Fonts. These services take care of providing the right font format for each browser. Some browsers are using standard font formats like OTF or WOFF (Web Open Font Format), while many mobile browsers use technologies like SVG for displaying font faces.
Preparing designs for templates
One way to design for Newscoop templates involves slicing a static mock-up of your publication into multiple images. A graphics application such as GIMP or Adobe Photoshop can be used for this task. The resulting images can then be re-created using HTML and CSS. The main advantage of slicing up and re-creating the design is that it reduces the bandwidth load for your site, which means increases in your readership will scale better, and your readers will get the pages faster. For instance, design elements such as horizontal rules and colored backgrounds can be styled using CSS, and therefore do not need to be served as image files.
Let's look at the sample Template Package "The Journal".

Front page of the sample Template Package "The Journal".
Before you begin the slicing process, you need to identify the main structural elements of the design, so that you know how to arrange and structure your HTML files. Dividing the design should follow the grid established in the previous chapter. The main divisions should end up being <div> tags. A <div> is a block containing images and text that can be positioned using CSS.
An important thing to remember when creating HTML files is that you should use IDs for <div> tags that are present only once in your site pages (e.g. navigation, sidebar, footer, etc.). You should use classes for <div> tags that are repeated more than once on the same page (e.g. links, pages, etc.)
Dividing the front page template
The diagram below shows how the design for "The Journal" front page template is divided:

Your HTML files will end up being .tpl files, which are Newscoop template files. For "The Journal", the front page template front.tpl is a skeleton which includes and positions the following sub-templates:
- _html-head.tpl This is not visible in the diagram above, but it is an important template used on all site pages. It defines the 'head' tag section of HTML pages.
- top.tpl Includes all templates with prefix 'top', and creates remaining elements of the header section of the page (date, RSS link, logo). This template is repeated on all site pages.
- top-login.tpl Template used to generate the login form and register link. If a reader is logged in, it makes links to the reader's account page and to logout.
- top-highlights.tpl Lists the three newest articles with the switch 'highlight' switched on.
- top-recent-entries.tpl Lists the three last published news articles.
- top-search-box.tpl Generates the search form.
- top-nav.tpl Used for site-wide navigation.
- front-top-story.tpl Displays just the newest article with the switch 'On front page is on'.
- front-tabs.tpl Makes tabs with most-read and most-commented articles, and then lists the actual articles.
- front-three-categories.tpl Lists three articles (regardless of section) which have the switch 'On section page is on'.
- front-also-categories.tpl Makes a horizontally-scrollable list of 12 articles that don't have any special switch on.
- front-bottom-about.tpl Template with hard-coded 'About this site' content.
- front-bottom-meta.tpl Makes hard-coded links to important pages that are used for Newscoop administration, such as the administrator login.
- front-bottom-poll.tpl Displays the latest defined poll.
- footer.tpl This is the part of every page that contains links to 'about' pages and legal information.
Dividing the article and section templates
The diagram below shows how article and section page designs can be divided into sub-templates. The top.tpl and footer.tpl sub-templates are re-used from the front page design, but in between these are different sub-templates. Some of these sub-templates may have been created for just one specific purpose, while others will be re-used again and again.

Organising template files
Every template package available for download from Sourcefabric has three main templates:
- Front page
- Section page
- Article page
These are called - no surprise here - front.tpl, section.tpl and article.tpl.
You could run a publication with these three templates and nothing else. But to make the most of the template engine's power, you should divide up your templates further, creating sub-templates which can be easily reused and edited.
There are some parts of pages which are identical, regardless of the section or the article. This is usually the case for the header, navigation and footer, for example. But it could also be an image stream from flickr, a Twitter feed, a 'Like' button from Facebook, or a similar icon for sharing content from a third party provider.
You don't have to duplicate this part of the template. In fact, it's even better to hand off these functions to sub-templates. Then when you apply a change to the sub-template, it will show up across your entire site.
You can take out sub-templates, place them in a subfolder and call them with an include, like this:
{{ include file="set_thejournal/_tpl/article-comments.tpl" }}
As you can see in this example, the path to the template which is being included needs to be named. Planning your templates' folder structure carefully will save you time later, especially when you run more than one publication on Newscoop and have several different designs in action.
We encourage you to follow the folder structure described below. It's not set in stone; you can structure your templates and folders however you prefer, but the Newscoop community has agreed on this structure after years of working with templates. We consider it to be best practice. Also, the template packs Sourcefabric provides all feature this structure. If you use the same logic it will be easier to use examples or copy sub-templates from one template package to another. Read on to find out what we recommend when it comes to naming templates and placing them in your file system.
Template naming
Besides the main templates (front.tpl, section.tpl, article.tpl) you will probably have many sub-templates to run your publication. Depending on whether they're common across multiple pages, or unique to a page, you may follow these rules. But you don't have to, because Newscoop doesn't have reserved names for specific templates; it's really up to you to create your environment the way you like.
- _html-head.tpl is the template we provide for all links, meta tags and information globally needed for your publication, like jQuery, webfonts, CSS files and universal JavaScript.
- Unique code for sections or articles can be called from _html-head.tpl using {{ if $gimme->template->name == "path/to/article.tpl" }} or with other IF conditions like switches, topics or keywords. Such additional includes could be slideshows or special CSS files. For quick development, having one template (for example _html-head.tpl) saves you lot of time when you have to introduce some changes, and keeps things consistent. You can always chop it up later.
- Includes that are used on more/all pages can have short names, like header.tpl, main-nav.tpl, footer.tpl
- Included templates that are specific for a single page (or a few pages from the same context) can have a prefix, like article-sidebar.tpl or front-top-story.tpl. This way you will have templates for article page grouped together in the template file listing. The same goes for archive, front page, search and so on.
- Special templates that are not directly used to output content on the web page but to define context (for example the _html-head.tpl which defines the HEAD section of web pages, or some RSS or sitemap generators) can have the '_' (underscore) sign as the first character; this way, all such templates are grouped together on the top of the template listing page.
Folder structure
Your templates will always be inside the filesystem path:
/path/to/documentroot/templates/
These files are accessible through the template editor of the Newscoop administration interface. Inside this folder you can add sub-folders. We recommend the following structure:

Here's some practical advice on how to make your life easier with a clean and functional folder structure:
- templates/set_name/
Replace "name" with the name of your template package. For example, we are using "set_thejournal" for the template package "The Journal". The main templates are placed inside this folder, like front.tpl, section.tpl, article.tpl or universally used templates like search.tpl, archive.tpl, gallery.tpl etc. The include path is:
{{ include file="set_thejournal/gallery.tpl" }}
- templates/set_name/_tpl/
All your sub-templates are collected inside this sub-folder. In our experience it isn't necessary to divide this into further sub-folders. Instead you should use the name of sub-templates for further clustering, like article-comments.tpl, article-author.tpl, etc. The include path is:
{{ include file="set_thejournal/_tpl/article-comments.tpl" }}
- templates/set_name/_img/
If you need images on the file system for your publication, place them here. The source path is:
<img src="http://{{ $gimme->publication->site }}/templates/set_name/_img/logo.png" />
- templates/set_name/_js/
Place all the JavaScript files you need in this folder. They are included like this in the header:
<script type="text/javascript" src="http://{{ $gimme->publication->site }}/templates/set_thejournal/_js/tabs.js"></script>
- templates/set_name/_css/
You can place universal CSS files into this folder, things like grid, or font sizes. Alternatively you can use a subfolder (see next point). These CSS files are included like this:
<link href="http://{{ $gimme->publication->site }}/templates/set_thejournal/_css/default.css" rel="stylesheet" type="text/css" />
- templates/set_name/_css/skinname/
For the CSS files, we decided to introduce a subfolder, which is best being described as a skin. For example, the CSS in this folder could change the colour of your site, in which case you might have folders like "red", "blue" and "morning mist" in here. You call these files with:
<link href="http://{{ $gimme->publication->site }}/templates/set_thejournal/_css/green/green-skin.css" rel="stylesheet" type="text/css" />
- templates/set_name/_misc/
Use this folder for additional code, like a Flash Player which is being embedded in your templates. The URL path is:
http://{{ $gimme->publication->site }}/templates/set_thejournal/_misc/
If you need the folder path it would be:
/path_to_document_root/templates/set_thejournal/_misc/
If you check out our template packages you will see that beyond this strict structure, we actually get a bit looser and let our hair down. For example, you'll find image folders inside the CSS folders, providing background images. A good rule of thumb would be keep your ship in order for as long as you can. Then get flexible and sail with the wind.
Tips and tricks for the template novice
This chapter is a collection of snippets offering a quick overview of the inclusion of files, modification of strings, working with date and time, and managing line breaks. The following chapters will bring these snippets to life. For more modifications, you can consult the http://www.smarty.net documentation.
Including files
Templates and sub-templates are included using the template path starting inside the templates folder:
{{ include file="set_thejournal/_tpl/article-comments.tpl" }}
Date and time
For full date and time formatting options, see the template reference at the end of this manual.
Print current time (e.g. format: 25 April 2011, 16:20:45)
{{$smarty.now|camp_date_format:"%e %M %Y, %H:%i:%S"}}
Print date and time of publication of an article
{{ $gimme->article->publish_date|camp_date_format:"%e %M %Y, %H:%i:%S" }}
Modifying strings
Stripping tags from WYSIWYG content
{{ $gimme->article->intro|strip_tags }}
Truncate string to specific length
{{ $gimme->article->intro|truncate:70 }}
Escaping HTML and stripping tags (e.g. for meta description)
{{ $gimme->article->intro|strip_tags|escape:'html' }}
Upper and lower case
{{ $gimme->article->name|upper }}
{{ $gimme->article->name|lower }}
Replacing and chopping strings
Replacing parts of the string (example: whitespace into underscore)
{{ $gimme->article->name|replace:' ':'_' }}
You can also use a regular expression with regex_replace
{{ $gimme->browser->moz_data.2|regex_replace:"/\./":"-" }}
|regex_replace:"/\./":"-" replaces all dots with dashes. This can be useful in JavaScript elements. The following line uses regex_replace to replace fancy quotes like » « ” and so on with "
{{$gimme->article->name|regex_replace:'/&(.*?)quo;/':'"'}}
Trim a string (chop off whitespace at the beginning and end)
{{ $gimme->article->seo_title|trim }}
Counting and statistics
Counting characters, words, sentences and paragraphs:
Headline "{{ $gimme->article->name }}" has
{{ $gimme->article->name|count_characters }} characters and
{{ $gimme->article->name|count_words }} words.
The full article has
{{ $gimme->article->full_text|count_sentences }} sentences and
{{ $gimme->article->full_text|count_paragraphs }} paragraphs.
Useful conditions
Checking if variable is empty
{{ if $gimme->article->seo_title|strip_tags|trim !== "" }}
Using the if condition with these string modifiers makes sure that no HTML tags or whitespace is in the field.
Avoiding line breaks
Anything within {{strip}} {{/strip}} tags is stripped of extra spaces or carriage returns at the beginnings and ends of the lines before they are displayed. Let's say you had a publication where the value of the seo_title field often contained leading spaces, sometimes editors even get HTML tags into the field:
<strong>Newscoop</strong> Rocks!
The following example will output a single line starting and ending with quotes, but without leading spaces, like "STARTNewscoop Rocks!END". Any HTML code will be stripped out.
"{{ strip }}START
{{ if $teststring|strip_tags|trim !== "" }}
{{ $teststring|strip_tags|trim }}
{{ /if }}END
{{ /strip }}"
If you want to keep whitespace between elements, use a workaround with:
{{ textformat wrap=200 }}
This will turn everything into a single line with a space between each element, and applying a line break every 200 characters. Adjust the value of 200 to meet your needs. The example below will list various values in one line inside the body tag:
<body class="{{ textformat wrap=200 }}
{{ $gimme->browser->browser_working }}
{{ $gimme->browser->ua_type }}
{{ $gimme->browser }}
{{ /textformat }}" >
Installing template packs
If you want to see a final result of the process of chopping up a design, the easiest way is to download one of the template packs for Newscoop from Sourcefabric. Each template pack contains a complete sample publication with all the templates that publication requires. You can then change the sample publication to meet your needs. On the Sourcefabric website you can find packs providing all elements of a publication: database structure, sample content and the actual templates:
http://www.sourcefabric.org/en/products/newscoop_templates/
These template packs are provided in the form of Newscoop backup files.

Warning: if you already have one or more publications on your Newscoop server, uploading a template pack will erase your entire database and files from all your publications, and replace them with sample content! Do not attempt this procedure on a production Newscoop server unless you have backed it up first!
Using the Backup/Restore feature of Newscoop, you can install a template pack after downloading it from the Sourcefabric website to your local computer's desktop. Then log in to the Newscoop administration interface, and select Backup/Restore from the Actions menu.
On the Backup/Restore page, click the Upload backup file link, and click the Browse button to select the template pack from your local computer. Then click the Save button to upload the file. After upload, click the Restore icon for the template pack, on the right side of the list of the available backup files. This orange and white icon looks like a life preserver, of the kind you might find on a boat.

The restore process starts with an empty pop-up window, connecting to the server. Do not close this window, otherwise the restore process will be interrupted. The process takes some time (it can be minutes, depending on the size of the publication and speed of the server). It will finish with an alert window where you have to click "Resend".
After the restore process has finished, there is only one user in the system, the Administrator, with the login and password: admin
To finish the process, log in using admin as login and password. Then go to Content > Publications and select "Configure" in the new publication. Now you have to add the URL of your publication as a site alias. The template pack should now be visible at the URL of your publication.
Publication
Newscoop content is organized in a hierarchical structure which conforms to the tradition of newspapers and magazines: publications, issues, sections and articles. Each publication is made up of issues, each issue is in turn made up of sections, which are comprised of articles.
In this chapter we'll look at how publication settings can be set in the admin interface and then accessed by $gimme->publication and its variants.

Configure Publication view for general attributes and comments in the administration interface
You can set a range of parameters in the configuration when creating or editing a publication in the administration interface. This chapter will explain only those parameters related to the $gimme->publication object through the template language.
Each publication has an attributes menu (accessible in the administration interface under Content->Publication and then by clicking on the wrench-and-screwdriver icon for configure).
There are three sections in the publication attributes menu for each publication:
- General attributes and Comments on the left side of the menu
- Subscription defaults on the right side of the menu
General Attributes
The fields in the general attributes section present in $gimme->publication are listed below:
Name of the publication (e.g. "The Journal")
{{ $gimme->publication->name }}
Default Site Alias is the name of the web server on which your publication will be hosted (e.g. www.example.com). Newscoop enables multiple publications to be hosted on the same web server, provided that a unique alias has been set up for each publication by your system administrator. If you try to access the alias URL before this setting is made, you will see an error message indicating that the alias was not yet assigned to a publication.
{{ $gimme->publication->site }}
Here is an example using $gimme->publication->site taken from The Journal's _tpl/_html-head.tpl:
<script type="text/javascript">
var tb_pathToImage = 'http://{{ $gimme->publication->site }}/templates/set_thejournal/_img/loadingAnimation.gif';
</script>
<script type="text/javascript" src="http://{{ $gimme->publication->site }}/templates/set_thejournal/_js/tabs.js"></script>
<script type="text/javascript" src="http://{{ $gimme->publication->site }}/templates/set_thejournal/_js/scripts.js"></script>
<script type="text/javascript" src="http://{{ $gimme->publication->site }}/templates/set_thejournal/_js/easing.js"></script>
<link rel="index" title="The Journal" href="http://{{ $gimme->publication->site }}">
$gimme->publication->default_language returns information related to the publication's default language. Here are a few examples:
<ul>
<li>name: {{ $gimme->publication->default_language->name }}
is the language name</li>
<li>number: {{ $gimme->publication->default_language->number }}
is language identifier in the Newscoop database (integer value)</li>
<li>english_name: {{ $gimme->publication->default_language->english_name }}
is language name in English</li>
<li>code: {{ $gimme->publication->default_language->code }}
is language international code</li>
<li>defined: {{ if $gimme->publication->default_language->defined }}SET{{ else }}NOT SET{{ /if }}
is boolean value (true/false) - true if the language was set in the current environment; false otherwise</li>
</ul>
A full reference to all properties of the template objects is given at the end of this book. The examples covered here might not cover all possibilities.
Comments
The fields in the Comments section in the screenshot above are accessible through $gimme->publication as follows:
Public allowed to comment? Check this box if non-subscribers will be allowed to make comments on articles
{{ if $gimme->publication->public_comments }}YES{{ /if }}
Public comments moderated? If you check this box, non-subscriber comments will be hidden from readers until they have been reviewed by a staff member
{{ if $gimme->publication->captcha_enabled }}CAPTCHA{{ /if }}
You can see some of these examples in action in the advanced section of this Cookbook.
Subscription Defaults
The rest of the fields are related to subscriptions, which you can adjust later if you wish. First, you have to select a time unit for your subscriptions; which could be days, months, weeks or years.

Configure Subscription default view in the administration interface
You can set two types of subscriptions: paid and trial. Paid subscriptions have the following properties:
- Currency: the subscription currency. Even if a subscription request is sent and the currency setting is changed before payment, the information about the subscriber's payment due is correctly recorded
- Time unit cost per one section:
- for one language: the price for access to a particular section in a single language
- for all languages: the price for access to a section in all available languages
- Default time period: the usual duration of the paid subscription. This value is used when a reader subscribes through the website. The period for a particular subscription can be modified from the administration interface
Here is some sample code for subscriptions:
<h3>Subscriptions</h3>
<ul>
<li>Trial subscription: {{ $gimme->publication->subscription_trial_time }} {{ $gimme->publication->subscription_time_unit }}</li>
<li>Paid subscription: {{ $gimme->publication->subscription_paid_time }} {{ $gimme->publication->subscription_time_unit }}</li>
</ul>
<h4>Subscription costs:</h4>
<ul>
<li>{{ $gimme->publication->subscription_currency }} {{ $gimme->publication->subscription_unit_cost }} (access one language)</li>
<li>{{ $gimme->publication->subscription_currency }} {{ $gimme->publication->subscription_unit_cost_all_lang }} (access all languages)</li>
</ul>
Controlling access based on subscriptions is described in the chapter titled "Subscriptions, Registration and Content Access."
Issues
If you've worked on a periodical publication (meaning that it's regularly published on a daily, weekly, monthly or quarterly schedule), you're familiar with the concept of issues. If you come from a blogging background, you're probably used to an unstructured process of publishing your articles. Often blogging systems will create arbitrary issues in your archive by clustering articles, for example in months.
In this chapter we'll look at how Newscoop works with issues, and how each issue's characteristics such as name, publish date and URL can be accessed in the template language.
In Newscoop, each issue can have a separate template assigned to it, meaning that you can have a different layout for different seasons, events or even different layouts for 1-, 2- or 3-column headlines (especially useful for breaking news coverage or slow news days). You can also translate individual issues. And, from the administration interface, you set automated publishing for an entire issue.
From the Newscoop administration interface for The Journal, you can access the issue details menu by going to Content->The Journal and then clicking on the wrench-and-screwdriver Configure icon.
Here is an example template that returns a number of attributes for a given issue:
<h3>Issue No.{{ $gimme->issue->number }}: {{ $gimme->issue->name }}</h3>
<ul>
<li>Published: {{ $gimme->issue->publish_date|camp_date_format:"%e. %M %Y" }}</li>
<li>Using template: {{ $gimme->issue->template->name }}</li>
<li>Inside publication: {{ $gimme->issue->publication->name }}</li>
<li>URL name: .../{{ $gimme->issue->url_name }}/</li>
<li>Latest issue? {{ if $gimme->issue->is_current }}yes{{ else }}no{{ /if }}</li>
</ul>
For "The Journal," this displays something like this:
Issue No.13: January 2011
- Published: 1. January 2011
- Using template: set_thejournal/front.tpl
- Inside publication: The Journal
- URL name: .../jan2011/
- Latest issue? yes
A full reference of properties for the object $gimme->issue can be found at the end of this manual.
Using 'set' and 'unset' to change values for an issue
In the templates you can also change the values for a given issue. In the following example this is done to include static pages from the first issue (example taken from _tpl/footer.tpl of "The Journal"):
{{ set_issue number="1" }}
{{ set_section number="5" }}
{{ list_articles }}
<li class="page_item"><a href="{{ uri options="article" }}" title="{{ $gimme->article->name }}">{{ $gimme->article->name }}</a></li>
{{ /list_articles }}
You can set the issue name and the issue number. You can reverse the issue to the default value (the value for the default runtime environment of the displayed page):
{{ set_default_issue }}
You can also set the issue to the last published issue:
{{ set_current_issue }}
If you want to drop the information you have set, you can use:
{{ unset_issue }}
Unsetting an issue does not lose the issue value forever. It can be set with the above commands to default, current or an assigned value.
Sections
Sections are distinct clusters of articles. You will have seen sections in most print publications: Culture, Business, Sports, International Affairs, and so on. Usually these sections are visible in the publication's navigation; below you can see an example for the sample publication "The Journal". In this case, the section POLITICS is active, either because the reader is looking at the content of this section, or is reading an article inside the section:

Sections can be translated, and sections also have a description which can be added in the administration interface. The Newscoop developers are currently working on access levels for editors and journalists along section lines, meaning that you can assign your staff to sections and they are only allowed to work inside that section.
Here you can see the $gimme->section object in action:
<h3>Section No.{{ $gimme->section->number }}: {{ $gimme->section->name }}</h3>
{{ $gimme->section->description }}
<ul>
<li>Published: {{ $gimme->section->publish_date|camp_date_format:"%e. %M %Y" }}</li>
<li>Using template: {{ $gimme->section->template->name }}</li>
<li>Inside: {{ $gimme->section->publication->name }}/{{ $gimme->section->issue->name }}</li>
<li>URL name: .../{{ $gimme->section->url_name }}/</li>
</ul>
This displays something along these lines, depending on where you are, in "The Journal":
Section No.40: Health
All the things that do you good.
- Published: 20. April 2011
- Using template: set_thejournal/section.tpl
- Inside: The Journal/January 2011
- URL name: .../health/
Note: A section's publishing date is the same as the publishing date of the issue.
Using $gimme->section in the navigation template
In your navigation, you can use $gimme->section to check which element of the navigation needs to be active, because this is the section the reader is in (example taken from_tpl/top-nav.tpl of "The Journal"):
{{ list_sections }}
<li class="cat-item{{ if $gimme->section->number ==
$gimme->default_section->number }} current_page_item{{ /if }}">
<a href="{{ uri options="section" }}" title="View all posts filed under {{ $gimme->section->name }}">{{ $gimme->section->name }}</a>
</li>
{{ /list_sections }}
{{ if $gimme->section->number == $gimme->default_section->number }} checks if the section number provided by the list function is identical with the one of the page. If this is the case, an additional class is added. This class is then used in the CSS to style this element.
Listing Sections
In the above example, list_sections was already introduced. The list commands (for issues, sections, articles, languages, comments and others) can be tuned in many ways. A full reference can be found at the end of this manual.
Lists are usually not so elaborate when used on sections. You'll find more interesting examples in the chapter on articles. For sections, ordering is probably the most commonly used feature. Here are some examples; ordering by number (ascending):
{{ list_sections order="bynumber asc" }}
{{ $gimme->section->number }}. {{ $gimme->section->name }}
{{ /list_sections }}
..or ordering by number (descending):
{{ list_sections order="bynumber desc" }}
{{ $gimme->section->number }}. {{ $gimme->section->name }}
{{ /list_sections }}
This returns the section numbers in ascending or descending order, and also lists their names.
Setting and Unsetting Section
You can also change the section's values in the templates. In the following example this is done to access the static pages in section number 5 of the first issue (the example is taken from _tpl/footer.tpl of "The Journal" sample publication):
{{ set_issue number="1" }}
{{ set_section number="5" }}
{{ list_articles }}
<li class="page_item"><a href="{{ uri options="article" }}" title="{{ $gimme->article->name }}">{{ $gimme->article->name }}</a></li>
{{ /list_articles }}
You can set the section name and the section number. You can reverse the section to the default value (the value for the default runtime environment of the displayed page):
{{ set_default_section }}
If you want to drop the information, you can use:
{{ unset_section }}
Unsetting a section does not lose the section information forever, it can be set with the above commands back to default, or an assigned value.
Articles
In this chapter you will learn how to display elements of an article, as well as building article lists. Among all templates, article.tpl is generally the one where most template functions are called, and many sub-templates are included. No surprise, since a lot of things usually show up in an article page:
- title
- authors
- publish date
- intro
- full text
- attachments
- comments
- map
- the list of other articles from the same section
- ...?
Each article has an Article Type, which has a list of fields you set up to reflect the content (like "intro", "twitter", "full_text", "seo_title" and so on). Some of the elements in the list above refer to fields defined in the Article Type, like title, intro or full text. Others are objects related to an article, like attachments, maps or comments. There can also be references to objects independent from the article, which are linked to the article in the Article Edit screen of the administration interface, like authors.
You are advised to use the {{ include }} feature of the template engine to manage all possible shapes and forms an article can take. Chop your article template into sub-templates and call them in when and where you need them. As we already described in a previous chapter on cutting a HTML page into templates, it is much easier to divide a template into pieces and use includes.
You can take a look at the example article.tpl in the template pack "The Journal".
Best practice is to separate the main article content from the other auxiliary parts. That's why we have different template includes like:
{{ include file="set_thejournal/_tpl/article-cont.tpl" }}
{{ include file="set_thejournal/_tpl/article-comments.tpl" }}
{{ include file="set_thejournal/_tpl/article-map.tpl" }}
{{ include file="set_thejournal/_tpl/sidebar-related.tpl" }}
Let's take a look at what is going on inside the _tpl/article-cont.tpl file:

Design delivered by template _tpl/article-cont.tpl
The article title is the most important thing in the Article. It should use either the <h1> or <h2> heading tag (depending on how you decided to mark up your publication name; see more on these issues in the chapter on Search Engine Optimisation):
<h2>{{ $gimme->article->name }}</h2>
You can refer to the publish date and the section where the article came from. Article authors, photographers and other contributors are being mentioned next.
Published on {{ $gimme->article->publish_date|camp_date_format:"%e %M %Y" }}
in <a href="{{ uri options="section" }}">{{ $gimme->section->name }}</a>
<br />
By: {{ list_article_authors }}
{{ $gimme->author->name }} ({{ $gimme->author->type|lower }})
{{ if !$gimme->current_list->at_end }}, {{ /if }}
{{ /list_article_authors }}
Do you map and display locations? Great! Here is how to display them on the page:
Location(s): {{ list_article_locations }}
{{ if $gimme->location->enabled }}{{ $gimme->location->name }}
{{ if $gimme->current_list->at_end }}{{ else }}, {{ /if }}
{{ /if }}
{{ /list_article_locations }}
Now let's start the story. In the following code snippet we will display the introduction from the article, using the Article Field intro. We are also checking if the image with the number 1 is present and present it accordingly. The last line lists the rest of the story, stored in the Article Field full_text.
{{if $gimme->article->has_image(1)}}<img src="{{url options="image 1"}}" alt="{{$gimme->article->image1->description}}" />{{/if}}
<div class="intro">{{ $gimme->article->intro }}</div>
<div class="full_text">{{ $gimme->article->full_text }}</div>
Not that difficult, is it? If you are still with us, go an extra round and check if the content is actually available to the reader, with $gimme->article->content_accessible. If the value returned is TRUE, either the article is available to everybody or the reader is logged in and has the right to access the article. You can find more on subscription management in the section of this Cookbook on Advanced templating.
{{ if $gimme->article->content_accessible }}
{{if $gimme->article->has_image(1)}}<img src="{{url options="image 1"}}" alt="{{$gimme->article->image1->description}}" />{{/if}}
<div class="intro">{{ $gimme->article->intro }}</div>
<div class="full_text">{{ $gimme->article->full_text }}</div>
{{ else }}
<p>This article is accessible only to registered and logged in users!</p>
{{ /if }}
As you can see, the article-cont.tpl sub-template is mostly about the article content itself. The rest are auxiliary, but very important parts. They are also included in the article.tpl template.
Article Comments
Comments are explained in more detail in the following chapter. We believe that they are an essential way to communicate with your audience - and for your audience to communicate among themselves. In "The Journal" template pack, comments look like this:

Screenshot from the comments on "The Journal" template package.
Article Map
To round up the article page, here is the line that displays a map with locations that have been set in the Article Edit page by your journalists. There is more about maps and geolocation in a later chapter.
<div class="widget block"><h3>Map</h3>
{{ map show_locations_list="true" show_reset_link="Show initial Map" width="300" height="250" }}
</div>

Map embedded in article. Locations are handled in the Article Edit screen.
Article Attachments
Journalists can attach files to an article. We also include them in the article.tpl as a separate sub-template article-attachments.tpl. The code snippet below checks if attachments are present, and displays a list if there are.
{{if $gimme->article->has_attachments}}
<ul>
{{list_article_attachments}}
<li>
<a href="{{uri options="articleattachment"}}">
{{$gimme->attachment->file_name}}</a>
[{{ $gimme->attachment->extension }}|{{$gimme->attachment->size_kb}}Kb]
<br />
{{$gimme->attachment->description}}
</li>
{{/list_article_attachments}}
</ul>
{{/if}}
Listing Articles
You can create lists of articles, which is usually done inside a section overview of the content. But it can also be interesting to use this on the article page for "further reading" or "related articles".
Listing articles with list_articles is the most powerful and mostly used statement in Newscoop. You can check the Template Reference at the end of this Cookbook for all function options. Here are just a few examples to give you a taste:
List the last 10 articles:
{{ list_articles length="10" order="byPublishDate desc" ignore_issue="true" ignore_section="true"}}
{{* code goes here *}}
{{ /list_articles }}
Show last published article, of type 'article', from section number 100, regardless of issue:
{{list_articles length="1" constraints="type is article section is 100" ignore_issue="true" order="bypublishdate desc"}}
{{* code goes here *}}
{{/list_articles}}
List the last article from section numbers 100 to 140:
{{ list_sections constraints="number greater_equal 100 number smaller_equal 140" }}
{{ list_articles length="1" ignore_issue="true" order="byPublishDate desc" }}
{{* code goes here *}}
{{/list_articles}}
{{/list_sections}}
List 10 more articles from the same section, ordered by publish date, excluding the one already defined:
{{list_articles length="10" constraints="number not `$gimme->default_article->number`" ignore_issue="true" order="bypublishdate desc"}}
{{* code goes here *}}
{{/list_articles}}
Article comments
In this chapter you will learn how to display comments and the comment form, and how to use CAPTCHA or ReCAPTCHA spam protection. Comments are the place for your readers to give their feedback on an article. Comments also reflect the conversation of the community of your publication. Your readers are not only communicating their ideas about the article, but also communicating with each other.
Enabling and disabling comments is set for each publication in the administration interface. Here you can enable or disable comments for publications, for article types and for individual articles. If you switch off comments at the publication level, no comments can be added at all. The next level is article type: if you disable comments here, the option will not appear in the Article Edit screen for articles of this type. If both of these options are enabled, editors can switch commenting off for an individual article.
Listing the most commented articles
Before we dive into article comments, here's a little nugget showing how you can list articles by the number of comments they have, in descending order:
{{ list_articles order="bycomments desc" }}
<p>
{{ $gimme->article->name }},
comments: {{ $gimme->article->comment_count }}
</p>
{{ /list_articles }}
This list_articles function will list the articles inside the current section, by default. To list all articles from an issue use:
{{ list_articles ignore_section="true" order="bycomments desc" }}
For the entire publication, use:
{{ list_articles ignore_section="true" ignore_issue="true" order="bycomments desc" }}
Listing article comments
The following code has been taken from the template pack "The Journal", designed by Woo Themes and available on the Sourcefabric website. If comments are available, you can list them like this:
{{ list_article_comments columns="2" order="bydate desc"}}
{{ if $gimme->current_list->at_beginning }}
<h4>{{ $gimme->article->comment_count }} Response(s) to "{{ $gimme->article->name }}"</h4>
<ol class="commentlist">
{{ /if }}
<li class="comment {{ if $gimme->current_list->column == "1" }}odd{{ else }}even{{ /if }}">
<div class="comment-head cl">
<div class="user-meta">
<strong class="name">{{ $gimme->comment->nickname }}</strong>
{{ $gimme->comment->submit_date|camp_date_format:"%e.%m.%Y at %H:%i" }}
</div>
</div>
<div class="comment-entry">
<p>{{ $gimme->comment->content }}</p>
</div>
</li>
{{ if $gimme->current_list->at_end }}
</ol>
{{ /if }}
{{ /list_article_comments }}
list_article_comments lists the comments. columns="2" is used to add "odd" and "even" classes in the list. order="bydate desc" assures that the newest comment appears on the top of the list. The other values in this example are pretty much self-explanatory.
More properties of the article comment can be printed, like e-mail or unique ID. You can find these properties in the reference part of this Cookbook.
If you want to display the comments only if commenting is enabled, use the above code inside the following IF function:
{{ if $gimme->article->comments_enabled }}
[... code goes here ...]
{{ /if }}
If you want to display the comments only if the reader has access to the content of the article - either because it is available to all, or because the user is logged in and has a subscription to the content - use the above code inside the following IF function:
{{ if $gimme->article->content_accessible }}
[... code goes here ...]
{{ /if }}
You can also combine the two like this:
{{ if $gimme->article->comments_enabled && $gimme->article->content_accessible }}
[... code goes here ...]
{{ /if }}
Creating the form for article comments
The comment form can be styled freely. It is wrapped in {{ comment_form }} which creates the form tag automatically. The HTML inside is limited only by your imagination.
{{ comment_form html_code="id=\"commentform\"" submit_button="SUBMIT" button_html_code="tabindex=\"6\"" }}
<label for="author"><small>Name (required)</small></label>
{{ camp_edit object="comment" attribute="nickname" html_code="id=\"author\" 22\" tabindex=\"1\"" }}
<label for="email"><small>E-mail (will not be published) (required)</small></label>
{{ camp_edit object="comment" attribute="reader_email" html_code="id=\"email\" 22\" tabindex=\"2\"" }}
<input type="hidden" name="f_comment_subject" value="Site comment" />
{{ camp_edit object="comment" attribute="subject" html_code="id=\"comment-subject\" tabindex=\"3\"" }}
<label for="comment"><small>Comment</small></label>
{{ camp_edit object="comment" attribute="content" html_code="id=\"comment\" rows=\"5\" tabindex=\"4\"" }}
<img src="{{ captcha_image_link }}"><br />
<label for="f_captcha_code"><small>Enter the code:</small></label>{{ camp_edit object="captcha" attribute="code" html_code="id=\"comment-code\" tabindex=\"5\"" }}
{{ /comment_form }}
As shown above, the display of the form can be controlled to show up only IF the article allows commenting or IF the user has access to the article.
Spam control with CAPTCHA
To prevent automated spamming, you can add a CAPTCHA image to your comment form. It displays letters which the user needs to type in before posting their comment. Include a CAPTCHA by adding the following lines just before {{ /comment_form }}:
<img src="{{ captcha_image_link }}"><br />
<label for="f_captcha_code"><small>Enter the code:</small></label>{{ camp_edit object="captcha" attribute="code" html_code="id=\"comment-code\" tabindex=\"5\"" }}
When submitting the comment, the string typed by the reader is checked against the CAPTCHA image. If it is not identical, an error can be displayed.
{{ if $gimme->submit_comment_action->is_error }}
{{ $gimme->submit_comment_action->error_message }}
{{ $gimme->submit_comment_action->error_code }}
{{ /if }}
The error code is machine generated and can not be changed. The error message can be changed in the administration interface, in "Localization".
Spam control with ReCAPTCHA Newscoop plugin
Instead of the solution mentioned above, you can use the ReCAPTCHA plugin (which works with Newscoop 3.5.2 and higher). In that case, you only need to use:
<p>
{{ recaptcha }}
</p>
You can read what reCAPTCHA is at http://www.google.com/recaptcha
Then, make sure to create the proper key for your site here:
https://www.google.com/recaptcha/admin/create
Your comment form will look like this

Steps to perform in order to work with this plugin:
- Download the recaptcha plugin from our site (if you installed Newscoop 3.5.2 or higher, you should have this plugin already in your Plugins Manager)
- Install and enable the plugin through the Plugins Manager in the Newscoop administration interface (in the main menu, Plugins -> Manage Plugins)
- Configure the plugin, the options are:
- Enable for comments:
- Enable for subscriptions:
- Enter the public key:
- Enter the private key:
- Include the appropriate template tag within your forms:
comments form:
{{ recaptcha }}
subscriptions form:
{{ recaptcha form='subscriptions' }}
Finally, enable the use of CAPTCHA for your publication in the Publication configure screen.
Checking for errors and article moderation
To go through the process of submitting, checking and giving feedback on article moderation you could structure the template in the following way:
{{ if $gimme->submit_comment_action->defined && $gimme->submit_comment_action->rejected }}
Your comment has not been accepted.
{{ /if }}
{{ if $gimme->submit_comment_action->is_error }}
{{ $gimme->submit_comment_action->error_message }}
{{ $gimme->submit_comment_action->error_code }}
{{ else }}
{{ if $gimme->submit_comment_action->defined }}
{{ if $gimme->publication->moderated_comments }}
Your comment has been sent for approval.
{{ /if }}
{{ /if }}
{{ /if }}
<h2>Leave a Reply</h2>
{{ if $gimme->user->blocked_from_comments }}
You are not allowed to comment.
{{ else }}
{{ comment_form html_code="id=\"commentform\"" submit_button="SUBMIT" button_html_code="tabindex=\"6\"" }}
[...]
{{ /comment_form }}
{{ /if }}
In this example you can also see where and how to place feedback for banned users.
Preview of comments
If you want to allow readers to preview their comments, you need to add the code preview_button="Preview" to {{ comment_form ... }}. "Preview" is the text that will be displayed on the button, but you can change this value.
{{ comment_form html_code="id=\"commentform\"" submit_button="SUBMIT" preview_button="Preview" button_html_code="tabindex=\"6\"" }}
If you add the preview_button, you will see the button show up at the end of the form. If the reader writes a comment and clicks "Preview", the preview can be displayed using the following template code:
{{ if $gimme->preview_comment_action->is_error }}
<p>There was an error previewing the comment:
{{ $gimme->preview_comment_action->error_message }}
</p>
{{ /if }}
{{ if $gimme->preview_comment_action->ok }}
<b>Comment preview</b><br/>
Subject: {{ $gimme->preview_comment_action->subject }}<br/>
Reader e-mail: {{ $gimme->preview_comment_action->reader_email }}<br/>
Content: {{ $gimme->preview_comment_action->content }}
{{ /if }}
A good place to put this code is just above the comment form.
Nested comments: using threads and levels
Comments can be displayed as nested trees.
<ul>
{{ assign var="level" value="1" }}
{{ list_article_comments order="bydate asc" }}
{{ if $gimme->comment->level gt $level }}
{{ assign var="level" value=$gimme->comment->level }}
<ul>
{{ /if }}
{{ if $gimme->comment->level < $level }}
{{ php }}
$gimme = $this->get_template_vars('gimme');
$level = $this->get_template_vars('level');
$count = $level - $gimme->comment->level;
for (; $count > 0; $count --) {
echo "</ul>";
}
{{ /php }}
{{ assign var="level" value=$gimme->comment->level }}
{{ /if }}
<li>{{ if $gimme->comment == $gimme->default_comment }}<b>{{ /if }}
Level: {{ $gimme->comment->level }}
<a href="{{ uri }}#comments">
Subject: {{ $gimme->comment->subject }}, Reader email: {{ $gimme->comment->reader_email }}
</a>
{{ if $gimme->comment == $gimme->default_comment }}</b>{{ /if }}<br/>
Content: {{ $gimme->comment->content }}
</li>
{{ /list_article_comments }}
</ul>
Sites in multiple languages
In this chapter, we're working with one of Newscoop's main advantages: the ability to easily create and manage multilingual publications.
The following screenshot shows the administration interface of a publication in English, Russian and Spanish. This is what you will see when you go to the list of issues:

List of issues in the admin interface for a multilingual publication in English, Russian and Spanish.
In Newscoop, there is the publication's default language (set in Content >Publication >Configure) and other language versions, or translations. Other languages are defined by creating translations of issues and articles. In the screenshot above, you can see that every issue is translated into two additional languages.
You don't need to create these translations with every new issue - when you add a new issue and choose the option to 'Use the structure of previous issue', a new issue will be created with all the language versions that already exist.
Note that all of an issue's language versions hold the same issue number. Similarly, sections in translated issues keep the original section's number, and translated articles keep the original article's number.
So how does Newscoop handle multilingual content? By changing the language parameter.
Take a look at these three URLs:
http://example.com/en/mar2011/posts/4/healthy-options.htm
http://example.com/es/mar2011/posts/4/opciones-saludables.htm
http://example.com/ru/mar2011/posts/4/-.htm
The most important difference regarding multilinguality lies in the language code (en, es, ru) and in the last part of the URL, generated using topics for SEO purposes. Incidentally, those links will work without that last part of the url. The article number (4) is enough to tell Newscoop which article it is.
Switching between languages
To switch from one language to another, we build a list of available languages. In our language switcher, if we change only the language parameter, all other parameters currently active will be used. If you change the language while on the article page, you will jump from translation to translation.
<ul>
{{ list_languages of_publication="true" }}
<li style="background: transparent url(http://{{ $gimme->publication->site }}/templates/_img/flags/{{ $gimme->language->code }}.png) no-repeat 5px center">
<a href="{{ uri }}/">{{ $gimme->language->name }}</a>
</li>
{{ /list_languages }}
</ul>
This switcher lists all languages defined by the content inside a publication. Because you cannot place a Greek translation into a Spanish issue, the appropriate issue is automatically created at the moment when you try to create an article in a language which is not yet defined.

Now let's get back to our language switcher. It will try to keep the active issue, section and article (if they exist in the required language). If not, the switcher will simply fall back to the previous level where a translation exists (i.e. section, and if section doesn't exist, then issue, which definitely exists - otherwise it wouldn't be on the language list).
What happens once your user switches to another language? Newscoop tries to serve all database content in that language - not only articles, but all other elements like system values for date (day names and month names), topics, author biographies etc. It is therefore important that all these values are translated to languages you plan to use.
Template strings also need translation; this is how you treat every string:
{{ if $gimme->language->english_name == "English" }}Search{{ /if }}
{{ if $gimme->language->english_name == "Spanish" }}Bsqueda{{ /if }}
[...]
NOTE: There are some pieces of content that are not yet translatable:
- Image captions
- Form buttons
- Some configuration settings that might be used to output values, for example {{ $siteinfo.description }}
You can solve this situation with following workarounds:
- Create an article field of single-line text, where journalists can store translations of image captions
- For forms, you will need to set 'if' statements to check which language page is opened and to provide a version of the form with appropriate button labels (or graphical buttons)
- Skip using configuration values, and instead use the translatable information stored in the publication structure (in some special article maybe, or as section description, or... be creative)
Search templates
You can control your search form and search results with templates. This gives you design freedom for the list of results, as well as the complexity and appearance of your search form.
The Search Form
Using the default Newscoop function {{ search_form }} creates a form like the following screenshot:

You can use the following code to create the form:
<h3>Search Articles</h3>
{{ search_form template="search.tpl" submit_button="Search" html_code="class=\"group\" id=\"search-form\"" button_html_code="id=\"search-button\"" }}
{{ camp_edit object="search" attribute="keywords" html_code="id=\"search-field\"" }}
{{ /search_form }}
The search terms are sent to the sub-template specified inside the function: search.tpl. (Note: if your search.tpl file is inside a folder, you need to specify the full path, the same as with the include function. You can also see how different html classes/IDs can be added to the form elements (using html_code and button_html_code; quotes inside need to be escaped), and how the submit_button text is defined (submit_button="Search").
To create a search form which doesn't have a button with text, but an image like the one shown below, you can use the following approach.

<div class="search">
{{ search_form template="search.tpl" submit_button=" " html_code="id=\"topSearch\"" button_html_code="class=\"replace\"" }}
<p class="fields">
{{ camp_edit object="search" attribute="keywords" html_code="id=\"s\" }}
</p>
{{ /search_form }}
</div><!-- /.search -->
Search results
First, here is the example code for the search results template search.tpl:
<div id="main">
<h1>Search results</h1>
{{ list_search_results length="5" order="bypublishdate desc" constraints="type is news" }}
<div class="post">
<h2 class="post-title"><a href="{{ uri options="article" }}" rel="bookmark" title="{{ $gimme->article->name }}</a></h2>
<p class="post-details">Published on {{ $gimme->article->publish_date|camp_date_format:"%e %M %Y" }} by {{ $gimme->article->author->name }} in <a href="{{ uri options="section" }}">{{ $gimme->section->name }}</a></p>
{{ if $gimme->article->has_image(1) }}<a title="{{ $gimme->article->name }}" href="{{ uri options="article" }}"><img src="{{ uri options="image 1 width 134"}}" alt="{{ $gimme->article->image->description }}" class="woo-image thumbnail"></a>{{ /if }}
<p>{{ $gimme->article->deck }}</p>
</div><!-- /.post -->
{{ if $gimme->current_list->at_end }}
<div class="more_entries">
<div class="alignleft">{{ if $gimme->current_list->has_previous_elements }}<a href="{{ uripath options="template search.tpl" }}?{{ urlparameters options="previous_items" }} ">« Newer Entries</a>{{ /if }}</div>
<div class="alignright">{{ if $gimme->current_list->has_next_elements }}<a href="{{ uripath options="template search.tpl" }}?{{ urlparameters options="next_items" }}">Older Entries »</a>{{ /if }}</div>
</div>
{{ /if }}
{{ /list_search_results }}
{{ if $gimme->prev_list_empty }}
<div class="postinformation">No results found</div>
{{ /if }}
</div><!-- /#main -->
Inside the list of search results, we have a div container of the class "post" which is being repeated as many times as there are results for the search terms. List length is limited to 5, so if there are more than five list elements, a link to the next page is created. The link to the previous page is also created, in case the reader is not on the first page of search results. All of this is done inside an if statement:
{{ if $gimme->current_list->at_end }}
....
{{ /if }}
You can also find a neat pagination example in the advanced section of this manual, where pagination is explained. If no search results were found, Newscoop would display a message like this:
{{ if $gimme->prev_list_empty }}
<div class="postinformation">No results found</div>
{{ /if }}
The parameter prev_list_empty refers to the list just before this statement - which was the search results list. In case the list of search results was empty, this sends an appropriately apologetic message.
Advanced search
Newscoop also offers 'advanced search' options. An advanced search form may appear to your publication's readers like this screenshot:

The code which generates this form is shown below:
{{ search_form template="search.tpl" submit_button="Search" button_html_code="id=\"adv-search-button\" class=\"rounded\"" }}
<div class="left">
<div class="form-element">
<label>Search by:</label>
<input class="radio" name="f_search_scope" value="content" checked="checked" type="radio">text
<input class="radio" name="f_search_scope" value="title" type="radio">title
<input class="radio" name="f_search_scope" value="author" type="radio">author
</div>
<div class="form-element">
<label for="adv-search">Keyword:</label>
{{ camp_edit object="search" attribute="keywords" html_code="id=\"adv-search\"" }}
</div>
<div class="form-element">
<label for="adv-select">Issue:</label>
{{ camp_select object="search" attribute="issue" html_code="id=\"adv-select\"" }}
</div>
<div class="form-element">
<label>Date:</label>
<div class="g-left">from {{ camp_edit object="search" attribute="start_date" }}</div>
<div class="g-right">to {{ camp_edit object="search" attribute="end_date" }}</div>
</div>
</div><!-- /.left -->
<div class="right">{{ /search_form }}</div>
This form is different than the simple search form earlier in this chapter, as it has more options for filtering the results of the search. Firstly, the reader has the option to narrow their search only to article text, article title, or article author, by selecting the appropriate radio button. The generated HTML for this part of the form looks like this:
<div class="form-element">
<label>Search by:</label>
<input class="radio" name="f_search_scope" value="content" checked="checked" type="radio">text
<input class="radio" name="f_search_scope" value="title" type="radio">title
<input class="radio" name="f_search_scope" value="author" type="radio">author
</div>
Next, the reader has the option to select a particular issue to narrow down their search, and this part of the code is responsible for that feature:
<div class="form-element">
<label for="adv-select">Issue:</label>
{{ camp_select object="search" attribute="issue" html_code="id=\"adv-select\"" }}
</div>
The HTML generated after template parsing is:
<div class="form-element">
<label for="adv-select">:</label>
<select name="f_search_issue" id="adv-select">
<option value="0" selected="selected"> </option>
<option value="8">8. Issue 8 (2011-03-18 08:00:08)</option>
....
<option value="1">1. Issue 1 (2010-12-02 08:00:07)</option>
</select>
</div>
The final option is to specify the time frame from which the reader wants to get search results. This is done with inline date choosers:
<div class="form-element">
<label>Date:</label>
<div class="g-left">from {{ camp_edit object="search" attribute="start_date" }}</div>
<div class="g-right">to {{ camp_edit object="search" attribute="end_date" }}</div>
</div>
The HTML that gets generated by this piece of Newscoop code is rather too long for this book. You can style the start and end date fields in CSS with the following id's:
#advanced-search #f_search_end_date,
#advanced-search #f_search_start_date {
width: 58px;
}
If you need to style the calendar that pops up when the reader clicks the date chooser field, there is the file javascript/jscalendar/calendar-system.css in your Newscoop installation. Feel free to play with it.
Making a 404 page template
Good-looking, user-friendly "404 page" templates let people know that although the page they requested can't be found, the site is still up and running correctly. Another Newscoop feature at the publication configuration level enables site developers to specify the template which will be used when readers try to load an invalid URL or non-existent page.

Your job is to design a new template for this purpose, and then to select it in the drop-down menu above. Every time a site visitor tries to open a non-existent page, you can provide them with a message that something went wrong, and offer useful links to pages they might be interested in.
For example, this ccould be your 404 template:
{{ include file="_tpl/_html-head.tpl" }}
<body>
<div id="top">
<div id="top-meta">
<div class="date">{{$smarty.now|camp_date_format:"%M %e, %Y"}} </div>
{{ include file="_tpl/top-search-box.tpl" }}
</div><!-- /#top-meta -->
<div id="header">
<div class="logo">
<a href="http://{{ $gimme->publication->site }}" title="{{ $gimme->publication->name }}"><img src="http://{{ $gimme->publication->site }}/templates/_img/logo.png" alt=""></a>
</div><!-- /.logo -->
</div><!-- /#header -->
</div><!-- /#top -->
<div>
{{ if ! $gimme->url->is_valid }}
<h1>Sorry, the requested page was not found.</h1>
{{ /if }}
</div>
<div id="footer">
<ul id="category-nav">
{{ list_sections }}
<li class="cat-item"><a href="{{ uri options="section" }}" title="View all posts filed under {{ $gimme->section->name }}">{{ $gimme->section->name }}</a></li>
{{ /list_sections }}
</ul>
<ul id="page-nav">
{{ set_issue number="1" }}
{{ set_section number="5" }}
{{ list_articles }}
<li class="page_item"><a href="{{ uri options="article" }}" title="{{ $gimme->article->name }}">{{ $gimme->article->name }}</a></li>
{{ /list_articles }}
{{ unset_section }}
<li style="border: medium none;" class="page_item"><a href="{{ uri options="template set_thejournal/archive.tpl" }}" title="Archives">Archives</a></li>
{{ set_default_issue }}
</ul>
</div>
</body>
</html>
A quicker solution may be to redirect all invalid URL requests back to your home page, but visitors deserve more precise information about what's going on, as well as a choice about what they want to do next.
Topics, switches, keywords to structure content
This chapter explains how to order your content in many different ways. Newscoop's structure of issue > section > article has many advantages. Depending on your publication, you might want to add other ways to present, structure and group your content. Topics, switches and keywords allow you to do exactly that.
With topics, you can cross-reference your content, similar to what tags or categories generally do. Topics are organized like a tree, with root topics and subtopics. Topics can be translated, can be part of an article type and can become part of the URL. You can check in your template if and what topics are assigned to an article. In this way you can use topics to structure your content - and change your layout, if you want.
Some publications using Newscoop replace the concept of issue > section > article entirely and order their content exclusively using topics. Structuring with topics and using the tree of topics and subtopics offers some liberties:
- An article can have more than one topic
- The topic tree structure allows variable depth of content
- Based on the position in the topic tree, similar articles can be grouped
Switches are another powerful way to filter your content. Beside two built-in switches ('Show article on front page' and 'Show article on section page'), you can create custom switches, and then filter your content if articles have these switches active.
Finally, keywords can be used in some cases to further fine-tune your article listings, but also as an option in creating article URLs which are human readable, increasing SEO.
Topics
How you organize topics in a topic tree may be very important. It's usually a good approach to create a root topic for group of topics, and then make subtopics in that branch.

This way, you can approach a specific topic branch in your templates. Let's look at an example - you are on a full article page, and want to provide information about all the categories that article is assigned to.

The code for this example is:
<div class="tags">
<p>Posted in {{ list_article_topics root="categories:en" }}<a href="{{ uri options="template index.tpl" }}" title="View all posts in category '{{ $gimme->topic->name }}'" rel="category tag">{{ $gimme->topic->name }}</a>{{ if !$gimme->current_list->at_end }}, {{ /if }}{{ /list_article_topics }}</p>
<p>Food type: {{ list_article_topics root="Food type:en" }}<a href="{{ uri options="template archive-food-type.tpl" }}" title="View all posts for food type '{{ $gimme->topic->name }}'" rel="food-type">{{ $gimme->topic->name }}</a>{{ if !$gimme->current_list->at_end }}, {{ /if }}{{ /list_article_topics }}</p>
</div>
You see that by specifying option root="categories:en" we can narrow down the list of topics. If we leave the root option unspecified, the listing will return all topics assigned to an article, regardless of the branch they are in.
What's more, this allows us to make topic names links to pages which list all articles assigned that topic. This is possible because the topic parameter is forwarded to the next page as one of the URL parameters, for example ?tpid=34. As we said before, when some topic is active, it heavily affects the context, because all article listings are filtered to the currently active topic only. So, the next page could have a simple article list like this:
{{ list_articles length="10" ignore_issue="true" ignore_section="true" order="bypublishdate desc" }}
and it will return the last ten articles that have this topic assigned, regardless of the section and issue.
You can also work with topics independently, by directly specifying the context you want to work with.
{{ set_topic name="garlic:en" }} .... {{ unset_topic }}
Everything inside set_topic and unset_topic is filtered to that specified topic, of course. Don't forget to unset the topic when you don't need it any more. Also, when you jump to some page with the topic parameter specified, be aware that the topic context affects the whole page with all its elements - main navigation, for example. So, in your included templates, be sure to think side-wide, not only about one page, and if working with articles, be sure that you locally switch off the topic parameter. You can do that using:
{{ local }}
{{ unset_topic }}
..... your code ...
{{ /local }}
You can also make listings of subtopics. One example that we provide here creates a drop-down menu with selectable topics that will send you to the next page (category-page.tpl) with the selected topic activated.
<script type="text/JavaScript">
function MM_jumpMenu(targ,selObj,restore){
eval(targ+".location='"+selObj.options[selObj.selectedIndex].value+"'");
if (restore) selObj.selectedIndex=0;
}
</script>
<form action="" method="post">
<label for="category">Category:</label>
<select id="category" name="category" onChange="MM_jumpMenu('parent',this,0)">
{{ set_topic name="Category:en" }}
<option selected>----- choose -----</option>
{{ list_subtopics }}
<option value="{{ uri options="template category-page.tpl" }}"> {{ $gimme->topic->name }}</option>
{{ /list_subtopics }}
{{ unset_topic }}
</select>
</form>
In Newscoop you don't need to specify the topic parameter directly in:
{{ uri options="template category-page.tpl" }}
because the topic is currently active (you are inside the topics list!) and is already part of {{ uri }}.
For the use of topics in SEO strategy, see the chapter on Search Engine Optimization.
Switches
You can use switches in two ways - by setting an 'if' clause
{{ if $gimme->article->custom_switch_name }}
.... your code ...
{{ /if }}
or in article lists, using
{{ list_articles constraints="custom_switch_name is on" }}
The list will then (beside other options that you may set) filter articles to return only those with custom_switch_name switched on.
You can, for example, use custom switches to determine if an article has to appear on the website in a breaking news block, or as an ordinary, less emphasized article. You can find an example of this in the chapter about dynamic page layouts.
Beside custom switches, you can use Newscoop's built-in switches 'On front page is on' and 'On section page is on'. Initially, these switches are meant to be used to determine if an article needs to be shown on the front and/or on the section page. Imagine a publication with sections featuring very many articles; not all articles can show up on the section page, and it would be even harder to link all articles directly from front page. So, these options can help journalists and editors promote the most exciting content in their publication.
Built-in switches can be used in article lists:
{{ list_articles constraints="onfrontpage is on" }}
{{ list_articles constraints="onsection is on" }}
or in 'if' clauses:
{{ if $gimme->article->on_front_page }}
{{ if $gimme->article->on_section_page }}
Keywords
The Keyword field exists by default in every article, and you can use its content in different ways - by setting if clauses, for example:
{{ if $gimme->article->has_keyword("organic") }}
...
{{ /if }}
or in an article list:
{{ list_articles constraints="keyword organic" }}
...
{{ /list_articles }}
Such a list will return all articles with the keyword 'organic' assigned. For using keywords in SEO strategy, see the chapter Search Engine Optimization (SEO).
Managing static pages
Newscoop doesn't have a special place for publishing static pages. There are different ways of handling static pages, depending on the requirements of your publication. You can park them in a separate publication, in a separate issue or a dedicated section.
A simple way of handling static pages is by using a specific Article Type - in our case "page" - and place pages in any issue or section you want. Then you can list those static pages like this:
<ul>
{{ list_articles ignore_issue="true" ignore_section="true" constraints="type is page" }}
<li><a href="{{ uri options="article" }}">{{ $gimme->article->name }}</a></li>
{{ /list_articles }}
</ul>
This will list all articles which are of the type "page", regardless of their issue or section.
A more sophisticated approach often seen in Newscoop implementations is to create a special issue, outside of the chronological ordering of "normal" issues. Most often that's issue number 1, with a structure and articles which are different from the rest of the publication.
For example, you could have issue number 1 with the name 'pages', and inside it the sections 'about' and 'legal'. To access the content in your publication, you would set the environment to the special issue, and by enclosing everything in {{ local }}...{{ /local }} you could ensure that general context of parameters is not changed.
{{ local }}
{{ set_issue number="1" }}
{{ list_sections }}
We have two sections, and want to create two subheads with section names, and then unordered lists with articles inside:
{{ list_articles constraints="type is page" }}
{{ if $gimme->current_list->at_beginning }}
<h3>{{ $gimme->section->name }}</h3>
<ul>
{{ /if }}
The subhead will be printed, and the unordered list opened only if the section has articles inside.
<li><a href="{{ uri options="article" }}">{{ $gimme->article->name }}</a></li>
In the code above, all the names of articles inside the section are made into links pointing to the full article pages.
{{ if $gimme->current_list->at_end }}
</ul>
{{ /if }}
The code above will close the unordered list, once the last article is reached. Finally, the statements are closed, with the code below.
{{ /list_articles }}
{{ /list_sections }}
{{ /local }}
This way, editors of the publication have the option to independently update the content of these static pages. Keeping them in issue number 1, they can easily jump there with only one click from the issue listing page.
List of popular articles (most read)
For many publications, a listing of the most popular articles is an easy way to keep readers on the site, thus increasing both page views and time on site. Newscoop has an internal statistics mechanism which counts page views (the mechanism counts each URL request as a "read"), and that mechanism can be called in other templates.
In this case, we will call the available functions to make a list of popular articles, which can then be arranged on a page like the screenshot below.
The following code snippet is taken from The Journal's front page, from the sub-template set_thejournal/_tpl/front_tabs.tpl
It is displayed inside a jQuery tab which displays comments together with the most read articles, which explains why the CSS <div> tags are the same for both. Read the chapter List of latest comments for instructions on how to make that template, and read the chapter on Tabs with jQuery for instructions on how to make the tab.
This will do the following:
- Assign the styling for the tab box
- Set the issue to the current one
- Return a list of five articles, ordered by popularity in descending order
- Set a constraint for the article type of 'news'
- Get the URI for the article
- Display the article name
<div id="tabs" class="block">
<ul class="idTabs wrap tabs">
<li><a class="selected" href="#commented">Most Read</a></li>
<li><a href="#recentcomments">Recent Comments</a></li>
</ul>
<div class="inside">
<ul style="display: block;" id="commented">
{{ local }}
{{ set_current_issue }}
{{ list_articles length="5" order="bypopularity desc" constraints="type is news" }}
<li><a href="{{ uri options="article" }}">{{ $gimme->article->name }}</a></li>
{{ /list_articles }}
{{ /local }}
Here is another example, which will tell Newscoop to do the following:
- List the ten most popular articles
- Those articles must have the article type of 'article'
- They must be from sections numbered between 20-300
- They must only be from the last five issues
- They will be ordered in descending order according to their popularity
{{ list_articles length="10" constraints="type is article section greater 19 section smaller 301 issue greater `$gimme->issue->number-5`" order="bypopularity desc" }}
Note the use of the backtick character in the code above. The next snippet will list the ten most popular articles in the last seven days. It will:
- Assign a variable for the date that is seven days in the past
- List the ten most popular articles in descending order
- Set constraints so that the dates of the articles returned are within the time we set in the variable
- Return articles regardless of issue and section
{{assign var="xdate" value="-7 days"|date_format:"%Y-%m-%d"}}
{{list_articles length="10" order="bypopularity desc" constraints="publish_date greater $xdate reads greater 0" ignore_issue="true" ignore_section="true"}}
The following example will:
- Assign a variable for a date one month in the past
- List the ten most popular articles in descending order
- Set constraints where the article type is 'article,' and the publish date is within the time we set in the variable
- Return articles regardless of issue
- Return articles regardless of section
{{assign var="xdate" value="-1 month"|date_format:"%Y-%m-%d"}}
{{list_articles length="10" order="bypopularity desc" constraints="type is article publish_date greater $xdate reads greater 0" ignore_issue="true" ignore_section="true"}}
List of latest comments
The Newscoop internal statistics mechanism keeps track of the latest comments, and this mechanism can be used to create a list of the ten most recent comments on the site for all articles. The following code snippet is taken from The Journal's front page, from the sub-template set_thejournal/_tpl/front_tabs.tpl
It is displayed inside a jQuery tab which displays comments together with most read articles (read the chapter List of popular articles (most read) for instructions on how to make that template).
Here is a screenshot:

This code snippet will:
- Set the current issue as the active environment
- List five articles, ordered by the latest comment, in descending order
- Set a constraint so that the article type is 'news'
- Apply a different style for the recent comments
- List a single comment, by date
- List the nickname given by a commenter on a comment
- Combine that with the name of the article they're commenting on
- Make that article name appear in italic
<ul>
{{ local }}
{{ set_current_issue }}
{{ list_articles length="5" order="byLastComment desc" constraints="type is news" }}
<li class="recentcomments">{{ list_article_comments length="1" order="bydate desc"}}{{ $gimme->comment->nickname }}{{ /list_article_comments }} on <a href="{{ uri options="article" }}" style="font-style: italic">{{ $gimme->article->name }}</a></li>
{{ /list_articles }}
{{ /local }}
</ul>
Here is another example which will do the following:
- List the ten most recent comments, regardless of article
- Order the comments by date, in descending order
- Provide the URI for the comment and the article's name
- Return the count of article comments
- Return an excerpt of the article comments, truncated to 400 characters
- Return the date and time the comment was posted
{{list_article_comments length="10" ignore_article="true" order="byDate desc"}}
<a href="{{uri}}#comments">{{$gimme->article->name}}</a><sup>{{$gimme->article->comment_count}}</sup>
<p>{{$gimme->comment->content|truncate:400}} <span>{{$gimme->comment->submit_date|camp_date_format:"%H:%i"}}</span></p>
{{/list_article_comments}}
Finally, here is a similar, but more limited approach. We will:
- List the ten most recently-commented articles, ordered by last comment, in descending order, regardless of the issue and section they were published in
- Return the article's URI
- Return the article's name
- Return the count of comments for the article
{{ list_articles length="10" order="byLastComment desc" ignore_issue="true" ignore_section="true" }}
<a href="{{ uri }}#comments">{{ $gimme->article->name }}</a><sup>{{ $gimme->article->comment_count }}</sup>
{{ /list_articles }}
To learn more about listing comments for one specific article and providing the comment form, read the chapter on Article Comments.
Using maps
In Newscoop, journalists can add points of interest (POIs) to a map from the article edit page, and then add additional information which will appear in a pop-up bubble when a reader clicks on the POI. This information can include HTML (including embeds from YouTube, Flickr or Soundcloud).
Map displayed in article. Screenshot taken from "Ushahidi Cooker" template package.
For more on how editors and journalists can create maps and add POIs, see the Locations chapter in the manual Newscoop 3 for Journalists and Editors, available from:
http://manuals.sourcefabric.org
Creating maps is creating content
Before we dive into how you can use Newscoop's maps and POIs in your templates, here's a bit of our philosophy on geolocation.
Newscoop's mapping is different than just opening a Google Maps embed and passing POIs to Google. This distinction is important, because it has to do with what many publishers believe will make you money now, and in the future as well.
Publishers may be making a strategic mistake when they pass their POIs to commercial map providers like Google. It will be harder to monetize that data because Google and its competitors will be likely to be doing the monetizing instead. We believe that mobile content represents a major revenue opportunity for publishers, and that location-based information is one of the keys to mobile revenue.
This was one of the main reasons we wanted to provide publishers with two important alternatives. The first is that in Newscoop 3's mapping features, publishers keep the points of interest inside their own database, and because they own their databases, publishers can monetize that information as they see fit.
Select the map provider you like
The second crucial point in our design of the geolocation features in Newscoop 3 has to do with supporting OpenStreetMap, as a free and open source alternative to commercial online mapping services. OpenStreetMap is to maps as Wikipedia is to encyclopedias - anyone can contribute and improve its accuracy, which means that many parts of the world are far better mapped with OpenStreetMap than they are with commercial maps - countries such as Georgia are completely blank in Google Maps and Bing, for example, but are mapped in detail with OpenStreetMap.
OpenStreetMap also provides publishers with additional strategic importance: The project will probably never compete with publishers in the same way that commercial services are doing and will continue to do. For example, publishers that are too-closely tied to a mapping service provider could fall victim to changes in terms of service. And because publishers using Newscoop 3.5 can choose between Google Maps and OpenStreetMap, their options are open (this switching is enabled by a very cool open source project called OpenLayers, by the way).
Important: OpenStreetMaps' own site and base maps are not intended for large-scale map tile serving; they'll actually throttle back heavy users. It's better to use a service like Mapquest Open (Mapquest's own implementation of OpenStreetMap, at http://open.mapquest.com) which is not limited. Mapquest Open is also supported out-of-the-box in Newscoop as an option.
Templating and Maps
Requirements
In order to display maps, you must include jQuery in the header of your document, with a link like this:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js">
Displaying a Map within an Article
On the templating side, Newscoop's maps are quite easy to implement, relying on only a couple of templating directives. Here is a simple example from "The Journal" template package which includes a map inside the article-map.tpl sub-template:
{{ if $gimme->article->has_map }}
{{ include file="set_thejournal/_tpl/article-map.tpl" }}
{{ else }}
{{ include file="set_thejournal/_tpl/_banner300x250.tpl" }}
{{ /if }}
In the code above we first validate if the current article has a map, and if so, we include the template rendering the map. If the article does not have a map, we display an advertisement instead.
Inside the article-map.tpl file included in the snippet above, there's a one-line directive:
{{ map show_locations_list="true" show_reset_link="Show initial Map" width="300" height="250" }}
This will display a 300px by 250px map, plus the text list of the locations (also called Points Of Interest, or POI's), with a text link which, when clicked, resets the map to the position the editor or journalist originally set.

The resulting map displays the list of points and the map with two points on it. The width and height values used here are not mandatory; if not present, then the global values set in Newscoop preferences are used. You can find more details on this in the chapter System Preferences of the Newscoop 3 for Journalists and Editors manual.
Listing Article Locations
In the previous example, you saw that it's possible to display the list of locations together with the map, but it's a simple list. What if you want to display a list with some more data about each location? You might need to publish that data even without displaying the graphical map. For this purpose, Newscoop provides a special function list_article_locations.
We are now going to display a more detailed list of locations for the same article, with the following code:
{{ map show_locations_list="false" show_reset_link="Show initial Map" width="300" height="250" }}
{{ list_article_locations }}
{{ if $gimme->location->enabled }}
<p>
Location Name: {{ $gimme->location->name }}<br />
Geo Position: {{ $gimme->location->longitude }},
{{ $gimme->location->latitude }}<br />
Description: {{ $gimme->location->text }}<br />
</p>
{{ /if }}
{{ /list_article_locations }}
And the output looks like this:


Geolocation was recently introduced with the release of Newscoop 3.5.0, so it is a relatively new feature. It is already powerful, and will become even better as we get more feedback from web developers. Important improvements are being developed for the upcoming releases, most of them under the concept of Multi-maps.
Currently, when you are editing an article in the Newscoop administration interface you have the option of adding a map, and then you can add as many locations (point of interests) as you want. All those locations are stored in the database and can be displayed in article pages, but only together with the article those points are related to.
The concept of multi-maps goes far beyond this. You will be able to set a map using several different options, grouping multiple locations regardless of which articles they belong to. It is called multi-maps because a single map will be able to display locations from multiple articles, but also because in a single article you will be able to display multiple maps.
It will be possible to do advanced stuff by defining a map specifying, for example:
- from which articles you want to display locations, with all those points in a single map
- one or more topics, then Newscoop will find all articles connected to those topics and display all the locations from those articles, again in a single map
- the area (rectangle, polygon). Newscoop will look for all the locations matching this criteria and they will be displayed in a map
It will be also possible to select a map, and then display the list of all the articles the journalists have written corresponding to the locations in that map.
Sounds exciting? Actually, it is!
Managing multiple authors and articles
Newscoop has a built in author management tool in which you can create and edit author accounts, with biographies, pictures and other information. You can also create different kinds of author accounts, for photographers, translators, researchers or other contributors - multiple authors can be assigned to a single article.

The following sample code will explain how to print author information when displaying an article. You can print an author's last and first name, their image URL, full name, author type (photographer, etc.), their email address and biographical text.
<ul>
{{ list_article_authors }}
<li style="clear: left;">
<strong>{{ $gimme->author->last_name }}</strong>, {{ $gimme->author->first_name }}<br />
<img src="{{ $gimme->author->picture->imageurl }}" align="left" width="66px">
{{ $gimme->author->name }}
({{ $gimme->author->type }}):
<a href="mailto:{{ $gimme->author->email }}">{{ $gimme->author->email }}</a>
{{ $gimme->author->biography->text }}
</li>
{{ /list_article_authors }}
</ul>
Subscriptions, registration and content access
Newscoop templates can be constructed in a way that they deliver content depending on the status of the user (logged in or not) and their subscription (does the user have access to this article, section, or language?)
If you decide to use subscriptions, this chapter explains how control access to the content, and how to set up the registration process and forms. In a previous chapter we discussed the strategy of using subscriptions in your publication. Further below, you can find a quick introduction to managing subscriptions through the administration interface.
Using a subscription mechanism allows you to manage content access:
- Some content is accessible only to those users who are logged in
- An additional requirement for paid subscriptions may be that the reader has to have a valid subscription for the content they are attempting to access
Journalists and editors then need to switch off the 'Visible to non-subscribers' option on the article edit screen, in order to restrict access to the article.
Controlling content and functionality access
You can check if the reader is logged in with $gimme->user->logged_in:
{{ if $gimme->user->logged_in }}
{{ include file="_tpl/article-comments.tpl" }}
{{ else }}
Register and log in to comment
{{ /if }}
You can check if the user has access to content with $gimme->article->content_accessible. What you do with this information is up to you. You can still deliver the same content if you want, or you can only deliver parts of it. Here are two examples to illustrate this. First, truncate the article for readers who are not allowed access yet:
{{ if $gimme->article->content_accessible }}
{{ include file="_tpl/article-fullcontent.tpl" }}
{{ else }}
{{ $gimme->article->full_text|truncate:300 }}
Buy a subscription today to get full access!
{{ /if }}
Or display relevant information in classified ads to readers who have subscribed, like this:
{{ $gimme->article->ad_text }}<br/>Contact:
{{ if $gimme->article->content_accessible }}
<a href="mailto:{{ $gimme->article->ad_email }}">{{ $gimme->article->ad_email }}</a>
{{ else }}
Subscribe for contact information.
{{ /if }}
Registration, login and subscription templates
Your job gets much more complicated if you need to provide the entire functionality circle:
- Login option for your publication's existing subscribers
- Register option for new subscribers
- Account page for users to check or change their personal information, including changing their password
- Option to resend lost or forgotten passwords
- Logout option
If you're also working with paid/trial subscriptions, it's not enough for the reader just to be registered; they may be required to have a valid subscription to some, or all, sections or publications. You will need to develop functionality which:
- ensures that the reader is able to choose what they want to subscribe to (which language if more than one is available; which sections; which publications)
- gives the reader information on what they can choose, and what the price will be
Login and Registration Box
The first thing that a reader needs is the option to login or register. This can be displayed in a box placed somewhere near the top of your publication's pages.

The Newscoop template for this is:
<div class="logintop">
{{ if ! $gimme->user->logged_in }}
{{ login_form submit_button="login" }}
<p class="fields"><a href="{{ uri options="template register.tpl" }}">Register</a> | {{ if $gimme->login_action->is_error }}<span >{{ $gimme->login_action->error_message }}!</span>{{ else }}Sign in:{{ /if }}
<label for="uname"></label> {{ camp_edit object="login" attribute="uname" html_code="value=\"username\"" }}
<label for="uname"></label> {{camp_edit object="login" attribute="password" html_code="value=\"password\"" }}
{{ /login_form }}</p>
{{ else }}<form><p class="fields">Welcome, <a href="{{ uri options="template register.tpl" }}">{{ $gimme->user->name }}</a> | <a href="?logout=true">logout</a></p></form>
{{ /if }}
</div><!-- /.login-top -->
This template will check to see if the user is already logged in, and if they are, it will display 'Welcome, <Full Name>', where Full Name is also a link to the page where the reader can review their personal information. Also, an option for logging out is displayed.
Logging out works by generating a new URL parameter when the link is clicked:
<a href="?logout=true">logout</a>
This will reload the current page, but the hook is in the _html-head.tpl template. When this parameter in the URL is provided, the currently logged-in user is logged out. Here is the code:
{{ if $gimme->url->get_parameter('logout') == 'true' }}
<META HTTP-EQUIV="Set-Cookie" CONTENT="LoginUserId=; path=/">
<META HTTP-EQUIV="Set-Cookie" CONTENT="LoginUserKey=; path=/">
{{ $gimme->url->reset_parameter('logout') }}
<META HTTP-EQUIV="Refresh" content="0;url={{ uri }}">
{{ /if }}
Now, for some more serious stuff: If the user is not logged in, this template provides the options for logging in or registering. Registering calls the register.tpl template (the same one is used for modifying an existing reader's data).
Registration Template register.tpl
First, here's the whole code:
{{ if !$gimme->edit_user_action->defined && !$gimme->edit_subscription_action->defined }}
{{ include file="_tpl/user-form.tpl" }}
{{ /if }}
{{ if $gimme->edit_user_action->defined && $gimme->edit_user_action->is_error }}
<h5>Error registering your account: {{ $gimme->edit_user_action->error_message }}</h5>
{{ include file="_tpl/user-form.tpl" }}
{{ /if }}
{{ if $gimme->edit_user_action->defined && $gimme->edit_user_action->ok }}
{{ if $gimme->edit_user_action->type == "add" }}
<h5>Your user account was successfully added. You will soon receive a confirmation about how to access your subscription.</h5>
{{else }}
<h5>User data successfully added/modified</h5>
{{ /if }}
{{ /if }}
The code should be self-explanatory - it basically checks whether it should load the user form immediately (if no previous action was taken, it means that the reader wants to perform a new account registration), and additionally it checks to see if an error was generated in the registration process. Finally, if the previous action was a successful registration or account modification, the template will send the appropriate message.
Registration and Profile Form: user-form.tpl
The template called in the process of registration or account modification is user-form.tpl. We're using a table in this case because it's faster to make, but you can create your own CSS-based solution if you prefer:
{{ user_form template="subscription.tpl" submit_button="submit" }}
<p style="margin: 15px 0">Please fill in the following form in order to create the subscription account.</p>
<table id="contact" cellspacing="0" cellpadding="0">
<tr>
<td><label for="contact-name">Full name:</label></td>
<td>{{ camp_edit object="user" attribute="name" html_code="class=\"tablefield widerone\" id=\"contact-name\"" }}</td>
</tr>
<tr>
<td><label for="contact-email">E-mail:</label></td>
<td>{{ camp_edit object="user" attribute="email" html_code="class=\"tablefield widerone\" id=\"contact-email\"" }}</td>
</tr>
<tr>
<td><label for="contact-uname">Username:</label></td>
<td>{{ camp_edit object="user" attribute="uname" html_code="class=\"tablefield widerone\" id=\"contact-uname\"" }}</td>
</tr>
{{ if ! $gimme->user->logged_in }}
<tr>
<td><label for="contact-password">Password:</label></td>
<td>{{ camp_edit object="user" attribute="password" html_code="class=\"tablefield widerone\" id=\"contact-password\"" }}</td>
</tr>
<tr>
<td><label for="contact-passwordagain">Password (again):</label></td>
<td>{{ camp_edit object="user" attribute="passwordagain" html_code="class=\"tablefield widerone\" id=\"contact-passwordagain\"" }}</td>
</tr>
{{ /if }}
<tr>
<td><label for="contact-city">City, Country:</label></td>
<td>{{ camp_edit object="user" attribute="city" html_code="class=\"tablefield widerone\" id=\"contact-city\"" }}</td>
</tr>
<tr>
<td><label for="contact-phone">Phone:</label></td>
<td>{{ camp_edit object="user" attribute="phone" html_code="class=\"tablefield widerone\" id=\"contact-phone\"" }}</td>
</tr>
<tr>
<td><label for="second_phone">Phone (cell):</label></td>
<td>{{ camp_edit object="user" attribute="second_phone" html_code="class=\"tablefield widerone\" id=\"second_phone\"" }}</td>
</tr>
<input type="hidden" name="SubsType" value="paid" /> </table>
<div id="submitformdiv">
{{ /user_form }}
</div>
{{ if $gimme->user->logged_in }}<p style="margin: 15px 0"> To change your password, go <a href="{{ uri options="template user-chgpass.tpl" }}">here</a></p>
{{ /if }}
This is the universal user form which, in the case of user registration, also includes fields to define and double-check the user's password. In the other case, when a user is logged in when submitting this form, it means that the user is modifying their data and not creating a new user. The option for changing the password is then offered in a separate template (so as not to mess with changing the other data).
After registering or modifying the data, the user is redirected to the subscribe.tpl template, where the final step of creating or changing the subscription is performed.
In this example we are presuming that your publication intends to work with paid subscriptions, so we have one hidden parameter:
<input type="hidden" name="SubsType" value="paid" />
You can change it to work with trial subscriptions as well. Or, you can create a drop-down menu so the reader can choose what sort of subscription they wants to have:
Subscription type:
<select name="SubsType">
<option value="trial">Trial</option>
<option value="paid">Paid</option>
</select>
Please note that this Newscoop functionality isn't payment processing; it is for the system's internal purposes to determine whether or not the reader is subscribed to the content. Action is required from the site's staff to approve or decline the subscription, based on the reader's payment data.
Subscription Areas: subscription.tpl
The final step in this process, after creating a new user, is to define the content the user is interested in registering for. In Newscoop, publishers can set different prices for different languages, sections, or publications, and you can offer potential subscribers either a global publication subscription, or subscription by sections.
But before offering these forms, you need to check if everything went well, or if there were some errors... So here is the subscription.tpl template:
{{* no user form submitted, no subscription form submitted: display the user form *}}
{{ if !$gimme->edit_user_action->defined
&& !$gimme->edit_subscription_action->defined }}
{{ include file="_tpl/user-form.tpl" }}
{{ /if }}
{{* user form submitted with errors: display the error and the user form *}}
{{ if $gimme->edit_user_action->defined
&& $gimme->edit_user_action->is_error }}
<h5 style="margin-bottom: 20px">There was an error submitting the account creation form:
{{ $gimme->edit_user_action->error_message }}</h5>
{{ include file="_tpl/user-form.tpl" }}
{{ /if }}
{{* user form submitted ok: display the subscription form *}}
{{ if $gimme->edit_user_action->defined
&& $gimme->edit_user_action->ok }}
{{ include file="_tpl/subscription-form.tpl" }}
{{ /if }}
{{* subscription form submitted with errors: display the error and the submit form *}}
{{ if $gimme->edit_subscription_action->defined
&& $gimme->edit_subscription_action->is_error }}
<p style="margin: 15px 0">There was an error submitting the subscription form:
{{ $gimme->edit_subscription_action->error_message }}</p>
{{ include file="_tpl/subscription-form.tpl" }}
{{ /if }}
{{* subscription form submitted ok: display success message *}}
{{ if $gimme->edit_subscription_action->defined
&& $gimme->edit_subscription_action->ok }}
<p style="margin: 15px 0">Your subscription was created successfully.</p>
{{ /if }}
The subscription form itself:
{{ subscription_form type="by_section" total="Total" template="subscription.tpl" button_html_code="class=\"submitbutton\"" }}
<table class="userform">
<tr>
<th colspan="2">Please fill in the following form in order to create the subscription.</th>
</tr>
<tr>
<td colspan="2">
Subscription time:
{{ $gimme->publication->subscription_time }} {{ $gimme->publication->subscription_time_unit }}
</td>
</tr>
<tr>
<td colspan="2">
{{ camp_select object="subscription" attribute="alllanguages" }}
<span class="formtext">Subscribe to all languages</span>
</td>
</tr>
<tr>
<td>Languages:</td>
<td>{{ camp_select object="subscription" attribute="languages" }}
</tr>
<tr>
<td colspan="2">Sections</td>
</tr>
{{ list_sections }}
<tr>
<td colspan="2">
{{ camp_select object="subscription" attribute="section" }}
<input name="tx_subs{{ $gimme->section->number }}" type="hidden" value="{{ $gimme->publication->subscription_time }}">
{{ $gimme->section->name }}
</td>
</tr>
{{ /list_sections }}
</table>
{{ /subscription_form }}
All subscription options (price, time, time unit, currency...) are set on the Publication configuration page in Newscoop's administration interface (you can find it in Content -> Publications, then choose the wrench-and-screwdriver 'Configure' icon)

Then on the section level, you can decide to Add section to all subscriptions or to Delete section from all subscriptions.
The following user-chgpass.tpl template is only used to change existing Newscoop readers' passwords.
{{ user_form submit_button="submit" template="register.tpl" }}
<table id="contact" cellspacing="0" cellpadding="0">
<tr>
<td><label for="contact-passowrd">Password:</label></td>
<td>{{ camp_edit object="user" attribute="password" html_code="class=\"tablefield widerone\" id=\"contact-password\"" }}</td>
</tr>
<tr>
<td><label for="contact-passowrdagain">Password (again):</label></td>
<td>{{ camp_edit object="user" attribute="passwordagain" html_code="class=\"tablefield widerone\" id=\"contact-passwordagain\"" }}</td>
</tr>
</table>
<div style="margin: 15px 0;">
{{ /user_form }}
</div>
After changing the password, this template redirects the reader back to the register.tpl template.
At this point, you might be asking yourself: "Why the hell is the closing tag for the user_form set inside the div?" Put down your laser blaster nice and slow, and we'll explain: It's because the closing tag defines the position of the submit button.
Browser detection and robots (search engines)
For advanced web design, it is helpful to know more about the browser where the site is being displayed. You can also detect if your pages are being grabbed by a search engine robot, and deliver content accordingly. For example, if you are using a subscription model for your publication, you can display more information to the search engine robot than you would to an anonymous reader. This way, the search engines will list your content more descriptively than if they only grabbed the "please subscribe" page.
This chapter will give you some ideas on how to detect the client browser, or search engine robot, and change your templates accordingly. The template reference at the end of this Cookbook provides all the options for the browser object.
This is the kind of information Newscoop can get from a browser or robot:
iPhone browser
- Browser: safari, version 528.16 | Engine: webkit, version 528.18
- Mobile: device: iphone | OS: iphone os | OS version: 3.0
- Bot: no
- Type: mobile = handheld
Google Chrome browser
- Browser: chrome, version 10.0.648.205 | Engine: webkit, version 534.16
- Mobile: no
- Bot: no
- Type: bro = normal browser
Firefox browser
- Browser: firefox, version 3.6.16 | Engine: gecko, version 1.9
- Mobile: no
- Bot: no
- Type: bro = normal browser
Google robot
- Browser: googlebot, version 2.1 | Engine: false, version false
- Mobile: no
- Bot: yes
- Type: bot = web bot
The easy CSS way: classes in the body tag
An easy way to deliver different styles to different browsers is to add classes to the body tag, and then apply changes using CSS. Here some examples of the information you can print in the body tag with Newscoop:
iPhone 3
<body class="webkit mobile safari iphone iphoneos iphoneos3 iphoneos3-0 safari528 safari528-16" >
Firefox 3.6.16
<body class="moz bro gecko firefox firefox3 firefox3-6 firefox3-6-16 gecko1 gecko1-9" >
Internet Explorer 8
<body class="ie bro msie msie8 msie8-0 trident" >
Google Bot 2.1
<body class="google bot googlebot" >
Chrome 10.0.648.205
<body class="webkit bro chrome chrome10 chrome10-0-648-205" >
You can get these rich body tags using the following code snippet. Note: {{ textformat wrap=200 }} is used in this example to list all the classes in one line and avoid line breaks. The first line break would be applied after 200 characters - which is beyond what this code will deliver. Throw out what you don't need. You could also place the template in a separate file and use {{ include }}.
<body class="{{ textformat wrap=200 }}
{{ $gimme->browser->browser_working }}
{{ $gimme->browser->ua_type }}
{{ $gimme->browser }}
{{* mobile device / OS *}}
{{ $gimme->browser->mobile_data.0 }}
{{ $gimme->browser->mobile_data.3|regex_replace:"/\ /":"" }}
{{ strip }}{{ $gimme->browser->mobile_data.3|regex_replace:"/\ /":"" }}
{{ $gimme->browser->mobile_data.4|regex_replace:"/[\.][0-9]*/":"" }}{{ /strip }}
{{ strip }}{{ $gimme->browser->mobile_data.3|regex_replace:"/\ /":"" }}
{{ $gimme->browser->mobile_data.4|regex_replace:"/\./":"-" }}{{ /strip }}
{{* firefox / gecko *}}
{{ $gimme->browser->moz_data.0 }}
{{ strip }}{{ $gimme->browser->moz_data.0 }}
{{ $gimme->browser->moz_data.1|regex_replace:"/[\.][0-9]*/":"" }}{{ /strip }}
{{ strip }}{{ $gimme->browser->moz_data.0 }}
{{ $gimme->browser->moz_data.1|regex_replace:"/[\.][0-9]*$/":""|regex_replace:"/\./":"-" }}{{ /strip }}
{{ strip }}{{ $gimme->browser->moz_data.0 }}
{{ $gimme->browser->moz_data.1|regex_replace:"/\./":"-" }}{{ /strip }}
{{ if $gimme->browser->browser_working == "moz" }}
gecko{{ $gimme->browser->moz_data.2|regex_replace:"/[\.][0-9]*/":"" }}
gecko{{ $gimme->browser->moz_data.2|regex_replace:"/\./":"-" }}
{{ /if }}
{{* internet explorer *}}
{{ if $gimme->browser->browser_working == "ie" }}
{{ strip }}{{ $gimme->browser->browser_name }}
{{ $gimme->browser->webkit_data.2|regex_replace:"/[\.][0-9]*/":"" }}{{ /strip }}
{{ strip }}{{ $gimme->browser->browser_name }}
{{ $gimme->browser->webkit_data.2|regex_replace:"/\./":"-" }}{{ /strip }}
{{ if $gimme->browser->webkit_data.2 > 8 }}chakra{{ else }}trident{{ /if }}
{{ /if }}
{{* chrome *}}
{{ if $gimme->browser->browser_working == "webkit" }}
{{ strip }}{{ $gimme->browser->webkit_data.0 }}
{{ $gimme->browser->webkit_data.1|regex_replace:"/[\.][0-9]*/":"" }}{{ /strip }}
{{ strip }}{{ $gimme->browser->webkit_data.0 }}
{{ $gimme->browser->webkit_data.1|regex_replace:"/\./":"-" }}{{ /strip }}
{{ /if }}
{{ /textformat }}" >
Full template control: browser_detection.tpl
To collect the information listed at the beginning of this chapter, you can use the sub-template browser_detection.tpl. It should be called in the header of your pages, and will return a set of variables that make it easy to manage your templates for different browsers or robots. Here is the code for browser_detection.tpl:
{{* gecko / firefox ***********************************}}
{{ if $gimme->browser->browser_working == "moz" }}
{{ assign var="browserdetect_name" value=`$gimme->browser->moz_data.0` }}
{{ assign var="browserdetect_version" value=`$gimme->browser->moz_data.1` }}
{{ assign var="browserdetect_engineversion" value=`$gimme->browser->moz_data.2` }}
{{ assign var="browserdetect_engine" value="gecko" }}
{{ /if }}
{{* webkit / chrome / safari ***********************************}}
{{ if $gimme->browser->browser_working == "webkit" }}
{{ assign var="browserdetect_engineversion" value=`$gimme->browser->browser_number` }}
{{ assign var="browserdetect_name" value=`$gimme->browser->webkit_data.0` }}
{{ assign var="browserdetect_version" value=`$gimme->browser->webkit_data.1` }}
{{ assign var="browserdetect_engine" value="webkit" }}
{{ /if }}
{{* ie / internet explorer ***********************************}}
{{ if $gimme->browser->browser_working == "ie" }}
{{ assign var="browserdetect_name" value=`$gimme->browser->browser_name` }}
{{ assign var="browserdetect_engineversion" value=`$gimme->browser->webkit_data.2` }}
{{ assign var="browserdetect_version" value=`$gimme->browser->webkit_data.2` }}
{{ if $gimme->browser->webkit_data.2 > 8 }}
{{ assign var="browserdetect_engine" value="chakra" }}
{{ else }}
{{ assign var="browserdetect_engine" value="trident" }}
{{ /if }}
{{ /if }}
{{* bot / search engine ***********************************}}
{{ if $gimme->browser->ua_type == "bot" }}
{{ assign var="browserdetect_name" value=`$gimme->browser->browser_name` }}
{{ assign var="browserdetect_version" value=`$gimme->browser->browser_math_number` }}
{{ assign var="browserdetect_engine" value="false" }}
{{ assign var="browserdetect_engineversion" value="false" }}
{{ /if }}
{{* mobile devices ******************************************}}
{{ if $gimme->browser->ua_type != "mobile" }}
{{ assign var="browserdetect_mobile_device" value="false" }}
{{ assign var="browserdetect_mobile_os" value="false" }}
{{ assign var="browserdetect_mobile_os_number" value="false" }}
{{ else }}
{{ assign var="browserdetect_mobile_device" value=`$gimme->browser->mobile_data.0` }}
{{ assign var="browserdetect_mobile_os" value=`$gimme->browser->mobile_data.3` }}
{{ assign var="browserdetect_mobile_os_number" value=`$gimme->browser->mobile_data.4` }}
{{ /if }}
Save the code snippet above inside the _tpl folder of your template package. If you are using "The Journal" template pack, include it like this:
{{ include file="set_thejournal/_tpl/browser_detection.tpl" }}
If your template package has a different name, adjust the path accordingly. After the template has been called, the information about the browser listed earlier can be displayed by these lines:
<ul>
<li>Browser: {{ $browserdetect_name }}, version {{ $browserdetect_version }}
| Engine: {{ $browserdetect_engine }}, version {{ $browserdetect_engineversion }}</li>
<li>Mobile: {{ if $browserdetect_mobile_device == "false" }}no{{ else }}
device: {{ $browserdetect_mobile_device }} |
OS: {{ $browserdetect_mobile_os }} |
OS version: {{ $browserdetect_mobile_os_number }}
{{ /if }}</li>
<li>Bot: {{ if $gimme->browser->ua_type == "bot" }}yes{{ else }}no{{ /if }}</li>
<li>Type: {{ $gimme->browser->ua_type }} =
{{ if $gimme->browser->ua_type == "bot" }}web bot{{ /if }}
{{ if $gimme->browser->ua_type == "bro" }}normal browser{{ /if }}
{{ if $gimme->browser->ua_type == "bbro" }}simple browser{{ /if }}
{{ if $gimme->browser->ua_type == "mobile" }}handheld{{ /if }}
{{ if $gimme->browser->ua_type == "dow" }}downloading agent{{ /if }}
{{ if $gimme->browser->ua_type == "lib" }}http library{{ /if }}
</li>
Mobile device detection and templates
This chapter will give you a quick start into delivering different content to different devices, such as mobile phones. In the chapter on Browser detection and robots (search engines), you will find a more in-depth introduction. The template reference at the end of this Cookbook lists all options for the browser object.
Delivering content to mobile devices is becoming an increasingly important issue for web developers. Whereas devices like tablets handle normal websites well, the majority of mobile phone users benefit from custom templates, delivering content for smaller screens.
Some design issues can be handled using the media="handheld" versus media="screen" property in the link tag:
<link rel="stylesheet" type="text/css" href="...mobile.css" media="handheld"/>
<link rel="stylesheet" type="text/css" href="...screen.css" media="screen"/>
However, it is more elegant to serve custom pages for different devices. Among other factors, the amount of data downloaded can be reduced if you don't deliver parts of your page which are not meant for mobile devices - rather than just "hiding" them with CSS.
Here a simple example of how Newscoop can display a sidebar on the page, but only if the client does not use a mobile device:
{{ if $gimme->browser->ua_type != "mobile" }}
{{ include file="set_setname/_tpl/sidebar.tpl" }}
{{ /if }}
Change the path of the included file to match your template package. You can use the same logic for calling CSS files in the header:
{{ if $gimme->browser->ua_type == "mobile" }}
<link href="http://{{ $gimme->publication->site }}/templates/set_thejournal/_css/mobile.css" media="handheld" rel="stylesheet" type="text/css" >
{{ else }}
<link href="http://{{ $gimme->publication->site }}/templates/set_thejournal/_css/style.css" media="handheld" rel="stylesheet" type="text/css" >
{{ /if }}
If you want to deliver content more specifically for different browsers on mobile devices, read the chapter on browser detection. This will enable you, for example, to display links to you iPhone App only if the device is an iPhone. In a similar manner, you can handle media for different browsers as well. For instance, if the device does not support Flash, don't display the Flash player, but a link to the file.
Note: there might be issues with caching systems. If you encounter a problem with browser detection when testing your Newscoop site, switch off the cache and see if that fixes the problem.

A Mobile Browser Plugin is in development, which will give you more detailed information like the size of the display on the client side, allowing for even better control.
Tag clouds using topics
A tag cloud is a collection of words in one place, a depiction of the text content of your publication. Normally, tags are listed alphabetically, and the importance of each tag is shown with font size or colour. To make a tag cloud in Newscoop, we can use topics and sub-topics. First, you will need to create a list of Newscoop sub-topics, having the parent topic 'tagcloud':

Then, you will just need to attach the required sub-topics to an article:

Then, you need to create a Tag Cloud template. Please note that this template will be doing a lot of listings, so it might be a good idea to put it a cron job to produce the output, and place the result in a file for further inclusion from other templates.
The first thing to do will be to list all sub-topics (tags) of the main topic 'tagcloud' and get minimum and maximum numbers of articles having each topic. Also, we need to set up font-size ranges for the output:
{{ local }}
{{ unset_issue }}
{{ unset_section }}
{{ unset_article }}
{{ unset_topic }}
{{ set_topic name="tagcloud:en" }}
{{ assign var="first_good_tag" value=true }}
{{ list_subtopics }}
{{ assign var="posts_count" value="0" }}
{{ list_articles ignore_issue="true" }}
{{ assign var="posts_count" value=$gimme->current_list->count }}
{{ /list_articles }}
{{ if $posts_count > 0 }}
{{ if $first_good_tag }}
{{ assign var="min" value=$posts_count }}
{{ assign var="max" value=$posts_count }}
{{ assign var="first_good_tag" value=false }}
{{ /if }}
{{ if $posts_count > $max }}
{{ assign var="max" value=$posts_count }}
{{ /if }}
{{ if $posts_count < $min }}
{{ assign var="min" value=$posts_count }}
{{ /if }}
{{ /if }}
{{ /list_subtopics }}
{{ assign var="minSize" value="90" }}
{{ assign var="maxSize" value="240" }}
{{ assign var="diff_max_min" value="`$max-$min`" }}
{{ assign var="diff_maxSize_minSize" value="`$maxSize-$minSize`" }}
Next, we create the actual output. List sub-topics, get articles having each sub-topic, and assign the number of times the sub-topic was used:
<ul class="tag-cloud">
{{ list_subtopics }}
{{ assign var="posts_count" value="0" }}
{{ list_articles ignore_issue="true" }}
{{ assign var="posts_count" value=$gimme->current_list->count }}
{{ assign var="tag_name" value=$gimme->topic->name }}
{{ /list_articles }}
Then we calculate font size for the sub-topic in the tag cloud:
{{ if $posts_count > 0 }}
{{ if $min == $max }}
{{ assign var="fontSize" value="`$diff_maxSize_minSize/2+$minSize`" }}
{{ else }}
{{ assign var="a" value="`$posts_count-$min`" }}
{{ assign var="b" value="`$a/$diff_max_min`" }}
{{ assign var="fontSize" value="`$b*$diff_maxSize_minSize+$minSize`" }}
{{ /if }}
And finally output the result:
<li>
<span style="}}%"><a href="/?tpl=special_template_to_list_articles_based_on_topic.tpl&tag={{ $tag_name }}" title="{{ $posts_count }} articles having topic {{ $tag_name }}">{{ $tag_name }}</a></span>
</li>
{{ /if }}
{{ /list_subtopics }}
</ul>
{{ /local }}
As a result, you should get a Tag Cloud like the following screenshot:

Tag cloud created using topics
Dynamic page layouts
In this chapter, you'll learn how to create dynamic page layouts that change automatically when a staff user clicks on a check box on the Article Edit page.
The example we show here features an Article Type with a custom switch 'breaking_news'. This custom switch can be added to the Article Type in the Newscoop administration interface. The journalist or editor then sees a checkbox for 'breaking_news' in the Article Edit screen, which they will click whenever they consider the story they are working on to be particularly important.
The result of a staff user clicking this checkbox can be detected in the template. Inside list_articles a constraint is added, collecting only articles where the custom switch called 'breaking_news' is turned on. If there's an article that fulfills that criteria, then it's listed. If not, the layout remains the same:
{{ list_articles length="1" ignore_section="true" order="bypublishdate desc" constraints="breaking_news is on" }}
That tells $gimme to list one article with the following constraints:
- Display articles regardless of the section they're in
- Present the articles in descending chronological order according to their published date
- Only display articles where the "breaking_news" custom switch is on
The whole template looks like this:
{{ list_articles length="1" ignore_section="true" order="bypublishdate desc" constraints="breaking_news is on" }}
<div id="breakingNews">
<h3><a href="{{ uri options="article" }}">{{ $gimme->article->name }}</a></h3>
{{ list_article_images length="1" }}
<div id="breakingNewsLeft">
<img src="{{ uri options="image width 435" }}" alt="{{ $gimme->article->image->description }}" />
<p class="footnote">{{ $gimme->article->image->description }} {{ if $gimme->article->image->photographer }}(Photo: {{ $gimme->article->image->photographer }}){{ /if }}</p>
</div>
{{ /list_article_images }}
{{ if $gimme->prev_list_empty }}
<div id="breakingNewsLeft">
<img src="/templates/images/breaking-news-{{ $gimme->language->code }}.jpg" alt="Breaking news" />
</div>
{{ /if }}
<div id="breakingNewsCenter">
{{ $gimme->article->publish_date|camp_date_format:"%M %e, %Y" }}
<p>{{ $gimme->article->deck }}</p>
</div>
</div>
{{ /list_articles }}
For more on using custom switches, see the chapter titled Topics, switches, keywords to structure content.
Working with images
It's an understatement to say that images are crucial to news organizations. Because of their central role, Newscoop has a powerful and user-friendly media archive for storing, retrieving and reusing images in the administration interface. Newscoop's template language can access images in a number of different ways, and the output can be sent to web pages, to jQuery slideshows or other channels (see the chapter Image galleries with jQuery for more on that).
In this chapter, we'll look at how Newscoop templates work with images, image attributes and metadata. According to the Newscoop template reference, "The image object is usually initialized inside a list of article images or a list of images. It is not initialized at the beginning of the template and cannot be initialized by other Newscoop functions." In other words, images must be used through lists or through articles.
You can make use of images through the article object, like when the current article has one or more images attached. One more place where you can use an image object is with author objects. We'll go into these options in detail below. What you can't do at this point is use an image object as a single isolated element, because it has to be set first by any of the means mentioned above.
Displaying an article image
Let's start with a simple example. You have an article with only one image, and you want to display the image when the article is requested.
You can point to an image in two ways, either:
<img src="{{ $gimme->article->image1->imageurl }}" alt="{{ $gimme->article->image->caption }}" />
or:
<img src="{{ uri options="image 1" }}" alt="{{ $gimme->article->image->caption }}" />
The following code snippet does more, it:
- Gets the URL for an image attached to an article
- Puts the image caption (the description) into the ALT tag
- Puts the photo description into the title tag
- Displays the photographer's name
- Displays the image caption (the description)
<img src="{{ $gimme->article->image->imageurl }}"
alt="{{ $gimme->article->image->caption }}"
title="{{ $gimme->article->image->description }}" /><br />
by {{ $gimme->article->image->photographer }}<br />
{{ $gimme->article->image->description }}
An example of what similar code looks like in the browser is below (taken from the "The Journal" template pack):

You can even validate whether the article has an image or not. The value passed in parentheses correspond to the image number you assign to the image when attaching it to the article.
{{ if $gimme->article->has_image(1) }}
<img src="{{ $gimme->article->image->imageurl }}" />
{{ /if }}
It's also possible to access the image directly by the index number. If an image with that given index does not exist, then an empty image object is returned, and nothing will be displayed. It is good practice to first validate whether the requested image exists or not, but you already know how to do that!
<img src="{{ $gimme->article->image5->imageurl }}" />
There are more image properties you can display; we've already used some like imageurl, photographer and description, but there'll be more in the following examples. You can read the entire list in the chapter Template Objects -> Image of the Newscoop Template Reference.
Listing all images attached to an article
This is basically the same as we did before, but within a list of article images. Let's see some code:
{{ list_article_images }}
<li>
<img src="{{ $gimme->article->image->imageurl }}" /><br />
Caption: {{ $gimme->article->image->caption }}<br />
By: {{ $gimme->article->image->photographer }}
</li>
{{ /list_article_images }}
There's no need to use image indexes, because the list provides iteration over all images attached to the article.
Listing images from the media archive
Now the fun begins :-)
You already know how to work with image objects and how to list images attached to articles; this is very useful and will allow you to use image content all over your site.
But in specific cases you'll probably want to display images not necessarily related to articles. Remember that Newscoop provides a Media Archive (read more about it in the Newscoop 3 for Journalists and Editors manual), and every image you attached to an article is stored there.
The Newscoop template language provides a function to build lists of images according to different criteria. Let's say you want to build a list of images from a specific photographer. This code snippet can:
- Get a list of images where the photographer name is John Doe
- Order the images by the last update
- Get the images themselves based on their URLs
- Get the image captions (descriptions)
{{ list_images photographer=" John\ Doe" order="byLastUpdate" }}
<img src="{{ $gimme->image->imageurl }}" /><br />
<p>{{ $gimme->image->description }}</p>
{{ /list_images }}
Now here's list of images where the string "Prague" is present:
{{ list_images caption_like="Prague" order="byPhotographer" }}
<img src="{{ $gimme->image->imageurl }}" /><br />
<p>{{ $gimme->image->caption }}</p>
{{ /list_images }}
There are many other criteria you can use. A detailed list can be found in the Newscoop Template Reference in the List Images chapter.
Thumbnails
Newscoop automatically generates a 64-pixel-wide thumbnail for every image when the image file is uploaded into the Media Archive. Displaying a thumbnail is as easy as this:
<img src="{{ $gimme->image->thumbnailurl }} />
Author picture
The author object has the property picture, which is an image object, so that you can use it exactly as an article image. There's more on this in the chapter Managing multiple authors and articles in this Cookbook.
Scaling in percent and absolute size
Images in Newscoop are only stored in two different sizes: the original size and the automatically generated thumbnail. Usually it is necessary to display those images in a different size than those two available, so Newscoop provides a simple way to do this on the fly:
<img src="{{ $gimme->image->imageurl }}&ImageRatio=70" />
Here we just specified a ratio equal to 70, which means the image will be resized to 70 percent of its original size. You also have the option to provide an specific width or height value.
<img src="{{ $gimme->image->imageurl }}&ImageWidth=350&ImageHeight=310" />
Any image provided by $gimme can be scaled as shown above, including the thumbnail and author pictures. The logic of how Newscoop processes the values when both width and height are provided (and even the ratio) at the same time is explained, with more examples, in the wiki page: http://wiki.sourcefabric.org/x/c4EH
Pagination of lists and long articles
Pagination means dividing content into discrete pages, each displaying a page number. When a long list of search results is divided into more than one page, allowing the reader to proceed from page to page, that's pagination.
In this chapter, you will learn an advanced method for list pagination, and how to use subtitles to break up long articles.
Pagination of a long article list
Sometimes you might want to split a long list of articles into pages. You might do this on Section pages to show all articles in that particular section, without requiring the reader to scroll down too much.
To implement pagination we need to add an extra page parameter to a URL, something like the following example:
http://site_name/language_code/issue_number/section_number/?page=number
Then we can use the GET parameter to check the page we are on. We will use Smarty directly to check GLOBAL variables:
{{ if $smarty.get.page }}{{ assign var="page" value=`$smarty.get.page` }}{{ else }}{{ assign var="page" value="1" }}{{ /if }}
To split a list of articles into pages we will use a column parameter, which will control how many articles should be shown on a page. In this case, row parameter will be the actual page.
... {{ if $gimme->current_list->count > 10 }} ...
... {{ if $gimme->current_list->row == $page }} ...
In this example, we also need to add the ignore_issue parameter to get articles from all issues. The first part of the code, which will show the articles, would be:
{{ if $smarty.get.page }}
{{ assign var="page" value=`$smarty.get.page }}{{ else }}{{ assign var="page" value="1" }}{{ /if }}
{{ list_articles columns="10" ignore_issue="true" }}
{{ if $gimme->current_list->row == $page }}
<div class="list-articles"><a href="{{ uri options="article" }}">{{ $gimme->article->name }}</a>{{ $gimme->article->intro }}</div>
{{ /if }}
{{ /list_articles }}
...
In the second part of the code we will show page numbers, and add the page parameter to links. To do this, we will need to list the articles once again:
{{ list_articles columns="10" ignore_issue="true" }}
{{ if $gimme->current_list->count > 10 }}
{{ if $gimme->current_list->at_beginning }}
<div class="list-page-numbers">Page:
{{ /if }}
{{ if $gimme->current_list->column == 1 }}
{{ if $gimme->current_list->row == $page }}
<span>{{ $gimme->current_list->row }}</span>
{{ else }}
<a href="{{ uri options="article" }}?page={{ $gimme->current_list->row }}">{{ $gimme->current_list->row }}</a>
{{ /if }}
{{ /if }}
{{ if $gimme->current_list->at_end }}
</div>
{{ /if }}
{{ /if }}
{{ /list_articles }}
You will now have a list of articles and a list of page numbers, as shown in the screenshot below. You are free to add additional styles and controls to make your list shine.

Subtitles inside long Article Fields
You can include subtitles (also known as subheads) in longer articles, to break the article into pages. The journalist uses the WYSIWYG editor, marks the subtitle in the text and selects "campsite_subhead" from the pulldown menu under "styles". A simple list of all subtitles inside the article can be displayed on the article page like this:
<ul>
{{ list_subtitles field_name="full_text" }}
<li>{{ $gimme->subtitle->name }}</li>
{{ /list_subtitles }}
</ul>
Note that inside list_subtitles you need to specify the article field which you are working with, in this case the field full_text. The subtitles listed will all be from this particular article field, rather than any other field that may contain subtitles.
Adding a simple "previous" and "next" navigation from article subtitle to article subtitle can be done like this:
{{ if $gimme->article->full_text->has_previous_subtitles }}
<a href="{{ uri options="previous_subtitle full_text" }}">Previous</a>
{{ else }}
Previous
{{ /if }}
|
{{ if $gimme->article->full_text->has_next_subtitles }}
<a href="{{ uri options="next_subtitle full_text" }}">Next</a>
{{ else }}
Next
{{ /if }}
This navigation will display active links to "Previous" or "Next" only if there is a previous or next item in the list. Otherwise, the words Previous and Next are not clickable, and are just displayed for design reasons, so the eye does not need to jump back and forth.
Once you are using subtitles in an article with pagination, the content will no longer be displayed in a single page format. In order to display the entire article in a single page (e.g. for printing) you can use a link with options like this:
<a href="{{ uri options="all_subtitles full_text" }}">View entire article</a>
Audio player for attached MP3 files
Newscoop has an easy mechanism for attaching files to articles. In the Article Edit screen, on the right, you can attach files either from the existing file archive or upload new files. In this example we will embed an MP3 player in the page, playing audio files which have been attached to the article.
We offer two different examples of using an embedded Flash player. The first example embeds a player at the end of an article, like this:

Audio player on intex-press.by
The player we're using in this example needs to be placed in this folder:
/templates/_swf/player_mp3_maxi.swf
Any other player and any other folder location is possible. You only need to change the path in the code accordingly.
This code snippet will:
- Check to see if the article has any attachments; if it does, it will list them
- Check to see if the attachment has an extension of "mp3"
- If it is mp3, it will:
-
- Display the attachment's file description
- Call the Flash player and set its values
- Give the Flash player the URI for the article attachment
- Create a download link for the article attachment with its URI, file name and size
{{ if $gimme->article->has_attachments }}
{{ list_article_attachments }}
{{ if $gimme->attachment->extension == "mp3" }}
{{ $gimme->attachment->description }}<br />
<object height="20" width="200" data="/templates/_swf/player_mp3_maxi.swf" type="application/x-shockwave-flash" align="top">
<param value="/templates/_swf/player_mp3_maxi.swf" name="movie" />
<param name="wmode" value="opaque" />
<param value="mp3={{ uri options="articleattachment" }}&showstop=1&showvolume=1&buttonwidth=25&sliderwidth=15&bgcolor1=5EA65E&bgcolor2=365E36" name="FlashVars" />
</object><br />
<a href="{{ uri options="articleattachment" }}" />{{ $gimme->attachment->file_name }}, {{ $gimme->attachment->size_kb }}Kb</a>
{{/if}}
{{/list_article_attachments}}
{{/if}}
Using multiple players
The second example comes from Fluter.de, and involves keywords and multiple players. Here is a screenshot of how the players appear on the page:

Audio players on fluter.de
This example does the following:
- Uses an IF statement to see if the article has the keyword of 'mp3podcast1'
- If it does, Newscoop calls a Flash player
- Newscoop passes the Flash player the URL of the MP3 file
The audio files on Fluter.de are not article attachments. In the editorial workflow of that publication, the audio files are created separately and uploaded to a special location on the server. The code example below will point to the location:
http://www.fluter.de/medien/podcast_audio/
There, the audio files are sorted in subfolders by issue number, which we can retrieve using {{ $gimme->issue->number }}. Each file name contains a combination of issue number and article number, and finishes with the track number, so we can retrieve a specific file using:
podcast_mp3_{{ $gimme->issue->number }}_{{ $gimme->article->number }}_f1.mp3
The publication editor adds a keyword to the article containing the number of the audio files; mp3podcast1 means one file, mp3podcast2 two files, and so on. Depending on this keyword, the template will create one or more players. Here is the code for one player:
{{ if $gimme->article->has_keyword(mp3podcast1) }}
<object type="application/x-shockwave-flash" data="/medien/player/player.swf" width="290" height="24" id="audioplayer1"><param name="movie" value="http://www.fluter.de/audio-player/player.swf" />
<param name="FlashVars" value="playerID=1&bg=0x999999&leftbg=0x74787A&lefticon=0xffffff&rightbg=0x0090f0&rightbghover=0x74787A&righticon=0x000000&righticonhover=0x0090f0&text=0xffffff&slider=0x0090f0&track=0xFFFFFF&border=0xffffff&loader=0xffffff&soundFile=http%3A%2F%2Fwww.fluter.de%2Fmedien%2Fpodcast_audio%2F{{ $gimme->issue->number }}%2Fpodcast_mp3_{{ $gimme->issue->number }}_{{ $gimme->article->number }}_f1.mp3" />
<param name="quality" value="high" />
<param name="menu" value="false" />
<param name="bgcolor" value="#ffffff" />
</object>
{{ /if }}
This approach can be used for any file attachments; you can apply similar methods for PDF attachments or movies, for example. See the section Article object and attachment, comment, location in the Template Reference for more information on working with article attachments.
RSS, sitemap, KML and XML
The Newscoop template engine allows you deliver many kinds of structured content, including HTML, XML, CSV, vCard and more. In this chapter we will explain a few of these formats and how they are created. The process is always the same: develop your business logic, and then wrap the presentation logic around it.
RSS Feed
We will start with producing an RSS feed for syndication of the latest 15 articles from the current section in the publication. First, let's look at the basic structure of an RSS document. The channel tag contains three elements; channel metadata, an image block and an items list:
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
<channel>
[channel metadata]
[image block]
[items list]
</channel>
</rss>
Channel metadata is a required element which can include the channel's name or title, description, language, URL and copyright information.
<title>{{ $gimme->publication->name }}</title>
<link>http://{{ $gimme->publication->site }}</link>
<description>{{ $siteinfo.description }}</description>
<language>{{ $gimme->language->code }}</language>
<copyright>Copyright {{ $smarty.now|date_format:"%Y" }, {{ $gimme->publication->name }}</copyright>
<lastBuildDate>{{ $smarty.now|date_format:"%a, %d %b %Y %H:%M:%S" }} +0100</lastBuildDate>
<generator>Newscoop</generator>
The Newscoop snippet above grabs the name and site attributes of the publication, as well as the language code. Also, we make use of Smarty with some special modifiers to display the current date and time in two different formats (for more information on this, please read the Smarty manual).
Image block - the image's URL, title, link, width, and height tags allow RSS viewers to translate the file into HTML. This block is very straight forward, using the site and name attributes of the Newscoop publication.
<image>
<url>http://{{ $gimme->publication->site }}/templates/classic/img/logo-rss.jpg</url>
<title>{{ $gimme->publication->name }}</title>
<link>http://{{ $gimme->publication->site }}</link>
<width>144</width>
<height>19</height>
</image>
Items list - this is the most important piece of the RSS document, as the actual feeds are generated here. For this purpose we will use the list_articles statement with $gimme to request the latest 15 published articles. The list is built using the current language, publication, issue and section from the context.
{{ list_articles length="15" order="bypublishdate desc" }}
[list of items]
{{ /list_articles }}
Now we need to define the list of items.
<item>
<title>{{ $gimme->article->name }}</title>
<link>{{ url options="article" }}</link>
<description>
{{ $gimme->article->intro|strip_tags:false|strip|escape:'html':'utf-8' }}
</description>
<category domain="{{ url options="section" }}">
{{ $gimme->section->name }}
</category>
{{ if $gimme->article->author->name }}
<atom:author>
<atom:name>{{ $gimme->article->author->name }}</atom:name>
</atom:author>
{{ /if }}
<pubDate>
{{ $gimme->article->publish_date|date_format:"%a, %d %b %Y %H:%M:%S" }} +0100
</pubDate>
<guid isPermaLink="true">{{ url options="article" }}</guid>
</item>
Let's explain where we get the data from for each item tag:
title: The article name.
link: The article URL from Newscoop.
description: The text of the article intro, which is a custom field for the particular article type used here. In addition, we use some smarty modifiers in order to clean up the text, making sure it will be displayed properly.
category: We use the section name here.
atom author: If the article has an author defined, then we display their full name.
pubDate: The publication date of the article, with some special formatting. Please read up on the Smarty date_format modifier if you aren't sure about this.
guid: The article url as global unique identifier for the item.
Finally, this is how the whole template file should look:
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/">
<channel>
<title>{{ $gimme->publication->name }}</title>
<link>http://{{ $gimme->publication->site }}</link>
<description>{{ $siteinfo.description }}</description>
<language>{{ $gimme->language->code }}</language>
<copyright>Copyright {{ $smarty.now|date_format:"%Y" }}, {{ $gimme->publication->name }}</copyright>
<lastBuildDate>{{ $smarty.now|date_format:"%a, %d %b %Y %H:%M:%S" }} +0100</lastBuildDate>
<generator>Newscoop</generator>
<image>
<url>http://{{ $gimme->publication->site }}/templates/classic/img/logo-rss.jpg</url>
<title>{{ $gimme->publication->name }}</title>
<link>http://{{ $gimme->publication->site }}</link>
<width>144</width>
<height>19</height>
</image>
<atom:link href="http://{{ $gimme->publication->site }}/templates/feed/index-en.rss" rel="self" type="application/rss+xml" />
{{ list_articles length="20" order="bypublishdate desc" }}
<item>
<title>{{ $gimme->article->name|html_entity_decode|regex_replace:'/&(.*?)quo;/':'"' }}</title>
<link>http://{{ $gimme->publication->site }}/ru/{{ $gimme->issue->number }}/{{ $gimme->section->url_name }}/{{ $gimme->article->number }}</link>
<description>
{{ $gimme->article->intro|strip_tags:false|strip|escape:'html':'utf-8' }}
</description>
<category domain="http://{{ $gimme->publication->site }}/{{ $gimme->language->code }}/{{ $gimme->issue->number }}/{{ $gimme->section->url_name }}">{{ $gimme->section->name }}</category>
{{ if $gimme->article->author->name }}
<atom:author><atom:name>{{ $gimme->article->author->name }}</atom:name></atom:author>
{{/if}}
<pubDate>{{ $gimme->article->publish_date|date_format:"%a, %d %b %Y %H:%M:%S" }} +0100</pubDate>
<guid isPermaLink="true">http://{{ $gimme->publication->site }}/{{ $gimme->language->code }}/{{ $gimme->issue->number }}/{{ $gimme->section->url_name }}/{{ $gimme->article->number }}</guid>
</item>
{{/list_articles}}
</channel>
</rss>
How to get it working
There are different ways to achieve this, however what we recommend is to use Google FeedBurner as it provides significant benefits like statistics, social sharing, among others. Read more about FeedBurner here.
Now that you already have your RSS template file you need to configure it in FeedBurner. You can do this easily by input the URL to the RSS in your site, usually the URL looks like this as it is a direct reference to the RSS template file:
http://your.site.url/?tpl=123
FeedBurner will give you back a new "burned" URL that looks something like this:
http://feeds.feedburner.com/YourFeedName
Where YourFeedName is the name you input when burning your RSS feed in FeedBurner.
Now all what you need to do is to include the following line in the header template of your site.
<link rel="alternate" type="application/rss+xml" title="Newscoop News" href="http://feeds.feedburner.com/YourFeedName" />
Google Sitemaps
The Sitemaps protocol, introduced by Google, allows you to inform search engines about links on your site that are available for crawling. A Sitemap is a file in a specific XML format that lists the URLs of your site, including metadata about each URL carrying data like last updated, the relevance of the resource compared to other URLs in the site, and so on. This allows search engines to index the site in a more optimal way.
How to build a site map depends on the content structure you have designed for your specific site, but whatever it is $gimme will allow you to generate it.
Goal / Task
To display the Site Map for our particular use case, listing: All articles regardless language, issue and section, of type news, All articles regardless language, issue and section, of type show, All subtopics in English and French languages with parent topic equal to Countries, All sections from the current issue in English and French languages.
Implementation
All articles regardless language, issue and section, of type news.
{{ list_articles ignore_language="true" ignore_issue="true" ignore_section="true" order="bypublishdate desc" constraints="type is news" }}
<url>
<loc>http://wadr.org{{ uri options="article" }}</loc>
<lastmod>{{ $gimme->article->publish_date|camp_date_format:"%Y-%m-%d" }}</lastmod>
<changefreq>daily</changefreq>
<priority>0.6</priority>
</url>
{{ /list_articles }}
Notice the use of ignore_language, ignore_issue and ignore_section, all they are set to true so that those values from the context are ignored when building the list. We use the same approach for the next list.
All articles regardless language, issue and section, of type show.
{{ list_articles ignore_issue="true" ignore_section="true" ignore_language="true" order="bypublishdate desc" constraints="type is show" }}
<url>
<loc>http://wadr.org{{ uri options="article" }}</loc>
<lastmod>{{ $gimme->article->publish_date|camp_date_format:"%Y-%m-%d" }}</lastmod>
<changefreq>daily</changefreq>
<priority>0.8</priority>
</url>
{{ /list_articles }}
This list is similar to the first one, only difference is we are requesting articles of a different type: show this time.
All subtopics in English language with parent topic equal to Countries.
{{ set_language name="English" }}
{{ set_topic name="Countries:en" }}
{{ list_subtopics }}
<url>
<loc>http://wadr.org/{{ $gimme->language->code }}/?tpid={{ $gimme->topic->identifier }}&tpl=1442/</loc>
<changefreq>daily</changefreq>
<priority>0.4</priority>
</url>
{{ /list_subtopics }}
All subtopics in French language with parent topic equal to Countries.
{{ set_language name="French" }}
{{ set_topic name="Countries:en" }}
{{ list_subtopics }}
<url>
<loc>http://wadr.org/{{ $gimme->language->code }}/?tpid={{ $gimme->topic->identifier }}&tpl=1442/</loc>
<changefreq>daily</changefreq>
<priority>0.4</priority>
</url>
{{ /list_subtopics }}
All sections from the current issue in English language.
{{ set_current_issue }}
{{ set_language name="English" }}
{{ list_sections }}
<url>
<loc>http://wadr.org/{{ $gimme->language->code }}/{{ $gimme->issue->url_name }}/{{ $gimme->section->url_name }}/</loc>
<changefreq>weekly</changefreq>
<priority>0.3</priority>
</url>
{{ /list_sections }}
All sections from the current issue in French language.
{{ set_language name="French" }}
{{ list_sections }}
<url>
<loc>http://wadr.org/{{ $gimme->language->code }}/{{ $gimme->issue->url_name }}/{{ $gimme->section->url_name }}/</loc>
<changefreq>weekly</changefreq>
<priority>0.3</priority>
</url>
{{ /list_sections }}
This is how the full Sitemap file should look like:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
{{ list_articles ignore_language="true" ignore_issue="true" ignore_section="true" order="bypublishdate desc" constraints="type is news" }}
<url>
<loc>http://wadr.org{{ uri options="article" }}</loc>
<lastmod>{{ $gimme->article->publish_date|camp_date_format:"%Y-%m-%d" }}</lastmod>
<changefreq>daily</changefreq>
<priority>0.6</priority>
</url>
{{ /list_articles }}
{{ list_articles ignore_issue="true" ignore_section="true" ignore_language="true" order="bypublishdate desc" constraints="type is show" }}
<url>
<loc>http://wadr.org{{ uri options="article" }}</loc>
<lastmod>{{ $gimme->article->publish_date|camp_date_format:"%Y-%m-%d" }}</lastmod>
<changefreq>daily</changefreq>
<priority>0.8</priority>
</url>
{{ /list_articles }}
{{ set_language name="English" }}
{{ set_topic name="Countries:en" }}
{{ list_subtopics }}
<url>
<loc>http://wadr.org/{{ $gimme->language->code }}/?tpid={{ $gimme->topic->identifier }}&tpl=1442/</loc>
<changefreq>daily</changefreq>
<priority>0.4</priority>
</url>
{{ /list_subtopics }}
{{ set_language name="French" }}
{{ set_topic name="Countries:en" }}
{{ list_subtopics }}
<url>
<loc>http://wadr.org/{{ $gimme->language->code }}/?tpid={{ $gimme->topic->identifier }}&tpl=1442/</loc>
<changefreq>daily</changefreq>
<priority>0.4</priority>
</url>
{{ /list_subtopics }}
{{ set_current_issue }}
{{ set_language name="English" }}
{{ list_sections }}
<url>
<loc>http://wadr.org/{{ $gimme->language->code }}/{{ $gimme->issue->url_name }}/{{ $gimme->section->url_name }}/</loc>
<changefreq>weekly</changefreq>
<priority>0.3</priority>
</url>
{{ /list_sections }}
{{ set_language name="French" }}
{{ list_sections }}
<url>
<loc>http://wadr.org/{{ $gimme->language->code }}/{{ $gimme->issue->url_name }}/{{ $gimme->section->url_name }}/</loc>
<changefreq>weekly</changefreq>
<priority>0.3</priority>
</url>
{{ /list_sections }}
</urlset>
How to get it working
There are different ways to inform the search engines to crawl your site using the XML Sitemap we just created. However, this is out of the scope of this guide as it has nothing to do with Newscoop templating.
You can find detailed information on how to do it in these following links:
http://www.sitemaps.org/
https://www.google.com/support/webmasters/bin/answer.py?hl=en&answer=78808&ctx=cb
KML Documents for exporting map locations
KML is like a RSS-Feed for geo-location data. It is a XML specific notation for expressing geographic annotation and visualization within Maps and Earth browsers and applications.
One of the sample Template Packages on the Sourcefabric website is the "Ushahidi Cooker" which is dedicated to mapping content and generating KML-Feeds. You will come across KML-Feeds when you export from mapping services or - in the case of Ushahidi - when you want to import additional information into a map. Newscoop handles maps and using the following code can deliver valid KML feeds.
Goal / Task
To generate a simple KML file containing the list of locations for the current article.
Implementation
The structure of a basic KML file breaks down as follows:
- An XML header and a KML namespace declaration. You will see these two lines in the full version of the KML file at the end of this section.
- A Placemark object that contains the following elements: A name used as the label for the Placemark, a description that appears in the "balloon" attached to the Placemark, and a Point that specifies the position of the Placemark on the Earth's surface.
KML is much more complex than this and allow you to provide more information about the locations in your map and style those as much as you want, but that is KML-specific and out of the scope of this document. What we want to show you here is how you can use $gimme to pull the data and display the locations, which ultimately is what matters the most.
First you need to provide basic info about the article, in this case we use the article name and section name as the name for our KML document, and the custom field intro as the description.
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>{{ $gimme->article->name }} in {{ $gimme->section->name }}</name>
<description><![CDATA[{{ $gimme->article->intro }}]]></description>
Next, we provide some custom styling for the marker icons. For this we need to generate a unique id per location, so we use the article number plus the incremental index in the list. We also validate inside the list if the location is enabled or not.
{{ list_article_locations }}
{{ if $gimme->location->enabled }}
<Style id="style{{ $gimme->article->number }}-{{ $gimme->current_list->index }}">
<IconStyle>
<Icon>
<href>http://www.sourcefabric.org/geolocation/markers/marker-gold.png</href>
</Icon>
</IconStyle>
</Style>
{{ /if }}
{{ /list_article_locations }}
Now the most important section, the list of locations to be displayed on the map. We use list_article_locations and after making sure the location is enabled we build the Placemark block. For the Placemark name we are using here the location name together with the article name. Then we use styleUrl to reference the custome style defined in the block above.
The last sub-block is Point, which is where we actually specify the location positioning on the map. Notice the use of $gimme->location->longitude and $gimme->location->latitude, it could not be more intuitive :-). The value 0.000000 after latitude corresponds to altitude, which is not relevant for this example but must be there as per KML specifications.
{{ list_article_locations }}
{{ if $gimme->location->enabled }}
<Placemark>
<name>{{ $gimme->location->name }} @ {{ $gimme->article->name }}</name>
<description></description>
<styleUrl>#style{{ $gimme->article->number }}-{{ $gimme->current_list->index }}</styleUrl>
<Point>
<coordinates>{{ $gimme->location->longitude }},{{ $gimme->location->latitude }},0.000000</coordinates>
</Point>
</Placemark>
{{ /if }}
{{ /list_article_locations }}
This is how the full KML file should look like.
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
<Document>
<name>{{ $gimme->section->name }} in {{ $gimme->article->name }}</name>
<description><![CDATA[{{ $gimme->article->description }}]]></description>
{{ list_article_locations }}
{{ if $gimme->location->enabled }}
<Style id="style{{ $gimme->article->number }}-{{ $gimme->current_list->index }}">
<IconStyle>
<Icon>
<href>http://www.sourcefabric.org/geolocation/markers/marker-gold.png</href>
</Icon>
</IconStyle>
</Style>
{{ /if }}
{{ /list_article_locations }}
{{ list_article_locations }}
{{ if $gimme->location->enabled }}
<Placemark>
<name>{{ $gimme->location->name }} @ {{ $gimme->article->name }}</name>
<description></description>
<styleUrl>#style{{ $gimme->article->number }}-{{ $gimme->current_list->index }}</styleUrl>
<Point>
<coordinates>{{ $gimme->location->longitude }},{{ $gimme->location->latitude }},0.000000</coordinates>
</Point>
</Placemark>
{{ /if }}
{{ /list_article_locations }}
</Document>
</kml>
Put KML feeds into action
KML files are aim to be used on browsers and any other kind of application supporting this format, like for example Google Earth, Google Maps, Ushahidi Layers. So, once Newscoop generates this file for you, you just need to use it in any of these tools depending on your needs.
You can try this with the Template Package "Ushahidi Cooker" - where you will also find more detailed information in a blog post about the "Ushahidi Cooker":
http://www.sourcefabric.org/en/products/newscoop_templates/
Search engine optimisation (SEO)
Search Engine Optimisation is about improving the way your content is visible on the Internet. This is often understood as making your publication show up as highly as possible in search results. But limiting SEO to tricking search engines would be missing the point. Think about SEO as part of the service that you provide to your readers, not just a mechanism to jump the queue in search algorithms.
Imagine you have published an article about the impact the fall of the Berlin Wall has had on urban planning in that city today. It is named "Right in the middle" and because your web design uses big, trendy letters this short title just looks really good. Your Newscoop template is using the article name in the title tag in the header of the HTML document.
Imagine a potential reader who is typing "Berlin Wall" into their favourite search engine. Amongst the results, somewhere, your article shows up. The search engine will display the content of the title tag in the long list of results. What are the chances that the reader would click "Right in the middle" when looking for specific information about the Berlin Wall? The reader would probably be more likely to click "Fall of Berlin Wall heats up property speculation 20 years later".
This descriptive content increases the chances that readers will click on your article. At the same time, search engines value the content of the title tag highly. This little bit of extra work is likely to catapult your page upwards in the ranks of search results. Where the old title tag did not even mention the Berlin Wall, your new title tag does, and provides additional key words that will have an impact on your article's ranking and your publication's visibility.
This chapter will help you to make most of your publication's most valuable asset: your content. The following examples will cover a number of small modifications to your templates and other parts of your website which can deliver improved page rank and visibility. The examples will focus on SEO practices involving your publication or template structure, with a few journalistic guidelines.
Creating descriptive page titles
Add the field "seo_title" to your article type. This field can be displayed with $gimme->article->seo_title in the header region of your document.
<head>
<title>{{ $gimme->article->seo_title }}</title>
</head>
However, if the journalist forgot to fill in this field, the title tag of the page would be empty. So you should present a fallback option. A simple way of doing this, providing a reasonable solution for section pages and the home page at the same time, would be:
<head>
<title>{{ strip }}
{{ if $gimme->article->seo_title|trim !== "" }}
{{ $gimme->article->seo_title|escape:'html'|trim }} |
{{ else }}
{{ $gimme->article->name|escape:'html'|trim }} |
{{ /if }}
{{ $gimme->section->name }} in {{ $gimme->publication->name }}
{{ /strip }}
</title>
</head>
The functions trim and escape:'html' are used to make sure the content is clean and HTML. If the seo_title field is not filled in, the article name is displayed instead. If you are on a section page, the article values are not displayed if you link to the section using option=section.
Use the "description" meta tag
The description is a summary of what your article is about. The description meta tag goes into the header of your document. Many times, the text in this description will be given as an introduction to the page in a search result. The meta tag looks like this:
<meta name="description=" content="...">
Ideally, you should add a field to the Article Type that holds the description content. If this field is empty, you should use text from the main text of the article. A custom description will often be more inviting to a reader, in a list of search results, than the first lines of the main text.
Because the description will most probably come from a WYSIWYG textarea field, it is important to strip_tags. Opinions on the ideal length for meta descriptions vary. In the following example, we set the length to the first 150 characters of the article's main text, if no custom description has been provided.
<meta name="description=" content="{{ strip }}
{{ if $gimme->article->description_tag|strip_tags|trim !== "" }}
{{ $gimme->article->description_tag|strip_tags|escape:'html'|trim }}
{{ else }}
{{ $gimme->article->full_text|strip_tags|escape:'html'|trim|truncate:150 }}
{{ /if }}
{{ /strip }}" />
Human readable URLs reflecting the content
Information in the URL describing the content of the page is valued highly by search engines. You can control the URL for each issue and section, setting short names. So instead of the section number "/12/", this part of the URL might read "/culture/". You can find these options in the Newscoop administration interface. Select "Settings" in the list of issues and sections.
The article content can be reflected in three different human readable ways in the URL. You can select the option to use the article title, article keywords, or topics linked with the article. If your publication requires it, you can also create a combination of these options. The configuration for the URL display is done in the administration interface under "Configure Publication".
Here some examples of what these URLs could look like:
- by article title - http://yoursite.com/en/mar2011/posts/4/Healthy-options-for-your-sweet-tooth.htm (the article title is "Healthy options for your sweet tooth")
- by article keywords - http://yoursite.com/en/mar2011/posts/4/healthy-options.htm (the article has keywords "healthy" and "options")
- by article topics - http://yoursite.com/en/mar2011/posts/4/health-dine-wine-tomato-garlic-bread.htm (the article has topics "health", "dine", "wine", "tomato", "garlic" and "bread")
- by combining some - or all - of these options
Structure heading tags properly
Heading tags (h1, h2, h3, ...) reflect the hierarchy of the content on a page. This is how search engines read them, so you should design your page in the same way for humans. For example, when designing a page, don't use heading tags to control the layout.
HTML 5 is not very different from HTML 4 when it comes to SEO, so the rules are almost the same:
- Use only one H1 element on any page
- You can use any number of H2, H3, H4, H5, H6 elements on any page, as long they follow this hierarchy
- Use <ul> or <ol> tags for lists
- For menus, use the <ul> tag in HTML 4 and the <nav> tag in HTML 5
- Use <div> tags for styling blocks inside a template
- Use inline tags like <p> or <span> only for content
The logic for using only one H1 element is derived from the fact that search engines identify <h1> tags as page titles. Sometimes, search engines ignore <title> tags because they have been abused by webmasters.
HTML 5 also introduces new tags like <header>, <footer>, <nav>, <article>, <aside> and <section>. Search engines disqualify the use of multiple <header> tags if they are positioned one after another, but not if they are used as headers for each <article> tag. The same thing happens for <nav> and <footer> tags. A page can have multiple <article>, <aside> and <section> tags, each of these containing just one <header>, <footer> and <nav> tag.
XML Sitemap for your publication
Providing a sitemap in a specific XML format will make it easy for search engines to gain access to your content. The XML sitemap delivers all content that you wish to be indexed in a machine readable file.
Providing a sitemap also makes sure that search engines will find all of your content. A simple example: if you are using Flash to link from one page to another, that link is not being followed, because it is invisible to spiders (search engine robots). Such "invisible" pages will be listed in the sitemap, and help search engines to understand where these pages are.
In order to create a sitemap for your publication, see the chapter about XML, RSS, KML and sitemaps.
Unique URLs: the canonical tag
Canonical tags have one important purpose: tell search engines what the "clean" URL of the page is. The canonical tag sits in the header of your page. It was introduced in February 2009 by Google, Yahoo and Microsoft and it looks like this:
<link rel="canonical" href="http://www.example.com/" />
This is meant to put an end to the issues related to duplicate content. In short: duplicate content was used by some sites to increase their page rank. To prevent this kind of spamming, search engines rated domains with duplicate content lower. But any CMS will need different URLs for the same page, for example when passing on a parameter in the URL for browsing history, login, related items and others. The canonical tag now allows sites to make sure they are not ranked lower because they produce some duplicate content. Using the canonical tag will result in higher page ranks.
You need to adjust the following example to the template and folder names you are using for your publication.
{{ if $gimme->template->name == "package_name/article.tpl" }}
<link rel="canonical" href="{{ url options="article" }}" />
{{ /if }}
{{ if $gimme->template->name == "package_name/section.tpl" }}
<link rel="canonical" href="{{ url options="section" }}" />
{{ /if }}
{{ if $gimme->template->name == "package_name/index.tpl" }}
<link rel="canonical" href="http://{{ $gimme->publication->site }}" />
{{ /if }}
Additional checklist for your journalists and editors
The following list is not relevant for making templates. But while you are working on SEO, you might as well pass on some tips to your colleagues who are contributing content. At the end of the day, their input will guide the audience to your site.
Explain to the journalists and editors that their input into SEO could dramatically increase the readership of their articles on your publication's site. A little extra effort increases advertiser value, extends the shelf life of the article, and makes the journalist who wrote it much more famous.
When writing descriptions (for both articles and images)...
- Summarize the content accurately. Below are a few pointers that might help journalists and editors create a good description.
- Write unique descriptions. While this might appear impossible in large publications with thousands of articles and a large contributing staff, keeping this idea in your head will help avoid being boring and generic.
- Write for your audience, not for a search engine. Avoid writing a description tag that bears no resemblance to the content of the article. Don't write up a list of keywords, but form a sentence or two.
- Do not use the same description across your site. This could actually be worse than using no description tag at all. Imagine all search results in a list saying: "Simply the best magazine in the world".
When writing an article or image description, or providing a custom SEO title, include the following elements:
- Who or what is being shown? What is the name of the person, the animal, the building, the event? "Bird" is better than nothing, but "Eagle" would be better
- Where is it happening? "Eagle in the sky" is good, "Eagle in the sky above the Alps" is better
- Why is it happening? Why are you writing about it? Are you writing about an "Endangered Eagle in the sky above the Alps"
- When is this happening? Are we looking at an "Endangered Eagle in the sky above the Alps in Spring"?
You don't need to go overboard with building endless descriptions. Prioritize according to your story. The above questions are a good way to get to the essence quickly. In the end, you might settle for "Endangered Eagle flys in the Alps" - this captures the story better and would attract far more readers than "Bird" would ever do.
Make use of the image alt description
When adding an image, do not leave the alt tag empty. Firstly, screen reader programs for people with visual impairments rely on this information. Secondly, image searches on the Internet will categorise and rank images based on information in the alt tag. Readers finding your publication through image searches may be more common than you might think.
Link text should relate to the page it links to
When linking to a page, make sure the link text is related to the content of the page you link to. "You can download Newscoop here" is bad. "Download Newscoop for free" is better.
Newscoop and HTML5
The big challenge for web publishing today is the migration of sites to the HTML5 and CSS3 standards. Fortunately, Newscoop is HTML5 ready.
Other content management systems rely on HTML code provided by third-party widgets, modules or plugins. Changing the HTML output of these external modules often requires digging into their code. In Newscoop, because of the strict separation of business logic and presentation logic in the template engine, you have total control over HTML5 and CSS3 template output.
Below, we introduce a few examples of HTML5 / CSS3 in Newscoop templates to illustrate the ease of implementation of HTML5 features.
HTML metatags and header information
A typical HTML5 header in Newscoop would start like this:
<!DOCTYPE html>
<html lang="{{ $gimme->language->code }}">
<head>
<meta charset="utf-8" />
<meta name="description" content="{{ $siteinfo.description }}" />
<meta name="keywords" content="{{ if $gimme->article->keywords }}
{{ $gimme->article->keywords }},
{{ /if }}
{{ $siteinfo.keywords }}" />
<title>{{ $gimme->publication->name }}</title>
<link rel="stylesheet" href="screen.css" media="all" />
</head>
{{ $siteinfo.description }} is the global variable which holds the site description specified in the Newscoop administration interface.
{{ $gimme->article->keywords }} and {{ $siteinfo.keywords }} are two ways to include meta tag keywords. In Newscoop, an individual article can have its own keywords specified. If that's the case, the meta tag for keywords will be filled with these article specific keywords. Otherwise, only global site keywords will be used.
Finally, the site title is defined showing the name of the publication using {{$gimme->publication->name}}.
Multiple columns in HTML5
Multi-Column Layout defines new CSS properties for columns of text. Content can flow into multiple columns, with a gap between them. You can put the content in the appropriate places inside the HTML layout.
<header>
<hgroup>
<h1>{{ $gimme->article->name }}</h1>
</hgroup>
<p>By: {{ $gimme->article->author->name }}</p>
</header>
<div class="text1">
<p>{{ $gimme->article->lead }}</p>
</div>
<div class="text2" id="customCols">
<p>{{ $gimme->article->body }}</p>
</div>
Accompanied by some CSS3 styling, this piece of code is enough to divide text into columns, gaps, and even rules between columns.
.text2 {
-webkit-column-count: 2;
-moz-column-count: 2;
column-count: 2;
-webkit-column-gap: 20px;
-moz-column-gap: 20px;
column-gap: 20px;
-webkit-column-rule: 1px solid #999;
-moz-column-rule: 1px solid #999;
column-rule: 1px solid #999;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
}
Video and audio handling
Not only text content is HTML5 ready - Newscoop can handle media attachments in a HTML5 way. The following code shows how an audio file which has been attached to an article in the Newscoop administration interface can be handled in HTML5:
<audio controls>
<source src="{{ uri options="articleattachment" }}"
type="{{ $gimme->attachment->mime_type }}">
</audio>
The code above displays a player for the specified audio attachment. To help the browser to determine the MIME type of the audio file, the 'type' attribute is specified, although it can be omitted. The same technique is possible for video content:
<video controls width="520" height="330">
<source src="{{ uri options="articleattachment" }}"
type="{{ $gimme->attachment->mime_type }}">
</video>
In both cases, {{ uri options="articleattachment" }} is replaced with the audio or video file URL. With HTML5, you don't need to specify Flash players, because modern browsers have a built-in player for embedded multimedia content.
Troubleshooting templates
Newscoop's administration interface has a built-in preview option on the article edit page which also shows template parsing errors, if there are any. When you browse your publication in the preview window, you can see error messages for all parts of your publication.

At the bottom of the preview window you can see error messages from the template parser.
The second frame on this page displays any parsing errors, which can be very useful for debugging templates. It immediately narrows down possible errors to the specific main or included template. It also displays the line and type of error.
The error messages are not always precise. The point where the parser encounters an error may only be a reflection of a problem coming from further up in the template. If the message shown by the parse error frame is not useful to find the problem, you'll have to find an alternate way to locate it.
For example, in some situations, checking the source of the generated HTML page helps. It may be that the content you expect to be shown somewhere doesn't appear on the page, but it's in the HTML source. This obviously shows that the problem is not in Newscoop but somewhere in HTML or CSS. The opposite is also true; if the source contains all the <div> and <li> tags that it should but their content is empty, you can be sure that Newscoop isn't working like it should.
There are lots of very handy tools out there in browsers nowadays. You can use them to easily parse your HTML code and find an error. The one used in Firefox is Firebug. It is an extension to Firefox, all you need to do is to find it in the repository and install to the browser:

The usage is pretty easy - open, inspect element, find error:

But what is really good, is that you can debug your jQuery templates with it. Just adding a few lines of code to your JavaScript will provide Console feedback:
console.log ("Here are the date links:\r\n");
...
console.log (link + "\r\n");

There's almost the same tool in Chrome, which can be found in the menu under Tools -> Developer tools:

Another debugging strategy may be inserting temporary tags for printing the values of Newscoop variables.
The following code checks the values of variables in the registration process. It doesn't make any sense to use on a live site, but it may be useful for debugging purposes:
<h2>Add new subscription</h2>
{{* debug user add/edit/subscribe *}}
<h5>Edit_user_action:</h5>
<p>Edit user action defined: {{ if $gimme->edit_user_action->defined }}defined{{ else }}not defined{{/if}}</p>
<p>Edit user action error: {{ if $gimme->edit_user_action->is_error }}is_error, code: {{ $gimme->edit_user_action->error_code }}, message: {{ $gimme->edit_user_action->error_message }}{{ else }}not error{{/if}}</p>
<p>Edit user action ok: {{ if $gimme->edit_user_action->ok }}ok{{ else }}not ok{{/if}}</p>
<p>edit user action type: {{ $gimme->edit_user_action->type }}</p>
<h5>Edit_subscription_action:</h5>
<p>Subs action defined: {{ if $gimme->edit_subscription_action->defined }}defined{{ else }}not defined{{/if}}</p>
<p>Subs action error: {{ if $gimme->edit_subscription_action->is_error }}is_error, code: {{ $gimme->edit_subscription_action->error_code }}, message: {{ $gimme->edit_subscription_action->error_message }}{{ else }}not error{{/if}}</p>
<p>Subs action ok: {{ if $gimme->edit_subscription_action->ok }}ok{{ else }}not ok{{/if}}</p>
<p>Subs action {{ if $gimme->edit_subscription_action->is_trial }}is_trial{{ else }}not trial{{/if}}</p>
<p>subs action {{ if $gimme->edit_subscription_action->is_paid }}is_paid{{ else }}not paid{{/if}}</p>
{{* end debugging *}}
This would be the output:

Similarly to this, you can use this temporary outputs wherever you feel you need to check what's really happening. For example, inside a list to check how values of list index and list count change with every new cycle -
{{ list_articles }}
<div class="post wrap">
<p>Current list index: {{ $gimme->current_list->index }}, list count: {{ $gimme->current_list->count }}</p>
<h2 class="post-title"><a href="{{ uri options="article" }}" rel="bookmark" title="{{ $gimme->article->name }}">{{ if ! $gimme->article->content_accessible }}* {{ /if }}{{ $gimme->article->name }}</a></h2>
</div>
{{ /list_articles }}
Here we put a temporary <p> tag with values of index and count above every title, and the result would be like this screenshot:

Or, you may want to check the values of parameters forwarded to a page. You can do this at the template's very beginning:
<p>Language: {{ $gimme->language->name }}<br />
Issue: {{ $gimme->issue->name }} <br />
Section: {{ $gimme->section->name }}<br />
Article no: {{ $gimme->article->number }}<br />
Topic active? {{ if $gimme->topic->defined }}yes{{ else }}no{{ /if }}
</p>
{{ include file="set_thejournal/_tpl/top.tpl" }}
The output displays the values of the parameters, so you can check if everything is OK:

Most common errors / problems
- Missing a closing element for {{ if }} statements - this especially happens when several 'if' clauses are nested. You can simplify your expression by using {{ elseif }}; that will reduce the need for closing 'if's
- Missing list closing element - this also happens more often when using lists inside lists
- Wrong syntax inside an 'article list' constraints option. Because there are a lot of possible options, always consult the template reference at the end of this book for options and their correct formatting
- Syntax errors in general - again, the safest way to avoid errors is to always consult the template reference
- Context problems - these are harder to discover because they don't produce parse errors in the preview window. To discover context-related values problems, try inserting temporary tags to output the values of variables. Do it at the beginning of the template, then do it again after an action was performed. This way, you can see what really happens with those variables.
Where to go for more help
There are a few places you can turn for troubleshooting assistance on your templates. The first place to look is the Newscoop support forum, which you can find at http://forum.sourcefabric.org
Sourcefabric also offers paid support. As the maintainer of Newscoop (and its largest code contributor), Sourcefabric can provide a broad and deep body of knowledge to our customers. For example, we can help troubleshoot your templates or installation, or we can create custom templates for you. You can find more details about Sourcefabric's services on the website: http://services.sourcefabric.org
Using jQuery and PHP in templates
The Newscoop template engine comes with a set of custom functions which are used in examples in this Cookbook. A full template reference can be found at the end of the book. Everything involving the $gimme object is Newscoop related.
You can also find a number of examples in the advanced section, which use jQuery and PHP. This chapter explains some of the background information you need to know to make your work with advanced functions easier to understand. It will also allow you to venture into making your own. If you do, by all means, tell us about it! You can mail us at contact@sourcefabric.org and share your ideas with the community in our forums at http://forums.sourcefabric.org
Using jQuery in your templates
jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. If you haven't used jQuery yet, you could start getting familiar with it by reading the tutorial on the jQuery site: http://docs.jquery.com/Tutorials:How_jQuery_Works
To use jQuery with Newscoop, you just need to add libraries in your _html-header.tpl file, and that's it! It will be much easier if you follow our recommendations and put all your own jQuery code in a separate file (/templates/set_name/_js/functions.js).
So the first thing to do will be to include all required jQuery libraries in the html header:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="Content-Language" content="en" />
...
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js"></script>
<link type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/themes/base/jquery-ui.css" rel="stylesheet" />
<script src="http://{{ $gimme->publication->site }}/templates/set_name/_js/functions.js"></script>
...
</head>
The first <script> line is the jQuery library itself. It is required for all functions to work.
The next two lines are for jQuery UI, which provides abstractions for low-level interaction and animation, advanced effects and high-level, themeable widgets, built on top of the jQuery JavaScript Library.
As you can see in the above example, we included all libraries from Google's CDN (see http://code.google.com/apis/libraries/devguide.html#jqueryUI). You also can download jQuery (see http://docs.jquery.com/Downloading_jQuery) and copy it to the right place on your server:
<!-- Grab Google CDNs jQuery. fall back to local if necessary -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script>!window.jQuery && document.write(unescape('%3Cscript src="http://{{ $gimme->publication->site }}/templates/set_thejournal/_js/jquery-1.5.2.min.js"%3E%3C/script%3E'))</script>
...
<script src="http://{{ $gimme->publication->site }}/templates/set_name/_js/functions.js"></script>
Your part of the magic is created inside the functions.js file:
$(document).ready(function(){
...
});
If you need to place a piece of jQuery inside some particular template, just use the <script> tag:
<script type="text/javascript">$(document).ready(function(){
...
});</script>
jQuery, like other JavaScript frameworks, is a very handy tool to make your designs work, so that you can concentrate on other things. Here is, just for example, a small piece of code to make an "Increase/Decrease Font Size" control. First, the JavaScript, then the template code:
functions.js
var articleBox = $(".block-article");
var originalFontSize = $(articleBox).css('font-size');
// Increase Font Size
$("a[href=#zoomin]").click(function(){
var currentFontSize = $(articleBox).css('font-size');
var currentFontSizeNum = parseFloat(currentFontSize, 10);
var newFontSize = currentFontSizeNum*1.1;
$(articleBox).css('font-size', newFontSize);
return false;
});
// Decrease Font Size
$("a[href=#zoomout]").click(function(){
var currentFontSize = $(articleBox).css('font-size');
var currentFontSizeNum = parseFloat(currentFontSize, 10);
var newFontSize = currentFontSizeNum*0.9;
$(articleBox).css('font-size', newFontSize);
return false;
});
article-cont.tpl
<div class="block-fonts-control">
<a href="#zoomin">Increase</a> / <a href="#zoomout">Decrease</a> font
</div>
...
<div class="block-article">
{{$gimme->article->intro}}
{{$gimme->article->full_text}}
</div>
Using PHP in your templates
The {{ php }} tag allows PHP code to be embedded directly into the template. This is for advanced users only, not normally needed and not recommended. The following information was taken from http://www.smarty.net
Example PHP code within {{ php }} tags:
{{ php }}
// including a php script directly from the template.
include('/path/to/display_weather.php');
{{ /php }}
Passing on variables between $gimme and PHP
When using PHP, you might want to work with $gimme values inside PHP, as well as pass on PHP variables to the template. In order to do this, you need to assign the variables first, then you can access them inside PHP. Important: use backticks ` in the assign function. Here's a little example:
Assigning a variable in the template to use with PHP
{{ assign var="profile_email" value=`$gimme->comment->reader_email` }}
{{ php }}
$profile_email = $this->get_template_vars('profile_email');
print $profile_email;
{{ /php }}
Note: there seems to be no way to pass on variables from an included file into the parent. We could not figure it out. If you can, please add your code here!
Assign a variable in PHP to use in the template
{{* a {{php}} block that assigns the variable $varX *}}
{{php}}
$this->assign('varX','Toffee');
{{/php}}
{{* output the variable in the template *}}
<strong>{{$varX}}</strong> is my favourite ice cream :-)
Pulldown menu with Superfish using jQuery
Download and documentation: http://users.tpg.com.au/j_birch/plugins/superfish/
Pulldown menus with sub-menus opening on mouse-over are very popular. We recommend using Superfish for elegance, flexibility and SEO compatible design. We show you how to add this to your Newscoop publication in five simple steps.
Superfish is a jQuery menu plugin developed by Joel Birch which adds neat usability to an existing CSS drop-down menu (so it degrades gracefully without JavaScript). You can see it in action at www.sourcefabric.org. Go to the Superfish website for more details, examples and documentation. Download the zip-file before we start.
In our example, we use the Template Package "Ushahidi Cooker". The Superfish navigation will be added beneath the header and above the breadcrumbs. You can download the "Ushahidi Cooker" at www.sourcefabric.org under Products > Newscoop > Templates. Without the pulldown menu, the design looks like this:

The "Ushahidi Cooker" is a directory of maps. We will now improve usability with a pulldown menu.
After you downloaded the Superfish zip-file, fire up your text editor and open the example.html file.
1. Adding JavaScript and CSS links to header
When you open the file example.html in the Superfish zip, you will see these lines in the header of the document, linking in the CSS files, the JavaScript files and initialise the jQuery plugin:
<link rel="stylesheet" type="text/css" href="css/superfish.css" media="screen">
<script type="text/javascript" src="js/jquery-1.2.6.min.js"></script>
<script type="text/javascript" src="js/hoverIntent.js"></script>
<script type="text/javascript" src="js/superfish.js"></script>
<script type="text/javascript">
// initialise plugins
jQuery(function(){
jQuery('ul.sf-menu').superfish();
});
</script>
Following the recommended folder structure described in an earlier chaper, I change these to:
<link rel="stylesheet" type="text/css" href="/templates/set_ushahidicooker/_css/superfish/css/superfish.css" media="screen">
<script type="text/javascript" src="/templates/set_ushahidicooker/_js/jquery-1.2.6.min.js"></script>
<script type="text/javascript" src="/templates/set_ushahidicooker/_js/hoverIntent.js"></script>
<script type="text/javascript" src="/templates/set_ushahidicooker/_js/superfish.js"></script>
As you can see in this example, Superfish comes with a jQuery file (jquery-1.2.6.min.js). Note: there is a new folder now inside _css by the name of superfish with a subfolder css. Superfish has a css and an images folder, they both go into the new superfish folder. You'll make your life easier if you keep files in separate folders.
These changes need to be added in the sub-template for the header. For the "Ushahidi Cooker" this is:
set_ushahidicooker/_tpl/header.tpl
Because this file already calls jQuery (see below), I leave this line out. I add the lines just beneath the linked jquery.min.js and add the initialising JavaScript before the header closes.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<!-- Superfish files -->
<link rel="stylesheet" type="text/css" href="/templates/set_ushahidicooker/_css/superfish/css/superfish.css" media="screen">
<script type="text/javascript" src="/templates/set_ushahidicooker/_js/hoverIntent.js"></script>
<script type="text/javascript" src="/templates/set_ushahidicooker/_js/superfish.js"></script>
<script type="text/javascript">
// initialise plugins
jQuery(function(){
jQuery('ul.sf-menu').superfish();
});
</script>
</head>
2. Copying files to correct folders
Create the folder superfish inside _css and move the css and images folder into is. These are the files and folders you should now have:
set_ushahidicooker/_css/superfish/css/
- superfish.css
- superfish-navbar.css
- superfish-vertical.css
set_ushahidicooker/_css/superfish/images/
- arrows-ffffff.png
- shadow.png
Also move the JavaScript files into the _js folder.
3. Create the sub-template to build the navigation
The file you create is called sf-menu.tpl and is saved inside set_ushahidicooker/_tpl/
4. Generate the menu HTML with Newscoop
In our case, we are listing the sections as the visible menu items running horizontally, and the articles in each section are in the pulldown item. The code inside sf-menu.tpl looks like this:
<ul class="sf-menu">
{{ list_sections }}
<li>
<a href="{{ uri }}">{{ $gimme->section->name }}</a>
{{ list_articles }}
{{ if $gimme->current_list->at_beginning }}
<ul>
{{ /if }}
<li>
<a href="{{ uri }}">{{ $gimme->article->name }}</a>
</li>
{{ if $gimme->current_list->at_end }}
</ul>
{{ /if }}
{{ /list_articles }}
</li>
{{ /list_sections }}
</ul>
Again, the same list. Now we focus on the Newscoop action that is taking place:
List all sections and open a list item:
{{ list_sections }}
<li>
Create a link to the section, displaying the section name:
<a href="{{ uri }}">{{ $gimme->section->name }}</a>
List all articles. These will be the articles inside the current section from the list_section command. In other words: only the ones in the section we just printed:
{{ list_articles }}
Now we open another unordered list (ul). But only when we start with the listing of articles:
{{ if $gimme->current_list->at_beginning }}
<ul>
{{ /if }}
Now the articles are listed as list items:
<li>
<a href="{{ uri }}">{{ $gimme->article->name }}</a>
</li>
Then we close the unordered list, once we reached the last item and finish list_articles:
{{ if $gimme->current_list->at_end }}
</ul>
{{ /if }}
{{ /list_articles }}
Now we have left the sub-loop of articles, we are back again with the section. We close the list item and then the section:
</li>
{{ /list_sections }}
Note: if a section is empty, the sub-list will not be built by Newscoop.
5. Include sf-menu.tpl in the page
You can call this page now anywhere you want with:
{{ include file="set_ushahidicooker/_tpl/sf-menu.tpl" }}
The screenshot show the Superfish pulldown at the end of the template _tpl/title.tpl. Open the file title.tpl and add this line at the end. Then it should end like this:
...
<h1>{{ $gimme->publication->name }}</h1>
<span>Location and Map Directory with Geographic Data Feed (KML)</span>
</div>
{{ include file="set_ushahidicooker/_tpl/sf-menu.tpl" }}
Done. Now you could adjust the CSS files if you like. If you don't, the Superfish will look like this:

The "Ushahidi Cooker" now has a pulldown menu, showing the city maps for each section.
Tabs with jQuery
jQuery tabs are an efficient way to show content like Most Recent Articles or Most Recent Comments in one place. You can read a lot about the jQuery UI Tabs widget at their site, http://jqueryui.com/demos/tabs/
Here is an example jQuery tab (see the chapters on Most Recent Articles or Most Recent Comments to see how those are generated):

Here's the jQuery part:
$(function(){
$('#container-1 ul').tabs();
});
The rest is done inside Newscoop templates.
Here's the logic:
<div id="container-1">
<ul>
<li><a href="#fragment-1">Title 1</a></li> {{* first tab title *}}
<li><a href="#fragment-2">Title 2</a></li> {{* second tab title *}}
</ul>
<div id="fragment-1">
{{* first tab content *}}
</div>
<div id="fragment-2">
{{* second tab content *}}
</div>
</div>
And here's the actual example:
<div id="container-1">
<ul>
<li><a href="#fragment-1"><span> </span></a></li> {{* first tab title *}}
<li><a href="#fragment-2"><span> </span></a></li> {{* second tab title *}}
</ul>
<div id="fragment-1"> {{* first tab content *}}
{{set_section number="1"}}
{{list_articles length="12" constraints="onfrontpage is off onsection is on" ignore_issue="true"}}
<h4><a href="{{uri options="article"}}">{{ $campsite->article->name}}</a>{{if $campsite->article->has_video}}<i class="ico video"></i>{{/if}}{{if $campsite->article->has_photo}}<i class="ico photo"></i>{{/if}}{{if $campsite->article->has_audio}}<i class="ico audio"></i>{{/if}}</h4>
<p class="container-date">{{$campsite->article->publish_date|camp_date_format:"%d %M %Y."}}</p>
<p>{{$campsite->article->Intro_front}}{{if $campsite->article->comment_count>0}}<a href="{{uri options="article"}}#comments" class="comments_counter">{{$campsite->article->comment_count}}</a>{{/if}}</p>
{{/list_articles}}
{{set_default_section}}
</div>
<div id="fragment-2"> {{* second tab content *}}
{{local}}
{{unset_issue}}
{{list_issues length="2" order="bynumber desc"}}
{{list_sections constraints="number greater 9 number smaller 70"}}
{{list_articles length="4" constraints="topic is \ :ru" order="bynumber desc"}}
<h4><a href="{{uri options="article"}}">{{$campsite->article->name}}</a>{{if $campsite->article->has_video}}<i class="ico video"></i>{{/if}}{{if $campsite->article->has_photo}}<i class="ico photo"></i>{{/if}}{{if $campsite->article->has_audio}}<i class="ico audio"></i>{{/if}}</h4>
<p class="container-date">{{$campsite->article->publish_date|camp_date_format:"%d %M %Y."}}</p>
<p>{{$campsite->article->intro}}{{if $campsite->article->comment_count>0}}<a href="{{uri options="article"}}#comments" class="comments_counter">{{$campsite->article->comment_count}}</a>{{/if}}</p>
{{/list_articles}}
{{/list_sections}}
{{/list_issues}}
{{/local}}
</div>
</div>
Ticker with jQuery
Do you want a BBC-style ticker like the one on http://wadr.org/ driven by Newscoop? Of course you do!

Everything important is in this code:
<div id="ticker-wrapper" class="no-js">
<ul id="js-news" class="js-hidden">
{{ list_articles length="5" order="bypublishdate desc" constraints="section is 5" }}
<li class="news-item">
<a href="{{ uri options="article" }}" >{{ $gimme->article->name }}</a>
</li>
{{ /list_articles }}
</ul>
</div>
This code selects the last five published articles from section number 5 and creates an unordered list of article names, also linking them to the full article page.
Add some jQuery magic:
$(document).ready(function(){
$('#js-news').ticker({
titleText: 'WADR Highlights'
});
});
The engine behind this is the jQuery News Ticker (http://www.jquerynewsticker.com/), so be sure to have all necessary includes in their place, in _html-head.tpl
<!-- Grab Google CDN's jQuery. fall back to local if necessary -->
<script src="/ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.js"></script>
<script>!window.jQuery && document.write(unescape('%3Cscript src="http://{{ $gimme->publication->site }}/templates/js/jquery-1.5.1.min.js"%3E%3C/script%3E'))</script>
<script type="text/javascript" src="http://{{ $gimme->publication->site }}/templates/js/jquery-ui-1.8.10.custom.min.js"></script>
<script type="text/javascript" src="http://{{ $gimme->publication->site }}/templates/js/jquery.ticker.js"></script>
and also the css file that belongs to it:
<link type="text/css" rel="stylesheet" href="http://{{ $gimme->publication->site }}/templates/css/highlights.css" />
This is of course just one of hundreds of different solutions that you can find on the Internet, so feel free (and encouraged) to explore and play with other toys!
Image galleries with jQuery
This example is using a specific gallery solution working with jQuery. Once you understand the logic behind the code, you can use any gallery you want. Just download the package and add Newscoop template code where needed. This chapter will show you how it's done.
Our gallery example will display a number of images attached to an article in your publication. Again, you can modify the logic easily and, for example, call in one image from a list of articles instead.
Start with attaching a number of Images to an Article, which you want to show to the world. In this case we think of the Article as a container for your images. All you need to do is list_article_images and decide, how you want them to show up (Lightbox, Slimbox, whatever) - and that's it!
An important thing before you start is to decide what size (in pixels) your images and thumbnails will have. You will need these numbers set to make all images and thumbnails appear unified.
It's up to you to decide which tool you will use to make your images shine. In this example we will use Fancybox (http://fancybox.net/) and the jQuery plugin. But you are not limited in any way, and can choose any gallery you like - Newscoop will just provide images for your favourite plugin.
Simple Article Image Gallery
This type of image gallery could be used to show additional images, which are part of an Article, but do not fit in the main text.
Here's a real life example (http://ganc-chas.by/by/page/history/323) of how it's done (you can copy & paste it to your page, and edit it later):
{{list_article_images columns="4"}}
{{if $gimme->current_list->count > 1}}
{{if $gimme->current_list->at_beginning}}
<div class="image-gallery-title">Article Images</div>
<div class="image-gallery-container">
{{/if}}
{{if $gimme->image->article_index > 2}}
<a href="{{uri options="image"}}" rel="gallery" class="gallery_thumbnail" title="{{$gimme->image->description|escape}}">
<img src="{{uri options="image"}}&ImageRatio=20" alt="{{$gimme->image->description|escape}}" width="100" height="100" />
</a>
{{/if}}
{{if $gimme->current_list->at_end}}
</div>
{{/if}}
{{/if}}
{{/list_article_images}}
<script type="text/javascript">
$(document).ready(function(){
$("a.gallery_thumbnail").fancybox({
type: 'image',
titlePosition: 'inside',
transitionIn: 'none',
transitionOut: 'none',
centerOnScroll: 'true'
});
$("a.gallery_thumbnail").live("mouseenter",function(){$(this).animate({opacity:1},200);});
$("a.gallery_thumbnail").live("mouseleave",function(){$(this).animate({opacity:0.8},200);});
});
</script>
Let's now take a look at parts of code:
{{list_article_images columns="4"}}
{{if $gimme->current_list->count > 1}}
{{if $gimme->current_list->at_beginning}}
<div class="image-gallery-title">Article Images</div>
<div class="image-gallery-container">
{{/if}}
We want to have article images placed in 4 columns. First, we check if the Article has images attached. Then we provide a header for the gallery and container <div> element.
{{if $gimme->image->article_index > 2}}
<a href="{{uri options="image"}}" rel="gallery" class="gallery_thumbnail" title="{{$gimme->image->description|escape}}">
<img src="{{uri options="image"}}&ImageRatio=20" alt="{{$gimme->image->description|escape}}" width="100" height="100" />
</a>
{{/if}}
In this example we will list only images with numbers 3 and higher - this is done to separate gallery images from the main article images. You can decide to have images for the gallery numbered 100 and above - it's up to you.
We need to provide Fancybox with a link to an original image (full size), and also a thumbnail image (&ImageRatio) to show to the user. We also supply class & rel names for Fancybox to define a group of image objects that should be used for the gallery. Other Image properties could also be included, like description in the above example. Finally, we close the list:
{{if $gimme->current_list->at_end}}
</div>
{{/if}}
{{/if}}
{{/list_article_images}}
That's pretty much it for Newscoop. Now let's go down to the jQuery part:
<script type="text/javascript">
$(document).ready(function(){
$("a.gallery_thumbnail").fancybox({
type: 'image',
titlePosition: 'inside',
transitionIn: 'none',
transitionOut: 'none',
centerOnScroll: 'true'
});
$("a.gallery_thumbnail").live("mouseenter",function(){$(this).animate({opacity:1},200);});
$("a.gallery_thumbnail").live("mouseleave",function(){$(this).animate({opacity:0.8},200);});
});
</script>
This example assumes that you already read the Fancybox HowTo (http://fancybox.net/howto) and included all necessary jquery and fancybox libraries. The rest is pretty simple - you just need to fire up the plugin, using jquery selector (a.gallery_thumbnail) and provide it with the different options you want to have.
Here we also added a few lines of code to make our thumbnails look even fancier. So the final result should look like this:

And when you click on an image, you have a bigger one with a description and arrows to navigate through the others:

Advanced Image Galleries
You can also make an advanced presentation of Images, using a few more lines of code and plugins. The approach should be the same:
- Provide a list of links to full-size images (<a href="{{ uri options="image" }}"...)
- Provide a list of thumbnail images (<img src="{{ uri options="image" }}&ImageWidth=100" width="100" ... />)
For example, you can combine thumbnails + average size images + full-size images:

Calendars with jQuery
Usually you will want to use a calendar to show a visual presentation of published articles in the archive. In Newscoop, we added a special function to provide a Calendar control, which will highlight all days that have articles (or issues) published. When a user clicks on a date, a link action fires up to open a defined URL with an additional parameter date. It could be used to address an archive template and sort articles according to the provided date.
The calendar function is based on the jQueryUI widget Datepicker (http://jqueryui.com/demos/datepicker/). So the first thing to do will be to include all required jQuery libraries:
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/jquery-ui.min.js"></script>
<link type="text/css" href="http://ajax.googleapis.com/ajax/dlibs/jqueryui/1.8.11/themes/base/jquery-ui.css" rel="stylesheet" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.11/i18n/jquery.ui.datepicker-ru.min.js"></script>
As you can see in this example, we included all libraries from Google's CDN. You can use your own custom libraries, downloaded from the jQuery site. The last one is only required if you want to show a calendar in a language other than English. By default, the Calendar will be presented in the current site language. A function detects what language the website content is, and therefore what language the Calendar will be.
The following construction will create a Calendar control::
{{ calendar container="cal1Container" url="/?tpl=archive.tpl" style="my_calendar" min_date="2009-03-01" max_date="2009-03-31" clickable_dates="articles" }}
- container: This attribute is mandatory. It allows you to define an unique HTML identifier (id) for the calendar container.
- url: This attribute is mandatory. Define the action link of the Calendar once the user clicks a date.
- clickable_dates: This attribute is optional. There are two possible values for this attribute: "articles" and "issues", with the latter being the default. If you pass "articles", the Calendar will show as highlighted all dates where at least one article is published (publish_date). If you pass "issues" or nothing at all, thr Calendar will show as highlighted all dates when an issue has been published.
- style: This attribute is optional. Sets a custom CSS class for the calendar container. If it is not defined, the default class "calendar" will be used.
- min_date: This attribute is optional. It sets the Calendar's minimum selectable date. The date format should be "yyyy-mm-dd".
- max_date: This attribute is optional. It sets the Calendar's maximum selectable date. The date format should be "yyyy-mm-dd".
The resulting output will be like this (remember, we included the Russian language in the example above):

You can then style the Calendar the way you want it to be (remember, we used the class name "my_calendar"). Also, the look is based on the UI theme that you use, so you can adjust the theme according to your needs (we used the base theme in this example).
The source code of the Calendar output is the following:
<!-- Begin Calendar widget //-->
<div class="my_calendar">
<div id="cal1Container"></div>
<script type="text/javascript">
$(function() {
var issueDates = new Array();
var articleDates = new Array("2009-03-27","2009-03-28");
$.datepicker.setDefaults($.datepicker.regional["en"]);
$("#cal1Container").datepicker({
dateFormat: "yy-mm-dd",
minDate: "2009-03-01",
maxDate: "2009-03-31",
beforeShowDay: function(displayedDate) {
var dDate = "";
var dDay = displayedDate.getDate();
var dMonth = displayedDate.getMonth() + 1;
if (dDay < 10) dDay = "0" + dDay;
if (dMonth < 10) dMonth = "0" + dMonth;
dDate = displayedDate.getFullYear() + "-" + dMonth + "-" + dDay;
for (i = 0; i < issueDates.length; i++) {
if (dDate == issueDates[i]) {
return [false,"ui-state-active",""];
}
}
for (i = 0; i < articleDates.length; i++) {
if (dDate == articleDates[i]) {
return [true, "ui-state-active", ""];
}
}
return [false, ""]; // disable all other days
},onSelect: function(selectedDate) {
var contentDates = new Array("2009-03-27","2009-03-28");
for (var i in contentDates) {
if (selectedDate == contentDates[i]) {
var linkTo = "/?tpl=archive.tpl&date=" + selectedDate;
window.location = linkTo;
}
}
}});
});
</script>
</div>
<!--End Calendar widget //-->
Extending functionality
You can see that all the hard work of creating the visual presentation is given to jQuery UI Datepicker. All we need to do is provide dates in correct format. You can take this approach and provide any data you want. Just note that it should be readable by the plugin.
Of course, it is much more easier to use a Calendar function supplied in Newscoop, but sometimes you will need more. Here is how we made a Calendar of PDF versions in the archive. First we need to provide variables in JSON format. For that purpose we have made a small template (_json-pdf-items.tpl):
{
"pdf":{
{{list_articles constraints="type is pdf issue greater 1 section is 300 publish_date greater 1900-01-01"}}
"{{$gimme->article->publish_date|date_format:"%Y-%m-%d"}}":{
"link":
"{{list_article_attachments length="1"}}http://{{$gimme->publication->site}}{{uri options="articleAttachment"}}{{/list_article_attachments}}",
"title":" {{$gimme->issue->name}}({{$gimme->issue->number}}) {{$gimme->issue->publish_date|camp_date_format:"%d.%m.%Y"}} - pdf"}{{if !$gimme->current_list->at_end}},{{/if}}{{/list_articles}}
}
}
Next, we need to read variables from that template and save them for jQuery. Actually, we use a cron-job to grab the data and put it into the .json file. But it could also be done directly, addressing the template:
/* Datepickers */
var pdf_date;
$.ajax({async:false,dataType:'json',url:'/?tpl=_json-pdf-items.tpl',success: function(d){pdf_date=d;}});
The contents of the JSON-formatted file will be something like this:
{
"pdf":{
"2010-06-29":{"link":"http://ganc-chas.by/attachment/000000026.pdf","title":" 25(391) 17.06.2010 - pdf"},
"2010-06-04":{"link":"http://ganc-chas.by/attachment/000000025.pdf","title":" 23(389) 04.06.2010 - pdf"}
}
}
And here's a jQuery part of the stuff (we use a slightly modified version which could be found at http://ganc-chas.by/templates/js/functions.js):
// PDF Archive Calendar
$("#PDFArchive").datepicker({
changeMonth: true,
changeYear: true,
beforeShowDay: function(d){
var date = $.datepicker.formatDate("yy-mm-dd",d);
show=false;;caption="";link="#";
if (pdf_date.pdf[date]){
show=true;
style="ui-state-attention active";
caption=pdf_date.pdf[date].title;
link=pdf_date.pdf[date].link;
}
return [show,style,caption,link];
}
});
The final output will be a small nifty Calendar containing all your PDF versions (you can see it in action at http://ganc-chas.by/by/page/archive/):

Calendar interface using jQuery.
Using polls with AJAX
In this chapter you will find an advanced way to use the polls provided with Newscoop. Using AJAX and jQuery, the user interaction becomes smooth, and no visible page reload is required to add a vote and display the poll results. Any modern jQuery version does the trick, and needs to be called in the header of the page. You can find the documentation of the original templates on the Sourcefabric website, in the wiki.
First, we will need to list the current Poll, in our case, the latest one. When loading the page, no poll action has happened yet (meaning: voting) so we display the poll. And most importantly, a DIV container should be defined, which will be used to send and receive data via AJAX.
{{list_polls length="1" order="bynumber desc"}}
{{if !$gimme->poll_action->defined}}
<p class="title">Poll of the day</p>
<p class="poll-question">{{$gimme->poll->question}}</p>
<div id="poll" class="poll">
{{/if}}
...
Next we need to check if the poll is still open to votes, and if no data is sent yet. We do not use a submit_button, as the data will be sent by an AJAX call.
{{if $gimme->poll->is_votable && !$gimme->poll_action->defined}}
{{poll_form template="poll.tpl" submit_button=false}}
{{list_poll_answers order="byOrder asc"}}
{{pollanswer_edit}}{{$gimme->pollanswer->answer}}<br />
{{/list_poll_answers}}
<input type="submit" id="submit_poll" class="button" value="I think so!" />
{{/poll_form}}
...
The same template is used to provide output, if the data was sent by the user.
{{else}}
<p>Voted: {{$gimme->poll->votes}}</p>
{{list_poll_answers order="byOrder asc"}}
<div class="answer">{{$gimme->pollanswer->percentage|string_format:"%d"}}%: {{ $gimme->pollanswer->answer }}
<div style="width:{{$gimme->pollanswer->percentage|string_format:"%d"}}%;background:#5d4040;"> </div>
</div>
{{/list_poll_answers}}
{{/if}}
And finally: the closing tag.
...
{{if !$gimme->poll_action->defined}}
</div>
{{/if}}
{{/list_polls}}
The jQuery part of the code is pretty small. We use $.post to parse the form data, send it via AJAX to the server, and place the resulting output where it should be (<div id="poll">).
$(document).ready(function(){
$('#submit_poll').click(function(){
$.post(
$('form[name=poll]').attr("action"),
$('form[name=poll]').serialize(),
function(data){$('#poll').html(data);
});
return false;
});
});
Below you can see the entire template poll.tpl, which you can include in your page.
{{list_polls length="1" order="bynumber desc"}}
{{if !$gimme->poll_action->defined}}
<p class="title">Poll of the day</p>
<p class="poll-question">{{$gimme->poll->question}}</p>
<div id="poll" class="poll">
{{/if}}
{{if $gimme->poll->is_votable && !$gimme->poll_action->defined}}
{{poll_form template="poll.tpl" submit_button=false}}
{{list_poll_answers order="byOrder asc"}}
{{pollanswer_edit}}{{$gimme->pollanswer->answer}}<br />
{{/list_poll_answers}}
<input type="submit" id="submit_poll" class="button" value="I think so!" />
{{/poll_form}}
{{else}}
<p>Voted: {{$gimme->poll->votes}}</p>
{{list_poll_answers order="byOrder asc"}}
<div class="answer">{{$gimme->pollanswer->percentage|string_format:"%d"}}%: {{ $gimme->pollanswer->answer }}
<div style="width:{{$gimme->pollanswer->percentage|string_format:"%d"}}%;background:#5d4040;"> </div>
</div>
{{/list_poll_answers}}
{{/if}}
{{if !$gimme->poll_action->defined}}
</div>
{{/if}}
{{/list_polls}}
<script type="text/javascript">
$(document).ready(function(){
$('#submit_poll').click(function(){
$.post(
$('form[name=poll]').attr("action"),
$('form[name=poll]').serialize(),
function(data){$('#poll').html(data);
});
return false;
});
});
</script>