<commit_before>'use strict';

import moduleName from '../../../../Frontend/js/app/angular/name';

describe('Controllers', function() {
  let scope;
  let passPromise = true;
  let controller;

  // Mocked Services
  angular.module('mocks', [])
    .factory('deepNgLoginService', function($q) {
      var anonymousLogin = jasmine.createSpy('anonymousLogin')
        .andCallFake(function() {
        var token = 'test_token';

        if (passPromise) {
          return $q.when(token);
        } else {
          return $q.reject('something went wrong');
        }

      });

      return {
        anonymousLogin: anonymousLogin(),
      };
    })
    .factory('deepNgToDoService', function($q) {
      var fetchAllToDo = () => {
        return ['test', 'fetched'];
      };

      var createToDo = () => {
        return 'createToDo called';
      };

      var deleTodo = () => {
        return 'deleTodo called';
      };

      return {
        fetchAllToDo: fetchAllToDo,
        todoList: ['test', 'fetched'],
        editedTodo: null,
        allChecked: false,
        createToDo: createToDo,
        deleteTodo: deleTodo(),
        originalTodo: {
          Title: 'todo',
          Completed: true,
        },
      };
    });

  beforeEach(function() {
    angular.mock.module(moduleName);
    angular.module('mocks');
  });

  beforeEach(
    inject(
      ($rootScope, $controller, _deepNgLoginService_, _deepNgToDoService_) => {
        scope = $rootScope.$new();

        let inputParameters = {
          $scope: scope,
          deepNgToDoService: _deepNgToDoService_,
          deepNgLoginService: _deepNgLoginService_,
        };

        scope.$digest();

        controller = $controller('DeepNgToDoController', inputParameters);
        scope.$digest();
      })
  );

  describe('DeepNgToDoController', function() {
    it('DeepNgToDoController constructor sets valid default values',
      function() {
        expect(Object.keys(controller).length).toBe(4);
        expect(typeof controller.toDoService).toEqual('object');
        expect(typeof controller.deepLog).toEqual('object');
      }
    );

    it('create() sets title="" and saving=false with response.isError',
      function() {
        let actualResult = null;
        let error = null;
        controller.title = 'test';

        try {
          actualResult = controller.create();
        } catch (e) {
          error = e;
        }

        //@todo - add check for async
        expect(error).toBe(null);
      }
    );

    it(
      'update() for event === "blur" && this.prevEvent === "submit"',
      function() {
        let actualResult = null;
        let error = null;
        let completedTask = {
          Title: 'todo',
          Completed: true,
        };
        controller.prevEvent = 'submit';

        try {
          actualResult = controller.update(completedTask, 'blur');
        } catch (e) {
          error = e;
        }

        expect(actualResult).toBe(undefined);
        expect(error).toBe(null);
        expect(controller.prevEvent).toBe(null);
      }
    );

    it('update() method for reverted === true ', function() {
      let actualResult = null;
      let error = null;
      let completedTask = {
        Title: 'todo',
        Completed: true,
      };
      let event = 'blur';
      controller.prevEvent = false;
      controller.reverted = true;

      try {
        actualResult = controller.update(completedTask, event);
      } catch (e) {
        error = e;
      }

      expect(actualResult).toBe(undefined);
      expect(error).toBe(null);
      expect(controller.reverted).toBe(null);
    });

    it(
      'update() !reverted and todo.Title !== toDoService.originalTodo.Title',
      function() {
        let actualResult = null;
        let error = null;
        let completedTask = {
          Title: 'new todo',
          Completed: true,
        };
        let event = 'blur';
        controller.prevEvent = false;
        controller.reverted = false;

        try {
          actualResult = controller.update(completedTask, event);
        } catch (e) {
          error = e;
        }

        expect(error).toBe(null);
        expect(controller.reverted).toBe(false);
        expect(controller.toDoService.editedTodo).toBe(null);
        expect(actualResult).toBe(undefined);
      }
    );

    it('delete() method', function() {
      let error = null;
      let completedTask = {
        Title: 'todo',
        Completed: true,
      };

      try {
        controller.delete(completedTask);
      } catch (e) {
        error = e;
      }

      expect(error).toBe(null);
    });

    it('toggleCompleted() method', function() {
      let error = null;
      let completedTask = {
        Title: 'todo',
        Completed: true,
      };

      try {
        controller.toggleCompleted(completedTask, true);
      } catch (e) {
        error = e;
      }

      expect(error).toBe(null);
    });

    it('markAll() method', function() {
      let error = null;

      try {
        controller.markAll(true);
      } catch (e) {
        error = e;
      }

      expect(error).toBe(null);
    });
  });
});
<commit_msg>Fixed controller unit test<commit_after>'use strict';

import moduleName from '../../../../Frontend/js/app/angular/name';

describe('Controllers', function() {
  let scope;
  let passPromise = true;
  let controller;

  // Mocked Services
  angular.module('mocks', [])
    .factory('deepNgLoginService', function($q) {
      var anonymousLogin = jasmine.createSpy('anonymousLogin')
        .andCallFake(function() {
        var token = 'test_token';

        if (passPromise) {
          return $q.when(token);
        } else {
          return $q.reject('something went wrong');
        }

      });

      return {
        anonymousLogin: anonymousLogin(),
      };
    })
    .factory('deepNgToDoService', function($q) {
      var fetchAllToDo = () => {
        return ['test', 'fetched'];
      };

      var createToDo = () => {
        return 'createToDo called';
      };

      var deleTodo = () => {
        return 'deleTodo called';
      };

      return {
        fetchAllToDo: fetchAllToDo,
        todoList: ['test', 'fetched'],
        editedTodo: null,
        allChecked: false,
        createToDo: createToDo,
        deleteTodo: deleTodo(),
        originalTodo: {
          Title: 'todo',
          Completed: true,
        },
      };
    });

  beforeEach(function() {
    angular.mock.module(moduleName);
    angular.module('mocks');
  });

  beforeEach(
    inject(
      ($rootScope, $controller, _deepNgLoginService_, _deepNgToDoService_) => {
        scope = $rootScope.$new();

        let inputParameters = {
          $scope: scope,
          deepNgToDoService: _deepNgToDoService_,
          deepNgLoginService: _deepNgLoginService_,
        };

        scope.$digest();

        controller = $controller('DeepNgToDoController', inputParameters);
        scope.$digest();
      })
  );

  describe('DeepNgToDoController', function() {
    it('DeepNgToDoController constructor sets valid default values',
      function() {
        expect(Object.keys(controller).length).toBe(4);
        expect(typeof controller.toDoService).toEqual('object');
        expect(typeof controller.deepLog).toEqual('object');
      }
    );

    it('create() sets title="" and saving=false with response.isError',
      function() {
        let actualResult = null;
        let error = null;
        controller.title = 'test';

        try {
          actualResult = controller.create();
        } catch (e) {
          error = e;
        }

        //@todo - add check for async
        expect(error).toBe(null);
      }
    );

    it(
      'update() for event === "blur" && this.prevEvent === "submit"',
      function() {
        let actualResult = null;
        let error = null;
        let completedTask = {
          Title: 'todo',
          Completed: true,
        };
        controller.prevEvent = 'submit';

        try {
          actualResult = controller.update(completedTask, 'blur');
        } catch (e) {
          error = e;
        }

        expect(actualResult).toBe(undefined);
        expect(error).toBe(null);
        expect(controller.prevEvent).toBe(null);
      }
    );

    it('update() method for reverted === true ', function() {
      let actualResult = null;
      let error = null;
      let completedTask = {
        Title: 'todo',
        Completed: true,
      };
      let event = 'blur';
      controller.prevEvent = false;
      controller.toDoService.reverted = true;

      try {
        actualResult = controller.update(completedTask, event);
      } catch (e) {
        error = e;
      }

      expect(actualResult).toBe(undefined);
      expect(error).toBe(null);
      expect(controller.toDoService.reverted).toBe(null);
    });

    it(
      'update() !reverted and todo.Title !== toDoService.originalTodo.Title',
      function() {
        let actualResult = null;
        let error = null;
        let completedTask = {
          Title: 'new todo',
          Completed: true,
        };
        let event = 'blur';
        controller.prevEvent = false;
        controller.toDoService.reverted = false;

        try {
          actualResult = controller.update(completedTask, event);
        } catch (e) {
          error = e;
        }

        expect(error).toBe(null);
        expect(controller.toDoService.reverted).toBe(false);
        expect(controller.toDoService.editedTodo).toBe(null);
        expect(actualResult).toBe(undefined);
      }
    );

    it('delete() method', function() {
      let error = null;
      let completedTask = {
        Title: 'todo',
        Completed: true,
      };

      try {
        controller.delete(completedTask);
      } catch (e) {
        error = e;
      }

      expect(error).toBe(null);
    });

    it('toggleCompleted() method', function() {
      let error = null;
      let completedTask = {
        Title: 'todo',
        Completed: true,
      };

      try {
        controller.toggleCompleted(completedTask, true);
      } catch (e) {
        error = e;
      }

      expect(error).toBe(null);
    });

    it('markAll() method', function() {
      let error = null;

      try {
        controller.markAll(true);
      } catch (e) {
        error = e;
      }

      expect(error).toBe(null);
    });
  });
});
<|endoftext|>


<commit_before>/**
 * @fileoverview Transformer Visualization D3 javascript code.
 *
 *

 *  Based on: https://github.com/tensorflow/tensor2tensor/blob/master/tensor2tensor/visualization/attention.js
 *
 * Change log:
 *
 * 12/19/18  Jesse Vig   Assorted cleanup. Changed orientation of attention matrices.
 */

requirejs(['jquery', 'd3'], function($, d3) {

const TEXT_SIZE = 15;
const BOXWIDTH = TEXT_SIZE * 8;
const BOXHEIGHT = TEXT_SIZE * 1.5;
const WIDTH = 2000;
const HEIGHT_PADDING = 100;
const MATRIX_WIDTH = 150;
const HEAD_COLORS = d3.scale.category10();
const CHECKBOX_SIZE = 20;

var params = window.params;
var config = {};

function lighten(color) {
  var c = d3.hsl(color);
  var increment = (1 - c.l) * 0.6;
  c.l += increment;
  c.s -= increment;
  return c;
}

function transpose(mat) {
  return mat[0].map(function(col, i) {
    return mat.map(function(row) {
      return row[i];
    });
  });
}

function zip(a, b) {
  return a.map(function (e, i) {
    return [e, b[i]];
  });
}

function render() {

  var attnData = config.attention[config.filter];
  var leftText = attnData.left_text;
  var rightText = attnData.right_text;
  var attentionHeads = attnData.attn[config.layer];

  $("#vis svg").empty();
  $("#vis").empty();

  var height = config.initialTextLength * BOXHEIGHT * 2 + HEIGHT_PADDING;
  var svg = d3.select("#vis")
            .append('svg')
            .attr("width", WIDTH)
            .attr("height", height);

  var attData = [];
  for (var i=0; i < config.nHeads; i++) {
    var att = attentionHeads[i];
    var att_trans = transpose(att);
    attData.push(zip(att_trans, att));
  }

  renderText(svg, leftText, true, attData, 0);
  renderText(svg, rightText, false, attData, MATRIX_WIDTH + BOXWIDTH);

  renderAttentionHighlights(svg, attData);

  svg.append("g").classed("attentionHeads", true);

  renderAttention(svg, attentionHeads);

  drawCheckboxes(0, svg, attentionHeads);

}

function renderText(svg, text, isLeft, attData, leftPos) {
  // attData: list of tuples (att, att_trans), one for each layer. att and att_trans are attention matrics for each layer.
  //           att is of shape [nHeads, source_len, target_len)
  var id = isLeft ? "left" : "right";
  var textContainer = svg.append("svg:g")
                         .attr("id", id);

  textContainer.append("g").classed("attentionBoxes", true)
               .selectAll("g")
               .data(attData)
               .enter()
               .append("g")
               .selectAll("rect")
               .data(function(d) {return d;})
               .enter()
               .append("rect")
               .attr("x", function(d, i, j) {
                 return leftPos + boxOffsets(j);
               })
               .attr("y", function(d, i) {
                 return (+1) * BOXHEIGHT;
               })
               .attr("width", BOXWIDTH / activeHeads())
               .attr("height", function() { return BOXHEIGHT; })
               .attr("fill", function(d, i, j) {
                  return HEAD_COLORS(j);
                })
               .style("opacity", 0.0);

  var tokenContainer = textContainer.append("g").selectAll("g")
                                    .data(text)
                                    .enter()
                                    .append("g");

  tokenContainer.append("rect")
                .classed("background", true)
                .style("opacity", 0.0)
                .attr("fill", "lightgray")
                .attr("x", leftPos)
                .attr("y", function(d, i) {
                  return (i+1) * BOXHEIGHT;
                })
                .attr("width", BOXWIDTH)
                .attr("height", BOXHEIGHT);

  var textEl = tokenContainer.append("text")
                              .text(function(d) { return d; })
                              .attr("font-size", TEXT_SIZE + "px")
                              .style("cursor", "default")
                              .style("-webkit-user-select", "none")
                              .attr("x", leftPos)
                              .attr("y", function(d, i) {
                                return (i+1) * BOXHEIGHT;
                              });

  if (isLeft) {
    textEl.style("text-anchor", "end")
           .attr("dx", BOXWIDTH - TEXT_SIZE)
           .attr("dy", TEXT_SIZE);
  } else {
    textEl.style("text-anchor", "start")
           .attr("dx", + TEXT_SIZE)
           .attr("dy", TEXT_SIZE);
  }

  tokenContainer.on("mouseover", function(d, index) {
    textContainer.selectAll(".background")
                 .style("opacity", function(d, i) {
                   return i == index ? 1.0 : 0.0;
                 });

    svg.selectAll(".attentionHeads").style("display", "none");

    svg.selectAll(".lineHeads")  // To get the nesting to work.
       .selectAll(".attLines")
       .attr("stroke-opacity", function(d) {
          return 1.0;
        })
       .attr("y1", function(d, i) {
        if (isLeft) {
          return (index+1) * BOXHEIGHT + (BOXHEIGHT/2);
        } else {
          return (i+1) * BOXHEIGHT + (BOXHEIGHT/2);
        }
     })
     .attr("x1", BOXWIDTH)
     .attr("y2", function(d, i) {
       if (isLeft) {
          return (i+1) * BOXHEIGHT + (BOXHEIGHT/2);
        } else {
          return (index+1) * BOXHEIGHT + (BOXHEIGHT/2);
        }
     })
     .attr("x2", BOXWIDTH + MATRIX_WIDTH)
     .attr("stroke-width", 2)
     .attr("stroke", function(d, i, j) {
        return HEAD_COLORS(j);
      })
     .attr("stroke-opacity", function(d, i, j) {
      if (isLeft) {d = d[0];} else {d = d[1];}
      if (config.headVis[j]) {
        if (d) {
          return d[index];
        } else {
          return 0.0;
        }
      } else {
        return 0.0;
      }
     });

    function updateAttentionBoxes() {
      var id = isLeft ? "right" : "left";
      var leftPos = isLeft ? MATRIX_WIDTH + BOXWIDTH : 0;
      svg.select("#" + id)
         .selectAll(".attentionBoxes")
         .selectAll("g")
         .selectAll("rect")
         .attr("x", function(d, i, j) { return leftPos + boxOffsets(j); })
         .attr("y", function(d, i) { return (i+1) * BOXHEIGHT; })
         .attr("width", BOXWIDTH/activeHeads())
         .attr("height", function() { return BOXHEIGHT; })
         .style("opacity", function(d, i, j) {
            if (isLeft) {d = d[0];} else {d = d[1];}
            if (config.headVis[j])
              if (d) {
                return d[index];
              } else {
                return 0.0;
              }
            else
              return 0.0;
         });
    }

    updateAttentionBoxes();
  });

  textContainer.on("mouseleave", function() {
    d3.select(this).selectAll(".background")
                   .style("opacity", 0.0);
    svg.selectAll(".attLines").attr("stroke-opacity", 0.0);
    svg.selectAll(".attentionHeads").style("display", "inline");
    svg.selectAll(".attentionBoxes")
       .selectAll("g")
       .selectAll("rect")
       .style("opacity", 0.0);
  });
}

function renderAttentionHighlights(svg, attention) {
  var line_container = svg.append("g");
  line_container.selectAll("g")
                .data(attention)
                .enter()
                .append("g")
                .classed("lineHeads", true)
                .selectAll("line")
                .data(function(d){return d;})
                .enter()
                .append("line").classed("attLines", true);
}

function renderAttention(svg, attentionHeads) {
  var line_container = svg.selectAll(".attentionHeads");
  line_container.html(null);
  for(var h=0; h<attentionHeads.length; h++) {
    for(var s=0; s<attentionHeads[h].length; s++) {
      for(var a=0; a<attentionHeads[h][s].length; a++) {
        line_container.append("line")
        .attr("y1", (s+1) * BOXHEIGHT + (BOXHEIGHT/2))
        .attr("x1", BOXWIDTH)
        .attr("y2", (a+1) * BOXHEIGHT + (BOXHEIGHT/2))
        .attr("x2", BOXWIDTH + MATRIX_WIDTH)
        .attr("stroke-width", 2)
        .attr("stroke", HEAD_COLORS(h))
        .attr("stroke-opacity", function() {
          if (config.headVis[h]) {
            return attentionHeads[h][s][a]/activeHeads();
          } else {
            return 0.0;
          }
        }());
      }
    }
  }
}

// Checkboxes
function boxOffsets(i) {
  var numHeadsAbove = config.headVis.reduce(
      function(acc, val, cur) {return val && cur < i ? acc + 1: acc;}, 0);
  return numHeadsAbove * (BOXWIDTH / activeHeads());
}

function activeHeads() {
  return config.headVis.reduce(function(acc, val) {
    return val ? acc + 1: acc;
  }, 0);
}

function drawCheckboxes(top, svg, attentionHeads) {
  var checkboxContainer = svg.append("g");
  var checkbox = checkboxContainer.selectAll("rect")
                                  .data(config.headVis)
                                  .enter()
                                  .append("rect")
                                  .attr("fill", function(d, i) {
                                    return HEAD_COLORS(i);
                                  })
                                  .attr("x", function(d, i) {
                                    return (i+1) * CHECKBOX_SIZE;
                                  })
                                  .attr("y", top)
                                  .attr("width", CHECKBOX_SIZE)
                                  .attr("height", CHECKBOX_SIZE);

  function updateCheckboxes() {
    checkboxContainer.selectAll("rect")
                              .data(config.headVis)
                              .attr("fill", function(d, i) {
      var headColor = HEAD_COLORS(i);
      var color = d ? headColor : lighten(headColor);
      return color;
    });
  }

  updateCheckboxes();

  checkbox.on("click", function(d, i) {
    if (config.headVis[i] && activeHeads() == 1) return;
    config.headVis[i] = !config.headVis[i];
    updateCheckboxes();
    renderAttention(svg, attentionHeads);
  });

  checkbox.on("dblclick", function(d, i) {
    // If we double click on the only active head then reset
    if (config.headVis[i] && activeHeads() == 1) {
      config.headVis = new Array(config.nHeads).fill(true);
    } else {
      config.headVis = new Array(config.nHeads).fill(false);
      config.headVis[i] = true;
    }
    updateCheckboxes();
    renderAttention(svg, attentionHeads);
  });
}

function initialize() {
  config.attention = params['attention'];
  config.filter = params['default_filter'];
  config.nHeads = config.attention[config.filter]['attn'][0].length;
  config.headVis  = new Array(config.nHeads).fill(true);
  config.layer = 0;
  config.initialTextLength = config.attention[config.filter].right_text.length
}

$("#layer").empty();
for(var i=0; i<12; i++) {
  $("#layer").append($("<option />").val(i).text(i));
}

$("#layer").on('change', function(e) {
  config.layer = +e.currentTarget.value;
  render();
});

$("#filter").on('change', function(e) {
  config.filter = e.currentTarget.value;
  render();
});

initialize();
render();

});<commit_msg>Support models with more than 12 layers in attention-head view.<commit_after>/**
 * @fileoverview Transformer Visualization D3 javascript code.
 *
 *

 *  Based on: https://github.com/tensorflow/tensor2tensor/blob/master/tensor2tensor/visualization/attention.js
 *
 * Change log:
 *
 * 12/19/18  Jesse Vig   Assorted cleanup. Changed orientation of attention matrices.
 */

requirejs(['jquery', 'd3'], function($, d3) {

const TEXT_SIZE = 15;
const BOXWIDTH = TEXT_SIZE * 8;
const BOXHEIGHT = TEXT_SIZE * 1.5;
const WIDTH = 2000;
const HEIGHT_PADDING = 100;
const MATRIX_WIDTH = 150;
const HEAD_COLORS = d3.scale.category10();
const CHECKBOX_SIZE = 20;

var params = window.params;
var config = {};
initialize();

function lighten(color) {
  var c = d3.hsl(color);
  var increment = (1 - c.l) * 0.6;
  c.l += increment;
  c.s -= increment;
  return c;
}

function transpose(mat) {
  return mat[0].map(function(col, i) {
    return mat.map(function(row) {
      return row[i];
    });
  });
}

function zip(a, b) {
  return a.map(function (e, i) {
    return [e, b[i]];
  });
}

function render() {

  var attnData = config.attention[config.filter];
  var leftText = attnData.left_text;
  var rightText = attnData.right_text;
  var attentionHeads = attnData.attn[config.layer];

  $("#vis svg").empty();
  $("#vis").empty();

  var height = config.initialTextLength * BOXHEIGHT * 2 + HEIGHT_PADDING;
  var svg = d3.select("#vis")
            .append('svg')
            .attr("width", WIDTH)
            .attr("height", height);

  var attData = [];
  for (var i=0; i < config.nHeads; i++) {
    var att = attentionHeads[i];
    var att_trans = transpose(att);
    attData.push(zip(att_trans, att));
  }

  renderText(svg, leftText, true, attData, 0);
  renderText(svg, rightText, false, attData, MATRIX_WIDTH + BOXWIDTH);

  renderAttentionHighlights(svg, attData);

  svg.append("g").classed("attentionHeads", true);

  renderAttention(svg, attentionHeads);

  drawCheckboxes(0, svg, attentionHeads);

}

function renderText(svg, text, isLeft, attData, leftPos) {
  // attData: list of tuples (att, att_trans), one for each layer. att and att_trans are attention matrics for each layer.
  //           att is of shape [nHeads, source_len, target_len)
  var id = isLeft ? "left" : "right";
  var textContainer = svg.append("svg:g")
                         .attr("id", id);

  textContainer.append("g").classed("attentionBoxes", true)
               .selectAll("g")
               .data(attData)
               .enter()
               .append("g")
               .selectAll("rect")
               .data(function(d) {return d;})
               .enter()
               .append("rect")
               .attr("x", function(d, i, j) {
                 return leftPos + boxOffsets(j);
               })
               .attr("y", function(d, i) {
                 return (+1) * BOXHEIGHT;
               })
               .attr("width", BOXWIDTH / activeHeads())
               .attr("height", function() { return BOXHEIGHT; })
               .attr("fill", function(d, i, j) {
                  return HEAD_COLORS(j);
                })
               .style("opacity", 0.0);

  var tokenContainer = textContainer.append("g").selectAll("g")
                                    .data(text)
                                    .enter()
                                    .append("g");

  tokenContainer.append("rect")
                .classed("background", true)
                .style("opacity", 0.0)
                .attr("fill", "lightgray")
                .attr("x", leftPos)
                .attr("y", function(d, i) {
                  return (i+1) * BOXHEIGHT;
                })
                .attr("width", BOXWIDTH)
                .attr("height", BOXHEIGHT);

  var textEl = tokenContainer.append("text")
                              .text(function(d) { return d; })
                              .attr("font-size", TEXT_SIZE + "px")
                              .style("cursor", "default")
                              .style("-webkit-user-select", "none")
                              .attr("x", leftPos)
                              .attr("y", function(d, i) {
                                return (i+1) * BOXHEIGHT;
                              });

  if (isLeft) {
    textEl.style("text-anchor", "end")
           .attr("dx", BOXWIDTH - TEXT_SIZE)
           .attr("dy", TEXT_SIZE);
  } else {
    textEl.style("text-anchor", "start")
           .attr("dx", + TEXT_SIZE)
           .attr("dy", TEXT_SIZE);
  }

  tokenContainer.on("mouseover", function(d, index) {
    textContainer.selectAll(".background")
                 .style("opacity", function(d, i) {
                   return i == index ? 1.0 : 0.0;
                 });

    svg.selectAll(".attentionHeads").style("display", "none");

    svg.selectAll(".lineHeads")  // To get the nesting to work.
       .selectAll(".attLines")
       .attr("stroke-opacity", function(d) {
          return 1.0;
        })
       .attr("y1", function(d, i) {
        if (isLeft) {
          return (index+1) * BOXHEIGHT + (BOXHEIGHT/2);
        } else {
          return (i+1) * BOXHEIGHT + (BOXHEIGHT/2);
        }
     })
     .attr("x1", BOXWIDTH)
     .attr("y2", function(d, i) {
       if (isLeft) {
          return (i+1) * BOXHEIGHT + (BOXHEIGHT/2);
        } else {
          return (index+1) * BOXHEIGHT + (BOXHEIGHT/2);
        }
     })
     .attr("x2", BOXWIDTH + MATRIX_WIDTH)
     .attr("stroke-width", 2)
     .attr("stroke", function(d, i, j) {
        return HEAD_COLORS(j);
      })
     .attr("stroke-opacity", function(d, i, j) {
      if (isLeft) {d = d[0];} else {d = d[1];}
      if (config.headVis[j]) {
        if (d) {
          return d[index];
        } else {
          return 0.0;
        }
      } else {
        return 0.0;
      }
     });

    function updateAttentionBoxes() {
      var id = isLeft ? "right" : "left";
      var leftPos = isLeft ? MATRIX_WIDTH + BOXWIDTH : 0;
      svg.select("#" + id)
         .selectAll(".attentionBoxes")
         .selectAll("g")
         .selectAll("rect")
         .attr("x", function(d, i, j) { return leftPos + boxOffsets(j); })
         .attr("y", function(d, i) { return (i+1) * BOXHEIGHT; })
         .attr("width", BOXWIDTH/activeHeads())
         .attr("height", function() { return BOXHEIGHT; })
         .style("opacity", function(d, i, j) {
            if (isLeft) {d = d[0];} else {d = d[1];}
            if (config.headVis[j])
              if (d) {
                return d[index];
              } else {
                return 0.0;
              }
            else
              return 0.0;
         });
    }

    updateAttentionBoxes();
  });

  textContainer.on("mouseleave", function() {
    d3.select(this).selectAll(".background")
                   .style("opacity", 0.0);
    svg.selectAll(".attLines").attr("stroke-opacity", 0.0);
    svg.selectAll(".attentionHeads").style("display", "inline");
    svg.selectAll(".attentionBoxes")
       .selectAll("g")
       .selectAll("rect")
       .style("opacity", 0.0);
  });
}

function renderAttentionHighlights(svg, attention) {
  var line_container = svg.append("g");
  line_container.selectAll("g")
                .data(attention)
                .enter()
                .append("g")
                .classed("lineHeads", true)
                .selectAll("line")
                .data(function(d){return d;})
                .enter()
                .append("line").classed("attLines", true);
}

function renderAttention(svg, attentionHeads) {
  var line_container = svg.selectAll(".attentionHeads");
  line_container.html(null);
  for(var h=0; h<attentionHeads.length; h++) {
    for(var s=0; s<attentionHeads[h].length; s++) {
      for(var a=0; a<attentionHeads[h][s].length; a++) {
        line_container.append("line")
        .attr("y1", (s+1) * BOXHEIGHT + (BOXHEIGHT/2))
        .attr("x1", BOXWIDTH)
        .attr("y2", (a+1) * BOXHEIGHT + (BOXHEIGHT/2))
        .attr("x2", BOXWIDTH + MATRIX_WIDTH)
        .attr("stroke-width", 2)
        .attr("stroke", HEAD_COLORS(h))
        .attr("stroke-opacity", function() {
          if (config.headVis[h]) {
            return attentionHeads[h][s][a]/activeHeads();
          } else {
            return 0.0;
          }
        }());
      }
    }
  }
}

// Checkboxes
function boxOffsets(i) {
  var numHeadsAbove = config.headVis.reduce(
      function(acc, val, cur) {return val && cur < i ? acc + 1: acc;}, 0);
  return numHeadsAbove * (BOXWIDTH / activeHeads());
}

function activeHeads() {
  return config.headVis.reduce(function(acc, val) {
    return val ? acc + 1: acc;
  }, 0);
}

function drawCheckboxes(top, svg, attentionHeads) {
  var checkboxContainer = svg.append("g");
  var checkbox = checkboxContainer.selectAll("rect")
                                  .data(config.headVis)
                                  .enter()
                                  .append("rect")
                                  .attr("fill", function(d, i) {
                                    return HEAD_COLORS(i);
                                  })
                                  .attr("x", function(d, i) {
                                    return (i+1) * CHECKBOX_SIZE;
                                  })
                                  .attr("y", top)
                                  .attr("width", CHECKBOX_SIZE)
                                  .attr("height", CHECKBOX_SIZE);

  function updateCheckboxes() {
    checkboxContainer.selectAll("rect")
                              .data(config.headVis)
                              .attr("fill", function(d, i) {
      var headColor = HEAD_COLORS(i);
      var color = d ? headColor : lighten(headColor);
      return color;
    });
  }

  updateCheckboxes();

  checkbox.on("click", function(d, i) {
    if (config.headVis[i] && activeHeads() == 1) return;
    config.headVis[i] = !config.headVis[i];
    updateCheckboxes();
    renderAttention(svg, attentionHeads);
  });

  checkbox.on("dblclick", function(d, i) {
    // If we double click on the only active head then reset
    if (config.headVis[i] && activeHeads() == 1) {
      config.headVis = new Array(config.nHeads).fill(true);
    } else {
      config.headVis = new Array(config.nHeads).fill(false);
      config.headVis[i] = true;
    }
    updateCheckboxes();
    renderAttention(svg, attentionHeads);
  });
}

function initialize() {
  config.attention = params['attention'];
  config.filter = params['default_filter'];
  config.nLayers = config.attention[config.filter]['attn'].length;
  console.log('num layers')
  console.log(config.nLayers)
  config.nHeads = config.attention[config.filter]['attn'][0].length;
  config.headVis  = new Array(config.nHeads).fill(true);
  config.layer = 0;
  config.initialTextLength = config.attention[config.filter].right_text.length
}

$("#layer").empty();
for(var i=0; i<config.nLayers; i++) {
  $("#layer").append($("<option />").val(i).text(i));
}

$("#layer").on('change', function(e) {
  config.layer = +e.currentTarget.value;
  render();
});

$("#filter").on('change', function(e) {
  config.filter = e.currentTarget.value;
  render();
});

render();

});<|endoftext|>


<commit_before>'use strict';

describe("bicyclesController", function () {

    beforeEach(module('myApp'));

    it('should be defined', inject(function ($controller) {
        var bicyclesController = $controller('BicyclesController', { $scope: {} });
        expect(bicyclesController).toBeDefined();
    }));

    it('should have 2 bicycles', inject(function ($httpBackend, $controller) {
        $httpBackend.expectGET('api/bicycles')
              .respond([{
                  id: 1,
                  name: 'testBicycle1'
              },
              {
                  id: 2,
                  name: 'testBicycle2'
              }]);

        var $scope = {};
        $controller('BicyclesController', { $scope: $scope });

        $httpBackend.flush();

        expect($scope.bicycles).toBeDefined();
        expect($scope.bicycles.length).toEqual(2);
        expect($scope.bicycles[1].name).toEqual("testBicycle2");
    }));
});<commit_msg>Chapter5 Example2: added verify expectations check<commit_after>'use strict';

describe("bicyclesController", function () {

    beforeEach(module('myApp'));

    it('should be defined', inject(function ($controller) {
        var bicyclesController = $controller('BicyclesController', { $scope: {} });
        expect(bicyclesController).toBeDefined();
    }));

    it('should have 2 bicycles', inject(function ($httpBackend, $controller) {
        $httpBackend.expectGET('api/bicycles')
              .respond([{ id: 1, name: 'testBicycle1' },
                        { id: 2, name: 'testBicycle2' }]);

        var $scope = {};
        $controller('BicyclesController', { $scope: $scope });

        $httpBackend.flush();

        expect($scope.bicycles).toBeDefined();
        expect($scope.bicycles.length).toEqual(2);
        expect($scope.bicycles[1].name).toEqual("testBicycle2");

        $httpBackend.verifyNoOutstandingExpectation();
        $httpBackend.verifyNoOutstandingRequest();
    }));
});<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 Glyptodon LLC
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/**
 * A directive which displays the contents of a filesystem received through the
 * Guacamole client.
 */
angular.module('client').directive('guacFileBrowser', [function guacFileBrowser() {

    return {
        restrict: 'E',
        replace: true,
        scope: {

            /**
             * The client whose file transfers should be managed by this
             * directive.
             *
             * @type ManagedClient
             */
            client : '=',

            /**
             * @type ManagedFilesystem
             */
            filesystem : '='

        },

        templateUrl: 'app/client/templates/guacFileBrowser.html',
        controller: ['$scope', '$element', '$injector', function guacFileBrowserController($scope, $element, $injector) {

            // Required types
            var ManagedFilesystem = $injector.get('ManagedFilesystem');

            // Required services
            var $interpolate     = $injector.get('$interpolate');
            var $templateRequest = $injector.get('$templateRequest');

            /**
             * The jQuery-wrapped element representing the contents of the
             * current directory within the file browser.
             *
             * @type Element[]
             */
            var currentDirectoryContents = $element.find('.current-directory-contents');

            /**
             * Statically-cached template HTML used to render each file within
             * a directory. Once available, this will be used through
             * createFileElement() to generate the DOM elements which make up
             * a directory listing.
             *
             * @type String
             */
            var fileTemplate = null;

            /**
             * Returns whether the given file is a normal file.
             *
             * @param {ManagedFilesystem.File} file
             *     The file to test.
             *
             * @returns {Boolean}
             *     true if the given file is a normal file, false otherwise.
             */
            $scope.isNormalFile = function isNormalFile(file) {
                return file.type === ManagedFilesystem.File.Type.NORMAL;
            };

            /**
             * Returns whether the given file is a directory.
             *
             * @param {ManagedFilesystem.File} file
             *     The file to test.
             *
             * @returns {Boolean}
             *     true if the given file is a directory, false otherwise.
             */
            $scope.isDirectory = function isDirectory(file) {
                return file.type === ManagedFilesystem.File.Type.DIRECTORY;
            };

            /**
             * Changes the currently-displayed directory to the given
             * directory.
             *
             * @param {ManagedFilesystem.File} file
             *     The directory to change to.
             */
            $scope.changeDirectory = function changeDirectory(file) {
                ManagedFilesystem.changeDirectory($scope.filesystem, file);
            };

            /**
             * Initiates a download of the given file. The progress of the
             * download can be observed through guacFileTransferManager.
             *
             * @param {ManagedFilesystem.File} file
             *     The file to download.
             */
            $scope.downloadFile = function downloadFile(file) {
                ManagedFilesystem.downloadFile($scope.client, $scope.filesystem, file.streamName);
            };

            /**
             * Creates a new element representing the given file and properly
             * handling user events, bypassing the overhead incurred through
             * use of ngRepeat and related techniques.
             *
             * Note that this function depends on the availability of the
             * statically-cached fileTemplate.
             *
             * @param {ManagedFilesystem.File} file
             *     The file to generate an element for.
             *
             * @returns {Element[]}
             *     A jQuery-wrapped array containing a single DOM element
             *     representing the given file.
             */
            var createFileElement = function createFileElement(file) {

                // Create from internal template
                var element = angular.element($interpolate(fileTemplate)(file));

                // Double-clicking on unknown file types will do nothing
                var fileAction = function doNothing() {};

                // Change current directory when directories are clicked
                if ($scope.isDirectory(file)) {
                    element.addClass('directory');
                    fileAction = function changeDirectory() {
                        $scope.changeDirectory(file);
                    };
                }

                // Initiate downloads when normal files are clicked
                else if ($scope.isNormalFile(file)) {
                    element.addClass('normal-file');
                    fileAction = function downloadFile() {
                        $scope.downloadFile(file);
                    };
                }

                // Mark file as focused upon click
                element.on('click', function handleFileClick() {

                    // Fire file-specific action if already focused
                    if (element.hasClass('focused')) {
                        fileAction();
                        element.removeClass('focused');
                    }

                    // Otherwise mark as focused
                    else {
                        element.parent().children().removeClass('focused');
                        element.addClass('focused');
                    }

                });

                // Prevent text selection during navigation
                element.on('selectstart', function avoidSelect(e) {
                    e.preventDefault();
                    e.stopPropagation();
                });

                return element;

            };

            /**
             * Sorts the given map of files, returning an array of those files
             * grouped by file type (directories first, followed by non-
             * directories) and sorted lexicographically.
             *
             * @param {Object.<String, ManagedFilesystem.File>} files
             *     The map of files to sort.
             *
             * @returns {ManagedFilesystem.File[]}
             *     An array of all files in the given map, sorted
             *     lexicographically with directories first, followed by non-
             *     directories.
             */
            var sortFiles = function sortFiles(files) {

                // Get all given files as an array
                var unsortedFiles = [];
                for (var name in files)
                    unsortedFiles.push(files[name]);

                // Sort files - directories first, followed by all other files
                // sorted by name
                return unsortedFiles.sort(function fileComparator(a, b) {

                    // Directories come before non-directories
                    if ($scope.isDirectory(a) && !$scope.isDirectory(b))
                        return -1;

                    // Non-directories come after directories
                    if (!$scope.isDirectory(a) && $scope.isDirectory(b))
                        return 1;

                    // All other combinations are sorted by name
                    return a.name.localeCompare(b.name);

                });

            };

            // Watch directory contents once file template is available
            $templateRequest('app/client/templates/file.html').then(function fileTemplateRetrieved(html) {

                // Store file template statically
                fileTemplate = html;

                // Update the contents of the file browser whenever the current directory (or its contents) changes
                $scope.$watch('filesystem.currentDirectory.files', function currentDirectoryChanged(files) {

                    // Clear current content
                    currentDirectoryContents.html('');

                    // Display all files within current directory, sorted
                    angular.forEach(sortFiles(files), function displayFile(file) {
                        currentDirectoryContents.append(createFileElement(file));
                    });

                });

            }); // end retrieve file template

            // Refresh file browser when any upload completes
            $scope.$on('guacUploadComplete', function uploadComplete(event, filename) {

                // Refresh filesystem, if it exists
                if ($scope.filesystem)
                    ManagedFilesystem.refresh($scope.filesystem, $scope.filesystem.currentDirectory);

            });

        }]

    };
}]);
<commit_msg>GUAC-1465: Cherry-pick changes from 7da1312 for 0.9.9 re-release.<commit_after>/*
 * Copyright (C) 2015 Glyptodon LLC
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/**
 * A directive which displays the contents of a filesystem received through the
 * Guacamole client.
 */
angular.module('client').directive('guacFileBrowser', [function guacFileBrowser() {

    return {
        restrict: 'E',
        replace: true,
        scope: {

            /**
             * The client whose file transfers should be managed by this
             * directive.
             *
             * @type ManagedClient
             */
            client : '=',

            /**
             * @type ManagedFilesystem
             */
            filesystem : '='

        },

        templateUrl: 'app/client/templates/guacFileBrowser.html',
        controller: ['$scope', '$element', '$injector', function guacFileBrowserController($scope, $element, $injector) {

            // Required types
            var ManagedFilesystem = $injector.get('ManagedFilesystem');

            // Required services
            var $interpolate     = $injector.get('$interpolate');
            var $templateRequest = $injector.get('$templateRequest');

            /**
             * The jQuery-wrapped element representing the contents of the
             * current directory within the file browser.
             *
             * @type Element[]
             */
            var currentDirectoryContents = $element.find('.current-directory-contents');

            /**
             * Statically-cached template HTML used to render each file within
             * a directory. Once available, this will be used through
             * createFileElement() to generate the DOM elements which make up
             * a directory listing.
             *
             * @type String
             */
            var fileTemplate = null;

            /**
             * Returns whether the given file is a normal file.
             *
             * @param {ManagedFilesystem.File} file
             *     The file to test.
             *
             * @returns {Boolean}
             *     true if the given file is a normal file, false otherwise.
             */
            $scope.isNormalFile = function isNormalFile(file) {
                return file.type === ManagedFilesystem.File.Type.NORMAL;
            };

            /**
             * Returns whether the given file is a directory.
             *
             * @param {ManagedFilesystem.File} file
             *     The file to test.
             *
             * @returns {Boolean}
             *     true if the given file is a directory, false otherwise.
             */
            $scope.isDirectory = function isDirectory(file) {
                return file.type === ManagedFilesystem.File.Type.DIRECTORY;
            };

            /**
             * Changes the currently-displayed directory to the given
             * directory.
             *
             * @param {ManagedFilesystem.File} file
             *     The directory to change to.
             */
            $scope.changeDirectory = function changeDirectory(file) {
                ManagedFilesystem.changeDirectory($scope.filesystem, file);
            };

            /**
             * Initiates a download of the given file. The progress of the
             * download can be observed through guacFileTransferManager.
             *
             * @param {ManagedFilesystem.File} file
             *     The file to download.
             */
            $scope.downloadFile = function downloadFile(file) {
                ManagedFilesystem.downloadFile($scope.client, $scope.filesystem, file.streamName);
            };

            /**
             * Recursively interpolates all text nodes within the DOM tree of
             * the given element. All other node types, attributes, etc. will
             * be left uninterpolated.
             *
             * @param {Element} element
             *     The element at the root of the DOM tree to be interpolated.
             *
             * @param {Object} context
             *     The evaluation context to use when evaluating expressions
             *     embedded in text nodes within the provided element.
             */
            var interpolateElement = function interpolateElement(element, context) {

                // Interpolate the contents of text nodes directly
                if (element.nodeType === Node.TEXT_NODE)
                    element.nodeValue = $interpolate(element.nodeValue)(context);

                // Recursively interpolate the contents of all descendant text
                // nodes
                if (element.hasChildNodes()) {
                    var children = element.childNodes;
                    for (var i = 0; i < children.length; i++)
                        interpolateElement(children[i], context);
                }

            };

            /**
             * Creates a new element representing the given file and properly
             * handling user events, bypassing the overhead incurred through
             * use of ngRepeat and related techniques.
             *
             * Note that this function depends on the availability of the
             * statically-cached fileTemplate.
             *
             * @param {ManagedFilesystem.File} file
             *     The file to generate an element for.
             *
             * @returns {Element[]}
             *     A jQuery-wrapped array containing a single DOM element
             *     representing the given file.
             */
            var createFileElement = function createFileElement(file) {

                // Create from internal template
                var element = angular.element(fileTemplate);
                interpolateElement(element[0], file);

                // Double-clicking on unknown file types will do nothing
                var fileAction = function doNothing() {};

                // Change current directory when directories are clicked
                if ($scope.isDirectory(file)) {
                    element.addClass('directory');
                    fileAction = function changeDirectory() {
                        $scope.changeDirectory(file);
                    };
                }

                // Initiate downloads when normal files are clicked
                else if ($scope.isNormalFile(file)) {
                    element.addClass('normal-file');
                    fileAction = function downloadFile() {
                        $scope.downloadFile(file);
                    };
                }

                // Mark file as focused upon click
                element.on('click', function handleFileClick() {

                    // Fire file-specific action if already focused
                    if (element.hasClass('focused')) {
                        fileAction();
                        element.removeClass('focused');
                    }

                    // Otherwise mark as focused
                    else {
                        element.parent().children().removeClass('focused');
                        element.addClass('focused');
                    }

                });

                // Prevent text selection during navigation
                element.on('selectstart', function avoidSelect(e) {
                    e.preventDefault();
                    e.stopPropagation();
                });

                return element;

            };

            /**
             * Sorts the given map of files, returning an array of those files
             * grouped by file type (directories first, followed by non-
             * directories) and sorted lexicographically.
             *
             * @param {Object.<String, ManagedFilesystem.File>} files
             *     The map of files to sort.
             *
             * @returns {ManagedFilesystem.File[]}
             *     An array of all files in the given map, sorted
             *     lexicographically with directories first, followed by non-
             *     directories.
             */
            var sortFiles = function sortFiles(files) {

                // Get all given files as an array
                var unsortedFiles = [];
                for (var name in files)
                    unsortedFiles.push(files[name]);

                // Sort files - directories first, followed by all other files
                // sorted by name
                return unsortedFiles.sort(function fileComparator(a, b) {

                    // Directories come before non-directories
                    if ($scope.isDirectory(a) && !$scope.isDirectory(b))
                        return -1;

                    // Non-directories come after directories
                    if (!$scope.isDirectory(a) && $scope.isDirectory(b))
                        return 1;

                    // All other combinations are sorted by name
                    return a.name.localeCompare(b.name);

                });

            };

            // Watch directory contents once file template is available
            $templateRequest('app/client/templates/file.html').then(function fileTemplateRetrieved(html) {

                // Store file template statically
                fileTemplate = html;

                // Update the contents of the file browser whenever the current directory (or its contents) changes
                $scope.$watch('filesystem.currentDirectory.files', function currentDirectoryChanged(files) {

                    // Clear current content
                    currentDirectoryContents.html('');

                    // Display all files within current directory, sorted
                    angular.forEach(sortFiles(files), function displayFile(file) {
                        currentDirectoryContents.append(createFileElement(file));
                    });

                });

            }); // end retrieve file template

            // Refresh file browser when any upload completes
            $scope.$on('guacUploadComplete', function uploadComplete(event, filename) {

                // Refresh filesystem, if it exists
                if ($scope.filesystem)
                    ManagedFilesystem.refresh($scope.filesystem, $scope.filesystem.currentDirectory);

            });

        }]

    };
}]);
<|endoftext|>


<commit_before>(function() {
  'use strict';
  /**
   *  @ngdoc overview
   *  @name ui.grid.autoResize
   *
   *  @description
   *
   *  #ui.grid.autoResize
   *
   *
Beta This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.

   *
   *  This module provides auto-resizing functionality to UI-Grid.
   */
  var module = angular.module('ui.grid.autoResize', ['ui.grid']);

  module.directive('uiGridAutoResize', ['gridUtil', function(gridUtil) {
    return {
      require: 'uiGrid',
      scope: false,
      link: function($scope, $elm, $attrs, uiGridCtrl) {

        $scope.$watch(function() {
          return $elm[0].clientWidth;
        }, function(newVal, oldVal) {
          if (newVal !== oldVal) {
            uiGridCtrl.grid.gridWidth = newVal;
            uiGridCtrl.grid.refresh();
          }
        });

        $scope.$watch(function() {
          return $elm[0].clientHeight;
        }, function(newVal, oldVal) {
          if (newVal !== oldVal) {
            uiGridCtrl.grid.gridHeight = newVal;
            uiGridCtrl.grid.refresh();
          }
        });

      }
    };
  }]);
})();
<commit_msg>fix(uiGridAutoResize): Changed [0].clientHeight to gridUtil.elementHe… (#6490)<commit_after>(function() {
  'use strict';
  /**
   *  @ngdoc overview
   *  @name ui.grid.autoResize
   *
   *  @description
   *
   *  #ui.grid.autoResize
   *
   *
Beta This feature is ready for testing, but it either hasn't seen a lot of use or has some known bugs.

   *
   *  This module provides auto-resizing functionality to UI-Grid.
   */
  var module = angular.module('ui.grid.autoResize', ['ui.grid']);

  module.directive('uiGridAutoResize', ['gridUtil', function(gridUtil) {
    return {
      require: 'uiGrid',
      scope: false,
      link: function($scope, $elm, $attrs, uiGridCtrl) {
        var timeout = null;

        var debounce = function(width, height) {
          if (timeout !== null) {
            clearTimeout(timeout);
          }
          timeout = setTimeout(function() {
            uiGridCtrl.grid.gridWidth = width;
            uiGridCtrl.grid.gridHeight = height;
            uiGridCtrl.grid.refresh();
            timeout = null;
          }, 400);
        };

        $scope.$watchGroup([
          function() {
            return gridUtil.elementWidth($elm);
          },
          function() {
            return gridUtil.elementHeight($elm);
          }
        ], function(newValues, oldValues, scope) {
          if (!angular.equals(newValues, oldValues)) {
            debounce(newValues[0], newValues[1]);
          }
        });
      }
    };
  }]);
})();
<|endoftext|>


<commit_before>/* eslint-disable */
import { storiesOf } from "@kadira/storybook";
import withReadme from "storybook-readme/with-readme";
import backgrounds from "react-storybook-addon-backgrounds";
import centered from "/.storybook/decorators/centered";
import defaultColors from "/.storybook/defaults";

import ProgressBar from "../";
import Readme from "./progress.md";

const story = storiesOf("ProgressBar", module)
  .addDecorator(centered)
  .addDecorator(backgrounds(defaultColors()))
  ;

story
  .add("Light", withReadme(
    Readme,
    () => (
      <ProgressBar
        title="My Fund"
        total="1000"
        percentDone="35"
        theme="light"
      />
    )
  ))
  .add("Dark", withReadme(
    Readme,
    () => (
      <ProgressBar
        title="My Fund"
        total="1000"
        percentDone="35"
      />
    )
  ));
<commit_msg>fixed progress story<commit_after>/* eslint-disable */
import { storiesOf } from "@kadira/storybook";
import withReadme from "storybook-readme/with-readme";
import backgrounds from "react-storybook-addon-backgrounds";
import centered from "/.storybook/decorators/centered";
import defaultColors from "/.storybook/defaults";

import { Progress as ProgressBar } from "../";
import Readme from "./progress.md";

const story = storiesOf("ProgressBar", module)
  .addDecorator(centered)
  .addDecorator(backgrounds(defaultColors()))
  ;

story
  .add("Light", withReadme(
    Readme,
    () => (
      <ProgressBar
        title="My Fund"
        total="1000"
        percentDone="35"
        theme="light"
      />
    )
  ))
  .add("Dark", withReadme(
    Readme,
    () => (
      <ProgressBar
        title="My Fund"
        total="1000"
        percentDone="35"
      />
    )
  ));
<|endoftext|>


<commit_before>/**
 * Created by huanli<klx211@gmail.com> on 1/6/15.
 *
 * Variable prefixes' meanings:
 * -------------------------------------------------------------------------
 * --- The prefix of a variable's name reveals the type of data it holds ---
 * -------------------------------------------------------------------------
 *
 * a: Array
 * b: Boolean
 * d: DOM
 * f: Function
 * l: List(an array-like object)
 * n: Number
 * o: Object
 * r: Regular expression
 * s: String
 * x: More than one type
 *  : Special case or NOT my code
 *
 * *** These prefixes can be concatenated to indicate that the variable can
 *         hold the specified types of data ***
 */

(function () {
    'use strict';

    /**
     * All the event subjects that will be emitted during the process of dragging.
     *
     * @author Kevin Li<huali@tibco-support.com>
     * @type {Object}
     */
    var kDraggableEvents = {
            DRAG_START: 'kDraggableDragStart',
            DRAG_END: 'kDraggableDragEnd'
        },
        /**
         * All the class name constants.
         *
         * @author Kevin Li<huali@tibco-support.com>
         * @type {Object}
         */
        kClassNames = {
            DRAGGABLE: 'k-draggable',
            DRAGGING: 'k-dragging',
            HANDLE: 'k-handle'
        };

    angular
        .module('kl.draggable', [])
        .constant('kDraggableEvents', kDraggableEvents)
        .constant('kClassNames', kClassNames)
        .directive('kDraggable', kDraggable);

    kDraggable.$inject = [
        'kDraggableEvents',
        'kClassNames',
        '$document'
    ];

    /**
     * Facotry function of the directive.
     *
     * @author Kevin Li<huali@tibco-support.com>
     * @param {Object} kDE An object containing all the event subjects that will be emitted during the process of
     * dragging.
     * @param {Object} kCN An object containing all the class name constants.
     * @param {jQuery} $document A jQuery wrapper for the browser's window.document object.
     * @returns {Object} The directive's definition object.
     */
    function kDraggable(kDE, kCN, $document) {

        return {
            link: function (scope, element, attrs) {

                attrs.$addClass(kCN.DRAGGABLE);

                var sSelector = attrs.kDraggable,
                    jqHandleElement;

                if (angular.isString(sSelector) && sSelector.length > 0) {

                    jqHandleElement = element.find(sSelector);
                    jqHandleElement.addClass(kCN.HANDLE);

                } else {

                    attrs.$addClass(kCN.HANDLE);
                }

                registerListeners(scope, element, jqHandleElement);
            },
            restrict: 'A',
            scope: {}
        };

        /**
         * Register all the necessary listeners for dragging an element.
         *
         * @author Kevin Li<huali@tibco-support.com>
         * @param {Object} oScope The directive's scope object.
         * @param {jQuery} jqDraggableElement The HTML element which is wrapped by jQuery and is to be dragged.
         * @param {jQuery} jqHE The HTML element which is wrapped by jQuery and is the handle for dragging.
         */
        function registerListeners(oScope, jqDraggableElement, jqHE) {

            jqHE = jqHE || jqDraggableElement;

            jqHE.on('mousedown', onMousedown);

            function onMousedown(oEvent) {

                /**
                 * The value of left property of the HTML element to be dragged when the mouse button is held down.
                 *
                 * @author Kevin Li<huali@tibco-support.com>
                 * @type {number}
                 */
                var nElementLeft = jqDraggableElement.position().left,
                    /**
                     * The value of top property of the HTML element to be dragged when the mouse button is held down.
                     *
                     * @author Kevin Li<huali@tibco-support.com>
                     * @type {number}
                     */
                    nElementTop = jqDraggableElement.position().top,
                    /**
                     * The X position of the mouse cursor when the mouse button is held down.
                     *
                     * @author Kevin Li<huali@tibco-support.com>
                     * @type {number}
                     */
                    nMouseX = oEvent.pageX,
                    /**
                     * The Y position of the mouse cursor when the mouse button is held down.
                     *
                     * @author Kevin Li<huali@tibco-support.com>
                     * @type {number}
                     */
                    nMouseY = oEvent.pageY,
                    /**
                     * A counter to tell whether it's the first time to move the mouse after the mouse button is held
                     * down.
                     *
                     * @author Kevin Li<huali@tibco-support.com>
                     * @type {number}
                     */
                    nCounter = 0;

                // Add box shadows so that it looks like the HTML element has just been lifted up.
                jqDraggableElement.addClass(kCN.DRAGGING);

                $document.on('mousemove', onMousemove);
                $document.on('mouseup', onMouseup);

                function onMousemove(oEvent) {

                    if (nCounter === 0) {

                        // This is the first move of the mouse after the mouse button is held down.
                        nCounter += 1;
                        oScope.$emit(kDE.DRAG_START);
                    }

                    jqDraggableElement.css({
                        left: nElementLeft + (oEvent.pageX - nMouseX),
                        top: nElementTop + (oEvent.pageY - nMouseY)
                    });
                }

                function onMouseup() {

                    $document.off('mousemove', onMousemove);
                    $document.off('mouseup', onMouseup);

                    // Remove the box shadows so that it looks like the HTML element has just been put down.
                    jqDraggableElement.removeClass(kCN.DRAGGING);

                    nCounter = 0; // Reset the counter when the mouse button is released.
                    oScope.$emit(kDE.DRAG_END);
                }
            }
        }
    }

}());<commit_msg>* Corrected the email address.<commit_after>/**
 * Created by huanli<klx211@gmail.com> on 1/6/15.
 *
 * Variable prefixes' meanings:
 * -------------------------------------------------------------------------
 * --- The prefix of a variable's name reveals the type of data it holds ---
 * -------------------------------------------------------------------------
 *
 * a: Array
 * b: Boolean
 * d: DOM
 * f: Function
 * l: List(an array-like object)
 * n: Number
 * o: Object
 * r: Regular expression
 * s: String
 * x: More than one type
 *  : Special case or NOT my code
 *
 * *** These prefixes can be concatenated to indicate that the variable can
 *         hold the specified types of data ***
 */

(function () {
    'use strict';

    /**
     * All the event subjects that will be emitted during the process of dragging.
     *
     * @author Kevin Li<klx211@gmail.com>
     * @type {Object}
     */
    var kDraggableEvents = {
            DRAG_START: 'kDraggableDragStart',
            DRAG_END: 'kDraggableDragEnd'
        },
        /**
         * All the class name constants.
         *
         * @author Kevin Li<klx211@gmail.com>
         * @type {Object}
         */
        kClassNames = {
            DRAGGABLE: 'k-draggable',
            DRAGGING: 'k-dragging',
            HANDLE: 'k-handle'
        };

    angular
        .module('kl.draggable', [])
        .constant('kDraggableEvents', kDraggableEvents)
        .constant('kClassNames', kClassNames)
        .directive('kDraggable', kDraggable);

    kDraggable.$inject = [
        'kDraggableEvents',
        'kClassNames',
        '$document'
    ];

    /**
     * Facotry function of the directive.
     *
     * @author Kevin Li<klx211@gmail.com>
     * @param {Object} kDE An object containing all the event subjects that will be emitted during the process of
     * dragging.
     * @param {Object} kCN An object containing all the class name constants.
     * @param {jQuery} $document A jQuery wrapper for the browser's window.document object.
     * @returns {Object} The directive's definition object.
     */
    function kDraggable(kDE, kCN, $document) {

        return {
            link: function (scope, element, attrs) {

                attrs.$addClass(kCN.DRAGGABLE);

                var sSelector = attrs.kDraggable,
                    jqHandleElement;

                if (angular.isString(sSelector) && sSelector.length > 0) {

                    jqHandleElement = element.find(sSelector);
                    jqHandleElement.addClass(kCN.HANDLE);

                } else {

                    attrs.$addClass(kCN.HANDLE);
                }

                registerListeners(scope, element, jqHandleElement);
            },
            restrict: 'A',
            scope: {}
        };

        /**
         * Register all the necessary listeners for dragging an element.
         *
         * @author Kevin Li<klx211@gmail.com>
         * @param {Object} oScope The directive's scope object.
         * @param {jQuery} jqDraggableElement The HTML element which is wrapped by jQuery and is to be dragged.
         * @param {jQuery} jqHE The HTML element which is wrapped by jQuery and is the handle for dragging.
         */
        function registerListeners(oScope, jqDraggableElement, jqHE) {

            jqHE = jqHE || jqDraggableElement;

            jqHE.on('mousedown', onMousedown);

            function onMousedown(oEvent) {

                /**
                 * The value of left property of the HTML element to be dragged when the mouse button is held down.
                 *
                 * @author Kevin Li<klx211@gmail.com>
                 * @type {number}
                 */
                var nElementLeft = jqDraggableElement.position().left,
                    /**
                     * The value of top property of the HTML element to be dragged when the mouse button is held down.
                     *
                     * @author Kevin Li<klx211@gmail.com>
                     * @type {number}
                     */
                    nElementTop = jqDraggableElement.position().top,
                    /**
                     * The X position of the mouse cursor when the mouse button is held down.
                     *
                     * @author Kevin Li<klx211@gmail.com>
                     * @type {number}
                     */
                    nMouseX = oEvent.pageX,
                    /**
                     * The Y position of the mouse cursor when the mouse button is held down.
                     *
                     * @author Kevin Li<klx211@gmail.com>
                     * @type {number}
                     */
                    nMouseY = oEvent.pageY,
                    /**
                     * A counter to tell whether it's the first time to move the mouse after the mouse button is held
                     * down.
                     *
                     * @author Kevin Li<klx211@gmail.com>
                     * @type {number}
                     */
                    nCounter = 0;

                // Add box shadows so that it looks like the HTML element has just been lifted up.
                jqDraggableElement.addClass(kCN.DRAGGING);

                $document.on('mousemove', onMousemove);
                $document.on('mouseup', onMouseup);

                function onMousemove(oEvent) {

                    if (nCounter === 0) {

                        // This is the first move of the mouse after the mouse button is held down.
                        nCounter += 1;
                        oScope.$emit(kDE.DRAG_START);
                    }

                    jqDraggableElement.css({
                        left: nElementLeft + (oEvent.pageX - nMouseX),
                        top: nElementTop + (oEvent.pageY - nMouseY)
                    });
                }

                function onMouseup() {

                    $document.off('mousemove', onMousemove);
                    $document.off('mouseup', onMouseup);

                    // Remove the box shadows so that it looks like the HTML element has just been put down.
                    jqDraggableElement.removeClass(kCN.DRAGGING);

                    nCounter = 0; // Reset the counter when the mouse button is released.
                    oScope.$emit(kDE.DRAG_END);
                }
            }
        }
    }

}());<|endoftext|>


<commit_before>(function () {
  'use strict';

  window.Jakduk = {
    BoardCommentSize: 30,
    BoardCommentContentLengthMin: 3, // 게시판 댓글 입력 가능한 최소한의 문자열 수
    BoardCommentContentLengthMax: 800, // 게시판 댓글 입력 가능한 최대 문자열 수
    SummernoteContentsMinSize: 5,
    FormEmailLengthMin: 6,
    FormEmailLengthMax: 30,
    FormPasswordLengthMin: 4,
    FormPasswordLengthMax: 20,
    FormUsernameLengthMin: 2,
    FormUsernameLengthMax: 20,
    ItemsPerPageOnSearch: 10, 			// 찾기에서 페이지 당 아이템 수
    ItemsPerPageOnSearchGallery: 12, 	// 찾기에서 사진첩의 페이지 당 아이템 수
    ItemsPerPageOnGallery: 24,  		// 사진첩에서 한번 로딩할때 가져오는 그림의 수
    ItemsPerPageOnBoardComments: 10,
    origin: window.location.protocol + window.location.host + (window.location.port ? ':' + window.location.port : window.location.port),
    isEmpty: function (str) {
      var obj = String(str);
      return !!(obj === null || obj === undefined || obj === 'null' || obj === 'undefined' || obj === '');
    },
    needLogin: function (message) {
      if (window.confirm(message)) {
        window.location = '/board/free/write';
      }
    }
  };
}());

(function () {
  'use strict';

  angular.module('jakdukCommon', [])
    .config(['$interpolateProvider', '$httpProvider', function ($interpolateProvider, $httpProvider) {
      $interpolateProvider.startSymbol('{%');
      $interpolateProvider.endSymbol('%}');
      $httpProvider.defaults.withCredentials = true;
    }])
    // mongodb id의 앞 8자리(16진수)로 Date 객체 생성.
    .filter('dateFromObjectId', function () {
      return function (objectId) {
        return new Date(parseInt(objectId.substring(0, 8), 16) * 1000);
      }
    })
    // mongodb id의 앞 8자리(16진수)를 int로 변환.
    .filter('intFromObjectId', function () {
      return function (objectId) {
        return parseInt(objectId.substring(0, 8), 16) * 1000;
      }
    })
    .filter('objectIdFromDate', function () {
      return function (date) {
        return Math.floor(date.getTime() / 1000).toString(16) + "0000000000000000";
      }
    })
    .controller("headerCtrl", ['$scope', '$location', function ($scope, $location) {

      var port = $location.port();
      var prefix = $location.protocol() + '://' + $location.host();
      var prefixPath = (port == 80 || port == 443) ? prefix : prefix + ':' + $location.port();
      var absUrl = $location.absUrl();
      var path = absUrl.slice(prefixPath.length);

      $scope.isActive = function (viewLocation) {
        return path.match(viewLocation);
      };

      $scope.btnEnterOnHeaderSearch = function (url) {
        if ($scope.searchOnHeader.trim() < 1) {
          return;
        }

        location.href = url + '?q=' + $scope.searchOnHeader.trim() + '&w=PO;CO;GA;';
      };

      $scope.btnSearchOnHeader = function () {
        $scope.searchFocusOnHeader = true;
      };
    }])
    .directive('focus', ['$timeout', '$parse', function ($timeout, $parse) {
      /**
       * focus directive
       * http://fiddle.jshell.net/ubenzer/9FSL4/8/
       */
      return {
        restrict: 'A',
        link: function (scope, element, attrs) {
          scope.$watch(attrs.focus, function (newValue, oldValue) {
            if (newValue) {
              element[0].focus();
            }
          });
          element.bind("blur", function (e) {
            $timeout(function () {
              scope.$apply(attrs.focus + "=false");
            }, 0);
          });
          element.bind("focus", function (e) {
            $timeout(function () {
              scope.$apply(attrs.focus + "=true");
            }, 0);
          })
        }
      }
    }]);

}());
<commit_msg>clean code<commit_after>(function () {
  'use strict';

  window.Jakduk = {
    BoardCommentSize: 30,
    BoardCommentContentLengthMin: 3, // 게시판 댓글 입력 가능한 최소한의 문자열 수
    BoardCommentContentLengthMax: 800, // 게시판 댓글 입력 가능한 최대 문자열 수
    SummernoteContentsMinSize: 5,
    FormEmailLengthMin: 6,
    FormEmailLengthMax: 30,
    FormPasswordLengthMin: 4,
    FormPasswordLengthMax: 20,
    FormUsernameLengthMin: 2,
    FormUsernameLengthMax: 20,
    ItemsPerPageOnSearch: 10, 			// 찾기에서 페이지 당 아이템 수
    ItemsPerPageOnSearchGallery: 12, 	// 찾기에서 사진첩의 페이지 당 아이템 수
    ItemsPerPageOnGallery: 24,  		// 사진첩에서 한번 로딩할때 가져오는 그림의 수
    ItemsPerPageOnBoardComments: 10,
    origin: window.location.protocol + window.location.host + (window.location.port ? ':' + window.location.port : window.location.port),
    isEmpty: function (str) {
      var obj = String(str);
      return !!(obj === null || obj === undefined || obj === 'null' || obj === 'undefined' || obj === '');
    },
    needLogin: function (message) {
      if (window.confirm(message)) {
        window.location.href = '/board/free/write';
      }
    }
  };
}());

(function () {
  'use strict';

  angular.module('jakdukCommon', [])
    .config(['$interpolateProvider', '$httpProvider', function ($interpolateProvider, $httpProvider) {
      $interpolateProvider.startSymbol('{%');
      $interpolateProvider.endSymbol('%}');
      $httpProvider.defaults.withCredentials = true;
    }])
    // mongodb id의 앞 8자리(16진수)로 Date 객체 생성.
    .filter('dateFromObjectId', function () {
      return function (objectId) {
        return new Date(parseInt(objectId.substring(0, 8), 16) * 1000);
      }
    })
    // mongodb id의 앞 8자리(16진수)를 int로 변환.
    .filter('intFromObjectId', function () {
      return function (objectId) {
        return parseInt(objectId.substring(0, 8), 16) * 1000;
      }
    })
    .filter('objectIdFromDate', function () {
      return function (date) {
        return Math.floor(date.getTime() / 1000).toString(16) + "0000000000000000";
      }
    })
    .controller("headerCtrl", ['$scope', '$location', function ($scope, $location) {

      var port = $location.port();
      var prefix = $location.protocol() + '://' + $location.host();
      var prefixPath = (port == 80 || port == 443) ? prefix : prefix + ':' + $location.port();
      var absUrl = $location.absUrl();
      var path = absUrl.slice(prefixPath.length);

      $scope.isActive = function (viewLocation) {
        return path.match(viewLocation);
      };

      $scope.btnEnterOnHeaderSearch = function (url) {
        if ($scope.searchOnHeader.trim() < 1) {
          return;
        }

        location.href = url + '?q=' + $scope.searchOnHeader.trim() + '&w=PO;CO;GA;';
      };

      $scope.btnSearchOnHeader = function () {
        $scope.searchFocusOnHeader = true;
      };
    }])
    .directive('focus', ['$timeout', '$parse', function ($timeout, $parse) {
      /**
       * focus directive
       * http://fiddle.jshell.net/ubenzer/9FSL4/8/
       */
      return {
        restrict: 'A',
        link: function (scope, element, attrs) {
          scope.$watch(attrs.focus, function (newValue, oldValue) {
            if (newValue) {
              element[0].focus();
            }
          });
          element.bind("blur", function (e) {
            $timeout(function () {
              scope.$apply(attrs.focus + "=false");
            }, 0);
          });
          element.bind("focus", function (e) {
            $timeout(function () {
              scope.$apply(attrs.focus + "=true");
            }, 0);
          })
        }
      }
    }]);

}());
<|endoftext|>


<commit_before>/**
 * @copyright Copyright 2014 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @fileoverview Model for query column/result data.
 * @author joemu@google.com (Joe Allan Muharsky)
 */

goog.provide('p3rf.perfkit.explorer.models.perfkit_simple_builder.FieldResult');
goog.provide('p3rf.perfkit.explorer.models.perfkit_simple_builder.LabelResult');
goog.provide('p3rf.perfkit.explorer.models.perfkit_simple_builder.MeasureResult');
goog.provide('p3rf.perfkit.explorer.models.perfkit_simple_builder.PivotConfigModel');
goog.provide('p3rf.perfkit.explorer.models.perfkit_simple_builder.QueryColumnModel');
goog.provide('p3rf.perfkit.explorer.models.perfkit_simple_builder.QueryDateGroupings');
goog.provide('p3rf.perfkit.explorer.models.perfkit_simple_builder.QueryTablePartitioning');
goog.provide('p3rf.perfkit.explorer.models.perfkit_simple_builder.SamplesMartFields');
goog.provide('p3rf.perfkit.explorer.models.perfkit_simple_builder.SamplesMartMeasures');

goog.scope(function() {
var explorer = p3rf.perfkit.explorer;

/**
 * Type definition for a label-result specifier.  Though it's a simple string,
 * the wrapper is required for angular binding purposes.
 * @constructor
 */
explorer.models.perfkit_simple_builder.LabelResult = function() {
  /** @type {!string} */
  this.label = '';
};
var LabelResult = explorer.models.perfkit_simple_builder.LabelResult;

/**
 * Type definition for a label-result specifier.  Though it's a simple string,
 * the wrapper is required for angular binding purposes.
 * @constructor
 */
explorer.models.perfkit_simple_builder.FieldResult = function(name) {
  /** @type {!string} */
  this.name = name || '';
};
var FieldResult = explorer.models.perfkit_simple_builder.FieldResult;

/**
 * Type definition for a measure-result specifier.  Though it's a simple string,
 * the wrapper is required for angular binding purposes.
 * @constructor
 */
explorer.models.perfkit_simple_builder.MeasureResult = function(name) {
  /** @type {!string} */
  this.name = name || '';
};
var MeasureResult = explorer.models.perfkit_simple_builder.MeasureResult;

/**
 * Type definition for a pivot configuration.  Pivots specify a column, row and
 * value field, and transform the results so that the "column" field's unique
 * values are displayed as column headers.
 * @constructor
 */
explorer.models.perfkit_simple_builder.PivotConfigModel = function() {
  /**
   * @type {!string}
   * @export
   */
  this.row_field = '';

  /**
   * @type {!string}
   * @export
   */
  this.column_field = '';

  /**
   * @type {!string}
   * @export
   */
  this.value_field = '';
};
var PivotConfigModel = explorer.models.perfkit_simple_builder.PivotConfigModel;

/**
 * Constants describing the types of filters applied to dates.
 * @export
 */
explorer.models.perfkit_simple_builder.QueryDateGroupings = {
  NONE: '',
  YEAR: 'Year',
  MONTH: 'Month',
  WEEK: 'Week',
  DAY: 'Day',
  HOUR: 'Hour'
};
var QueryDateGroupings = (
    explorer.models.perfkit_simple_builder.QueryDateGroupings);

/**
 * Constants describing the types of filters applied to dates.
 * @export
 */
explorer.models.perfkit_simple_builder.SamplesMartFields = {
  TEST: 'test',
  TARGET: 'target',
  PRODUCT_NAME: 'product_name',
  PRODUCT_VERSION: 'product_version',
  PRODUCT_BRANCH_CL: 'product_branch_cl',
  PRODUCT_CHERRY_PICK_CLS: 'product_cherry_pick_cls',
  TEST_VERSION: 'test_version',
  OWNER: 'owner',
  LOG_URI: 'log_uri',
  RUN_URI: 'run_uri',
  LABELS: 'labels',
  METRIC: 'metric',
  VALUE: 'value',
  UNIT: 'unit',
  TIMESTAMP: 'timestamp',
  METRIC_URI: 'metric_uri',
  SAMPLE_URI: 'sample_uri'
};
var SamplesMartFields = (
    explorer.models.perfkit_simple_builder.SamplesMartFields);

/**
 * Constants describing the types of measures applied to values.
 * @export
 */
explorer.models.perfkit_simple_builder.SamplesMartMeasures = {
  MIN: 'MIN',
  MAX: 'MAX',
  AVG: 'AVG',
  STDDEV: 'STDDEV',
  COUNT: 'COUNT',
  LAST: 'LAST',
  MEAN: 'MEAN',
  SUM: 'SUM',
  VARIANCE: 'VARIANCE',
  PCT_50: '50%',
  PCT_99: '99%',
  PCT_9999: '99.99%'
};
var SamplesMartMeasures = (
    explorer.models.perfkit_simple_builder.SamplesMartMeasures);

/**
 * @enum {string}
 */
explorer.models.perfkit_simple_builder.QueryShapes = {
  TABULAR: 'Tabular',
  PIVOT: 'Pivot'
};
var QueryShapes = explorer.models.perfkit_simple_builder.QueryShapes;

/**
 * Describes the possible structures of a BigQuery table.
 *   Default - unset value.  Used to refer to parent scope settings, such as
 *       the widget leaving it blank in favor of the dashboard setting.
 *   OneTable - assumes a single table with all data.
 *   PerDate - contains a table for each individual day.  The Table Wildcard
 *       Functions are used to determine which tables will be queries.  For
 *       more information on Table Wildcard Functions, see:
 *   https://cloud.google.com/bigquery/query-reference#tablewildcardfunctions
 * @enum {string}
 */
explorer.models.perfkit_simple_builder.QueryTablePartitioning = {
  DEFAULT: '',
  ONETABLE: 'OneTable',
  PERDAY: 'PerDay'
};
var QueryTablePartitioning = (
    explorer.models.perfkit_simple_builder.QueryTablePartitioning);

/**
 * Angular service that provides the column configuration of a Samples query.
 * @constructor
 */
explorer.models.perfkit_simple_builder.QueryColumnModel = function() {
  /** @export @type {!boolean} */
  this.show_date = false;

  /** @export @type {!QueryDateGroupings} */
  this.date_group = QueryDateGroupings.NONE;

  /** @export @type {!Array.<!FieldResult>} */
  this.fields = [];

  /** @export @type {!boolean} */
  this.measure_values = false;

  /**
   * A list of 'name' objects where name is a string describing the measure.
   * Acceptable values are common non-arg functions (MIN, MAX, AVG, etc.), as
   * well as percentiles (99%, etc.).
   * @export @type {Array.<!FieldResult>}
   */
  this.measures = [];

  /** @export @type {Array.<!LabelResult>} */
  this.labels = [];

  /** @export @type {!boolean} */
  this.pivot = false;

  /** @export @type {!PivotConfigModel} */
  this.pivot_config = new PivotConfigModel();

  /** @type @type {?number} */
  this.row_limit = null;

  /**
   * Specifies the project id that the query will connect to.  If not provided,
   * will use the dashboard-level project id, or the app-engine default.
   * @export @type {?string}
   */
  this.project_id = null;

  /**
   * Specifies the dataset that the query will connect to.  If not provided,
   * will use the dashboard-level dataset name, or the app-engine default.
   * @export @type {?string}
   */
  this.dataset_name = null;

  /**
   * Specifies the table that the query will connect to.  If not provided, will
   * use the dashboard-level table name or the app-engine default.
   * @export @type {?string}
   */
  this.table_name = null;

  /**
   * Specifies the type of partitioning used on the table.  For more
   * information, see the docstring for QueryTablePartitioning.
   * @export @type {QueryTablePartitioning}
   */
  this.table_partition = QueryTablePartitioning.DEFAULT;
};

var QueryColumnModel = explorer.models.perfkit_simple_builder.QueryColumnModel;

});  // goog.scope
<commit_msg>Removed invalid MEAN function.<commit_after>/**
 * @copyright Copyright 2014 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @fileoverview Model for query column/result data.
 * @author joemu@google.com (Joe Allan Muharsky)
 */

goog.provide('p3rf.perfkit.explorer.models.perfkit_simple_builder.FieldResult');
goog.provide('p3rf.perfkit.explorer.models.perfkit_simple_builder.LabelResult');
goog.provide('p3rf.perfkit.explorer.models.perfkit_simple_builder.MeasureResult');
goog.provide('p3rf.perfkit.explorer.models.perfkit_simple_builder.PivotConfigModel');
goog.provide('p3rf.perfkit.explorer.models.perfkit_simple_builder.QueryColumnModel');
goog.provide('p3rf.perfkit.explorer.models.perfkit_simple_builder.QueryDateGroupings');
goog.provide('p3rf.perfkit.explorer.models.perfkit_simple_builder.QueryTablePartitioning');
goog.provide('p3rf.perfkit.explorer.models.perfkit_simple_builder.SamplesMartFields');
goog.provide('p3rf.perfkit.explorer.models.perfkit_simple_builder.SamplesMartMeasures');

goog.scope(function() {
var explorer = p3rf.perfkit.explorer;

/**
 * Type definition for a label-result specifier.  Though it's a simple string,
 * the wrapper is required for angular binding purposes.
 * @constructor
 */
explorer.models.perfkit_simple_builder.LabelResult = function() {
  /** @type {!string} */
  this.label = '';
};
var LabelResult = explorer.models.perfkit_simple_builder.LabelResult;

/**
 * Type definition for a label-result specifier.  Though it's a simple string,
 * the wrapper is required for angular binding purposes.
 * @constructor
 */
explorer.models.perfkit_simple_builder.FieldResult = function(name) {
  /** @type {!string} */
  this.name = name || '';
};
var FieldResult = explorer.models.perfkit_simple_builder.FieldResult;

/**
 * Type definition for a measure-result specifier.  Though it's a simple string,
 * the wrapper is required for angular binding purposes.
 * @constructor
 */
explorer.models.perfkit_simple_builder.MeasureResult = function(name) {
  /** @type {!string} */
  this.name = name || '';
};
var MeasureResult = explorer.models.perfkit_simple_builder.MeasureResult;

/**
 * Type definition for a pivot configuration.  Pivots specify a column, row and
 * value field, and transform the results so that the "column" field's unique
 * values are displayed as column headers.
 * @constructor
 */
explorer.models.perfkit_simple_builder.PivotConfigModel = function() {
  /**
   * @type {!string}
   * @export
   */
  this.row_field = '';

  /**
   * @type {!string}
   * @export
   */
  this.column_field = '';

  /**
   * @type {!string}
   * @export
   */
  this.value_field = '';
};
var PivotConfigModel = explorer.models.perfkit_simple_builder.PivotConfigModel;

/**
 * Constants describing the types of filters applied to dates.
 * @export
 */
explorer.models.perfkit_simple_builder.QueryDateGroupings = {
  NONE: '',
  YEAR: 'Year',
  MONTH: 'Month',
  WEEK: 'Week',
  DAY: 'Day',
  HOUR: 'Hour'
};
var QueryDateGroupings = (
    explorer.models.perfkit_simple_builder.QueryDateGroupings);

/**
 * Constants describing the types of filters applied to dates.
 * @export
 */
explorer.models.perfkit_simple_builder.SamplesMartFields = {
  TEST: 'test',
  TARGET: 'target',
  PRODUCT_NAME: 'product_name',
  PRODUCT_VERSION: 'product_version',
  PRODUCT_BRANCH_CL: 'product_branch_cl',
  PRODUCT_CHERRY_PICK_CLS: 'product_cherry_pick_cls',
  TEST_VERSION: 'test_version',
  OWNER: 'owner',
  LOG_URI: 'log_uri',
  RUN_URI: 'run_uri',
  LABELS: 'labels',
  METRIC: 'metric',
  VALUE: 'value',
  UNIT: 'unit',
  TIMESTAMP: 'timestamp',
  METRIC_URI: 'metric_uri',
  SAMPLE_URI: 'sample_uri'
};
var SamplesMartFields = (
    explorer.models.perfkit_simple_builder.SamplesMartFields);

/**
 * Constants describing the types of measures applied to values.
 * @export
 */
explorer.models.perfkit_simple_builder.SamplesMartMeasures = {
  MIN: 'MIN',
  MAX: 'MAX',
  AVG: 'AVG',
  STDDEV: 'STDDEV',
  COUNT: 'COUNT',
  LAST: 'LAST',
  SUM: 'SUM',
  VARIANCE: 'VARIANCE',
  PCT_50: '50%',
  PCT_99: '99%',
  PCT_9999: '99.99%'
};
var SamplesMartMeasures = (
    explorer.models.perfkit_simple_builder.SamplesMartMeasures);

/**
 * @enum {string}
 */
explorer.models.perfkit_simple_builder.QueryShapes = {
  TABULAR: 'Tabular',
  PIVOT: 'Pivot'
};
var QueryShapes = explorer.models.perfkit_simple_builder.QueryShapes;

/**
 * Describes the possible structures of a BigQuery table.
 *   Default - unset value.  Used to refer to parent scope settings, such as
 *       the widget leaving it blank in favor of the dashboard setting.
 *   OneTable - assumes a single table with all data.
 *   PerDate - contains a table for each individual day.  The Table Wildcard
 *       Functions are used to determine which tables will be queries.  For
 *       more information on Table Wildcard Functions, see:
 *   https://cloud.google.com/bigquery/query-reference#tablewildcardfunctions
 * @enum {string}
 */
explorer.models.perfkit_simple_builder.QueryTablePartitioning = {
  DEFAULT: '',
  ONETABLE: 'OneTable',
  PERDAY: 'PerDay'
};
var QueryTablePartitioning = (
    explorer.models.perfkit_simple_builder.QueryTablePartitioning);

/**
 * Angular service that provides the column configuration of a Samples query.
 * @constructor
 */
explorer.models.perfkit_simple_builder.QueryColumnModel = function() {
  /** @export @type {!boolean} */
  this.show_date = false;

  /** @export @type {!QueryDateGroupings} */
  this.date_group = QueryDateGroupings.NONE;

  /** @export @type {!Array.<!FieldResult>} */
  this.fields = [];

  /** @export @type {!boolean} */
  this.measure_values = false;

  /**
   * A list of 'name' objects where name is a string describing the measure.
   * Acceptable values are common non-arg functions (MIN, MAX, AVG, etc.), as
   * well as percentiles (99%, etc.).
   * @export @type {Array.<!FieldResult>}
   */
  this.measures = [];

  /** @export @type {Array.<!LabelResult>} */
  this.labels = [];

  /** @export @type {!boolean} */
  this.pivot = false;

  /** @export @type {!PivotConfigModel} */
  this.pivot_config = new PivotConfigModel();

  /** @type @type {?number} */
  this.row_limit = null;

  /**
   * Specifies the project id that the query will connect to.  If not provided,
   * will use the dashboard-level project id, or the app-engine default.
   * @export @type {?string}
   */
  this.project_id = null;

  /**
   * Specifies the dataset that the query will connect to.  If not provided,
   * will use the dashboard-level dataset name, or the app-engine default.
   * @export @type {?string}
   */
  this.dataset_name = null;

  /**
   * Specifies the table that the query will connect to.  If not provided, will
   * use the dashboard-level table name or the app-engine default.
   * @export @type {?string}
   */
  this.table_name = null;

  /**
   * Specifies the type of partitioning used on the table.  For more
   * information, see the docstring for QueryTablePartitioning.
   * @export @type {QueryTablePartitioning}
   */
  this.table_partition = QueryTablePartitioning.DEFAULT;
};

var QueryColumnModel = explorer.models.perfkit_simple_builder.QueryColumnModel;

});  // goog.scope
<|endoftext|>