Archivo de la etiqueta: snippet

1263055255_application-javascript

Generar propiedades de un objeto (JSON) dinámicamente.

El caso es el siguiente: Tenemos un objeto al que queremos crearle propiedades anidadas pero nos gustaría no tener que preocuparnos de si sus parent existen. por ejemplo, si tuviera un objeto “miObjeto” y quisiera crearle una función en miObjeto.modulos.ctools.watcher, primero tendría que crear ese path. eso o podemos usar esta función:

/**
 * Genera propiedades de un objeto (JSON) dinamicamente.
 * @returns objeto extendido.
 */
function extend(base, ns_string) {
    var parts = ns_string.split('.'),
        pl, i;
    pl = parts.length;
    for (i = 0; i < pl; i++) {
        //create a property if it doesnt exist
        if (typeof base[parts[i]] == 'undefined') {
            base[parts[i]] = {};
        }
        base = base[parts[i]];
    }
    return base;
}

Y listo, ya podemos extender nuestro objeto de forma dinámica:

var miObjeto = {};
//console.log("Esto va a dar error porque 'modulos.ctools.watcher' no existe");
//console.log(miObjeto.modulos.ctools);
extend(miObjeto, 'modulos.ctools.watcher');
extend(miObjeto, 'settings.general');
miObjeto.modulos.ctools.watcher = function () {
    console.log("Soy una función!");
};
console.log(miObjeto);

Resultado:
resultado-objeto-propiedades-dinamicas
Chau!

Druplicon

Drupal: Obtener un árbol de términos de forma anidada

Este problema es mas viejo que la injusticia. taxonomy_get_tree() devuelve un array de terms plano en lugar de hacerlo de forma anidada. La solución es esta pequeña función:

<?php
function taxonomy_get_nested_tree($vid_or_terms = array(), $max_depth = NULL, $parent = 0, $parents_index = array(), $depth = 0) {
  if (!is_array($vid_or_terms)) {
    $vid_or_terms = taxonomy_get_tree($vid_or_terms);
  }
  foreach ($vid_or_terms as $term) {
    foreach ($term->parents as $term_parent) {
      if ($term_parent == $parent) {
        $return[$term->tid] = $term;
      }
      else {
        $parents_index[$term_parent][$term->tid] = $term;
      }
    }
  }
  foreach ($return as &$term) {
    if (isset($parents_index[$term->tid]) && (is_null($max_depth) || $depth < $max_depth)) {
      $term->children = taxonomy_get_nested_tree($parents_index[$term->tid], $max_depth, $term->tid, $parents_index, $depth + 1);
    }
  }
  return $return;
}

Y listo, ahora en lugar de usar taxonomy_get_tree(), usa taxonomy_get_nested_tree():

<?php
$voc = taxonomy_vocabulary_machine_name_load('categoria');
$tree = taxonomy_get_nested_tree($voc->vid);

Ya está, el resultado ahora está anidado tal como tengas anidados los terms.

Nota: Me he basado en ésta función, que a su vez se basa en otras.

Renderizar el tree

Acá dejo tambien una función para renderizar el tree:

<?php
function taxonomy_nested_tree_render($tree, $recurring = FALSE) {
  $items = array();
  if (count($tree)) {
    foreach ($tree as $term) {
      $path = taxonomy_term_uri($term);
      $item = array('data' => l($term->name, $path["path"]));
      if (isset($term->children)) {
        $item["children"] = taxonomy_nested_tree_render($term->children, TRUE);
      }
      $items[] = $item;
    }
  }
  if ($recurring) {
    return $items;
  }
  return array(
    '#theme' => 'item_list',
    '#items' => $items,
    '#attributes' => array('class' => 'taxonomy-tree'),
  );
}

Uso:

<?php
$voc = taxonomy_vocabulary_machine_name_load('categoria');
$tree = taxonomy_get_nested_tree($voc->vid);
return taxonomy_nested_tree_render($tree);
jquery-logo

jQuery: detectar cuando se copia, pega o corta

Señoras y señores, les juro que no he sido capaz de encontrar la documentación de estos tres eventos en la api de jQuery, pero ahí están y funcionan!

Testeado en FF, Chrome, IE7 IE8

$(document).ready(function() {
    $("#mi-textarea").bind('copy', function(e) {
        alert('Copiando!');
    });
    $("#mi-textarea").bind('paste', function(e) {
        alert('repartiendo!... digo, pegando!');
    });
    $("#mi-textarea").bind('cut', function(e) {
        alert('Cortando!');
    });
});
Herramientas

Reemplazar la ñ, acentos, espacios y caracteres especiales con PHP [Actualizada]

<?php
/**
 * Reemplaza todos los acentos por sus equivalentes sin ellos
 *
 * @param $string
 *  string la cadena a sanear
 *
 * @return $string
 *  string saneada
 */
function sanear_string($string)
{
    $string = trim($string);
    $string = str_replace(
        array('á', 'à', 'ä', 'â', 'ª', 'Á', 'À', 'Â', 'Ä'),
        array('a', 'a', 'a', 'a', 'a', 'A', 'A', 'A', 'A'),
        $string
    );
    $string = str_replace(
        array('é', 'è', 'ë', 'ê', 'É', 'È', 'Ê', 'Ë'),
        array('e', 'e', 'e', 'e', 'E', 'E', 'E', 'E'),
        $string
    );
    $string = str_replace(
        array('í', 'ì', 'ï', 'î', 'Í', 'Ì', 'Ï', 'Î'),
        array('i', 'i', 'i', 'i', 'I', 'I', 'I', 'I'),
        $string
    );
    $string = str_replace(
        array('ó', 'ò', 'ö', 'ô', 'Ó', 'Ò', 'Ö', 'Ô'),
        array('o', 'o', 'o', 'o', 'O', 'O', 'O', 'O'),
        $string
    );
    $string = str_replace(
        array('ú', 'ù', 'ü', 'û', 'Ú', 'Ù', 'Û', 'Ü'),
        array('u', 'u', 'u', 'u', 'U', 'U', 'U', 'U'),
        $string
    );
    $string = str_replace(
        array('ñ', 'Ñ', 'ç', 'Ç'),
        array('n', 'N', 'c', 'C',),
        $string
    );
    //Esta parte se encarga de eliminar cualquier caracter extraño
    $string = str_replace(
        array("\\", "¨", "º", "-", "~",
             "#", "@", "|", "!", "\"",
             "·", "$", "%", "&", "/",
             "(", ")", "?", "'", "¡",
             "¿", "[", "^", "`", "]",
             "+", "}", "{", "¨", "´",
             ">", "< ", ";", ",", ":",
             ".", " "),
        '',
        $string
    );
    return $string;
}

Ejemplo de uso:

<?php
echo sanear_string("áàäâªÁÀÂÄdoéèëêÉÈÊËreíìïîÍÌÏÎmióòöôÓÒÖÔfaúùüûÚÙÛÜsolñÑçÇlasi\\¨º-~#@|!\,·$%&/()?¡¿[^`]+}{¨´>< ;,:. ");

Lo anterior imprime:

"aaaaaAAAAdoeeeeEEEEreiiiiIIIImiooooOOOOfauuuuUUUUsolnNcClasi"
Druplicon

Drupal 6: El tag http-equiv=”Content-type” de
sale duplicado

Un curioso bug en Drupal y de facil solucion. Solamente tenes que poner el siguiente snippet en el template.php de tu theme o bien en algún modulo de tu propia factoría :)

function TU_THEME_preprocess_page(&$vars) {
    $matches = array();
    preg_match_all('/(]*>)/', $vars['head'], $matches);
    if (count($matches) >= 2) {
        $vars['head'] = preg_replace('/]*>/', '', $vars['head'], 1); // strip 1 only
    }
}
1263055255_application-javascript

JS: Como saber si un objeto undefined está undefined

Suena a boludez:

if (objetoso == undefined) {
    alert("objetoso no está definido.");
}

Pero lo anterior no te va a funcionar porque al querer comparar un objeto que está indefinido, el navegador va a arrojarte un error :S

La forma correcta de hacer esta comprobación entonces es:

if (typeof(objetoso) === "undefined") {
    alert("objetoso no está definido.");
}

Y ya nos evitamos que se rompa todo por culpa de un objeto indefinido…

Bye.

Notas rápidas de strpos() (PHP)

Strpos() devuelve la posición del primer caracter de la palabra que estamos buscando.

Ejemplos:

<?php
//en la posición 0
if ($posicion = strpos("hola mundo", "hola") !== FALSE) {
    echo "Palabra encontrada en la posición $posicion";
}
?>
<?php
//en la posición 9
if ($posicion = strpos("he dicho hola mundo!", "hola") !== FALSE) {
    echo "Palabra encontrada en la posición $posicion";
}
?>

Nunca hay que olvidar de hacer la comparación del resultado con comparaciones estrictas (“===”, “!==”) para evitar falsos positivos o negativos.

PHP

Snippet: Verificar si una fecha está dentro de un rango de fechas en PHP.

La saqué de la documentación de PHP creo recordar, y a alguien le puede ser útil ;)

<?php
/**
 * Verifica que una fecha esté dentro del rango de fechas establecidas
 * @param $start_date fecha de inicio
 * @param $end_date fecha final
 * @param $evaluame fecha a comparar
 * @return true si esta en el rango, false si no lo está
 */
function check_in_range($start_date, $end_date, $evaluame) {
    $start_ts = strtotime($start_date);
    $end_ts = strtotime($end_date);
    $user_ts = strtotime($evaluame);
    return (($user_ts >= $start_ts) && ($user_ts <= $end_ts));
}

Ejemplo de uso:

<?php
$start_date = '2010-06-01';
$end_date = '2010-06-30';
$fecha_a_evaluar = '2010-06-15';
if (check_in_range($start_date, $end_date, $fecha_a_evaluar)) {
    echo "estas en rango";
} else {
    echo "fuera de rango";
}
Druplicon

Múltiples drupal_execute() en Drupal 6 es imposible… O NO :)

El otro día Nicolas, un amigo y compañero de trabajo se quebró la cabeza con este tema. La cosa debía ser mas bien simple, en un bucle tenia que procesar una serie de datos, rellenar un formulario programaticamente y darle un drupal_execute() para que se creen una cantidad de nodos…

Eso fue de todo menos simple. Resulta que el que programó la función drupal_validate_form() se olvidó que podía caber la posibilidad de que alguien quisiera llamarlo en bucle, y no se le ocurrió mejor idea que cachear la primera validación y cortar cualquier otra dentro de un mismo request.

La solución por la que se decantó Nicolas fue la de crear una implementación propia de ciertas funciones. Antes que digan algo, recomiendo que se den una vuelta por los foros de Drupal y se convensan de la imposibilidad de aplicar una solución mejor.
De hecho esta solución es bastante buena, porque no tenes mas que poner el código en tu modulo, e invocar la versión modificada de drupal_execute().

La modificación se tuvo hacer mucho antes de llegar a drupal_validate_form() para poder tomar control sobre la misma, por lo que en esta modificación hubo que reemplazar funciones de:
drupal_execute() -> drupal_execute_no_cache()
drupal_process_form() -> drupal_process_form_no_cache()
drupal_validate_form() -> drupal_validate_form_no_cache();

los archivos modificados son estos:

/**
 * @see drupal_execute
 * Unica diferencia, utiliza métodos propios (_no_cache) para evitar el cacheo de validaciones
 */
function drupal_execute_no_cache($form_id, &$form_state) {
    $args = func_get_args();
    // Make sure $form_state is passed around by reference.
    $args[1] = &$form_state;
    $form = call_user_func_array('drupal_retrieve_form', $args);
    $form['#post'] = $form_state['values'];
    drupal_prepare_form($form_id, $form, $form_state);
    drupal_process_form_no_cache($form_id, $form, $form_state);
}
/**
 * @see drupal_process_form
 *
 * @param $form_id
 * @param $form
 * @param $form_state
 */
function drupal_process_form_no_cache($form_id, &$form, &$form_state) {
    $form_state['values'] = array();
    $form = form_builder($form_id, $form, $form_state);
    // Only process the form if it is programmed or the form_id coming
    // from the POST data is set and matches the current form_id.
    if ((!empty($form['#programmed'])) || (!empty($form['#post']) && (isset($form['#post']['form_id']) && ($form['#post']['form_id'] == $form_id)))) {
        $form_state['process_input'] = TRUE;
        drupal_validate_form_no_cache($form_id, $form, $form_state);
        // form_clean_id() maintains a cache of element IDs it has seen,
        // so it can prevent duplicates. We want to be sure we reset that
        // cache when a form is processed, so scenerios that result in
        // the form being built behind the scenes and again for the
        // browser don't increment all the element IDs needlessly.
        form_clean_id(NULL, TRUE);
        if ((!empty($form_state['submitted'])) && !form_get_errors() && empty($form_state['rebuild'])) {
            $form_state['redirect'] = NULL;
            form_execute_handlers('submit', $form, $form_state);
            // We'll clear out the cached copies of the form and its stored data
            // here, as we've finished with them. The in-memory copies are still
            // here, though.
            if (variable_get('cache', CACHE_DISABLED) == CACHE_DISABLED && !empty($form_state['values']['form_build_id'])) {
                cache_clear_all('form_' . $form_state['values']['form_build_id'], 'cache_form');
                cache_clear_all('storage_' . $form_state['values']['form_build_id'], 'cache_form');
            }
            // If batches were set in the submit handlers, we process them now,
            // possibly ending execution. We make sure we do not react to the batch
            // that is already being processed (if a batch operation performs a
            // drupal_execute).
            if ($batch =& batch_get() && !isset($batch['current_set'])) {
                // The batch uses its own copies of $form and $form_state for
                // late execution of submit handers and post-batch redirection.
                $batch['form'] = $form;
                $batch['form_state'] = $form_state;
                $batch['progressive'] = !$form['#programmed'];
                batch_process();
                // Execution continues only for programmatic forms.
                // For 'regular' forms, we get redirected to the batch processing
                // page. Form redirection will be handled in _batch_finished(),
                // after the batch is processed.
            }
            // If no submit handlers have populated the $form_state['storage']
            // bundle, and the $form_state['rebuild'] flag has not been set,
            // we're finished and should redirect to a new destination page
            // if one has been set (and a fresh, unpopulated copy of the form
            // if one hasn't). If the form was called by drupal_execute(),
            // however, we'll skip this and let the calling function examine
            // the resulting $form_state bundle itself.
            if (!$form['#programmed'] && empty($form_state['rebuild']) && empty($form_state['storage'])) {
                drupal_redirect_form($form, $form_state['redirect']);
            }
        }
    }
}
/**
 * @see drupal_validate_form
 *
 * @param $form_id
 * @param $form
 * @param $form_state
 */
function drupal_validate_form_no_cache($form_id, $form, &$form_state) {
    // If the session token was set by drupal_prepare_form(), ensure that it
    // matches the current user's session.
    if (isset($form['#token'])) {
        if (!drupal_valid_token($form_state['values']['form_token'], $form['#token'])) {
            // Setting this error will cause the form to fail validation.
            form_set_error('form_token', t('Validation error, please try again. If this error persists, please contact the site administrator.'));
        }
    }
    _form_validate($form, $form_state, $form_id);
}

Como dije. Copienlo a su módulo y usen drupal_execute_no_cache() en lugar de drupal_execute().