<commit_before>$.ajaxSetup({
  type: "POST",
  async: false,
  traditional: true,
  scriptCharset: "utf-8",
  contentType: "application/x-www-form-urlencoded;charset=UTF-8"
});

String.prototype.endsWith = function(str){return (this.match(str+"$")==str)}

var pathArray = window.location.pathname.split( '/' );
var webAppPath;
if (!(typeof(CONTEXT_PATH) == 'undefined')){
  webAppPath = CONTEXT_PATH;
}
if(webAppPath == undefined){
  webAppPath = "/" + pathArray[1];
}

if(webAppPath.endsWith("/")) {
  webAppPath = webAppPath.substr(0, webAppPath.length-1);
}

var GB_ANIMATION = true;
var CDF_CHILDREN = 1;
var CDF_SELF = 2;
var ERROR_IMAGE = webAppPath + "/content/pentaho-cdf/resources/style/images/error.png";
var CDF_ERROR_DIV = 'cdfErrorDiv';

$.blockUI.defaults.fadeIn = 0;
$.blockUI.defaults.message = '<div style="padding: 15px;"><img src="' + webAppPath + '/content/pentaho-cdf/resources/style/images/busy.gif" /><h3>Processing...</h3></div>';
$.blockUI.defaults.css.left = '40%';
$.blockUI.defaults.css.top = '30%';
$.blockUI.defaults.css.marginLeft = '85px';
$.blockUI.defaults.css.width = '170px';
$.blockUI.defaults.css.opacity = '.8';
$.blockUI.defaults.css['-webkit-border-radius'] = '10px'; 
$.blockUI.defaults.css['-moz-border-radius'] = '10px';


var ERROR_CODES = [];
ERROR_CODES["UNKNOWN"] = ["ERROR: ","resources/style/images/error.jpg"];
ERROR_CODES["0012"] = ["No data available (MDXLookupRule did not execute successfully)","resources/style/images/alert.jpg"];
ERROR_CODES["0006"] = ["Could not establish a connection to the database","resources/style/images/error.jpg"];


if (typeof $.SetImpromptuDefaults == 'function')
  $.SetImpromptuDefaults({
    prefix: 'colsJqi',
    show: 'slideDown'
  });

var Dashboards = 
	{
		TRAFFIC_RED: webAppPath + "/content/pentaho-cdf/resources/style/images/traffic_red.png",
		TRAFFIC_YELLOW: webAppPath + "/content/pentaho-cdf/resources/style/images/traffic_yellow.png",
		TRAFFIC_GREEN: webAppPath + "/content/pentaho-cdf/resources/style/images/traffic_green.png",
		globalContext: true, // globalContext determines if components and params are retrieved from the current window's object or from the Dashboards singleton
		runningCalls: 0, // Used to control progress indicator for async mode
		components: [],
		parameters: [], // only used if globalContext = false
		args: [],
		monthNames : ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
        i18nCurrentLanguageCode : null,  // Reference to current language code . Used in every place where jquery plugins used in CDF hasm native internationalization support (ex: Datepicker)
        i18nSupport : null  // Reference to i18n objects
	}

// Log
Dashboards.log = function(m){
  if (typeof console != "undefined" ){
    console.log("CDF: " + m);
  }
}

// REFRESH ENGINE begin

Dashboards.RefreshEngine = function(){// Manages periodic refresh of components

  var NO_REFRESH = 0;//currently no distinction between explicitly disabled or not set
  var refreshQueue = new Array();//component refresh queue
  var activeTimer = null;//timer for individual component refresh

  var globalRefreshPeriod = NO_REFRESH;
  var globalTimer = null;

  Dashboards.RefreshEngine.QueueItem = function() {
    return {
      nextRefresh : 0,
      component : null
    };
  }

  //set global refresh and (re)start interval
  var startGlobalRefresh = function(refreshPeriod){
    if (globalTimer != null) {
      clearInterval(globalTimer);
      globalTimer = null;
    }
    globalRefreshPeriod = (refreshPeriod >0)? refreshPeriod : NO_REFRESH;
    if(globalRefreshPeriod != NO_REFRESH){
      globalTimer = setInterval("Dashboards.refreshEngine.fireGlobalRefresh()",globalRefreshPeriod * 1000);//ToDo: cleaner way to call
    }
  }

  var clearFromQueue = function(component){
    for (var i = 0; i < refreshQueue.length; i++) {
      if (refreshQueue[i].component == component) {
        refreshQueue.splice(i,1);
        i--;
      }
    }
  }

  var clearQueue = function(){
    if(refreshQueue.length > 0) refreshQueue.splice(0,refreshQueue.length);
  }

  //binary search for elem's position in coll (nextRefresh asc order)
  var getSortedInsertPosition = function(coll, elem){
    var high = coll.length - 1;
    var low = 0;
    var mid;

    while (low <= high) {
      mid = parseInt((low + high) / 2)
      if (coll[mid].nextRefresh > elem.nextRefresh) {
        high = mid - 1;
      } else if (coll[mid].nextRefresh < elem.nextRefresh) {
        low = mid + 1;
      } else {//==
        return mid;
      }
    }
    return low;
  }
  var sortedInsert = function(rtArray,rtInfo){
    var pos = getSortedInsertPosition(rtArray,rtInfo);
    rtArray.splice(pos,0,rtInfo);
  }

  var stopTimer = function(){
    if (activeTimer != null) {
      clearTimeout(activeTimer);
      activeTimer = null;
    }
  }

  var restartTimer = function(){
    stopTimer();
    Dashboards.refreshEngine.fireRefresh();
  }

  var getCurrentTime = function (){
    var date = new Date();
    return date.getTime();
  }

  var isFirstInQueue = function(component){
    return refreshQueue.length > 0 && refreshQueue[0].component == component;
  }

  var refreshComponent = function(component){
    //if refresh period is too short, progress indicator will stay in user's face
    //		let(Dashboards.runningCalls = 0){
    Dashboards.update(component);
  //			Dashboards.runningCalls = 0;
  //			Dashboards.hideProgressIndicator()
  //		}
  }

  var insertInQueue = function(component){
    var time = getCurrentTime();
    // normalize invalid refresh
    if (!(component.refreshPeriod > 0)) {
      component.refreshPeriod = NO_REFRESH;
    }
    if (component.refreshPeriod != NO_REFRESH) {
      //get next refresh time for component
      var info = new Dashboards.RefreshEngine.QueueItem();
      info.nextRefresh = time + (component.refreshPeriod * 1000);
      info.component = component;
      sortedInsert(refreshQueue, info);
    }
  }
  return {

    //set a component's refresh period and clears it from the queue if there;
    //processComponent must be called to activate the refresh timer for the component
    registerComponent : function(component, refreshPeriod){
      if(!component) return false;

      component.refreshPeriod = (refreshPeriod > 0)? refreshPeriod : NO_REFRESH;
      var wasFirst =  isFirstInQueue(component);
      clearFromQueue(component);
      if(wasFirst) restartTimer();

      return true;
    },

    getRefreshPeriod : function(component){
      if(component && component.refreshPeriod > 0) return component.refreshPeriod;
      else return NO_REFRESH;
    },

    //sets next refresh for given component and inserts it in refreshQueue, restarts timer if needed
    processComponent : function(component){
      insertInQueue(component);
      if(isFirstInQueue(component)) restartTimer();
      return true;//dbg
    },

    //clears queue, sets next refresh for all components, restarts timer
    processComponents : function(){
      clearQueue();
      for(var i=0; i<Dashboards.components.length;i++){
        insertInQueue(Dashboards.components[i]);
      }
      restartTimer();
      return true;//dbg
    },

    //pop due items from queue, refresh components and set next timeout
    fireRefresh : function(){
      activeTimer = null;
      var currentTime = getCurrentTime();

      while(refreshQueue.length > 0 &&
        refreshQueue[0].nextRefresh <= currentTime){
        var info = refreshQueue.shift();//pop first
        //call update, which calls processComponent
        refreshComponent(info.component);
      }
      if(refreshQueue.length > 0){
        activeTimer = setTimeout("Dashboards.refreshEngine.fireRefresh()", refreshQueue[0].nextRefresh - currentTime );//ToDo: cleaner way to call
      //activeTimer = setTimeout(this.fireRefresh, refreshQueue[0].nextRefresh - currentTime );
      }
    },

    // called when a valid globalRefreshPeriod exists
    // updates all components without their own refresh period
    fireGlobalRefresh: function(){
      for(i=0;i<Dashboards.components.length;i++){
        var comp = Dashboards.components[i];
        if (!(comp.refreshPeriod > 0) //only update those without refresh
          && comp.type != "select") { //and that are not pov widgets
          refreshComponent(comp);
        }
      }
    },

    setGlobalRefresh : function(refreshPeriod){
      startGlobalRefresh(refreshPeriod);
    },

    getQueue : function(){
      return refreshQueue;
    }
  };
}

Dashboards.refreshEngine = new Dashboards.RefreshEngine();

//REFRESH ENGINE end

Dashboards.setGlobalContext = function(globalContext) {
  Dashboards.globalContext = globalContext;
}

Dashboards.showProgressIndicator = function() {
  Dashboards.blockUIwithDrag();
}

Dashboards.hideProgressIndicator = function() {
  if(Dashboards.runningCalls <= 0){
    $.unblockUI();
    Dashboards.showErrorTooltip();
  }
}

Dashboards.incrementRunningCalls = function() {
  Dashboards.runningCalls++ ;
  Dashboards.showProgressIndicator();
//Dashboards.log("+Running calls incremented to: " + Dashboards.runningCalls);
}

Dashboards.decrementRunningCalls = function() {
  Dashboards.runningCalls-- ;
  //Dashboards.log("-Running calls decremented to: " + Dashboards.runningCalls);
  if(Dashboards.runningCalls<=0){
    Dashboards.hideProgressIndicator();
    Dashboards.runningCalls = 0; // Just in case
  }
}

Dashboards.bindControl = function(object) {

  // see if there is a class defined for this object
  var objectType = typeof object["type"]=='function'?object.type():object.type;
  var classNames = [
  // try type as class name
  objectType,
  // try Type as class name with first letter uppercase
  objectType.substring(0,1).toUpperCase() + objectType.substring(1),
  // try TypeComponent as class name
  objectType.substring(0,1).toUpperCase() + objectType.substring(1) + 'Component'
  ];
  
  var objectImpl;
  for (var i = 0; i < classNames.length && (objectImpl == null || typeof objectImpl == 'undefined'); i++) {
    try {
      eval('objectImpl = new ' + classNames[i]);
    } catch (e) {
    }
  }
  
  if (typeof objectImpl == 'undefined'){
    alert ("Object type " + object["type"] + " can't be mapped to a valid class");
  } else {
	// this will add the methods from the inherited class. Overrides not allowed
	$.extend(object,objectImpl);
  }
}

Dashboards.blockUIwithDrag = function() {
    if (typeof Dashboards.i18nSupport !== "undefined" && Dashboards.i18nSupport != null) {
        // If i18n support is enabled process the message accordingly
        $.blockUI.defaults.message = '<div style="padding: 15px;"><img src="' + webAppPath + '/content/pentaho-cdf/resources/style/images/busy.gif" /><h3>' + Dashboards.i18nSupport.prop('processing.message') + '</h3></div>';
    }

  $.blockUI();
  var handle = $('<div id="blockUIDragHandle" style="cursor: pointer; width: 170px; -webkit-border-radius: 5px; -moz-border-radius: 5px; background-color: rgba(0,0,0,0.25);" align="right"><a style="padding-right: 5px; text-decoration: none; color: black; font-weight: bold; font-color: black; font-size: 8pt" href="javascript:$.unblockUI()" title="Click to unblock">X</a></div>')
  $("div.blockUI.blockMsg").prepend(handle);
  $("div.blockUI.blockMsg").draggable({
    handle: "#blockUIDragHandle"
  });
}

//Dashboards.xactionCallback = function(object,str){
//	$('#'+object.htmlObject).html(str);
//	Dashboards.runningCalls--;
//}

Dashboards.update = function(object) {
  if(!(typeof(object.preExecution)=='undefined')){
    var ret = object.preExecution.apply(object);
    if (typeof ret != "undefined" && !ret)
      return; // if preExecution returns false, we'll skip the update
  }
  if (object.tooltip != undefined){
    object._tooltip = typeof object["tooltip"]=='function'?object.tooltip():object.tooltip;
  }
  // first see if there is an objectImpl
  if ((object.update != undefined) &&
    (typeof object['update'] == 'function')) {
    object.update();
		
    // check if component has periodic refresh and schedule next update
    this.refreshEngine.processComponent(object);
		
  } else {
  // unsupported update call
  }

  if(!(typeof(object.postExecution)=='undefined')){
    object.postExecution.apply(object);
  }
  // if we have a tooltip component, how is the time.
  if (object._tooltip != undefined){
    $("#" + object.htmlObject).attr("title",object._tooltip).tooltip({
      delay:0,
      track: true,
      fade: 250
    });
  }
};

Dashboards.createAndCleanErrorDiv = function(){
  if ($("#"+CDF_ERROR_DIV).length == 0){
    $("body").append("<div id='" +  CDF_ERROR_DIV + "'></div>");
  }
  $("#"+CDF_ERROR_DIV).empty();
}<commit_msg>added better error handling to Dashboards.update()<commit_after>$.ajaxSetup({
  type: "POST",
  async: false,
  traditional: true,
  scriptCharset: "utf-8",
  contentType: "application/x-www-form-urlencoded;charset=UTF-8"
});

String.prototype.endsWith = function(str){return (this.match(str+"$")==str)}

var pathArray = window.location.pathname.split( '/' );
var webAppPath;
if (!(typeof(CONTEXT_PATH) == 'undefined')){
  webAppPath = CONTEXT_PATH;
}
if(webAppPath == undefined){
  webAppPath = "/" + pathArray[1];
}

if(webAppPath.endsWith("/")) {
  webAppPath = webAppPath.substr(0, webAppPath.length-1);
}

var GB_ANIMATION = true;
var CDF_CHILDREN = 1;
var CDF_SELF = 2;
var ERROR_IMAGE = webAppPath + "/content/pentaho-cdf/resources/style/images/error.png";
var CDF_ERROR_DIV = 'cdfErrorDiv';

$.blockUI.defaults.fadeIn = 0;
$.blockUI.defaults.message = '<div style="padding: 15px;"><img src="' + webAppPath + '/content/pentaho-cdf/resources/style/images/busy.gif" /><h3>Processing...</h3></div>';
$.blockUI.defaults.css.left = '40%';
$.blockUI.defaults.css.top = '30%';
$.blockUI.defaults.css.marginLeft = '85px';
$.blockUI.defaults.css.width = '170px';
$.blockUI.defaults.css.opacity = '.8';
$.blockUI.defaults.css['-webkit-border-radius'] = '10px'; 
$.blockUI.defaults.css['-moz-border-radius'] = '10px';


var ERROR_CODES = [];
ERROR_CODES["UNKNOWN"] = ["ERROR: ","resources/style/images/error.jpg"];
ERROR_CODES["0012"] = ["No data available (MDXLookupRule did not execute successfully)","resources/style/images/alert.jpg"];
ERROR_CODES["0006"] = ["Could not establish a connection to the database","resources/style/images/error.jpg"];


if (typeof $.SetImpromptuDefaults == 'function')
  $.SetImpromptuDefaults({
    prefix: 'colsJqi',
    show: 'slideDown'
  });

var Dashboards = 
	{
		TRAFFIC_RED: webAppPath + "/content/pentaho-cdf/resources/style/images/traffic_red.png",
		TRAFFIC_YELLOW: webAppPath + "/content/pentaho-cdf/resources/style/images/traffic_yellow.png",
		TRAFFIC_GREEN: webAppPath + "/content/pentaho-cdf/resources/style/images/traffic_green.png",
		globalContext: true, // globalContext determines if components and params are retrieved from the current window's object or from the Dashboards singleton
		runningCalls: 0, // Used to control progress indicator for async mode
		components: [],
		parameters: [], // only used if globalContext = false
		args: [],
		monthNames : ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
        i18nCurrentLanguageCode : null,  // Reference to current language code . Used in every place where jquery plugins used in CDF hasm native internationalization support (ex: Datepicker)
        i18nSupport : null  // Reference to i18n objects
	}

// Log
Dashboards.log = function(m){
  if (typeof console != "undefined" ){
    console.log("CDF: " + m);
  }
}

// REFRESH ENGINE begin

Dashboards.RefreshEngine = function(){// Manages periodic refresh of components

  var NO_REFRESH = 0;//currently no distinction between explicitly disabled or not set
  var refreshQueue = new Array();//component refresh queue
  var activeTimer = null;//timer for individual component refresh

  var globalRefreshPeriod = NO_REFRESH;
  var globalTimer = null;

  Dashboards.RefreshEngine.QueueItem = function() {
    return {
      nextRefresh : 0,
      component : null
    };
  }

  //set global refresh and (re)start interval
  var startGlobalRefresh = function(refreshPeriod){
    if (globalTimer != null) {
      clearInterval(globalTimer);
      globalTimer = null;
    }
    globalRefreshPeriod = (refreshPeriod >0)? refreshPeriod : NO_REFRESH;
    if(globalRefreshPeriod != NO_REFRESH){
      globalTimer = setInterval("Dashboards.refreshEngine.fireGlobalRefresh()",globalRefreshPeriod * 1000);//ToDo: cleaner way to call
    }
  }

  var clearFromQueue = function(component){
    for (var i = 0; i < refreshQueue.length; i++) {
      if (refreshQueue[i].component == component) {
        refreshQueue.splice(i,1);
        i--;
      }
    }
  }

  var clearQueue = function(){
    if(refreshQueue.length > 0) refreshQueue.splice(0,refreshQueue.length);
  }

  //binary search for elem's position in coll (nextRefresh asc order)
  var getSortedInsertPosition = function(coll, elem){
    var high = coll.length - 1;
    var low = 0;
    var mid;

    while (low <= high) {
      mid = parseInt((low + high) / 2)
      if (coll[mid].nextRefresh > elem.nextRefresh) {
        high = mid - 1;
      } else if (coll[mid].nextRefresh < elem.nextRefresh) {
        low = mid + 1;
      } else {//==
        return mid;
      }
    }
    return low;
  }
  var sortedInsert = function(rtArray,rtInfo){
    var pos = getSortedInsertPosition(rtArray,rtInfo);
    rtArray.splice(pos,0,rtInfo);
  }

  var stopTimer = function(){
    if (activeTimer != null) {
      clearTimeout(activeTimer);
      activeTimer = null;
    }
  }

  var restartTimer = function(){
    stopTimer();
    Dashboards.refreshEngine.fireRefresh();
  }

  var getCurrentTime = function (){
    var date = new Date();
    return date.getTime();
  }

  var isFirstInQueue = function(component){
    return refreshQueue.length > 0 && refreshQueue[0].component == component;
  }

  var refreshComponent = function(component){
    //if refresh period is too short, progress indicator will stay in user's face
    //		let(Dashboards.runningCalls = 0){
    Dashboards.update(component);
  //			Dashboards.runningCalls = 0;
  //			Dashboards.hideProgressIndicator()
  //		}
  }

  var insertInQueue = function(component){
    var time = getCurrentTime();
    // normalize invalid refresh
    if (!(component.refreshPeriod > 0)) {
      component.refreshPeriod = NO_REFRESH;
    }
    if (component.refreshPeriod != NO_REFRESH) {
      //get next refresh time for component
      var info = new Dashboards.RefreshEngine.QueueItem();
      info.nextRefresh = time + (component.refreshPeriod * 1000);
      info.component = component;
      sortedInsert(refreshQueue, info);
    }
  }
  return {

    //set a component's refresh period and clears it from the queue if there;
    //processComponent must be called to activate the refresh timer for the component
    registerComponent : function(component, refreshPeriod){
      if(!component) return false;

      component.refreshPeriod = (refreshPeriod > 0)? refreshPeriod : NO_REFRESH;
      var wasFirst =  isFirstInQueue(component);
      clearFromQueue(component);
      if(wasFirst) restartTimer();

      return true;
    },

    getRefreshPeriod : function(component){
      if(component && component.refreshPeriod > 0) return component.refreshPeriod;
      else return NO_REFRESH;
    },

    //sets next refresh for given component and inserts it in refreshQueue, restarts timer if needed
    processComponent : function(component){
      insertInQueue(component);
      if(isFirstInQueue(component)) restartTimer();
      return true;//dbg
    },

    //clears queue, sets next refresh for all components, restarts timer
    processComponents : function(){
      clearQueue();
      for(var i=0; i<Dashboards.components.length;i++){
        insertInQueue(Dashboards.components[i]);
      }
      restartTimer();
      return true;//dbg
    },

    //pop due items from queue, refresh components and set next timeout
    fireRefresh : function(){
      activeTimer = null;
      var currentTime = getCurrentTime();

      while(refreshQueue.length > 0 &&
        refreshQueue[0].nextRefresh <= currentTime){
        var info = refreshQueue.shift();//pop first
        //call update, which calls processComponent
        refreshComponent(info.component);
      }
      if(refreshQueue.length > 0){
        activeTimer = setTimeout("Dashboards.refreshEngine.fireRefresh()", refreshQueue[0].nextRefresh - currentTime );//ToDo: cleaner way to call
      //activeTimer = setTimeout(this.fireRefresh, refreshQueue[0].nextRefresh - currentTime );
      }
    },

    // called when a valid globalRefreshPeriod exists
    // updates all components without their own refresh period
    fireGlobalRefresh: function(){
      for(i=0;i<Dashboards.components.length;i++){
        var comp = Dashboards.components[i];
        if (!(comp.refreshPeriod > 0) //only update those without refresh
          && comp.type != "select") { //and that are not pov widgets
          refreshComponent(comp);
        }
      }
    },

    setGlobalRefresh : function(refreshPeriod){
      startGlobalRefresh(refreshPeriod);
    },

    getQueue : function(){
      return refreshQueue;
    }
  };
}

Dashboards.refreshEngine = new Dashboards.RefreshEngine();

//REFRESH ENGINE end

Dashboards.setGlobalContext = function(globalContext) {
  Dashboards.globalContext = globalContext;
}

Dashboards.showProgressIndicator = function() {
  Dashboards.blockUIwithDrag();
}

Dashboards.hideProgressIndicator = function() {
  if(Dashboards.runningCalls <= 0){
    $.unblockUI();
    Dashboards.showErrorTooltip();
  }
}

Dashboards.incrementRunningCalls = function() {
  Dashboards.runningCalls++ ;
  Dashboards.showProgressIndicator();
//Dashboards.log("+Running calls incremented to: " + Dashboards.runningCalls);
}

Dashboards.decrementRunningCalls = function() {
  Dashboards.runningCalls-- ;
  //Dashboards.log("-Running calls decremented to: " + Dashboards.runningCalls);
  if(Dashboards.runningCalls<=0){
    Dashboards.hideProgressIndicator();
    Dashboards.runningCalls = 0; // Just in case
  }
}

Dashboards.bindControl = function(object) {

  // see if there is a class defined for this object
  var objectType = typeof object["type"]=='function'?object.type():object.type;
  var classNames = [
  // try type as class name
  objectType,
  // try Type as class name with first letter uppercase
  objectType.substring(0,1).toUpperCase() + objectType.substring(1),
  // try TypeComponent as class name
  objectType.substring(0,1).toUpperCase() + objectType.substring(1) + 'Component'
  ];
  
  var objectImpl;
  for (var i = 0; i < classNames.length && (objectImpl == null || typeof objectImpl == 'undefined'); i++) {
    try {
      eval('objectImpl = new ' + classNames[i]);
    } catch (e) {
    }
  }
  
  if (typeof objectImpl == 'undefined'){
    alert ("Object type " + object["type"] + " can't be mapped to a valid class");
  } else {
	// this will add the methods from the inherited class. Overrides not allowed
	$.extend(object,objectImpl);
  }
}

Dashboards.blockUIwithDrag = function() {
    if (typeof Dashboards.i18nSupport !== "undefined" && Dashboards.i18nSupport != null) {
        // If i18n support is enabled process the message accordingly
        $.blockUI.defaults.message = '<div style="padding: 15px;"><img src="' + webAppPath + '/content/pentaho-cdf/resources/style/images/busy.gif" /><h3>' + Dashboards.i18nSupport.prop('processing.message') + '</h3></div>';
    }

  $.blockUI();
  var handle = $('<div id="blockUIDragHandle" style="cursor: pointer; width: 170px; -webkit-border-radius: 5px; -moz-border-radius: 5px; background-color: rgba(0,0,0,0.25);" align="right"><a style="padding-right: 5px; text-decoration: none; color: black; font-weight: bold; font-color: black; font-size: 8pt" href="javascript:$.unblockUI()" title="Click to unblock">X</a></div>')
  $("div.blockUI.blockMsg").prepend(handle);
  $("div.blockUI.blockMsg").draggable({
    handle: "#blockUIDragHandle"
  });
}

//Dashboards.xactionCallback = function(object,str){
//	$('#'+object.htmlObject).html(str);
//	Dashboards.runningCalls--;
//}

Dashboards.update = function(object) {
  try {
    if(!(typeof(object.preExecution)=='undefined')){
      var ret = object.preExecution.apply(object);
      if (typeof ret != "undefined" && !ret)
        return; // if preExecution returns false, we'll skip the update
    }
    if (object.tooltip != undefined){
      object._tooltip = typeof object["tooltip"]=='function'?object.tooltip():object.tooltip;
    }
    // first see if there is an objectImpl
    if ((object.update != undefined) &&
      (typeof object['update'] == 'function')) {
      object.update();
  		
      // check if component has periodic refresh and schedule next update
      this.refreshEngine.processComponent(object);
  		
    } else {
    // unsupported update call
    }
  
    if(!(typeof(object.postExecution)=='undefined')){
      object.postExecution.apply(object);
    }
    // if we have a tooltip component, how is the time.
    if (object._tooltip != undefined){
      $("#" + object.htmlObject).attr("title",object._tooltip).tooltip({
        delay:0,
        track: true,
        fade: 250
      });
    }
  } catch (e) {
    this.log("Error updating " + object.name +": "+ e);
  }
};

Dashboards.createAndCleanErrorDiv = function(){
  if ($("#"+CDF_ERROR_DIV).length == 0){
    $("body").append("<div id='" +  CDF_ERROR_DIV + "'></div>");
  }
  $("#"+CDF_ERROR_DIV).empty();
}
{'fraction_non_alphanumeric': 0.13904576436222005, 'fraction_numerical': 0.009113924050632912, 'mean_word_length': 3.567057986481679, 'pattern_counts': {'":': 1, '<': 53, '<?xml version=': 0, '>': 55, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3388627', 'n_tokens_mistral': 8045, 'n_tokens_neox': 7723, 'n_words': 1852}