<commit_before>//= jquery
//= console-helper
//= jquery.gridster.with-extras
//= underscore

$(function() {

  //----------------------
  // Alert for timeouts
  //----------------------
  function check_last_server_communication (li, config){
    var lastUpdate = $(li).attr('last-update');

    if (lastUpdate){
      var elapsedEl = '.widget-title span.widget-elapsed';
      if ($(elapsedEl, li).length === 0){
        $('.widget-title', li).append('<span class="widget-elapsed"></span>');
      }

      var elapsed = ((+new Date()) - lastUpdate);

      if (config.interval){ // job has a specific predefined interval
        // calculate based on retryOnErrorTimes or use 2xinterval.
        var max_time_to_show_offline = config.interval * (config.retryOnErrorTimes || 2);
        if (elapsed > max_time_to_show_offline){ // this widget if offline
          var str_elapsed = ' <span class="alert alert_high">&gt;1h</span>';
          $('.widget-title span.widget-elapsed', li).html(str_elapsed);
          $('.content', li).addClass('offline');
        }
        else{
          $('.widget-title span.widget-elapsed', li).html('');
          $('.content', li).removeClass('offline');
        }

        $('.widget-title span.widget-elapsed', li).html('');
      }
    }
  }

  var defaultHandlers = { //they can be overwritten by widget´s custom implementation
    onError : function (el, data){
      var timestamp = new Date();
      $('.content', el).html("<div class='error'>" + data.error + " (" + timestamp.toISOString() + ")</div>");
      console.error(data);
    },
    onInit : function (el, data){
      $("<img class=\"spinner\" src=\"images/spinner.gif\">").insertBefore($('.content', el));
    }
  };

  var globalHandlers = { //global pre-post event handlers
    onPreError : function (el, data){
      $('.content', el).addClass('onerror');
      $(".spinner", el).hide();
    },

    onPreData : function (el, data){
      $('.content', el).removeClass('onerror');
      $(".spinner", el).hide();
    }
  };

  if (!$("#widgets-container").length)
      return;

  function log_error (eventId, err){
    console.error('ERROR on ' + eventId + ': ' + err);
  }

  function bind_widget(widgetsSocket, li){
    var widgetId = encodeURIComponent($(li).attr("data-widget-id"));
    var eventId = $(li).attr("data-event-id");

    // fetch widget html and css
    $(li).load("/widgets/" + widgetId, function() {

      // fetch widget js
      $.get('/widgets/' + widgetId + '/js', function(js) {

        try{
          eval('var widget_js = ' + js);
          widget_js = $.extend({}, defaultHandlers, widget_js);
          widget_js.onInit(li);
        }
        catch (e){
          log_error(eventId, e);
        }

        widgetsSocket.on(eventId, function (data) { //bind socket.io event listener
            var f = data.error ? widget_js.onError : widget_js.onData;

            globalHandlers.onPreData.apply(widget_js, $(li));

            if (data.error){
              globalHandlers.onPreError.apply(widget_js, [$(li), data]);
            }

            try{
              f.apply(widget_js, [$(li), data]);
            }
            catch (e){
              log_error(eventId, e);
            }

            // save timestamp
            $(li).attr("last-update", +new Date());

            //----------------------
            // Server timeout notifications
            //----------------------
            if (!widget_js.config){ // fill config when first data arrives
              widget_js.config = data.config;
              setInterval(function(){
                check_last_server_communication(li, widget_js.config);
              }, 5000);
            }
        });

        widgetsSocket.emit("resend", eventId);
        console.log("Sending resend for " + eventId);

      });
    });
  }

  function bind_ui(widgetsSocket){
    var gutter = parseInt($("#main-container").css("paddingTop"), 10) * 2;
    var gridsterGutter = gutter/2;
    var height = 1080 - $("#widgets-container").offset().top - gridsterGutter;
    var width = $("#widgets-container").width();
    var vertical_cells = 4, horizontal_cells = 6;
    var widgetSize = {
      w: (width - horizontal_cells * gutter) / horizontal_cells,
      h: (height - vertical_cells * gutter) / vertical_cells
    };

    $(".gridster ul").gridster({
      widget_margins: [gridsterGutter, gridsterGutter],
      widget_base_dimensions: [widgetSize.w, widgetSize.h]
    })
    .children("li").each(function(index, li) {
      bind_widget(widgetsSocket, li);
    });
  }

  var options = {
    'reconnect': true,
    'reconnection delay': 5000,
    'reopen delay': 3000,
    'max reconnection attempts': 100
  };

  //----------------------
  // widget socket
  //----------------------
  var socket_w = io.connect('/widgets', options);

  socket_w.on("connect", function() {

    console.log('connected');
    $('#main-container').removeClass("disconnected");

    bind_ui(socket_w);

    socket_w.on("disconnect", function() {
      $('#main-container').addClass("disconnected");
      console.log('disconnected');
    });<commit_msg>Extract function to bind socket to gridster li<commit_after>//= jquery
//= console-helper
//= jquery.gridster.with-extras
//= underscore

$(function() {

  //----------------------
  // Alert for timeouts
  //----------------------
  function check_last_server_communication (li, config){
    var lastUpdate = $(li).attr('last-update');

    if (lastUpdate){
      var elapsedEl = '.widget-title span.widget-elapsed';
      if ($(elapsedEl, li).length === 0){
        $('.widget-title', li).append('<span class="widget-elapsed"></span>');
      }

      var elapsed = ((+new Date()) - lastUpdate);

      if (config.interval){ // job has a specific predefined interval
        // calculate based on retryOnErrorTimes or use 2xinterval.
        var max_time_to_show_offline = config.interval * (config.retryOnErrorTimes || 2);
        if (elapsed > max_time_to_show_offline){ // this widget if offline
          var str_elapsed = ' <span class="alert alert_high">&gt;1h</span>';
          $('.widget-title span.widget-elapsed', li).html(str_elapsed);
          $('.content', li).addClass('offline');
        }
        else{
          $('.widget-title span.widget-elapsed', li).html('');
          $('.content', li).removeClass('offline');
        }

        $('.widget-title span.widget-elapsed', li).html('');
      }
    }
  }

  var defaultHandlers = { //they can be overwritten by widget´s custom implementation
    onError : function (el, data){
      var timestamp = new Date();
      $('.content', el).html("<div class='error'>" + data.error + " (" + timestamp.toISOString() + ")</div>");
      console.error(data);
    },
    onInit : function (el, data){
      $("<img class=\"spinner\" src=\"images/spinner.gif\">").insertBefore($('.content', el));
    }
  };

  var globalHandlers = { //global pre-post event handlers
    onPreError : function (el, data){
      $('.content', el).addClass('onerror');
      $(".spinner", el).hide();
    },

    onPreData : function (el, data){
      $('.content', el).removeClass('onerror');
      $(".spinner", el).hide();
    }
  };

  if (!$("#widgets-container").length)
      return;

  function log_error (eventId, err){
    console.error('ERROR on ' + eventId + ': ' + err);
  }

  function bind_widget(io, li){
    var widgetId = encodeURIComponent($(li).attr("data-widget-id"));
    var eventId = $(li).attr("data-event-id");

    // fetch widget html and css
    $(li).load("/widgets/" + widgetId, function() {

      // fetch widget js
      $.get('/widgets/' + widgetId + '/js', function(js) {

        try{
          eval('var widget_js = ' + js);
          widget_js = $.extend({}, defaultHandlers, widget_js);
          widget_js.onInit(li);
        }
        catch (e){
          log_error(eventId, e);
        }

        io.on(eventId, function (data) { //bind socket.io event listener
            var f = data.error ? widget_js.onError : widget_js.onData;

            globalHandlers.onPreData.apply(widget_js, $(li));

            if (data.error){
              globalHandlers.onPreError.apply(widget_js, [$(li), data]);
            }

            try{
              f.apply(widget_js, [$(li), data]);
            }
            catch (e){
              log_error(eventId, e);
            }

            // save timestamp
            $(li).attr("last-update", +new Date());

            //----------------------
            // Server timeout notifications
            //----------------------
            if (!widget_js.config){ // fill config when first data arrives
              widget_js.config = data.config;
              setInterval(function(){
                check_last_server_communication(li, widget_js.config);
              }, 5000);
            }
        });

        io.emit("resend", eventId);
        console.log("Sending resend for " + eventId);

      });
    });
  }

  function buildUI(mainContainer, gridsterContainer){
    var gutter = parseInt(mainContainer.css("paddingTop"), 10) * 2;
    var gridsterGutter = gutter/2;
    var height = 1080 - mainContainer.offset().top - gridsterGutter;
    var width = mainContainer.width();
    var vertical_cells = 4, horizontal_cells = 6;
    var widgetSize = {
      w: (width - horizontal_cells * gutter) / horizontal_cells,
      h: (height - vertical_cells * gutter) / vertical_cells
    };

    gridsterContainer.gridster({
      widget_margins: [gridsterGutter, gridsterGutter],
      widget_base_dimensions: [widgetSize.w, widgetSize.h]
    });
  }

  function bindSocket (io, gridsterContainer){
    gridsterContainer.children("li").each(function(index, li) {
      bind_widget(io, li);
    });
  }

  //----------------------
  // Main
  //----------------------

  var mainContainer = $("#main-container");
  var gridsterContainer = $(".gridster ul");

  buildUI(mainContainer, gridsterContainer);

  var options = {
    'reconnect': true,
    'reconnection delay': 5000,
    'reopen delay': 3000,
    'max reconnection attempts': 100
  };

  //----------------------
  // widget socket
  //----------------------
  var socket_w = io.connect('/widgets', options);

  socket_w.on("connect", function() {

    console.log('connected');
    $('#main-container').removeClass("disconnected");

    bindSocket(socket_w, gridsterContainer);

    socket_w.on("disconnect", function() {
      $('#main-container').addClass("disconnected");
      console.log('disconnected');
    });
{'fraction_non_alphanumeric': 0.18987101669195752, 'fraction_numerical': 0.005500758725341426, 'mean_word_length': 2.163816381638164, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '225705', 'n_tokens_mistral': 3194, 'n_tokens_neox': 3037, 'n_words': 650}