lunes, 24 de abril de 2017

Error ocasionado por Response.Write y ScriptManager

La intención es hacer que cierto texto se actualice dinámicamente, según el value de un key en el web.config.

El value del key se almacena en un Session.

Si se usa Respose.Write sucede un error, y la página no responde.

<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:contentplaceholder id="ContentPlaceHolder3" runat="server">
<div class="menu_principal">
<ul class="lista_simple">
<%
Select Case Session("ROL")                  
Case "ROL007"
Response.Write("")
Case Else
%>
<div class="modulo">
<div class="titulo_modulo">
<% Response.Write(Session("MASTER_CALEND_ACAD"))%>
</div>
<div>
<ul class="lista_simple">
<li><a href="lima_2017-I.pdf" id="calLima"   target = "_Blank"   >Lima</a></li>
</ul>
</div>
</div>

<%
End Select
%>
</asp:contentplaceholder>
</ContentTemplate>
</asp:UpdatePanel>

Esto genera el siguiente error en el ScriptManager:
No se pudo analizar el mensaje recibido del servidor. Este error suele producirse cuando la respuesta resulta modificada por llamadas a Response.Write() o cuando los filtros de respuesta, los HttpModules o el seguimiento de servidor están habilitados.

La solución es no usar Response.Write. En vez de eso, se debe usar una función pública que devuelva el value del key.

VB
==
Public Function Titulo_Mostrar() As String
Return System.Configuration.ConfigurationManager.AppSettings("MasterCalendAcad")
End Function

Y reemplazar

ASPX
====
<% Response.Write(Session("MASTER_CALEND_ACAD"))%>

por

ASPX
====
<%=Titulo_Mostrar()%>

Listo.

lunes, 2 de enero de 2017

Crystal Reports - Error de conector de base de datos desconocido

Este mensaje aparece al asignar nuestro dataset tipado al reporte.

dtFichaInscrip.TableName = "FichaIns"
ds.Tables.Add(dtFichaInscrip)
rpt.SetDataSource(ds)

Para solucionarlo, en el archivo App.config de nuestro proyecto de Escritorio debemos agregar unas líneas, y comentar otras.

Debe quedar así:

<?xml version="1.0"?>
<configuration>
    <!--<startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/>        
    </startup>-->

    <startup useLegacyV2RuntimeActivationPolicy="true">
        <supportedRuntime version="v4.0"/>
    </startup>
.
.
.


martes, 19 de julio de 2016

Diálogo modal con Bootstrap, Javascript y jQuery

En el archivo *.js:

function Notas_Evaluciones_jQuery(NumNota) {
    var Contenedor = '#ContentPlaceHolder1_';

    $('.css' + NumNota).on('click', function (e) {
        $('#dlgEval').modal({
            keyboard: true,          //Puede cerrar el diálogo con ESC
            backdrop: 'static'      //Se cierra el diálogo sólo con los botones o ESC
        });

        $('#dlgEval').modal('show');


        return false;
    });

    return false;
}

En el archivo *.aspx:

<div class="modal fade" id="dlgEval" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
  <div class="modal-dialog" role="document">
<div class="modal-content">
 <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Cerrar"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="myModalLabel">Ficha de evaluación del participante</h4>
 </div>
 <div runat="server" id="divDlgEval" class="modal-body">          
 </div>
 <div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cerrar</button>
<button type="button" class="btn btn-primary">Guardar</button>
 </div>
</div>
  </div>
</div>

martes, 14 de junio de 2016

Crystal Reports 2008 - Servidor ocupado

Al iniciar Crystal Reports 2008, aparece un pequeño diálogo que dice: "No se puede completar esta acción porque el otro programa esta ocupado. Elija Cambiar a... para activar el programa ocupado y corregir el problema."


La solución es la siguiente:

1) Abrir el Administrador de tareas (CTRL + ALT + SUPR).
2) Ubicar la tarea Agent.exe y finalizarla.


3) En el pequeño diálogo que dice Servidor ocupado, hacer clic en el botón Reintentar.


4) Ahora que ya se pudo abrir Crystal Reports, en el menú Ayuda, desmarcar la opción Comprobar actualizaciones al iniciar.


5) Salir y volver a entrar para comprobar que ya se solucionó.

miércoles, 1 de junio de 2016

SP_HELPTEXT en MySQL

En MySql, el equivalente de sp_helptext de SQL Server se escribe así:

show create procedure Nombre_Procedimiento_Almacenado;

Por ejemplo: show create procedure pa_Encuestas_Sesion_Respuesta_INS;

El código del sp está en la columna Create Procedure de la tabla resultado.

lunes, 2 de mayo de 2016

Desactivar Ir a página anterior con tecla Retroceder (Backspace)

Hasta ahora, es el único código que funciona en los tres navegadores principales.

Javascript
=========
$(document).ready(function () {
    $(document).on("keydown", function (e) {
        if (e.which === 8 && !$(e.target).is("input:not([textarea]), [contentEditable], [contentEditable=true]")) {
            e.preventDefault();
        }

        if (e.which === 8 && !$(e.target).is("input:not([readonly]):not([type=radio]):not([type=checkbox])")) {

            e.preventDefault();
        }
    });
});

Quitar funcionalidad a un textbox DatePicker jQuery UI

Javascript / jQuery
==============

// boolEstado: true, false 

if (boolEstado) {
    $(Contenedor + 'txtFecSesion').datepicker('disable');
}
else {
    $(Contenedor + 'txtFecSesion').datepicker('enable');
}

Cruce de horarios

Como la validación del lado del servidor era demasiado lenta, implementé esta solución del lado del cliente, más sencilla.


Javascript
========

//Horario: 'MAR 11:44-19:15'
//HorarioList: 'MAR 09:15-11:45 - JUE 08:30-10:00 - SAB 09:15-1145'

function Cruce_De_Horario(Horario, HorarioList) {
    var Dias = Horario.split(' - ');
    var DiasList = HorarioList.split(' - ');
    var i = 0, k = 0;

    var Dia_Hora_I, Dia_Hora_K;
    var Dia_I, H1_I, H2_I, Dia_K, H1_K, H2_K;

    for (i = 1; i <= Dias.length; i++) {
        Dia_Hora_I = Dias[i - 1].split(' ');

        Dia_I = Dia_Hora_I[0];
        H1_I = new Date('2016/01/01 ' + Dia_Hora_I[1].split('-')[0]);
        H2_I = new Date('2016/01/01 ' + Dia_Hora_I[1].split('-')[1]);

        for (k = 1; k <= DiasList.length; k++) {
            Dia_Hora_K = DiasList[k - 1].split(' ');

            Dia_K = Dia_Hora_K[0];
            H1_K = new Date('2016/01/01 ' + Dia_Hora_K[1].split('-')[0]);
            H2_K = new Date('2016/01/01 ' + Dia_Hora_K[1].split('-')[1]);

            if (Dia_I == Dia_K) {
                if (H1_I >= H1_K && H1_I <= H2_K) {
                    if (H1_I.getHours() != H2_K.getHours() || H1_I.getMinutes() != H2_K.getMinutes()) {

                        return Dia_Hora_I[0] + ' ' + Dia_Hora_I[1] + '|' + Dia_Hora_K[0] + ' ' + Dia_Hora_K[1];
                    }
                }

                if (H2_I >= H1_K && H2_I <= H2_K) {
                    if (H2_I.getHours() != H1_K.getHours() || H2_I.getMinutes() != H1_K.getMinutes()) {

                        return Dia_Hora_I[0] + ' ' + Dia_Hora_I[1] + '|' + Dia_Hora_K[0] + ' ' + Dia_Hora_K[1];
                    }
                }
            }
        }
    }

    return '';
}

La idea es validar que no haya cruce de horario entre el curso seleccionado arriba, y los ya seleccionados abajo.




SweetAlert no muestra diálogo de confirmación después de grabar

Mi error fue no haber establecido a false la propiedad closeOnConfirm de la primera alerta, que desencadena en la segunda.

Debe ser así:

Javascript
=========

$(Contenedor + 'btnGuardar').click(function () {
Controles_Validar_Reiniciar();

if (!Controles_Validar()) {
return false;
}

Dialogo_ConfirmarRegistro();   //1° Alerta

return false;
});

function Dialogo_ConfirmarRegistro() {
    swal({
        title: "Confirmar registro de notas",
        text: "Las notas ingresadas van a ser registradas. ¿Desea continuar?",
        type: "warning",
        showCancelButton: true,
        confirmButtonClass: "btn-danger",
        confirmButtonText: "Sí",
        cancelButtonText: "No",
        closeOnConfirm: false,
        allowEscapeKey: true
    },
        function () {
            Registrar_Notas();            
        }
    );

    return false;
}

function Registrar_Notas() {
    var Contenedor = '#ContentPlaceHolder1_';
    var CodSemestre = $(Contenedor + 'ddlSemestre').val();
    var CodCompetencia = $(Contenedor + 'ddlCompetencia').val();
    var CodCarga = $(Contenedor + 'hdnCodCarga').val();
    var CodCurso = $(Contenedor + 'hdnCodCurso').val();  
    var CodNota = $(Contenedor + 'hdnNota').val();
    var CodFecha = $(Contenedor + 'txtFecSesion').val();
    var IdControl = '_txt' + CodNota + '_';
    var IdCheck = '_chkSinNota_';
    var arrNotas = new Array();
 
    $(Contenedor + 'dtgNotas .css' + CodNota).each(function (index) {
        var objNotas = {
            CodAlumno: '',
            CodNota: 0.00
        };

        objNotas.CodAlumno = $('#' + this.id.replace(IdControl, '_lblCodAlumno_')).text();

        if ($('#' + this.id.replace(IdControl, IdCheck)).is(':checked')) {          
            objNotas.CodNota = -1.00;
        }
        else {
            objNotas.CodNota = parseFloat(this.value);
        }

        arrNotas.push(objNotas);
    });

    var objParams = {
        Semestre: CodSemestre,
        CodCarga: CodCarga,
        CodCurso: CodCurso,
        CodCompetencia: CodCompetencia,
        NumNota: CodNota,
        FecSesion: CodFecha,
        arrNotas: arrNotas      
    };  

    var arg = Sys.Serialization.JavaScriptSerializer.serialize(objParams);

    MostrarEspera(true);

    Registrar_Notas_Call(arg, function (result) {
        var Entity = Sys.Serialization.JavaScriptSerializer.deserialize(result.split('~')[0]);

        MostrarEspera(false);

        if (Entity.Resultado == "1") {
            //2° Alerta: Success
            swal({
                title: 'Operación completada',
                text: 'Las notas ingresadas han sido registradas correctamente.',
                type: 'success',
                showCancelButton: false,
                confirmButtonClass: 'btn-info',
                confirmButtonText: 'Aceptar',
                closeOnConfirm: false,
                allowEscapeKey: false
            },
                function () {
                    Reiniciar_Formulario();   
                }
            );
        }
        else {
            Dialogo_Error(Entity.MsgError);   //2° Alerta: Error
        }

        $(Contenedor + 'hdnMsgError').val(Entity.MsgError);
        $(Contenedor + 'hdnMsgErrorBD').val(Entity.MsgBD);

        return false;
    });

    return false;
}

function Dialogo_Error(MsgError) {
    swal({
        title: 'Operación no completada',
        text: MsgError,
        type: "warning",
        showConfirmButton: false,
        showCancelButton: true,
        cancelButtonText: "Aceptar",
        closeOnConfirm: false,
        allowEscapeKey: true
    });

    return false;
}

martes, 28 de mayo de 2013

Horas / Minutos transcurridos entre dos fechas

select
rtrim(DATEDIFF(MI, '27/05/2013 09:52:00','27/05/2013 11:41:00') / 60) +
':' +
rtrim(DATEDIFF(MI, '27/05/2013 09:52:00','27/05/2013 11:41:00') % 60)

viernes, 17 de mayo de 2013

Pasar más de un parámetro al jQuery autocomplete

Normalmente pasamos un sólo valor al autocomplete: el valor escrito en el textbox (request.term). ¿Y si queremos pasar algún otro valor, por ejemplo, para usarlo como parámetro en un sp?
 
HTML
====
<table width="800px" border="0">
    <tr>
        <td style="width:90px;">
            N° Nota Salida
        </td>
        <td>
            <asp:TextBox ID="txtNumeroDoc" runat="server" Width="80px" MaxLength="10" CssClass="IntegerType">

        </td>
        <td>
             <asp:HiddenField runat="server" ID="hdnCodUsuario" Value="1" />
        </td>
    </tr>
</table>


Javascript
==========
$(document).ready(function () {

    $('#txtNumeroDoc').autocomplete({
        source: function (request, response) {
            $.ajax({
                type: 'POST',
                contentType: 'application/json; charset=utf-8',
                url: '../../ws/autocomplete.asmx/NotaIngresoSalida',
                data: "{'tag': '" + request.term + "', 'CodUsuario': '" + $('#hdnCodUsuario').val() + "'}",
          
                dataType: 'json',
                async: true,
                success: function (data) {
                    response($.map(data.d, function (item) {
                        return {
                            value: item.value,
                            label: item.label,
                            seriedoc: item.seriedoc,
                            numerodoc: item.numerodoc
                        };
                    }));
                },
                error: function (result) {
                    alert('No se pudo cargar la lista de notas de salida.');
                }
            });
        },
        minLength: 2,
        select: function (event, ui) {
            NotaIngresoSalida_Buscar(ui.item.seriedoc, ui.item.numerodoc);
        }
    });

});

function NotaIngresoSalida_Buscar(strSerieDoc, strNumeroDoc) {
    alert(strSerieDoc + '-' + strNumeroDoc);

    return false;
}



WebServices
===========
   <WebMethod()> _
    Public Function NotaIngresoSalida(ByVal tag As String, ByVal CodUsuario As String) As Object
        Dim output As String = ""

        Dim lhtbResultado = New With {.value = "", .label = "", .seriedoc = "", .numerodoc = ""}
        Dim Lista = {lhtbResultado}.ToList()

        Try
            Dim objbnNotaIngresoSalida As New bnNotaIngresoSalida
            Dim dt As New DataTable

            dt = objbnNotaIngresoSalida.pf_NotaIngresoSalida_Salidas_Autocomplete(tag, CodUsuario)

            If dt.Rows.Count > 0 Then
                Lista.RemoveAt(0)

                For i = 0 To dt.Rows.Count - 1
                    Dim lhtbItem = New With {.value = "", .label = "", .seriedoc = "", .numerodoc = ""}

                    With lhtbItem
                        .value = dt(i).Item(0)
                        .label = dt(i).Item(0)
                        .seriedoc = dt(i).Item(1)
                        .numerodoc = dt(i).Item(2)
                    End With

                    Lista.Add(lhtbItem)
                Next
            End If

            output = Lista.ToString()

        Catch ex As Exception

        End Try

        Return Lista
    End Function

lunes, 13 de mayo de 2013

Obtener el id del tr que contiene un input específico

¿Cuál es el ID de la fila de una tabla que contiene un textbox que está siendo procesado por nuestro script?

HTML
==== 
<div id="divMod2" class="divNeumatConfig" style="display:none;">
    <table style="width:850px;" class="ui-widget ui-widget-content ui-corner-all">
        <tr>
            <td align="center">                                          
                <table border="0" width="840px">
                    <tr id="trMod2Eje1">
                        <td colspan="2" align="right">
                            <asp:TextBox runat="server" ID="txtMod2Pos1" Width="80px" CssClass="CodNeumatico" style="text-align:center"></asp:TextBox>
                        </td>
                        <td class="celdanegra">1</td>
                        <td>&nbsp;</td>
                        <td>&nbsp;</td>
                        <td>&nbsp;</td>
                        <td>&nbsp;</td>
                        <td class="celdanegra">2</td>
                        <td colspan="2" align="left">
                            <asp:TextBox runat="server" ID="txtMod2Pos2" Width="80px" CssClass="CodNeumatico" style="text-align:center"></asp:TextBox>
                        </td>
                    </tr>
                    <tr>
                        <td colspan="2" align="right">
                            <asp:TextBox runat="server" ID="txtMod2Pos1Med" CssClass="BorderlessRight"></asp:TextBox><asp:ImageButton ID="imgMod2Pos1" runat="server" CssClass="imgMarca" ImageUrl="~/images/neumaticos/nothing.png" Height="27px" Width="30px" ImageAlign="AbsMiddle"/>
                        </td>
                        <td>&nbsp;</td>
                        <td>&nbsp;</td>
                        <td>&nbsp;</td>
                        <td>&nbsp;</td>
                        <td>&nbsp;</td>
                        <td>&nbsp;</td>
                        <td colspan="2">                                                      
                            <asp:ImageButton ID="imgMod2Pos2" runat="server" CssClass="imgMarca" ImageUrl="~/images/neumaticos/nothing.png" Height="27px" Width="30px" ImageAlign="AbsMiddle"/><asp:TextBox runat="server" ID="txtMod2Pos2Med" CssClass="BorderlessLeft"></asp:TextBox>
                        </td>
                    </tr>
                </table>                                          
            </td>
        </tr>
    </table>      
</div>


JavaScript
==========
$('#divMod' + $(Contenedor + 'hdnModeloCfg').val() + ' .CodNeumatico').each(function (index) {
    intPosicion = parseInt(this.id.split('Pos')[1], 10);       
    intEje = parseInt($(this).closest('tr').attr('id').split('Eje')[1],10);

    var objNeumatConf = {
        CodNeumatico: $('#' + this.id).val(),
        Eje: intEje,
        Posicion: intPosicion
    };

    arrNeumaticos.push(objNeumatConf);
});

martes, 23 de abril de 2013

Ocultar título de un dialog específico

La idea es asignar un nombre único de clase al diálogo (por ejemplo, "alert"), para luego ocultar la barra de título del diálogo que tenga la clase especificada.

//Diálogo "Procesando...". No lleva barra de título.
function MostrarEspera(pboolMostrar) {
    if (pboolMostrar) {
        $('#dlgWait').dialog({
            autoOpen: false,
            modal: true,
            height: 'auto',
            dialogClass: 'alert'
        });

        $('.alert div.ui-dialog-titlebar').hide();
        $('.ui-button').remove();  //Opcional: remueve el botón Cerrar (x) de TODOS los diálogos...
        $('#dlgWait').dialog('open');
    }
    else {
        $('#dlgWait').dialog('close');
    }
}


//Diálogo para editar un item. Lleva barra de título.
function EditRow(HlkControlID) {
    $('#dlgEditarNeumatico').dialog({
        autoOpen: false,
        modal: true,
        height: 'auto',
        width: 1100,
        dialogClass: 'Edit'
    });

    $('#dlgEditarNeumatico').dialog('open');  
    $('.ui-button').remove();

    return false;
}

lunes, 7 de mayo de 2012

Una nueva aventura

No tengo ni la menor idea de lo que debo publicar aquí. Así que, por mientras, escribiré acerca de mi día a día y sobre algunas cosas que no debería olvidar. Porque ese es mi mayor problema - virtud: olvido rápido.