Añadir el sistema grid de Bootstrap al tinymce de WordPress

Uno de los problemas que hay en el editor de WordPress es que algunas veces los themes tienen diseños específicos que no se muestran en el editor. Actualmente, el uso de Bootstrap está cada vez más extendido, por lo que es buena idea añadir la opción de meter columnas en los posts de forma sencilla.

boton_bootstrap

Lo primero que deberemos hacer es añadir en el functions.php el código necesario para añadir un botón al TinyMCE:

add_action( 'init', 'sw_mce_buttons' );
// Filtros para añadir los botones
function sw_mce_buttons() {
    add_filter( "mce_external_plugins", "sw_mce_add_buttons" );
    add_filter( 'mce_buttons', 'sw_mce_register_buttons' );
}
// Añade el script del plugin tinymce
function sw_mce_add_buttons( $plugin_array ) {
    $plugin_array['iqn'] = get_template_directory_uri() . '/js/tinymce-plugin.js';
    return $plugin_array;
}
// Un nuevo botón que se identifica como 'bootstrap'
function sw_mce_register_buttons( $buttons ) {
    array_push( $buttons, 'bootstrap' ); 
    return $buttons;
}
// Añadimos el css de bootstrap y uno propio para personalizar cosas
function sw_mce_css($wp) {
	$wp .= ',' . get_bloginfo('stylesheet_directory') . '/bootstrap/bootstrap.min.css'.',' . get_bloginfo('stylesheet_directory') . '/css/tinymce.css';
	return $wp;
}
add_filter( 'mce_css', 'sw_mce_css' );

Después tenemos que crear el javascript para el plugin de TinyMCE:

(function() {
    // Creamos el plugin
    tinymce.create('tinymce.plugins.iqn', {
        init : function(ed, url) {
          // Muestra el dialogo que permite personalizar las columnas
          // Mostrará una caja de texto donde se pondra el ancho de la columna
          // de 1 a 12, y cuando se indique un valor, automáticamente se añadirá otra columna
          function bootstrapDialog() {
            var html = '<div class="bootstrap-dialog">';
            html += '<p class="howto">Añade columnas basadas en el sistema <a href="http://getbootstrap.com/css/#grid">grid de Bootstrap</a></p>';
            html += '<p>Rellena el ancho (1-12) de cada celda. Nuevas celdas aparecerán automáticamente</p>';
            html += '<div class="columns_container"><input type="text" class="column_width" /></div>';
            html += '<p><input type="checkbox" id="new_row" name="new_row" /> <label for="new_row">Añadir nueva fila</p>';
            html += '</div>';
            var panel = {
                type: 'container',
                html: html
            };
            // Abre el dialogo
            win = ed.windowManager.open({
                title: "Columnas de Bootstrap",
                spacing: 10,
                padding: 10,
                items: [panel], // el panel creado antes
                buttons: [ // Botones
                    {text: "Insertar", subtype: 'primary', onclick: function() {
                        var content = ed.getContent();
                        var html = ' ';
                        // Si se marca la casilla, se añade una fila
                        if (jQuery('#new_row:checked').length == 1) html += '<div class="row">';
                        // Por cada columna, se crea una capa
                        jQuery('.column_width').each(function() {
                          var $this = jQuery(this);
                          if ($this.val()) html += '<div class="col-sm-'+$this.val()+'">Columna tamaño '+$this.val()+'</div>';
                        });
                        if (jQuery('#new_row:checked').length == 1) html += '</div>';
                        ed.execCommand('mceInsertContent', false, html);
        	        win.close();
                    }},
                    {text: "Cerrar", onclick: function() {
  	                win.close();
                    }}
                ]
             });
          }
          ed.addButton('bootstrap', {
              title : 'Columnas Bootstrap',
              onclick: bootstrapDialog
          });
        },
        createControl : function(n, cm) {
            return null;
        },
        getInfo : function() {
            return {
                longname : 'Bootstrap columns',
                author : 'SentidoWeb',
                version : "0.1"
            };
        }
    });
    // Register plugin
    tinymce.PluginManager.add( 'iqn', tinymce.plugins.iqn );
})();
 
jQuery(document).ready(function() {
  // Se crea una casilla nueva si se actualiza el contenido de la última
  jQuery('body').on('keyup', '.column_width', function() {
    var $this = jQuery(this);
    var $inputs = jQuery('.column_width');
    if($this.val()) {
      if ($inputs.index(this) == $inputs.length - 1) {
        $this.after('<input type="text" class="column_width" />');
      }
    }
  });
});

Y ya por último, crearnos el fichero tiniymce.css que se incluirá en el contenido del editor. Yo simplemente he recuadrado los elementos para que se diferencien en el editor:

.row {padding: 4px; border: 1px dashed #bbb;}
.col-sm-1, 
.col-sm-2, 
.col-sm-3, 
.col-sm-4, 
.col-sm-5, 
.col-sm-6, 
.col-sm-7, 
.col-sm-8, 
.col-sm-9, 
.col-sm-10, 
.col-sm-11, 
.col-sm-12 {xmargin: 4px; border: 1px dotted #ccc;}

Y si modificáis el diseño del admin, podéis aprovechar ese css para añadir el css necesario para el botón.

i.mce-i-bootstrap {
	font: normal 20px/1 'dashicons';
	padding: 0;
	vertical-align: top;
	speak: none;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	margin-left: -2px;
	padding-right: 2px;
}
i.mce-i-bootstrap:before {
	content: '\f479';
}
.bootstrap-dialog p {padding: 5px 0;}
.bootstrap-dialog p a {color: #0074A2; text-decoration: underline;}
.mce-container .columns_container {border: 1px solid #F0f0f0; padding: 20px; border-radius: 4px; margin: 10px 0;}
.mce-container .columns_container input.column_width {
    margin-right: 5px;
    padding: 9px 3px;
    text-align: center;
    width: 39px;
}
Share Button

Añadir Javascript relacionado con templates en WordPress

La jerarquía de las plantillas de wordpress permite definir diferentes plantillas para mostrar según el tipo de contenido. Por ejemplo, la template para mostrar el contenido de un post es single.php, pero si es un custom post type podemos crearnos la template single-miposttype.php y que use esa plantilla específica para mostrar los contenidos del custom post type. Si se trata de una página mostrará page.php, y así con todos los tipos de contenido.

Lo que nos encontramos en ocasiones es que queremos ejecutar un javascript específico asociado a esa plantilla, lo cual podemos hacerlo a la hora de añadir los scripts preguntando por el tipo de contenido. Pero si lo queremos hacer de una forma más automática, podemos añadir en el filtro template_include la acción de añadir el script.

add_filter('template_include', 'js_load_script_template');
function js_load_script_template($template) {
  // Obtenemos el fichero de la template que se usa
  $js = pathinfo($template);
  $js = $js['filename'];
  // Me gusta obtener la versión del theme para evitar caches
  $my_theme = wp_get_theme();
  $version = $my_theme->get( 'Version' );  
  // Si el fichero js existe, p.e. single-miposttype.js lo añadimos
  if (file_exists(get_template_directory().'/js/'.$js.'.js')) {
    wp_enqueue_script( $js, get_bloginfo('template_directory').'/js/'.$js.'.js', array(), $version );
  }
  // Tambien ejecuto el script relacionado con la plantilla generica, p.e. single.js
  $js_part = preg_replace('#^([^\-]+)\-.*$#', '1', $js);
  if ($js != $js_part && file_exists(get_template_directory().'/js/'.$js_part.'.js')) {
    wp_enqueue_script( $js_part, get_bloginfo('template_directory').'/js/'.$js_part.'.js', array(), $version );
  }    
  return $template;
}
Share Button

Añadir editor WYSIWYG al widget Texto de WordPress

Uno de los problemas que se pueden tener a la hora de desarrollar un plugin es que el cliente sepa editar los widgets añadiendo o modificando el HTML. Es por ello que he creado la posibilidad de añadir un pequeño plugin jQuery de edición WYSIWYG a los widgets Texto que vienen en WordPress por defecto, pero lo mismo se puede hacer para cualquier otro widget, incluído los que crees personalmente.

nicedit

Lo primero será bajarnos el plugin nicEdit, el cual permite de forma muy sencilla añadir un editor WYSIWYG a cualquier elemento. He elegido este plugin y no otro porque en el poco espacio que ofrece el textarea, poner otro plugin más completo, dificultaría su uso, de todas formas, si se quiere usar otro plugin, pues sin problema.

Yo me he creado un directorio /js donde he metido los dos ficheros de nicedit: nicEdit.js y nicEditorIcons.gif.

El siguiente paso es editar nuestro functions.php para añadir el siguiente código:

// El action in_widget_form es el encargado de llamar al método 
// form del widget, el que dibuja el formulario
// Comprobaremos si es un WP_Widget_Text y si es así
// añadiremos un checkbox para permitir que el textarea
// sea WYSIWYG
add_action('in_widget_form', 'set_nicedit_form_widget', 10, 3);
function set_nicedit_form_widget($obj, $return, $instance) {
  if (is_a($obj, 'WP_Widget_Text')) { ?>
		<p><input class="nicedit" id="<?php echo $obj->get_field_id('nicedit'); ?>" name="<?php echo $obj->get_field_name('nicedit'); ?>" type="checkbox" <?php checked(isset($instance['nicedit']) ? $instance['nicedit'] : 0); ?> />&nbsp;<label for="<?php echo $obj->get_field_id('nicedit'); ?>"><?php _e('Utilizar editor HTML'); ?></label></p>
<?php 
    if (isset($instance['nicedit']) && !empty($_POST)) {
      // Si se ha marcado la opción nicedit en el form y se ha dado GUARDAR
      // llamamos la funcion init (explicada más adelante) que se encarga de
      // añadir el WYSIWYG al textarea
?>
    <script type="text/javascript">
      init();
    </script>
<?php    
    }
  }
}
// El WP_Widget_Text no tiene el checkbox nicedit en su código
// por lo que al hacer un update lo ignoraría
add_filter('widget_update_callback', 'set_nicedit_update_widget', 10, 4);
function set_nicedit_update_widget($instance, $new_instance, $old_instance, $obj) {
  if (is_a($obj, 'WP_Widget_Text')) {
    $instance["nicedit"] = isset($new_instance["nicedit"]) && $new_instance["nicedit"] == 'on';
  }
  return $instance;
}
// Añadimos los scripts y styles necesarios si estamos en la pantalla de widgets
add_action( 'admin_enqueue_scripts', 'add_admin_widget_scripts' );
function add_admin_widget_scripts() {
  global $current_screen;
  if ($current_screen->base == 'widgets') {
     wp_enqueue_script( 'nicedit', get_bloginfo('template_directory') . '/js/nicEdit.js' );
     wp_enqueue_script( 'admin', get_bloginfo('template_directory') . '/js/admin.js' );
     wp_localize_script( 'admin', 'admin', array('path'=>get_bloginfo('template_directory')) );
     wp_enqueue_style( 'admin', get_bloginfo('template_directory') . '/css/admin.css' );
  }
}

Ahora deberemos añadir la funcionalidad javascript al código que hemos metido en el widget (admin.js):

// Esta función es la encargada de añadir el WYSIWYG al textarea
function init() {
  // Busca todos los checkbox nicedit (le metimos un class) 
  // que estén seleccionados
  jQuery('input:checkbox.nicedit:checked').each(function() {
    var $this = jQuery(this);
    // Si ya tiene un nicedit nos lo cepillamos
    var niceditor = $this.data('nicedit');
    var $textearea = $this.parents('form:first').find('textarea');
    if (niceditor) niceditor.removeInstance($textearea.attr('id'));
    // Añadimos el nicedit al textarea, puedes meterle más botones, mira la doc de nicedit para ello
    var area = new nicEditor({buttonList : ['bold','italic', 'link', 'unlink', 'xhtml'], iconsPath: admin.path+ '/js/nicEditorIcons.gif'}).panelInstance($textearea.attr('id'));
    $this.data('nicedit', area);
  });
}
 
jQuery(document).ready(function() {
  // Si pulsamos el checkbox, añadimos o quitamos el nicedit
  // Almacenaremos el objeto nicedit para poder utilizarlo despues
  jQuery('.widget-liquid-right').on('click', 'input:checkbox.nicedit', function() {
    var $this = jQuery(this);
    var $textearea = $this.parents('form:first').find('textarea');
    var niceditor = $this.data('nicedit');
    if (niceditor) {
      niceditor.removeInstance($textearea.attr('id'));
      $this.data('nicedit', false);
    } else {
      var area = new nicEditor({buttonList : ['bold','italic', 'link', 'unlink', 'xhtml'], iconsPath: admin.path+ '/js/nicEditorIcons.gif'}).panelInstance($textearea.attr('id'));
      $this.data('nicedit', area);
    }
  });
 
  // nicEdit controla los submits para actualizar los valores,
  // pero en los widgets no funciona, por lo que antes del submit
  // forzamos la actualización del valor
  jQuery('#widgets-right').on('click', ':submit', function() {
    // Quizás se pueda utilizar el objeto nicedit almacenado anteriormente
    // pero esto lo hice así en una versión inicial menos genérica y no lo he tocado
    for(var i=0; i<nicEditors.editors.length; i++) for(var j=0; j<nicEditors.editors[i].nicInstances.length; j++) nicEditors.editors[i].nicInstances[j].saveContent();
  });
  // Apaño el orden de los widgets para meter nicedit a los nuevos widgets
  // Es necesario si se pusieran los nicedit seleccionados por defecto,
  // que en este ejemplo no es el caso, pero si lo añadierais a un widget propio
  // no os funcioanría si no hicierais esto.
  // Lo que hago es meter un pequeño hack a la función saveOrder
  wpWidgets._saveOrder = wpWidgets.saveOrder
  wpWidgets.saveOrder = function() {
    init();
    wpWidgets._saveOrder();
  }
  // Activo los nicedit en los textareas marcados 
  // como tal cuando se carga la página al principio
  init();
});

Y por último solo nos falta meterle el css necesario, en este caso, el nicedit tiene un pequeño bug y si el textarea tiene un width = 100% no calcula el tamaño real, por eso se lo metemos por css (admin.css).

 
textarea.widefat {
  width: 400px;
  height: 100px;
}

Y listo, ya solo falta que el cliente no os dé mucho la lata.

Share Button

Añadir contenido a los datepicker de jQuery UI

En algunas ocasiones es necesario añadir contenido al calendario que te ofrecer el datepicker de jQuery UI, por ejemplo añadir un combo que indice “horario mañanas/tarde”. Para conseguirlo será necesario ‘toquetear’ un poco el objeto jQuery.datepicker.

Tendremos que hacer dos cosas: primero deberemos evitar que cuando se selecciona un día se cierre automáticamente el popup con el calendario y después tendremos que modificar el HTML que devuelve la clase.

Para evitar el auto-cierre tenemos que añadir la opción showButtonPanel ya que nos ofrecerá el botón “Close” que nos permitirá cerrar el popup cuando hayamos indicado todos los campos necesarios. También es necesario modificar la función jQuery.datepicker._selectDate tal y como lo indican en StackOverflow:

// Añadimos datepicker al input que queremos
jQuery('.fecha')
  .datepicker({
    showButtonPanel: true,
    dateFormat: "DD, d MM, yy" 
  });
 
// Modificamos la funcion _selectDate
jQuery.datepicker._selectDateOverload = jQuery.datepicker._selectDate;
jQuery.datepicker._selectDate = function(id, dateStr) {
    var target = jQuery(id);
    var inst = this._getInst(target[0]);
    inst.inline = true;
    jQuery.datepicker._selectDateOverload(id, dateStr);
    inst.inline = false;
    this._updateDatepicker(inst);
    // Usar el .html() para luego usar el .text() es porque si usas el regional de datepicker, te salen entidades html en vez de letras acentuadas
    // Se le añade el valor del nuevo campo select que hemos incluido
    target.val(jQuery('<div />').html(dateStr).text()+' @ '+jQuery('#horario').val());
}

Bien, ya tenemos el evento onSelect modificado, ahora nos falta cambiar el HTML que se dibuja, para ello modificaremos la función jQuery.datepicker._generateHTML:

jQuery.datepicker._generateHTMLExtended = jQuery.datepicker._generateHTML;
jQuery.datepicker._generateHTML = function(inst) {
  var html = jQuery.datepicker._generateHTMLExtended(inst);
  var div = jQuery('<div />').html(html);
  div.find('table:first').after('<p>Horario:</p><select id="horario"><option value="mañanas">mañanas</option><option value="tardes">tardes</option></select>');
  return div.html();
}
 
// Incluimos tambien un evento para que cuando se seleccione el horario, se modifique el campo input
jQuery('#horario').live('change', function() {
  var $obj = jQuery('.fecha');
  $obj.val($obj.val().replace(/@.*/, '@ '+jQuery(this).val()));
});
Share Button

Progreso de subida de ficheros únicamente con HTML5

Uno de los mayores problemas con los que nos hemos encontrado a la hora de hacer aplicaciones que suben ficheros, es mostrar al usuario cuánto se ha subido y así poder saber cuánto queda. Ahora con HTML5 y XMLHttpRequest Level 2 podemos mostrarlo sin necesidad de parte del servidor.

El script hace uso de Evento de Progreso de HTML5 para poder mostrar:

  • total: total de bytes
  • loaded: bytes subidos
  • lengthComputable: indica si el tamaño del fichero es conocido
  • transferSpeed: velocidad de transferencia
  • timeRemaining: tiempo que falta (en formato Date)

Por ahora solo es compatible con Firefox, Chrome y Safari.

En el post lo explican con gran detalle.

Html5 File Upload with Progress

Share Button

JSZip: crear ficheros ZIP mediante Javascript

Interesante librería que nos permite crear ficheros ZIP desde Javascript, con unas simples líneas de código podemos crear zips con ficheros de texto, imágenes, crear directorios…

var zip = new JSZip();
zip.add("Hello.txt", "Hello World\n");
img = zip.folder("images");
img.add("smile.gif", imgData, {base64: true});
content = zip.generate();
location.href="data:application/zip;base64,"+content;

El único problema que hay es a la hora de generar el nombre del fichero: Firefox crea un fichero con un nombre extraño y acabado en .part, Safari lo nombra “Unknown” sin extensión, Chrome “download.zip” e IE directamente ni funciona la librería.

JSZip

Vía / @devongovett

Share Button

PDF.js librería Javascript para leer PDF en Canvas

Interesante librería Javascript que nos permite mostrar en Canvas (HTML5) el contenido de un PDF. Puede venir muy bien para aplicaciones móviles, ya que en navegación en escritorio normalmente la gente tiene instalado un visor de PDFs.

<html>
<head>
  <title>Simple pdf.js page viewer</title>
  <script type="text/javascript"
          src="pdf.js"></script>
  <style type"text/css">
body {
  margin: 6px;
  padding: 0px;
  background-color: #c0bdb7;
}
#controls {
  border-bottom: 1px solid black;
  position:fixed;
  left: 0px; top: 0px;
  width: 100%;
  padding: 7px;
  background-color: rgb(242, 240, 238);
}
span#info {
  float: right;
  font: 14px sans-serif;
  margin-right: 10px;
}
#viewer {
  margin: auto;
  border: 1px solid black;
  width: 8.5in;
  height: 11in;
}
#pageNumber {
  text-align: right;
}
  </style>
 
<script type="text/javascript">
function queryParams() {
    var qs = window.location.search.substring(1);
    var kvs = qs.split("&");
    var params = { };
    for (var i = 0; i < kvs.length; ++i) {
        var kv = kvs[i].split("=");
        params[unescape(kv[0])] = unescape(kv[1]);
    }
    return params;
}
 
var canvas, numPages, pageDisplay, pageNum;
function load() {
    canvas = document.getElementById("canvas");
    canvas.mozOpaque = true;
    pageDisplay = document.getElementById("pageNumber");
    infoDisplay = document.getElementById("info");
    pageNum = parseInt(queryParams().page) || 1;
    fileName = queryParams().file || "compressed.tracemonkey-pldi-09.pdf";
    open(fileName);
}
 
function open(url) {
    document.title = url;
    req = new XMLHttpRequest();
    req.open("GET", url);
    req.mozResponseType = req.responseType = "arraybuffer";
    req.expected = (document.URL.indexOf("file:") == 0) ? 0 : 200;
    req.onreadystatechange = xhrstate;
    req.send(null);
}
 
function xhrstate() {
    if (req.readyState == 4 && req.status == req.expected) {
        var data = req.mozResponseArrayBuffer ||
                   req.mozResponse ||
                   req.responseArrayBuffer ||
                   req.response;
        pdf = new PDFDoc(new Stream(data));
        numPages = pdf.numPages;
        document.getElementById("numPages").innerHTML = numPages.toString();
        gotoPage(pageNum);
    }
}
 
function displayPage(num) {
    pageDisplay.value = num;
 
    var t0 = Date.now();
 
    var page = pdf.getPage(pageNum = num);
 
    var t1 = Date.now();
 
    var ctx = canvas.getContext("2d");
    ctx.save();
    ctx.fillStyle = "rgb(255, 255, 255)";
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.restore();
 
    var gfx = new CanvasGraphics(ctx);
 
    // page.compile will collect all fonts for us, once we have loaded them
    // we can trigger the actual page rendering with page.display
    var fonts = [];
    page.compile(gfx, fonts);
 
    var t2 = Date.now();
 
    // This should be called when font loading is complete
    page.display(gfx);
 
    var t3 = Date.now();
 
    infoDisplay.innerHTML = "Time to load/compile/render: "+ (t1 - t0) + "/" + (t2 - t1) + "/" + (t3 - t2) + " ms";
}
 
function nextPage() {
    if (pageNum < numPages)
        ++pageNum;
    displayPage(pageNum);
}
 
function prevPage() {
    if (pageNum > 1)
        --pageNum;
    displayPage(pageNum);
}
function gotoPage(num) {
    if (0 <= num && num <= numPages)
        pageNum = num;
    displayPage(pageNum);
}
  </script>
</head>
 
<body onload="load();">
  <div id="controls">
    <button onclick="prevPage();">Previous</button>
    <button onclick="nextPage();">Next</button>
    <input type="text" id="pageNumber" onchange="gotoPage(this.value);"
           value="1" size="4"></input>
    / <span id="numPages">--</span>
    <span id="info"></span>
  </div>
  <div id="viewer">
    <!-- Canvas dimensions must be specified in CSS pixels.  CSS pixels
      -- are always 96 dpi.  These dimensions are 8.5x11in at 96dpi. -->
    <canvas id="canvas" width="816" height="1056"></canvas>
  </div>
</body>
 
</html>

PDF.js

Vía / @badass_js

Share Button

Popcorn.js librería Javascript que permite sincronizar vídeo y contenido en HTML5

Popcorn.js es una librería que permite sincronizar la etiqueta <video> de HTML5 con contenido que deseemos mostrar. Para ello utiliza las propiedades, métodos y eventos nativos de HTMLMediaElement. Además ofrece un sistema de plugins desarrollados por la comunidad:

document.addEventListener("DOMContentLoaded", function () {
      // Create a popcporn instance by calling Popcorn("#id-of-my-video")
      var pop = Popcorn("#video");
      // play the video right away
      pop.play()
      // add a footnote at 2 seconds
        .footnote({
          start: 2,
          end: 6,
          text: "This footnote is the stepping stone of progress!",
          target: "footnotediv"
        });
    }, false);

Podéis ver algunos ejemplos bastante interesantes. Una librería muy útil para presentaciones y vídeos corporativos.

Popcorn.js

Share Button

MathJax: librería javascript para mostrar fórmulas matemáticas

MathJax es una librería javascript que permite mostrar fórmulas LaTeX y MathML en nuestras páginas. Es compatible con casi todos los navegadores (menos IE5.5 lógicamente), permite copiar el código TeX y MathML de la página, utiliza fuentes CSS y no imágenes o Flash y muchas cosas más.

<!DOCTYPE html>
<html>
<head>
<title>MathJax TeX Test Page</title>
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({tex2jax: {inlineMath: [['$','$'], ['\(','\)']]}});
</script>
<script type="text/javascript"
  src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML">
</script>
</head>
<body>
When $a \ne 0$, there are two solutions to \(ax^2 + bx + c = 0\) and they are
$$x = {-b \pm \sqrt{b^2-4ac} \over 2a}.$$
</body>
</html>

MathJax

Share Button

jQuery Graceful Websocket: plugin jQuery para websockets

jQuery Graceful Websocket es un plugin jQuery que nos permite comunicarnos con el servidor usando websockets de HTML5. El problema es que tan solo Chrome permite los websokets (creo que Firefox los tiene desactivados por defecto por temas de seguridad), además se necesita que el servidor los pueda tratar, por lo que este plugin permite una alternativa mediante Ajax transparente al desarrollador.

// Si el servidor no admite websockets sustituye el ws:// por http://
var ws = $.gracefulWebSocket("ws://127.0.0.1:8080/");
// Envía datos al servidor. 
// Si el servidor no admite websockets lo envía mediante POST
ws.send("message to server");
// Recibe datos del servidor
// Si el servidor no admite websockets hace un polling mediante GET
ws.onmessage = function (event) {
   var messageFromServer = event.data;   
};

WebSocket plugin for jQuery with graceful degradation

Share Button