Alex Kehayias's Blog

  • Archive
  • RSS

How to make an interactive bookmarklet part 2

Let’s talk about how to generate a bookmarklet using server-side templating and pure javascript (no libraries!). In part 1 we discussed the basic framework for making a bookmarklet and performing requests directly from the client’s page. Now we’ll see how to set up the foundation for a bookmarklet UI and make it look good.

Building a Bookmarklet Template in Django

Let’s create a file called bookmarklet.js. In it we are going to add a self executing piece of javascript and leverage django templates to fill in the information we need. In here we are going to build the response using nothing but javascript and send it back to the user who requested the bookmarklet (remember all they did was request it to be initialized, see part 1 for more info). With django templates we can do some pretty handy things so that you don’t need to manually write out the template as a string in javascript. For example:

javascript:(function(){
    var d=document,
    {% comment %}Create the elements we need {% endcomment %}
    c=d.createElement("div"),
    b=d.body,
    l=d.location;
    {% comment %} server_scheme_and_netlog is my own tag which returns the base url of the website{% endcomment %}
    c.id="bookmarkletArticleAlertBox";
    {% comment %}This is where django templates get's awesome{% endcomment %}    
    {% comment %}Make sure the html rendered has no breaks{% endcomment %}    
    c.innerHTML = '{% spaceless %}{% include "bookmarklet_body.html" %}{% endspaceless %}';
    {% comment %}Add the elements to the dom{% endcomment %}
    b.appendChild(t);
    b.appendChild(c);

....snip....

What we did was construct a div that will hold our bookmarklet UI and using django templates (the {%include … %} part) we can template the html easily, inheriting the context of this view. Please make sure to add the “spaceless” tags here because the innerHTML will fail if there are line breaks and I’ll be damned if I have to add linebreaks to my template. Also be extremely picky with your quotes as that can also lead to disaster.

Now in our “bookmarklet_body.html” we can create our UI just as if it were any other django template (almost). For example:

{% load static %}
{% load url_tags %}
{% comment %}NOTE Make sure you ONLY use double quotes!{% endcomment %}    

<div id="bookmarkletAssistant">
    <img src="{% server_scheme_and_netloc %}{% get_static_prefix %}images/assistant.png" style="border: 2px solid #666666;"/><br/>    
    <img id="bookmarkletLoadingImage" src="{% server_scheme_and_netloc %}{% get_static_prefix %}images/bookmarklet-ajax-loader.gif" style="display:none;"/>
</div>
<div id="bookmarkletResponse">
    <p>Hey Chief, almost ready!</p>
    <div id="bookmarkletPictureSelector">
        <p>
            <label>Select Picture:</label><br/>
            <div id="bookmarkletImageContainer">
                <img id="bookmarkletCurrentImage" />
                <a id="bookmarkletSelectPrev">&laquo;</a><a id="bookmarkletSelectNext" >&raquo;</a>
            </div>
        </p>
    </div>
    <p id="bookmarkletImageCheckboxContainer"><input id="bookmarkletImageCheckbox" type="checkbox" style="margin-right: 5px;" />
    <label>No Picture</label></p>
    <p>
        <label>Editor&rsquo;s Note:</label><br/>
        <textarea id="bookmarkletTextArea" placeholder="Add your commentary on the article here. (optional)"></textarea>
    </p>
    <input id="bookmarkletSubmit" type="submit" value="Publish Article" />
    <a id="bookmarkletCancel">Cancel</a>
</div>

Notice how all the elements are contained within elements with IDs. This is extremely important so you can clean up after yourself and not pollute the dom. You will also need to do this so that subsequent interactions can find your bookmarklet and update the contents. BTW this is exactly what is used in Edorati. 

Make sure that you have a view set up so that you know it is from your bookmarklet and can respond with your javascript template. When the user initializes the bookmarklet (see part 1 for reference) they will be requesting a url that you control. All you need to do is map that url to a view function and do the following:

    variables = {'some_var': 'blah blah'}
    resp = render_to_string('bookmarklet.js', variables)
    return HttpResponse(resp, mimetype="text/javascript")

This will make sure we are responding with javascript and not html. The javascript will be executed as soon as it is received by the user. It’s actually very fast and should feel close to instantaneous. 

Making it Look Pretty

Plain unstyled html would be a terrible idea for a bookmarklet. Keep in mind that you are injecting onto another page where their stylesheet is unknown. That means we need to style and reset the css for the bookmarklet or it will not look consistent across sites. Here’s how:

    // in bookmarklet.js
    t=d.createElement("link"), 
    t.rel="stylesheet";
    t.media="screen, projections";
    t.type="text/css";
    t.href="{% server_scheme_and_netloc %}{% get_static_prefix %}stylesheets/bookmarklet.css";

Whoa, dynamically loading css just for our bookmarklet! Nothing fancy going on here, just using plain ol’ css to beautify our bookmarklet. Just make sure that you do not inadvertently style the rest of the elements on the page with your stylesheet. As mentioned before, add an ID for all major elements and when it comes to css, use the ID selector to style the element instead of the element selector or class. If you have to use classes just obfuscate the name so there is little possibility of you impacting the page i.e bookmarklet-textarea-field vs. textarea.  

Next Week

Next week we’ll go over how to make the bookmarklet come alive with interaction through event binding and requests using about 15 lines of pure javascript and no libraries.

    • #django
    • #bookmarklet
    • #javascript
  • 1 year ago
  • 2
  • Permalink
  • Share
    Tweet

2 Notes/ Hide

  1. e-mechanism likes this
  2. oldnotes reblogged this from alexkehayias
  3. alexkehayias posted this
← Previous • Next →

About

Blogging about hacking code, life, and music.

Me, Elsewhere

  • @alexkehayias on Twitter
  • Facebook Profile
  • Linkedin Profile

Twitter

loading tweets…

I Dig These Posts

  • Post via jordanorelli
    hexes

    image

    source

    Post via jordanorelli
  • Photoset via ruineshumaines

    Katharina Grosse

    Photoset via ruineshumaines
  • Photoset via myedol

    Imeüble by Bjørn Jørund Blikstad

    Created out of plastic this interesting shelving system really messes with your mind. Simple to assemble and...

    Photoset via myedol
  • Photo via tr3ats

    There’s a sense of satisfaction when using a pen ‘til it runs out of ink. It doesn’t happen often, but when it does, it feels like the arrival of a...

    Photo via tr3ats
See more →
  • RSS
  • Random
  • Archive
  • Mobile

Effector Theme by Carlo Franco.

Powered by Tumblr