<commit_before>$(document).ready(function () {
  nav = new Nav();

  // load in the tabs for navigation
  makeNavBar(nav);

  $(".navbar").click("a", getGroup);  
  $(".navbar").click("a", nav.setActive);  
  $("body").submit(".field-form", updateField); 

});

function updateField(e) {
  e.preventDefault();

  // get the form, its url, and value(theres only one)
  var $form = $(e.target);
  var url = $form.attr("action");
  var updateValue = $form.find("input").val();

  // submit an update request, refresh the page on done
  $.ajax({
    url: url,
    type: "PUT",
    contentType: "application/json",
    data: JSON.stringify({ value: updateValue})
  }).done(function(data) {
    var groupId = $('.navbar li.active').data('group-id')
    // refresh data by getting page info again and reloading the page
    $.getJSON("/groups/" + groupId, function(data) { 
      var rootTitle = $('.navbar li.active').data("group-id");
      loadPage(data); 
    });
  });
}

function getGroup(e) {
  // get the navigation link clicked
  var li = $(e.target).parent()
  var classes = li.attr("class");
  // if its not active, change the content
  if (classes == undefined || classes == "" || !classes.includes("active")) {
    // pull off the group id for a GET request
    var url = "/groups/" + li.data("group-id")
    // get the json for the page and load it
    $.getJSON(url, function(data) {
      var rootTitle = $('.navbar li.active').data("group-id");
      loadPage(data);
    })
  }
}


function makeNavBar(nav) { 
  var index = 0;
  // get the index json for groups, this is universal
  // across all xml inputs so we can get all info
  $.getJSON("/groups", function(json) {
    // iterate through the first level depth 
    $.each(json.contents, function(id, data) {
      // if there is no value, its a group
      if (data.value == undefined) {
        // add it to the navigation section
        nav.add(data.title, index, id);
      } else {
        // it its not a group add it as input
        // to the main content section
        var input = new Input(id, data);
        $(".page").append(input.$el);
      }
      
      // if this iteration is for the first menu item,
      // make it active and load its contents
      if (index == 0 && data.type == "group") {
        nav.initActiv(0);
        loadPage(data, id);
      }
      
      index++;
    });       
  });
}

function loadPage(data, rootTitle) {
  // clear whatever is in the main content area now
  $(".page").html("");

  // put in the title and description
  var $title = $("<h2>" + data.title + "</h2>");
  var $desc = $("<p>" + data.description + "</p>");

  $(".page").append($title);
  $(".page").append($desc);

  // iterate through the elements in the page
  $.each(data.contents, function(id, sectionData) {
    // if its a group, add the section header
    if (sectionData.type == "group") {
      var rootTitle = $(".active").data("group-id")
      var subGroup = new SubGroup(sectionData.title, id, true);

      addSubGroup(id, sectionData, subGroup);
      subGroup.buildUrls(rootTitle);
    } else {
      // for a field, build the url and put it in the input
      var url = "/groups/" + $(".active").data("group-id") + "/fields/"
      var input = new Input(id, sectionData, url);
      $(".page").append(input.$el);
    }
  });
}


/* 
 * Subgroup and Input related code
 */

// takes in the name and the contained data for a given subgroup
// and adds inputs as well as recursively adding any extra subgroups
function addSubGroup(name, data, parent) {
  $.each(data.contents, function(id, contents) {
    // if we have a nested group, recurse
    if (contents.type == "group") {
      var subGroup = new SubGroup(contents.title, id);
      parent.subgroups.push(subGroup);
      addSubGroup(id, contents, subGroup);
      parent.$el.find('.body-content').eq(0).append(subGroup.$el);
    } else {
      // if not a group, add input to the SubGroup object
      parent.addInput(id, contents);
    } 
  })
  $(".page").append(parent.$el);
}

// SubGroup holds some easy to access attributes as well as its DOM
// element. This allows for us to go through after fully loading a 
// page and adding the full urls easily
function SubGroup(name, id, top) {
  this.subgroups = [];
  this.inputs = [];

  this.name = name;
  this.id = id;
  if (top) {
    this.$el = $('<div class="panel panel-default"><div class="panel-heading">' + name + '</div><div class="panel-body body-content"></div></div>');
  } else {
    this.$el = $('<li class="list-group-item deep-group"><h3>' + name + '</h3><div class="body-content"></div></li>');
  }
}


// Handles making a new input and putting it in the subgroup's internal
// inputs variable as well as in the DOM
SubGroup.prototype.addInput = function(id, contents) {
  var input = new Input(id, contents);
  this.inputs.push(input);
  this.$el.find('.body-content').eq(0).append(input.$el);
}

SubGroup.prototype.buildUrls = function(url) {
  base = url + "." + this.id;
  $.each(this.inputs, function(i, input) {
    var url = "/groups/" + base + "/fields/" + input.name;
    input.$el.attr("action", url);
  });

  $.each(this.subgroups, function(i, subgroup) {
    subgroup.buildUrls(base);
  });
}


// Input is used to hold state of an input field and easily allow us to
// hold it in a SubGroup for final page loading
function Input(name, data, baseUrl) {
  // make a copy of the hidden template in the DOM
  this.$el = $($('#input-template').html()).clone()

  // keep a copy of name for when building urls
  this.name = name;
  
  // add tooltip functionality if there is a description
  if (data.description) {
    this.$el.attr("data-toggle","tooltip");
    this.$el.attr("data-placement","left");
    this.$el.attr("title",data.description);
    this.$el.tooltip();
  }

  // make the base URL and add it in
  var url = baseUrl + name;<commit_msg>Add range for placeholder and field types for integers<commit_after>$(document).ready(function () {
  nav = new Nav();

  // load in the tabs for navigation
  makeNavBar(nav);

  $(".navbar").click("a", getGroup);  
  $(".navbar").click("a", nav.setActive);  
  $("body").submit(".field-form", updateField); 

});

function updateField(e) {
  e.preventDefault();

  // get the form, its url, and value(theres only one)
  var $form = $(e.target);
  var url = $form.attr("action");
  var updateValue = $form.find("input").val();

  // submit an update request, refresh the page on done
  $.ajax({
    url: url,
    type: "PUT",
    contentType: "application/json",
    data: JSON.stringify({ value: updateValue})
  }).done(function(data) {
    var groupId = $('.navbar li.active').data('group-id')
    // refresh data by getting page info again and reloading the page
    $.getJSON("/groups/" + groupId, function(data) { 
      var rootTitle = $('.navbar li.active').data("group-id");
      loadPage(data); 
    });
  });
}

function getGroup(e) {
  // get the navigation link clicked
  var li = $(e.target).parent()
  var classes = li.attr("class");
  // if its not active, change the content
  if (classes == undefined || classes == "" || !classes.includes("active")) {
    // pull off the group id for a GET request
    var url = "/groups/" + li.data("group-id")
    // get the json for the page and load it
    $.getJSON(url, function(data) {
      var rootTitle = $('.navbar li.active').data("group-id");
      loadPage(data);
    })
  }
}


function makeNavBar(nav) { 
  var index = 0;
  // get the index json for groups, this is universal
  // across all xml inputs so we can get all info
  $.getJSON("/groups", function(json) {
    // iterate through the first level depth 
    $.each(json.contents, function(id, data) {
      // if there is no value, its a group
      if (data.value == undefined) {
        // add it to the navigation section
        nav.add(data.title, index, id);
      } else {
        // it its not a group add it as input
        // to the main content section
        var input = new Input(id, data);
        $(".page").append(input.$el);
      }
      
      // if this iteration is for the first menu item,
      // make it active and load its contents
      if (index == 0 && data.type == "group") {
        nav.initActiv(0);
        loadPage(data, id);
      }
      
      index++;
    });       
  });
}

function loadPage(data, rootTitle) {
  // clear whatever is in the main content area now
  $(".page").html("");

  // put in the title and description
  var $title = $("<h2>" + data.title + "</h2>");
  var $desc = $("<p>" + data.description + "</p>");

  $(".page").append($title);
  $(".page").append($desc);

  // iterate through the elements in the page
  $.each(data.contents, function(id, sectionData) {
    // if its a group, add the section header
    if (sectionData.type == "group") {
      var rootTitle = $(".active").data("group-id")
      var subGroup = new SubGroup(sectionData.title, id, true);

      addSubGroup(id, sectionData, subGroup);
      subGroup.buildUrls(rootTitle);
    } else {
      // for a field, build the url and put it in the input
      var url = "/groups/" + $(".active").data("group-id") + "/fields/"
      var input = new Input(id, sectionData, url);
      $(".page").append(input.$el);
    }
  });
}


/* 
 * Subgroup and Input related code
 */

// takes in the name and the contained data for a given subgroup
// and adds inputs as well as recursively adding any extra subgroups
function addSubGroup(name, data, parent) {
  $.each(data.contents, function(id, contents) {
    // if we have a nested group, recurse
    if (contents.type == "group") {
      var subGroup = new SubGroup(contents.title, id);
      parent.subgroups.push(subGroup);
      addSubGroup(id, contents, subGroup);
      parent.$el.find('.body-content').eq(0).append(subGroup.$el);
    } else {
      // if not a group, add input to the SubGroup object
      parent.addInput(id, contents);
    } 
  })
  $(".page").append(parent.$el);
}

// SubGroup holds some easy to access attributes as well as its DOM
// element. This allows for us to go through after fully loading a 
// page and adding the full urls easily
function SubGroup(name, id, top) {
  this.subgroups = [];
  this.inputs = [];

  this.name = name;
  this.id = id;

  if (top) {
    this.$el = $('<div class="panel panel-default"><div class="panel-heading">' + name + '</div><div class="panel-body body-content"></div></div>');
  } else {

    this.$el = $('<li class="list-group-item deep-group"><h3>' + name + '</h3><div class="body-content"></div></li>');
  }
}


// Handles making a new input and putting it in the subgroup's internal
// inputs variable as well as in the DOM
SubGroup.prototype.addInput = function(id, contents) {
  var input = new Input(id, contents);
  this.inputs.push(input);
  this.$el.find('.body-content').eq(0).append(input.$el);
}

SubGroup.prototype.buildUrls = function(url) {
  base = url + "." + this.id;
  $.each(this.inputs, function(i, input) {
    var url = "/groups/" + base + "/fields/" + input.name;
    input.$el.attr("action", url);
  });

  $.each(this.subgroups, function(i, subgroup) {
    subgroup.buildUrls(base);
  });
}


// Input is used to hold state of an input field and easily allow us to
// hold it in a SubGroup for final page loading
function Input(name, data, baseUrl) {
  // make a copy of the hidden template in the DOM
  this.$el = $($('#input-template').html()).clone()

  // keep a copy of name for when building urls
  this.name = name;

  // set the range if there is one
  if (data.range) {
    var range = data.range[0] + " to " + data.range[1];
    this.$el.find('input').attr("placeholder", range);
  }

  // set the form type
  switch (data.type) {
  case "base_integer":
    this.$el.find('input').attr("type","number")
    break;
  default:
    // its a string or will be soon
    this.$el.find('input').attr("type","text")
    break;
  }

  // add tooltip functionality if there is a description
  if (data.description) {
    this.$el.attr("data-toggle","tooltip");
    this.$el.attr("data-placement","left");
    this.$el.attr("title",data.description);
    this.$el.tooltip();
  }

  // make the base URL and add it in
  var url = baseUrl + name;
{'fraction_non_alphanumeric': 0.16436339847902526, 'fraction_numerical': 0.0016354567012838335, 'mean_word_length': 2.829054477144646, 'pattern_counts': {'":': 1, '<': 35, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, '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': '505323', 'n_tokens_mistral': 3842, 'n_tokens_neox': 3750, 'n_words': 1209}