If your website generates useful data a great way to propagate it is by providing widgets. A widget is a portable chunk of code that can be installed and executed within any separate HTML-based web page. By providing widgets, owners of other websites can display a small portion of your website, in theirs.
Building widgets is very easy, but building a widget editor and preview tool for each widget can be time consuming. I wanted to build at least a half dozen widgets for RepresentMe so I came up with a Generic Widget Builder. This tool will allow you to easily add new widgets each with their own editor and preview, requiring very little code.
Overview
This example will use the Lawkmakers By Zipcode widget. It accepts a zipcode and displays the lawmakers for that zipcode.
Step 1 – BuilderForm
The BuilderForm is a Django Form that contains some common fields that most widgets will want, such as color and background. Fields you add to the form will automatically be added to the preview page.
from repme_widgets.builder.forms import WidgetFormBase
class LawmakersWidgetForm(WidgetFormBase):
"""
Form for a single lawmaker with a single issue
"""
zipcode = forms.CharField()
Step 2 – Builder Tempate
The builder template is a django template used to render the javascript or html code that will display the widget. By defining it as a template we can take input from a form and give the user both the code neccesary for their customized widget, and a preview
<script type="text/javascript">
repme_host_url = "{{host}}";
repme_zipcode = "{{zipcode}}";
repme_frame_height = "340";
repme_frame_width = "220";
repme_bgcolor = "{{background_color}}";
repme_textcolor = "{{text_color}}";
repme_bordercolor = "{{border_color}}";
</script>
<script type="text/javascript" src="http://{{host}}/widgets/js/lawmakers.js">
</script>
Some values are not included in the form:
Host – this comes from the settings file, this is required because the code must include an absolute url including hostname.
Height/Width – The height and width for a widget is often fixed so we haven’t included it in the form.
Step 3 – URL Handler For This Widget’s Builder
All widget’s built with the Generic Widget Builder use the same handler, passing the form class and widget template as parameters. These values will be used to customize the preview page to your widget.
from repme_widgets.forms import LawmakersWidgetForm
(r'^builder/lawmakers/$', builder, {'form_class':LawmakersWidgetForm, 'widget_template':'widgets/builder/lawmakers.html'}),
Step 4 – Rendering The Widget
There are a few ways to build a widget. They all result in an Iframe that loads a small portion of your website. You can either call an Iframe directory, passing in your properties or use javascript to write the iframe to the document. RepresentMe uses the latter because the code the users must cut-n-paste is simpler and easier to read or modify outside the builder.
Here is the javascript loader:
var fHeight = parseInt(window.repme_frame_height);
if (window.navigator.userAgent.indexOf("MSIE")) {
fHeight = fHeight + 7;
}
document.write('<iframe name="repme_lawmaker" width="'+window.repme_frame_width+'" height="' + fHeight + '" scrolling="auto" frameborder="0" style="border-style: solid; border-width: 1px; border-color:' + window.repme_bordercolor + ';" allowtransparency="true" hspace="0" vspace="0" marginheight="0" marginwidth="0" src="http://' + window.repme_host_url + '/widgets/lawmakers/?zip=' + window.repme_zipcode + '&color='+window.repme_textcolor+'&bg_color='+window.repme_bgcolor+'"></iframe>')
The view called by this widget is just another django view, except its output is a much smaller window.
Wrap Up
You should now be able to easily build an editor and preview tool for your widget. Here is the widget I discussed in action. The rest of the widgets for RepresentMe are here.
RepresentMe is released under GPLv3, feel free to reuse the Generic Widget Builder with your site.
I’m attempting to build a HTML widget similar what you’ve done here. How can I get access to your code?
I’m new to django and python so please correct me if I’m wrong but I dont believe I can use
from repme_widgets.builder.forms import WidgetFormBase
without access to the code.
Thanks,
Sorry about that. The code is found here:
http://github.com/kreneskyp/representme/tree/43731d3bcb1142d93f31d1676c07c9d3581c77d2/repme_widgets