Sunday, December 31, 2006

Mimic python

After the article yesterday i decided to mimic the python behaviour for strings and arrays.
Below you find the function to get parts from a string or an array. I added a '1,5,4' limiter to get specific and/or loose parts.

function getStrArr($var,$limiter){
if(is_numeric($limiter)){
// get one value
if(strpos($limiter,'-') === false){
return (is_array($var))?$var[$limiter]:substr($var,$limiter,1);
// get last value(s)
}else{
return (is_array($var))? array_slice($var,$limiter) : substr($var,strlen($var)+$limiter) ;
}
}else{
if(strpos($limiter,',') === false){
if(strpos($limiter,':') == 0){
$lim = str_replace(':','',$limiter);
// get part from the begin
if(strpos($limiter,'-') === false){
return (is_array($var))?array_slice($var,0,$lim):substr($var,0,$lim);
// get part from the end
}else{
return (is_array($var))? array_slice($var,$lim) : substr($var,strlen($var)+$lim);
}
}else{
$temp = explode(':',$limiter);
if($temp[1] == ''){
// exclude part from begin
if(strpos($limiter,'-') === false){
return (is_array($var))?array_slice($var,$temp[0]):substr($var,$temp[0]);
// exclude part from the end
}else{
return (is_array($var))? array_slice($var,0,count($var)+$temp[0]) : substr($var,0,strlen($var)+$temp[0]);
}
}else{
// get self defined part
$min = $temp[1]-$temp[0];
return (is_array($var))? array_slice($var,$temp[0],$min) : substr($var,$temp[0],$min);
}
}
}else{
// get pieces
$temp = explode(',',$limiter);
if(is_array($var)){
$arr = array();
foreach($temp as $t){ $arr[] = $var[$t]; }
return $arr;
}else{
$str = '';
foreach($temp as $t){ $str .= substr($var,$t,1); }
return $str;
}
}
}
}

Saturday, December 30, 2006

Beginning python : string and array

I wanted to climb up the programmer hierarchy so i decided to look at some python tutorials, not that i'm near to be a good OO php programmer but i found out if you aim high you get better doing the things you think you understand.

There are already a few things that caught my attention. At first the webdevelopment seems to look awfully like perl. In a tutorial i found they just printed the the html but i think i will find better ways when i explore python further.

Beside the obvious differences like syntax i found it refreshing there were similar functions for strings and arrays, they are in a datatype group called sequences. I will switch from python to php to show similar output

# define string and array variable
string = 'test'
array = [1, 2, 3, 4]


// define string and array variable
$string = 'test';
$array = array(1, 2, 3, 4);


# get size
len(string)
len(array)


// get size
strlen($string);
count($array);


# get one value
string[2]
array[2]


// get one value
substr($string,2,1);
$array[2]


# get last value
string[-1]
array[-1]


// get last value
substr($string,strlen($string)-1);
$array[count($array)-1];


# get multiple values start in the beginning
string[:2] # display the first 2
array[:2]
string[2:] # display everything except the first 2
array[2:]


// get multiple values start in the beginning
substr($string,0,2); // display the first 2
array_slice($array,0,2);
substr($string,2); // display everything except the first 2
array_slice($array,2);


# get multiple values start in the end
string[:-2]
array[:-2]
string[-2:]
array[-2:]


// get multiple values start in the end
substr($string,strlen($string)-2);
array_slice($array,-2);
substr($string,0,strlen($string)-2);
array_slice($array,0,count($array)-2);


# get part of variable
string[1:3]
array[1:3]


// get part of variable
substr($string,1,2);
array_slice($array,1,2);


# add value
string + ' test'
array + 5


// add value
$string .= ' test';
$array[] = 5;


# copy variable with itself
2*string
2*array


// copy variable with itself
$string .= $string;
foreach($array as $value){ $array[] = $value; }

As you can see there is more php code necessary and it involves different functions as well. There is also a loop necessary in php to mimic the python code.
You can also see a difference getting a part of the variable in python and php. In python you limit the part by the value key and in php you limit the part by how many values you need.

Because strings and arrays are a basic in every language it has to be as easy as possible to work with them.

Monday, December 25, 2006

Mysql last inserted id

In a few articles on mysql the function LAST_INSERT_ID() is used to extract the last inserted id but i experienced a problem with it. When i insert multiple rows in one query the LAST_INSERT_ID displays the first inserted id and not the last.

INSERT INTO table (field1,field2) VALUES (value1,value2),(value3,value4)

The function is also restricted to the table field that has an AUTO_INCREMENT value. To avoid the problem and make it more flexible i created a maxFieldOfTable function.

function maxFieldOfTable($table,$field = 'id'){
$result = mysql_query('SELECT MAX('.$field.') FROM '.$table);
return (!$result)? mysql_error():mysql_result($result,0);
}

Sunday, December 24, 2006

Simple php/javascript in place editing

This last few weeks i learned more about things i consider basic so that's why i want to give some working examples of it.

The first thing i want to get some attention to is the button tag. I read an article in the forgotten html tags series about the button tag. In the article the design advantages where emphasised but there are programming advantages too. The biggest advantage is the separation of the value and the title.

<input type="submit" name="button" value="Title" />
<button type="submit" name="button" value="1">Title</button>

When you have an input tag the posted value is the value that you have to display on the button. With the button tag you can put any value you want to post in the value attribute.

When i made forms where a row of data needed to be changed i used a radiobox with the id of the row which needed to be checked before you could click a button. With the button tag it's possible to only have to click on the button.

Php code



Now that we got that behind us lets look at the php code of the in place editing

foreach($data as $row){
$text = $row['field1'];
$buttonvalue = $row['id'];
$buttonname = 'update';
$buttontitle = 'Update';
if((isset($_POST['update']) && $_POST['update'] == $buttonvalue) ||
(isset($_POST['updateok']) && $check == 0 && $_POST['updateok'] == $buttonvalue)){
$text = '<input type="text" name="text" id="text" value="'.$text.'" />';
$buttonname = 'updateok';
$buttontitle = 'OK';
}
?><tr><td><?php echo $text; ?></td><td><button type="submit" name="<?php echo $buttonname; ?>" class="<?php echo $buttonname; ?>" value="<?php echo $buttonvalue; ?>"><?php echo $buttontitle; ?></button></td></tr><?php
}

This is the code needed to display the form input to change the text. The data variable is a result from a query that is caught in an array. To make the text changeable i rely on the button name and the value send when the button with the update class is clicked. The update code is located in a separate file because of the javascript functionality.

if(isset($_POST['updateok'])){
// mysql : update table set field1='$_POST['text']' where id= $_POST['updateok'];
$check = (mysql_affected_rows() == 1)? 1:0;
if(isset($_POST['js'])){ echo $check; }
}

As you could see in the first code fragment there is a second statement when the text has to be form input and that's when it wasn't possible to update the text. Most of the time that is due to a temporary programming blindness- not correct table, set a character to much or to little, ... - but it can be useful to report problems once the site is live. The only thing i needed to add to make it work in javascript is the output of the check variable.

Javascript



This was the easy part. Now we are going to climb steep coding hills. I use the jQuery library to make the javascript coding easier. The javascript code can be split up in two parts; the changing of the text to form input and the updating of the text. The changing of the text can also be split up in two parts. The first part is the check for changeable text and close it if there is a changeable text found.

if($('button.updateok').size() == 1){
$('button.updateok').html('Update').attr({class:'update'});
var text = $('#text').attr('value');
$('#text').parent().html(text);
}

People who are familiar with jQuery see a few simple lines but i will write it out.
If a button tag with the class updateok is found the innerhtml of the button will be changed to Update and the class will be changed to update. The variable text catches the value attribute from the element with the id text, this variable will be placed in the innerhtml of the parent tag that contains the element with the id text.
The second part is changing from the text to form input.

$(this).html('OK').attr({class:'updateok'});
var text = $(this).parent().prev('td').html();
$(this).parent().prev('td').html('<input type="text" name="text" id="text" value="'+text+'" />');

The code is similar so i won't write it out. The only thing that has changed is the this variable. I can work with it because the code is called in the function that is responsible to intercept the click event. You will see it later.
Now we are ready for the updating code

var id = $(this).attr('value');
var textt = $(this).parent().prev('td').children('#text')[0];
var text = $(textt).attr('value');
var self = this;
$.ajax({
type: 'POST',
url: 'update.php',
data: 'updateok='+id+'&text='+text+'&js=1',
success: function(msg){
if(msg == 1){
$(self).html('Update').attr({class:'update'});
$(self).parent().prev('td').html(text);
}else{
alert('Problem changing field.');
}
}
});

The first part of the code is lifting the necessary values off the page to put then in the server request. The text value is found by starting from the button (this), going up the dom tree (parent), find the previous tablecell (prev('td')) and look in the tablcell for the first element with the id text (children('#text')[0]). This is caught in a temporary variable that is used to extract the value. The variable self is used in the callback of the request. The request has a this variable of his own.

The request itself happens inside the ajax function. The hash of the function takes care of the different parts. The succes key of the hash is called when the server returns an ok message. To get the returned values from the server you have to catch it in a function argument (msg) and because i echoed the check php variable all i had to do is look for the 1 value. If it's 1 then the text and the button change again.

If you have read so far you deserve to see the full javascript code.

$(function(){
$('button.update').click(function(){
if($(this).attr('class') == 'updateok'){
var id = $(this).attr('value');
var textt = $(this).parent().prev('td').children('#text')[0];
var text = $(textt).attr('value');
var self = this;
$.ajax({
type: 'POST',
url: 'update.php',
data: 'updateok='+id+'&text='+text+'&js=1',
success: function(msg){
if(msg == 1){
$(self).html('Update').attr({class:'update'});
$(self).parent().prev('td').html(text);
}else{
alert('Problem changing field.');
}
}
});
}else{
if($('button.updateok').size() == 1){
$('button.updateok').html('Update').attr({class:'update'});
var text = $('#text').attr('value');
$('#text').parent().html(text);
}
$(this).html('OK').attr({class:'updateok'});
var text = $(this).parent().prev('td').html();
$(this).parent().prev('td').html('<input type="text" name="text" id="text" value="'+text+'" />');
}
return false;
});
});

The first line is called when the document is loaded. The second line is the click event interceptor function. The third line is a check if the button has the updateok class. This may seem odd because in the click function you look for the button with the update class but because the first line is only called when the page has loaded it keeps seeing the original state. Only after the click event it finds the javascript manipulated elements and their attributes.
In the end the return false statement is added so that the normal behaviour of the button is cancelled.

Conlusion



Now you have two layers of functionality that react the same and do the same with a minimal amount of code. For javascript i used more code than in php because the posting of the form in php takes work out of my hands. This code isn't finished because there is no input control but that can be added easily.

An example can be found at : Simple php/javascript in place editing

Saturday, December 16, 2006

Programmers logic

In the years i'm programming webforms i always had the instinctive idea i should penalize the user of the forms with an error message and redirecting the user back to the form. I know now that is a wrong line of thinking.

It is wrong because of two reasons
- Users need to fill in some of the fields again
- The need to program the error messages and return of entered data

In the era usability is not a buzz word but a rule to live by it's plain wrong to let the user input data again when it's not necessary.

A scenario : we have three radioboxes; good, bad, neutral. Connected to the bad radiobox are three checkboxes; very, very, very (I didn't think a lot about this).

My normal behavior would be to check if one of the checkboxes was checked. If one is look if the bad radiobox was checked. If it isn't back to the form clearing the checkboxes and radioboxes and an error message on top. This is brutal behavior. At least i could check the bad radiobox and let the checkbox stay checked but then it would be rude to redirect to the form because the only thing i do then is saying how stupid the user is.

Adding error code is another thing. It is annoying because most of the time it is basically the same code. It's the design of the site or the demand of the client that forces you to write the code in a not generic way. Because it is a user input there is always a possibility of a form of an hack attack so you have to check that too before returning the value.

Taking the scenario from above you can add a css class to the label or a message next to the label or a border around the check- and radioboxes, ... .

The best way to deal with the given scenario is to check if a checkbox is checked. If it is set the radiobox value to the bad value and let the user think they did everything good.

You can't do that with every inputfield you have. You have to balance the user/programmer decisions about the input. If some data is necessary to continue you have to set up errors but otherwise make the form filling labor as smooth as possible.

The new beginning of my programming blog

I've been neglecting this blog for a while so i'm starting again and what starts a boring blog better than humor

Saturday, October 21, 2006

Plugin updates

I rewrote the mp3player plugin and changed the page. The code is no longer a download. You can copy and paste it from the page. The code is much cleaner now.

I made some small changes in the texrep plugin. Check the updates for more information.
There are still some bugs left but i'm working on them.

Sunday, October 15, 2006

New jquery plugin : texrep

I worked on a new jquery plugin: texrep. It's short for textreplacement. It's just a funny name.

Texrep replaces a text with an image using a font file.

You can find the code and examples at http://dlinck.d.googlepages.com/jquerytexrep.

Tuesday, October 10, 2006

jquery mp3player update

I moved the player code to my jquery googlepage

I added more options like playing a file on startup and choice of flashplayer insertion.

I will set up som examples tomorrow.

Monday, October 09, 2006

Structured css file

There is a lot to find about how to structure your css files but you have to find the best method for yourself.

With comments you can't go wrong. I use them like this

/*------------ generic --------*/

/*------------ div -----------*/

/*------------ span -----------*/

/*------------ title -----------*/

/*------------ paragraph -----------*/

/*------------ link -----------*/

/*------------ list -----------*/

/*------------ image -----------*/

/*------------ form -----------*/

/*------------ table -----------*/

This way you can find the css style by the function of the html tag and still add extra comment. To make it more readable I add the tag in front of the id or class selector when i have to use a parent element.

/*------------ div -----------*/
#content
    { width: 80%; }
#navigation
    { width: 20%; }
/*------------ link -----------*/
div#content a, div#navigation a
    { text-decoration: none; }
div#navigation a
    { font-weight:bold; }

The following advise you can see in the previous example. by indenting the actual style and putting it on one line you have a visual guidance and a compact css file. An additional advantage of seperating the selectors from the style is that you can have a line of selectors where the style is fully visible underneath. Of course you must be aware not to use to many selectors. In the example the first link selector can be

/*------------ link -----------*/
a
    { text-decoration: none; }


This works for me but different methods aren't wrong.

Monday, September 11, 2006

Good practice

There is a lot said about good practice when programming and there are a few things i use.

- Produce reusable code

Even if you are sure the code you write is never going to used on another site write it as it will be used for other sites. Reusable code is a lot cleaner and more flexible than improv code. This makes your site faster.

- Only the code that displays html must maintain html.

Get as much html out off php classes and javascript functions. If there is no way to remove the html out of the code keep it as simple as possible. If a css class is needed or another attribute make it an argument so it can be adjusted without crawling through the function code.

- Javascript interfaces need server language script

When you are coding in javascript sometimes you can forget it can be turned off. You can make nice things but when users can't do anything on your site without javascript you never reach all the people that want to use your site. If there is html that has no purpose without javascript it's site fat.

- Use html wisely

Because div and span tags are the most generic tags you can use them to replace all tags. Use html tags according to their purpose. You can bend their purpose a bit like using a list to build a menu that looks like a table. Use an id attribute only once per page.

- Make css readable and cascading

When you create css based on html you are going to get into trouble sooner or later. If you put everything in a class or an id your css file is going to be lengthy and you are going to have to use multiple classes if you want to add javascript functionality to an element. Use an id to style included elements. Split your css file into sections using comment lines.

These are a few tips. I hope they work out for you too.

Sunday, September 10, 2006

From server to client

I think most people who are used to program with server languages like php and perl have trouble ajusting to javascript as a partner language instead of a supporting language.

To give an example. I've worked on Smooth paginator. The idea behind it is simple. Group pages together by sets to minimize the place taken by the page links. Although it's nice work the one thing that's bothering me is the fact that the sub-group is generated by the php code therefore it is shown when javascript is turned off, The subgroup has no use then. The subgroups need to be generated by javascript to degradate gracefull.

If you plan to migrate from a server script to a more client script approach you have to keep in mind javascript can be turned off or not read by the browser. Try to back-up as much client functionality with server functionality. The way i do it is by creating everything in a server script language and then i'm creating the client script whitch uses methods from the server script through ajax calls. This way you don't have to program the same funtionality twice and you have the new way of handling user actions.
If it's difficult to mimic the javascript behaviour make sure the functionality is not essential for the use of the application.

I've adjusted the smooth paginators code to generate the sub-groups but it has to be approved by the creator of the code. But i'll think he isn't going to be difficult about it because he switched from version .02 to .03 using my rough javascript code. That's surely nothing to be proud of, the improved code is.

Tuesday, September 05, 2006

Blogger navbar

The blogger branded bar hides itself as soon as the mouse moves in an area outside of the bar. This are four lines of jQuery code.

$(document).mousemove( function(e) {
ym = (e.y || e.clientY);
if(ym < 32){ $("#b-navbar").attr("class","show"); }else{ $("#b-navbar").attr("class","hide"); }
});

First we add the mousemove event to the document so that it can monitor the cursor. Than we define the place of the cursor in relation with the top of the visible website.
The bar is 32 (firefox)/ 34 (IE) pixels so i took the lowest number. If the mouse is below that height the class show will be added to the bar whitch the blogger people gave the id b-navbar. If the mouse is above that height the class show will be added.

My first impulse was to use the hide and show functions of jquery but they didn't respond so i made a hide and show css class where i change the visibility.

You could put the search box on your page so it stays accessable all of the time by putting the form code somewhere into your template.

<form id="b-search" name="b-search" action="http://search.blogger.com/"><input type="text" id="b-query" name="as_q" />
<input type="hidden" name="ie" value="UTF-8" />
<input type="hidden" name="ui" value="blg" />
<input type="hidden" name="bl_url" value="xwerocode.blogspot.com" />
<input type="image" src="http://www.blogger.com/img/navbar/2/btn_search_this.gif" alt="Search This Blog" id="b-searchbtn" title="Search this blog with Google Blog Search" onclick="document.forms['b-search'].bl_url.value='xwerocode.blogspot.com'" />
<input type="image" src="http://www.blogger.com/img/navbar/2/btn_search_all.gif" alt="Search All Blogs" value="Search" id="b-searchallbtn" title="Search all blogs with Google Blog Search" onclick="document.forms['b-search'].bl_url.value=''" />
</form>



I skimmed the divs and other things that where in the original form to make the form more readable. Ofcourse you have to change xwerocode.blogspot.com to your url or you could search my blog on yours.
If you want to change the color of the form just use the style attribute in the form tag.
You can change the type of the button from image to button to have more lay-out options but don't forget to add a value to the "search this blog" button.

Sunday, September 03, 2006

Changing the form content after submiting

Changing the page content after submiting is a common practice. Many programmers redirect to a new page. If you want to do an ajaw, the w is for whatever, call you have to stay on the same page but that possible with a server script language too. I'm using php most of the time. so here is the php code for it.

<?php
$good = 0;
if($_POST['send']){
// handle submit
$good = 1;
}
?>
<html>
<head>
<title>example form</title>
</head>
<body>
<?php if($good == 1){ ?>
<p>Your form was submitted</p>
<?php }else{ ?>
<form action="" method="post" id="form">
<input type="text" name="text" id="text"><br>
<input type="submit" name="send" value="Send" id="send">
</form>
<?php } ?>
</body>
</html>

This form can be ajawed easy with jQuery backed up with your original php code. Maybe you already noticed the id attributes of the form tags. That are the action trigger (send), the input value (text) and the placeholder (form).
The javascript that would be added is

$(document).ready(function(){
$("#send").click(function(){
$.post("process.php",{text: $("#text").val()},function(html){ $("#form").html(html); });
return false;
});
});

That's all. The click function catches the clicking of the button. Return false is added to stop the normal behaviour of the button.
The post function has three arguments; file, parameters and callback. The argument of the callback function can have any name you want and it gives back the output of the file. The file can output anything you want- html, xml, json - but html is the most easy option. The content inside the form tags is changed to the output of the file with the html function.

You can put your form handle code in a class method that you then call in the process.php as on the actual page to make your code less fault-prone. And it's best to add an action to the form tag.

Announcement

I going to continue to write the blog in English so the content is understandable for all readers. When you want to program the best documentation is written in English. Maybe i'm going to maintain a parallel Dutch blog but only if there are enough requests.

Wednesday, August 30, 2006

Mp3player 1.0

Thanks to a great tip i was able to get the player going in IE too.

Instead of the two optional parameters i now have the two alt values, play and stop, for the mp3controler image and width, height, align, style and fontcolor for the player all wrapped in an nice associative array.

$("a.example1").mp3player({play: 'listen'});
$("a.example2").mp3player({fontcolor: '002EB8'});

example links:
MSTRKRFT - Work On You (Para One Remix)
Elvis Costello - Watching the Detectives (My Aim Is True, 1977)
You need to click twice to let the player work because of the two different classes. In IE i also noticed a flickering when clicking on the play state of the mp3control. These issues will be handled in the next releases.

If you want to attach the mp3player to all mp3 files
$("a[@href $= .mp3]").mp3player();

I also added the mp3 check to make sure the files are all playable.

the code for this version is :

$.fn.mp3player = function(options){
var play = options && options.play && (options.play.length > 0) ? options.play : 'play';
var stop = options && options.stop && (options.stop.length > 0) ? options.stop : 'stop';
var width = options && options.width && (options.width.length > 0 && typeof options.width == 'number') ? options.width : '100';
var height = options && options.height && (options.height.length > 0 && typeof options.height == 'number') ? options.height : '14';
var align = options && options.align && (options.align.length > 0) ? options.align : 'middle';
var style = options && options.style && (options.style.length > 0) ? options.style : 'vertical-align: bottom; margin-right: 0.2em;';
var fontcolor = options && options.fontcolor && (options.fontcolor.length > 0) ? options.fontcolor : '000000';
return this.each(function(){
if($(this).attr("href").match(/.mp3$/i)){
$(this).prepend('<img src="http://del.icio.us/static/img/mp3/play.gif" alt="'+play+'" class="mp3control"> ');
$(this).find("img.mp3control").click(function(){
var url = $(this).parent().attr("href");
var alt = $(this).attr("alt");
if(alt == play){
// reset all values op page
$("embed#player").remove();
$("img.mp3control").attr({src : "http://del.icio.us/static/img/mp3/play.gif", alt : play});
// adjust image and innerhtml
$(this).attr({src : "http://del.icio.us/static/img/mp3/stop.gif", alt : stop});
$(this).after('<embed width="'+width+'" height="'+height+'" align="'+align+'" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" allowscriptaccess="sameDomain" name="player" id="player" wmode="transparent" quality="high" flashvars="theLink='+url+'&fontColor='+fontcolor+'" src="http://del.icio.us/static/swf/playtagger.swf" style="'+style+'"/>');
return false;
}else{
$(this).attr({src : "http://del.icio.us/static/img/mp3/play.gif", alt : play});
$("embed#player").remove();
return false;
}
});
}
});
};

Tuesday, August 29, 2006

jquery plugin beta

Javascript isn't really my language. Im just too stupid to program with it.

The previous version of my code got a major flaw. For each link it found it added a click event. The second link it found got two click events so the second canceled the first. The thirth got three click events so the code worked, and so on.

This was solved by replacing
$("img.mp3control").click(function()

by
$(this).find("img.mp3control").click(function()

I also changed the class value of the image to mp3control because i thought play was to generic.

Someone on the jquery list told me it wasn't working on IE6 and he is right. The player is added and removed but it gets stuck loading the file. In firefox 1.5 and Opera 9 the file plays.

The adjusted code can be found in the head tag of the sourcecode.

Monday, August 28, 2006

My first jquery plugin

Weer een Engelse post omdat ik dit ga linken in een e-mail op de jquery discussie lijst.

To make up for my stupid mistake and because i wanted to try to make a plugin as an experiment, i tranformed my shot at a del.icio.us powered mp3 player to a plugin. It wasn't as difficult as i thought it would be. With Klaus Hartls tabs plugin code as an example i took the code you find in the article below and put it in the the jQuery plugin construct. I couldn't use the toggle function anymore but by defining the alt attribute of the added image i could create a simple if statement.

Here is the plugin code:


$.fn.mp3player = function(play,stop){
if (typeof play == "undefined") { play = "play"; }
if (typeof stop == "undefined") { stop = "stop"; }
return this.each(function(){
$(this).prepend('<img src="http://del.icio.us/static/img/mp3/play.gif" alt="'+play+'" class="play"> ');
$("img.play").click(function(){
var url = $(this).parent().attr("href");
var alt = $(this).attr("alt");
if(alt == play){
// reset all values op page
$("object#player").remove();
$("img.play").attr({src : "http://del.icio.us/static/img/mp3/play.gif", alt : play});
// adjust image and innerhtml
$(this).attr({src : "http://del.icio.us/static/img/mp3/stop.gif", alt : stop});
$(this).after('<object width="100" height="14" align="middle" id="player" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" style="vertical-align: bottom; margin-right: 0.2em;"><param value="transparent" name="wmode"/><param value="sameDomain" name="allowScriptAccess"/><param value="'+url+'&fontColor=000000" name="flashVars"/><param value="http://del.icio.us/static/swf/playtagger.swf" name="movie"/><param value="high" name="quality"/><embed width="100" height="14" align="middle" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" allowscriptaccess="sameDomain" name="player" wmode="transparent" quality="high" flashvars="theLink='+url+'&fontColor=000000" src="http://del.icio.us/static/swf/playtagger.swf" style="vertical-align: bottom; margin-right: 0.2em;"/></object>');
return false;
}else{
$(this).attr({src : "http://del.icio.us/static/img/mp3/play.gif", alt : play});
$("object#player").remove();
return false;
}
});
});
};

Like any other plugin it gets called like this:

$("a mp3").mp3player();


example : Cunts are still running the world

I added two optional parameters. The first is the alt value for the play image and the second is the alt value for the stop image. This way you can add your own language or whatever you want to the alt attribute of the image.

For me the plugin has a bonus because there is less javascript code in the html body.

The things i still have to do is check if the href attribute is present and if the file really is an mp3.

I'm just a thief with a little imagination so please be gentle in the comments.

Sunday, August 27, 2006

Automatisch een mp3 speler bij een link

Als je mijn vorige artikel gelezen hebt ben je misschien nieuwsgierig hoe de code voor de speler nu juist ineen zit.

Ik maak gebruik van de javascript bibliotheek jQuery. Omdat ik ze niet kan uploaden naar blogspot moet ik hotlinken naar de bron.

<script type="text/javascript" src="http://jquery.com/src/jquery-1.0.pack.js"></script>

Dit bestand is de gecompresseerde versie van de bibliotheek. Die is een 16 kb groot.
Vervolgens zet ik mijn javascript onderaan de artikel code omdat script code in de head tag niet gelezen wordt. Nu zal ik de code opsplitsen zodat ze duidelijker wordt.
Eerst voeg ik aan alle links met het class attribuut mp3 de speelknop toe van del.icio.us.

$("a.mp3").prepend('<img src="http://del.icio.us/static/img/mp3/play.gif" alt="beluister" class="play"> ');


De speelknop heeft de class play en aan de hand daarvan bind ik de klik evenementen met de toggle functie van jQuery.

$("img.play").toggle(function(){},function(){});


De toggle functie bestaat uit twee functies. De eerste functie zorgt voor de oneven klik evenementen. In deze eerste functie haal ik het url op, zet ik alles weer naar de oorspronkelijke staat(komt van pas als er al bestanden beluisterd zijn), verander de attributen van de speelknop, voeg ik de flashspeler van del.icio.us toe na de speelknop met het opgehaalde url en stop het normale klik gedrag.

var url = $(this).parent().attr("href");

$("object#player").remove();
$("img.play").attr({src : "http://del.icio.us/static/img/mp3/play.gif", alt : "beluister"});

$(this).attr({src : "http://del.icio.us/static/img/mp3/stop.gif", alt : "stop"});

$(this).after('<object width="100" height="14" align="middle" id="player" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" style="vertical-align: bottom; margin-right: 0.2em;"><param value="transparent" name="wmode"/><param value="sameDomain" name="allowScriptAccess"/><param value="'+url+'&fontColor=000000" name="flashVars"/><param value="http://del.icio.us/static/swf/playtagger.swf" name="movie"/><param value="high" name="quality"/><embed width="100" height="14" align="middle" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" allowscriptaccess="sameDomain" name="player" wmode="transparent" quality="high" flashvars="theLink='+url+'&fontColor=000000" src="http://del.icio.us/static/swf/playtagger.swf" style="vertical-align: bottom; margin-right: 0.2em;"/></object>');

return false;

De tweede functie van de toggle functie zorgt voor het afhandelen van de even klik evenementen. Hier verander ik de attributen van de speelknop weer naar de originele staat, verwijder de flashspeler en stop het normale klik gedrag.

$(this).attr({src : "http://del.icio.us/static/img/mp3/play.gif", alt : "beluister"});

$("object#player").remove();

return false;

In zijn geheel geeft dat volgende code;

$("a.mp3").prepend('<img src="http://del.icio.us/static/img/mp3/play.gif" alt="beluister" class="play"> ');
$("img.play").toggle(function(){
var url = $(this).parent().attr("href");
$("object#player").remove();
$("img.play").attr({src : "http://del.icio.us/static/img/mp3/play.gif", alt : "beluister"});
$(this).attr({src : "http://del.icio.us/static/img/mp3/stop.gif", alt : "stop"});
$(this).after('<object width="100" height="14" align="middle" id="player" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" style="vertical-align: bottom; margin-right: 0.2em;"><param value="transparent" name="wmode"/><param value="sameDomain" name="allowScriptAccess"/><param value="'+url+'&fontColor=000000" name="flashVars"/><param value="http://del.icio.us/static/swf/playtagger.swf" name="movie"/><param value="high" name="quality"/><embed width="100" height="14" align="middle" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" allowscriptaccess="sameDomain" name="player" wmode="transparent" quality="high" flashvars="theLink='+url+'&fontColor=000000" src="http://del.icio.us/static/swf/playtagger.swf" style="vertical-align: bottom; margin-right: 0.2em;"/></object>');
return false;
},function(){
$(this).attr({src : "http://del.icio.us/static/img/mp3/play.gif", alt : "beluister"});
$("object#player").remove();
return false;
});

Het enige wat er nu moet gebeuren in de artikels is de class mp3 toevoegen aan de links die een speler moeten hebben en dan gebeurt alles zonder andere javascript code in je html te zetten.

Ik heb de code getest met de laatste en meest gangbare versies van IE, firefox, opera en konqueror. Volgens een maccer werkt het niet in safari. Ik zal hier naar kijken als ik tijd heb.

Jquery debug

Omdat ik op een mogelijk probleem gestoten ben in jquery ga ik dit artikel verder in het Engels schrijven

I was trying to make a link for playing mp3's using the del.icio.us player.
Every link with the class mp3 will get the play button from del.icio.us.
$("a.mp3").prepend('<img src="http://del.icio.us/static/img/mp3/play.gif" alt="beluister" class="play">&nbsp;');


On clicking the play image the player should appear with the value from the href attribute of the link. But here something goes wrong.
$("img.play").click(function(){
var link = $(this).parent().html().split(';');
alert(link[1]);
var url = $(this).parent().attr("href");
alert(url);
$(this).parent().html('<img src="http://del.icio.us/static/img/mp3/stop.gif" alt="stop" class="stop"><object width="100" height="14" align="middle" id="player" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" style="vertical-align: bottom; margin-right: 0.2em;"<>param value="transparent" name="wmode"/><param value="sameDomain" name="allowScriptAccess"/><param value="'+url+'&fontColor=000000" name="flashVars"/><param value="http://del.icio.us/static/swf/playtagger.swf" name="movie"/><param value="high" name="quality"/><embed width="100" height="14" align="middle" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" allowscriptaccess="sameDomain" name="player" wmode="transparent" quality="high" flashvars="theLink='+url+'&fontColor=000000" src="http://del.icio.us/static/swf/playtagger.swf" style="vertical-align: bottom; margin-right: 0.2em;"/></object>'+link);
return false;
});


test link : Cunts are still running the world

It gets the alert with innerhtml, without the play image, but not the alert with the value of the href attribute and it continues the link behaviour even with the return false; code. When i only alert the innerhtml it acts as expected.

The functional code of the site is found near the bottom of the source code. Blogspot doesn't execute javascript code inside the head tag.

The thirth part of the code would be the click event of the stop image.

I saw it on Mars needs guitars and i thought it was great so i wanted to add it to my blog too.

If it's a bug in jquery i hope it will be fixed soon. You just got to love the fast respons on their mailing list.

update : The problem was linking to an older version of jquery. I made some changes in the functional code now to make it work.

Javascript

Op Ramblings of a man gebruik ik verschillende javascript trucjes om de rechterzijde wat frivoler te maken. Zo heb ik flick zeitgeist en The hype machine javavscript widgets.
Het probleem van de hype machine widget was dat het de link niet opende in een nieuw venster. Liever een nieuw venster dan mijn blog te laten verdwijnen. De oplossing was redelijk simpel. Eerst jquery toevoegen en dan een klein scriptje maken dat een target attribuut toevoegd aan de hype machine links.

<script type="text/javascript"> $("#profile-container table tr td a").set("target","_blank");</script>

Javascript is nooit mijn favoriete programmeertaal geweest maar met de libraries die er nu zijn wordt het dragelijk.
Ik ben een fan geworden van jquery omdat ik veel sneller resultaat bereikte dan met prototype.

Het jammere aan blogspot/blogger is dat je de code op de pagina moet zetten. code in de head tag wordt niet uitgevoerd.