/ 05.mar.2009
Scriptet jag bloggade om tidigare är nu klart och jag kallar det spent-per-day. Jag har använt mig av Gruff för att generera graferna och slutresultatet blev rätt stiligt.
Det ligger självklart på GitHub.
Genererar grafer utifrån datat på översiktssidan på swedbank.se
/ 27.feb.2009
YQL gör det möjligt att hämta data från en mängd olika källor med ett SQL-liknande frågespråk. Man kan även använda det för sina egna applikationer.
A “mediator service” that enables developers to query, filter, and combine data across Yahoo! and beyond.
SELECT url,title,abstract FROM search.web WHERE query="pizza" |
1 2 |
http://query.yahooapis.com/v1/public/yql?q=select%20url%2Ctitle%2Cabstract %20from%20search.web%20where%20query%3D%22pizza%22&format=json&callback=? |
Ersätt det avslutande frågetecknet med din callback-metod. Om du använder jQuery kommer den att sköta det åt dig.
Övningsuppgiften på gårdagens Athegatorsdag bestod i att man med data returnerat av en YQL sökning på Flickr samt jQuery skulle skapa ett bildgalleri.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Latest images tagged Athega</title> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"> </script> <script type="text/javascript"> // We don't want any conflicts jQuery.noConflict(); // SELECT * FROM flickr.photos.search // WHERE text='Athega' LIMIT 8 var query = 'http://query.yahooapis.com/v1/public/yql?q=' + 'select%20*%20from%20flickr.photos.search%20' + 'where%20text%3D%22Athega%22%20limit%208' + '&format=json&callback=?'; // Get the data (function($) { $.getJSON(query, function(yql) { $.each(yql.query.results.photo, function(index, photo) { // Build the url photo.url = 'http://farm' + photo.farm + '.static.flickr.com/' + photo.server + '/' + photo.id + '_' + photo.secret + '_s.jpg'; // Create and append the img to the #images div $('<img />').attr({ src: photo.url, title: photo.title }).appendTo('#images'); }); }); })(jQuery); </script> <style type="text/css"> #images { width: 300px; } </style> </head> <body> <div id="images"></div> </body> </html> |
/ 27.feb.2009
Ett open source JavaScript bibliotek som förenklar interaktionen mellan HTML och JavaScript.
jQuery är byggt runt CSS selektorer (CSS 1, 2 och 3) och sedan en tid använder man motorn Sizzler för att hantera de tunga lyften.
jQuery fyllde tre år den 14:e januari, version 1.3 släpptes samma dag.
$('div').addClass('special'); |
Den senaste versionen (1.3.2) släpptes den 20:e februari och den innehåller ett flertal prestandaförbättringar:
jQuery är tänkt att byggas ut med hjälp av plugins.
Att lägga på nya metoder:
jQuery('div').hideRemove(); |
Trivialt att implementera:
1 2 3 4 5 |
jQuery.fn.hideRemove = function(speed) { return this.hide(speed, function() { jQuery(this).remove(); }); }; |
Exempel på plugins:
Mer information http://plugins.jquery.com/
Till skillnad från många andra JavaScript ramverk så är utvecklarna av jQuery måna om att inte skräpa ner i det globala namnutrymmet. Man behöver inte ens exponera $-metoden om man inte vill.
1 2 3 4 5 |
jQuery.noConflict();
jQuery(document).ready(function(){
// Din egen kod
}); |
Man kan dock fortfarande använda sig av $ om man skickar in jQuery i en anonym metod.
(function($) { /* Kod som använder sig av $ */ })(jQuery) |
Mer information http://docs.jquery.com/Using_jQuery_with_Other_Libraries
1 2 3 4 5 |
jQuery('div#intro h2'); jQuery('div.section > p'); jQuery('input:radio'); $('div#intro h2'); |
$('div.section'); // returnerar en kollektion |
1 2 3 4 5 |
$('div.section').size(); // Antal element som matchades av selektorn $('div.section').each(function(div) { // Manipulation av div elementet }); |
De flesta jQuery metoderna opererar på alla matchade element i en kollektion.
1 2 3 4 |
$('div.section').addClass('highlighted'); $('img.photo').attr('src', '/default.png'); $('a.foo').html('<em>Click me now!</em>'); $('p:odd').css('background-color', '#ccc'); |
Några metoder returnerar värdet på det först matchade elementet.
1 2 3 |
var height = $('div#intro').height(); var src = $('img.photo').attr('src'); var lastP = $('p:last').html(); |
jQuery tillhandahåller förbättrade metoder för att traversera DOM:en.
1 2 3 4 5 |
$('div.section').next(); $('div.section').prev(); $('div.section').prev('a'); $('div.section').parent(); $('div.section').parents(); |
jQuery tillhandahåller metoder för att tilldela event handlers.
1 2 3 4 |
$('a').click(function(ev) { $(this).css({backgroundColor:'orange'}); ev.preventDefault(); }); |
1 2 3 4 5 |
$(document).ready(function() { alert('The DOM is ready!'); }); $(function() { alert('This is a shortcut') }); |
Mer information http://en.wikipedia.org/wiki/Unobtrusive_JavaScript
Alla jQuery metoder returnerar ett nytt jQuery objekt, detta gör att man kan kedja ihop metoderna efter varandra.
$('h1').fadeOut().addClass('highlight').fadeIn(); |
jQuery har bra stöd för Ajax och Ajax-liknande funktionalitet som JSONP.
$('div#intro').load('/some/file.html'); |
Några mer avancerade metoder:
1 2 3 4 |
$.get(url, params, callback); $.post(url, params, callback); $.getJSON(url, params, callback); $.getScript(url, callback); |
Microsoft har beslutat att skeppa stöd för jQuery i kommande versioner av Visual Studio. Detta inkluderar officiellt stöd för jQuery Intellisense.
Nokia har meddelat att de kommer att använda jQuery i sin WebKit-baserade Web Run-Time
Mer information http://blog.jquery.com/2008/09/28/jquery-microsoft-nokia/
Google tillhandahåller ett CDN för ett flertal olika ramverk, jQuery är ett av dem.
Mer information http://code.google.com/apis/ajaxlibs/
API Dokumentationen för jQuery hittar man på http://api.jquery.com/ där man även kan installera en AIR-version.
John Resig’s presentation Learning jQuery @ MIT
/ 18.okt.2008
Den här gången handlar det om CSS och HTML.
För ett tag sedan skulle jag använda ett stylesheet för mobila enheter genom media="handheld". Det fungerade såklart inte alls i Opera Mini 4.1, men jag tänkte inte så mycket mer på det utan löste det på annat sätt. Nu har jag tagit reda på orsaken, och den kallas CSS3 Media Queries.
Med dessa “queries” kan man definiera css-regler som appliceras baserat på vad enheten man använder sig av klarar av. I mitt exempel så har jag en regel som bara appliceras på enheter med en skärm som är mindre än 481 pixlar bred. (Av en ren händelse så har iPhone en 480px bred skärm)
1 2 3 4 5 6 7 8 9 10 11 12 |
@media screen and (max-width: 480px) { * { position: static !important; background-image: none !important; margin-left: 0 !important; padding: 0 !important; margin-bottom: 0 !important; } /* Resten av reglerna för mobila enheter */ } |
Opera rekomenderar dock att man även i fortsättningen använder sig av ett stylesheet med media="handheld" för de enheter som ännu inte stödjer CSS3 Media Queries.
Enligt mig en av världens bästa webbdesigners, Dan Cederholm har skrivit en liten post om att välja den bästa tillgängliga ampersanden.
Kortfattat så går det hela ut på att lägga till en class=”amp” runt alla &-tecken.
Gott <span class="amp">&</span> Blandat |
1 2 3 4 |
span.amp {
font-family: Baskerville, Palatino, Constantia, serif;
font-style: italic;
} |
Gott & Blandat
Gott & Blandat
(Ingen skillnad? Då har din RSS-läsare troligtvis strippat bort style taggen)
För att automatisera detta kan man använda sig av Typogrify (Django) eller MarkDown+SmartyPants (Finns till de flesta publiceringssystem).
Mikroformat är standarder, baserade ovanpå HTML eller XHTML. Mikroformat är en utökad semantik, som åstadkommer i (X)HTML möjligheten att märka upp information, som annars man hade behövt en annan teknik till, såsom RDF eller någon annan tillämpning av XML. Mikroformat är alltså inte en utvidgning av befintlig (X)HTML, som HTML5, utan man använder endast befintliga taggar och attribut. [Wikipedia]
Ett mikroformat jag använder mig av är hCard vilket är en 1:1 representation av vCard.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
<div class="vcard" id="hcard-Peter-Hellberg"> <img class="photo" alt="" src="http://c7.se/images/peter_small.jpg"/> <div class="fn n"> <span class="given-name">Peter</span> <span class="family-name">Hellberg</span> </div> <div> <span class="role">System Developer</span>, <a href="http://c7.se/" class="org url">Code7 Interactive</a> <div> <h3>Email <span class="amp">&</span> Jabber</h3> <p> <a href="mailto:peter@c7.se" class="email jabber">peter@c7.se</a> </p> <h3>Address</h3> <div class="adr"> <div class="street-address">Mosstenabacken 1</div> <div> <span class="postal-code">124 32</span> <span class="locality">Bandhagen</span> </div> <span class="region">Stockholm</span>, <span class="country-name">Sweden</span> </div> </div> |
Med hjälp av biblioteket mofo kan jag nu hämta följande data:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
>> peter = hCard.find 'http://c7.se/contact' => #<HCard:0x1141e90 @role="System Developer", @url="http://c7.se/", @base_url="http://c7.se", @org="Code7 Interactive", @n=#<OpenStruct family_name="Hellberg", given_name="Peter">, @properties=["org", "email", "fn", "url", "photo", "n", "role", "adr"], @photo="http://c7.se/images/peter_small.jpg", @adr=#<Adr:0x1167438 @country_name="Sweden", @base_url="http://c7.se", @region="Stockholm", @properties=[ "street_address", "locality", "region", "country_name", "postal_code" ], @locality="Bandhagen", @postal_code="124 32", @street_address="Mosstenabacken 1">, @fn="Peter Hellberg", @email="peter@c7.se"> |
/ 23.sep.2008
Spree (GitHub) är en komplett lösning för ehandel skriven i Rails. Den är distribuerad som en gem (Vilket även Axept kommer att vara när det släpps).
Precis som det låter, 30 tutorials för Mootools 1.2 hittar du på http://www.consideropen.com/blog/category/mootools-12/ (Dag 21 nu..)
Jag har använt tjänsten time.onrails.org - Time tracking made simple. hela sommaren och den har verkligen levt upp till sitt namn, smidigt att lägga till nya uppdrag, sektioner (veckor/månader/etc) och framförallt att lägga in timmarna. Nu har den precis blivit ännu bättre genom att de lagt till stöd för fakturering genom Blinksale. Mitt arbetsflöde är nu att använda time.onrails.org först och sen i slutet av månaden fylla i Journyx.
Jag har sedan länge hållt ett öga på Andy Clarke’s privata hemsida And All That Malarkey som sedemera mynnade ut i Stuff and Nonsense. Nu har han tagit och dragit igång For A Beautiful Web som är en samling workshops med titlar som:
Det finns även några riktiga godbitar i den tillhörande bloggen, till exempel Time to stop showing clients static design visuals.
När jag ska färgsätta något så brukar jag för det mesta besöka colourlovers.com där det finns topplistor på färger och även hela paletter med färger som passar (mer eller mindre) bra ihop. Rekomenderas.
Det händer rätt ofta att jag använder ikonerna Silk av Mark James (Twitter), enda problemet är att det är så många ikoner (1000 stycken nu) att det blir svårt att hitta rätt.
En gammal klasskompis (Twitter) har dock löst detta problem genom att utveckla FamFamFam Icon Browser
/ 22.sep.2008
Paperclip (GitHub) är ett plugin till ActiveRecord som gör det enkelt att använda filer som vilka andra attribut som helst. Inga extra tabeller i databasen. Det enda som krävs är att man har installerat ett bibliotek för bildbehandling.
1 2 3 4 5 |
class User < ActiveRecord::Base has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" } end |
1 2 3 |
def create @user = User.create( params[:user] ) end |
1 2 3 |
form_for :user, :html => { :multipart => true } do |form| form.file_field :avatar end |
image_tag @user.avatar.url(:thumb) |
scoped_search (GitHub) är en gem som gör det trivialt att söka i sina modeller utan att kräva en indexeringslösning som Thinking Sphinx.
1 2 3 |
class Project < ActiveRecord::Base searchable_on :name, :description end |
Project.search_for(params[:q]).each { |project| ... } |
/ 18.sep.2008

Fotograf: G. Taylor McKnight
Panda (GitHub) är en Merbapplikation som hanterar uppladdning, encoding och streaming av video utvecklad av New Bamboo
Ribs (GitHub) är ett JRuby ORM som gör det möjligt att persistera rubyobjekt med Hibernate utvecklat av Ola Bini.
Bort (GitHub) har nu släppts i version 0.2. Bort är en förkonfigurerad Railsapplikation med flera av de mest använda plugins redan installerade.
Hyperactive Resource (GitHub) är en utbyggnad till ActiveResource som lägger till många ActiveRecord-lika funktioner vilket underlättar för att göra “drop in” ersättningar av existerande ActiveRecord modeller. Den inkluderar dynamiska finders, validering på klientsidan, hooks vid validering och persistering samt mycket mer.
Shoulda (GitHub) gör det enkelt att skriva eleganta, lättförstådda och underhållningsbara test. Shoulda består av testmakron, assertions och hjälpmetoder som lagts till ramverket Test::Unit. Det är helt kompatibelt med redan existerande testfall. Bara att börja använda.
Ruby-Processing (GitHub) är en JRuby wrapper för ramverket Processing. Viss inspiration är hämtad från NodeBox.
Ny och fräsch dokumentation på http://guides.rails.info
/ 07.aug.2008
Mitt första projekt paketerat som en gem är nu släppt på GitHub, det kallas “Personnummer” och inte helt oväntat hanterar det Svenska personnummer.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Gem::Specification.new do |s| s.name = "personnummer" s.version = "0.0.1" s.date = "2008-08-06" s.summary = "Personnummer handles validation of Swedish personal id..." s.description = "Personnummer handles validation of Swedish person..." s.has_rdoc = false s.email = "peter@c7.se" s.homepage = "http://c7.se/code/personnummer" s.authors = ["Peter Hellberg"] s.files = ["README.markdown", "Changelog", "LICENSE", "demo.rb", "lib/personnummer.rb"] end |
Lägg till GitHub i source listan (Behöver bara göras en gång)
gem sources -a http://gems.github.com |
Installera, som vanligt på GitHub är namnet prefixat med användarnamn (c7)
sudo gem install c7-personnummer |
1 2 3 4 5 6 7 8 9 |
require 'rubygems' require 'personnummer' p = Personnummer.new('830428-5912') if p.valid? designation = (p.male?) ? 'He' : 'She' puts "#{designation} was born in #{p.region}" end |
Vilket kommer att returnera:
He was born in Skaraborgs län |
/ 04.aug.2008
Prawn är ett nytt PDF bibliotek helt skrivet i Ruby. Utgångspunkterna har varit att det ska vara enkelt att producera PDF filer och att tillhandahålla all funktionalitet man behöver utan att bli begravd i komplexitet.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Prawn::Document.generate("images.pdf", :page_layout => :landscape) do foo = "#{Prawn::BASEDIR}/data/images/foo.jpg" text "o hai" image foo text "flowing text" image foo, :position => :center text "beneath images" image foo, :position => :right text "again" image foo, :position => :left text "and again" image foo, :position => 50 end |
1 2 3 4 5 6 7 8 9 |
Prawn::Document.generate("multi.pdf", :page_layout => :landscape) do |pdf| pdf.text "This is on a landscaped page" pdf.start_new_page(:layout => :portrait) pdf.text "This is on a portrait page" pdf.start_new_page(:size => "LEGAL") pdf.text "This is on legal paper size" pdf.start_new_page(:left_margin => 150, :right_margin => 150) pdf.text "This page has very wide left and right margins" end |
Installera Prawn genom RubyGems med gem install prawn eller klona från git://github.com/sandal/prawn.git
/ 31.jul.2008
Idag släppte SUN sin förhandsversion av JavaFX SDK’n. Jag har ända sedan Chrilles presentation på sommarkonferensen varit lite sugen på att testa JavaFX och nu finns det en komplett utvecklingsmiljö i form av Netbeans 6.1 med stöd för JavaFX att ladda ner. Java 6 krävs för att det hela ska fungera.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
var weather1 = Weather{}; var f = Frame { stage: Stage { fill: Color.GREY content:[ Group { transform: Transform.translate(0,5); content: weather1 } ] } title: "Weather in Stockholm" closeAction: function() { System.exit(0); } resizable: false width: 255 height: 120 visible: true }; |
Om man bara vill leka runt lite med JavaFX så finns JavaFXPAD (Java Web Start) som är en testmiljö liknande Try Ruby! (som vi använde på en av mina genomgångar av Ruby). Man startar helt enkelt applikationen och kan skriva kod i ett textfält, koden körs direkt så man kan hela tiden se förändringar i den övre delen av fönstret.

/ 31.jul.2008
Adblock Plus i all ära men ibland vill man ändra själva utseendet på webbplatserna man besöker. Ett plugin som gör just detta är Greasemonkey vilket låter användaren skriva egna script för att skräddarsy sin surfning.
Jag ville dock bara lägga till lite css, detta kan man göra i filen userContent.css som under Mac OS X ska ligga i följande katalog:
~/Library/Application Support/Firefox/Profiles/[RANDOM].default/chrome/ |
1 2 3 4 5 6 |
/* Remove ads */
iframe[name=”google_ads_frame”],
div.profile_sidebar_ads,
div.social_ad,
div#sidebar_ads,
div.rs div.sponsor { display: none !important; } |
/ 24.jul.2008
Jag behövde en datumväljare till mitt nuvarande projekt och efter lite eftersökningar så hittade jag MooTools DatePicker men den fungerade inte helt till belåtenhet. Speciellt inte med version 1.2 av MooTools så jag såg till att uppdatera den.
Det visade sig vara enklare än väntat, jag ersatte bara följande rad:
else if (dp.container) dp.container.remove(); |
med
else if (dp.container) dp.container.destroy(); |
För att göra inputfältet skrivbart (för att kunna skicka tomma datum) så tog jag bort följande rad:
dp.setProperties({'id':dp.getProperty('name'), 'readonly':true}); |
/ 22.jul.2008
Ett “problem” jag haft med senare versioner av rake (efter version 0.8) är att beskrivningarna till varje task är trunkerade till 80 tecken, oavsett hur bred terminalen faktiskt är.
Efter en snabb googling fick jag fram en stilig lösning.
max_column = 80 - name.size - width - 7 |
ersätts med
max_column = cols - name.size - width - 7 |
och följande metoder läggs till
1 2 3 4 5 6 7 8 9 |
def cols unix? ? (%x{stty size 2>/dev/null}.split.collect { |x| x.to_i }[1]) : 80 rescue 80 end def unix? RUBY_PLATFORM =~ /(darwin|linux|(net|free|open)bsd|cygwin|solaris)/i end |
/ 26.jun.2008
Jag skulle testa olika deploymentlösningar och ville testa nginx i kombination med thin även om vi antagligen kommer att köra Phusion Passenger under Apache på grund av andra system skrivna i PHP.
Jag kollade runt lite hur man skulle konfigurera nginx och hittade Nginx, my new favorite front end for mongrel cluster..
Utvecklingsversionen (0.7.3) var en aning instabil så jag valde att installera 0.6.31 och använde följande config.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
user peter peter;
worker_processes 2;
error_log logs/error.log notice;
pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
# no sendfile on OSX uncomment
#this if your on linux or bsd
#sendfile on;
tcp_nopush on;
keepalive_timeout 65;
tcp_nodelay on;
upstream cluster {
server 127.0.0.1:5001;
server 127.0.0.1:5002;
}
gzip on;
gzip_min_length 1100;
gzip_buffers 4 8k;
gzip_types text/plain;
server {
listen 80;
#server_name localhost;
root /path/to/public;
access_log off;
rewrite_log on;
location ~ ^/$ {
if (-f /index.html){
rewrite (.*) /index.html last;
}
proxy_pass http://cluster;
}
location / {
if (!-f $request_filename.html) {
proxy_pass http://cluster;
}
rewrite (.*) $1.html last;
}
location ~ .html {
root /path/to/public;
}
location ~* ^.+\.(jpg|png|ico|css|zip|doc|xls|pdf|ppt|txt|js)$ {
root /path/to/public;
}
location / {
proxy_pass http://cluster;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
} |
Jag blev galet imponerad av hur snabbt nginx klarar att leverera statiskt innehåll (ungefär 7400 förfrågningar/s eller 5400 Kb/s) men dynamiskt innehåll var inga problem heller, en enkel vy levererades ungefär 380-400 förfrågningar/s vid 8 samtidiga anslutningar och 2000 förfrågningar.
Det ska bli intressant att testa mephisto då den cachear rätt hårt.
Allt detta på min Macbook Pro.
/ 27.maj.2008
Genom RubyFlow fick jag reda på att version 1.1.4 av testramverket RSpec släppte idag. Jag tog tillfället i akt att börja använda det i mitt nuvarande projekt.
Det finns även integration med min editor TextMate genom projektet rspec-tmbundle.
Jag råkade dock ut för lite trubbel då jag skulle köra igång testerna, det verkade inte som om rätt version av ruby kördes. Detta avhjälptes genom att editera PATH variabeln i environment.plist så att den ruby-binär jag ville använda hittades först.
$ mate ~/.MacOSX/environment.plist |
Loggade ut för att ladda om variablerna.
Jag skrev sedan följande spec för att testa så att allt fungerade som det skulle.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
require File.dirname(__FILE__) + '/../spec_helper' module CompanySpecHelper def valid_company_attributes { :name => 'Testföretag', :org_number => '123456-1234', :customer_number => 1 } end end describe Company do include CompanySpecHelper before(:each) do @company = Company.new @company.attributes = valid_company_attributes end it "should be valid with all attributes" do @company.should be_valid end it "should not be valid without a name" do @company.name = nil @company.should_not be_valid end end |
Och det fungerade!

Temat heter micro och är gjort av seaofclouds.
Det drivs med Mephisto under Ruby on Rails