﻿/*
 * HeatMap functions.
 * Authors: CHR, DFK
 * Date: 08/09/2009
 */
// MSM. Extension de filtro jquery para detectar si un elemento es realmente visible
jQuery.extend(jQuery.expr[":"], {

    reallyvisible: function(a) {
        function getFirstParentNonInheritedVisibility(a) {
            var lParents = jQuery(a).parents();
            if (lParents.length == 0)
                return 'visible';
            var i = 0;
            while (i < lParents.length) {
                var lCurrentParent = lParents[i];
                if (jQuery(lCurrentParent).css('visibility') === 'visible')
                    return 'visible';
                if (jQuery(lCurrentParent).css('visibility') === 'hidden')
                    return 'hidden';
                i++;
            }
            return 'visible';
        }
        return (a.offsetWidth > 0 || a.offsetHeight > 0) &&
                        ((jQuery(a).css('visibility') === 'visible') ||
                         ((jQuery(a).css('visibility') === 'inherit') && (getFirstParentNonInheritedVisibility(a) === 'visible')));
    }
});

function HeatMap(aMainContentId) {
    this.MainContentId = aMainContentId;
    this.StartTime = new Date();
    this.Referrer = document.referrer;
}

HeatMap.prototype.executeTests = function() {
    var lControlsToGenerate = $('form *[id!=]');
    var self = this;
    
    $.each(lControlsToGenerate, function(i, val) {
    
        var lControlTest = $get(val.id);
        
        var lControlX = self.getX(lControlTest);
        var lControlY = self.getY(lControlTest);
        
        var lControlWidth = lControlTest.offsetWidth;
        var lControlHeight = lControlTest.offsetHeight;
        
        if (lControlWidth > 0 &&
        lControlHeight > 0 &&
        val.innerHTML.trim().length > 0 &&
        lControlX > 0 &&
        lControlY > 0) {
            var lNumberPerControl = 10;
            for (i = 0; i < lNumberPerControl; i++) {
                var lFooXRel = Math.floor(Math.random() * lControlWidth);
                var lFooX = lFooXRel + lControlX;
                var lFooYRel = Math.floor(Math.random() * lControlHeight);
                var lFooY = lFooYRel + lControlY;
                
                var lFooEvent = {
                    target: lControlTest,
                    pageX: lFooX,
                    pageY: lFooY
                };
                self.registerClick(lFooEvent, 0, 0);
            }
        }
    });
    TLK.RadAlert('Clicks aleatorios generados con éxito.');
}

HeatMap.prototype.registerClick = function(e, offsetLeft, offsetTop) {
    var el = e.target;
    while ($(el).attr('id') == '' && $(el) != $(document.body)) {
        el = $(el)[0].parentNode;
    }
    
    var relX = e.pageX - this.getX(el);
    var relY = e.pageY - this.getY(el);
    
    this.doRegisterClick(el, e.target.tagName, relX, relY);
}

HeatMap.prototype.doRegisterClick = function(el, tagName, relX, relY) {
    var lElapsedMilliseconds = new Date() - this.StartTime;
    
    var clickEntity = {
        SizeX: el.offsetWidth,
        SizeY: el.offsetHeight,
        // Text: el.innerText.substr(0, 500),
        ControlClientId: el.id,
        ControlX: relX,
        ControlY: relY,
        TagName: tagName,
        ContentId: this.MainContentId,
        ElapsedTime: lElapsedMilliseconds,
        Referrer: this.Referrer,
        // Parámetros imprescindibles para que vaya con los repeater paginados
        DataPagerQueryStrings: _dataPagerQueryStrings,
        QueryString: window.location.search
    };
    
    var arguments = $.compactJSON({
        "aClick": clickEntity
    });
    
    // Ponemos OnFailNull porque hay un error extraño con navegadores NO IE
    // Se registra el click correctamente pero da un error.
    this.executeHeatMapMethod("RegisterClick", arguments, null);
}


HeatMap.prototype.generateQuery = function() {
    var query = {
        ContentId: this.MainContentId,
        DateFrom: '1990-01-01',
        DateTo: '2090-01-01',
        // Parámetros imprescindibles para que vaya con los repeater paginados
        DataPagerQueryStrings: _dataPagerQueryStrings,
        QueryString: window.location.search
    };
    
    var hMapFilters = window.top.hMapFilters;
    
    if (hMapFilters) {
        query.DateFrom = hMapFilters.DateFrom;
        query.DateTo = hMapFilters.DateTo;
    }
    
    return query;
}

HeatMap.prototype.getY = function(oElement) {
    var iReturnValue = 0;
    while (oElement != null) {
        iReturnValue += oElement.offsetTop;
        oElement = oElement.offsetParent;
    }
    return iReturnValue;
}
HeatMap.prototype.getX = function(oElement) {
    var iReturnValue = 0;
    while (oElement != null) {
        iReturnValue += oElement.offsetLeft;
        oElement = oElement.offsetParent;
    }
    return iReturnValue;
}

HeatMap.prototype.createHeatMapIFrame = function() {
    var iframe = document.createElement("iframe");
    iframe.id = "__HeatMapIframe";
    var qstringInit = '?';
    if (window.location.href.split('?') > 1) { // ya tiene query
        qstringInit = '&';
    }
    
    var qstring = 'DisableEIP=true&HeatMap=true&Width=' + document.body.offsetWidth + '&Height=' + document.body.offsetHeight;
    // Poner el ? o el & para la queryString según si ya existía o no
    var prefix = window.location.href.indexOf('?') == -1 ? '?' : '&';
    $(iframe).attr('src', window.location.href.replace('#', '') + prefix + qstring);
    
    // Ver el offset que introduce la barra del EIP
    var oEIPToolBarDiv = $get('__ContentViewerContainer');
    var lOffTop = 0;
    if (oEIPToolBarDiv) {
        lOffTop = oEIPToolBarDiv.offsetTop;
    }
    
    $(iframe).css('display', 'block');
    $(iframe).css('position', 'absolute');
    $(iframe).css('top', lOffTop + 'px');
    $(iframe).css('left', '0px');
    
    $(iframe).css('border', '0');
    $(iframe).css('border', 'none');
    $(iframe).css('z-index', '8000');
    
    $(iframe).css('height', document.body.offsetHeight);
    $(iframe).css('width', document.body.offsetWidth);
    $(iframe).css('overflow', 'hidden');
    
    //$(iframe).hide();
    //$(iframe).fadeIn();
    
    document.body.appendChild(iframe);
    //var kito = $('<div id="hMapLoading" class="progressBackgroundFilter"><img src="/pb/Controls/BackOffice/Edition/ElementEdition/Skins/Default/img/loading_blue.gif" style="border: 0px;" alt="Cargando.." />Cargando..</div>');
    var kito = $('<div id="hMapLoading" class="progressBackgroundFilter"><div class="progressImagePosition"><img alt="Calculando mapa de calor..." src="/pb/Controls/BackOffice/Edition/ElementEdition/Skins/Default/img/loading_blue.gif" style="border: 0px;" /></div><div id="progressTextPosition" class="TitleLabelField">Calculando mapa de calor...</div></div>');
    
    kito.css('position', 'fixed');
    kito.css('top', '0px');
    kito.css('left', '0px');
    kito.css('right', '0px');
    kito.css('bottom', '0px');
    kito.css('height', '100%');
    kito.css('width', '100%');
    
    kito.css('z-index', '10000');
    kito.appendTo('body');
    
    // creamos capa debajo iframe para ocultar web al redimensionar
    var lDiv = window.top.document.createElement("div");
    lDiv.id = "divFakeHeatMapBackground";
    lDiv.style.position = "absolute";
    lDiv.style.backgroundColor = "#C0C0C0";
    lDiv.style.left = "0px";
    lDiv.style.top = lOffTop + 'px';
    lDiv.style.width = "100%";
    lDiv.style.height = document.body.offsetHeight;
    lDiv.style.zIndex = 7000;
    window.top.document.body.appendChild(lDiv);
    
    return iframe;
}

HeatMap.prototype.generateHeatMap = function() {
    var query = this.generateQuery();
    var arguments = $.compactJSON({
        "aQuery": query
    });
    var self = this;

    this.executeHeatMapMethod('GetControlsToProcess', arguments, function(result) {
        var actualHeatMapPosition = new Array();
        $.each(result.d, function(i, val) {
            if (val !== null && val !== '') {
                var el = $get(val);
                // MSM: Determinamos si el elemento es realmente visible
                if (el && $(el).is(':reallyvisible')) {
                    var actualPos = {
                        ControlClientId: val,
                        PosX: self.getX(el),
                        PosY: self.getY(el),
                        ClientSizeX: el != undefined ? el.offsetWidth : 0,
                        ClientSizeY: el != undefined ? el.offsetHeight : 0
                    };
                    actualHeatMapPosition.push(actualPos);
                }
            }
        });
        self.calculateHeatMap(actualHeatMapPosition);
    });
}

HeatMap.prototype.calculateHeatMap = function(actualHeatMapPosition) {
    var lBody = document.body;
    var query = this.generateQuery();
    
    var arguments = $.compactJSON({
        "aQuery": query,
        "aWidth": lBody.offsetWidth,
        "aHeigth": $.query.get('Height'),
        "aPositions": actualHeatMapPosition
    });
    
    this.executeHeatMapMethod('CalculateHeatMap', arguments, function(result) {
        // Crear el tag imagen con el mapade calor
        var oImg = $get('__HeatMapImg');
        if (!oImg) {
            oImg = document.createElement("img");
        }
        // Ver el offset que introduce la barra del EIP
        var oEIPToolBarDiv = $get('__ContentViewerContainer');
        var lOffTop = 0;
        if (oEIPToolBarDiv) {
            lOffTop = oEIPToolBarDiv.offsetTop;
        }
        
        oImg.setAttribute('src', "/HeatMapHandler.ashx?heatMapId=" + result.d);
        $(oImg).attr('id', '__HeatMapImg');
        $(oImg).css('display', 'block');
        $(oImg).css('position', 'absolute');
        $(oImg).css('top', lOffTop + 'px');
        $(oImg).css('left', '0px');
        $(oImg).css('filter', 'alpha(opacity=80)');
        $(oImg).css('opacity', '0.8');
        $(oImg).css('z-index', '8001');
        $(oImg).css('overflow', 'hidden');
        $(oImg).attr('height', $.query.get('Height') - 5); // 5 mágico
        $(oImg).attr('width', lBody.offsetWidth);
        
        document.body.appendChild(oImg);
        window.top.$('#hMapLoading').remove();
        
    });
}

HeatMap.prototype.isHeatMapVisible = function() {
    var lTempBalls = $(".HMBallInfo");
    return (lTempBalls.length > 0);
}

HeatMap.prototype.removeHeatMapStatsIfEnabled = function() {
    var lTempBalls = $(".HMBallInfo");
    if (lTempBalls.length > 0) {
        // Es porque hay que quitarlas YA
        $.each(lTempBalls, function(i, val) {
            $(val).remove();
        });
        // Lo mismo con las capas que pudieran estar abiertas.
        var lBallLayers = $("*[class^='HMInfo']");
        $.each(lBallLayers, function(i, val) {
            $(val).remove();
        });
        return;
    }
}

HeatMap.prototype.executeHeatMapStats = function() {

    var lQuery = this.generateQuery();
    var lArguments = $.compactJSON({
        "aQuery": lQuery
    });
    var self = this;
    
    if (this.isHeatMapVisible()) {
        this.removeHeatMapStatsIfEnabled();
        return;
    }
    
    var lTempBalls = $(".HMBallInfo");
    if (lTempBalls.length > 0) {
        // Es porque hay que quitarlas YA
        $.each(lTempBalls, function(i, val) {
            $(val).remove();
        });
        // Lo mismo con las capas que pudieran estar abiertas.
        var lBallLayers = $("*[class^='HMInfo']");
        $.each(lBallLayers, function(i, val) {
            $(val).remove();
        });
        return;
    }
    
    this.executeHeatMapMethod("GetHeatMapLinkStats", lArguments, function(result) {
        if (result.d.length == 0) {
            TLK.RadAlert('No hay registros para esta página');
            return;
        }
        
        $.each(result.d, function(i, val) {
            var el = $get(val.ControlClientId);
            
            var lIcon;
            lIcon = $("<img id='" + val.ControlClientId + "_HM' class='HMBallInfo' src='/pb/img/HeatMap/Level" + val.Interval + ".png'/>");
            
            var lPosX = self.getX(el) - 22;
            var lPosY = self.getY(el) - 2;
            
            // Corrección para evitar que queden sobre la izquierda...
            if (lPosX < 0) {
                lPosX = 0;
            }
            
            lIcon.appendTo(document.body);
            lIcon.css('position', 'absolute');
            lIcon.css('left', lPosX + 'px');
            lIcon.css('top', lPosY + 'px');
            lIcon.css('z-index', '8005');
            // Agregar mouseover a la bola
            lIcon.mouseover(function(e) {
                self.ControlMouseOver(el, 'HMHilite' + val.Interval);
            });
            lIcon.mouseout(function(e) {
                self.DownliteAll();
            });
            lIcon.click(function(e) {
                self.CreateHeatZoneInfoLayer(val.ControlClientId, lPosX, lPosY, val);
            });
        });
    });
}

HeatMap.prototype.CreateHeatZoneInfoLayer = function(sourceControl, posX, posY, val) {
    var lLayerId = sourceControl + "_HMInfo";
    var self = this;
    
    var lTempLayer = $get(lLayerId);
    if (lTempLayer) {
        var lLayerToHide = $("#" + lLayerId);
        lLayerToHide.hide('slow', function() {
            lLayerToHide.remove();
        });
        return;
    }
    
    var lMasInfoId = sourceControl + "_Info";
    var lLayer = $("<div id='" + lLayerId + "' class='HMInfo" + val.Interval + "'></div>");
    var lPar = $("<b>Total de Clicks</b>: " + val.Clicks + "<br />");
    var lPar2 = $('<b>Porcentaje</b>: ' + Math.round(val.Percentage) + '%<br /><a class="HMapMasInfo" id="' + lMasInfoId + '">M&aacute;s Informaci&oacute;n</a><br />');
    
    lPar.appendTo(lLayer);
    lPar2.appendTo(lLayer);
    
    var lPosXFinal = posX + 5;
    var lPosYFinal = posY + 20;
    
    // Control para evitar que quede sobre la derecha de la pantalla.
    if (lPosXFinal > (document.body.clientWidth - 220)) {
        lPosXFinal = document.body.clientWidth - 220;
    }
    
    lLayer.css('left', lPosXFinal);
    lLayer.css('top', lPosYFinal);
    lLayer.appendTo(document.body);
    lLayer.hide();
    lLayer.fadeIn("slow");
    
    var lMasInfo = $('#' + lMasInfoId);
    lMasInfo.click(function(e) {
        lMasInfo.remove();
        self.MoreInfoLayer(lLayer, sourceControl);
        lLayer.css('width', '200px');
    });
}

HeatMap.prototype.MoreInfoLayer = function(aInfoLayer, aSourceControlId) {

    var masInfoDivContainer = $('<div></div>').appendTo(aInfoLayer);
    
    var masInfoDiv = $('<div class="hMapMoreInfoDiv"></div>').appendTo(masInfoDivContainer);
    var ulLowerTabs = $('<ul class="hMapLowerTabs"></ul>').appendTo(masInfoDivContainer);
    var lInfoText = $('<div class="hTabsToolTip"></div>').appendTo(masInfoDivContainer).hide();
    
    var browsers = this.creareMoreInfoLayerLowerTab("/pb/img/HeatMap/Navegadores.png", "Informaci&oacute;n de navegadores", lInfoText).appendTo(ulLowerTabs);
    var referrer = this.creareMoreInfoLayerLowerTab("/pb/img/HeatMap/Referer.png", "Informaci&oacute;n de Referrer", lInfoText).appendTo(ulLowerTabs);
    var timeToClick = this.creareMoreInfoLayerLowerTab("/pb/img/HeatMap/TimeToClick.png", "Informaci&oacute;n de tiempo hasta clicar", lInfoText).appendTo(ulLowerTabs);
    var os = this.creareMoreInfoLayerLowerTab("/pb/img/HeatMap/SistemaOperativo.png", "Informaci&oacute;n de Sistemas operativos", lInfoText).appendTo(ulLowerTabs);
    
    var showInfoTabFunction = Function.createDelegate(this, function(result) {
        this.showInfoTab(masInfoDiv, result);
    });
    
    var self = this;
    
    self.QueryBrowsers(aSourceControlId, function(result) {
        showInfoTabFunction(result);
    });
    browsers.click(function() {
        self.QueryBrowsers(aSourceControlId, function(result) {
            showInfoTabFunction(result);
        });
    });
    
    timeToClick.click(function() {
        self.QueryTimeToClick(aSourceControlId, function(result) {
            showInfoTabFunction(result);
        });
    });
    
    os.click(function() {
        self.QueryOperatingSystem(aSourceControlId, function(result) {
            showInfoTabFunction(result);
        });
    });
    
    referrer.click(function() {
        self.QueryReferrer(aSourceControlId, function(result) {
            showInfoTabFunction(result);
        });
    });
}

HeatMap.prototype.showInfoTab = function(masInfoDiv, result) {
    masInfoDiv.empty();
    $.each(result.d, function(i, val) {
        var divInfo = $('<div class="barDiv"><div style="margin-bottom: 5px">' + val.Description + ':</div></div>').appendTo(masInfoDiv);
        var spanBar = $('<span class="barSpan"><span class="percentageBar">' + val.Percentage + '%</span></span>').appendTo(divInfo);
        $(spanBar).progressBar(val.Percentage, {
            showText: true,
            increment: 5,
            speed: 10
        });
    });
}

HeatMap.prototype.QueryBrowsers = function(aSourceControlId, aCallBack) {
    this.ExecuteMoreInfoQuery('GetHeatMapControlStatsAgent', aSourceControlId, aCallBack);
}

HeatMap.prototype.QueryTimeToClick = function(aSourceControlId, aCallBack) {
    this.ExecuteMoreInfoQuery('GetHeatMapControlStatsTimeToClick', aSourceControlId, aCallBack);
}

HeatMap.prototype.QueryOperatingSystem = function(aSourceControlId, aCallBack) {
    this.ExecuteMoreInfoQuery('GetHeatMapControlStatsOS', aSourceControlId, aCallBack);
}


HeatMap.prototype.QueryReferrer = function(aSourceControlId, aCallBack) {
    this.ExecuteMoreInfoQuery('GetHeatMapControlStatsReferrer', aSourceControlId, aCallBack);
}

HeatMap.prototype.ExecuteMoreInfoQuery = function(aMethod, aSourceControlId, aCallBack) {
    var query = this.generateQuery();
    var arguments = $.compactJSON({
        "aQuery": query,
        "aClientControlId": aSourceControlId
    });
    this.executeHeatMapMethod(aMethod, arguments, aCallBack);
}

HeatMap.prototype.creareMoreInfoLayerLowerTab = function(src, title, infoLayer) {
    var lTab = $('<li><img src="' + src + '" title="' + title + '" alt="' + title + '"/></li>');
    //    lTab.mouseover(function(e) {
    //        infoLayer[0].innerHTML = title;
    //        infoLayer.fadeIn(300);
    //    });
    //    lTab.mouseout(function(e) {
    //        infoLayer[0].innerHTML = "";
    //        infoLayer.hide();
    //    });
    return lTab;
}


HeatMap.prototype.ControlMouseOver = function(sourceControl, borderStyle) {
    this.CrearMarcoGenerico(sourceControl, borderStyle);
}

HeatMap.prototype.DownliteAll = function(domElementToIgnore) {
    function removeIfNotCurrent(elemArray, domElementToIgnore) {
        for (var i = 0; i < elemArray.length; i++) {
            var jCurrentElement = $(elemArray[i]);
            var lSourcElement = jCurrentElement.data("sourceElement");
            if (lSourcElement !== domElementToIgnore) {
                jCurrentElement.remove();
                if ($(lSourcElement).data("highlighted")) {
                    $(lSourcElement).data("highlighted", false);
                }
            }
        }
    }
    
    removeIfNotCurrent($("*[class^='HMHilite']"), domElementToIgnore);
};

HeatMap.prototype.CrearMarcoGenerico = function(source, classname) {

    var padding = 3;
    var jSource = $(source);
    var ofs = jSource.offset();
    var h = jSource.outerHeight();
    var w = jSource.outerWidth();
    
    var lDivHightliteLeft = $("<div class='" + classname + "'></div>").appendTo($("body"));
    lDivHightliteLeft.css("left", ofs.left - padding);
    lDivHightliteLeft.css("top", ofs.top - padding);
    lDivHightliteLeft.css("width", 1);
    lDivHightliteLeft.css("height", h + 2 * padding);
    lDivHightliteLeft.data("sourceElement", source);
    
    var lDivHightliteRight = $("<div class='" + classname + "'></div>").appendTo($("body"));
    lDivHightliteRight.css("left", ofs.left + w + padding);
    lDivHightliteRight.css("top", ofs.top - padding);
    lDivHightliteRight.css("width", 1);
    lDivHightliteRight.css("height", h + 2 * padding);
    lDivHightliteRight.data("sourceElement", source);
    
    var lDivHightliteTop = $("<div class='" + classname + "'></div>").appendTo($("body"));
    lDivHightliteTop.css("left", ofs.left - padding);
    lDivHightliteTop.css("top", ofs.top - padding);
    lDivHightliteTop.css("width", w + 2 * padding);
    lDivHightliteTop.css("height", 1);
    lDivHightliteTop.data("sourceElement", source);
    
    var lDivHightliteBottom = $("<div class='" + classname + "'></div>").appendTo($("body"));
    lDivHightliteBottom.css("left", ofs.left - padding);
    lDivHightliteBottom.css("top", ofs.top + h + padding);
    lDivHightliteBottom.css("width", w + 2 * padding);
    lDivHightliteBottom.css("height", 1);
    lDivHightliteBottom.data("sourceElement", source);
    
    $("." + classname).fadeIn(300);
    
};

HeatMap.prototype.createDeleteHeatMapPopUp = function() {
    var url = '/' + utils.url.get_PageLang() + '/pb/forms/backoffice/HeatMap/HeatMapRemovePopUp.aspx';
    var wndMgr = TLK.GetRadWindowManager();
    var wnd = wndMgr.open(url);
    wnd.set_behaviors(Telerik.Web.UI.WindowBehaviors.Close);
    wnd.set_width(400);
    wnd.set_height(250);
    wnd.center();
    wnd.set_modal(true);
    wnd.set_visibleStatusbar(false);
};

HeatMap.prototype.closeHeatMapOptionsPupUp = function() {

    var wndMgr = TLK.GetRadWindowManager();
    var wnd = null;
    wnd = wndMgr.getWindowByName('HeatMapOptions');
    if (wnd != null && wnd != undefined) {
        wnd.close();
        return;
    }
};

HeatMap.prototype.isHeatMapOptionsVisible = function() {
    var wndMgr = TLK.GetRadWindowManager();
    var wnd = null;
    wnd = wndMgr.getWindowByName('HeatMapOptions');
    return (wnd != null && wnd != undefined);
};

HeatMap.prototype.createHeatMapOptionsPopUp = function() {

    var wndMgr = TLK.GetRadWindowManager();
    var url = '/' + utils.url.get_PageLang() + '/pb/forms/backoffice/HeatMap/HeatMapOptionsPopUp.aspx?ContentId=' + this.MainContentId;
    
    var wnd = wndMgr.open(url, 'HeatMapOptions');
    wnd.set_behaviors(Telerik.Web.UI.WindowBehaviors.Move + Telerik.Web.UI.WindowBehaviors.Pin);
    wnd.set_width(400);
    wnd.set_height(265);
    // Centrar para luego poder mover abajo a la derecha
    wnd.center();
    var bounds = wnd.getWindowBounds();
    
    wnd.moveTo(document.body.offsetWidth - 405, bounds.y + 150);
    
    wnd.set_visibleStatusbar(false);
    wnd.set_modal(false);
    wnd.togglePin();
    
    return wnd;
}



HeatMap.prototype.executeHeatMapMethod = function(methodName, methodArguments, onSuccess, onFail) {
    this.executeMethod("HeatMapService.asmx", methodName, methodArguments, onSuccess, onFail ? onFail : this.OnFail);
}

HeatMap.prototype.OnFailNull = function(XMLHttpRequest, textStatus, errorThrown) {
    //NOOP XD
}

HeatMap.prototype.OnFail = function(XMLHttpRequest, textStatus, errorThrown) {

    try {
        TLK.RadAlert($.evalJSON(XMLHttpRequest.responseText).Message);
    } 
    catch (e) {
        TLK.RadAlert('Ha ocurrido un error');
    }
}
HeatMap.prototype.executeMethod = function(serviceName, methodName, methodArguments, onSuccess, onFail) {
    // IMPORTANTE: En navegadores no IE (FireFox, Chrome) el registro de click sobre un enlace da un error
    // si ejecutamos la llamada de manera asíncrona. En Chrome ni siquiera hace traza.
    // Decidimos hacer síncrona la llamada para navegadores no IE para solucionar este problema.
    var isIE = navigator.userAgent.search('MSIE') != -1;
    $.ajax({
        async: isIE,
        type: "POST",
        url: "/pb/services/" + serviceName + "/" + methodName + "?pbl=" + utils.url.get_PageLang(),
        data: methodArguments,
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: onSuccess,
        error: onFail
    });
}
