Filtered by JavaScript, Python

Page 40

Reset

input/textarea switcher with jQuery

January 11, 2008
2 comments JavaScript

Here's a very early version of a solution to a problem where you have an input box want to give the user the option to expand the box to a textarea if they want to enter more stuff such as multiple line content. Your implementation, when you attempt the same thing, might be differently but feel free to copy this as a good start for your own projects. The demo show how it works.

What was important for me in doing this was that I didn't want to get close to the XHTML at all since (in this particular case) it was generated from a widget mechanism and I wanted the expanding option a luxury only for those who bother with the full Javascript. The key solution for me was the ability to replace elements in the DOM tree and copy the attributes when going from input to textarea or the other way around.

Feedback welcomed. Bare in mind that this was a quick first attempt and that I haven't tested this on IE.

jQuery and Highslide JS

January 8, 2008
5 comments JavaScript

If you use the wonderful Javascript library jQuery and the wonderful (standalone) Javascript plugin Highslide JS of recent version you should be aware of something.

As of recent versions of Highlide the way the Expander function works is that it looks at an element's onclick attribute and not it's attached events which means that if a DOM element has the event but not the attribute you get a Javascript error. In older versions of Highslide you were able to do this:


$('a.highslide').click(function() {
   return hs.expand(this, options);
});

But that's no longer working since the attribute isn't set. Here's the new way of doing it:


$('a.highslide').each(function() {
   this.onclick = function() {
     return hs.expand(this, options);
   };
});

String comparison function in Python (alpha)

December 22, 2007
7 comments Python

I was working on a unittest which when it failed would say "this string != that string" and because some of these strings were very long (output of a HTML lib I wrote which spits out snippets of HTML code) it became hard to spot how they were different. So I decided to override the usual self.assertEqual(str1, str2) in Python's unittest class instance with this little baby:


def assertEqualLongString(a, b):
   NOT, POINT = '-', '*'
   if a != b:
       print a
       o = ''
       for i, e in enumerate(a):
           try:
               if e != b[i]:
                   o += POINT
               else:
                   o += NOT
           except IndexError:
               o += '*'

       o += NOT * (len(a)-len(o))
       if len(b) > len(a):
           o += POINT* (len(b)-len(a))

       print o
       print b

       raise AssertionError, '(see string comparison above)'

It's far from perfect and doesn't really work when you've got Unicode characters that the terminal you use can't print properly. It might not look great on strings that are really really long but I'm sure that's something that can be solved too. After all, this is just a quick hack that helped me spot that the difference between one snippet and another was that one produced <br/> and the other produced <br />. Below are some examples of this utility function in action.

Truncated! Read the rest by clicking the link below.

isArithmeticExpression() in Javascript

December 19, 2007
0 comments JavaScript

Following from some work that I blogged about two days ago (Calculator in Python for dummies) I've now extended the functionality thinking into the AJAX scripts that sit on top of this Python server-side functionality. How this was implemented is boring but the following function helped me a lot. Here's the code with a very basic unit test after:


function isArithmeticExpression(s) {
  return /[\d]\s*\+\s*[\d]|[\d]\s*\-\s*[\d]|[\d]\s*\/\s*[\d]|[\d]\s*\*\s*[\d]|[\d]\s*\^\s*[\d]/.test(s) &amp;&amp;
        s.split(/\)/).length == s.split(/\(/).length &amp;&amp;
        !/[A-Za-z_]/.test(s);
}

function assert(fact) {
  if (!fact) alert("Assert failure!");
}
assert(isArithmeticExpression('') == false);
assert(isArithmeticExpression('++123') == false);
assert(isArithmeticExpression('+123') == false);
assert(isArithmeticExpression('2+123') == true);
assert(isArithmeticExpression('2 + 123') == true);
assert(isArithmeticExpression('2 + - 123') == false);
assert(isArithmeticExpression('2 + 123') == true);
assert(isArithmeticExpression('(2 + 123)') == true);
assert(isArithmeticExpression('2^6') == true);
assert(isArithmeticExpression('(2+1))^6') == false);
assert(isArithmeticExpression('a+123') == false);
assert(isArithmeticExpression('1a1+2x3') == false);

Basically, it returns true if the string appears to contain only numbers and one of the expected operators +, -, *, / or ^ in between two numbers.

It's far from perfect. I can think of cases where it will actually fail. But those cases are very rare and are too unlikely to happy and cause a major problem in this application and I'd rather get on with it than to spend any more time on this. After all, this is just a Javascript that tries to help if it can. The server-side code needs to "perfect" and if someone enters a weird expression, the server-side error handling will at least pick it up.

Calculator in Python for dummies

December 17, 2007
17 comments Python

I need a mini calculator in my web app so that people can enter basic mathematical expressions instead of having to work it out themselfs and then enter the result in the input box. I want them to be able to enter "3*2" or "110/3" without having to do the math first. I want this to work like a pocket calculator such that 110/3 returns a 36.6666666667 and not 36 like pure Python arithmetic would. Here's the solution which works but works like Python:


def safe_eval(expr, symbols={}):
   return eval(expr, dict(__builtins__=None), symbols)

def calc(expr):
   return safe_eval(expr, vars(math))

assert calc('3*2')==6
assert calc('12.12 + 3.75 - 10*0.5')==10.87
assert calc('110/3')==36

Truncated! Read the rest by clicking the link below.

WSSE Authentication and Apache

December 13, 2007
1 comment Python

I recently wrote a Grok application that implements a REST API for Atom Publishing so that I can connect a website I have via my new Nokia phone has LifeBlog which uses the Atom API to talk to the server.

Anyway, the authentication on Atom is WSSE (good introduction article) which basically works like this:


PasswordDigest = Base64 \ (SHA1 (Nonce + CreationTimestamp + Password))

This is one of the pieces in a request header called Authorization which can look something like this:


Authorization: WSSE profile="UsernameToken"
X-WSSE: UsernameToken Username="bob", PasswordDigest="quR/EWLAV4xLf9Zqyw4pDmfV9OY=", 
Nonce="d36e316282959a9ed4c89851497a717f", Created="2003-12-15T14:43:07Z"

What I did was I wrote a simple Python script to mimic what the Nokia does but from a script. The script creates a password digest using these python modules: sha, binascii and base64 and then fires off a POST request. Here's thing, if you generate this header with base64.encodestring(ascii_string) you get something like this:


quR/EWLAV4xLf9Zqyw4pDmfV9OY=\n

Notice the extra newline character at the end of the base64 encoded string. This is perfectly valid and is decoded easily with base64.decodestring(base64_string) by the Grok app. Everything was working fine when I tried posting to http://localhost:8080/++rest++atompub/snapatom and my application successfully authenticated the dummy user. I was happy.

Then I set this up properly on atom.someotherdomain.com which was managed by Apache who internally rewrote the URL to a Grok on localhost:8080. The problem now was that the Authentication header value was broken into two lines because of the newline character and then the whole request was rejected by Apache because some header values came without a : semi-colon.

The solution was to not use base64.encodestring() and base64.decodestring() but to instead use base64.urlsafe_b64encode() and base64.urlsafe_b64decode(). Let me show you:


>>> import base64
>>> x = 'Peter'
>>> base64.encodestring(x)
'UGV0ZXI=\n'
>>> base64.urlsafe_b64encode(x)
'UGV0ZXI='
>>> base64.decodestring(base64.urlsafe_b64encode(x))
'Peter'

If you're still reading, then hopefully you won't make the same mistake as I did and wasting time on trying to debug Apache. The lesson learned from this is to use the URL safe base64 header values and not the usual ones.

geopy distance calculation pitfall

December 10, 2007
1 comment Python

Geopy is a great little Python library for working with geocoding and distances using various online services such as Google's geocoder API.

Today I spent nearly half an hour trying to debug what was going on with my web application since I was getting this strange error:


AttributeError: 'VincentyDistance' object has no attribute '_kilometers'

Truncated! Read the rest by clicking the link below.

Note to self about Jeditable

November 22, 2007
0 comments JavaScript

I've been struggling hard this morning to get Jeditable to work in IE (6 and 7). Whilst everything was working perfectly fine in Firefox, in IE the clickable editable text would just disappear and never return. The solution was to use the latest jQuery 1.2.1. I was using version 1.1.4 which was why it didn't work.

Jeditable is a brilliant plugin with really good configuration options (hint read the source code's documentation comment) and I'll now send an email to Mika about this pitfall and suggest that he includes it in his documentation.

Spellcorrector 0.2

September 24, 2007
3 comments Python

Unlike previous incarnations of Spellcorrector not it does not by default load the two huge language files for English and Swedish. Alternatively/additionally you can load your own language file. The difference between loading a language file and training on your own words is that trained words are always assumed to be correct.

Another major change with this release is that a pickle file is created once the language file or own training file has been parsed once. This works like a cache, if the original text file changes, the pickle file is recreated. The outcome of this is that the first time you create a Spellcorrector instance it takes a few seconds if the language files is large but on the second time it takes virtually no time at all.

Truncated! Read the rest by clicking the link below.

Vertically expanding textarea input boxes

September 19, 2007
0 comments JavaScript

I've recently improved the IssueTrackerProduct so that when you start to write in the little textarea it expands and grows vertically as the text gets larger and larger. Other sites like Highrise do this too for note taking.

Long story short, here's the demo and here's the solution:


function _getNoLines(element) {
  var hardlines = element.value.split('\n');
  var total = hardlines.length;
  for (var i=0, len=hardlines.length; i<len; i++) {
     total += Math.max(Math.round(hardlines[i].length / element.cols), 1) - 1;
  }
  return total;
}

$(function() {

  // First, for all the textareas that have lots of lines of text 
  // in them, we want to double their number of rows
  $('textarea.autoexpanding').each(function() {
     while (_getNoLines(this) > parseInt(this.rows))
       this.rows = '' + Math.round((parseInt(this.rows) * 1.5));
  });

  // When a user enters new lines, if they have entered more
  // lines than the textarea has rows, then double the textareas rows
  $('textarea.autoexpanding').bind('keyup', function() {
     if (_getNoLines(this) > parseInt(this.rows))
       this.rows = '' + Math.round((parseInt(this.rows) * 1.5));
  });

}

Truncated! Read the rest by clicking the link below.