martes, 20 de diciembre de 2016

Plugin javascript para el control de rangos de contacto L-V de 8:00 a 17:00 y S-D de 10:00 a 14:00


Me he visto en la necesidad de crear un "picker" que permita la selección de rangos horarios de contacto, esto con la finalidad de poder especificar que una persona puede ser contactada por ejemplo de Lunes a Viernes de 8:00 a 17:00 y de Sábado a Domingo de 10:00 a 14:00.

Este plugin ha sido desarrollado pensando que sea utilizado junto con la librería de jQuery y al menos la hoja de estilo de Bootstrap (siempre que se quiera un diseño ajustado a Bootstrap).


A continuación los parametros que se pueden establecer en el plugin:

 return $.fn.rangeSheduleContact.defaults = {  
       days: [  
         { label: 'L', tooltip: 'Lunes', value: 'L' },  
         { label: 'M', tooltip: 'Martes', value: 'M' },  
         { label: 'X', tooltip: 'Miércoles', value: 'X' },  
         { label: 'J', tooltip: 'Jueves', value: 'J' },  
         { label: 'V', tooltip: 'Viernes', value: 'V' },  
         { label: 'S', tooltip: 'Sábado', value: 'S' },  
         { label: 'D', tooltip: 'Domingo', value: 'D' }  
       ],  
       minutes: [  
         { label: '00', value: 0 },  
         { label: '15', value: 15 },  
         { label: '30', value: 30 },  
         { label: '45', value: 45 }  
       ],  
       texts: {  
         captionEmptyRange: '<div class="alert alert-info">Especifíque un rango de contacto</div>',  
         iconButtonTextPopup: '<i class="glyphicon glyphicon-chevron-down"></i>',  
         iconButtonDeleteRange: '<i class="glyphicon glyphicon glyphicon-remove"></i>',  
         add: 'Agregar',  
         close: 'Cerrar',  
         titleBarFrom: 'Desde',  
         titleBarTo: 'Hasta',  
         errorMsgSelectDayForm: 'Debe seleccionar el día desde del rango',  
         errorMsgSelectDayTo: 'Debe seleccionar el día hasta del rango',  
         errorMsgSelectHourFrom: 'Debe seleccionar la hora desde del rango',  
         errorMsgSelectHourTo: 'Debe seleccionar la hora hasta del rango',  
         errorMsgSelectMinuteFrom: 'Debe seleccionar el minuto desde del rango',  
         errorMsgSelectMinuteTo: 'Debe seleccionar el minuto hasta del rango',  
         errorMsgDayToLessThanDayFrom: 'El día hasta debe ser un día igual o posterior al día desde',  
         errorMsgRangeInOtherRange: 'El rango especificado se encuentra dentro de otro rango existente'  
       },  
       numbersLineShow: 1,  
       hourMin: 0,  
       hourMax: 24,  
       defaultHourFrom: 8, //Pendiente  
       defaultHourTo: 17, //Pendiente  
       defaultDayFrom: 'L', //Pendiente  
       defaultDayTo: 'V', //Pendiente  
       editable: true,  
       enabled: true,  
       preventRangeNegative: true,  
       preventRangeInOtherRanges: true,  
       callbacks: {  
         callbackErrorMsg: function (element, msg) { alert(msg); },  
         callbackRangeAdd: function (element, range) { },  
         callbackRangeAdded: function (element, range) { },  
         callbackOpenPopup: function (element) { },  
         callbackClosePopup: function (element) { },  
       }  
     };  


Podéis ver el plugin funcionando y el código fuente en JSFiddle.

sábado, 2 de enero de 2016

Los plugins JavaScript/jQuery más utilizados en mis desarrollos - Parte 4 - Animate.css


Este post forma parte de una serie de artículos en los que menciono los plugins que más utilizo en mis desarrollos:

  1. Parte 1: Select2
  2. Parte 2: SweetAlert
  3. Parte 3: Noty
  4. Parte 4: Animate.css
  5. Parte 5: Waipoints
  6. Parte 5: ScrollToFixed
  7. Parte 6: Parallax

Animate.css

A pesar de no ser un plugin como tal, lo he incluido en esta serie de artículos, ya que es una hoja de estilo que se puede combinar con cualquier plugin y permite simplemente realizar animaciones de manera muy muy fácil.



Esta hoja de estilo nos permitirá que los elementos en las páginas tengan un pco más de vida. Por ejemplo, como veremos en el próximo artículo, podríamos utilizarlo junto con el plugin waypoint para ir haciendo aparecer de forma animada los elementos en la página según vamos haciendo scroll.

Veamos algunos ejemplos:


Para mayor información ir a la página oficial: https://github.com/daneden/animate.css

miércoles, 25 de noviembre de 2015

Los plugins JavaScript/jQuery más utilizados en mis desarrollos - Parte 3 - Noty


Este post forma parte de una serie de artículos en los que menciono los plugins que más utilizo en mis desarrollos:

  1. Parte 1: Select2
  2. Parte 2: SweetAlert
  3. Parte 3: Noty
  4. Parte 4: Animate.css
  5. Parte 5: Waipoints
  6. Parte 5: ScrollToFixed
  7. Parte 6: Parallax

Noty

Es un plugin que suelo utilizar bastante para mostrar notificaciones al usuario, sin obligar al mismo a tener que realizar una acción. Tiene infinidad de opciones parar mostrar las notificaciones, en cualquier lugar de la pantalla, puedes personalizar los colores, el tiempo que quieres que se muestre, entre muchas otras configuraciones.




Por ejemplo, al presionar guardar en un formulario simple, anteriormente mostraba un mensaje que decía que se había guardado satisfactoriamente y el usuario tenia que presionar el botón aceptar... Algo que terminaba siendo incomodo en caso de querer crear varios registos y adicionalmente es una información obvia, debemos mostrar un gran mensaje si algo falla no si todo va bien... Así que llegue a un consenso con este plugin, muestro el mensaje, pero el mismo no es bloqueante y se queda abajo a la derecha, tal y como se muestra en la siguiente imagen.


También lo suelo utilizar para indicar que ha recibido un mensaje el usuario al conectado, tal y como se muestra en la siguiente imagen:


Noty al igual que nuestro plugin sweetAlert, también permite realizar preguntas tipo ok/cancel, de la misma manera utilizando los callbacks.

A continuación algunos ejemplos de cómo utilizar el plugin Noty:

Para mayor información respecto al plugin, podéis ir a la página oficial: http://ned.im/noty/#/about

lunes, 19 de octubre de 2015

Los plugins JavaScript/jQuery más utilizados en mis desarrollos - Parte 2 - SweetAlert


Este post forma parte de una serie de artículos en los que menciono los plugins que más utilizo en mis desarrollos:

  1. Parte 1: Select2
  2. Parte 2: SweetAlert
  3. Parte 3: Noty
  4. Parte 4: Animate.css
  5. Parte 5: Waipoints
  6. Parte 5: ScrollToFixed
  7. Parte 6: Parallax

SweetAlert

Es un plugin bastante útil a nivel visual, sinceramente aporta poco a nivel funcional, pero a nivel estético aporta una infinidad. En los sitios que he propuesto el uso de este plugin, no lo solo lo han aceptado, sino que se ha vuelto un plugin de uso común en cada uno de sus proyectos.



Este plugin viene a sustituir y/o mejorar el uso de al menos 3 funciones de JavaScript: Alert, Confirm y Prompt. 

Pero si ya tenemos esta funcionalidad cubierta, ¿Para qué sustituirla?
Muy simple, es básicamente por un tema de estética e incluso usabilidad. Un alert, detiene la ejecución javascript a la espera que el usuario haga click en el botón aceptar, con lo que si sucediese algún evento importante, no podríamos enterarnos, ya que javascript se encuentra detenido. 

Captura de un alert normal de javascript

Captura de un alert usando SweetAlert


Como vemos en las imágenes anteriores, la mejora en cuanto diseño es muy grande, simplemente no son comparables. Esto sin contar, que podemos hacer que el mensaje se parezca o combine con nuestra página web, en cuanto a colores, iconos tipo de letra etc. 

Para usar este plugin es necesario entender cómo funcionan los callbacks en JavaScript, si aún no sabes como van, no te preocupes, lo cogerás enseguida...

Los alerts, confirm y promt los usábamos de la siguiente manera:


La ejecución del script de la imagen anterior, no llegaría ejecutar la segunda linea hasta que el usuario hiciera click en el alert... Los que nos permitía hacer cosas como la siguiente:


Con el sweetAlert no es tan simple, ya que el no detiene la ejecución de javascript, con lo que necesitaremos usar callbacks y quedará así:


Como se muestra en la imagen anterior el segundo parámetro que le pasamos a la función swal es un callback que el invocará cuando el usuario haga click en ok o cancel...

A continuación un ejemplo de su uso:



Para más información del plugin, visitar la página oficial: http://t4t5.github.io/sweetalert/

martes, 15 de septiembre de 2015

Los plugins JavaScript/jQuery más utilizados en mis desarrollos - Parte 1 - Select2


Después de utilizar infinidades de librerías y/o plugins en múltiples desarrollos web, he pensado en publicar un artículo indicando los que más he utilizado.

  1. Parte 1: Select2
  2. Parte 2: SweetAlert
  3. Parte 3: Noty
  4. Parte 4: Animate.css
  5. Parte 5: Waipoints
  6. Parte 5: ScrollToFixed
  7. Parte 6: Parallax

Select2

Con diferencia es el plugin que más he utilizado dentro de mis desarrollos, este plugin permite mejorar ampliamente la caja de selección que incorporan los navegadores (es decir el elemento select).

Es muy útil sobre todo para poder mostrar muchos elementos y cargarlos dinámicamente. Es decir, que entre su múltitus de funcionalidades, permite la carga progresiva de elemento a través de ajax, lo que nos permite evitar tener selects con cientos de options, ya que esto relentiza considerablemente la carga de la página. Lo descubrí en el año 2011 justamente debido a que tenía un select con unos 3mil registros y este cargaba muy lento.




Otro punto a resaltar de este plugin, es que nos permite fácilmente hacer una selección múltiple al estilo etiquetas, tal y como se muestra en la siguiente imagen:



También permite agrupar los elementos dentro del select, tal y como se muestra a continuación:




A continuación un pequeño ejemplo:

Ejemplo: Select 2 - Múltiple selección


Para mayor información podéis ir a la página oficial: https://select2.github.io/

martes, 19 de mayo de 2015

AX Dynamics - Job para crear clientes a través de un dialogo con campos dinámicos



Después de un tiempo ya incursionando en el mundo de axapta y su lenguaje X++, he pensado que puede venir bien escribir sobre ello, ya que hay pocos ejemplos en internet en español.

A continuación veremos un pequeño ejemplo de un job que crea clientes con dos diálogos creados dinámicamente. Para ello realizaremos los siguientes pasos

1) Ubicamos en el árbol (AOT) los jobs y presionamos botón derecho "Crear nuevo Job"


2) Especificamos el nombre del Job, lo llamaremos "InsertCustomersDinamics"


3) Introducimos el siguiente código:

static void ARInsertClients2(Args _args)
{
    //Tabla de clientes, donde insertaremos los nuevos clientes
    CustTable                    custTable;
    //Tabla de grupos de clientes
    CustGroup                   custGroup;
    //Se cuencial de clientes
    NumberSeq                  numberSeq;
    //Dialogo donde le solicitaremos al usuario, el núero de clientes a crear
    Dialog                          dialogNum;
    //Dialogo donde solicitaremos los datos de los clientes a crear
    Dialog                          dialogVals;
    DialogField                  fieldNumCus;
    DialogGroup                dialogGroupTmp;
    Array                            fieldNameCus;
    Array                            fieldCustGroup;
    boolean                        ret;
    boolean                        retAll;
    IntegerBLN                  numCustomerToCreate;
    IntegerBLN                  numCustomer;
    CustName                    custName;
    CustGroupId                custGroupId;

    //inicializamos los arrays
    fieldNameCus   = new Array(Types::Class);
    fieldCustGroup = new Array(Types::Class);

    //Solicitamos al usuario que indique el número de clientes a crear
    //textlabel @@QAP24: Carga Masiva de Clientes
    dialogNum = new Dialog("@QAP24");
    //textlabel @QAP16: Cantidad de clientes
    //textlbel @QAP23: Cantidad de clientes a crear de forma masiva
    fieldNumCus = dialogNum.addField(extendedTypeStr(IntegerBLN), "@QAP16", "@QAP23");
    fieldNumCus.mandatory_RU(true);

    dialogNum.run();
    if (dialogNum.closedOk())
    {
        numCustomerToCreate = fieldNumCus.value();

        //labeltext @QAP25: Datos de los Clientes a Crear
        dialogVals = new Dialog("@QAP25");

        for (numCustomer=1; numCustomer<=numCustomerToCreate; numCustomer+=1)
        {
            dialogGroupTmp = dialogVals.addGroup("Cliente " + int642str((numCustomer)));

            //textlabel @SYS27874: Nombre del Cliente
            fieldNameCus.value(numCustomer, dialogVals.addField(extendedTypeStr(CustName), "@SYS27874"));
            fieldNameCus.value(numCustomer).mandatory_RU(true);

            //textlabel @QAP19: Grupo de Cliente
            fieldCustGroup.value(numCustomer, dialogVals.addField(extendedTypeStr(CustGroupId), "@QAP19"));
            fieldNameCus.value(numCustomer).mandatory_RU(true);

        }

        dialogVals.run();
        if (dialogVals.closedOk())
        {
            ttsBegin;
            //inicializamos la variable rtAll a true para establecer que por defecto todo ira bien
            retAll = true;

            for (numCustomer=1; numCustomer<=numCustomerToCreate; numCustomer+=1)
            {
                custName            = fieldNameCus.value(numCustomer).value();
                custGroupId         = fieldCustGroup.value(numCustomer).value();

                //obtenemos el grupo de cliente que utilizaremos enlos clientes a crear
                custGroup = CustGroup::find(custGroupId);

                //si encontramos el grupo de clientes, continuamos
                if (custGroup)
                {
                    //Invocamos la inicialización del registro
                    custTable.initValue();

                    //obtenemos la secuencia del AccountNum de los párametros customers
                    numberSeq               = NumberSeq::newGetNum(CustParameters::numRefCustAccount());

                    //Asignamos el suguiente número
                    custTable.AccountNum    = numberSeq.num();

                    custTable.CustGroup     = custGroup.CustGroup;
                    custTable.initFromCustGroup(custGroup);

                    //ejecutamos las validaciones de la tabla
                    ret                     = custTable.validateWrite();

                    if (ret)
                    {
                        custTable.insert(DirPartyType::Organization, custName + " " + int2str(numCustomer));
                        //textlabel @QAP20: se creó satisfactoriamente el cliente cón el código {0}
                        info(strFmt("@QAP20", custTable.AccountNum));
                    }
                    else
                    {
                        //textlabel @QAP21: No se guardo el cliente
                        info("@QAP21");
                        retAll = false;
                    }
                }
                else
                {
                    //textlabel @QAP22: No se encontro el código: {0} en la tabla Grupos de Clientes
                    info(strFmt("@QAP22", custGroupId));
                    retAll = false;
                }
            }

            //si todos los registros se insertaron correctamente, hacemos el commit, sino abortamos todo.
            if (retAll)
            {
                ttsCommit;
            }
            else
            {
                ttsAbort;
            }
        }
    }

}


miércoles, 14 de enero de 2015

Para qué nos vale la comprobación con doble negación en JavaScript


Como sabéis JavaScript y su esquema de "tipado débil" permite la ejecución de ciertas instrucciones que de entrada puede parecer un poco raras tales como a===b o !!value, son expresiones que ciertamente no estamos acostumbrados a ver en lenguajes tipo c# o vb... Básicamente se debe a que internamente JavaScript realiza las conversiones de tipos (próximamente escribiré sobre este tema).


El uso de la doble negación es más común de lo que nos puede parecer en primer momento, suele utilizarse en bastantes librerías profesionales y la verdad es que una vez que te acostumbras, resulta la manera más elegante en comprobar un valor. Antes de explicar cómo funciona realmente la doble negación o el uso de doble exclamación en JavaScript , tengamos en cuentan algunas aclaraciones:

  • Al evaluar expresiones en JavaScript, este convierte automáticamente la expresión en un valor booleano. Es decir: 'true' == true
  • Cuando usamos una negación (por ejemplo: !true ) realmente lo que estamos haciendo es convertir en booleano e invertir/negar el valor evaluado, es decir !true == false o esta expresión  !'true' == false. (ambas expresiones, devuelven true, ya que convierte a booleano y evalúa la expresión)  
  • Cuando evaluamos expresiones, no hace falta comparar contra un booleano. Es decir, no hace falta que hagamos esto if (success == true) simplemente podemos hacer esto: if (success)


Entonces, una doble negación en JavaScript es...

Una doble negación en JavaScript, realmente lo que hace es con el primer símbolo de exclamación, convierte a booleano y niega (o invierte) la expresión y con la segunda exclamación, lo vuelves a negar (invertir) y obtienes el valor original convertido a booleano.

Con este post quería dejar claro los posibles resultados al utilizar la doble negación en base a lo que se este evaluando, así que a continuación veréis una tabla de resultados en base a diferentes valores evaluados:

InstrucciónResultadoComentario
!!false
false
//false es falso
!!true
true
//true es verdadero
!!0
false
//0 es falso
!!1
true
//1 es verdadero
!!-1
true
//-1 es verdadero
!!2
true
//2 se toma como objeto y al no ser undefined, es verdadero
!!3
true
//3 se toma como objeto y al no ser undefined, es verdadero
!!parseInt("test")
false
//NaN es falso
!!(vacio)
false
//empty es falso
!!"no vacio"
true
//las cadenas no vacias al no ser undefined son verdaderas
!!"0"
true
//"0" al ser una cadena se toma como verdadero
!!undefined
false
//(undefined) es falso
!!null
false
//(null) es falso
!!{a:1,b:2}
true
//(object) es verdadero
!!{}
true
//todos los objetos son verdaderos
!![]
true
//un array tambien es un objeto, con lo que es verdadero

Podéis ver esto en ejecución en el siguiente ejemplo: