Monday, December 1, 2008

Web-related Drag theory

After vain attemps to realize a good drag method in a web enviorment, i finally understand what i guess is the best way.
A little bit of history :p ...
I started months ago, interested in web dashboard, to implement a dom-drag, i done but it works bad. Sometimes the dragged element "loose the focus" so the mouse pointer go ahead and the element stays back; then when i try to drag it once again it goes away far from mouse :p.
I try in two differents spheres:
Pure DOM-Drag and SVG-Drag (helped by jquery).
Now im gonna tell you my solution..
All is based around 3 javascript events: onmousedown, onmousemove and onmouseup.

onmousedown:
------------
This event mean the drag start. Set the elment fired as the event's target; store a variable to true which mean the drag is start. This event should be defined in every draggable elements.

onmouseup:
----------
This event mean that the drag is ended. Set the focused element stored with onmousedown to null and to false the variable setted at onmousedown. I think the best is to "bind" this event in the whola document, so if the pointer "goes out" the element this event will be "fired" anyway.

onmousemove:
------------
This event is the real drag! This event should be set in the container (maybe the whola document) in which the element is dragged. All you have to do is to set the coordinates of the dragged element (set by onmousedown) to this event's coordinate (if and only if the variable stored in onmousedown is true!).

Onmousedown set the element, tell the "engine" that somthing should be drag, onmousemove get the pointer coordinates and set it as the dragged-element coordinate, onmouseup free all resource and cut off the drag.

Have a nice day!
UPDATE: Pretty Code

var startDrag = false;
var obj = document.getElementById('dragme');
document.onmousemove = function(evt) {
if(startDrag) {
obj.innerHTML = '(' + evt.pageX + ';' + evt.pageY + ')';
obj.style.left = evt.pageX + 'px'
obj.style.top = evt.pageY + 'px'
}
}

document.onmouseup = function(evt) {
startDrag = false;
obj.innerHTML = 'Drag-me';
}

obj.onmousedown = function(evt) {
startDrag = true;
}

Tuesday, November 4, 2008

Regex in markup

Well, in an older post (the italian one only) i made intensive use of regex to retrive HTML tags text content. Well, now i want to give you a simple trick to do this in a more elegant way.
Be careful: this post doesn't want to explain regex at all!
We all know that a markup tag with a content look like <tag_name>content</tag_name>.
Well to retrive the content we only need to match everything between tag_name, we match it as:
"everything tat is not the character 'less than'".
So the regex look like: /<tag_name>([^<]+)<\/tag_name>/

here a php interactive session:

Interactive shell

php > $string = "<tag_name_one>http://tag_name_one.com</tag_name_one><tag_name_two>123 ## @ jhkasdfh</tag_name_two>";
php > $tag_name = "tag_name_one";
php > $result = array();
php > preg_match("/<$tag_name>([^<]+)<\/$tag_name>/", $string, $result);
php > print_r($result);
Array
(
[0] => <tag_name_one>http://tag_name_one.com</tag_name_one>
[1] => http://tag_name_one.com
)
php > $tag_name = "tag_name_two";
php > preg_match("/<$tag_name>([^<]+)<\/$tag_name>/", $string, $result);
php > print_r($result);
Array
(
[0] => <tag_name_two>123 ## @ jhkasdfh</tag_name_two>
[1] => 123 ## @ jhkasdfh
)

About duality

Find a place to die, find another way to fail, find another sin to do...
Find The place to live, find your own way to win, find another good thing to do...
That's about duality, that's about what i think about life, that's why.i.am.here.
Nothing is true nothing is false, it's just about duality, there's a thing and it's opposite, and the circle get close with the opposite thing inside it's opposite.
What is real and what is not, doesn't really care, what care is to choose your actions between your mind and your heart; don't let them haze your mind don't let them dirty your heart... Promise me, keep in mind.
What about you, what about me... nothing is safe now and nothing is lost at all.
Keep in mind: true false truelse falrue and so on and again...

Thursday, October 9, 2008

Improve mapidev

In order to gain more visibility and gain more readers, i'm thinking about to switch my language to english.

Hope this could be useful, and most of all will helps to let more people to know what i write.

Numeri di telefono on the fly

NB: Italian only, this script is useful for italian only readers. This script recive as input an italian phone number and give its holder as output.

In questo post vediamo come ricavere on the fly informazioni su intestatari di numeri di telefono.

Si tratta di due scritp pensati per essere eseguiti direttamente dall'interprete php.

Può essere utile in ufficio sapere in anticipo chi sta telefonando e consultare il sito delle pagine bianche può risultare un dispendio di tempo. Questi script si occupano di interrogare il sito delle pagine bianche fornendo un numero di telefono; se questo è presente nell'elenco verrà visualizzato nella shell evitando i tempi di attesa del browser.

Gli script si servono della libreria curl, quindi è necessario averla propriamente installata sulla propria macchina.

Grazie alla curl, lo script interroga lo script delle pagine bianche incaricato di restituire il numero di telefono; ricevono in risposta il codice html che verrebbe normalmente visualizzato nel broswer. A questo punto il comportamento degli script è differente. Uno ricava i dati servendosi di regex; l'altro istanzia due oggetti: un DOMDocument e un DOMXPath; i dati vengono ricavati con query xpath.

La pagina di risposta delle pagine bianche formatta i dati all'interno di tag che (salvo grosse modifiche alla pagina!!) sono sempre gli stessi;, in questo modo è possibile ricavare i dati. Vediamo il codice degli script, tenendo presente che grosso modo la performance è praticamente identica.

pagine_bianche_regex.php

if($argc != 2) die("Parametro necessario: Numero di telefono\nNon devono essere presenti spazi all'interno del numero.\n\n");
$tel = $argv[1];
$url = "http://www.paginebianche.it/execute.cgi?btt=1&ts=106&cb=8&l=it&mr=10&rk=&om=&qs=$tel";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$out = curl_exec($ch);
$m = array();
$test = preg_match('/<h3 class\=\"org\">([a-zA-z\s]+)<\/h3>/',$out, $m);
echo "\n\t$tel";
if($test == 0) die("\n\tNumero Non Trovato\n\n");
echo "\n\tIntestatario/a: ".$m[1]."\n";
preg_match('/<span class="postal\-code">([0-9]+)<\/span>/', $out, $m);
echo "\tIndirizzo: ".$m[1]." ";
preg_match('/<span class="locality">([a-zA-z\s]+)<\/span>/', $out, $m);
echo $m[1]." ";
preg_match('/<span class="region">\(([A-Z]{2})\)<\/span>/', $out, $m);
echo $m[1]." ";
preg_match('/<span class="street\-address">([A-Za-z\s0-9,]+)<\/span>/', $out, $m);
echo $m[1]."\n\n";
curl_close($ch);

pagine_bianche_xpath.php

if($argc != 2) die("Parametro necessario: Numero di telefono\nNon devono essere presenti spazi all'interno del numero.\n\n");
$tel = $argv[1];
$url = "http://www.paginebianche.it/execute.cgi?btt=1&ts=106&cb=8&l=it&mr=10&rk=&om=&qs=$tel";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$out = curl_exec($ch);
$html = DOMDocument::loadHTML($out);
$xp = new DOMXpath($html);
echo "\n\t$tel";
$data = $xp->query("//h3[@class=\"org\"]");
if($data->length == 0) exit("\n\tNumero Non Trovato\n\n");
echo "\n\tIntestatario/a: ".$data->item(0)->nodeValue;
$data = $xp->query("//span[@class=\"postal-code\"]");
echo "\n\tIndirizzo: ".$data->item(0)->nodeValue;
$data = $xp->query("//span[@class=\"locality\"]");
echo " ".$data->item(0)->nodeValue;
$data = $xp->query("//span[@class=\"region\"]");
echo " ".$data->item(0)->nodeValue;
$data = $xp->query("//span[@class=\"street-address\"]");
echo " ".$data->item(0)->nodeValue."\n\n";
curl_close($ch);

Wednesday, October 8, 2008

A little help

Im gonna show you a simple function in php that will help you to generate the easiest insert mysql query (yet another...).

I use it in a personal web application, someone could find it useful too. It's just an alpha definition, but i really doubt to bring new modifications.

Context:

This function have been called in a asynchronous way from javascript (by XHR), so the parameters comes from $_GET array.

The function accept these parameters as input:

  • $table: name of the table the query concern;
  • $get_unset: ignored $_GET array's indexes that don't need to build the query;
  • $auto_id: this boolean flag is set to true if in that table exist an index called id which is autoincrement

It is clear the follow adaptations should be take into consideration: add an array parameter as a substitute of $_GET array, so $unset_get could be remove from the parameters list. 

Here the code:

function generate_query($table, $get_unset = null, $auto_id = true) {
  $field = "";
  $value = "";
  foreach($get_unset as $gu) unset($_GET[$gu]);
  $query = "INSERT INTO $table(";
  foreach($_GET as $k => $v) {
    $field .= "$k, ";
    $value .= "'$v', ";
  }
  if($auto_id) $query .= "id, ";
  $query .= substr($field, 0, -1).") VALUES(";
  if($auto_id) $query.="null, ";
  $query .= substr($value, 0, -1).")";
  return $query;
}

Tuesday, October 7, 2008

Xiaolin Wu look like circle

Xiaolin Wu had implement an algorithm to draw fast antialiased lines and circles.

In this post i will consider the circle.

His idea is based on draw the points next to the real circumference. Drawing that points with different intensity so that will be inverse proportion to the distance from the center and the total sum of the intensities will be constant.

The lemma that leads the plot loop is interesting as complex, so i advise you to search others resources, such as "Graphics Gems II" (you can find on google books the description i'm talkin about).

But i thought to change a little Xiaolin Wu's algorithm in this way:

  • I first plot the original circle;
  • I add two points with different intensity to the nearest real one.
It's a very fast way to draw antialias circle in php.

If you need a fast antialias cirlce to draw in php here's an implementation:

[EDIT : antialias circle full implementation here]

function distance(rad, y) {
real_point = SQRT ( rad*rad - y*y)
return CEIL(real_point) - real_point
}

i = rad
j = 0
I(i, j) = I
T = 0

WHILE ( i <= j ) { j = j + 1; IF distance(rad, j) > T THEN i = i + 1
I(i, j) = distance(rad, j)
I(i - 1, j) = distance(rad, j)
T = distance(rad, j)
}

How I translate sum pieces in PHP?

function distance($r, $y) {
$real_point = sqrt(pow($r, 2) - pow($y, 2));
return ceil($real_point) - $real_point;
}

function new_color($i) {
return $i * 127;
}

// ... plot loop

$current_distance = distance($r, $y);
$transparency = new_color($current_distance);

$alpha = imagecolorallocatealpha($img, /* colore */, $transparency);
$alpha2 = imagecolorallocatealpha($img, /* colore */, 127 - $transparency);

imagesetpixel($image, $x, $y, imagecolorallocate(/* ... */)); // real point
imagesetpixel($image, $x - 1, $y, $alpha2 ); // nearest, inside
imagesetpixel($image, $x + 1, $y, $alpha ); //nearest, outside

The results, high zoom to recognize how the algorithm works:

Finally the result:

Rectangles

Objective: A function allow to draw a rectangle, so we want to supply top-left corner coordinates, width and height. These variables must be retrive by click-drag-relase mouse.

The most easy way consists by click and drag the mouse in bottom-right direction. Retrive the 4 variables will be easy as follow:

  • x coordinate: first mouse click x coordinate;
  • y coordinate: first mouse click y coordinate;
  • width: mouse relase - x coordinate;
  • height: mouse relase - y coordinate.

Well these easy calculations doesn't work in the follow other instances:

  1. Mouse direction is to top-right (negative height);
  2. Mouse direction is top-left (both widht and height negatives);
  3. Mouse direction is bottom-left (width negative).

It is easy to get real width and height, we only need to take measurements as absolute value; find out the top-left corner coordinates too.

If a size is less then zero, it means that its coordinate will be the same as the mouse coordinate at the relase point.



width = mouse_end_x - mouse_start_x
height = mouse_end_y - mouse_start_y
IF ( width < 0 ) THEN rect_x = mouse_end_x ELSE rect_x = mouse_start_x
IF ( height < 0 ) THEN rect_y = mouse_end_y ELSE rect_y = mouse_start_y
rectangle ( rect_x, rect_y, |width|, |height| )