// ref: http://rubyforge.org/pipermail/mongrel-users/2007-July/003747.html // ry dahl // Don't Poll. Pull! // version 0.1 Ajax.Pull = Class.create(); Ajax.Pull.prototype = Object.extend(Ajax.Request.prototype, { initialize: function(url, options) { this.handler = options.handler; this.frequency = options.frequency || 0.5; options['method'] = options['method'] || 'get'; this.setOptions(options); this.transport = Ajax.getTransport(); this.request(url); this.startPuller(); }, startPuller: function() { this.pullPointer = 0; this.puller = new PeriodicalExecuter(this.pull.bind(this), this.frequency); }, pull: function() { if(this.transport.readyState < 3) { return; // not receiving yet } else if (this._complete) { this.puller.stop(); // this is our last pull } var slice = this.transport.responseText.slice(this.pullPointer); (this.options.pullDebugger || Prototype.emptyFunction)( 'slice: ' + slice + ''); slice.extractJSON().each((function(statement) { (this.options.pullDebugger || Prototype.emptyFunction)( 'extracted statement: ' + statement + ''); this.handler(eval( '(' + statement + ')' )); this.pullPointer += statement.length + 1; }).bind(this)); }, }); Object.extend(String.prototype, { extractJSON: function() { var insideString = false; var sBrackets = cBrackets = parens = 0; var statements = new Array(); var start = i = 0; for(i = 0; i < this.length; i++) { if( cBrackets < 0 || sBrackets < 0 || parens < 0 ) { // raise syntax error? } if(insideString) { switch(this[i]) { case '\\': i++; break; case '"': insideString = false; break; } } else { switch(this[i]) { case '"': insideString = true; break; case '{': cBrackets++; break; case '}': cBrackets--; break; case '[': sBrackets++; break; case ']': sBrackets--; break; case '(': parens++; break; case ')': parens++; break; case ';': if(cBrackets == 0 && sBrackets == 0 && parens == 0) { statements.push(this.slice(start, i)); start = i+1; } } } // if the last statement doesn't have a semicolon, it's okay // if(i != start && cBrackets == 0 && sBrackets == 0 && parens == 0) // statements.push(this.slice(start)); } return statements; } });