Showing posts with label Meta. Show all posts
Showing posts with label Meta. Show all posts

Friday, April 26, 2013

Using the Blogger API to search within a post's HTML content

A couple of months ago I wanted to switch the syntax highlighter I used to have on this blog to SunlightJS. Thing is though, I didn't want to go through every individual post I had written before and check whether they are using the (old) syntax highlighter to update their HTML markup.

Another problem was that the only way I would be able to truly know if a particular post is using the old syntax highlighter was by going through it's HTML content and determine whether the post currently has a tag like the following: <pre class="

The issue here is that the normal Google driven searchbox packaged with Blogger (the one you see on the right hand side) does not search through a posts' HTML content but rather through its textual content only which means it was useless for my task.

Because of this, I decided to write a script to semi-automate this task for me. The reason I say that the script semi-automates the job is because although I wanted it to show me all the posts in which I had used the old highlighter before, I could not risk making it to update the blog post automatically to use the new syntax highlighter because that would have involved HTML parsing and it was not worth the hassle. Besides, I didn't want to risk ruining my old posts because of a script fuckup.

So what the script does is it uses the Blogger API to batch-fetch all my previous blog posts, go through each posts' individual HTML content and notify me whether that particular post is using the old syntax highlighter. Searching is done using the regular expression engine and for my case, the function was pretty trivial:

getOccurences = function(haystack, needle) {
    var matches = haystack.match(new RegExp(needle, "g"));
    return matches ? matches.length: 0;
}

The Blogger API url I used to fetch my posts' details is as follows:

https://www.googleapis.com/blogger/v3/blogs/<blogid>/posts?key=<API key>

For the script to work I needed to provide it with three things:

Here's a demo of the script in action: http://jsfiddle.net/ydtuc/77/.

And this is how it looks like:


From the live demo (or the screenshot), you can see the output of the script in the bottom right pane. The script nicely formats each of the returned matches in a way that if I click on the #number of the post, it would take me to the actual blog post and clicking on the name of the post takes me to the Blogger editor for that current post so that I can easily update it. The number in parentheses next to the title of the post is the total number of occurrences the needle appears in the haystack.

This is the full script:

var key = 'AIzaSyCEsBaStg4bOHA2Yp75OqfbjBkk_kq0cMw',
    blogId = '7117612757607239790',
    baseMatcher = 'JavaScript', // the needle.
    allPosts = [],
    isProcessing,
    updateButton = $("#update"),
    update = (function (button) {
        var updateText = function (message, color) {
            button.attr("value", message);
            if (color) {
                button.css("color", color);
            }

        },
            revertButtonMessage = function () {
                changeButtonMessage("Update", "black");
            },
            changeButtonMessage = function (message, color) {
                var didIt;
                updateText(message, color);
                setTimeout(revertButtonMessage, 1000);
            },
            switchButtonMessage = function (message, color) {
                updateText(message, color);
            };

        return {
            changeButtonMessage: changeButtonMessage,
            switchButtonMessage: switchButtonMessage,
            revertButtonMessage: revertButtonMessage
        };
    }(updateButton)),
    formatLink = function (text, href) {
        return '<a href="' + href + '" target="_blank">' + text + '</a>';
    },
    getOccurences = function (haystack, needle) {
        var matches = haystack.match(new RegExp(needle, "g"));
        return matches ? matches.length : 0;
    },
    logger = (function () {
        var logs = $("#logs"),
            appendLine = function (line) {
                logs.append((line ? line : "") + "<br/>");
            };

        return {
            log: function (items) {
                appendLine('<span class="logHeader">Logs #' + new Date().getTime() + '</span>');
                appendLine();
                $.each(items, function (i, item) {
                    appendLine(formatLink('#' + i, item.url) + ': ' + formatLink(item.title, "http://www.blogger.com/blogger.g?blogID=" + blogId + "#editor/target=post;postID=" + item.id) + ' (' + getOccurences(item.content, baseMatcher) + ')');
                });
                appendLine();
            },
            clear: function () {
                logs.html('');
            }
        };
    }()),
    filter = function (items, predicateForPass) {
        var i = 0,
            j = items.length,
            item, passed = [],
            inc = 0;

        for (; i < j; ++i) {
            item = items[i];
            if (!predicateForPass(item)) {
                continue;
            }

            passed.push(item);
        }

        return passed;
    },
    getPosts = function (pageToken) {
        var url = 'https://www.googleapis.com/blogger/v3/blogs/' + blogId + '/posts?key=' + key,
            get = function (token) {
                var pagedUrl = url + (token ? ("&pageToken=" + token) : "");
                $.get(pagedUrl, function (response) {
                    var token = response.nextPageToken;
                    allPosts = allPosts.concat(response.items);

                    if (token) {
                        return get(token);
                    }

                    isProcessing = false;
                    update.changeButtonMessage("Finished", "green");
                    var filtered = filter(allPosts, function (item) {
                        var preTotal = getOccurences(item.content, baseMatcher),
                            preNewSyntaxHighlighter = getOccurences(item.content, baseMatcher + "sunlight");
                        return (preTotal - preNewSyntaxHighlighter) > 0;
                    });

                    console.log(filtered);
                    logger.clear();
                    logger.log(filtered);
                    allPosts.length = 0;
                });
            };

        update.switchButtonMessage("Getting posts...", "green");
        isProcessing = true;

        get(pageToken);
    };
updateButton.click(function () {
    if (isProcessing) {
        return update.changeButtonMessage("Busy; try again later", "red");
    }

    getPosts();
});

getPosts();

Wednesday, November 25, 2009

3D Rotating Tag Cloud for Blogger (Cumulus Cloud)

Today I implemented a rotating 3D tag cloud, called a Blogumus.  Such a script was initially written as a plugin for WordPress, called WP-Cumulus.

But Amanda from BloggerBuster has ported a version of the WordPress plugin to Blogger; and it's now called Blogumus.

Here's an example of the Blogumus in action:





Implementing the Blogumus for your Blogger blog is very easy:

  1. Find the side-bar section in your layout's html. The sidebar section starts with the following tag:


    <b:section class="sidebar" id="sidebar" preferred="yes">

  2. In your side-bar section (ie in the tag mentioned above), paste the following code:


    <b:widget id='Label99' locked='false' title='Labels' type='Label'>
    <b:includable id='main'>
    <b:if cond='data:title'>
    <h2><data:title/></h2>
    </b:if>
    <div class='widget-content'>
    <script src='http://halotemplates.s3.amazonaws.com/wp-cumulus-example/swfobject.js' type='text/javascript'/>
    <div id='flashcontent'>Blogumulus by <a href='http://www.roytanck.com/'>Roy Tanck</a> and <a href='http://www.bloggerbuster.com'>Amanda Fazani</a></div>
    <script type='text/javascript'>
    var so = new SWFObject("http://halotemplates.s3.amazonaws.com/wp-cumulus-example/tagcloud.swf", "tagcloud", "240", "300", "7", "#ffffff");
    // uncomment next line to enable transparency
    //so.addParam("wmode", "transparent");
    so.addVariable("tcolor", "0x333333");
    so.addVariable("mode", "tags");
    so.addVariable("distr", "true");
    so.addVariable("tspeed", "100");
    so.addVariable("tagcloud", "<tags><b:loop values='data:labels' var='label'><a expr:href='data:label.url' style='12'><data:label.name/></a></b:loop></tags>");
    so.addParam("allowScriptAccess", "always");
    so.write("flashcontent");
    </script>
    <b:include name='quickedit'/>
    </div>
    </b:includable>
    </b:widget>
    



To customize the dimensions and background-color, modify the following line from the code above:

var so = new SWFObject("http://halotemplates.s3.amazonaws.com/wp-cumulus-example/tagcloud.swf", "tagcloud", "240", "300", "7", "#ffffff");

The default values are:
  • Width: 240
  • Height: 300
  • Background Colour: #ffffff

To change the color of the font, modify it from the following line:

so.addVariable("tcolor", "0x333333");

The default color is #333333

This tutorial was adopted from Amanda's Tutorial.


Tuesday, November 24, 2009

'What I was listening to' box in my posts

I recently implemented a 'system' in where I show one or more songs I was listening to whilst writing a blog post, in this form:



To do that, I wrote a small script:

var blogmusic = function () {
    var lastContainerDone = 0;
    return function (music) {
        var musiccount = music.length,
            blogmusic = $(".blogmusic").eq(lastContainerDone++),
            header = $("<div/>").addClass("header");
        header.append("<center>What I was listening to</center>");
        var musiclist = $("<div/>").addClass("musiclist");
        for (var i = 0; i & lt; musiccount; i += 1) {
            var song = music[i];
            var listing = $("<div/>").addClass("listing");
            var songname = $("<span/>").addClass("songname").html('<a href="' + (song.link || '#') + '" target="_blank">"' + song.name + '"</a>');
            var artist = $("<span/>").addClass("artist").html('- ' + song.artist);
            listing.append(songname);
            listing.append(artist);
            musiclist.append(listing);
        }
        blogmusic.html(header);
        blogmusic.append(musiclist);
    };
} ();

And I invoke the script in my blog posts like such:

<div class="blogmusic">
<script>
blogmusic([
{ 
    artist : 'Jerry Lee Lewis',
    name : 'Whole Lotta Shakin\'',
    link : 'http://listen.grooveshark.com/#/song/Whole_Lotta_Shakin/6325468'
}
]);
</script>
</div>

Sunday, October 18, 2009

Syntax highlighting in Blogger

To implement code syntax highlighting, I used instructions from this post by Matthew V Ball.
Here are the instructions:

1. Go to http://syntaxhighlighter.googlecode.com/svn/trunk/Styles/SyntaxHighlighter.css, then perform a "select all" and "copy". The css information is now in the clipboard.

2. Paste the css information at the end of the css section of your blogger html template (i.e., after ).

3. [Updated March 25, 2009 to include closing script tags] Before the  tag, paste the following:

  1.   
  2. <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shCore.js' type='text/javascript'>script>  
  3. <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushCpp.js' type='text/javascript'>script>  
  4. <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushCSharp.js' type='text/javascript'>script>  
  5. <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushCss.js' type='text/javascript'>script>  
  6. <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushDelphi.js' type='text/javascript'>script>  
  7. <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushJava.js' type='text/javascript'>script>  
  8. <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushJScript.js' type='text/javascript'>script>  
  9. <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushPhp.js' type='text/javascript'>script>  
  10. <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushPython.js' type='text/javascript'>script>  
  11. <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushRuby.js' type='text/javascript'>script>  
  12. <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushSql.js' type='text/javascript'>script>  
  13. <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushVb.js' type='text/javascript'>script>  
  14. <script src='http://syntaxhighlighter.googlecode.com/svn/trunk/Scripts/shBrushXml.js' type='text/javascript'>script>  
Feel free to remove lines for languages you'll never use (for example, Delphi) -- it will save some loading time.

4. [Updated to add final /script] Before the  tag, insert the following:
  1.   
  2. <script language='javascript'>  
  3. dp.SyntaxHighlighter.BloggerMode();  
  4. dp.SyntaxHighlighter.HighlightAll('code');  
  5. script>  

5. Use the "Preview" button to make sure your website is correct, then click "Save Template".

6. When composing a blog entry that contains source code, click the "Edit Html" tab and put your source code (with html-escaped characters) between these tags:
  1. <pre name="code" class="cpp">  
  2. ...Your html-escaped code goes here...  
  3. pre>  

Substitute "cpp" with whatever language you're using (full list). (Choices: cpp, c, c++, c#, c-sharp, csharp, css, delphi, pascal, java, js, jscript, javascript, php, py, python, rb, ruby, rails, ror, sql, vb, vb.net, xml, html, xhtml, xslt)


For performing the HTML escaping, you can get a good list of tools by searching for 'html esaper' or a similar term. Here's the one I used while writing this post.