Go to file
Will Rossiter 1b54cfc321 Merge pull request #51 from NoBone/0.1
Updated Widget module to show hide Widgets in specified WidgetArea
2013-05-08 03:04:35 -07:00
_config NEW: Add an extension that provides the <page-url>/widget/<widget-id> URL as part of the widgets module. (Trac #7174) 2012-06-22 14:04:21 +12:00
code Update WidgetAreaEditor.php 2013-04-22 16:18:07 +03:00
css ENHANCEMENT: Adapt the Widgets Editor CMS UI to fit SS 3.0 2013-01-05 13:11:04 -06:00
javascript BUG: Enable chosen in WidgetAreaEditor fields. 2012-08-30 10:09:49 +03:00
lang Create nl.yml 2013-02-24 22:44:23 +01:00
scss ENHANCEMENT: Adapt the Widgets Editor CMS UI to fit SS 3.0 2013-01-05 13:11:04 -06:00
templates Fixed template usage 2013-03-19 10:13:15 +01:00
tests MINOR Initial commit 2012-04-18 23:20:33 +02:00
.gitignore ENHANCEMENT: Adapt the Widgets Editor CMS UI to fit SS 3.0 2013-01-05 13:11:04 -06:00
.travis.yml Only build 0.1 branch against 3.0 core 2013-04-04 01:50:21 +03:00
LICENSE MINOR Initial commit 2012-04-18 23:20:33 +02:00
README.md Updated README to describe WidgetPageExtension 2013-04-16 16:19:03 +02:00
_config.php MINOR Initial commit 2012-04-18 23:20:33 +02:00
composer.json Limit compat to 3.0 2013-04-04 01:13:01 +03:00
config.rb ENHANCEMENT: Adapt the Widgets Editor CMS UI to fit SS 3.0 2013-01-05 13:11:04 -06:00

README.md

Widgets Module

Build Status

Introduction

Widgets are small pieces of functionality such as showing the latest comments or Flickr photos. They normally display on the sidebar of your website. To check out a what a Widget can do watch the Widget video and try out the demo site

Requirements

  • SilverStripe 3.0

Installation

Install the module through composer:

composer require silverstripe/widgets

Widgets are essentially database relations to other models, mostly page types. By default, they're not added to any of your own models. The easiest and most common way to get started would be to create a single collection of widgets under the name "SideBar" on your Page class. This is handled by an extension which you can enable through your config.yml:

:::yml
Page:
  extensions:
    - WidgetPageExtension

Run a dev/build, and adjust your templates to include the resulting sidebar view. The placeholder is called $SideBarView, and loops through all widgets assigned to the current page.

Alternatively, you can add one or more widget collections to your own page types. Here's an example on how to just add widgets to a MyPage type, and call it MyWidgetArea instead.

:::php
class MyPage extends Page {
	// ...
  static $has_one = array(
		"MyWidgetArea" => "WidgetArea",
  );
	
  public function getCMSFields() {
		$fields = parent::getCMSFields();
		$fields->addFieldToTab("Root.Widgets", new WidgetAreaEditor("MyWidgetArea"));
		return $fields;
  }
}

In this case, you need to alter your templates to include the $MyWidgetArea placeholder.

Writing your own widgets

To create a Widget you need at least three files - a php file containing the class, a template file of the same name and a config file called _config.php (if you dont need any config options for the widget to work then you can make it blank). Each widget should be in its own folder like widgets_widgetName/

After installing or creating a new widget, make sure to run db/build?flush=1 at the end of the URL, before attempting to use it.

The class should extend the Widget class, and must specify three static variables - $title, the title that will appear in the rendered widget (eg Photos), $cmsTitle, a more descriptive title that will appear in the cms editor (eg Flickr Photos), and $description, a short description that will appear in the cms editor (eg This widget shows photos from Flickr). The class may also specify functions to be used in the template like a page type can.

If a Widget has configurable options, then it can specify a number of database fields to store these options in via the static $db array, and also specify a getCMSFields function that returns a !FieldList, much the same way as a page type does.

An example widget is below:

FlickrWidget.php

:::php
<?php
class FlickrWidget extends Widget {
	static $db = array(
		"User" => "Varchar",
		"Photoset" => "Varchar",
		"Tags" => "Varchar",
		"NumberToShow" => "Int"
	);
	
	static $defaults = array(
		"NumberToShow" => 8
	);

	static $title = "Photos";
	static $cmsTitle = "Flickr Photos";
	static $description = "Shows flickr photos.";
	
	public function Photos() {
		Requirements::javascript(THIRDPARTY_DIR . "/prototype/prototype.js");
		Requirements::javascript(THIRDPARTY_DIR . "/scriptaculous/effects.js");
		Requirements::javascript("mashups/javascript/lightbox.js");
		Requirements::css("mashups/css/lightbox.css");
		
		$flickr = new FlickrService();
		if($this->Photoset == "") {
			$photos = $flickr->getPhotos($this->Tags, $this->User, $this->NumberToShow, 1);
		} else {
			$photos = $flickr->getPhotoSet($this->Photoset, $this->User, $this->NumberToShow, 1);
		}
		
		$output = new ArrayList();
		foreach($photos->PhotoItems as $photo) {
			$output->push(new ArrayData(array(
				"Title" => $photo->title,
				"Link" => "http://farm1.static.flickr.com/" . $photo->image_path .".jpg",
				"Image" => "http://farm1.static.flickr.com/" .$photo->image_path. "_s.jpg"
			)));
		}
		return $output;
	}

	public function getCMSFields() {
		return new FieldList(
			new TextField("User", "User"),
			new TextField("PhotoSet", "Photo Set"),
			new TextField("Tags", "Tags"),
			new NumericField("NumberToShow", "Number to Show")
		);
	}
}

FlickrWidget.ss

:::ss
<% control Photos %>
	<a href="$Link" rel="lightbox" title="$Title"><img src="$Image" alt="$Title" /></a>
<% end_control %>

Extending and Customizing

Rendering a $Widget Individually

To call a single Widget in a page - without adding a widget area in the CMS for you to add / delete the widgets, you can define a merge variable in the Page Controller and include it in the Page Template.

This example creates an RSSWidget with the SilverStripe blog feed.

:::php
public function SilverStripeFeed() {
	$widget = new RSSWidget();
	$widget->RssUrl = "http://feeds.feedburner.com/silverstripe-blog";
	return $widget->renderWith("WidgetHolder");
}

To render the widget, simply include $SilverStripeFeed in your template:

  $SilverStripeFeed

As directed in the definition of SilverStripeFeed(), the Widget will be rendered through the WidgetHolder template. This is pre-defined at framework/templates/WidgetHolder.ss and simply consists of:

:::ss
<div class="WidgetHolder">
	<h3>$Title</h3>
	$Content
</div>

You can override the WidgetHolder.ss and Widget.ss templates in your theme too by adding WidgetHolder and Widget templates to themes/myThemeName/templates/Includes/

Changing the title of your widget

To change the title of your widget, you need to override the Title() method. By default, this simply returns the $title variable. For example, to set your widgets title to 'Hello World!', you could use:

widgets_yourWidget/YourWidgetWidget.php

:::php
public function Title() {
	return "Hello World!";
}

but, you can do exactly the same by setting your $title variable.

A more common reason for overriding Title() is to allow the title to be set in the CMS. Say you had a text field in your widget called WidgetTitle, that you wish to use as your title. If nothing is set, then you'll use your default title. This is similar to the RSS Widget in the blog module.

:::php
public function Title() {
	return $this->WidgetTitle ? $this->WidgetTitle : self::$title;
}

This returns the value inputted in the CMS, if it's set or what is in the $title variable if it isn't.

Forms within Widgets

To implement a form inside a widget, you need to implement a custom controller for your widget to return this form. Make sure that your controller follows the usual naming conventions, and it will be automatically picked up by the WidgetArea rendering in your Page.ss template.

mysite/code/MyWidget.php

:::php
class MyWidget extends Widget {
  static $db = array(
    'TestValue' => 'Text'
  );
}

class MyWidget_Controller extends Widget_Controller {
  public function MyFormName() {
    return new Form(
      $this, 
      'MyFormName', 
      new FieldList(
        new TextField('TestValue')
      ), 
      new FieldList(
        new FormAction('doAction')
      )
    );
  }
  
  public function doAction($data, $form) {
    // $this->widget points to the widget
  }
}

To output this form, modify your widget template.

mysite/templates/MyWidget.ss

:::ss
$Content
$MyFormName

Note: The necessary controller actions are only present in subclasses of Page_Controller. To use widget forms in other controller subclasses, have a look at ContentController->handleWidget() and ContentController::$url_handlers.

But what if I have widgets on my blog currently??

If you currently have a blog installed, the widget fields are going to double up on those pages (as the blog extends the Page class). One way to fix this is to comment out line 30 in BlogHolder.php and remove the DB entry by running a http://www.mysite.com/db/build.

blog/code/BlogHolder.php

:::php
<?php
class BlogHolder extends Page {
	
      ........
	static $has_one = array(
	//	"Sidebar" => "WidgetArea", COMMENT OUT
		'Newsletter' => 'NewsletterType'
      .......
	public function getCMSFields() {
		$fields = parent::getCMSFields();
		$fields->removeFieldFromTab("Root.Content","Content");
	//	$fields->addFieldToTab("Root.Widgets", new WidgetAreaEditor("Sidebar")); COMMENT OUT

	........

Then you can use the Widget area you defined on Page.php