Sunday, December 23, 2007

Blog Archive Carousel Widget

I've played around with blogspots' widget system and came up with a nice blog archive carousel widget. The widget is based on the standard blogger.com blog archive widget and jcarousel, a jquery plugin.
DISCLAIMER: Use at your own discretion.
How to use:

  • Go to your blog's Template -> Edit HTML.

  • Download Full Template for backup and save it somewhere you'll remember.

  • Go go Template -> Page elements and add a blog archive widget, save the page.

  • Go back to Template -> Edit HTML.

  • Make sure Expand Widget Templates is not checked.

  • Just below the <data:blog.pagetitle/> add the code below

    <!-- archive carousel -->
    <script src='http://javajavaproxy.googlepages.com/jquery-1.2.1.min.js'/>
    <script src='http://javajavaproxy.googlepages.com/jquery.jcarousel.pack.js'/>
    <script type='text/javascript'>
    jQuery(document).ready(function() {
    jQuery('#mycarousel').jcarousel({ vertical: true, scroll: 3}); });
    </script>
    <!-- //archive carousel -->

  • At the end of the <skin> section, just above the ]]></b:skin>add the code below

    /* new archive */
    UL.posts LI { font-size:80%; width:170px; padding-right:2px; border-bottom:1px solid silver;}
    .jcarousel-container { position: relative; }
    .jcarousel-clip { z-index: 2; padding: 0; margin: 0; overflow: hidden; position: relative; }
    .jcarousel-list { z-index: 1; overflow: hidden; position: relative; top: 0; left: 0; margin: 0; padding: 0; }
    .jcarousel-item { float: left; list-style: none; width: 170px; xheight: 18px; }
    .jcarousel-next { z-index: 3; display: none; }
    .jcarousel-prev { z-index: 3; display: none; }
    .jcarousel-skin-tango.jcarousel-container { -moz-border-radius: 10px; background: #F0F6F9; border: 1px solid #346F97; }
    .jcarousel-skin-tango.jcarousel-container-vertical { width: 170px; height: 170px; padding: 40px 20px; }
    .jcarousel-skin-tango .jcarousel-clip-vertical { width: 190px; height: 170px; }
    .jcarousel-skin-tango .jcarousel-item { width: 170px; xheight: 18px; }
    .jcarousel-skin-tango .jcarousel-item-vertical { margin-bottom: 10px; }
    .jcarousel-skin-tango .jcarousel-item-placeholder { background: #fff; color: #000; }
    .jcarousel-skin-tango .jcarousel-next-vertical { position: absolute; bottom: 5px; left: 99px; width: 32px; height: 32px; cursor: pointer; background: transparent url(http://javajavaproxy.googlepages.com/next-vertical.png) no-repeat 0 0; }
    .jcarousel-skin-tango .jcarousel-next-vertical:hover { background-position: 0 -32px; }
    .jcarousel-skin-tango .jcarousel-next-vertical:active { background-position: 0 -64px; }
    .jcarousel-skin-tango .jcarousel-next-disabled-vertical,
    .jcarousel-skin-tango .jcarousel-next-disabled-vertical:hover,
    .jcarousel-skin-tango .jcarousel-next-disabled-vertical:active { cursor: default; background-position: 0 -96px; }
    .jcarousel-skin-tango .jcarousel-prev-vertical { position: absolute; top: 5px; left: 99px; width: 32px; height: 32px; cursor: pointer; background: transparent url(http://javajavaproxy.googlepages.com/prev-vertical.png) no-repeat 0 0; }
    .jcarousel-skin-tango .jcarousel-prev-vertical:hover { background-position: 0 -32px; }
    .jcarousel-skin-tango .jcarousel-prev-vertical:active { background-position: 0 -64px; }
    .jcarousel-skin-tango .jcarousel-prev-disabled-vertical,
    .jcarousel-skin-tango .jcarousel-prev-disabled-vertical:hover,
    .jcarousel-skin-tango .jcarousel-prev-disabled-vertical:active { cursor: default; background-position: 0 -96px; }

  • find the
    <b:widget id="'BlogArchive1'" locked="'false'" title="'Blog" type="'BlogArchive'/">
    and replace this line with the following code

    <b:widget id='BlogArchiveCarousel' locked='false' title='Blog Archive' type='BlogArchive'>
    <b:includable id='toggle' var='interval'>
    <b:if cond='data:interval.toggleId'>
    <b:if cond='data:interval.expclass == "expanded"'>
    <a class='toggle' expr:href='data:widget.actionUrl + "&amp;action=toggle" + "&amp;dir=close&amp;toggle=" + data:interval.toggleId + "&amp;toggleopen=" + data:toggleopen'>
    <span class='zippy toggle-open'>&#9660; </span>
    </a>
    <b:else/>
    <a class='toggle' expr:href='data:widget.actionUrl + "&amp;action=toggle" + "&amp;dir=open&amp;toggle=" + data:interval.toggleId + "&amp;toggleopen=" + data:toggleopen'>
    <span class='zippy'>
    <b:if cond='data:blog.languageDirection == "rtl"'>
    &#9668;
    <b:else/>
    &#9658;
    </b:if>
    </span>
    </a>
    </b:if>
    </b:if>
    </b:includable>
    <b:includable id='interval' var='intervalData'>
    <b:loop values='data:intervalData' var='i'>
    <b:if cond='data:i.data'>
    <b:include data='i.data' name='interval'/>
    </b:if>
    <b:if cond='data:i.posts'>
    <b:include data='i.posts' name='posts'/>
    </b:if>
    </b:loop>
    </b:includable>
    <b:includable id='menu' var='data'>
    <select expr:id='data:widget.instanceId + "_ArchiveMenu"'>
    <option value=''><data:title/></option>
    <b:loop values='data:data' var='i'>
    <option expr:value='data:i.url'><data:i.name/> (<data:i.post-count/>)</option>
    </b:loop>
    </select>
    </b:includable>
    <b:includable id='flat' var='data'>
    <ul>
    <b:loop values='data:data' var='i'>
    <li class='archivedate'>
    <a expr:href='data:i.url'><data:i.name/></a> (<data:i.post-count/>)
    </li>
    </b:loop>
    </ul>
    </b:includable>
    <b:includable id='posts' var='posts'>
    <b:loop values='data:posts' var='i'>
    <li>&amp;nbsp;<a expr:href='data:i.url'><data:i.title/></a></li>
    </b:loop>
    </b:includable>
    <b:includable id='main'>
    <b:if cond='data:title'>
    <h2><data:title/></h2>
    </b:if>
    <div class='widget-content'>
    <div id='ArchiveList'>
    <div expr:id='data:widget.instanceId + "_ArchiveList"'>
    <ul class='jcarousel-skin-tango posts' id='mycarousel'>
    <b:include data='data' name='interval'/>
    </ul>
    </div>
    </div>
    <b:include name='quickedit'/>
    </div>
    </b:includable>
    </b:widget>

  • Preview the template

  • If all looks well, you can save your template. You might get prompted to confirm that BlogArchive1 will be deleted. Allow it (we changed it's name to "BlogArchiveCarousel")

Tuesday, December 18, 2007

MySQL 5.1 Clustering Might Just Actually Work

As I previously wrote mysql 5.0 clustering was a big issue for us since all data as placed in memory. It seems that mysql 5.1 clustering is going to be much better, including the ability to store non-index columns on disk (indexes and indexed columns are still stored in-memory), do (limited) cluster-to-cluster replication, and better varchar support for memory columns. Pitty it's only release candidate at the moment. can't wait for the GA to come out.

Monday, December 17, 2007

Tomcat java.net.BindException: Cannot assign requested address

I had a very strange error today when I tried to startup tomcat on some linux box that used to work. Since google was no help I figured I should document this somewhere.

Tomcat startup gave the notorious java.net.BindException: Cannot assign requested address. This usually means that another process is listening on the same port on this machine. I started with ps -ef grep java to make sure that no other tomcat process was running on the machine. Nothing.

I suspected that maybe some other web server was holding the port, but netstat -an showed that nothing binds this address. Moreover, telnet localhost 80 showed that no one is listening.

Looking at the server.xml I found out that the connector was binding to the hostname "demoserver" on port 80.

<Connector className="org.apache.coyote.tomcat4.CoyoteConnector"
address="demoserver" port="80"
minProcessors="5" maxProcessors="75"
enableLookups="true" redirectPort="8443"
acceptCount="100" debug="0" connectionTimeout="20000"
useURIValidationHack="false" disableUploadTimeout="true" />

trying to ping demoserver gave me errors, but nslookup demoserver gave me the right ip address.

After a few minutes I noticed that some clown added demoserver to /etc/hosts with the wrong ip address. Fixing /etc/hosts to have the right ip address for demoserver made tomcat work smooth and nice.

Sunday, December 9, 2007

PHP Allowed memory size of 8388608 bytes exhausted

If you try to install PHP PECL package and get an "Allowed memory size of 8388608 bytes exhausted" you should know that pecl ignores php.ini memory_limit directive. As suggested in
this post, you should use pear instead of pecl to install you package. For example, instead of doing

[root@hostname tmp]# pecl -v install APC

you should do

[root@hostname tmp]# pecl -v download APC
[root@hostname tmp]# pear -v install APC-3.0.15.tgz