Debugging Javascript

Posted by Anders Carlsen Fri, 12 Feb 2010 20:15:00 GMT

Jeg er blevet træt af at debugge med alert() Det er irriterende at skulle kikke ok hver gang, så nu har jeg lavet mit egen status meddelelsesvindue som jeg blot kan kalde med debug()

div elementet konstruerer jeg først dynamisk hvis det ikke findes i forvejen:
function MakeDebugElm()
{

    var elm = document.createElement("div");
    elm.id = "debug_element";
    elm.style.position = "absolute";
    elm.style.background = "#faa";
    elm.style.bottom = "0";
    elm.style.left = "10px";
    elm.style.size = "14px";
    elm.style.width = "90%";
    elm.style.height = "50px";
    elm.style.overflow = "auto";
    elm.style.zIndex = 5000;
    elm.hide = function() { this.style.display = "none"; };
    elm.show = function() { this.style.display = "block"; };
    elm.onclick = function() { this.style.display = "none"; };    
    var body = document.getElementsByTagName("body").item(0);
    body.appendChild(elm);
    return elm;
}

function debug(str)
{
    d = document.getElementById("debug_element")
    if( d == null)    
            d = MakeDebugElm();

    d.show();
    d.innerHTML = str + "<br />" + d.innerHTML;
}


Del

Posted in ,  | no comments

Logging af klik

Posted by Anders Carlsen Wed, 10 Feb 2010 19:18:00 GMT

Fornyligt fjernede jeg logging af klik på en hjemmeside for dels at få hurtigere og flere sidevisninger , dels for at højne min troværdighed i forhold til Google Bot.

Min gamle strategi

Jeg brugt en teknik hvor jeg ved hjælp af onclick function return false skjulte at når folk klikkede på et link først blev send til en controller som loggede klikket i database inden det blev vidresendt til den ønskede adresse. f.eks.

<a href="http://dr.dk" onclick="window.open('/links/goto/12') ; return false; >

Selvom Google skriver i deres information til webmastere at Google Bot ikke følger javascript, kunne jeg konstatere at det gør den faktisk. Dvs. Google registerede adressen links/goto og ikke dr.dk, hvilket ikke er særligt hensigtsmæssigt. Desuden koster en omdirigering ekstra tid for brugeren og ekstra resurcer på serveren, så jeg valgte at fjerne funktionen og finde en anden strategi.

Nye klik logging strategi

Så jeg tænkte, – hvordan gør Google det?

Ind på Google med Chrome, højreklik og vælg, kontroller element(Googles svar på Firebug)

<a href="http://www.1001line.dk/" class="l" 
onmousedown="return
 clk(this.href,'','','res',
'1','&amp;sig2=Yd8YBx8q77M9QpTMyuWYcw'
,'0CBAQFjAA')"><em>Svendborg Web</em></a>

Aha, så Google bruger onmusedown event til at registrerer hvad brugeren klikker på.

Onmouse down er den event som indtræffer lige når brugeren har klikket inden onclick event indtræffer.

EventListener Jeg ønskede ikke at have onmousdown tilskrevet inline til alle mine links, så jeg skulle bruge noget eventhandling og tænkte at det må jeg kunne gøre med prototype

Så jeg fandt følgende eksempel på http://www.prototypejs.org/api/function/bindaseventlistener

EventListener

var obj = { name: 'A nice demo' };

function handler(e) {
  var tag = Event.element(e).tagName.toLowerCase();
  var data = $A(arguments);
  data.shift();
  alert(this.name + '\nClick on a ' + tag +
    '\nOther args: ' + data.join(', '));
}

Event.observe(document.body, 'click', handler.bindAsEventListener(obj, 1, 2, 3));

(Af en eller anden grund virkede det først for mig da jeg fjernede body fra document.body)

Da det først virkede fik jeg hurtigt omskrevet scriptet så det passer til mit formål.


function handler(e) {
  var tag = Event.element(e).tagName.toLowerCase();
    if(tag == "a"){
        new Ajax.Request('/link_hits/click/?id=' 
                  + Event.element(e).id + "&url=" 
                  + eval('Event.element(e).href').escapeHTML() ,
                   {method: 'get', asynchronous:true, evalScripts:true})
        }
}

Event.observe(document, 'mousedown', handler.bindAsEventListener());

For at spare på serveren ønskede jeg ikke at skrive loggen i databasen men i en logfil, som jeg så efterfølgende kan parse.

Min controller action kom til at se sådan her ud.
def click
   render :nothing => true
    logger = Logger.new("#{RAILS_ROOT}/log/hits.log", 50, 1048576)
    logger.info "#{Time.now}, #{params[:url]}, #{params[:id]}, #{request.remote_ip}" 
  end

Og sådan ser min log info ud:

# Logfile created on Wed Feb 01 15:44:28 +0100 2010 by /
Wed Feb 10 15:44:28 +0100 2010, http://1001lin.dk/, 481, 127.0.0.1
Wed Feb 10 15:48:03 +0100 2010, http://localhost:3000/links/index/217-haandvaerk_byggeri, , 127.0.0.1

Så snart kan mine webstedsbrugere igen bruge links hits siden på mit websted.


Del

Posted in , , ,  | Tags , ,  | no comments

Hurtigere og Flere sidevisninger

Posted by Anders Carlsen Fri, 22 Jan 2010 08:48:00 GMT

Jeg har netop opdaget at jeg kan fordoble antallet af sidevisninger pr. session på min hjemmeside Århus Web, ved at fjerne en klik-optællings funktion.

Formålet med funktionen har været at kunne lave en optælling af hvilke links brugerne klikkede på via Århus Web , for dermed at kunne lave en top-liste. Som iøvrigt kan være en rimelig populær funktion.

Jeg har brugt en teknik hvor jeg ved hjælp af onclick først har send brugerne til en intern side som først har registreret klikket i databasen og derefter har vidersendt til den ønskede adresse således.

 <a  href="http://aarhuso.dk" 
  onclick="window.open('/links/goto/link?id=1'); 
  return false;">http://aarhuso.dk</a>

Brugeren vil på den måde kunne se den rigtige adresse ved onmouseover, og således ikke opdage funktionen udover at de altså vil få en langsommere afvikling.

En alternativ teknik kunne laves ved at man indsætter en dynamisk gennereret billed reference eller script nederst i html’en.


Del

Posted in , ,  | Tags  | no comments

Løsninger omkring omkring mit fotoalbum

Posted by Anders Carlsen Thu, 19 Apr 2007 11:54:00 GMT

For kort tide siden besluttede jeg mig for at nu var det på tide at jeg fik lavet et Fotoalbum / Billed Galleri på min hjemmeside Svendborg Web . Billeder er godt indhold. Det er let at gøre relevant i forhold til kontekst og mange vil gerne se billederne.

Web galleri generatorer

Jeg har tidligere anvendt forskellige web galleri generatore, som f.eks. den som findes i Picassa2 eller den der finde i Adobe Photoshop.

Men begge værktøjer generere statiske html sider som er alt for besværlige at integere i et dynamisk CMS. Så det jeg ønskede var et webgalleri med rige muligheder for administation af billederne.

Så min første tanke var at jeg ville finde og bruge noget kode som andre har skrevet. Der findes rigtigt mange open source PHP-gallerier, som f.eks. Coppermine men jeg ønskede et som var skrevet i Ruby On Rails

Open Source Projekter

På Ruby On Rails Wiki findes der en liste med open source projekter

Her finder jeg et dansk projekt rgallery som virker, men som ikke er færdigt udviklet.

Et andet projekt er Gullery Photo Gallery Det er rimeligt simpelt og alligevel elegant. Hvis jeg skulle have brugt det ville det alligevel have krævet en del omskrivning.

Jeg gør det selv

Så jeg beslutter mig for at kode mit eget galleri fra bunden. Jeg er jo trods alt webprogrammør, og det er sjovt at arbejde med billeder og Rmagick . Jeg har dog ladet mig inspirere af Gullery Photo Gallery dels ved at bruge lightbox js javascriptet, dels ved at bruge den samme struktur i frontend. – (Et galleri består af flere sæt af billeder, det er vel den mest naturlige måde at strukturere billederne på).

Rmagick vs mini-magick

En svaghed ved Gullery er også efter min mening at det benytter mini-magick istedet for Rmagick Billeder og billed manipulering er resurce krævende for en web server. Men Rmagick findes og det er et fantastisk værktøj, som kan alt. Så Rmagick er et must for mig, jeg vil hellere skifte web server end jeg vil skifte Rmagick ud med en diskount udgave.

Upload af billeder

Til webadministration høre naturligvis muligheden for at kunne uploade et billede og registrere det i en database. Men hvis man har flere hundrede billeder af gangen bliver det en alt for tung og langsom process at skulle side og uploade billederne manuelt. Registreringen af billederne, tagging, kategorisering og tildeling af titel er et stykke nødvendigt arbejde og det kan sagtens forgå på webserveren, uploading af mange billeder på en gang bruger jeg FTP til. Men inden jeg uploader billederne udvælger jeg og forbereder jeg dem i Picassa2 . Picassa2 har en glimrende funktion til export af billeder, hvor jeg selv kan bestemme størelse og komprimering. For at gøre det lettere for webserveren at håndtere billederne laver jeg et sæt af billederne i den maximale skærmstørelse og et sæt thumbnails af billederne.

Strategi til Caching af billeder

Den stratigi jeg hidtidigt havde brugt til caching af billeder som samtidigt have en en billeddatabase af genanvendelige billeder, hvar været altid at gemme et billede på serveren i den orginale version altså med den bedst mulige opløsning. Billeder fylder meget men de er har også værdifuldt indhold. Samtidigt har jeg så så genereret caches af billederne i forskellige prædefinerede størrelser. F.eks et med width 300px og et med width 100px.

Men efter at jeg for nyligt har sat mig grundigt ind i caching i Ruby On Rails har har fundet ud af hvor let det er at arbejde med, har jeg skiftet strategi og er gået over til at bruge RoR’s indbyggede caching også til håndtering af billeder.

Her er min metode til at lave thumbnails i mit billedgalleri

def gallery_set_picture

        id = params[:id]
        pic = Picture.find(id)

        picture_name = "#{$PATH_REGISTER}/#{pic.name}" 
           # Open the image-file
           img = Image.read(picture_name).first

      img.change_geometry!('200x150>') { |cols, rows, img|
                         img.resize!(cols, rows)
        }

        unless pic.is_landscape
          img = img.crop_resized!(200, 150, Magick::NorthGravity)
        end

        send_data(img.to_blob{ self.quality = 80 } , :type => "image/jpeg", :disposition => "inline", :stream => false) 
        GC.start
 end    
Øverst i min controller indsætter jeg så
caches_page :gallery_set_picture
Og nu har jeg så cached mit thumbnails billede. Default vi Rails cache billedet som picture_id.html eller picture_id.png (f.eks. 309.png) men det undgår jeg sådan her:
<a href="/assets/view_picture/<%= picture.picture_id %>_<%= friendly_path_name(picture.title) %>.jpg" 
Jeg har lavet en lille funktion til at fjerne æ , ø , å , mellemrum og andre uønskede tegn i titlen så jeg kan bruge den i filnavnet. Rails er ligeglad, Rails skal blot bruge id på billedet, men for brugeren af hjemmesiden kan det være nyttigt af have et ordentligt filnavn på billedet.

Rails er 5-10 gange hurtigere at udvikle i en PHP eller ASP.NET

Det er jo en påstand som kan diskuteres, men egentligt er det ligegyldigt, for det som betyder noget er at jeg oplever en meget større arbejdeglæde ved at arbejde med Ruby On Rails fremfor PHP eller ASP.NET Når jeg koder i Rails bruger jeg ufatteligt lidt tid på buissnes koden. Under 10%, resten af tiden bruger jeg på HTML, CSS og JavaScript. Og jeg syntes som de fleste andre webudviklere at det er rigtigt sjovt at arbejde med Javascript. Her er koden til et sæt billeder i mit galleri
<div style="width: 100%;">

<h1><%= @gallery_set.name%></h1>
<%= link_to "Tilbage", :controller => "galleri",  :id => @gallery_set.gallery_id %>
<div id="minipics">
<ul  id="list_pictures">
<% for picture in @pictures %>
<li id="item_<%= picture.id %>"> 
    <a class="asset" href="/assets/view_picture/<%= picture.picture_id %>_<%= friendly_path_name(picture.title) %>.jpg" rel="lightbox" title="<%= picture.title %>" description="<%= picture.description %>" cameradate="<%= picture.exif_datetime %>" aid="<%= picture.id %>"><img style="max-height:75px" src="/pictures/thumbnails/<%= picture.name %>" alt="<%= picture.description %>" title="<%= picture.title %><%= " #{picture.description}" if picture.description  %>" /></a>
</li>
<% end %>
</ul>
</div>
<div class="spacer"></div>
</div>

Det er ikke meget kode. Det er let at håndtere og skrive videre på. Jeg har da også tilføjet et javascript til at lave runde hjørner og jeg skal også have lavet preload af billederne på et senere tidspunkt.

Tableless html

For år tilbage ville jeg have brugt en table til at placere billederne i. Det ville have været besværligt at gøre de dynamisk,men man kan jo kode sig frem. Men den eneste rigtige måde at placere billederne på siden er ved hjælp at en liste
<ul id="list_pictures">
   <li>billede</li>
    .....
</ul>
Den tilhørende css ser sådan ud:
#list_pictures li
{
    margin: 10px; 
    padding: 0;
    display: inline;
    list-style-type: none;
    border: none;

    float:left;
    width:116px;
    height:85px;
    text-align:center;
    background: #DDD;
}
#list_pictures img {border:none;}
Istedetfor en lang liste af billeder med indryk og bullets, placere billederne sig pænt i rækkefølge og tilpasser sig den omgivende HTML.

Lightbox JS

Lightbox er et lækkert lille AJAX-agtigt javascript til at præsentere billeder med og det har fået stor udbredelse og bliver brugt i mange sammenhænge. Det er let at bruge og det er let at integrere på sin hjemmeside.

Til min glæde finder jeg også snart ud af at scriptet er kodet godt, hvilket gør det lettere at læse omskrive og tilpasse til mine behov.

event.keyCode – e.which

Jeg havde to ønsker til omskrivning: Det første var at jeg havde set et galleri på en af TV2 hjemmesider hvor man blot skulle trykke på “space” for at komme til næste billede. Så jeg var inde og kigge i TV2’s kode og med Firebug::Firefox Add-ons har det aldrig været lettere at disikere en kode og blive klogere. I lightbox.js lavede jeg så en lille tilføjelse til scriptet i funktionen til at capture keycode events:

function getKey(e){
    if (e == null) { // ie
        keycode = event.keyCode;
    } else { // mozilla
        keycode = e.which;
    }
    key = String.fromCharCode(keycode).toLowerCase();

    if(key == 'x'){ hideLightbox(); }

    if(key == ’ ‘){       next_asset(currentImageId);key=’’;return       false;

} }

next_asset er så en lille funktion og sørger for at billedskift og preaload.

Camera Date

Lightbox JS håndtere billedets titel ved at man i image taget indsætter attributten title.

Men jeg ønskede yderligere information vist sammen med mit billede. Bla. Camera Date. Camera Date og Rmagick har jeg beskrevet i et tidligere blog indlæg

Tilføjelsen til lightbox var lige ud af landevejen ved at tilføje en ekstra attribut – cameradate – til image tagget:
if(objLink.getAttribute('cameradate'))
                objCaption.innerHTML += '<br /><span class="cameradate">' + objLink.getAttribute('cameradate') + '</span>';

Valg af farver

Omkring valg af farver til hjemmeside har jeg for lang tid siden erkendt at sort ikke er nogen valgmulighed. Det dur bare ikke. Men tænkte jeg sort kan godt gå til billeder, for billeder præsentere sig selv bedst på en mørk baggrund. Så derfor var mit første valg at lave galleriet i sort, måske også fordi jeg havde Gullery Photo Gallery som forbillede.

Efter tilfældigt at være kommet forbi min fotograf ven Geir’s hjemmeside måtte jeg erkende at selv billeder skal præsenteres på en hvid hjemmeside. Det virker meget mere elegant og professionelt. Så nu er mit galleri hvidt. For at bløde lidt op på kanterne og kontrasterne, har jeg lagt billederne på en neutral grå baggrund og lavet runde hjørner med Nifty Corners


Del

Posted in , ,  | Tags , , , ,  | no comments

Puzzle Game Controller

Posted by Anders Carlsen Mon, 21 Nov 2005 21:42:00 GMT

I have made this Puzzle Game Controller that i want to show to You.
Del

Posted in , ,  | no comments

Scale & Crop

Posted by Anders Carlsen Fri, 14 Oct 2005 22:01:00 GMT

Så nu virker min Scale Crop demo igen. Den har også kun være ude af drift i et halvt år.
http://codebehind.dk/scale_crop/
Del

Posted in , ,  | no comments

FCKeditor

Posted by Anders Carlsen Thu, 13 Oct 2005 12:27:00 GMT

The FCKEditor is the best wysiwyg-editor that i know about. But not the most well documented.;-)
Anyway i have chosen to use it in a CMS that I am building.(Hopfully i can soon use it in this Typo Blog)
I ran into on big problem, that it took me some time to solve, so now i want to share my solution.
ondragdrop

You can drag and drop an image from the window into the text area. But Internet and Firefox handles this in to differnet ways. In Internet Explorer the src would be somothing like: In Internet Explorer the src would be somothing like: http://developmentserver:3000/images/image.jpg)
and in Firefox something like ../../images/image.jpg .
I cant use any of I, i want my src to be something like. /images/image.jpg

My thourgts was, well I can dig into The FCKEditor and change it to work the way i want it to. But it is very compleks, so I droped that again.

I found some documentation to work with on: http://wiki.fckeditor.net/Developer%27s_Guide/Javascript_API


function FCKeditor_OnComplete( editorInstance )
{
    editorInstance.Events.AttachEvent( 'OnSelectionChange', DoSomething ) ;
}


 
I can't deal with events on the FCKEditor ,because all events are handled inside the FCKEditor.


The function FCKeditor_OnComplete is called when The FCKeditor is loaded.
And you can use i to initalize some functions of your on that deals with the FCKeditor.
So here is what I did.


function parse_html(oFCKeditor)
{
    editor_text = oFCKeditor.GetXHTML("text");
    #removing everything before images in src
    r2 = /(src=\")[^ \n\r]+(\/images)/g
        
    oFCKeditor.SetHTML(editor_text.replace(r2,"src=\"/images"), 1)
    oFCKeditor.UpdateLinkedField();
}
    

function FCKeditor_OnComplete( oFCKeditor )
{
    //oFCKeditor.Events.AttachEvent( 'OnSelectionChange', DoSomething ) ;
    document.getElementById("article_form").onsubmit = function() {parse_html(oFCKeditor);}
    document.getElementById("article_form").onmouseover = function() {parse_html(oFCKeditor);}
}
Del

Posted in ,  | no comments

TinyMCE - Den bedste HTML Editor på nettet

Posted by Anders Carlsen Mon, 11 Apr 2005 10:08:19 GMT

Så fandt jeg lige en ny HTML Editor. TinyMCE
TinyMCE is a platform independent web based Javascript HTML WYSIWYG editor control released as Open Source under LGPL by Moxiecode Systems AB. It has the ability to convert HTML TEXTAREA fields or other HTML elements to editor instances. TinyMCE is very easy to integrate into other CMS systems.

Features

* Easy to integrate, takes only two lines of code. * Theme and template support. * Plugin support. * Easy to extend with custom code. * Customizable HTML/XHTML 1.0 output. Block invalid elements and force attributes. * International language support (Language packs) currenly English, Swedish, Italian, German, Czech, Hungarian, Dutch, Finnish, Danish and Arabic and much more. * Multiple browser support, currently Mozilla, MSIE and FireFox.
Det er ialtfald det bedste jeg har set. Total ren integration med backend.

Del

Posted in ,  | no comments

progress bar

Posted by Anders Carlsen Mon, 11 Apr 2005 00:05:47 GMT










Del

Posted in  | no comments

Generic QueryString JavaScript Object

Posted by Anders Carlsen Sat, 09 Apr 2005 02:15:48 GMT

Så fik jeg alligevel lavet lidt sjov idag. Jeg har jo opdaget at JavaScript er Objekt Orienteret :-)
function QueryString(path)
  {
  	this.path = path;
	this.toString = function()
	{
		result = this.path + "?";
		for(element in this)
		{
			if(typeof this[element] != 'function' && element != 'path')
			{
				result += element + "=" + this[element] + "&";
			}
		}
		return result;
	}
	
	this.toLink = function(text)
	{
		return "" + text + "";
	}
  }
Nu kan jeg skrive:
myObj = new QueryString("http://codebehind.dk");
  myObj.w = 100;
  myObj.rx = 1000;
  myObj.ry = 1000;

I stedet for at ende med noget rod som dette: url = '/pictures/crop?id=<%= @picture.id %>' + '&w=' + dd_picturer.w + '&h=' + dd_picturer.h + '&sx=' + (dd_crop.x - dd_picturer.x) + '&sy=' + (dd_crop.y - dd_picturer.y) + '&ex=' + dd_crop.w + '&ey=' + dd_crop.h;
Del

Posted in ,  | no comments