Posts Tagged ‘jQuery’

Cross-Domain with Sinatra / Rack and JSONP

Thursday, March 25th, 2010

There are several situations one might want to do cross-domain (/cross-site) AJAX-requests. Probably you experience the security borders of modern browsers very fast.
JSONP is a hack for JSON that provides a great workaround. It means sending a callback with the URL (eg. ?callback=sampleFunction). Server-sided we setup our application to respond with a JSON body wrapped in a function named like our callback function. In this case

sampleFunction({
  "ourData": [{
    "title": "is an array"
  },
    "title": "..."
  }]   
})

What we have to do (Sample)

Frontend
JS-Frameworks like jQuery are smart enough to send such requests with ease. Lets write a simple function with jQuery:

$.ajax({
  type: 'get',
  url: 'file.json',
  dataType: 'jsonp',
  success: function(data) {
    doSomethingWith(data);
  }
})

Let’s see how to setup the server:
Using Ruby and Rack it becomes very simple to beautifully provide regular JSON for non-JSONP clients and JSONP for jQuery & Co.
Simply use the rack middleware rack-contrib by Ryan Tomayko

gem install rack-rack-contrib --source=http://gems.github.com/

If you’re using pure rack, put this in your config.ru

require 'rack/contrib/jsonp'
use Rack::JSONP

Using Sinatra, I’d put it somewhere with my config files.
Let’s see how a sample Sinatra application could look like:

require 'sinatra'
require 'json'
require 'rack/contrib/jsonp'
 
use Rack::JSONP
 
before do
  content_type :json
end
 
get '/posts' do
  Posts.find.to_a.to_json
end

That simple, this powerful.

select any HTML text in element with jQuery

Thursday, November 19th, 2009

The following script jQuery extension selects any text from a given jQuery selector. Tested with Firefox and Safari – should work in IE6+ as well.

jQuery.fn.extend({
  selectText: function() {
    var text = $(this)[0];
    if ($.browser.msie) {
      var range = document.body.createTextRange();
      range.moveToElementText(text);
      range.select();
    } else if ($.browser.mozilla || $.browser.opera) {
      var selection = window.getSelection();
      var range = document.createRange();
      range.selectNodeContents(text);
      selection.removeAllRanges();
      selection.addRange(range);
    } else if ($.browser.safari) {
      var selection = window.getSelection();
      selection.setBaseAndExtent(text, 0, text, 1);
    }
    return $(this);
  }
})

To use it simly do:

var shortSelector = $('#name').selectText();
var longSelector = $('ul#names li:contains("Hampel")').selectText();

written on top of Source and Source

jQuery and stopPropagation

Monday, January 12th, 2009

Often you might not even notice the following problem: Imagine you got a table row or a list element including several links. By default you defined a function like

$('table tr').click(function(event) {
  target = $(this).find('a:first').attr('href');
  open(target, '_self');
})

In this case the function finds the first defined link in our row and links it to the row itself.
If we click on the link, we get redirected to the defined target. But as the link is lying in our linked row, this click will also be executed and our target is loaded twice. Even though the user won’t notice it, functions like deleting or answering will throw errors.
jQuery got a very nice core function to suppress the second loading.

stopPropagation()

We are using this function to stop the propagation of our click-event like shown:

$('table tr').click(function(event) {
  target = $(this).find('a:first').attr('href');
  open(target, '_self');
})
$('table tr a').click(function(event) {
  event.stopPropagation();
})

It reminds me of a “return false;”. Just look for the bind function here:
jQuery API Browser. There you may find more details on similiar cases, too.

UPDATE for Internet Explorer

As this won’t work in MS’ IE, you have to use the similar

event.cancelBubble = true;

(Source)

If you put both behind each other, IE would still throw some errors. So you should try following if-function if you are using jQuery:

    agent = jQuery.browser;
	if(agent.msie) {
		event.cancelBubble = true;
	} else {
		event.stopPropagation();
	}