<commit_before>'use strict';

function ApplicationController($scope, $location, $http, applicationState, Choko) {
  $scope.state = {};

  $scope.changeState = function() {
    var path = (!$location.path() || $location.path() == '/') ? '/home' : $location.path();

    $http.get(path)
    .success(function(data, status, headers, config) {
      if (data.data.redirect) {
        // Server returned a redirect.
        return $location.path(data.data.redirect);
      }

      // Rebuild the layout only when context changes.
      if ($scope.contexts instanceof Array && $scope.contexts.toString() == data.data.contexts.toString()) {
        // Update only panels in content region, and page information.
        // @todo: get the region the page-content panel is attached to
        // dinamically currently this is hadcoded to 'content' and will not work
        // if the page-content panel is attacehd to a different region.
        $scope.panels['content'] = data.data.panels['content'];
        $scope.page = data.data.page;
      }
      else {
        // Merge data from the server.
        angular.extend($scope, data.data);

        // Store scope as application state.
        applicationState.set($scope);
      }
    })
    .error(function(data, status, headers, config) {
      // Merge data from the server.
      angular.extend($scope.page, data.data);

      $scope.page.template = '/templates/error.html';

      // Store scope as application state.
      applicationState.set($scope);
    });
  }

  $scope.$watch(function() {
    return $location.path();
  }, function(){
    $scope.changeState();
  });
}
//ApplicationController.$inject = ['$scope', '$location', '$http', 'applicationState', 'Choko'];

function PanelController($scope, $location, $http, applicationState, Choko) {
  if ($scope.panel.type && $scope.panel.type !== 'default') {
    // Set view to the panel itself and call ViewController.
    $scope.view = $scope.panel;
    ViewController($scope, $location, $http, applicationState, Choko);
  }

  if ($scope.panel.bare) {
    $scope.template = $scope.panel.template || 'templates/panel-content.html';
  }
  else {
    $scope.template = 'templates/panel.html';
  }
}
//PanelController.$inject = ['$scope', '$location', '$http', 'applicationState', 'Choko'];

function PageController($scope, $location, $http, applicationState, Choko) {
  if (!$scope.page.type || $scope.page.type === 'default') {
    $scope.items = $scope.page.items || {};
    $scope.title = $scope.page.title;
  }
  else {
    // Set view to the panel itself and call ViewController.
    $scope.view = $scope.page;
    ViewController($scope, $location, $http, applicationState, Choko);
  }
}
//PageController.$inject = ['$scope', '$location', '$http', 'applicationState', 'Choko'];

function RowController($scope, $location, applicationState, Choko) {
  $scope.name = $scope.row.name;

  $scope.getTemplate = function() {
    return $scope.template || 'templates/row.html';
  }
}
//RowController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function ColumnController($scope, $location, applicationState, Choko) {
  $scope.name = $scope.column.name;

  $scope.getTemplate = function() {
    return $scope.template || 'templates/column.html';
  };
}
//ColumnController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function RegionController($scope, $location, applicationState, Choko) {
}
//RegionController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function NavigationController($scope, $location, $window, applicationState, Choko) {
  $scope.panel.classes.unshift('nav');

  $scope.isAbsolute = function(url) {
    return /^(?:[a-z]+:)?\/\//i.test(url);
  };

  $scope.goTo = function(url, $event) {
    $location.path(url);
    if ($event) {
      $event.preventDefault();
    }
  };

  $scope.isActive = function(route) {
    //var regexp = new RegExp('^' + pattern + '.*$', ["i"]);
    return route === $location.path();
  };
}
//NavigationController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function ItemController($scope, $location, applicationState, Choko) {
}
//ItemController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function DisplayRegionController($scope, $location, applicationState, Choko) {
}
//DisplayRegionController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function DisplayFieldController($scope, $location, applicationState, Choko) {
  $scope.field.template = $scope.field.template || '/templates/' + $scope.field.format + '.html';
}
//DisplayFieldController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function ReferenceElementController($scope, $location, applicationState, Choko) {
  Choko.get({type: $scope.element.reference.type}, function(response) {
    $scope.element.options = response;

    // Use radios if less then 5 options.
    $scope.fewOptions = ($scope.element.options && Object.keys($scope.element.options).length <= 5);
  });

  // Initialize data container if needed.
  $scope.data[$scope.element.name] = $scope.data[$scope.element.name] || [];

  // Toggle selection for a given option by name.
  $scope.toggleSelection = function(option) {
    var index = $scope.data[$scope.element.name].indexOf(option);

    // Is currently selected.
    if (index > -1) {
      $scope.data[$scope.element.name].splice(index, 1);
    }
    // Is newly selected.
    else {
      $scope.data[$scope.element.name].push(option);
    }
  };
}
//ReferenceElementController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function InlineReferenceElementController($scope, $location, applicationState, Choko) {
  var multiple = $scope.element.reference.multiple;

  // Subform errors are handled separately.
  $scope.errors = [];

  if (multiple) {
    // Initialize items container.
    if ($scope.data[$scope.element.name]) {
      $scope.items = $scope.data[$scope.element.name];
    }
    else {
      $scope.items = $scope.data[$scope.element.name] = [];
    }

    // Initilize local data container.
    $scope.data = {};

    $scope.saveItem = function(key) {
      // @todo: validate item.
      // Add item and cleanup data container and items.
      if (key != undefined) {
        $scope.items[key] = $scope.data;
      }
      else {
        $scope.items.push($scope.data);
      }
      $scope.data = {};

      // Reset form to original state.
      delete $scope.element.subform;
    };

    $scope.removeItem = function(index) {
      $scope.items.splice(index, 1);
    };
  }
  else {
    if ($scope.data[$scope.element.name]) {
      $scope.data = $scope.data[$scope.element.name];
    }
    else {
      $scope.data = $scope.data[$scope.element.name] = {};
    }
  }

  $scope.setSubForm = function(type, sub, data, key) {
    // Start by destroying the subform and its data.
    // @todo: eventually we may want to add a confirmation, if form is "dirty".
    delete $scope.element.subform;
    $scope.data = {};

    // Get the new subform from the REST server.
    Choko.get({type: 'form', key: 'type-' + type}, function(response) {
      var subform = $scope.element.subform = response;

      // We are editing a item, store data.
      if (data) {
        $scope.editing = true;

        // Make a copy of original data for restoring on cancel.
        $scope.data = angular.copy(data);
      }
      else {
        $scope.editing = false;
      }

      if (multiple) {
        subform.elements.push({
          name: 'add',
          title: 'Save',
          type: 'button',
          click: 'saveItem',
          arguments: [key],
          classes: ['btn-default'],
          weight: 15
        });
        subform.elements.push({
          name: 'cancel',
          title: 'Cancel',
          type: 'button',
          click: 'cancel',
          classes: ['btn-link'],
          weight: 20
        });
      }

      if (sub) {
        // Set subform element type to subform short name.
        $scope.data.type = subform.shortName;
      }
    });
  };

  if (multiple) {
    if ($scope.element.reference.subtypes && $scope.element.reference.subtypes.length == 1) {
      $scope.setSubForm($scope.element.reference.subtypes[0]);
    }

    $scope.cancel = function() {
      delete $scope.element.subform;
      $scope.data = {};
    };
  }
  else {
    $scope.setSubForm($scope.element.reference.type);
  }

}
//InlineReferenceElementController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function InlineReferenceElementItemController($scope, $filter, applicationState, Choko) {

  $scope.editItem = function() {
    $scope.setSubForm($scope.typeName(), !!$scope.element.reference.subtypes, $scope.item, $scope.key);
  };

  $scope.typeName = function() {
    var typeName = $scope.element.reference.type;

    // If it has subtypes, i.e. it's a polymorphic type, get the actual type
    // being added to load the correct form.
    if ($scope.element.reference.subtypes) {
      $scope.element.reference.subtypes.forEach(function(subtype) {
        if (subtype.shortName == $scope.item.type) {
          typeName = subtype.name;
        }
      });
    }

    return typeName;
  };

}
//InlineReferenceElementItemController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function ViewController($scope, $location, $http, applicationState, Choko) {
  // Handle 'list' type views.
  if ($scope.view.type === 'list' && $scope.view.itemType) {
    $scope.items = {};

    Choko.get({type: $scope.view.itemType}, function(response) {
      $scope.items = response;
    });

    if (!$scope.view.template && $scope.view.listStyle) {
      $scope.view.template = '/templates/' + $scope.view.listStyle + '.html';
    }

    if (!$scope.view.itemTemplate && $scope.view.itemDisplay) {
      Choko.get({type: 'display', key: $scope.view.itemDisplay}, function(display) {
        $scope.display = display;
        Choko.get({type: 'displayLayout', key: display.layout}, function(layout) {
          $scope.layout = layout;
          $scope.view.itemTemplate = '/templates/display-layout.html';
        });
      });
    }
  }

  // Handle 'item' type views.
  if ($scope.view.type === 'item' && $scope.view.itemType) {
    $scope.data = {};
    $scope.view.title = '';
    Choko.get({type: $scope.view.itemType, key: $scope.view.itemKey}, function(response) {
      $scope.data = response;
      $scope.view.title = response.title;
    },
    function(response) {
      // Error.
      if ($scope.page) {
        // If it's a page, show error, otherwise fail silently.
        $scope.data = response.data;
        $scope.view.title = response.data.title;
        $scope.view.template = '/templates/error.html';
      }
    });
  }

  // Handle 'form' type views.
  if ($scope.view.type === 'form' && $scope.view.formName) {
    $scope.data = {};

    if ($scope.view.itemType && $scope.view.itemKey) {
      Choko.get({type: $scope.view.itemType, key: $scope.view.itemKey}, function(response) {
        $scope.data = response;
      });
    }

    $scope.submit = function(url, redirect) {
      // Add itemKey to the URL if any.
      if ($scope.view.itemKey) {
        url += '/' + $scope.view.itemKey;
      }

      $http.post(url, $scope.data)
        .success(function(data, status, headers, config) {
          $scope.data = data;
          delete $scope.errors;
          if (redirect) {
            $location.path(redirect);
          }
        })
        .error(function(data, status, headers, config) {
          $scope.status = status;
          $scope.errors = data.data;
        });
    };

    Choko.get({type: 'form', key: $scope.view.formName}, function(response) {
      $scope.form = response;

      if ($scope.form.mainTypeName) {
        $scope.data.type = $scope.form.shortName;
      }

      // First we look for view (page/panel) redirect, then for form redirect.
      // The submit button will first look for a property of its own and
      // fallback to this.
      $scope.form.redirect = $scope.view.redirect || $scope.form.redirect || null;

      $scope.view.template = $scope.view.template || $scope.form.template;
      $scope.view.template = $scope.view.template || 'templates/form.html';
    });
  }
}
//ViewController.$inject = ['$scope', '$location', '$http', 'applicationState', 'Choko'];

function ElementController($scope, $location, applicationState, Choko) {
  $scope.element.template = $scope.element.template || 'templates/' + $scope.element.type + '.html';
}
//ElementController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function FileElementController($scope, $location, $upload, applicationState, Choko) {
  $scope.element.template = $scope.element.template || 'templates/' + $scope.element.type + '.html';
  $scope.progress = 0;

  // Initialize files container.
  // @todo support multiple files.
  $scope.data[$scope.element.name] = $scope.data[$scope.element.name] || null;

  $scope.onFileSelect = function($files) {
    for (var i = 0; i < $files.length; i++) {
      var file = $files[i];
      $scope.upload = $upload.upload({
        url: 'file',
        file: file
      })
      .progress(function(evt) {
        $scope.progress = parseInt(100.0 * evt.loaded / evt.total);
      })
      .success(function(data, status, headers, config) {
        $scope.data[$scope.element.name] = data.data.id;
      });
    }
  };
}
//FileElementController.$inject = ['$scope', '$location', '$upload', 'applicationState', 'Choko'];

function SubElementController($scope, $location, applicationState, Choko) {
  $scope.subElement.template = $scope.subElement.template || 'templates/' + $scope.subElement.type + '.html';
}
//SubElementController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function ButtonController($scope, $location, applicationState, Choko) {
  $scope.call = function(func, args) {
    $scope[func].apply(this, args);
  };
}
//ButtonController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function WYSIWYGController($scope, $location, applicationState, Choko) {
  $scope.options = {
    height: $scope.element.height || 300,
    toolbar: [
      ['style', ['style']],
      ['style', ['bold', 'italic', 'underline', 'clear']],
      ['para', ['ul', 'ol', 'paragraph']],
      ['insert', ['picture', 'link']],
      ['table', ['table']]
    ]
  };
}
//WYSIWYGController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];
<commit_msg>Refactored controllers to induce only needed injections and to inherit controllers.<commit_after>'use strict';

function ApplicationController($scope, $location, $http, applicationState) {
  $scope.state = {};

  $scope.changeState = function() {
    var path = (!$location.path() || $location.path() == '/') ? '/home' : $location.path();

    $http.get(path)
    .success(function(data, status, headers, config) {
      if (data.data.redirect) {
        // Server returned a redirect.
        return $location.path(data.data.redirect);
      }

      // Rebuild the layout only when context changes.
      if ($scope.contexts instanceof Array && $scope.contexts.toString() == data.data.contexts.toString()) {
        // Update only panels in content region, and page information.
        // @todo: get the region the page-content panel is attached to
        // dinamically currently this is hadcoded to 'content' and will not work
        // if the page-content panel is attacehd to a different region.
        $scope.panels['content'] = data.data.panels['content'];
        $scope.page = data.data.page;
      }
      else {
        // Merge data from the server.
        angular.extend($scope, data.data);

        // Store scope as application state.
        applicationState.set($scope);
      }
    })
    .error(function(data, status, headers, config) {
      // Merge data from the server.
      angular.extend($scope.page, data.data);

      $scope.page.template = '/templates/error.html';

      // Store scope as application state.
      applicationState.set($scope);
    });
  }

  $scope.$watch(function() {
    return $location.path();
  }, function(){
    $scope.changeState();
  });
}
//ApplicationController.$inject = ['$scope', '$location', '$http', 'applicationState'];

function PanelController($scope, $controller) {
  if ($scope.panel.type && $scope.panel.type !== 'default') {
    // Set view to the panel itself and call ViewController.
    $scope.view = $scope.panel;

    // Inherit controller.
    $controller('ViewController', {
      $scope: $scope
    });
  }

  if ($scope.panel.bare) {
    $scope.template = $scope.panel.template || 'templates/panel-content.html';
  }
  else {
    $scope.template = 'templates/panel.html';
  }
}
//PanelController.$inject = ['$scope', '$controller'];

function PageController($scope, $controller) {
  if (!$scope.page.type || $scope.page.type === 'default') {
    $scope.items = $scope.page.items || {};
    $scope.title = $scope.page.title;
  }
  else {
    // Set view to the panel itself and call ViewController.
    $scope.view = $scope.page;

    // Inherit controller.
    $controller('ViewController', {
      $scope: $scope
    });
  }
}
//PageController.$inject = ['$scope', '$controller'];

function RowController($scope) {
  $scope.name = $scope.row.name;

  $scope.getTemplate = function() {
    return $scope.template || 'templates/row.html';
  }
}
//RowController.$inject = ['$scope'];

function ColumnController($scope) {
  $scope.name = $scope.column.name;

  $scope.getTemplate = function() {
    return $scope.template || 'templates/column.html';
  };
}
//ColumnController.$inject = ['$scope'];

function RegionController() {
}
//RegionController.$inject = [];

function NavigationController($scope, $location) {
  $scope.panel.classes.unshift('nav');

  $scope.isAbsolute = function(url) {
    return /^(?:[a-z]+:)?\/\//i.test(url);
  };

  $scope.goTo = function(url, $event) {
    $location.path(url);
    if ($event) {
      $event.preventDefault();
    }
  };

  $scope.isActive = function(route) {
    //var regexp = new RegExp('^' + pattern + '.*$', ["i"]);
    return route === $location.path();
  };
}
//NavigationController.$inject = ['$scope', '$location'];

function ItemController() {
}
//ItemController.$inject = [];

function DisplayRegionController() {
}
//DisplayRegionController.$inject = [];

function DisplayFieldController($scope) {
  $scope.field.template = $scope.field.template || '/templates/' + $scope.field.format + '.html';
}
//DisplayFieldController.$inject = ['$scope'];

function ReferenceElementController($scope) {
  Choko.get({type: $scope.element.reference.type}, function(response) {
    $scope.element.options = response;

    // Use radios if less then 5 options.
    $scope.fewOptions = ($scope.element.options && Object.keys($scope.element.options).length <= 5);
  });

  // Initialize data container if needed.
  $scope.data[$scope.element.name] = $scope.data[$scope.element.name] || [];

  // Toggle selection for a given option by name.
  $scope.toggleSelection = function(option) {
    var index = $scope.data[$scope.element.name].indexOf(option);

    // Is currently selected.
    if (index > -1) {
      $scope.data[$scope.element.name].splice(index, 1);
    }
    // Is newly selected.
    else {
      $scope.data[$scope.element.name].push(option);
    }
  };
}
//ReferenceElementController.$inject = ['$scope'];

function InlineReferenceElementController($scope, Choko) {
  var multiple = $scope.element.reference.multiple;

  // Subform errors are handled separately.
  $scope.errors = [];

  if (multiple) {
    // Initialize items container.
    if ($scope.data[$scope.element.name]) {
      $scope.items = $scope.data[$scope.element.name];
    }
    else {
      $scope.items = $scope.data[$scope.element.name] = [];
    }

    // Initilize local data container.
    $scope.data = {};

    $scope.saveItem = function(key) {
      // @todo: validate item.
      // Add item and cleanup data container and items.
      if (key != undefined) {
        $scope.items[key] = $scope.data;
      }
      else {
        $scope.items.push($scope.data);
      }
      $scope.data = {};

      // Reset form to original state.
      delete $scope.element.subform;
    };

    $scope.removeItem = function(index) {
      $scope.items.splice(index, 1);
    };
  }
  else {
    if ($scope.data[$scope.element.name]) {
      $scope.data = $scope.data[$scope.element.name];
    }
    else {
      $scope.data = $scope.data[$scope.element.name] = {};
    }
  }

  $scope.setSubForm = function(type, sub, data, key) {
    // Start by destroying the subform and its data.
    // @todo: eventually we may want to add a confirmation, if form is "dirty".
    delete $scope.element.subform;
    $scope.data = {};

    // Get the new subform from the REST server.
    Choko.get({type: 'form', key: 'type-' + type}, function(response) {
      var subform = $scope.element.subform = response;

      // We are editing a item, store data.
      if (data) {
        $scope.editing = true;

        // Make a copy of original data for restoring on cancel.
        $scope.data = angular.copy(data);
      }
      else {
        $scope.editing = false;
      }

      if (multiple) {
        subform.elements.push({
          name: 'add',
          title: 'Save',
          type: 'button',
          click: 'saveItem',
          arguments: [key],
          classes: ['btn-default'],
          weight: 15
        });
        subform.elements.push({
          name: 'cancel',
          title: 'Cancel',
          type: 'button',
          click: 'cancel',
          classes: ['btn-link'],
          weight: 20
        });
      }

      if (sub) {
        // Set subform element type to subform short name.
        $scope.data.type = subform.shortName;
      }
    });
  };

  if (multiple) {
    if ($scope.element.reference.subtypes && $scope.element.reference.subtypes.length == 1) {
      $scope.setSubForm($scope.element.reference.subtypes[0]);
    }

    $scope.cancel = function() {
      delete $scope.element.subform;
      $scope.data = {};
    };
  }
  else {
    $scope.setSubForm($scope.element.reference.type);
  }

}
//InlineReferenceElementController.$inject = ['$scope', 'Choko'];

function InlineReferenceElementItemController($scope) {

  $scope.editItem = function() {
    $scope.setSubForm($scope.typeName(), !!$scope.element.reference.subtypes, $scope.item, $scope.key);
  };

  $scope.typeName = function() {
    var typeName = $scope.element.reference.type;

    // If it has subtypes, i.e. it's a polymorphic type, get the actual type
    // being added to load the correct form.
    if ($scope.element.reference.subtypes) {
      $scope.element.reference.subtypes.forEach(function(subtype) {
        if (subtype.shortName == $scope.item.type) {
          typeName = subtype.name;
        }
      });
    }

    return typeName;
  };

}
//InlineReferenceElementItemController.$inject = ['$scope'];

function ViewController($scope, $location, $http, Choko) {
  // Handle 'list' type views.
  if ($scope.view.type === 'list' && $scope.view.itemType) {
    $scope.items = {};

    Choko.get({type: $scope.view.itemType}, function(response) {
      $scope.items = response;
    });

    if (!$scope.view.template && $scope.view.listStyle) {
      $scope.view.template = '/templates/' + $scope.view.listStyle + '.html';
    }

    if (!$scope.view.itemTemplate && $scope.view.itemDisplay) {
      Choko.get({type: 'display', key: $scope.view.itemDisplay}, function(display) {
        $scope.display = display;
        Choko.get({type: 'displayLayout', key: display.layout}, function(layout) {
          $scope.layout = layout;
          $scope.view.itemTemplate = '/templates/display-layout.html';
        });
      });
    }
  }

  // Handle 'item' type views.
  if ($scope.view.type === 'item' && $scope.view.itemType) {
    $scope.data = {};
    $scope.view.title = '';
    Choko.get({type: $scope.view.itemType, key: $scope.view.itemKey}, function(response) {
      $scope.data = response;
      $scope.view.title = response.title;
    },
    function(response) {
      // Error.
      if ($scope.page) {
        // If it's a page, show error, otherwise fail silently.
        $scope.data = response.data;
        $scope.view.title = response.data.title;
        $scope.view.template = '/templates/error.html';
      }
    });
  }

  // Handle 'form' type views.
  if ($scope.view.type === 'form' && $scope.view.formName) {
    $scope.data = {};

    if ($scope.view.itemType && $scope.view.itemKey) {
      Choko.get({type: $scope.view.itemType, key: $scope.view.itemKey}, function(response) {
        $scope.data = response;
      });
    }

    $scope.submit = function(url, redirect) {
      // Add itemKey to the URL if any.
      if ($scope.view.itemKey) {
        url += '/' + $scope.view.itemKey;
      }

      $http.post(url, $scope.data)
        .success(function(data, status, headers, config) {
          $scope.data = data;
          delete $scope.errors;
          if (redirect) {
            $location.path(redirect);
          }
        })
        .error(function(data, status, headers, config) {
          $scope.status = status;
          $scope.errors = data.data;
        });
    };

    Choko.get({type: 'form', key: $scope.view.formName}, function(response) {
      $scope.form = response;

      if ($scope.form.mainTypeName) {
        $scope.data.type = $scope.form.shortName;
      }

      // First we look for view (page/panel) redirect, then for form redirect.
      // The submit button will first look for a property of its own and
      // fallback to this.
      $scope.form.redirect = $scope.view.redirect || $scope.form.redirect || null;

      $scope.view.template = $scope.view.template || $scope.form.template;
      $scope.view.template = $scope.view.template || 'templates/form.html';
    });
  }
}
//ViewController.$inject = ['$scope', '$location', '$http', 'Choko'];

function ElementController($scope) {
  $scope.element.template = $scope.element.template || 'templates/' + $scope.element.type + '.html';
}
//ElementController.$inject = ['$scope'];

function FileElementController($scope, $upload) {
  $scope.element.template = $scope.element.template || 'templates/' + $scope.element.type + '.html';
  $scope.progress = 0;

  // Initialize files container.
  // @todo support multiple files.
  $scope.data[$scope.element.name] = $scope.data[$scope.element.name] || null;

  $scope.onFileSelect = function($files) {
    for (var i = 0; i < $files.length; i++) {
      var file = $files[i];
      $scope.upload = $upload.upload({
        url: 'file',
        file: file
      })
      .progress(function(evt) {
        $scope.progress = parseInt(100.0 * evt.loaded / evt.total);
      })
      .success(function(data, status, headers, config) {
        $scope.data[$scope.element.name] = data.data.id;
      });
    }
  };
}
//FileElementController.$inject = ['$scope', '$upload'];

function SubElementController($scope) {
  $scope.subElement.template = $scope.subElement.template || 'templates/' + $scope.subElement.type + '.html';
}
//SubElementController.$inject = ['$scope'];

function ButtonController($scope) {
  $scope.call = function(func, args) {
    $scope[func].apply(this, args);
  };
}
//ButtonController.$inject = ['$scope'];

function WYSIWYGController($scope) {
  $scope.options = {
    height: $scope.element.height || 300,
    toolbar: [
      ['style', ['style']],
      ['style', ['bold', 'italic', 'underline', 'clear']],
      ['para', ['ul', 'ol', 'paragraph']],
      ['insert', ['picture', 'link']],
      ['table', ['table']]
    ]
  };
}
//WYSIWYGController.$inject = ['$scope'];
<|endoftext|>


<commit_before>'use strict';

function ApplicationController($scope, $location, $http, applicationState, Choko) {
  $scope.state = {};

  $scope.changeState = function() {
    var path = (!$location.path() || $location.path() == '/') ? '/home' : $location.path();

    $http.get(path)
    .success(function(data, status, headers, config) {
      // Rebuild the layout only when context changes.
      if ($scope.contexts instanceof Array && $scope.contexts.toString() == data.data.contexts.toString()) {
        // Update only panels in content region, and page information.
        // @todo: get the region the page-content panel is attached to
        // dinamically currently this is hadcoded to 'content' and will not work
        // if the page-content panel is attacehd to a different region.
        $scope.panels['content'] = data.data.panels['content'];
        $scope.page = data.data.page;
      }
      else {
        // Merge data from the server.
        angular.extend($scope, data.data);

        // Store scope as application state.
        applicationState.set($scope);
      }
    })
    .error(function(data, status, headers, config) {
      // Merge data from the server.
      angular.extend($scope.page, data.data);

      $scope.page.template = '/templates/error.html';

      // Store scope as application state.
      applicationState.set($scope);
    });
  }

  $scope.$watch(function() {
    return $location.path();
  }, function(){
    $scope.changeState();
  });
}
//ApplicationController.$inject = ['$scope', '$location', '$http', 'applicationState', 'Choko'];

function PanelController($scope, $location, $http, applicationState, Choko) {
  if ($scope.panel.type && $scope.panel.type !== 'default') {
    // Set view to the panel itself and call ViewController.
    $scope.view = $scope.panel;
    ViewController($scope, $location, $http, applicationState, Choko);
  }

  if ($scope.panel.bare) {
    $scope.template = $scope.panel.template || 'templates/panel-content.html';
  }
  else {
    $scope.template = 'templates/panel.html';
  }
}
//PanelController.$inject = ['$scope', '$location', '$http', 'applicationState', 'Choko'];

function PageController($scope, $location, $http, applicationState, Choko) {
  if (!$scope.page.type || $scope.page.type === 'default') {
    $scope.items = $scope.page.items || {};
    $scope.title = $scope.page.title;
  }
  else {
    // Set view to the panel itself and call ViewController.
    $scope.view = $scope.page;
    ViewController($scope, $location, $http, applicationState, Choko);
  }
}
//PageController.$inject = ['$scope', '$location', '$http', 'applicationState', 'Choko'];

function RowController($scope, $location, applicationState, Choko) {
  $scope.name = $scope.row.name;

  $scope.getTemplate = function() {
    return $scope.template || 'templates/row.html';
  }
}
//RowController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function ColumnController($scope, $location, applicationState, Choko) {
  $scope.name = $scope.column.name;

  $scope.getTemplate = function() {
    return $scope.template || 'templates/column.html';
  }
}
//ColumnController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function RegionController($scope, $location, applicationState, Choko) {
}
//RegionController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function NavigationController($scope, $location, applicationState, Choko) {
  $scope.panel.classes.unshift('nav');

  $scope.isActive = function(route) {
    //var regexp = new RegExp('^' + pattern + '.*$', ["i"]);
    return route === $location.path();
  };
}
//NavigationController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function ItemController($scope, $location, applicationState, Choko) {
}
//ItemController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function ReferenceElementController($scope, $location, applicationState, Choko) {
  Choko.get({type: $scope.element.reference.type}, function(response) {
    $scope.element.options = response;
  });

  $scope.data[$scope.element.name] = $scope.data[$scope.element.name] || [];

  // Toggle selection for a given option by name.
  $scope.toggleSelection = function(option) {
    var index = $scope.data[$scope.element.name].indexOf(option);

    // Is currently selected.
    if (index > -1) {
      $scope.data[$scope.element.name].splice(index, 1);
    }
    // Is newly selected.
    else {
      $scope.data[$scope.element.name].push(option);
    }
  };
}
//ReferenceElementController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function InlineReferenceElementController($scope, $location, applicationState, Choko) {
  var multiple = $scope.element.reference.multiple;

  // Subform errors are handled separately.
  $scope.errors = [];

  if (multiple) {
    if ($scope.data[$scope.element.name]) {
      $scope.items = $scope.data[$scope.element.name];
    }
    else {
      $scope.items = $scope.data[$scope.element.name] = [];
    }

    $scope.data = {};

    $scope.addItem = function() {
      // @todo: validate item.
      $scope.items.push($scope.data);
      $scope.data = {};
    };
    $scope.removeItem = function(index) {
      $scope.items.splice(index, 1);
    };
  }
  else {
    if ($scope.data[$scope.element.name]) {
      $scope.data = $scope.data[$scope.element.name];
    }
    else {
      $scope.data = $scope.data[$scope.element.name] = {};
    }
  }

  Choko.get({type: 'form', key: 'type-' + $scope.element.reference.type}, function(response) {
    var subform = $scope.element.subform = response;

    if (multiple) {
      subform.elements.push({
        name: 'add',
        title: 'Add',
        type: 'button',
        click: 'addItem',
        classes: ['btn-default'],
        weight: 15
      });
    }
  });
}
//InlineReferenceElementController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function ViewController($scope, $location, $http, applicationState, Choko) {
  // Handle 'list' type views.
  if ($scope.view.type === 'list' && $scope.view.itemType) {
    $scope.items = {};

    Choko.get({type: $scope.view.itemType}, function(response) {
      $scope.items = response;
    });
  }

  // Handle 'item' type views.
  if ($scope.view.type === 'item' && $scope.view.itemType) {
    $scope.item = {};
    $scope.view.title = '';
    Choko.get({type: $scope.view.itemType, key: $scope.view.itemKey}, function(response) {
      $scope.item = response;
      $scope.view.title = response.title;
    },
    function(response) {
      // Error.
      if ($scope.page) {
        // If it's a page, show error, otherwise fail silently.
        $scope.item = response.data;
        $scope.view.title = response.data.title;
        $scope.view.template = '/templates/error.html';
      }
    });
  }

  // Handle 'form' type views.
  if ($scope.view.type === 'form' && $scope.view.formName) {
    $scope.data = {};

    $scope.submit = function(url) {
      $http.post(url, $scope.data)
        .success(function(data, status, headers, config) {
          $scope.data = data;
          delete $scope.errors;
          $location.path('/');
        })
        .error(function(data, status, headers, config) {
          $scope.status = status;
          $scope.errors = data.data;
        });
    };

    Choko.get({type: 'form', key: $scope.view.formName}, function(response) {
      $scope.form = response;
      $scope.view.template = $scope.view.template || $scope.form.template;
      $scope.view.template = $scope.view.template || 'templates/form.html';
    });
  }
}
//ViewController.$inject = ['$scope', '$location', '$http', 'applicationState', 'Choko'];

function ElementController($scope, $location, applicationState, Choko) {
  $scope.element.template = $scope.element.template || 'templates/' + $scope.element.type + '.html';
}
//ElementController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function SubElementController($scope, $location, applicationState, Choko) {
  $scope.subElement.template = $scope.subElement.template || 'templates/' + $scope.subElement.type + '.html';
}
//SubElementController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function ButtonController($scope, $location, applicationState, Choko) {
  $scope.call = function(func) {
    $scope[func]();
  };
}
//ButtonController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];
<commit_msg>Fixing missing semicolon on controllers.js code.<commit_after>'use strict';

function ApplicationController($scope, $location, $http, applicationState, Choko) {
  $scope.state = {};

  $scope.changeState = function() {
    var path = (!$location.path() || $location.path() == '/') ? '/home' : $location.path();

    $http.get(path)
    .success(function(data, status, headers, config) {
      // Rebuild the layout only when context changes.
      if ($scope.contexts instanceof Array && $scope.contexts.toString() == data.data.contexts.toString()) {
        // Update only panels in content region, and page information.
        // @todo: get the region the page-content panel is attached to
        // dinamically currently this is hadcoded to 'content' and will not work
        // if the page-content panel is attacehd to a different region.
        $scope.panels['content'] = data.data.panels['content'];
        $scope.page = data.data.page;
      }
      else {
        // Merge data from the server.
        angular.extend($scope, data.data);

        // Store scope as application state.
        applicationState.set($scope);
      }
    })
    .error(function(data, status, headers, config) {
      // Merge data from the server.
      angular.extend($scope.page, data.data);

      $scope.page.template = '/templates/error.html';

      // Store scope as application state.
      applicationState.set($scope);
    });
  }

  $scope.$watch(function() {
    return $location.path();
  }, function(){
    $scope.changeState();
  });
}
//ApplicationController.$inject = ['$scope', '$location', '$http', 'applicationState', 'Choko'];

function PanelController($scope, $location, $http, applicationState, Choko) {
  if ($scope.panel.type && $scope.panel.type !== 'default') {
    // Set view to the panel itself and call ViewController.
    $scope.view = $scope.panel;
    ViewController($scope, $location, $http, applicationState, Choko);
  }

  if ($scope.panel.bare) {
    $scope.template = $scope.panel.template || 'templates/panel-content.html';
  }
  else {
    $scope.template = 'templates/panel.html';
  }
}
//PanelController.$inject = ['$scope', '$location', '$http', 'applicationState', 'Choko'];

function PageController($scope, $location, $http, applicationState, Choko) {
  if (!$scope.page.type || $scope.page.type === 'default') {
    $scope.items = $scope.page.items || {};
    $scope.title = $scope.page.title;
  }
  else {
    // Set view to the panel itself and call ViewController.
    $scope.view = $scope.page;
    ViewController($scope, $location, $http, applicationState, Choko);
  }
}
//PageController.$inject = ['$scope', '$location', '$http', 'applicationState', 'Choko'];

function RowController($scope, $location, applicationState, Choko) {
  $scope.name = $scope.row.name;

  $scope.getTemplate = function() {
    return $scope.template || 'templates/row.html';
  }
}
//RowController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function ColumnController($scope, $location, applicationState, Choko) {
  $scope.name = $scope.column.name;

  $scope.getTemplate = function() {
    return $scope.template || 'templates/column.html';
  };
}
//ColumnController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function RegionController($scope, $location, applicationState, Choko) {
}
//RegionController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function NavigationController($scope, $location, applicationState, Choko) {
  $scope.panel.classes.unshift('nav');

  $scope.isActive = function(route) {
    //var regexp = new RegExp('^' + pattern + '.*$', ["i"]);
    return route === $location.path();
  };
}
//NavigationController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function ItemController($scope, $location, applicationState, Choko) {
}
//ItemController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function ReferenceElementController($scope, $location, applicationState, Choko) {
  Choko.get({type: $scope.element.reference.type}, function(response) {
    $scope.element.options = response;
  });

  $scope.data[$scope.element.name] = $scope.data[$scope.element.name] || [];

  // Toggle selection for a given option by name.
  $scope.toggleSelection = function(option) {
    var index = $scope.data[$scope.element.name].indexOf(option);

    // Is currently selected.
    if (index > -1) {
      $scope.data[$scope.element.name].splice(index, 1);
    }
    // Is newly selected.
    else {
      $scope.data[$scope.element.name].push(option);
    }
  };
}
//ReferenceElementController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function InlineReferenceElementController($scope, $location, applicationState, Choko) {
  var multiple = $scope.element.reference.multiple;

  // Subform errors are handled separately.
  $scope.errors = [];

  if (multiple) {
    if ($scope.data[$scope.element.name]) {
      $scope.items = $scope.data[$scope.element.name];
    }
    else {
      $scope.items = $scope.data[$scope.element.name] = [];
    }

    $scope.data = {};

    $scope.addItem = function() {
      // @todo: validate item.
      $scope.items.push($scope.data);
      $scope.data = {};
    };
    $scope.removeItem = function(index) {
      $scope.items.splice(index, 1);
    };
  }
  else {
    if ($scope.data[$scope.element.name]) {
      $scope.data = $scope.data[$scope.element.name];
    }
    else {
      $scope.data = $scope.data[$scope.element.name] = {};
    }
  }

  Choko.get({type: 'form', key: 'type-' + $scope.element.reference.type}, function(response) {
    var subform = $scope.element.subform = response;

    if (multiple) {
      subform.elements.push({
        name: 'add',
        title: 'Add',
        type: 'button',
        click: 'addItem',
        classes: ['btn-default'],
        weight: 15
      });
    }
  });
}
//InlineReferenceElementController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function ViewController($scope, $location, $http, applicationState, Choko) {
  // Handle 'list' type views.
  if ($scope.view.type === 'list' && $scope.view.itemType) {
    $scope.items = {};

    Choko.get({type: $scope.view.itemType}, function(response) {
      $scope.items = response;
    });
  }

  // Handle 'item' type views.
  if ($scope.view.type === 'item' && $scope.view.itemType) {
    $scope.item = {};
    $scope.view.title = '';
    Choko.get({type: $scope.view.itemType, key: $scope.view.itemKey}, function(response) {
      $scope.item = response;
      $scope.view.title = response.title;
    },
    function(response) {
      // Error.
      if ($scope.page) {
        // If it's a page, show error, otherwise fail silently.
        $scope.item = response.data;
        $scope.view.title = response.data.title;
        $scope.view.template = '/templates/error.html';
      }
    });
  }

  // Handle 'form' type views.
  if ($scope.view.type === 'form' && $scope.view.formName) {
    $scope.data = {};

    $scope.submit = function(url) {
      $http.post(url, $scope.data)
        .success(function(data, status, headers, config) {
          $scope.data = data;
          delete $scope.errors;
          $location.path('/');
        })
        .error(function(data, status, headers, config) {
          $scope.status = status;
          $scope.errors = data.data;
        });
    };

    Choko.get({type: 'form', key: $scope.view.formName}, function(response) {
      $scope.form = response;
      $scope.view.template = $scope.view.template || $scope.form.template;
      $scope.view.template = $scope.view.template || 'templates/form.html';
    });
  }
}
//ViewController.$inject = ['$scope', '$location', '$http', 'applicationState', 'Choko'];

function ElementController($scope, $location, applicationState, Choko) {
  $scope.element.template = $scope.element.template || 'templates/' + $scope.element.type + '.html';
}
//ElementController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function SubElementController($scope, $location, applicationState, Choko) {
  $scope.subElement.template = $scope.subElement.template || 'templates/' + $scope.subElement.type + '.html';
}
//SubElementController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];

function ButtonController($scope, $location, applicationState, Choko) {
  $scope.call = function(func) {
    $scope[func]();
  };
}
//ButtonController.$inject = ['$scope', '$location', 'applicationState', 'Choko'];
<|endoftext|>


<commit_before>app.constant("FAVORITE_ENDPOINT", "php/apis/favorite/");
app.service("FavoriteService", function($http, FAVORITE_ENDPOINT) {

	function getUrl() {
		return(FAVORITE_ENDPOINT);
	}

	function getUrlForFavoriterId(favoriteeId) {
		return(getUrl() + favoriteeId);
	}

	function getUrlForFavoriteeId(favoriterId) {
		return(getUrl() + favoriterId);
	}

	/*I don't think we need this here. We're not calling an array of stuff*/
	/*this.all = function() {
		return($http.get(getUrl()));
	};*/

	this.fetchFavoriteByFavoriteeId = function(favoriteeId) {
		return($http.get(getUrl() + "?favoriteeId=" + favoriteeId));
	};

	this.fetchFavoriteByFavoriterId = function(favoriterId) {
		return($http.get(getUrl() + "?favoriterId=" + favoriterId));
	};

	this.fetchAllFavorites = function() {
		return($http.get(getUrl()));
	};

	this.create = function(favorite) {
		return($http.post(getUrl(), favorite));
	};

	/*TODO do we need destroy if we only unpost a favorite and not destroy? for both favoriter and favoritee*/
	this.destroy = function(favoriteeId) {
		return($http.delete(getUrlForFavoriteeId(favoriteeId)));
	};

	this.destroy = function(favoriterId) {
		return($http.delete(getUrlForFavoriterId(favoriterId)));
	};
});<commit_msg>used favoriter and favoritee in both create and destroy https://app.asana.com/0/161555263951762/170520114054348<commit_after>app.constant("FAVORITE_ENDPOINT", "php/apis/favorite/");
app.service("FavoriteService", function($http, FAVORITE_ENDPOINT) {

	function getUrl() {
		return(FAVORITE_ENDPOINT);
	}

	function getUrlForFavoriterId(favoriteeId) {
		return(getUrl() + favoriteeId);
	}

	function getUrlForFavoriteeId(favoriterId) {
		return(getUrl() + favoriterId);
	}

	/*I don't think we need this here. We're not calling an array of stuff*/
	/*this.all = function() {
		return($http.get(getUrl()));
	};*/

	this.fetchFavoriteById = function(favoriteeId) {
		return($http.get(getUrl() + "?favoriteeId=" + favoriteeId));
	};

	this.fetchFavoriteById = function(favoriterId) {
		return($http.get(getUrl() + "?favoriterId=" + favoriterId));
	};

	this.fetchAllFavorites = function() {
		return($http.get(getUrl()));
	};

	/*we're attempting to target the destroy between the favoritee and the favoriter*/
	this.create = function(favoriteeId, favoriterId) {
		return($http.post(getUrlforId(favoriteeId, favoriterId)));
	};

	/*we're attempting to target the destroy between the favoritee and the favoriter*/
	this.destroy = function(favoriteeId, favoriterId) {
		return($http.delete(getUrlforId(favoriteeId, favoriterId)));
	};

	/*comment this out*/
	/*this.destroy = function(favoriterId) {
		return($http.delete(getUrlForFavoriterId(favoriterId)));
	};*/
});<|endoftext|>


<commit_before>function bootstrap(data) {
  var dataSampled = [];
  for (var i = 0; i < data.length;i++)
    dataSampled.push(data[Math.floor(Math.random() * data.length)]);
  return dataSampled;
}

function sampleRow(data) {
  // Sample non-null elements from data
  var result = [];
  for (var j = 0; j < data[0].length; j++) {
    var k = 1;
    var r = undefined;
    for (var i = 0; i < data.length; i++)
      if (data[i][j] !== undefined)
	if (Math.random() * k++ < 1.0)
	  r = data[i][j];
    result.push(r);
  }
  return result;
}

function median(data) {
  // Sample non-null elements from data
  var result = [];
  for (var j = 0; j < data[0].length; j++) {
    var elms = []
    for (var i = 0; i < data.length; i++)
      if (data[i][j] !== undefined)
	elms.push(data[i][j]);

    if (elms.length % 2)
      result.push(elms[Math.floor(elms.length/2)]);
    else
      result.push(elms[Math.floor((elms.length + Math.random())/2)]);
  }
  return result;
}

function copyDefined(src, dst) {
  for (var j = 0; j < dst.length; j++)
    if (dst[j] === undefined)
      dst[j] = src[j];
  return dst;
}

function SplitPoint(fx, bx, pMissing) {
  this._fx = fx;
  this._bx = bx;
  this._pTies = Math.random();
  this._pMissing = pMissing;
}

SplitPoint.prototype.getSide = function(row) {
  if (row[this._fx] == undefined)
    return (Math.random() < this._pMissing) ? 1 : 0;
  else if (row[this._fx] == this._bx)
    return (Math.random() < this._pTies) ? 1 : 0;
  else
    return (row[this._fx] < this._bx) ? 1 : 0;
}

SplitPoint.prototype.serialize = function() {
  return {'bx': this._bx, 'fx': this._fx, 'pm': this._pMissing, 'pt': this._pTies};
}

function Leaf(representativeRow) {
  this._representativeRow = representativeRow;
}

Leaf.prototype.fill = function(row) {
 return copyDefined(this._representativeRow, row.slice(0));
}

Leaf.prototype.serialize = function() {
  return {'type': 'leaf', 'row': this._representativeRow};
}

function NonLeaf(split, lChild, rChild) {
  this._split = split;
  this._lChild = lChild;
  this._rChild = rChild;
}

NonLeaf.prototype.fill = function(row) {
  return [this._lChild, this._rChild][this._split.getSide(row)].fill(row);
}

NonLeaf.prototype.serialize = function() {
  return {'type': 'nonleaf', 'split': this._split.serialize(), 'L': this._lChild.serialize(), 'R': this._rChild.serialize()};
}

function RandomForest() {
  this._estimators = [];
}

RandomForest.prototype.fitTree = function(data, useMedian) {
  // Returns a classifier

  // Compute an representative feature vector
  if (useMedian)
    var representativeRow = median(data);
  else
    var representativeRow = sampleRow(data);

  // Handle leaf nodes (too few data points)
  if (data.length <= this._minLeaf) {
    return new Leaf(representativeRow);
  }

  var nFeatures = data[0].length;
  var bestIg = 0.0, bestSplit = undefined;
  for (var i = 0; i < this._maxFeatures; i++) {
    // Sample features
    var fx = Math.floor(Math.random() * nFeatures);
    var fy = Math.floor(Math.random() * nFeatures);

    // Sample split points
    var bx = data[Math.floor(Math.random() * data.length)][fx];
    var by = data[Math.floor(Math.random() * data.length)][fy];

    // Count statistics
    var c = [[0.0, 0.0], [0.0, 0.0]];
    for (var j = 0; j < data.length; j++)
      c[data[j][fx] < bx ? 1 : 0][data[j][fy] < by ? 1 : 0]++;

    // Calculate information gain
    function entropy(p) { return -p * Math.log(p) - (1 - p) * Math.log(1-p); }
    var H1 = entropy((c[0][0] + c[1][0]) / data.length);
    var H2 = (c[0][0] + c[0][1]) / data.length * (entropy(c[0][0] / (c[0][0] + c[0][1]))) + (c[1][0] + c[1][1]) / data.length * (entropy(c[1][0] / (c[1][0] + c[1][1])));

    var ig = H1 - H2;
    var pMissing = (c[0][0] + c[0][1] + 1.0) / (data.length + 2.0); // Mean of posterior assuming a Beta(1, 1) prior
    var pTies = Math.random(); // This ensures the split is uniform in the presense of points with infinite probability distribution

    if (!isNaN(ig) && ig > bestIg) {
      bestIg = ig;
      bestSplit = new SplitPoint(fx, bx, pMissing);
    }
  }

  if (bestIg == 0)
    return new Leaf(representativeRow);

  var dataSplit = [[], []];
  for (var i = 0; i < data.length; i++)
    dataSplit[bestSplit.getSide(data[i])].push(data[i]);

  if (dataSplit[0].length == 0 || dataSplit[1].length == 0)
    return new Leaf(representativeRow);

  var forest = this;
  var children = dataSplit.map(function(data) { return forest.fitTree(data, useMedian); });

  return new NonLeaf(bestSplit, children[0], children[1]);
}

RandomForest.prototype.train = function(data, nEstimators, useMedian, maxFeatures, minLeaf) {
  // Only used during training
  this._nEstimators = nEstimators;
  this._useMedian = useMedian;
  this._maxFeatures = maxFeatures; // Sampling from k^2 feature pairs
  this._minLeaf = minLeaf;

  for (var i = 0; i < this._nEstimators; i++) {
    var bootstrappedData = bootstrap(data);
    this._estimators.push(this.fitTree(bootstrappedData, this._useMedian));
  }
}

RandomForest.prototype.fill = function(row) {
  return this._estimators[Math.floor(Math.random() * this._nEstimators)].fill(row);
}

RandomForest.prototype.serialize = function() {
  return {'estimators': this._estimators.map(function(e) { return e.serialize(); })};
}

RandomForest.deserialize = function(data) {

}

module.exports = RandomForest;
<commit_msg>deserialization<commit_after>function bootstrap(data) {
  var dataSampled = [];
  for (var i = 0; i < data.length;i++)
    dataSampled.push(data[Math.floor(Math.random() * data.length)]);
  return dataSampled;
}

function sampleRow(data) {
  // Sample non-null elements from data
  var result = [];
  for (var j = 0; j < data[0].length; j++) {
    var k = 1;
    var r = undefined;
    for (var i = 0; i < data.length; i++)
      if (data[i][j] !== undefined)
	if (Math.random() * k++ < 1.0)
	  r = data[i][j];
    result.push(r);
  }
  return result;
}

function median(data) {
  // Sample non-null elements from data
  var result = [];
  for (var j = 0; j < data[0].length; j++) {
    var elms = []
    for (var i = 0; i < data.length; i++)
      if (data[i][j] !== undefined)
	elms.push(data[i][j]);

    if (elms.length % 2)
      result.push(elms[Math.floor(elms.length/2)]);
    else
      result.push(elms[Math.floor((elms.length + Math.random())/2)]);
  }
  return result;
}

function copyDefined(src, dst) {
  for (var j = 0; j < dst.length; j++)
    if (dst[j] === undefined)
      dst[j] = src[j];
  return dst;
}

function SplitPoint(fx, bx, pMissing, pTies) {
  this._fx = fx;
  this._bx = bx;
  this._pMissing = pMissing;
  this._pTies = pTies ? pTies : Math.random();
}

SplitPoint.prototype.getSide = function(row) {
  if (row[this._fx] == undefined)
    return (Math.random() < this._pMissing) ? 1 : 0;
  else if (row[this._fx] == this._bx)
    return (Math.random() < this._pTies) ? 1 : 0;
  else
    return (row[this._fx] < this._bx) ? 1 : 0;
}

SplitPoint.prototype.serialize = function() {
  return {'bx': this._bx, 'fx': this._fx, 'pm': this._pMissing, 'pt': this._pTies};
}

function Leaf(representativeRow) {
  this._representativeRow = representativeRow;
}

Leaf.prototype.fill = function(row) {
 return copyDefined(this._representativeRow, row.slice(0));
}

Leaf.prototype.serialize = function() {
  return {'t': 'l', 'row': this._representativeRow};
}

function NonLeaf(split, lChild, rChild) {
  this._split = split;
  this._lChild = lChild;
  this._rChild = rChild;
}

NonLeaf.prototype.fill = function(row) {
  return [this._lChild, this._rChild][this._split.getSide(row)].fill(row);
}

NonLeaf.prototype.serialize = function() {
  return {'t': 'nl', 'split': this._split.serialize(), 'L': this._lChild.serialize(), 'R': this._rChild.serialize()};
}

function RandomForest(estimators) {
  this._estimators = estimators ? estimators : [];
}

RandomForest.prototype.fitTree = function(data, useMedian) {
  // Returns a classifier

  // Compute an representative feature vector
  if (useMedian)
    var representativeRow = median(data);
  else
    var representativeRow = sampleRow(data);

  // Handle leaf nodes (too few data points)
  if (data.length <= this._minLeaf) {
    return new Leaf(representativeRow);
  }

  var nFeatures = data[0].length;
  var bestIg = 0.0, bestSplit = undefined;
  for (var i = 0; i < this._maxFeatures; i++) {
    // Sample features
    var fx = Math.floor(Math.random() * nFeatures);
    var fy = Math.floor(Math.random() * nFeatures);

    // Sample split points
    var bx = data[Math.floor(Math.random() * data.length)][fx];
    var by = data[Math.floor(Math.random() * data.length)][fy];

    // Count statistics
    var c = [[0.0, 0.0], [0.0, 0.0]];
    for (var j = 0; j < data.length; j++)
      c[data[j][fx] < bx ? 1 : 0][data[j][fy] < by ? 1 : 0]++;

    // Calculate information gain
    function entropy(p) { return -p * Math.log(p) - (1 - p) * Math.log(1-p); }
    var H1 = entropy((c[0][0] + c[1][0]) / data.length);
    var H2 = (c[0][0] + c[0][1]) / data.length * (entropy(c[0][0] / (c[0][0] + c[0][1]))) + (c[1][0] + c[1][1]) / data.length * (entropy(c[1][0] / (c[1][0] + c[1][1])));

    var ig = H1 - H2;
    var pMissing = (c[0][0] + c[0][1] + 1.0) / (data.length + 2.0); // Mean of posterior assuming a Beta(1, 1) prior
    var pTies = Math.random(); // This ensures the split is uniform in the presense of points with infinite probability distribution

    if (!isNaN(ig) && ig > bestIg) {
      bestIg = ig;
      bestSplit = new SplitPoint(fx, bx, pMissing);
    }
  }

  if (bestIg == 0)
    return new Leaf(representativeRow);

  var dataSplit = [[], []];
  for (var i = 0; i < data.length; i++)
    dataSplit[bestSplit.getSide(data[i])].push(data[i]);

  if (dataSplit[0].length == 0 || dataSplit[1].length == 0)
    return new Leaf(representativeRow);

  var forest = this;
  var children = dataSplit.map(function(data) { return forest.fitTree(data, useMedian); });

  return new NonLeaf(bestSplit, children[0], children[1]);
}

RandomForest.prototype.train = function(data, nEstimators, useMedian, maxFeatures, minLeaf) {
  // Only used during training
  this._nEstimators = nEstimators;
  this._useMedian = useMedian;
  this._maxFeatures = maxFeatures; // Sampling from k^2 feature pairs
  this._minLeaf = minLeaf;

  for (var i = 0; i < this._nEstimators; i++) {
    var bootstrappedData = bootstrap(data);
    this._estimators.push(this.fitTree(bootstrappedData, this._useMedian));
  }
}

RandomForest.prototype.fill = function(row) {
  return this._estimators[Math.floor(Math.random() * this._estimators.length)].fill(row);
}

RandomForest.prototype.serialize = function() {
  return {'t': 'f', 'estimators': this._estimators.map(function(e) { return e.serialize(); })};
}

RandomForest.deserialize = function(data) {
  if (data['t'] == 'f')
    return new RandomForest(data['estimators'].map(RandomForest.deserialize));
  else if (data['t'] == 'l')
    return new Leaf(data['row']);
  else if (data['t'] == 'nl')
    return new NonLeaf(new SplitPoint(data['split']['fx'], data['split']['bx'], data['split']['pm'], data['split']['pt']),
		       RandomForest.deserialize(data['L']),
		       RandomForest.deserialize(data['R']))
}

module.exports = RandomForest;
<|endoftext|>


<commit_before>//______________________________STOCHASTIQUE_BLOG_Bot_______________________________
//
//______________________MADE___BY___NIEMES_____INFO =-} niemes.info_____________
// -----------------------------------------------------------------------------
//-----------------------Authenticate Tumblr via OAuth--------------------------
var tumblr = require('tumblr.js');
var client = tumblr.createClient({
    consumer_key: 'your_consumer_key',
    consumer_secret: 'your_consumer_secret',
    token: 'your_token',
    token_secret: 'your_token_secret'
});

function init() {
    var postNumber = 178; // Number of Post every 24H. (250 max)
    var timeToPost = 86400000 / postNumber;

    console.log("-------- INIT --------");
    var reblogKey = [],
        postIdList = [];
    var tagList = ['design', 'moma', 'lol', 'geek', 'selfie', 'landscape', 'gif', 'illustration', 'embroidery', 'art', 'Architecture', 'streetart', 'PHOTOGRAPHY', 'URBAN', 'GRUNGE', 'ABANDONED', 'aesthetic', 'war', 'peace'];
    // starter tag.

    function GetPostKey() {

        var randTag = Math.floor((Math.random() * tagList.length) + 1);
        var tag = tagList[randTag];

        if (tagList.length < 5000) { // ex 5000 - Size limit of the taglist

            client.taggedPosts(tag, {
                filter: 'html'
            }, function(err, data) {
                if (data !== undefined) {
                    for (var i = 0; i < data.length; i++) {
                        if (data[i].tags !== undefined && (data[i].reblog_key !== undefined || data[i].id !== undefined)) {
                            reblogKey.push(data[i].reblog_key);
                            postIdList.push(data[i].id);
                            tagList.push(data[i].tags); // If you want to grab some tags...
                        }
                    }
                    if (err) {
                        console.log('TAG PROBLEM');
                        throw new Error(err);
                    } else {
                        console.log('Tags/Keys/Ids catched -= OK =- ');
                    }
                }
            });
        }
    }
    GetPostKey();
    setInterval(GetPostKey, 280000); // Time to grab post = id + key
    function reblogMachine() {

        var randKey = Math.floor((Math.random() * reblogKey.length) + 1);
        var key = reblogKey[randKey];
        var postId = postIdList[randKey];
        var blogName = 'your_tumblr.tumblr.com';
        var myCom = 'A simple comment'; // comment: if you want to add a comment on every rebloged-post. Leave empty if you want.
        if (key !== undefined && postIdList.length !== 0) {
            client.reblogPost(blogName, {
                id: postId,
                reblog_key: key,
                comment: myCom
            }, function(err, data) {
                if (err) {
                    console.log(
                        new error(err));
                    console.log('REBLOG PROBLEM' + err);
                } else {
                    // --------- ERROR LOG -----------
                    console.log('Reblog -= [OK] =- ' + data);
                }
            });
        }
    }
    setInterval(reblogMachine, timeToPost); // time for reblog 1000 = 1s (max 250 reblog/day)
    console.log("Time/min before every post : " + ((timeToPost / 1000) / 60));
}

init();
<commit_msg>Random_reblog<commit_after>//______________________________STOCHASTIQUE_BLOG_Bot___________________________
//----------------_________________RANDOM_REBLOG_____________-------------------
//______________________MADE___BY___NIEMES_____INFO =-} niemes.info_____________
// -----------------------------------------------------------------------------
//-----------------------Authenticate Tumblr via OAuth--------------------------
var tumblr = require('tumblr.js');
var client = tumblr.createClient({
    consumer_key: 'your_consumer_key',
    consumer_secret: 'your_consumer_secret',
    token: 'your_token',
    token_secret: 'your_token_secret'
});

function init() {
    var postNumber = 178; // Number of Post every 24H. (250 max)
    var timeToPost = 86400000 / postNumber;

    console.log("-------- INIT --------");
    var reblogKey = [],
        postIdList = [];
    var tagList = ['design', 'moma', 'lol', 'geek', 'selfie', 'landscape', 'gif', 'illustration', 'embroidery', 'art', 'Architecture', 'streetart', 'PHOTOGRAPHY', 'URBAN', 'GRUNGE', 'ABANDONED', 'aesthetic', 'war', 'peace'];
    // starter tag.

    function GetPostKey() {

        var randTag = Math.floor((Math.random() * tagList.length) + 1);
        var tag = tagList[randTag];

        if (tagList.length < 5000) { // ex 5000 - Size limit of the taglist

            client.taggedPosts(tag, {
                filter: 'html'
            }, function(err, data) {
                if (data !== undefined) {
                    for (var i = 0; i < data.length; i++) {
                        if (data[i].tags !== undefined && (data[i].reblog_key !== undefined || data[i].id !== undefined)) {
                            reblogKey.push(data[i].reblog_key);
                            postIdList.push(data[i].id);
                            tagList.push(data[i].tags); // If you want to grab some tags...
                        }
                    }
                    if (err) {
                        console.log('TAG PROBLEM ' + err);
                    } else {
                        console.log('Tags/Keys/Ids catched -= OK =- ');
                    }
                }
            });
        }
    }
    GetPostKey();
    setInterval(GetPostKey, 280000); // Time to grab post = id + key
    function reblogMachine() {

        var randKey = Math.floor((Math.random() * reblogKey.length) + 1);
        var key = reblogKey[randKey];
        var postId = postIdList[randKey];
        var blogName = 'your_tumblr.tumblr.com';
        var myCom = 'A simple comment'; // comment: if you want to add a comment on every rebloged-post. Leave empty if you want.
        if (key !== undefined && postIdList.length !== 0) {
            client.reblogPost(blogName, {
                id: postId,
                reblog_key: key,
                comment: myCom
            }, function(err, data) {
                if (err) {
                    console.log('REBLOG PROBLEM' + err);
                } else {
                    // --------- ERROR LOG -----------
                    console.log('Reblog -= [OK] =- ' + data);
                }
            });
        }
    }
    setInterval(reblogMachine, timeToPost); // time for reblog 1000 = 1s (max 250 reblog/day)
    console.log("Time/min before every post : " + ((timeToPost / 1000) / 60));
}

init();
<|endoftext|>


<commit_before>var Lang = A.Lang,
	isArray = Lang.isArray,
	isBoolean = Lang.isBoolean,
	isString = Lang.isString,
	isObject = Lang.isObject,

	CLASS_NAMES_SELECTION = 'CLASS_NAMES_SELECTION',

	ACTIVE_CELL = 'activeCell',
	BOUNDING_BOX = 'boundingBox',
	CELL = 'cell',
	CELL_INDEX = 'cellIndex',
	CONTAINER = 'container',
	FOCUSED = 'focused',
	KEY = 'key',
	MOUSEDOWN = 'mousedown',
	MOUSEENTER = 'mouseenter',
	MOUSEUP = 'mouseup',
	SELECTED = 'selected',
	SELECTION = 'selection',
	CHILDREN = 'children',

	_DOT = '.',

	clamp = function(value, min, max) {
		return Math.min(Math.max(value, min), max);
	};

var DataTableSelection = function () {};

DataTableSelection.ATTRS = {
	activeCell: {
		setter: 'getCell'
	},

	selection: {
		setter: '_setSelection'
	},

	tabIndex: {
		value: 0
	}
};

A.mix(DataTableSelection.prototype, {
	_capturing: false,
	_selectionEnd: null,
	_selectionSeed: null,
	_selectionStart: null,

	initializer: function() {
		var instance = this,
			boundingBox = instance.get(BOUNDING_BOX);

		instance[CLASS_NAMES_SELECTION] = {
			cell: instance.getClassName(CELL),
			selection: instance.getClassName(SELECTION)
		};

		instance._bindSelectionUI();

		boundingBox.addClass(instance[CLASS_NAMES_SELECTION].selection);
	},

	destroy: function() {
		var instance = this;

		instance._selectionKeyHandler.detach();
	},

	captureSelection: function(coords) {
		var instance = this,
			cells = [],
			cols = [],
			records = [],
			rows = [],
			i;

		for (i = 0; i < coords.length; i++) {
			var c = coords[i],
				cell = instance.getCell(c);

			rows.push(c[0]);
			cells.push(cell);
			cols.push(instance.getColumn(cell));
		}

		rows = A.Array.unique(rows);
		cols = A.Array.unique(cols);

		for (i = 0; i < rows.length; i++) {
			rows[i] = instance.getRow(rows[i]);
			records[i] = instance.getRecord(rows[i]);
		}

		return {
			cells: cells,
			cols: cols,
			coords: coords,
			records: records,
			rows: rows
		};
	},

	getCoord: function(seed) {
		var instance = this,
			cell = instance.getCell(seed),
			tbody = instance.body.tbodyNode,
			rowIndexOffset = tbody.get('firstChild.rowIndex');

		return [ cell.get('parentNode.rowIndex') - rowIndexOffset, cell.get(CELL_INDEX) ];
	},

	_bindSelectionUI: function() {
		var instance = this,
			classNames = instance[CLASS_NAMES_SELECTION];

		instance._selectionKeyHandler = A.getDoc().on(KEY, A.bind(instance._onSelectionKey, instance), 'down:37,38,39,40');

		instance.delegate(MOUSEUP, A.bind(instance._onSelectionMouseUp, instance), _DOT+classNames.cell);
		instance.delegate(MOUSEDOWN, A.bind(instance._onSelectionMouseDown, instance), _DOT+classNames.cell);
		instance.delegate(MOUSEENTER, A.bind(instance._onSelectionMouseEnter, instance), _DOT+classNames.cell);
	},

	_onSelectionMouseDown: function(event) {
		var instance = this,
			seed = event.currentTarget,
			boundingBox = instance.get(BOUNDING_BOX);

		boundingBox.unselectable();

		instance._capturing = true;
		instance._selectionSeed = seed;
		instance._selectionStart = instance._selectionEnd = instance.getCoord(seed);

		instance.set(ACTIVE_CELL, seed);
	},

	_onSelectionMouseEnter: function(event) {
		var instance = this,
			seed = event.currentTarget;

		if (!instance._capturing) {
			return;
		}

		instance._selectionSeed = seed;
		instance._selectionEnd = instance.getCoord(seed);

		instance.set(SELECTION, {
			start: instance._selectionStart,
			end: instance._selectionEnd
		});
	},

	_onSelectionMouseUp: function(event) {
		var instance = this,
			boundingBox = instance.get(BOUNDING_BOX);

		if (instance.get(FOCUSED)) {
			instance._selectionEnd = instance.getCoord(instance._selectionSeed);

			instance.set(SELECTION, {
				start: instance._selectionStart,
				end: instance._selectionEnd
			});
		}

		boundingBox.selectable();

		instance._capturing = false;
	},

	_onSelectionKey: function(event) {
		var instance = this,
			body = instance.body,
			tbody = body.tbodyNode,
			keyCode = event.keyCode,
			activeCell = instance.get(ACTIVE_CELL),
			activeCoord,
			imax = tbody.get(CHILDREN).size(),
			jmax = body.get('columns').length,
			i,
			j;

		if (activeCell && instance.get(FOCUSED)) {
			activeCoord = instance.getCoord(activeCell);

			i = activeCoord[0];
			j = activeCoord[1];

			if (keyCode === 37) {
				j--;
			}
			else if (keyCode === 38) {
				i--;
			}
			else if (keyCode === 39) {
				j++;
			}
			else if (keyCode === 40) {
				i++;
			}

			i = clamp(i, 0, imax-1);
			j = clamp(j, 0, jmax-1);

			instance.set(ACTIVE_CELL, [i, j]);

			instance.set(SELECTION, [i, j]);

			event.preventDefault();
		}
	},

	_parseRange: function(val) {
		var c1 = val[0],
			c2 = val[1],
			coords = [],
			i,
			j;

		for (i = Math.min(c1[0], c2[0]); i <= Math.max(c1[0], c2[0]); i++) {
			for (j = Math.min(c1[1], c2[1]); j <= Math.max(c1[1], c2[1]); j++) {
				coords.push([i,j]);
			}
		}

		return coords;
	},

	_setSelection: function(val) {
		var instance = this;

		if (isArray(val)) {
			if (!isArray(val[0])) {
				val = [val];
			}
		}
		else if (isObject(val)) {
			val = instance._parseRange([val.start, val.end]);
		}
		else if (A.instanceOf(val, A.Node)) {
			val = [instance.getCoord(val)];
		}

		return instance.captureSelection(val);
	}
});

A.DataTable.Selection = DataTableSelection;

A.Base.mix(A.DataTable, [ DataTableSelection ]);

A.DataTable.prototype.getColumn = (function (original) {
	return function (seed) {
		var cell;

		if (A.instanceOf(seed, A.Node)) {
			cell = this.getCell(seed);

			seed = cell && (cell.get('className').match(
				new RegExp(this.getClassName('col', '(\\w+)'))) || [])[1];
		}

		return original.call(this, seed);
	};
}(A.DataTable.prototype.getColumn));<commit_msg>AUI-657 DataTable columns configuration breaks on n-depth cloning complex objects. See http://yuilibrary.com/projects/yui3/ticket/2532597<commit_after>var Lang = A.Lang,
	isArray = Lang.isArray,
	isBoolean = Lang.isBoolean,
	isString = Lang.isString,
	isObject = Lang.isObject,

	CLASS_NAMES_SELECTION = 'CLASS_NAMES_SELECTION',

	ACTIVE_CELL = 'activeCell',
	BOUNDING_BOX = 'boundingBox',
	CELL = 'cell',
	CELL_INDEX = 'cellIndex',
	CONTAINER = 'container',
	FOCUSED = 'focused',
	KEY = 'key',
	MOUSEDOWN = 'mousedown',
	MOUSEENTER = 'mouseenter',
	MOUSEUP = 'mouseup',
	SELECTED = 'selected',
	SELECTION = 'selection',
	CHILDREN = 'children',

	_DOT = '.',

	clamp = function(value, min, max) {
		return Math.min(Math.max(value, min), max);
	};

var DataTableSelection = function () {};

DataTableSelection.ATTRS = {
	activeCell: {
		setter: 'getCell'
	},

	selection: {
		setter: '_setSelection'
	},

	tabIndex: {
		value: 0
	}
};

A.mix(DataTableSelection.prototype, {
	_capturing: false,
	_selectionEnd: null,
	_selectionSeed: null,
	_selectionStart: null,

	initializer: function() {
		var instance = this,
			boundingBox = instance.get(BOUNDING_BOX);

		instance[CLASS_NAMES_SELECTION] = {
			cell: instance.getClassName(CELL),
			selection: instance.getClassName(SELECTION)
		};

		instance._bindSelectionUI();

		boundingBox.addClass(instance[CLASS_NAMES_SELECTION].selection);
	},

	destroy: function() {
		var instance = this;

		instance._selectionKeyHandler.detach();
	},

	captureSelection: function(coords) {
		var instance = this,
			cells = [],
			cols = [],
			records = [],
			rows = [],
			i;

		for (i = 0; i < coords.length; i++) {
			var c = coords[i],
				cell = instance.getCell(c);

			rows.push(c[0]);
			cells.push(cell);
			cols.push(instance.getColumn(cell));
		}

		rows = A.Array.unique(rows);
		cols = A.Array.unique(cols);

		for (i = 0; i < rows.length; i++) {
			rows[i] = instance.getRow(rows[i]);
			records[i] = instance.getRecord(rows[i]);
		}

		return {
			cells: cells,
			cols: cols,
			coords: coords,
			records: records,
			rows: rows
		};
	},

	getCoord: function(seed) {
		var instance = this,
			cell = instance.getCell(seed),
			tbody = instance.body.tbodyNode,
			rowIndexOffset = tbody.get('firstChild.rowIndex');

		return [ cell.get('parentNode.rowIndex') - rowIndexOffset, cell.get(CELL_INDEX) ];
	},

	_bindSelectionUI: function() {
		var instance = this,
			classNames = instance[CLASS_NAMES_SELECTION];

		instance._selectionKeyHandler = A.getDoc().on(KEY, A.bind(instance._onSelectionKey, instance), 'down:37,38,39,40');

		instance.delegate(MOUSEUP, A.bind(instance._onSelectionMouseUp, instance), _DOT+classNames.cell);
		instance.delegate(MOUSEDOWN, A.bind(instance._onSelectionMouseDown, instance), _DOT+classNames.cell);
		instance.delegate(MOUSEENTER, A.bind(instance._onSelectionMouseEnter, instance), _DOT+classNames.cell);
	},

	_onSelectionMouseDown: function(event) {
		var instance = this,
			seed = event.currentTarget,
			boundingBox = instance.get(BOUNDING_BOX);

		boundingBox.unselectable();

		instance._capturing = true;
		instance._selectionSeed = seed;
		instance._selectionStart = instance._selectionEnd = instance.getCoord(seed);

		instance.set(ACTIVE_CELL, seed);
	},

	_onSelectionMouseEnter: function(event) {
		var instance = this,
			seed = event.currentTarget;

		if (!instance._capturing) {
			return;
		}

		instance._selectionSeed = seed;
		instance._selectionEnd = instance.getCoord(seed);

		instance.set(SELECTION, {
			start: instance._selectionStart,
			end: instance._selectionEnd
		});
	},

	_onSelectionMouseUp: function(event) {
		var instance = this,
			boundingBox = instance.get(BOUNDING_BOX);

		if (instance.get(FOCUSED)) {
			instance._selectionEnd = instance.getCoord(instance._selectionSeed);

			instance.set(SELECTION, {
				start: instance._selectionStart,
				end: instance._selectionEnd
			});
		}

		boundingBox.selectable();

		instance._capturing = false;
	},

	_onSelectionKey: function(event) {
		var instance = this,
			body = instance.body,
			tbody = body.tbodyNode,
			keyCode = event.keyCode,
			activeCell = instance.get(ACTIVE_CELL),
			activeCoord,
			imax = tbody.get(CHILDREN).size(),
			jmax = body.get('columns').length,
			i,
			j;

		if (activeCell && instance.get(FOCUSED)) {
			activeCoord = instance.getCoord(activeCell);

			i = activeCoord[0];
			j = activeCoord[1];

			if (keyCode === 37) {
				j--;
			}
			else if (keyCode === 38) {
				i--;
			}
			else if (keyCode === 39) {
				j++;
			}
			else if (keyCode === 40) {
				i++;
			}

			i = clamp(i, 0, imax-1);
			j = clamp(j, 0, jmax-1);

			instance.set(ACTIVE_CELL, [i, j]);

			instance.set(SELECTION, [i, j]);

			event.preventDefault();
		}
	},

	_parseRange: function(val) {
		var c1 = val[0],
			c2 = val[1],
			coords = [],
			i,
			j;

		for (i = Math.min(c1[0], c2[0]); i <= Math.max(c1[0], c2[0]); i++) {
			for (j = Math.min(c1[1], c2[1]); j <= Math.max(c1[1], c2[1]); j++) {
				coords.push([i,j]);
			}
		}

		return coords;
	},

	_setSelection: function(val) {
		var instance = this;

		if (isArray(val)) {
			if (!isArray(val[0])) {
				val = [val];
			}
		}
		else if (isObject(val)) {
			val = instance._parseRange([val.start, val.end]);
		}
		else if (A.instanceOf(val, A.Node)) {
			val = [instance.getCoord(val)];
		}

		return instance.captureSelection(val);
	}
});

A.DataTable.Selection = DataTableSelection;

A.Base.mix(A.DataTable, [ DataTableSelection ]);

A.DataTable.prototype.getColumn = (function (original) {
	return function (seed) {
		var cell;

		if (A.instanceOf(seed, A.Node)) {
			cell = this.getCell(seed);

			seed = cell && (cell.get('className').match(
				new RegExp(this.getClassName('col', '(\\w+)'))) || [])[1];
		}

		return original.call(this, seed);
	};
}(A.DataTable.prototype.getColumn));

// DataTable columns configuration breaks on n-depth cloning complex objects
// See http://yuilibrary.com/projects/yui3/ticket/2532597

A.DataTable.prototype._setColumns = function (val) {
	var keys = {},
		known = [],
		knownCopies = [],
		arrayIndex = A.Array.indexOf,
		isString = A.Lang.isString,
		isObject = A.Lang.isObject,
		isArray = A.Lang.isArray;

	function copyObj(o) {
		var copy = {},
			key, val, i;

		known.push(o);
		knownCopies.push(copy);

		for (key in o) {
			if (o.hasOwnProperty(key)) {
				val = o[key];

				if (isArray(val)) {
					copy[key] = val.slice();
				// Patch is right here, the second condition
				} else if (isObject(val, true) && val.constructor === copy.constructor) {
					i = arrayIndex(val, known);

					copy[key] = i === -1 ? copyObj(val) : knownCopies[i];
				} else {
					copy[key] = o[key];
				}
			}
		}

		return copy;
	}

	function genId(name) {
		// Sanitize the name for use in generated CSS classes.
		// TODO: is there more to do for other uses of _id?
		name = name.replace(/\s+/, '-');

		if (keys[name]) {
			name += (keys[name]++);
		} else {
			keys[name] = 1;
		}

		return name;
	}

	function process(cols, parent) {
		var columns = [],
			i, len, col, yuid;

		for (i = 0, len = cols.length; i < len; ++i) {
			columns[i] = // chained assignment
			col = isString(cols[i]) ? { key: cols[i] } : copyObj(cols[i]);

			yuid = A.stamp(col);

			// For backward compatibility
			if (!col.id) {
				// Implementers can shoot themselves in the foot by setting
				// this config property to a non-unique value
				col.id = yuid;
			}
			if (col.field) {
				// Field is now known as "name" to avoid confusion with data
				// fields or schema.resultFields
				col.name = col.field;
			}

			if (parent) {
				col._parent = parent;
			} else {
				delete col._parent;
			}

			// Unique id based on the column's configured name or key,
			// falling back to the yuid.  Duplicates will have a counter
			// added to the end.
			col._id = genId(col.name || col.key || col.id);

			if (isArray(col.children)) {
				col.children = process(col.children, col);
			}
		}

		return columns;
	}

	return val && process(val);
};<|endoftext|>


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

  var app = angular.module('viewCustom', ['angularLoad']);

  app.run(['$rootScope', '$location', '$window', function ($rootScope, $location, $window) {
    //record GA page view event to new primo tracker GA ID
    $rootScope.$on('$locationChangeSuccess', function (event) {
      //temporarily create a tracker specifically to new Primo
      if ($window.ga) {
        $window.ga(function () {
          $window.ga('create', 'UA-4365437-14', 'search.library.uq.edu.au', 'NewPrimoTracker');
        });
        $window.ga('NewPrimoTracker.send', 'pageview', { location: $location.url() });
      }
    });

  }]);

  var branchName = '/'; // default. Use for prod
  if (window.location.hostname === 'search.library.uq.edu.au') {
    if (/vid=61UQ_DEV/.test(window.location.href)) {
      branchName = '/primo-prod-dev/';
    }
  } else {
    if (/vid=61UQ_DEV/.test(window.location.href)) {
      branchName = '/primo-sand-box-dev/';
    } else if (/vid=61UQ/.test(window.location.href)) {
      branchName = '/primo-sand-box/';
    }
  }

  // we found it was more robust to always insert the askus button with javascript, so completely skip "by attribute"
  var newTemplate = '<uq-header hideLibraryMenuItem="true" searchLabel="library.uq.edu.au" searchURL="http://library.uq.edu.au"></uq-header>' +
      '<uq-site-header hideMyLibrary hideAskUs></uq-site-header>';
  var oldTemplate = '
<uqlibrary-alerts></uqlibrary-alerts>
' +
      '
<uq-minimal-header show-login-button="false"></uq-minimal-header>
';

  var libraryTemplate = (branchName === '/primo-prod-dev/') ? newTemplate : oldTemplate;
  app.component('prmTopBarBefore', {
    template: libraryTemplate
  });

  app.component('prmSearchBookmarkFilterAfter', {
    controller: function($scope){
      // move the primo-login-bar up so it overlaps uq-site-header and is visually one bar
      const primoLoginBar = document.querySelector('prm-topbar>div.top-nav-bar.layout-row') || false;
      !!primoLoginBar && (primoLoginBar.style.marginTop = '-61px');
    },
    template: '<askus-button nopaneopacity></askus-button>'
  });

  // based on https://knowledge.exlibrisgroup.com/Primo/Community_Knowledge/How_to_create_a_%E2%80%98Report_a_Problem%E2%80%99_button_below_the_ViewIt_iframe
  app.component('prmFullViewServiceContainerAfter', {
    bindings: {parentCtrl: '<'},
    controller: function($scope){
      var vm = this;

      vm.targeturl = '';

      var recordId = '';
      // no one knows what the TN actually means (per SVG), but in practice all the CDI records have it on their record id
      if (!!vm.parentCtrl.item.pnx && !!vm.parentCtrl.item.pnx.control && !!vm.parentCtrl.item.pnx.control.recordid &&
          vm.parentCtrl.item.pnx.control.recordid[0] && vm.parentCtrl.item.pnx.control.recordid[0].startsWith('TN')) {
        recordId = encodeURIComponent(vm.parentCtrl.item.pnx.control.recordid);
      }
      if (recordId === '') {
        if (!!vm.parentCtrl.item.pnx && !!vm.parentCtrl.item.pnx.search && !!vm.parentCtrl.item.pnx.search.recordid) {
          recordId = encodeURIComponent(vm.parentCtrl.item.pnx.search.recordid);
        }
      }
      if (recordId === '') {
        // from http://stackoverflow.com/questions/11582512/how-to-get-url-parameters-with-javascript/11582513#11582513
        var fieldname = 'docid';
        var temp = encodeURIComponent((new RegExp('[?|&]' + fieldname + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [null, ''])[1].replace(/\+/g, '%20')) || null;
        if (temp !== null) {
          recordId = temp;
        }
      }

      var recordTitle = '';
      if (recordId !== '' && !!vm.parentCtrl.item.pnx && !!vm.parentCtrl.item.pnx.search && !!vm.parentCtrl.item.pnx.search.title && !!vm.parentCtrl.item.pnx.search.title[0]) {
        recordTitle = encodeURIComponent(vm.parentCtrl.item.pnx.search.title[0]);
      }
      if (recordTitle === '' && recordId !== '' && !!vm.parentCtrl.item.pnx && !!vm.parentCtrl.item.pnx.display && !!vm.parentCtrl.item.pnx.display.title && !!vm.parentCtrl.item.pnx.display.title[0]) {
        recordTitle = encodeURIComponent(vm.parentCtrl.item.pnx.display.title[0]);
      }
      if (recordTitle !== '') {
        var maxNumberCharCRMCanAccept = 239;
        recordTitle = recordTitle.trim().substring(0, maxNumberCharCRMCanAccept);
      }

      var isIE11 = navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > -1;

      // if we are not IE11 and can get a docid and a title - add a button
      if (!isIE11 && recordId !== '' && recordTitle !== '') {
        var crmDomain = 'https://uqcurrent--tst1.custhelp.com'; // we can probably return the live url for all when this is in prod
        if (window.location.hostname === 'search.library.uq.edu.au') {
          crmDomain = 'https://support.my.uq.edu.au';
        }

        vm.targeturl = crmDomain + "/app/library/contact/report_problem/true/incidents.subject/" + recordTitle + "/incidents.c$summary/" + recordId;
      }
    },
    template : '
<getit-link-service>' +
        '<button class="help-button md-button md-primoExplore-theme md-ink-ripple" type="button" data-ng-click="buttonPressed($event)" aria-label="Report a Problem" aria-hidden="false">' +
        'Report a Problem' +
        '</button>' +
        '</getit-link-service>
'
  });

  /****************************************************************************************************/

  /*In case of CENTRAL_PACKAGE - comment out the below line to replace the other module definition*/

  /*var app = angular.module('centralCustom', ['angularLoad']);*/

  /****************************************************************************************************/

  // if the record is one of certain types, the 'Available Online' link should open View It, instead of jumping straight to the resource
  // (this is because there are usually multiple resources, and the default one may not be the best)
  app.controller('prmOpenSpecificTypesInFullController', [
    function () {
      var vm = this;
      vm.$onInit = function () {
        var resourceType = (!!vm.parentCtrl.result && !!vm.parentCtrl.result.pnx && !!vm.parentCtrl.result.pnx.display &&
            !!vm.parentCtrl.result.pnx.display.type && vm.parentCtrl.result.pnx.display.type.length > 0 &&
            vm.parentCtrl.result.pnx.display.type[0]) || '';
        if (resourceType === 'journal' || resourceType === 'newspaper') {
          vm.parentCtrl.isDirectLink = function () { return false; };
        }
      };
    }
  ]);
  app.component('prmOpenSpecificTypesInFull', {
    bindings: { parentCtrl: '<' },
    controller: 'prmOpenSpecificTypesInFullController'
  });
  app.component('prmSearchResultAvailabilityLineAfter', {
    bindings: { parentCtrl: '<' },
    template: '<prm-open-specific-types-in-full parent-ctrl="$ctrl.parentCtrl"></prm-open-specific-types-in-full>'
  });

  function insertScript(url) {
    var script = document.querySelector("script[src*='" + url + "']");
    if (!script) {
      var heads = document.getElementsByTagName("head");
      if (heads && heads.length) {
        var head = heads[0];
        if (head) {
          script = document.createElement('script');
          script.setAttribute('src', url);
          script.setAttribute('type', 'text/javascript');
          head.appendChild(script);
        }
      }
    }
  }

  function insertLink(link) {
    var linkTag = document.querySelector("link[href*='" + link.href + "']");
    if (!linkTag) {
      var heads = document.getElementsByTagName("head");
      if (heads && heads.length) {
        var head = heads[0];
        if (head) {
          linkTag = document.createElement('link');
          linkTag.setAttribute('href', link.href);
          linkTag.setAttribute('rel', link.rel);
          head.appendChild(linkTag);
        }
      }
    }
  }

  // this script should only be called on views that have UQ header showing
  if (branchName === '/primo-prod-dev/') {
    insertScript('https://homepage-development.library.uq.edu.au/feature-leadegroot-1/test-web-components/uq-lib-reusable.min.js');
    insertLink({
      rel: 'stylesheet',
      href: '//assets.library.uq.edu.au' + branchName + 'reusable-components/primo2/custom-styles.css'
    });
  } else {
    var links = [
      {rel: 'import', href: '//assets.library.uq.edu.au' + branchName + 'reusable-components/elements.vulcanized.html'},
      {
        rel: 'stylesheet',
        href: '//assets.library.uq.edu.au' + branchName + 'reusable-components/primo2/custom-styles.css'
      }
    ];
    insertLink(links[0]);
    insertLink(links[1]);

    var scripts = [
      '//assets.library.uq.edu.au' + branchName + 'reusable-components/webcomponentsjs/webcomponents-lite.min.js',
      '//assets.library.uq.edu.au' + branchName + 'reusable-components/resources/preloader.js',
      '//assets.library.uq.edu.au' + branchName + 'reusable-components/primo2/load.js',
    ];
    insertScript(scripts[0]);
    insertScript(scripts[1]);
    insertScript(scripts[2]);
  }
})();
<commit_msg>control which branches get which template [PT #177032832]<commit_after>(function () {
  "use strict";

  var app = angular.module('viewCustom', ['angularLoad']);

  app.run(['$rootScope', '$location', '$window', function ($rootScope, $location, $window) {
    //record GA page view event to new primo tracker GA ID
    $rootScope.$on('$locationChangeSuccess', function (event) {
      //temporarily create a tracker specifically to new Primo
      if ($window.ga) {
        $window.ga(function () {
          $window.ga('create', 'UA-4365437-14', 'search.library.uq.edu.au', 'NewPrimoTracker');
        });
        $window.ga('NewPrimoTracker.send', 'pageview', { location: $location.url() });
      }
    });

  }]);

  // we found it was more robust to always insert the askus button with javascript, so completely skip "by attribute"
  var newTemplate = '<uq-header hideLibraryMenuItem="true" searchLabel="library.uq.edu.au" searchURL="http://library.uq.edu.au"></uq-header>' +
      '<uq-site-header hideMyLibrary hideAskUs></uq-site-header>';
  var oldTemplate = '
<uqlibrary-alerts></uqlibrary-alerts>
' +
      '
<uq-minimal-header show-login-button="false"></uq-minimal-header>
';

  var branchName = '/'; // default. Use for prod
  var libraryTemplate = oldTemplate;
  if (window.location.hostname === 'search.library.uq.edu.au') {
    if (/vid=61UQ_DEV/.test(window.location.href)) {
      branchName = '/primo-prod-dev/';
      libraryTemplate = newTemplate;
    }
  } else {
    if (/vid=61UQ_DEV/.test(window.location.href)) {
      branchName = '/primo-sand-box-dev/';
    } else if (/vid=61UQ/.test(window.location.href)) {
      branchName = '/primo-sand-box/';
      libraryTemplate = newTemplate;
    }
  }

  app.component('prmTopBarBefore', {
    template: libraryTemplate
  });

  app.component('prmSearchBookmarkFilterAfter', {
    controller: function($scope){
      // move the primo-login-bar up so it overlaps uq-site-header and is visually one bar
      const primoLoginBar = document.querySelector('prm-topbar>div.top-nav-bar.layout-row') || false;
      !!primoLoginBar && (primoLoginBar.style.marginTop = '-61px');
    },
    template: '<askus-button nopaneopacity></askus-button>'
  });

  // based on https://knowledge.exlibrisgroup.com/Primo/Community_Knowledge/How_to_create_a_%E2%80%98Report_a_Problem%E2%80%99_button_below_the_ViewIt_iframe
  app.component('prmFullViewServiceContainerAfter', {
    bindings: {parentCtrl: '<'},
    controller: function($scope){
      var vm = this;

      vm.targeturl = '';

      var recordId = '';
      // no one knows what the TN actually means (per SVG), but in practice all the CDI records have it on their record id
      if (!!vm.parentCtrl.item.pnx && !!vm.parentCtrl.item.pnx.control && !!vm.parentCtrl.item.pnx.control.recordid &&
          vm.parentCtrl.item.pnx.control.recordid[0] && vm.parentCtrl.item.pnx.control.recordid[0].startsWith('TN')) {
        recordId = encodeURIComponent(vm.parentCtrl.item.pnx.control.recordid);
      }
      if (recordId === '') {
        if (!!vm.parentCtrl.item.pnx && !!vm.parentCtrl.item.pnx.search && !!vm.parentCtrl.item.pnx.search.recordid) {
          recordId = encodeURIComponent(vm.parentCtrl.item.pnx.search.recordid);
        }
      }
      if (recordId === '') {
        // from http://stackoverflow.com/questions/11582512/how-to-get-url-parameters-with-javascript/11582513#11582513
        var fieldname = 'docid';
        var temp = encodeURIComponent((new RegExp('[?|&]' + fieldname + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [null, ''])[1].replace(/\+/g, '%20')) || null;
        if (temp !== null) {
          recordId = temp;
        }
      }

      var recordTitle = '';
      if (recordId !== '' && !!vm.parentCtrl.item.pnx && !!vm.parentCtrl.item.pnx.search && !!vm.parentCtrl.item.pnx.search.title && !!vm.parentCtrl.item.pnx.search.title[0]) {
        recordTitle = encodeURIComponent(vm.parentCtrl.item.pnx.search.title[0]);
      }
      if (recordTitle === '' && recordId !== '' && !!vm.parentCtrl.item.pnx && !!vm.parentCtrl.item.pnx.display && !!vm.parentCtrl.item.pnx.display.title && !!vm.parentCtrl.item.pnx.display.title[0]) {
        recordTitle = encodeURIComponent(vm.parentCtrl.item.pnx.display.title[0]);
      }
      if (recordTitle !== '') {
        var maxNumberCharCRMCanAccept = 239;
        recordTitle = recordTitle.trim().substring(0, maxNumberCharCRMCanAccept);
      }

      var isIE11 = navigator.userAgent.indexOf('MSIE') !== -1 || navigator.appVersion.indexOf('Trident/') > -1;

      // if we are not IE11 and can get a docid and a title - add a button
      if (!isIE11 && recordId !== '' && recordTitle !== '') {
        var crmDomain = 'https://uqcurrent--tst1.custhelp.com'; // we can probably return the live url for all when this is in prod
        if (window.location.hostname === 'search.library.uq.edu.au') {
          crmDomain = 'https://support.my.uq.edu.au';
        }

        vm.targeturl = crmDomain + "/app/library/contact/report_problem/true/incidents.subject/" + recordTitle + "/incidents.c$summary/" + recordId;
      }
    },
    template : '
<getit-link-service>' +
        '<button class="help-button md-button md-primoExplore-theme md-ink-ripple" type="button" data-ng-click="buttonPressed($event)" aria-label="Report a Problem" aria-hidden="false">' +
        'Report a Problem' +
        '</button>' +
        '</getit-link-service>
'
  });

  /****************************************************************************************************/

  /*In case of CENTRAL_PACKAGE - comment out the below line to replace the other module definition*/

  /*var app = angular.module('centralCustom', ['angularLoad']);*/

  /****************************************************************************************************/

  // if the record is one of certain types, the 'Available Online' link should open View It, instead of jumping straight to the resource
  // (this is because there are usually multiple resources, and the default one may not be the best)
  app.controller('prmOpenSpecificTypesInFullController', [
    function () {
      var vm = this;
      vm.$onInit = function () {
        var resourceType = (!!vm.parentCtrl.result && !!vm.parentCtrl.result.pnx && !!vm.parentCtrl.result.pnx.display &&
            !!vm.parentCtrl.result.pnx.display.type && vm.parentCtrl.result.pnx.display.type.length > 0 &&
            vm.parentCtrl.result.pnx.display.type[0]) || '';
        if (resourceType === 'journal' || resourceType === 'newspaper') {
          vm.parentCtrl.isDirectLink = function () { return false; };
        }
      };
    }
  ]);
  app.component('prmOpenSpecificTypesInFull', {
    bindings: { parentCtrl: '<' },
    controller: 'prmOpenSpecificTypesInFullController'
  });
  app.component('prmSearchResultAvailabilityLineAfter', {
    bindings: { parentCtrl: '<' },
    template: '<prm-open-specific-types-in-full parent-ctrl="$ctrl.parentCtrl"></prm-open-specific-types-in-full>'
  });

  function insertScript(url) {
    var script = document.querySelector("script[src*='" + url + "']");
    if (!script) {
      var heads = document.getElementsByTagName("head");
      if (heads && heads.length) {
        var head = heads[0];
        if (head) {
          script = document.createElement('script');
          script.setAttribute('src', url);
          script.setAttribute('type', 'text/javascript');
          head.appendChild(script);
        }
      }
    }
  }

  function insertLink(link) {
    var linkTag = document.querySelector("link[href*='" + link.href + "']");
    if (!linkTag) {
      var heads = document.getElementsByTagName("head");
      if (heads && heads.length) {
        var head = heads[0];
        if (head) {
          linkTag = document.createElement('link');
          linkTag.setAttribute('href', link.href);
          linkTag.setAttribute('rel', link.rel);
          head.appendChild(linkTag);
        }
      }
    }
  }

  // this script should only be called on views that have UQ header showing
  if (libraryTemplate === newTemplate) {
    insertScript('https://homepage-development.library.uq.edu.au/feature-leadegroot-1/test-web-components/uq-lib-reusable.min.js');
    insertLink({
      rel: 'stylesheet',
      href: '//assets.library.uq.edu.au' + branchName + 'reusable-components/primo2/custom-styles.css'
    });
  } else {
    var links = [
      {rel: 'import', href: '//assets.library.uq.edu.au' + branchName + 'reusable-components/elements.vulcanized.html'},
      {
        rel: 'stylesheet',
        href: '//assets.library.uq.edu.au' + branchName + 'reusable-components/primo2/custom-styles.css'
      }
    ];
    insertLink(links[0]);
    insertLink(links[1]);

    var scripts = [
      '//assets.library.uq.edu.au' + branchName + 'reusable-components/webcomponentsjs/webcomponents-lite.min.js',
      '//assets.library.uq.edu.au' + branchName + 'reusable-components/resources/preloader.js',
      '//assets.library.uq.edu.au' + branchName + 'reusable-components/primo2/load.js',
    ];
    insertScript(scripts[0]);
    insertScript(scripts[1]);
    insertScript(scripts[2]);
  }
})();
<|endoftext|>