Sunday, September 07, 2008

New FF add-ons

Ubiquity is the first add-on that makes me want to dive in the firefox internals. I tried creating add-ons myself but i was turned off by all the files you need to maintain. Ubiquity makes it easier to start playing with firefox. For example this Ubiq, ubiquity is just too long to write it all the time, command

// speeddial, sqlitemanager, fireftp, firefly
CmdUtils.CreateCommand({
name: "add-on-gui",
icon: "https://addons.mozilla.org/img/favicon.ico",
takes: {name: noun_arb_text},
execute: function(name){
var addon = name.text;
Utils.openUrlInBrowser( "chrome://"+addon+"/content/"+addon+".xul" );
}
});

Ubiquity is a javascript powered addon, they even included jQuery. It has several functions to let the creation of commands not stand in your way, CreateCommand is the most basic. As you see it takes a YAML like syntax as an argument, in javascript it's know as JSON.

What this command does is opening the GUI for add-ons like speeddial, sqlitemanager, fireftp, firefly in a new tab by pressing ctrl+SPACE, typing add-on-gui speeddial and pressing return.
If you used one of those add-ons extensively you could have bookmarked the url but in my opinion that makes your bookmarks more browser bound. Maybe i'm just an old school bookmarker thinking that bookmarks are only for websites.

Now i'm talking about bookmarks, another recent add-on is tagmarks. Tagmarks adds a number of icons next to the bookmark star in the locationbar for easy tagging. There are a few read later add-ons that want to make your bookmarks easier to maintain but firefox 3 bookmarks are database powered so maintaining them already is easy if you use the tag feature.
It comes out-of-the-box with a few tags most people won't find useful; radiation, add, stop. But creating your own tags is not that hard if you are willing to do a little bit of graphic work.

The icons are stored in the profile\extentions\tagmarks@felipc.com\chrome\skin\icons directory. If you look at the icons they have a grey and color part. This is called in css programming a sprite. Only one part of the image is visible. So if you want to make your own tagmark you have to make a sprite. I use xnview and inkscape to do it but there will be one application solutions.

  1. open the icon file you want to use in xnview

  2. grayscale the icon and save it

  3. import the color and gray icon in inkscape and position them next to eachother

  4. Select the two images and export as bitmap


Now all you need to do is, put the icon in the icons directory and open ...\tagmarks@felipc.com\chrome\content\taglist.js in notepad or another editor. There you find again a JSON formatted list that you can modify.

If you don't want to go through all this trouble you just press ctrl+SPACE, type tag any-tags-you-like and press return. So we are back to Ubiquity with one of the build-in commands. The add-on still needs a bit more work but it already proves to be an essential add-on, certainly for the people who are used to command line like applications as launchy, quicksilver, and others. Ubiquity will make it possible to reduce the number of add-ons if you like to type. But people who like GUI extensions are not left in the cold because of it.

Wednesday, June 18, 2008

First FF3 bug

In all the heat of the world record download attempt i still experience the same bug that kept me away from using the FF beta versions.

Closing the browser using alt-F4 or the close button in the upper right corner gets me me an empty page on restarting the browser when the homepage value is set to open previous tabs.

The only the tabs are restored is by closing the the browser with the file menu exit option.

Wednesday, May 07, 2008

IE8 < IE5

It's been a long time ago that i visited the windows update site and now that i installed IE8 beta i wanted to visit the site for the SP3 service pack but i've got the message i had to install IE with a higher version number than 5.

Is IE8 IE4 in disguise?

Sunday, March 23, 2008

php do

Recently i discovered you can't use do as a class method.

class Activate
{
function do()
{
return "it's good for you.";
}
}

if you want to use Activate::do() you will get an error.

Wednesday, March 12, 2008

simple word to number and number to word functions

I saw this python blog post and i wondered how the functions translate to php.

// to make the function language independent i put the array outside the functions
$array = array('zero','one','two','three','four','five','six','seven','eight','nine');
// number to words function
function d_to_w($digits,$array)
{
$temp = preg_split('//', $digits, -1, PREG_SPLIT_NO_EMPTY);
$return = array();
foreach($temp as $check)
{
if(is_numeric($check))
{
$return[] = $array[$check];
}
}
return implode(' ',$return);
}
// words to number function
function w_to_d($word,$array)
{
$temp = preg_split('/(\.|,|;|:| )/',$word, -1, PREG_SPLIT_NO_EMPTY);
$return = array();
foreach($temp as $check)
{
$temp2 = array_search(strtolower($check), $array);
if(is_numeric($temp2))
{
$return[] = $temp2;
}
}
return implode('',$return);
}

I've added a check to make the function more real world usable. An example use of the functions is;

echo d_to_w('100',$array).'
'.w_to_d('one zero zero',$array).'
';
echo d_to_w('1.00',$array).'
'.w_to_d('one,zero zero',$array).'
';

Saturday, February 16, 2008

Strange loop behaviour in php

I was doing some minor adjustments and i was puzzled why i could only get the last item from the loop. I found out the behavoir was created by a semi colon behind the round brackets.

$array = array(1,2,3);
foreach($array as $item);
{
echo $item;
}

Produces 3 and not 123 as expected.

Monday, November 12, 2007

CodeIgniter and jQuery

On the CodeIgniter forum there are quite a few jQuery questions so I'm bringing up some pointers.

jQuery file splitting


One big jquery file is great if you want to save http connections but it's not always the best approach. For instance if you have page specific code that doesn't need to be loaded until the visitor gets on that page.

Once you separated the page specific code into different files you can do two things :
- add the link to the javascript file to your page specific view
- have a variable in your view file and add the link to the javascript file when it's needed.
With the first method you can run into trouble if someone uploads his view without the javascript link. The second method can be a source of bugs if you have a templated site because the variable always needs a value if you add it to the basic lay-out.

Ajax


The relative url is most of the time (/index.php)/controller/method but if you refer to the same controller you can use ../method.

If you are using a get request don't add the parameters using jQuerys build in functionality but add them to the url (controller/method/key/value/key/value) and retrieve the key-value pairs using the CodeIgniter uri->uri_to_assoc method.

My latest jQuery snippets on the CodeIgniter forum


Content to new window
Highlight words using a sentence/keywords on the page
hack for inline links

Wednesday, October 31, 2007

jquery plugin : switchcss

Introduction



I was answering a question posed on the CodeIgniter forum about a stylesheet switcher and i came up with this code. It is rough but it worked.

Later that day i read in the mailinglist of jquery there was A Plugin Development Pattern tutorial

After reading this i wanted to make the rough code into a plugin and switchcss was born.

Features



Other stylesheet switchers i found where based on alternative stylesheets that had to be loaded and thus making the pages heavier to load. This was the concern of the poster on the CodeIgniter forum so i made this stylesheet switcher to work with one theme css that gets changed.

It remembers the chosen theme using a cookie.

Files



Dependencies:


switchcss plugin

Usage



Link to the files and at least one theme css file and add following code to your ready method

$(function(){
// previously chosen theme
$.cookieswitchcss();
// elements that hold the alternate themes
$('.switchcss').switchcss();
});

Now clicking on the elements changes the stylesheet and adds the theme to the cookie.

By default the css filename is prefixed with theme_ and the text of the element is extracted to add to the prefix of the name. And the link element should have the title themecss.

All the defaults :

cookiename

default : csstheme

linktitle

the value of the title attribute from the link element that holds the theme css file.

default : themecss

cssprefix

general prefix used by the theme css files

default : theme_

themename

Which value to use to complete the css file name.

text : content of the element

other : value of the attribute you define here

default : text



These options are used by the two functions so i made them public (thank you tutorial) so you only have to define them once.


$.fn.switchcss.defaults.linktitle = 'theme';
// gets the value of the title attribute of the anchors
$.fn.switchcss.defaults.themename = 'title';
$.cookieswitchcss();
$('a').switchcss();


I hope it comes in handy for someone.

Thursday, October 18, 2007

Instant form validation

When you think about javascript validation and when to trigger it the first thing you think about is the onblur event. The trouble with the onblur even is not everyone is tabbing through form so it's possible not all fields are validated. The same goes for a key event.

So most of the programmers use the click event to submit the form. The problem in asp.net is that if you use the asp:net button tag the javascript of the asp.net control is handled after your own javascript code so the form is processed even if you added return false for the event.

I don't know how to influence the control behavior yet so what i did is attach the validation to the button mouseover event. This way you see the errors before you even click the button.

I don't know why i haven't thought of that before because it's so easy and noticeable.

You can find a demo at mouseover button validation

Friday, August 31, 2007

date class update

I hadn't used the class before i posted it, stupid me, therefore i wasn't aware of the problem inserting the custom dateformat in a sql statement.

Mysql formats the dates as following yyyy-mm-dd hh:mm:ss so i had to convert the custom format into the database format. As you can see the added function dbformat is pretty simple leaving room for self formatted date strings.

In the interface functions i call the dbformat function and that gets the class up and running.




class Datemodel extends Model
{
function Datemodel()
{
parent::Model();
}

/**
*
* interface functions
*
*/

function get($format = 'YmdHis', $date = null)
{
$date = (!isset($date))?$this->timestamp('db'):$this->dbformat($date);
return $this->format($date,$this->preformat($format));
}

function getstr($str,$format = 'YmdHis', $date = null)
{
$date = (!isset($date))?$this->timestamp('db'):$this->dbformat($date);
$sign = substr($str,0,1);
$period = trim(substr($str,1));
return $this->get($format,$this->interval($date,$sign,$period));
}

/**
*
* helper functions
*
*/

function timestamp($type = '')
{
switch($type)
{
case 'db': $query = $this->db->query('select NOW() as ts'); break;
default: $query = $this->db->query('select NOW()+0 as ts'); break;
}
$row = $query->row();
return $row->ts;
}

function format($date,$format)
{
$query = $this->db->query('select date_format("'.$date.'","'.$format.'") as val');
$row = $query->row();
return $row->val;
}

function interval($date,$sign,$period)
{
switch($sign)
{
case '+': $query = $this->db->query('select date_add("'.$date.'", interval '.$period.') as val'); break;
case '-': $query = $this->db->query('select date_sub("'.$date.'", interval '.$period.') as val'); break;
}
$row = $query->row();
return $row->val;
}

function dbformat($date)
{
if(strlen($date) == 14)
{
$year = substr($date,0,4);
$month = substr($date,4,2);
$day = substr($date,6,2);
$hour = substr($date,8,2);
$min = substr($date,10,2);
$sec = substr($date,12,2);
$date = $year.'-'.$month.'-'.$day.' '.$hour.':'.$min.':'.$sec;
}
return $date;
}

function preformat($str)
{
$array = array('%','a','b','c','d','e','h','i','j','k','l','m','p','r','s','u','v','w','x','y','D','H','I','M','S','U','V','W','X','Y');
foreach($array as $char)
{
$str = str_replace($char,'%'.$char,$str);
}
return $str;
}
}
?>


Saturday, August 25, 2007

mysql date functions for own timestamp format

Introduction

I recently got familiar with the limitations of the unix_timestamp. I had to make it possible to generate dates from before 1970. This was a real pain because i had used the normal date functions of php.

So i had to come up with something quick and my first thought was using the date functions of mysql. Mysql doesn't have the 1970 limitation so i was free to use any date possible.

Because i don't wanted to change all the datatypes of the fields containing dates i had to find a numeric timestamp. This was not so hard, YYYYMMDDHHMMSS gives me a date range from 10000101010101 to 99991231235959.

The code
I got used to have two functions to generate timestamps, date and strtotime. Because i wanted my functions in a class i had to use short names because no self respecting programmer want to type a lot, but they do it any way.
get and getstr seemed descriptive enough because i named the class date.

I made the class as a model class for code igniter because that's the framework i use nowadays for almost all my projects. But changing it to native php code is not going be to hard.
i only show the basic, alpha class here because i first want to test the more complex functions.



class Datemodel extends Model
{
function Datemodel()
{
parent::Model();
}

/**
*
* interface functions
*
*/

function get($format = 'YmdHis', $date = null)
{
if(!isset($date)){ $date = $this->timestamp('db'); }
return $this->format($date,$this->preformat($format));
}

function getstr($str,$format = 'YmdHis', $date = null)
{
if(!isset($date)){ $date = $this->timestamp('db'); }
$sign = substr($str,0,1);
$period = trim(substr($str,1));
return $this->get($format,$this->interval($date,$sign,$period));
}

/**
*
* helper functions
*
*/

function timestamp($type = '')
{
switch($type)
{
case 'db': $query = $this->db->query('select NOW() as ts'); break;
default: $query = $this->db->query('select NOW()+0 as ts'); break;
}
$row = $query->row();
return $row->ts;
}

function format($date,$format)
{
$query = $this->db->query('select date_format("'.$date.'","'.$format.'") as val');
$row = $query->row();
return $row->val;
}

function interval($date,$sign,$period)
{
switch($sign)
{
case '+': $query = $this->db->query('select date_add("'.$date.'", interval '.$period.') as val'); break;
case '-': $query = $this->db->query('select date_sub("'.$date.'", interval '.$period.') as val'); break;
}
$row = $query->row();
return $row->val;
}

function preformat($str)
{
$array = array('%','a','b','c','d','e','h','i','j','k','l','m','p','r','s','u','v','w','x','y','D','H','I','M','S','U','V','W','X','Y');
foreach($array as $char)
{
$str = str_replace($char,'%'.$char,$str);
}
return $str;
}
}
?>



As you can see the sql statements are very simple and for the format i made it possible to use the letter only format instead of the mysql format.

Future
This is only a basic, alpha class which should not be used on production sites.

i'm planning to make the class cross-database so it can be used everywhere and for now i'm testing a more complex method, diff, which takes care of date calculations. And the possibility for getstr and diff to be aware of weekends and vacations.

Saturday, July 28, 2007

Programmers and black holes

it's been awhile since i posted because i'm busy working on some things. I have to many ideas and to little time to work things out.

The one thing that is visible is the simple view library for the code igniter framework. I have abandoned it for a while because i needed to train a puppy but i will pick it up soon.

Apart from that i had the idea of creating an integrator library to generate jQuery code using only php. It's an effort which is maybe to much to handle alone but i want to have at least a proof of concept code.

In the past month(s) i also realised there is a big gap between developers and users. Where developers speak about rendering engines and applications, users speak about websites. Users don't care about programming languages, progressive enchantment, ajax, ... . They care about does the site does what i want it to do and does it do it fast and does it look nice enough to work on. I never understood why people wanted to work with the black and white/green programs and still do. I don't care much about how a certain button looks like but it has to te be descriptive or at least consistent within the GUI.

i'm going to have myself a summer of code on my own so keep checking the blog.

Thursday, May 31, 2007

Php timestamp

I've been working with dates recently and today i became aware there are four methods to generate a timestamp.

echo time();
echo date('U');

These are the simplest functions. Then there is the mktime function which is the worst function of them all. The arguments are hour,minutes,seconds,month,day,year. I don't know which type of dateformat that should mirror but it's not a format i know of.

And then there is the most human accessible function strtotime. But there is one problem if you want the last day of the next month for example then you have to use strtotime two times.

My function combines mktime, time and strtotime functions into one and as an extra it's possible to have multiple strtotime strings in an array. Another extra is the possibility to change the timestamp output using the date function. The mktime function is accessed by a numeric value with the format yyyymmddhhmmss.

function tsgen($fromnow = '',$ts = '')
{
if($fromnow == '')
{
return ($ts == '')?time():date($ts);
}
else
{
if(is_array($fromnow))
{
$tempbegin = array_shift($fromnow);
$timestamp = strtotime($tempbegin);
if($timestamp == -1){ $timestamp = false; }
if (!$timestamp) {
return false;
}
else
{
$error = 0;
foreach($fromnow as $str)
{
$timestamp = strtotime($str,$timestamp);
if($timestamp == -1){ $timestamp = false; }
if (!$timestamp) { $error++; }
}
if($error > 0)
{
return false;
}
else
{
return ($ts == '')?$timestamp:date($ts,$timestamp);
}

}
}
else
{
if(is_numeric($fromnow) && strlen($fromnow) == 14)
{
return mktime(substr($fromnow,8,2), substr($fromnow,10,2), substr($fromnow,12,2), substr($fromnow,4,2), substr($fromnow,6,2), substr($fromnow,0,4));
}
else
{
$timestamp = strtotime($fromnow);
if($timestamp == -1){ $timestamp = false; }
if (!$timestamp) {
return false;
}
else
{
return ($ts == '')?$timestamp:date($ts,$timestamp);
}
}
}
}
}

Examples

echo tsgen();
echo tsgen('+1 day');
echo tsgen(20070101010101);
echo tsgen(array('+28 days','last friday'));
echo tsgen('next month','d-m-Y');

I hope people will enjoy using this unified timestamp/date function

Monday, April 09, 2007

GTD my way

Getting things done seems to be a new lifestyle but it's only new for the people that do only talking. Lifehacker is a blog devoted to make you do things with the least amount of time spend on additional tasks. Some ideas are good but i have a feeling other posts just want to sell you software.

If you already read my blog you know i already tried to improve working with windows but there are some changes which i want to share with you.

The software


There are only 3 applications that make me more productive and help me to give a better overview of my tasks.

Launchy : using the key combination alt+spacebar i never have to click on the startbutton to find an application or a folder.

TaskSwitchXP : alt+tab is already a powerful key combination of windons but this applications adds screenshots and it remembers the previous application for fast switching. It also lets you not only select through the key combination but holding the keys it lets you select with your mouse.

Yod'm 3d : the most recent addition. Virtual desktops are old news but the cube view made it more attractive and understandable. The key combination is alt+control+arrow key.

How i make it work for me


Hiding the taskbar is the first thing when i set up windows. It only is a distraction and with taskswitchxp you don't need to click on the applications to show them.

Setting up the system is easy. Because most of my time i use the browser it goes on the first virtual desktop together with my email application, this is my internet desktop. Using yod'm 3d keys(left arrow) i go to the second desktop to open explorer, this is my file desktop. using the right arrow yod keys twice i set up my development desktop. The ide application i need and other tools.

Now everything is set up i can go to work. I open each application full screen so other applications don't distract me. Because of this setup i only have a few applications to screen through to find the right one.

Improvements


I open my browser and my email client from startup. I could open explorer too but i don't know how to set it default to the desktop on the left.

Because yod'm 3d doesn't allow to scroll vertical through the desktops i'm limited to three quick accessible desktops instead of five.

Not every application is accessible through launchy but using bat shortcuts it's possible.

These key combinations can be changed and desktops can be adjusted to your own needs. The speed improvement lays in the quick access to short lists of applications.

Friday, April 06, 2007

The imagebutton

This week i needed a table with buttons to manipulate the individual rows. My first instinct was to use button tags so i could use their value instead of a hidden input but that was without thinking about internet explorer so i used the imagebutton.

The problem in internet explorer is that the value is always the text of the button. the image button is just an input tag with image as type. To make the button unique just add a number after the name.

for($i=0;$i<10;$i++){
?><p><input type="image" name="button<?php echo $i; ?>" src="image.jpg" value="button"></p><?php
}

Now there are ten unique buttons. The following step is to get the button from the post array. In the example we have a limited, static number of buttons but if it's a databasetable you need to connect the buttons with and unique field in the database so there can't occur any mistakes.
Because $_POST['button0'] will only return the button text in internet explorer so you need to use the mouse click coordinates of the button that get send. The coordinates are button0_x and button0_y.

for($i=0;$i<10;$i++){
if(strlen(array_search('button'.$i.'_x',array_keys($_POST))) > 0){
// do something
}
}

Now that you know click coordinates are send you can use them to make one button act as two.

$click = $_POST['test_x'];
if($click > 24){
$test = 'Delete button';
}else{
$test = 'Update button';
}

The previous code is the code i used on the example page.

conclusion


The image button can spare you an hidden input and act as two buttons.

Saturday, March 17, 2007

Asp.net : the datagrid

The datagrid controle is a powerful datacontrol but because of the amount of code to get it to work the way you want, it's a hard thing to crack for beginners. All code from this article is used in the example.

The html code



<asp:DataGrid ID="datagrid" runat="server" AutoGenerateColumns="false" ShowFooter="true"

The tag is named asp:DataGrid and like all controls it needs an id and a runat attribute.
The autogeneratecolumns attribute is needed when you want more control over the output of the data, this will be the case most of the time.
The showfooter attribute is selfexplaining and i added it because i want a row to insert new data.

OnEditCommand="datagridEdit" OnCancelCommand="datagridCancel" OnUpdateCommand="datagridUpdate" OnItemDataBound="datagridBound" OnItemCommand="datagridVarCommands" >

These are all hooks to functions for the different events.

Now we are going to style the datagrid. You can do it inside the datagrid tag but for better readability you have different style tags.

<HeaderStyle CssClass="th" />
<AlternatingItemStyle CssClass="even" />
<SelectedItemStyle CssClass="editrow" />

All style attributes can be use inside these tags but they don't have the same names as the standard html tags. There is also a FooterStyle tag.

The next thing to do is to set up the columns.

<Columns>
<asp:BoundColumn HeaderText="Id" DataField="id" Visible="false" ReadOnly="true"></asp:BoundColumn>

<asp:TemplateColumn HeaderText="Title">
<ItemTemplate><asp:Literal ID="title" runat="server"></asp:Literal></ItemTemplate>
<EditItemTemplate><asp:TextBox ID="editTitle" runat="server"></asp:TextBox></EditItemTemplate>
<FooterTemplate><asp:TextBox ID="addTitle" runat="server">></asp:TextBox></FooterTemplate>
</asp:TemplateColumn>

All columns must be inside the Columns tag.
The first column is of the type BoundColumn. This type has the least flexibility but is good for important processing data like an id or if the data can be displayed without manipulation. If you want to get the data from the column it's best to set the readonly attribute true so you can get it in every event as a string. If you set the visible attribute false the column will not be visible on the page but you can use the data that is stored in the column.

The second column is of the TemplateColumn type. Inside the template you have several tags to control the content and/or display of the column. I used ItemTemplate, that is manditory, EditItemTemplate and FooterTemplate. I repeated this for the other columns.
It is allowed to put input fields in every templatetag.

Now that we have the content of our data grid we need to add the buttons to manipulate it.

<asp:EditCommandColumn HeaderText="" EditText="Edit Info" UpdateText="Update" CancelText="Cancel"></asp:EditCommandColumn>

<asp:TemplateColumn HeaderText="">
<ItemTemplate><asp:LinkButton CommandName="Delete" Text="Delete" ID="btnDel" Runat="server" /></ItemTemplate>
<FooterTemplate><asp:LinkButton CommandName="Insert" Text="Toevoegen" ID="btnAdd" Runat="server" /></FooterTemplate>
</asp:TemplateColumn>

There are two special types of command columns. The EditCommandColumn generates three buttons for you:

- the edit button is used to change the row from regular view to edit view.
- the cancel button is used to change the row from edit view to regular view
- the update button is used to commit the changes in the edit view and return to the regular view if needed

These actions aren't programmed by default that is why you need to put the function hooks in the DataGrid tag.

The second command column is the ButtonColumn. It gives you a column with buttons who are bound to a function. It's less code but i need a column where i have delete buttons for the existing rows and an add button for inserting a row. That is why i added another TemplateColumn.

That was it for the html side of the control. If you have a long datagrid you can set the MaintainScrollPositionOnPostback true if you have the 2.0 framework or higher. If you use the 1.x framework you can use the 4GuysFromRolla solution, it worked for me.

C# code


The most important function in the code behind page is Page_Load. Here you call everything you need to display the page. Mine looks like this.

void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Data();
}
}

Data is the function that binds the database to the datagrid control. And because the data can be different after a button click it only binds the data when there is no button click. If you don't do this your data will never change because the function is called before all the others.

public void Data()
{
try
{
conn.Open();
string sql = "select id, title,description,online from Content order by title";
SqlCommand com = new SqlCommand(sql, conn);
SqlDataAdapter myDA = new SqlDataAdapter();
myDA.SelectCommand = com;

DataSet myDS = new DataSet();
myDA.Fill(myDS);

datagrid.DataSource = myDS;
datagrid.DataBind();

}
catch (SqlException ex)
{
message.Text = ex.Message;
}
catch (Exception ex)
{
message.Text = ex.Message;
}
finally
{
conn.Close();
}
}

With the datagrid.DataSource variable you transfer the database query to the datagrid and datagrid.DataBind() does exactly what it says.

Now is you data connected with the datagrid but if you would run the code now you would see that only the BoundColumn has values. The template columns need some more attention.

public void datagridBound(Object sender, DataGridItemEventArgs e)
{
// get bound data row
DataRowView row = (DataRowView)e.Item.DataItem;

switch(e.Item.ItemType)
{
// @@@@ EDIT TEMPLATE
case ListItemType.EditItem:
((TextBox)e.Item.FindControl("editTitle")).Text = row["title"].ToString();
((TextBox)e.Item.FindControl("editContent")).Text = row["description"].ToString();
if ("1" == row["online"].ToString()) { ((CheckBox)e.Item.FindControl("editOnline")).Checked = true; }
break;
// @@@@ REGULAR TEMPLATES
case ListItemType.AlternatingItem:
case ListItemType.Item:
((Literal)e.Item.FindControl("title")).Text = row["title"].ToString();
((Literal)e.Item.FindControl("content")).Text = row["description"].ToString();
string online = "No";
if("1" == row["online"].ToString()){ online = "Yes"; }
((Literal)e.Item.FindControl("online")).Text = online;
break;
}

}

The datagridbound function takes care of the data for the regular templates and for the edit template. This way you have all the bound data manipulations in one function.
There is another way to bind the data in the templatetags.

<ItemTemplate><%# DataBinder.Eval(Container, "DataItem.id")%></ItemTemplate>

To manipulate this data you need to create a function, if you need to do this for several columns it can add a lot of code.

Next we have the event functions

public void datagridEdit(Object sender, DataGridCommandEventArgs e)
{
datagrid.EditItemIndex = (int)e.Item.ItemIndex;
Data();
}

public void datagridCancel(Object sender, DataGridCommandEventArgs e)
{
datagrid.EditItemIndex = -1;
Data();
}

These functions are for the edit and cancel button from the EditCommanndColumn.

public void datagridUpdate(Object sender, DataGridCommandEventArgs e)
{
message.Text = "<p>Updated row:</p><p>Id : " + e.Item.Cells[0].Text + "</p>";
message.Text += "<p>Title : " + ((TextBox)e.Item.FindControl("editTitle")).Text+"</p>";
message.Text += "<p>Content : " + ((TextBox)e.Item.FindControl("editContent")).Text + "</p>";
string online = "No";
if (((CheckBox)e.Item.FindControl("editOnline")).Checked) { online = "Yes"; }
message.Text += "<p>Online : " + online + "</p>";
Data();
}

This function supports the update button. Normally you will put your database code to update the databasefields.

public void datagridVarCommands(Object sender, DataGridCommandEventArgs e)
{
switch(e.CommandName)
{
// !!!! DELETE
case "Delete":
message.Text = "<p>Delete row</p><p>Id : " + e.Item.Cells[0].Text + "</p>";
break;
// !!!! ADD
case "Insert":
message.Text = "<p>Insert row:</p>";
message.Text += "<p>Title : " + ((TextBox)e.Item.FindControl("addTitle")).Text + "</p>";
message.Text += "<p>Content : " + ((TextBox)e.Item.FindControl("addContent")).Text + "</p>";
string online = "No";
if (((CheckBox)e.Item.FindControl("addOnline")).Checked) { online = "Yes"; }
message.Text += "<p>Online : " + online + "</p>";
break;
}
}

This last function is used to handle the delete and add buttons.

Conclusion


There is a fair amount of code necessary to come to a working datagrid but there are also parts where the datagrid control does the legwork. You can do a lot more with the datagrid control but the code in this article will come back most of the times.

The full code can be dowloaded.

Friday, March 16, 2007

Menu with javascript elements

There are a lot of javascript menu enchanters but the one thing seems to be missing the ability to degrade the menu.

I made an example that generates a part of the menu in javascript and a part that is accessible all the time. I wanted to have a different design for the non javascript menu.

The code can be shorter but i wrote it out so it's easier to understand.

Saturday, March 03, 2007

Google services going down?

In one day i got accused by google search and blogger of being a robot. Now i know i like technology but there aren't any computerized parts in my body, yet.

At work i was looking for code snippets and suddenly i got a page telling me my computer was infected and i had to fill in the captcha and then i could continue.

When i came home i wanted to write a poem on my other blog but it was flagged as a spam blog. I had to verify again that i was a human but to make it harder the captcha kept disappearing in firefox. I had to do the verification with internet explorer.

I read in the feeds people were having trouble with gmail as well. My gmail is a secondary email so i don't have a problem if it breaks down but people who depend on gmail as their master mail center must have had a hard time.

I think it's a conspiracy to promote the image captcha. People are coming up with other ways to protect their sites against bots and google can't have that. Then they can't do anything with the ocr software they bought or developed, i'm not sure. Tricks to outsmart the king of bots is a big no-no.

Anyway i'm declared human again by google search and blogger, sci-fi has become reality, now i can implant many rfid tags and a bioport for games.

Saturday, February 24, 2007

Lay-out html

i had to do a cross browser design and i adapted some new techniques and learned some new things.

The html code


The 'new' thing on the block for css layout are the conditional statements. They are comments that acts like if statements. Browsers don't render css the same and when you use these statements you can keep your css files clean of hacks. Much of the rendering quirks have to do with positioning the elements so you can create a general css file for the cross-browser styles. Because some of the rendering is different in IE6 and IE7 you can create a general IE file. So lets look at the code for it now, the css examples will follow later.

<link rel="stylesheet" type="text/css" href="css/default.all.css">
<!--[if IE]> <link href="css/default.ie.css" rel="stylesheet" type="text/css"> <![endif]-->
<!--[if lte IE 7]> <link href="css/default.ie7.css" rel="stylesheet" type="text/css"> <![endif]-->
<!--[if lte IE 6]> <link href="css/default.ie6.css" rel="stylesheet" type="text/css"> <![endif]-->
<!--[if !IE]>--> <link href="css/default.non.ie.css" rel="stylesheet" type="text/css"> <!--<![endif]-->

The conditional comments can be hidden, like the IE stylesheets, or visible like the non iE stylesheets.

The css code


Another thing i discovered is the peek-a-boo bug when there are floating divs inside another div. If you want to display a border for the container div the border disappears and appears magically if you scroll the page. Of course this only happens with IE.

There are two solutions. One is to set the position to relative but i experienced that if there is a hover-to-showmenu that works with absolute positions the shown items appear to be under the relative positioned element.
Here is where solution 2 kicks in. With the IE only zoom style you can get rid of the peek-a-boo bug without breaking javacripted behaviour if you set it to 1.

It's a bit of common knowledge but maybe someone can benefit from this.