This is going to be the first part of a blog post series about javascript
widgets.
First type I’m going to cover is Popup Widget. Sometimes it’s called Popin
Widget because there is no actually new window that pops up, instead the
content is shown IN-side a current page. The idea is quite simple: you provide
some html/js snippet to other sites. They put it into relevant place, and you
have some functionality of your site running there.
I’m going to explain how exactly it works, what should be done to achieve this,
and what common mistakes i see once and again.
At the end of the blog post you will get a link to complete javascript library,
grab it, play with it, and use it for fun or profit.
Content.
-
Layout
-
Cross-browser support.
-
Global namespace.
-
Loading javascript.
-
UI problem with WEDJE.
-
Never slow down target site.
-
Using of js frameworks.
-
Random div ids.
-
Passing parameters to the script.
-
Loading, please wait…
-
Pop up the popup.
-
HTML/JS snippet.
-
Passing referrer.
-
YUI compressor
-
Getting things together.
-
Example
Ok, less talk, more work. If you don’t have a time and strong will to read my
thoughts about the approach, scroll to the last part 15. Getting things
together.
1. Layout.
The main idea is very simple. Let’s call a site that have your widget - “target”.
You add one or more divs to the end of target document, and they hold an
iframe. Ifame content comes from your site. Once user clicks some button you
show a div and bring relevant iframe content. Once user click some “close”
link, you hide this div together with iframe. Actually it’s likely to remove
iframe completely, I will talk about this later.
2. Cross-browser support.
Well, there is nothing more to say about it. Your code should work with all
grade-A browsers, meaning FF, Safari, IE7/8 and Opera.
3. Global namespace.
Since we’re going to put our javascript into 3rd party website, we should not
spam javascript namespace with our own variables and functions. That’s why I
personally dislike Google approach with setting global variables like
google_ad_client = "12345";
4. Loading javascript.
It’s good idea to have static javascript that can be cached, or even loaded
from Amazon S3. If you think you have to generate javascript dynamically, most
probably you’re doing smth wrong and have to review your architecture.
There are 2 different ways to load external javascript: syncronous, and
asyncronous (which sometimes called
WEDJE
‐ Widget Enabled DOM Javascript Embedding).
5. UI problem with WEDJE.
WEDJE approach is the right one for most cases because your javascript doesn’t slow down the target site. But since we have to bind some button click event with our code, there is a chance that user will click this button before our js code is loaded in a asyncronous way. And that’s not good. That’s why this approach is not applicable here, at least it’s not applicable without modifications.
6. Never slow down target site.
Since WEDJE approach is not applicable here, we have to go with syncronous way
of loading assets. Once you include javascript into a web page, browser stops
loading everything else until it loads and runs this javascript.
It means that if your site is down and doesn’t respond to requests, target site
will be frozen until the browser figures this out and times out. In other
words, if your site is down - you hurt the target site.
It might be tempting to put your javascript on some cloud storage solution,
like Amazon S3 together with all your other assets.
But there is a problem with it. See, S3 doesn’t support HTTPS protocol. And if
someone will want to use your widget on secure site it will work, but with
nasty “secure/insecure content” message.
Not nice.
So please allow HTTP and HTTPS access to your widget, it’s really annoying to
find useful widget and not use because of lack of support for HTTPS
(Feedburner, i’m looking at you).
Update: see Dubek’s comment below about S3 and HTTPS.
7. Using of js frameworks.
Short answer is: no.
Long answer is: never ever even try.
Since we’re writing a widget, we are doing something that adds a value to a
target site.
Target site worked without our widget before and will keep working without it
in a future. That’s why we should be modest here. Modest as in NOT bringing
100K of framework to use 3.5 functions from it.
We have no choice - need to implement these functions by ourselves.
Here is the short list of functions we need:
- get element by id
- show element
- hide element
- remove element
Right, DOM has it, but who will write document.getElementById
serveral times?
It takes time to write and takes bytes to load :-)
8. Random div ids.
To avoid problems with similar ids on a page, I’d suggest to generarte random
ids for the elements we’re going to add to the page. Check out rnd(...)
function in the example code.
9. Passing parameters to the script.
As i mentioned above, I think it’s a good idea to avoid spamming the javascript
namespace.
So, to pass parameters to the script we need to add them into script URL, and
than parse from the script itself, e.g.:
.../mywidget.js?key1=value1&key2=value2
Once script is loaded, it finds itself in a DOM tree, parses parameters and
passes them as-is to the iframe URL defined in opts.iframe_base_url
.
See “detecting protocol and parameters” section of the code for more detalis.
10. Loading, please wait…
Some of the widgets we see on internet doesn’t provide a visual feedback to
users about what’s going on.
While iframe is being loaded users see only dark backgorund, when browser
starts loading the iframe users see some white background.
That’s not good.
We need to provide some visual feedback like “Loading, please wait…” until
the iframe is completely loaded. That’s is done by binding to onload
event
of the iframe and switching the iframe’s and “loading…” div’s “display”
styles.
Please pay attention to opts.close_image
and opts.loading_image
parameters
at the beginning of the script.
11. Pop up the popup.
There are serveral approaches here.
-
user put a link/button in any place he likes, and passes it’s DOM id to the
script to allow us binding to its click-event;
-
we create a link/button in a place that user includes the script.
The first one is a quite rare approach because it requires more coding on a
user side. But you can still use it If you’re a writing a widget for your own
site. In such a case you could pass parameter to the javascript as mentioned in
“Passing parameters to the script.”, parse it in jasvascript and
call bind(...)
function:
bind("my_parsed_elelemt_id", "click", function(){show_widget(); return false});
The second one is the one we’re going to implement and use.
We create fancy image that will serve as a link to show the popup and define it
in opts.button_image
, don’t forget to avoid defining protocol there.
12. HTML/JS snippet.
You should share with your users a snippet. Here it is:
<script type='text/javascript'>
document.write(unescape("%3Cscript src='" + ("https:" == document.location.protocol ? "https" : "http") + "://assets.astrails.com/popup-assests/astrails-widget.js?q=wow' type='text/javascript'%3E%3C/script%3E"));
</script>
The snippet will actually embed a button and bind all the events.
Pay attention that we pass q=wow parameter to the script, your server-side part
of a widget will get this parameter. You can pass anything you want in those
parameters.
13. Passing referrer.
Since we open server-side part of a widget in a iframe, sever-side script will
not obtain HTTP_REFERRER
value.
We need to pass it manually in request URL. Take a look at “detecting protocol
and parameters” section of the code for more details.
14. YUI compressor
To finally distribute your code use YUI
Compressor, it could reduce a
downloadable code size.
15. Getting things together.
-
Grab the code from
github.
-
Open astrails-widget.js, and change values of hash “opts” to point to your
URLs and adjust iframe sizes.
-
Read “6. Never slow down target site.” if you haven’t already. If
you will take only one thing from this article, make it this one.
-
Compress the script with YUI compressor.
-
Upload compressed script to the location defined in opts.js_url.
-
Copy-paste a snippet from “12. HTML/JS snippet.”, add parameters
you need on the server side to the javascript URL.
-
Write the server part refered by opts.iframe_base_url
.
-
Give this snippet to your users.
-
Enjoy.
16. Example
Click the button below to see it in action.
In a next part i will try cover so called Embedded Widgets.