iGoogle interface updated to lastest version of jQuery

5 09 2011

Many people have asked me to update my example of an iGoogle interface to the lastest version of jQuery. I have also repaired a problem with the database connection (I had moved my webpage to a different hosting company).

Here is the new version: http://www.jsabino.com/test2/

I have used jQuery 1.6.2 and jQuery UI 1.8.16.

You can also download the full source code here: http://www.jsabino.com/iNettutsDB3.zip

Thank you very much for all your comments.

Mario

Anuncios




Resolución del problema de cifras del programa “Cifras y letras” con PHP

21 05 2010

Resulta que hoy al llegar a comer a casa, haciendo zapping, me he enganchado un rato al programa “Cifras y letras”, en Telemadrid. En el problema de las cifras, han salido varios muy complicados, donde los concursantes se han quedado muy lejos del exacto. Pero claro, la presentadora sí tenía el exacto, con unas operaciones que no se le habrían ocurrido ni de lejos. Por supuesto, pensé, la solución se la ha dado el ordenador.

Así que, según he terminado de comer, he dicho: vamos a hacer en PHP un programita que resuelva el problema. Es fácil, una función recursiva que examine todas las posibilidades y se quede con la mejor. En una hora aproximadamente, he obtenido esto:

$final=859;
$numbers=array(6,6,7,25,10,1);

$best=0; $solution="";

Calc($numbers,"");
echo "$best<br><br>$solution";

function Calc($numbers,$sol) {

  global $best,$final,$solution;

  if ($best==$final) return ;

  if (count($numbers)==1) {
    if (abs($numbers[0]-$final)<abs($best-$final)) {$best=$numbers[0]; $solution=$sol;}
  } else {
    foreach ($numbers as $number) {
      if (abs($number-$final)<abs($best-$final)) {$best=$number; $solution=$sol;}
      if ($best==$final) return ;
    }
    for ($i=0;$i<count($numbers)-1;$i++) {
      for ($j=$i+1;$j<count($numbers);$j++) {

        // Suma
        $new_numbers=$numbers;
        unset($new_numbers[$i]);
        unset($new_numbers[$j]);
        $new_numbers = array_values($new_numbers);
        array_push($new_numbers,$numbers[$i]+$numbers[$j]);
        Calc($new_numbers,$sol.$numbers[$i]."+".$numbers[$j]."=".($numbers[$i]+$numbers[$j])."<br>");

        // Multiplicación
        $new_numbers=$numbers;
        unset($new_numbers[$i]);
        unset($new_numbers[$j]);
        $new_numbers = array_values($new_numbers);
        array_push($new_numbers,$numbers[$i]*$numbers[$j]);
        Calc($new_numbers,$sol.$numbers[$i]."x".$numbers[$j]."=".($numbers[$i]*$numbers[$j])."<br>");

        // Resta 1
        if ($numbers[$i]-$numbers[$j]>0) {
          $new_numbers=$numbers;
          unset($new_numbers[$i]);
          unset($new_numbers[$j]);
          $new_numbers = array_values($new_numbers);
          array_push($new_numbers,$numbers[$i]-$numbers[$j]);
          Calc($new_numbers,$sol.$numbers[$i]."-".$numbers[$j]."=".($numbers[$i]-$numbers[$j])."<br>");
        }

        // Resta 2
        if ($numbers[$j]-$numbers[$i]>0) {
          $new_numbers=$numbers;
          unset($new_numbers[$i]);
          unset($new_numbers[$j]);
          $new_numbers = array_values($new_numbers);
          array_push($new_numbers,$numbers[$j]-$numbers[$i]);
          Calc($new_numbers,$sol.$numbers[$j]."-".$numbers[$i]."=".($numbers[$j]-$numbers[$i])."<br>");
        }

        // División 1
        if (($numbers[$j]!=0) && ($numbers[$i]%$numbers[$j]==0)) {
          $new_numbers=$numbers;
          unset($new_numbers[$i]);
          unset($new_numbers[$j]);
          $new_numbers = array_values($new_numbers);
          array_push($new_numbers,$numbers[$i]/$numbers[$j]);
          Calc($new_numbers,$sol.$numbers[$i]."/".$numbers[$j]."=".($numbers[$i]/$numbers[$j])."<br>");
        }

        // División 2
        if (($numbers[$i]!=0) && ($numbers[$j]%$numbers[$i]==0)) {
          $new_numbers=$numbers;
          unset($new_numbers[$i]);
          unset($new_numbers[$j]);
          $new_numbers = array_values($new_numbers);
          array_push($new_numbers,$numbers[$j]/$numbers[$i]);
          Calc($new_numbers,$sol.$numbers[$j]."/".$numbers[$i]."=".($numbers[$j]/$numbers[$i])."<br>");
        }
      }
    }
  }
}

Por supuesto, el código se puede mejorar, pero desde luego, funciona a las mil maravillas. En el array $numbers con las cifras, se introducen los números con los que jugaremos. Y la variable $final es el número buscado. Como resultado, la página muestra el número más cercano obtenido y las operaciones realizadas para encontrarlo.

Después he pensado: bueno, seguro que esto lo ha hecho antes alguien. Pues sí, he encontrado esta solución implementada en C por Pedro Reina, pero con 841 líneas de código (incluidos los comentarios). En PHP yo lo he solucionado con las míseras 83 líneas que podéis ver más arriba.

Otro día me pongo con el problema de las letras…





A complete iGoogle like interface example with jQuery

5 05 2010

After my previous post about how to mimic the iGoogle interface with database, I have been working in a new version. Now I have added all you need to build a simple page, with these features:

  • The user starts with an empty page, where he can add widgets. There is a link “Add widget at column …” that creates a new widget at the selected column.
  • Any widget can be configured in the same way that before.
  • Widget content comes from an ajax request to a page called “widgets_rpc.php”. This page receives the id of the widget and should respond with the HTML content of that widget.
  • Widget configuration is stored in the database when the user changes something and loaded at the beginning.

You can see a working example here: http://www.jsabino.com/test

And you can download the complete source code here: http://www.jsabino.com/iNettutsDB2.zip

Inside the ZIP file, you can find:

  • script.sql: the script to create the required table in the database. You must execute it.
  • iNettuts_rpc.php: the same file for saving and loading widget configuration. Change here the database connect parameters (server, database, username and password).
  • index.html: now it is a simple page with the columns layout but without any widget, because they are created dynamically by a function called “Add”. It looks for the last added widget id and creates a new one in the selected column.
function Add() {
  var i=1;
  while ($("#widget"+i).length>0) i++;
  iNettuts.addWidget("#"+$("#col").val(), {
    id:    "widget"+i,
    color: "color-blue",
    title: "widget "+i
  })
}
  • widgets_rpc.php: file that retrieves the content of each widget. It is a simple version showing only “This is the content for widget n” yet.
  • inettuts.js: the core file where the widget logic is located. It was first programmed by James Padolsey but I have changed many things. There are three new functions: initWidget (returns the default widget layout), loadWidget (gets widget content with an ajax call) and addWidget (creates a new widget). I have also modified makeSortable (now it is called several times) and sortWidgets (draws widgets in a different way).
initWidget : function (opt) {
  if (!opt.content) opt.content=iNettuts.settings.widgetDefault.content;
  return '<li class="new widget '+opt.color+'"><div class="widget-head"><h3>'+opt.title+'</h3></div><div class="widget-content">'+opt.content+'</div></li>';
},

loadWidget : function(id) {
  $.post("widgets_rpc.php", {"id":id},
    function(data){
      $("#"+id+" "+iNettuts.settings.contentSelector).html(data);
    }
  )
},

addWidget : function (where, opt) {
  $("li").removeClass("new");
  var selectorOld = iNettuts.settings.widgetSelector;
  iNettuts.settings.widgetSelector = '.new';
  $(where).append(iNettuts.initWidget(opt));
  iNettuts.addWidgetControls();
  iNettuts.settings.widgetSelector = selectorOld;
  iNettuts.makeSortable();
  iNettuts.savePreferences();
  iNettuts.loadWidget(opt.id);
},

I have tested this example both in Firefox and Internet Explorer. Some users have reported problems in the comments of my last article, but it works fine for me.





How to Mimic the iGoogle Interface with Database

19 09 2009

James Padolsey wrote a great tutorial about “How to mimic the iGoogle interface” with jQuery. Thank you very much, James. I have used your code intensively.

The next step was a new article explaining how to save widgets configuration into a cookie. Very useful too. But the final part was to store that data in a database.

That’s what a have done: an example of the same code, but using a database. The changes are very easy to implement. I have just had to modify savePreferences and sortWidgets functions in inettuts.js file, and to write a new PHP file for saving and loading data.

I call jQuery post function to send the data using AJAX for savePreferences:

$.post("iNettuts_rpc.php","value="+cookieString);

As you can see, cookieString is the same variable stored into a cookie. Then iNettuts_rpc.php manages with the database. It’s a very simple PHP showing how to store the value for a user called John Doe:

header("Cache-Control: no-cache");
header("Pragma: nocache");

// User_id -&gt; Should come from a session variable
$user_id="john doe";

// DB connect parameters
$server="localhost";
$user="root";
$password="";
$database="iNettuts";

$table="iNettuts";
$field="config";

// DB connect
mysql_connect($server,$user,$password);
@mysql_select_db($database);

if (isset($_REQUEST["value"])) {
 // SET value  

 $value=$_REQUEST["value"];

 $rs=mysql_query("SELECT * FROM $table WHERE user_id='$user_id'");
 if (mysql_numrows($rs)==0)
 mysql_query("INSERT INTO $table($field,user_id) VALUES('$value','$user_id')");
 else
 mysql_query("UPDATE $table SET $field='$value' WHERE user_id='$user_id'");
 echo "OK";

} else {
 // GET value 

 $rs=mysql_query("SELECT $field FROM $table WHERE user_id='$user_id'");
 if ($row=mysql_fetch_row($rs))
 echo $row[0];
 else
 echo "";
}

mysql_close();

And finally, the most difficult part: loading data to sort widgets:

sortWidgets : function () {
 var iNettuts = this,
 $ = this.jQuery,
 settings = this.settings;

 if(!settings.saveToCookie) {
 $('body').css({background:'#000'});
 $(settings.columns).css({visibility:'visible'});
 return;
 }

 $.post("iNettuts_rpc.php", "",
 function(data){

 var cookie=data;

 if (cookie=="") {
 $('body').css({background:'#000'});
 $(settings.columns).css({visibility:'visible'});
 iNettuts.addWidgetControls();
 iNettuts.makeSortable();
 return;
 }

 /* For each column */
 $(settings.columns).each(function(i){

 var thisColumn = $(this),
 widgetData = cookie.split('|')[i].split(';');

 $(widgetData).each(function(){
 if(!this.length) {return;}
 var thisWidgetData = this.split(','),
 clonedWidget = $('#' + thisWidgetData[0]),
 colorStylePattern = /\bcolor-[\w]{1,}\b/,
 thisWidgetColorClass = $(clonedWidget).attr('class').match(colorStylePattern);

 /* Add/Replace new colour class: */
 if (thisWidgetColorClass) {
 $(clonedWidget).removeClass(thisWidgetColorClass[0]).addClass(thisWidgetData[1]);
 }

 /* Add/replace new title (Bring back reserved characters): */
 $(clonedWidget).find('h3:eq(0)').html(thisWidgetData[2].replace(/\[-PIPE-\]/g,'|').replace(/\[-COMMA-\]/g,','));

 /* Modify collapsed state if needed: */
 if(thisWidgetData[3]==='collapsed') {
 /* Set CSS styles so widget is in COLLAPSED state */
 $(clonedWidget).addClass('collapsed');
 }

 $('#' + thisWidgetData[0]).remove();
 $(thisColumn).append(clonedWidget);
 });
 });

 /* All done, remove loading gif and show columns: */
 $('body').css({background:'#000'});
 $(settings.columns).css({visibility:'visible'});

 iNettuts.addWidgetControls();
 iNettuts.makeSortable();

 });
 }

I have used the same variable names to make it easier.

You can download the full example here.





Bing vs. Google

4 09 2009

Desde la reciente presentación de Bing, el nuevo buscador de Microsoft, se ha escrito mucho sobre la calidad de ambos buscadores. ¿Cuál es mejor, Bing o Google?

Pues la respuesta es: decidid vosotros mismos. Y qué mejor forma de decidir que hacer la misma búsqueda en ambos buscadores. Para eso, he descubierto ésta página:

http://www.bing-vs-google.com

Basta con introducir el texto que quieres buscar y, como resultado, te aparecen Bing y Google en sendos frames verticales, con lo que puedes comparar los resultados fácilmente:

bing.vs.google

Yo he hecho varias pruebas. Por ejemplo, he introducido “php pdf”, una búsqueda bastante poco precisa, con el objetivo de encontrar información sobre la generación de ficheros PDF desde lenguaje PHP. En Google el primer resultado ha sido una página titulada Generar PDF con PHP y MySQL, justo lo que buscaba. Sin embargo, en Bing, los primeros resultados son páginas que hablan sobre PDF y tienen extensión PHP o al contrario. Es decir, nada relevantes. El primer resultado algo útil aparece en séptimo lugar, con el enlace al manual de la librería de PDF nativa en PHP, algo que Google también enlaza en sexta posición, pero después de cinco resultados realmente interesantes, como la librería FPDF o un par de blogs como desarrolloweb y webtaller.

Esta sensación se confirma con otras búsquedas realizadas y, además, en algunos casos se nota diferencia de velocidad de carga de los frames a favor de Google. Por lo tanto, mi veredicto está claro: me sigo quedando con Google. ¿Y vosotros?





Programando un CMS en verano

16 08 2009

Hace un calor tremendo en la calle y aquí estoy yo, programando un poco. Resulta que por cuestiones laborales, tengo que implementar una especie de gestor de contenidos, que ya va por la versión 2.0, pero que estoy rehaciendo casi por completo para la versión 3.0. La tecnología utilizada es PHP contra MySQL.

Todo empezó hace casi tres años, cuando tuve que implementar la primera versión. Apenas sabía PHP y tuve que buscarme la vida en tiempo record. Me basé en PHPNuke, cambiando mucho código para lograr cubrir los requisitos del cliente. Al menos, la aplicación lleva funcionando ya este tiempo en una gran empresa española, así que no debía estar tan mal.

Pero ahora he descubierto un nuevo mundo. Mis conocimientos de PHP ya no son lo que eran, así que decidí empezar de cero. Ahora el gestor de contenidos tiene un interfaz parecido a iGoogle y Netvibes, con widgets que se pueden configurar, mover, eliminar, etc. Esta parte la he desarrollado utilizando jQuery y copiando ejemplos que he sacado de varios sitios, sobre todo de esta página de NetTuts.

En la parte de servidor, PHP ya no está solo. Utilizo ADOdb para la gestión de la conexión con la base de datos, consiguiendo que lo que hoy funciona con MySQL, mañana lo pueda hacer con cualquier otra base de datos. Y lo que realmente ha supuesto un gran cambio, ahora utilizo el motor de plantillas Smarty para separar la parte de presentación de la lógica de negocio. Ahora que empiezo a sacar partido a Smarty, llego a pensar que se debería utilizar obligatoriamente en casi cualquier proyecto en PHP.

Para septiembre tengo que tener una beta operativa, así que tendré que seguir pasando calor y programando a la vez. En ota ocasión escribiré algo sobre todas estas tecnologías y unos cuantos trucos con las soluciones a los problemas que he ido encontrando.