Search

Friends

Atomspheric CO2 (PPM)

Archives

Blather

Uptime verified by Wormly.com

12 March 2013

Integrating Hero Framework accounts with Vanilla Forum using jsConnect

This is something of a hack, but it is pretty quick and easy. I've never used Smarty before, but it's pretty flexible (and slightly evil).

I put this in a Hero template called authenticate.thtml and mapped it to /authenticate. I installed the jsConnect module for Vanilla, set the secret and it was basically done. Seems to work for regular and embedded forums.

{strip}
{assign var=secret value='985d2f9eb57a8b55db3c04c20272bce9308764b0'}
{assign var=client_id value=$smarty.get.client_id}
{assign var=callback value=$smarty.get.callback}

{if $logged_in}
  {assign var=member value=['uniqueid'=>$member.id,'name'=>$member.first_name|cat:' '|cat:$member.last_name, 'email'=>$member.email, 'roles'=>'member']}
  {assign var=empty value=ksort($member)}

  {$member['signature'] = $member|@http_build_query|cat:$secret|@sha1}

  {$member['client_id'] = $client_id}
{else}
  {assign var=member value=['name'=>'', 'photourl'=>'']}
{/if}

{$callback}({$member|@json_encode})
{/strip}

25 September 2011

jQuery DOM Loaded Shortcut

Normally web folks suggest loading Javascript at the bottom of the page, but with something like jQuery it's quite handy to be able to use stuff like $(function() { $('#node').show(); } inline in your pages. It also seems like jQuery ends up being the biggest/slowest critical component on many pages, so waiting for the page to load to doing something often really means waiting for jQuery to load to do something.

So I wrote a small script that performs a tiny, tiny piece of jQuery functionality but allows you to happily load jQuery at the bottom of the page. In my tests it doesn't seem to have any impact on the time deferred stuff takes to fire, but it reduces time taken to display content by at least 200ms. It's not totally beautiful but it's alright. And it wouldn't be that hard I think to emulate all the traditional jQuery ways of deferring execution, so you wouldn't have to change any existing code.

<script>
var $_={
  _callbacks:new Array,
  ready:function(a){this._callbacks.push(a)},
  runDeferred:function(){jQuery.each(this._callbacks,function(a,b){b.call(document,jQuery)})}
}
var $=function(a){$_.ready(a)};

$(function($) {
    $('#elem').hide();
});
</script>

<body>
Page content
...

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script> jQuery(function() { $_.runDeferred() }); // At this point our temporary $() is gone anyway </script>
</body>

This is a simple alternative. You get a simple mechanism for including deferred behaviour inline. It will execute just as fast as it would with regular jQuery call. And you'll save around 200ms on each page load and frequently more. Or at least your content will show up faster. Even when jQuery is totally cached and there's no network operations at all, on my old system it looks like just running the 233kb of uncompressed Javascript that is jQuery 1.6.4 takes about 180ms. That's a delay for content displaying content that really doesn't seem necessary, since while the content is loading you're rarely using jQuery for anything more than deferred behaviour handling.

5 August 2011

Vertical centering of cropped image with jQuery

You can use HTML, CSS and jQuery to vertically center cropped images that you don't know the height of. It's a shame to use jQuery at all, but I think it's necessary. I looked at the CSS clip property and at negative proportional margins (margin-top: -50%; etc.), but unless you know the height of the image I don't think it will work.

<div style="height:100px;overflow:hidden;">
    <img id="crop" src="blah.jpg" style="height:200px;" />
</div>

<script type="text/javascript">
jQuery(document).ready(function($) {
    var image = $("#crop");
    image.css('marginTop', (-(image.height() - image.parent().height()) / 2) + "px");
});
</script>

20 September 2009

Wrap Long URLs with jQuery

This doesn't seem to exist on the internet, so I wrote it. It's not super great, but does the job.

$(document).ready(function () {
  $("a").each(function () {
    var t = $(this).text();
    if(t.length > 30) {
      $(this).text(t.replace(/\./g,". ").replace(/\//g, "/ "));
    }
  });
});

29 August 2008

Waiting cursor during Prototype’s Ajax.Request

In your stylesheet:

body.waiting {
  cursor: wait;
}

In your script:

document.body.addClassName('waiting');
new Ajax.Request(uri, {
  onComplete: function() {
    document.body.removeClassName('waiting');
  }
});

You probably want to be careful to make sure it's in the onComplete method and not the onSuccess method. Even better might be to create a setTimeout("document.body.removeClassName('waiting')", 3000), so you don't break the cursor for the rest of the page visit.

You also might prefer the "progress" instead of the "waiting" cursor. For other cursors and their compatibility check out QuirksMode.

9 July 2008

Unobtrusive Javascript

I've been reading a little about UJS lately, trying to figure out a nice way of building some AJAX back into the Rails project I'm working on. I had a look at the UJS plugin and tried out the Low Pro. But I'm not sure I'm convinced. PPK suggests that Javascript is to behaviour as CSS is to styling, but I disagree. CSS tends to apply to many elements in a site. Javascript is more likely to be specific to a page. Most of the benefit of CSS comes from classes and being apply to apply the same style to many things at once. It makes sense to keep something like that separate.

The is the "wrong" way to do it:

<a href="/event/new" onlick="AJAX.Request(...);return false;">Create event</a>

And this is the "right" way:

<a href="/event/new" id="create_event_link">Create event</a>
<script type="text/javascript">
//<![CDATA[
Event.addBehaviour({ '#create_event_link': Remote.Link }); // attach event listener to link
//]]>
</script>

Which is pretty verbose, and to truly do it properly you're meant to put that second block in a separate file. In a Rails application, that's going to be somewhere in public/javascripts/ which feels very much like the wrong place to put this sort of logic. The second solution will also break if the link is created dynamically after the page has loaded.

An event delegation solution might solve this particular problem. You could catch all links with the class "remote" for instance, and treat them as AJAX links. But it wouldn't be very configurable. Configurability isn't a big issue for CSS, but I think is an issue for Javascript.

I certainly understand the appeal of UJS, but I don't think the parallel between styling and behaviours is convincing. And for trivial behaviours like this I don't think duplication of code is a serious problem, either for download size or for maintenability.

0.929 seconds