9. Getting the Ingredients Together
Includes contains reusable template elements.
<widget type="file"><arg id="path">/_ingredients/templates/includes/head.html</arg></widget>
14. - Set up group template permissions.
- Save group.
- Set default page editing templates.
- Used when anyone in that group
creates a new page.
Default Templates
17. Looking Out for Opportunities (or Potential Headaches)
- Do I need a new template?
- Would it be best to create a new theme?
- Themes keep styles, JavaScript and templates cleanly compartmentalized.
- Protect the rest of your site from experimental work.
- LESS is automatically compiled for you and error logs are generated.
- Simply add the theme variable to the page. You can place it in an editable area.
<xphp var="theme">timeline</xphp>
19. Keeping Widgets in Check Widgets → All Widgets
The widget manager shows us which widgets are used where. Only works for saved widgets.
20. Keeping Widgets in Check
- Use widget names that can easily be understood at a glance.
- The name can be changed any time. The widget ID is the only part used by LiveWhale.
- Add a thoughtful widget description:
- a summary of what it does
- why it is unique
- an example of where the widget is used
21. Keeping Widgets in Check
- Duplicate an existing widget when you’d like to alter the appearance for a new use-case.
- Or, carefully add the widget to the page and change one or two arguments with the source
code button (mother widget method).
22. - Save widgets in the widget manager.
- Keeps everything neat and organized…
- Which helps us to fix widgets
- Makes it easy to duplicate widgets
Avoid Stray Widgets!
23. - Only show html if a variable exists (you can nest conditionals two levels deep):
{<div class="news-date"> {date} </div><div class="news-summary"> |summary| </div>}
- Show another widget variable if a variable is empty:
{!summary:location_title}
- Remove markup from a variable by appending _clean (useful for removing links):
{title_clean}
Widget Formatting Options
24. - For regular content, from any group.
- Used when anyone creates a new widget.
- Useful for global widgets.
- Use the class .lw_widget_news
to style the widget (applies to
all news widgets).
- Different default formats for each theme: /theme/fancy-theme/widgets/news.format.html
Widget Default Format Templates
25. Remove the stuff you don’t need.
Clean Markup: for unique, snazzy widgets.
No need for list of items here!
An <article> would be better.
Always add custom classes to
widgets when styling is unique:
- “Apply custom class”
- “Wrap widget with markup”
26. Add classes required for jQuery plugins.
Wrap widget output with markup: <div class="fancy-slider">{widget}</div>
Format results with:
<article class="fancy-slider-item" style="background-image:url({image_src});">
<a class="link" hef="{href}"></a>
<h4 class="headline">{headline}</h4>
<div class="summary">{summary}</div>
</article>
Clean Markup: for unique, snazzy widgets.
27. More Advanced Widgets
- Use xphp page variables to change widget content on a page-by-page basis.
- Use xphp group variables to change widget content on a per-group basis.
- Example: Show events tagged with the page title:
33. Example: Profiles Search
Use Quick Access to search through the results of a saved widget:
<h2>Quickly browse faculty by research area or keyword:</h2>
<form class="quickaccess-form">
<label class="screen-reader-text" for="faculty-quicksearch">Search faculty</label>
<input id="faculty-quicksearch" class="lw_qa_widget_88" type="text"
placeholder="Search faculty" data-qa-none-found="No faculty found.">
</form>
34. Example: Profiles Search
Use the data attribute to search over profile fields without displaying them in the results:
<widget type="profiles">
<arg id="type">Faculty</arg>
<arg id="paginate">false</arg>
<arg id="sort_order">alphabetical</arg>
<arg id="format"><a href="{href}" data-keywords="{profiles_78_clean}
{tags_starred_clean}">{name_clean}</a></arg>
</widget>
Search over name, “Faculty Expertise” and starred profile tags.
37. While we’re talking about search…
Use data-qa-none-found to change the no results message:
<input type="text" id="quicksearch" class="lw_qa lw_qa_widget_60" name="q"
placeholder="Search programs, people, practice areas" autocomplete="off"
data-qa-none-found="No quick results found. Press Enter to search." data-qa-max-results="20"
value="">
38. - Use the .editable class to make an area editable.
<div id="sidebar-content" class="editable optional">
<!-- Your editable content goes here -->
</div>
- Each editable element must have a unique ID.
- The .optional class allows that element to be hidden if
it doesn’t contain any content.
- When this element is hidden, the body gets class
.sidebar-content_hidden
Mastering the Page Editor
39. Mastering the Page Editor
- Use the .sidebar-content_hidden class to change the page
layout when there’s no sidebar content.
body.sidebar-content_hidden .main-content {
width: 100%;
}
- Use the .editable class to add site-wide styles that only
apply to editable areas.
.editable .lw_image {
margin-bottom: 10px;
max-width: 100%;
height:auto;
}
40. Mastering the Page Editor
- Include a clearfix on all editable areas.
.editable:before,
.editable:after {
content:'';
display: table;
clear: both;
}
- Add header styling for editable areas that may not apply
to headers on the homepage etc.
.editable h2 {
font-size: 26px;
color: red;
}
43. Mastering the Page Editor
Use the class .lw_editor_on to change the appearance while the page is being edited.
Use the widget editor to
add the class .empty when
there’s no image.
<arg id="no_results">
<div class="header-image
empty"></div>
</arg>
45. Mastering the Page Editor
Example: display a suggestion to include a header image on the page.
.header-image.empty {
display:none;
}
.lw_editor_on .header-image.empty {
display: block;
background-color: #ccc;
}
.lw_editor_on .header-image.empty:after {
content: 'Tag an image "header image" to appear here.';
display: block;
}
48. Mastering the Page Editor
Example: Insert images in the page editor and move them around after the page is saved.
/* position title image left of article divider */
#title img {
position: absolute;
left: 0;
top: 0;
transform: translate(-90.5%, -7%);
}
/* this treatment allows images to be positioned correctly and stay visible */
.lw_editor_on #title img {
position: relative;
transform: translateX(0);
}
49. Mastering the Page Editor
- Add buttons to the page editor toolbar.
$_LW->CONFIG['TOOLBAR_ADD_BUTTONS']=array('blockquote’, ‘hr');
- Edit the Formats dropdown to provide more styling options.
$_LW->REGISTERED_APPS['pages_editor']['custom']['style_formats']= array(
array('title'=>'Text styles:','selector'=>'p,h2,h4'),
array('title'=>'Small type','selector'=>'p,h2,h4','classes'=>'font-small'),
array('title'=>'Link styles:','selector'=>'a'),
array('title'=>'Button','selector'=>'a','classes'=>'button1'),
);
50. Mastering the Page Editor
- Customize the default gallery type used when adding a slideshow in the page editor.
$_LW->REGISTERED_MODULES['galleries']['custom']['default_type']='mini';
- Also customizes the gallery type for “Get Code” links in the gallery manager.
- Custom galleries are kept in the theme under /my_theme/galleries/
51. Mastering the Page Editor
- Call a JavaScript function after the page is edited.
$('body').bind('stopEdit.lw', function(){
// do this after LiveWhale page edit/save
});
- Similarly for the calendar:
$('body').bind('calLoad.lwcal', function() {
// do this each time the calendar view is refreshed
});
52. Owning Your Site
- Create a style guide for editors.
- Write informative widget descriptions.
- Add twice as many comments to your code as you think you need.
- Keep file paths predictable and file names understandable.
- Document everything unique to your site for future developers, for us, for yourself.
- Where’s the best place to keep all this documentation?
GetHelp.livewhale.com
55. Owning Your Site
Add a navigation widget to the dashboard in livewhale/client/private.config.php:
$_LW->CONFIG['DASHBOARD'] = array(
'left' => array(
array(
'LiveWhale CMS Help',
'<br/><widget id="127_help_navigation"></widget>'
),
),
);
GetHelp.livewhale.com
56. Example: Careers Microsite www.lakeforest.edu/careers/pathways
- Use a new theme (CSS & JavaScript).
- Add new default widget formats.
- Create new templates.
- New LiveWhale theme structure makes it easy
to keep everything bundled together.
65. <xphp content="true">
<if var="x" value=""/>
<content>
<!-- Show this if x is empty -->
</content>
<else content="true">
<content>
<!-- Show this if x is non-empty -->
</content>
</else>
</xphp>
LiveWhale Conditional Statements
https://livewhale.desk.com/customer/en/portal/articles/2490653-xphp-if-then-else-statement
66. <xphp content="true" ifmode="or">
<if var="profiles_22"/>
<if var="profiles_23"/>
<content>
<!-- one of these variables is non empty -->
</content>
</xphp>
LiveWhale Conditional Statements
https://livewhale.desk.com/customer/en/portal/articles/1522002-xphp-and-or-statements
67. <xphp content="true">
<if var="server_path" not_equals="{group_directory}index.php"/>
<content>
<!-- show this if it's not the group homepage -->
</content>
</xphp>
LiveWhale Conditional Statements
69. Tells the functions inside to use LiveWhale’s jQuery and keeps variables locally scoped.
http://adripofjavascript.com/blog/drips/an-introduction-to-iffes-immediately-invoked-function-express
ions.html
;(function($) {
// Assigns LiveWhale's jQuery to $
}(livewhale.jQuery));
LiveWhale jQuery IIFE
(Immediately Invoked Function Expression)
70. You can put the plugin JS in a custom theme OR call the plugin JavaScript on some pages only.
$.ajax({
url: "/scripts/plugin.js", // Use an IIFE in plugin.js if the plugin requires jQuery
dataType: "script",
cache: false
}).done(function() {
// Do stuff here using the plugin
});
Using Plugins in LiveWhale
71. Keeping Performance in Mind
function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
Example:
var myFunc = debounce( function() {
// do something here
}, 250, true);
Reduces the number of timed a function is called when resizing the window, scrolling, etc.
JavaScript debounce function from Underscore.js:
https://davidwalsh.name/javascript-debounce-function
72. Add this to you events detail file to display all events in the calendar instead of in their own
details template:
<?php
if (!empty($_GET['id'])) {
die('<html><head><meta http-equiv="refresh"
content="0;URL=/calendar/#event_id/'.(int)$_GET['id'].'/view/event">
</head><body><script
type="text/javascript">window.location.href="/calendar/#event_id/'.(int)$_GET['id'].'/view/event";
</script></body></html>');
};
require $_SERVER['DOCUMENT_ROOT'].'/livewhale/frontend.php';
?>
Displaying Events Only in the Calendar