<commit_before>'use strict';
(function(module) {
  try {
    module = angular.module('tink.interactivetable');
  } catch (e) {
    module = angular.module('tink.interactivetable', ['tink.popover','tink.sorttable','tink.tooltip','tink.safeApply']);
  }
  module.directive('tinkInteractiveTable',['$compile',function($compile){
    return{
      restrict:'EA',
      priority: 1500.1,
      compile: function compile(tElement, tAttrs) {
        $(tElement.find('thead tr')[0]).prepend($('
<input type="checkbox" ng-click="$parent.$parent.checkAll($event)" ng-class="{indeterminate:true}"  ng-model="$parent.$parent.allChecked" indeterminate id="{{$id}}-all" name="{{$id}}-all" value="">
	'));
        var td = $('<input type="checkbox" ng-change="checkChange(tinkData[$index])" ng-model="tinkData[$index].checked" id="{{$id}}-{{$index}}" name="{{$id}}-{{$index}}" value="">	');
        $(tElement.find('tbody tr')[0]).prepend(td);
        tAttrs._tr = $(tElement.find('tbody tr')[0]).clone();
        return {
          pre:function preLing(scope,elm,attr){
            $(tElement.find('tbody tr')[0]).prepend($('o	'));
          },
          post:function postLink(scope,elm,attr){
            scope._tr = attr._tr;
            scope.prevent = function($event){
              $event.stopPropagation();
            };
          }
        };
      }
    };
  }]);
    module.controller('interactiveCtrl', ['$scope','$attrs','$element','$compile', function($scope,$attrs,$element,$compile) {
        var ctrl = this;
        var tr = null;

        ctrl.replaceBody = function(tr){
          var tbody = $element.find('tbody');
          tbody.html('')
          //var td = $('
{{this.$parent}}1
<input type="checkbox" ng-change="$scope.child.checkChange($scope.child.tinkData[$index])" ng-model="$scope.child.tinkData[$index].checked" id="{{$id}}-{{$index}}" name="{{$id}}-{{$index}}" value="">	');
          tbody.append($attrs._tr.clone());
          //$(tbody.find('tr:first td:first')).replaceWith(td);

        ///  //$compile(td)($scope);
         // tbody.find('tr').append($('{{tinkData}}	'))
          //console.log(tbody.find('td:not(:last)'))

        //  $compile(tbody.find('td:last'))($scope);
          $compile(tbody.find('tr'))($scope);
        };

        ctrl.changeColumn = function(a,b){
          a+=1;
          b+=1;
          ctrl.swapTds(a,b);
          ctrl.replaceBody($attrs._tr);
        };

        ctrl.swapTds = function(a,b){
          var td1 = $attrs._tr.find('td:eq('+a+')'); // indices are zero-based here
          var td2 = $attrs._tr.find('td:eq('+b+')');
          if(a  b){
            td1.detach().insertBefore(td2);
          }
        };
      }])
  module.directive('tinkInteractiveTable',['$compile','$rootScope','safeApply',function($compile,$rootScope,safeApply){
    return{
      restrict:'EA',
      transclude:true,
      priority: 1500,
      replace:true,
      scope:{
        tinkData:'=',
        tinkHeaders:'=',
        initAllChecked:'=',
        tinkActions:'='
      },
      controller:'interactiveCtrl',
      templateUrl:'templates/reorder.html',
      compile: function compile(tElement, tAttrs) {

        return {
          pre: function preLink(scope, iElement, iAttrs, controller,transclude) {

          },
          post: function postLink(scope, iElement, iAttrs, controller) {
            /*stuff actions*/
            scope.actionConf = {};
            $compile(iElement.find('tbody tr'))(scope);
            var breakpoint = {};
            breakpoint.refreshValue = function () {
              var screenSize = window.getComputedStyle(document.querySelector('body'), ':before').getPropertyValue('content').replace(/\'/g, '')
              if(screenSize !== 'wide-xl-view'){
                scope.actionConf.tekst = false;
              }else{
                scope.actionConf.tekst = true;
              }
              if(screenSize === 'smartphone-view'){
                scope.actionConf.menu = true;
              }else{
                scope.actionConf.menu = false;
              }
            };
            $(window).resize(function () {
              safeApply(scope,function(){
                breakpoint.refreshValue();
              })
            }).resize();

            /*end actions*/
            scope.selected = -1;
            //If you select an other kolom name in de kolumn popup this function will be fired.
            scope.select = function(e,index){
              //Prevent the default to disable checkbox behaviour.
              e.preventDefault();
              //Changed the selected index.
              scope.selected = index;
            };
            scope.allChecked = false;

            scope.actionCallBack = function(c){
              var array = $.grep(scope.tinkData, function( a ) {
                return a.checked;
              });
              if(c.callback instanceof Function){
                c.callback(array);
              }

              scope.close();
            }

            scope.close = function(){
              $rootScope.$broadcast('popover-open', { group: 'option-table',el:$('

') });
            }

            scope.checkAll = function($event){
              var array = $.grep(scope.tinkData, function( a ) {
                return a.checked;
              });
              if(array.length === scope.tinkData.length){
                for (var i = 0, len = scope.tinkData.length; i < len; i++) {
                  scope.tinkData[i].checked = false;
                }
                scope.allChecked = false;
              }else{
                for (var i = 0, len = scope.tinkData.length; i < len; i++) {
                  scope.tinkData[i].checked = true;
                }
                scope.allChecked = true;
              }

            }
            scope.checked = function(){
              return $.grep(scope.tinkData, function( a ) {
                return a.checked;
              });
            }
            scope.checkChange = function(check){
              var array = $.grep(scope.tinkData, function( a ) {
                return a.checked;
              });
              if(array.length === scope.tinkData.length){
                scope.allChecked = true;
              }else if(array.length === 0 ){
                scope.allChecked = false;
              }else{
                scope.allChecked = false;
              }
            }

            scope.switchPosition = function(a,b){
              scope.tinkHeaders.swap(a,b);
              controller.changeColumn(a,b);
            }

            scope.hasActions = function(){
              if(scope.tinkActions !== undefined || scope.tinkActions !== null){
                if(scope.tinkActions instanceof Array && scope.tinkActions.length > 0){
                  return true;
                }
              }
              return false;
            }

            //function will be called when pressing arrow for order change
            scope.arrowUp = function(){
              if(scope.selected > 0){
                scope.switchPosition(scope.selected,scope.selected-1);
                scope.selected-=1;
              }
            };
            //function will be called when pressing arrow for order change
            scope.arrowDown = function(){
              if(scope.selected < scope.tinkHeaders.length-1){
                scope.switchPosition(scope.selected,scope.selected+1);
                scope.selected+=1;
              }
            };

            //added this to swap elements easly
            Array.prototype.swap = function(a, b) {
              var temp = this[a];
              this[a] = this[b];
              this[b] = temp;
            };

          }
        }
      }
    };
  }])
.filter('tinkActionFilter',['$filter',function($filter) {

  // In the return function, we must pass in a single parameter which will be the data we will work on.
  // We have the ability to support multiple other parameters that can be passed into the filter optionally
  return function(input, optional1, optional2) {
    var output;

    var master = $filter('filter')(optional1, {master: true});
    var sub = $filter('filter')(optional1, {master: false});

    if(optional2 === 'master'){
      if(master.length < 5){
        return input;
      }else{
        return input.slice(0,5);
      }
    }else{
      if(master.length >=5){
        return [];
      }else{
        return input.slice(0,5-master.length);
      }
    }
    return output;

  }

}])
.filter('tinkSlice', function() {
  return function(arr, start) {
    return (arr || []).slice(start);
  };
})
.directive('tinkShiftSort',['$timeout',function(timeout){
  return {
    restirct:'A',
    controller:'interactiveCtrl',
    link:function(scope,elem,attr,ctrl){
      timeout(function(){
        Sortable.create(elem.find('ul').get(0),{
          ghostClass: 'draggable-placeholder',
          animation: 200,
          handle:'.draggable-elem',
          onStart: function (evt) {
             scope.$apply(function(){
              scope.selected = evt.oldIndex;
            });
          },
          onUpdate: function (evt) {
            scope.$apply(function(){
              var oldIndex = evt.oldIndex;
              var newIndex = evt.newIndex;
              scope.switchPosition(oldIndex,newIndex);
            });
          },
        });
      },200);
    }
  };
}]);
})();
<commit_msg>working with checkboxe<commit_after>'use strict';
(function(module) {
  try {
    module = angular.module('tink.interactivetable');
  } catch (e) {
    module = angular.module('tink.interactivetable', ['tink.popover','tink.sorttable','tink.tooltip','tink.safeApply']);
  }
  module.directive('tinkInteractiveTable',['$compile',function($compile){
    return{
      restrict:'EA',
      priority: 1500.1,
      compile: function compile(tElement, tAttrs) {
        $(tElement.find('thead tr')[0]).prepend($('
<input type="checkbox" ng-click="$parent.$parent.checkAll($event)" ng-class="{indeterminate:true}"  ng-model="$parent.$parent.allChecked" indeterminate id="{{$id}}-all" name="{{$id}}-all" value="">
	'));
        var td = $('<input type="checkbox" ng-change="checkChange(tinkData[$index])" ng-model="tinkData[$index].checked" id="{{$id}}-{{$index}}" name="{{$id}}-{{$index}}" value="">	');
        $(tElement.find('tbody tr')[0]).prepend(td);
        tAttrs._tr = $(tElement.find('tbody tr')[0]).clone();
        return {
          pre:function preLing(scope,elm,attr){
            $(tElement.find('tbody tr')[0]).prepend($('o	'));
          },
          post:function postLink(scope,elm,attr){
            scope._tr = attr._tr;
            scope.prevent = function($event){
              $event.stopPropagation();
            };
          }
        };
      }
    };
  }]);
    module.controller('interactiveCtrl', ['$scope','$attrs','$element','$compile', function($scope,$attrs,$element,$compile) {
        var ctrl = this;
        var tr = null;

        ctrl.replaceBody = function(tr){
          var tbody = $element.find('tbody');
          tbody.html('')
          //var td = $('
{{this.$parent}}1
<input type="checkbox" ng-change="$scope.child.checkChange($scope.child.tinkData[$index])" ng-model="$scope.child.tinkData[$index].checked" id="{{$id}}-{{$index}}" name="{{$id}}-{{$index}}" value="">	');
          tbody.append($attrs._tr.clone());
          //$(tbody.find('tr:first td:first')).replaceWith(td);

        ///  //$compile(td)($scope);
         // tbody.find('tr').append($('{{tinkData}}	'))
          //console.log(tbody.find('td:not(:last)'))

        //  $compile(tbody.find('td:last'))($scope);
          $compile(tbody)($scope);
        };

        ctrl.changeColumn = function(a,b){
          a+=1;
          b+=1;
          ctrl.swapTds(a,b);
          ctrl.replaceBody($attrs._tr);
        };

        ctrl.swapTds = function(a,b){
          var td1 = $attrs._tr.find('td:eq('+a+')'); // indices are zero-based here
          var td2 = $attrs._tr.find('td:eq('+b+')');
          if(a  b){
            td1.detach().insertBefore(td2);
          }
        };
      }])
  module.directive('tinkInteractiveTable',['$compile','$rootScope','safeApply',function($compile,$rootScope,safeApply){
    return{
      restrict:'EA',
      transclude:true,
      priority: 1500,
      replace:true,
      scope:{
        tinkData:'=',
        tinkHeaders:'=',
        initAllChecked:'=',
        tinkActions:'='
      },
      controller:'interactiveCtrl',
      templateUrl:'templates/reorder.html',
      compile: function compile(tElement, tAttrs) {

        return {
          pre: function preLink(scope, iElement, iAttrs, controller,transclude) {

          },
          post: function postLink(scope, iElement, iAttrs, controller) {
            /*stuff actions*/
            scope.actionConf = {};
           // $compile(iElement.find('tbody tr'))(scope);
            controller.replaceBody(iAttrs._tr);
            var breakpoint = {};
            breakpoint.refreshValue = function () {
              var screenSize = window.getComputedStyle(document.querySelector('body'), ':before').getPropertyValue('content').replace(/\'/g, '')
              if(screenSize !== 'wide-xl-view'){
                scope.actionConf.tekst = false;
              }else{
                scope.actionConf.tekst = true;
              }
              if(screenSize === 'smartphone-view'){
                scope.actionConf.menu = true;
              }else{
                scope.actionConf.menu = false;
              }
            };
            $(window).resize(function () {
              safeApply(scope,function(){
                breakpoint.refreshValue();
              })
            }).resize();

            /*end actions*/
            scope.selected = -1;
            //If you select an other kolom name in de kolumn popup this function will be fired.
            scope.select = function(e,index){
              //Prevent the default to disable checkbox behaviour.
              e.preventDefault();
              //Changed the selected index.
              scope.selected = index;
            };
            scope.allChecked = false;

            scope.actionCallBack = function(c){
              var array = $.grep(scope.tinkData, function( a ) {
                return a.checked;
              });
              if(c.callback instanceof Function){
                c.callback(array);
              }

              scope.close();
            }

            scope.close = function(){
              $rootScope.$broadcast('popover-open', { group: 'option-table',el:$('

') });
            }

            scope.checkAll = function($event){
              var array = $.grep(scope.tinkData, function( a ) {
                return a.checked;
              });
              if(array.length === scope.tinkData.length){
                for (var i = 0, len = scope.tinkData.length; i < len; i++) {
                  scope.tinkData[i].checked = false;
                }
                scope.allChecked = false;
              }else{
                for (var i = 0, len = scope.tinkData.length; i < len; i++) {
                  scope.tinkData[i].checked = true;
                }
                scope.allChecked = true;
              }

            }
            scope.checked = function(){
              return $.grep(scope.tinkData, function( a ) {
                return a.checked;
              });
            }
            scope.checkChange = function(check){
              var array = $.grep(scope.tinkData, function( a ) {
                return a.checked;
              });
              if(array.length === scope.tinkData.length){
                scope.allChecked = true;
              }else if(array.length === 0 ){
                scope.allChecked = false;
              }else{
                scope.allChecked = false;
              }
            }

            scope.switchPosition = function(a,b){
              scope.tinkHeaders.swap(a,b);
              controller.changeColumn(a,b);
            }

            scope.hasActions = function(){
              if(scope.tinkActions !== undefined || scope.tinkActions !== null){
                if(scope.tinkActions instanceof Array && scope.tinkActions.length > 0){
                  return true;
                }
              }
              return false;
            }

            //function will be called when pressing arrow for order change
            scope.arrowUp = function(){
              if(scope.selected > 0){
                scope.switchPosition(scope.selected,scope.selected-1);
                scope.selected-=1;
              }
            };
            //function will be called when pressing arrow for order change
            scope.arrowDown = function(){
              if(scope.selected < scope.tinkHeaders.length-1){
                scope.switchPosition(scope.selected,scope.selected+1);
                scope.selected+=1;
              }
            };

            //added this to swap elements easly
            Array.prototype.swap = function(a, b) {
              var temp = this[a];
              this[a] = this[b];
              this[b] = temp;
            };

          }
        }
      }
    };
  }])
.filter('tinkActionFilter',['$filter',function($filter) {

  // In the return function, we must pass in a single parameter which will be the data we will work on.
  // We have the ability to support multiple other parameters that can be passed into the filter optionally
  return function(input, optional1, optional2) {
    var output;

    var master = $filter('filter')(optional1, {master: true});
    var sub = $filter('filter')(optional1, {master: false});

    if(optional2 === 'master'){
      if(master.length < 5){
        return input;
      }else{
        return input.slice(0,5);
      }
    }else{
      if(master.length >=5){
        return [];
      }else{
        return input.slice(0,5-master.length);
      }
    }
    return output;

  }

}])
.filter('tinkSlice', function() {
  return function(arr, start) {
    return (arr || []).slice(start);
  };
})
.directive('tinkShiftSort',['$timeout',function(timeout){
  return {
    restirct:'A',
    controller:'interactiveCtrl',
    link:function(scope,elem,attr,ctrl){
      timeout(function(){
        Sortable.create(elem.find('ul').get(0),{
          ghostClass: 'draggable-placeholder',
          animation: 200,
          handle:'.draggable-elem',
          onStart: function (evt) {
             scope.$apply(function(){
              scope.selected = evt.oldIndex;
            });
          },
          onUpdate: function (evt) {
            scope.$apply(function(){
              var oldIndex = evt.oldIndex;
              var newIndex = evt.newIndex;
              scope.switchPosition(oldIndex,newIndex);
            });
          },
        });
      },200);
    }
  };
}]);
})();
<|endoftext|>


<commit_before>// API calls in this file :
// - declare_page
// - store.set_webentity_homepage
// - store.rename_webentity
// - store.declare_webentity_by_lruprefix_as_url
// - store.set_webentity_status
// - crawl_webentity (webentity_id, depth = 0, phantom_crawl = false, status = 'IN', phantom_timeouts = {}, corpus = '--hyphe--')

import jsonrpc from '../utils/jsonrpc'

import { CRAWL_DEPTH } from '../constants'
import { createAction } from 'redux-actions'

// adding a page to corpus
export const DECLARE_PAGE_REQUEST = '§_DECLARE_PAGE_REQUEST'
export const DECLARE_PAGE_SUCCESS = '§_DECLARE_PAGE_SUCCESS'
export const DECLARE_PAGE_FAILURE = '§_DECLARE_PAGE_FAILURE'

// setting webentity's homepage
export const SET_WEBENTITY_HOMEPAGE_REQUEST = '§_SET_WEBENTITY_HOMEPAGE_REQUEST'
export const SET_WEBENTITY_HOMEPAGE_SUCCESS = '§_SET_WEBENTITY_HOMEPAGE_SUCCESS'
export const SET_WEBENTITY_HOMEPAGE_FAILURE = '§_SET_WEBENTITY_HOMEPAGE_FAILURE'

// setting webentity's name
export const SET_WEBENTITY_NAME_REQUEST = '§_SET_WEBENTITY_NAME_REQUEST'
export const SET_WEBENTITY_NAME_SUCCESS = '§_SET_WEBENTITY_NAME_SUCCESS'
export const SET_WEBENTITY_NAME_FAILURE = '§_SET_WEBENTITY_NAME_FAILURE'

// setting webentity's status
export const SET_WEBENTITY_STATUS_REQUEST = '§_SET_WEBENTITY_STATUS_REQUEST'
export const SET_WEBENTITY_STATUS_SUCCESS = '§_SET_WEBENTITY_STATUS_SUCCESS'
export const SET_WEBENTITY_STATUS_FAILURE = '§_SET_WEBENTITY_STATUS_FAILURE'

export const SET_WEBENTITY_CRAWLING_STATUS = '§_SET_WEBENTITY_CRAWLING_STATUS'

// creating webentity
export const CREATE_WEBENTITY_REQUEST = '§_CREATE_WEBENTITY_REQUEST'
export const CREATE_WEBENTITY_SUCCESS = '§_CREATE_WEBENTITY_SUCCESS'
export const CREATE_WEBENTITY_FAILURE = '§_CREATE_WEBENTITY_FAILURE'

// attaching a fetched webentity to an open tab
export const SET_TAB_WEBENTITY = '§_SET_TAB_WEBENTITY'

// adjust webentity
export const ADJUST_WEBENTITY = '§_ADJUST_WEBENTITY' // false => close, true => open with defaults, object => update fields
export const SAVE_ADJUSTED_WEBENTITY_REQUEST = '§_SAVE_ADJUSTED_WEBENTITY_REQUEST'
export const SAVE_ADJUSTED_WEBENTITY_SUCCESS = '§_SAVE_ADJUSTED_WEBENTITY_SUCCESS'
export const SAVE_ADJUSTED_WEBENTITY_FAILURE = '§_SAVE_ADJUSTED_WEBENTITY_FAILURE'

export const declarePage = (serverUrl, corpusId, url, tabId = null) => (dispatch) => {
  dispatch({ type: DECLARE_PAGE_REQUEST, payload: { serverUrl, corpusId, url } })

  return jsonrpc(serverUrl)('declare_page', [url, corpusId])
    .then(result => result.result || result ) // declare_page used to not return webentity directly but a { result } object, keep for backcompat
    /* webentity's homepage must be set manually by user
    .then((webentity) => {
      if (!webentity.homepage) {
        // Set homepage to requested URL if not defined yet
        return setWebentityHomepage(serverUrl, corpusId, url, webentity.id).then(() => {
          webentity.homepage = url
          return webentity
        })
      } else {
        return webentity
      }
    })
    */
    .then((webentity) => {
      dispatch({ type: DECLARE_PAGE_SUCCESS, payload: { serverUrl, corpusId, url, webentity } })
      if (tabId) {
        dispatch(setTabWebentity(tabId, webentity.id))
      }
      return webentity
    })
    .catch((error) => dispatch({ type: DECLARE_PAGE_FAILURE, payload: { serverUrl, corpusId, url, error } }))
}

export const setTabWebentity = createAction(SET_TAB_WEBENTITY, (tabId, webentityId) => ({ tabId, webentityId }))

export const setWebentityHomepage = (serverUrl, corpusId, homepage, webentityId) => (dispatch) => {
  dispatch({ type: SET_WEBENTITY_HOMEPAGE_REQUEST, payload: { serverUrl, corpusId, homepage, webentityId } })

  return jsonrpc(serverUrl)('store.set_webentity_homepage', [webentityId, homepage, corpusId])
    .then(() => dispatch({ type: SET_WEBENTITY_HOMEPAGE_SUCCESS, payload: { serverUrl, corpusId, homepage, webentityId } }))
    .catch((error) => {
      dispatch({ type: SET_WEBENTITY_HOMEPAGE_FAILURE, payload: { serverUrl, corpusId, homepage, webentityId, error } })
      throw error
    })
}

export const setWebentityName = (serverUrl, corpusId, name, webentityId) => (dispatch) => {
  dispatch({ type: SET_WEBENTITY_NAME_REQUEST, payload: { serverUrl, corpusId, name, webentityId } })

  return jsonrpc(serverUrl)('store.rename_webentity', [webentityId, name, corpusId])
    .then(() => dispatch({ type: SET_WEBENTITY_NAME_SUCCESS, payload: { serverUrl, corpusId, name, webentityId } }))
    .catch((error) => {
      dispatch({ type: SET_WEBENTITY_NAME_FAILURE, payload: { serverUrl, corpusId, name, webentityId, error } })
      throw error
    })
}

export const setWebentityStatus = (serverUrl, corpusId, status, webentityId) => (dispatch) => {
  dispatch({ type: SET_WEBENTITY_STATUS_REQUEST, payload: { serverUrl, corpusId, status, webentityId } })

  return jsonrpc(serverUrl)('store.set_webentity_status', [webentityId, status, corpusId])
    .then(() => dispatch({ type: SET_WEBENTITY_STATUS_SUCCESS, payload: { serverUrl, corpusId, status, webentityId } }))
    .catch((error) => {
      dispatch({ type: SET_WEBENTITY_STATUS_FAILURE, payload: { serverUrl, corpusId, status, webentityId, error } })
      throw error
    })
}

export const createWebentity = (serverUrl, corpusId, prefixUrl, name = null, homepage = null, tabId = null) => (dispatch) => {
  dispatch({ type: CREATE_WEBENTITY_REQUEST, payload: { serverUrl, corpusId, name, prefixUrl } })

  return jsonrpc(serverUrl)('store.declare_webentity_by_lruprefix_as_url', [prefixUrl, name, null, null, corpusId])
    .then((webentity) => {
      dispatch({ type: CREATE_WEBENTITY_SUCCESS, payload: { serverUrl, corpusId, webentity } })
      if (tabId) {
        dispatch(setTabWebentity(tabId, webentity.id))
      }
      return webentity
    })
    .then((webentity) => {
      if (homepage) {
        return dispatch(setWebentityHomepage(serverUrl, corpusId, homepage, webentity.id)).then(() => Object.assign(webentity, { homepage }))
      } else {
        return webentity
      }
    })
    .catch((error) => {
      dispatch({ type: CREATE_WEBENTITY_FAILURE, payload: { serverUrl, corpusId, name, prefixUrl, error } })
      throw error
    })
}

export const setAdjustWebentity = (webentityId, info) => ({ type: ADJUST_WEBENTITY, payload: { id: webentityId, info } })
export const showAdjustWebentity = (webentityId, crawl = false) => setAdjustWebentity(webentityId, { name: null, homepage: null, prefix: null, crawl })
export const hideAdjustWebentity = (webentityId) => setAdjustWebentity(webentityId, null)

export const saveAdjustedWebentity = (serverUrl, corpusId, webentity, adjust, tabId) => (dispatch) => {
  dispatch({ type: SAVE_ADJUSTED_WEBENTITY_SUCCESS, payload: { serverUrl, corpusId, adjust, webentity } })

  const { prefix, homepage, name, crawl } = adjust
  var operations = []

  if (prefix) {
    // Create a new web entity
    // Set its name and homepage at the same time + refresh tab by passing tab id
    operations.push(createWebentity(serverUrl, corpusId, prefix, name, homepage, tabId)(dispatch))
  } else {
    if (homepage && homepage !== webentity.homepage) {
      operations.push(setWebentityHomepage(serverUrl, corpusId, homepage, webentity.id)(dispatch))
    }
    if (name && name !== webentity.name) {
      operations.push(setWebentityName(serverUrl, corpusId, name, webentity.id)(dispatch))
    }
  }

  return Promise.all(operations)
    .then(([head]) => {
      if (crawl) {
        // if prefix, then webentity just been created, and we want this id, not the old one
        const id = prefix ? head.id : webentity.id
        const depth = CRAWL_DEPTH
        return jsonrpc(serverUrl)('crawl_webentity', [id, depth, false, 'IN', {}, corpusId])
          .then(() => {
            // Broadcast the information that webentity's status has been updated
            dispatch({ type: SET_WEBENTITY_STATUS_SUCCESS, payload: { serverUrl, corpusId, status: 'IN', webentityId: id } })
            dispatch({ type: SET_WEBENTITY_CRAWLING_STATUS, payload: { crawling_status: 'RUNNING', webentityId: id } })
          })
      }
    })
    .then(() => dispatch({ type: SAVE_ADJUSTED_WEBENTITY_SUCCESS, payload: { serverUrl, corpusId, adjust, webentity } }))
    .catch((error) => {
      dispatch({ type: SAVE_ADJUSTED_WEBENTITY_SUCCESS, payload: { serverUrl, corpusId, adjust, webentity, error } })
      throw error
    })
}
<commit_msg>follow api change<commit_after>// API calls in this file :
// - declare_page
// - store.set_webentity_homepage
// - store.rename_webentity
// - store.declare_webentity_by_lruprefix_as_url
// - store.set_webentity_status
// - crawl_webentity (webentity_id, depth = 0, phantom_crawl = false, status = 'IN', phantom_timeouts = {}, corpus = '--hyphe--')

import jsonrpc from '../utils/jsonrpc'

import { CRAWL_DEPTH } from '../constants'
import { createAction } from 'redux-actions'

// adding a page to corpus
export const DECLARE_PAGE_REQUEST = '§_DECLARE_PAGE_REQUEST'
export const DECLARE_PAGE_SUCCESS = '§_DECLARE_PAGE_SUCCESS'
export const DECLARE_PAGE_FAILURE = '§_DECLARE_PAGE_FAILURE'

// setting webentity's homepage
export const SET_WEBENTITY_HOMEPAGE_REQUEST = '§_SET_WEBENTITY_HOMEPAGE_REQUEST'
export const SET_WEBENTITY_HOMEPAGE_SUCCESS = '§_SET_WEBENTITY_HOMEPAGE_SUCCESS'
export const SET_WEBENTITY_HOMEPAGE_FAILURE = '§_SET_WEBENTITY_HOMEPAGE_FAILURE'

// setting webentity's name
export const SET_WEBENTITY_NAME_REQUEST = '§_SET_WEBENTITY_NAME_REQUEST'
export const SET_WEBENTITY_NAME_SUCCESS = '§_SET_WEBENTITY_NAME_SUCCESS'
export const SET_WEBENTITY_NAME_FAILURE = '§_SET_WEBENTITY_NAME_FAILURE'

// setting webentity's status
export const SET_WEBENTITY_STATUS_REQUEST = '§_SET_WEBENTITY_STATUS_REQUEST'
export const SET_WEBENTITY_STATUS_SUCCESS = '§_SET_WEBENTITY_STATUS_SUCCESS'
export const SET_WEBENTITY_STATUS_FAILURE = '§_SET_WEBENTITY_STATUS_FAILURE'

export const SET_WEBENTITY_CRAWLING_STATUS = '§_SET_WEBENTITY_CRAWLING_STATUS'

// creating webentity
export const CREATE_WEBENTITY_REQUEST = '§_CREATE_WEBENTITY_REQUEST'
export const CREATE_WEBENTITY_SUCCESS = '§_CREATE_WEBENTITY_SUCCESS'
export const CREATE_WEBENTITY_FAILURE = '§_CREATE_WEBENTITY_FAILURE'

// attaching a fetched webentity to an open tab
export const SET_TAB_WEBENTITY = '§_SET_TAB_WEBENTITY'

// adjust webentity
export const ADJUST_WEBENTITY = '§_ADJUST_WEBENTITY' // false => close, true => open with defaults, object => update fields
export const SAVE_ADJUSTED_WEBENTITY_REQUEST = '§_SAVE_ADJUSTED_WEBENTITY_REQUEST'
export const SAVE_ADJUSTED_WEBENTITY_SUCCESS = '§_SAVE_ADJUSTED_WEBENTITY_SUCCESS'
export const SAVE_ADJUSTED_WEBENTITY_FAILURE = '§_SAVE_ADJUSTED_WEBENTITY_FAILURE'

export const declarePage = (serverUrl, corpusId, url, tabId = null) => (dispatch) => {
  dispatch({ type: DECLARE_PAGE_REQUEST, payload: { serverUrl, corpusId, url } })

  return jsonrpc(serverUrl)('declare_page', [url, corpusId])
    .then(result => result.result || result ) // declare_page used to not return webentity directly but a { result } object, keep for backcompat
    /* webentity's homepage must be set manually by user
    .then((webentity) => {
      if (!webentity.homepage) {
        // Set homepage to requested URL if not defined yet
        return setWebentityHomepage(serverUrl, corpusId, url, webentity.id).then(() => {
          webentity.homepage = url
          return webentity
        })
      } else {
        return webentity
      }
    })
    */
    .then((webentity) => {
      dispatch({ type: DECLARE_PAGE_SUCCESS, payload: { serverUrl, corpusId, url, webentity } })
      if (tabId) {
        dispatch(setTabWebentity(tabId, webentity.id))
      }
      return webentity
    })
    .catch((error) => dispatch({ type: DECLARE_PAGE_FAILURE, payload: { serverUrl, corpusId, url, error } }))
}

export const setTabWebentity = createAction(SET_TAB_WEBENTITY, (tabId, webentityId) => ({ tabId, webentityId }))

export const setWebentityHomepage = (serverUrl, corpusId, homepage, webentityId) => (dispatch) => {
  dispatch({ type: SET_WEBENTITY_HOMEPAGE_REQUEST, payload: { serverUrl, corpusId, homepage, webentityId } })

  return jsonrpc(serverUrl)('store.set_webentity_homepage', [webentityId, homepage, corpusId])
    .then(() => dispatch({ type: SET_WEBENTITY_HOMEPAGE_SUCCESS, payload: { serverUrl, corpusId, homepage, webentityId } }))
    .catch((error) => {
      dispatch({ type: SET_WEBENTITY_HOMEPAGE_FAILURE, payload: { serverUrl, corpusId, homepage, webentityId, error } })
      throw error
    })
}

export const setWebentityName = (serverUrl, corpusId, name, webentityId) => (dispatch) => {
  dispatch({ type: SET_WEBENTITY_NAME_REQUEST, payload: { serverUrl, corpusId, name, webentityId } })

  return jsonrpc(serverUrl)('store.rename_webentity', [webentityId, name, corpusId])
    .then(() => dispatch({ type: SET_WEBENTITY_NAME_SUCCESS, payload: { serverUrl, corpusId, name, webentityId } }))
    .catch((error) => {
      dispatch({ type: SET_WEBENTITY_NAME_FAILURE, payload: { serverUrl, corpusId, name, webentityId, error } })
      throw error
    })
}

export const setWebentityStatus = (serverUrl, corpusId, status, webentityId) => (dispatch) => {
  dispatch({ type: SET_WEBENTITY_STATUS_REQUEST, payload: { serverUrl, corpusId, status, webentityId } })

  return jsonrpc(serverUrl)('store.set_webentity_status', [webentityId, status, corpusId])
    .then(() => dispatch({ type: SET_WEBENTITY_STATUS_SUCCESS, payload: { serverUrl, corpusId, status, webentityId } }))
    .catch((error) => {
      dispatch({ type: SET_WEBENTITY_STATUS_FAILURE, payload: { serverUrl, corpusId, status, webentityId, error } })
      throw error
    })
}

export const createWebentity = (serverUrl, corpusId, prefixUrl, name = null, homepage = null, tabId = null) => (dispatch) => {
  dispatch({ type: CREATE_WEBENTITY_REQUEST, payload: { serverUrl, corpusId, name, prefixUrl } })

  return jsonrpc(serverUrl)('store.declare_webentity_by_lruprefix_as_url', [prefixUrl, name, null, null, true, corpusId])
    .then((webentity) => {
      dispatch({ type: CREATE_WEBENTITY_SUCCESS, payload: { serverUrl, corpusId, webentity } })
      if (tabId) {
        dispatch(setTabWebentity(tabId, webentity.id))
      }
      return webentity
    })
    .then((webentity) => {
      if (homepage) {
        return dispatch(setWebentityHomepage(serverUrl, corpusId, homepage, webentity.id)).then(() => Object.assign(webentity, { homepage }))
      } else {
        return webentity
      }
    })
    .catch((error) => {
      dispatch({ type: CREATE_WEBENTITY_FAILURE, payload: { serverUrl, corpusId, name, prefixUrl, error } })
      throw error
    })
}

export const setAdjustWebentity = (webentityId, info) => ({ type: ADJUST_WEBENTITY, payload: { id: webentityId, info } })
export const showAdjustWebentity = (webentityId, crawl = false) => setAdjustWebentity(webentityId, { name: null, homepage: null, prefix: null, crawl })
export const hideAdjustWebentity = (webentityId) => setAdjustWebentity(webentityId, null)

export const saveAdjustedWebentity = (serverUrl, corpusId, webentity, adjust, tabId) => (dispatch) => {
  dispatch({ type: SAVE_ADJUSTED_WEBENTITY_SUCCESS, payload: { serverUrl, corpusId, adjust, webentity } })

  const { prefix, homepage, name, crawl } = adjust
  var operations = []

  if (prefix) {
    // Create a new web entity
    // Set its name and homepage at the same time + refresh tab by passing tab id
    operations.push(createWebentity(serverUrl, corpusId, prefix, name, homepage, tabId)(dispatch))
  } else {
    if (homepage && homepage !== webentity.homepage) {
      operations.push(setWebentityHomepage(serverUrl, corpusId, homepage, webentity.id)(dispatch))
    }
    if (name && name !== webentity.name) {
      operations.push(setWebentityName(serverUrl, corpusId, name, webentity.id)(dispatch))
    }
  }

  return Promise.all(operations)
    .then(([head]) => {
      if (crawl) {
        // if prefix, then webentity just been created, and we want this id, not the old one
        const id = prefix ? head.id : webentity.id
        const depth = CRAWL_DEPTH
        return jsonrpc(serverUrl)('crawl_webentity', [id, depth, false, 'IN', {}, corpusId])
          .then(() => {
            // Broadcast the information that webentity's status has been updated
            dispatch({ type: SET_WEBENTITY_STATUS_SUCCESS, payload: { serverUrl, corpusId, status: 'IN', webentityId: id } })
            dispatch({ type: SET_WEBENTITY_CRAWLING_STATUS, payload: { crawling_status: 'RUNNING', webentityId: id } })
          })
      }
    })
    .then(() => dispatch({ type: SAVE_ADJUSTED_WEBENTITY_SUCCESS, payload: { serverUrl, corpusId, adjust, webentity } }))
    .catch((error) => {
      dispatch({ type: SAVE_ADJUSTED_WEBENTITY_SUCCESS, payload: { serverUrl, corpusId, adjust, webentity, error } })
      throw error
    })
}
<|endoftext|>


<commit_before>/**
 * Created by cristinaionescu on 26/01/2016.
 */
var MongoClient = require("vertx-mongo-js/mongo_client");

module.exports = MongoClientObj;

function MongoClientObj(host, port, dbName, poolname) {
    this.collectionName = null;
    this.mongoClient = MongoClient.createShared(vertx, {
        "connection_string": "mongodb://" + host + ":" + port,
        "db_name": dbName
    }, poolname);

    if ( this.mongoClient ) {
        console.log("Connected to MongoDB @ " + host + ":" + port + "/" + dbName);
    } else {
        throw "MongoClient could not be instantiated";
    }
};

MongoClientObj.prototype.saveObjectToDB = function(object, colName, cb) {
    var collectionName = colName ? colName : this.collectionName;

    this.mongoClient.save(collectionName, object, function (id, err) {
        if (!err && !id) {
            id = object._id;
        } else {
            console.log("ERR " + err);
        }
        cb(id, err);
    });
};

MongoClientObj.prototype.getDocumentsFromDB = function(query, colName, cb) {
    var collectionName = colName ? colName : this.collectionName;
    var queryResults = [];

    this.mongoClient.find(collectionName, query, function (res, res_err) {
        if (!res_err) {
            if (res.length > 0) {
                Array.prototype.forEach.call(res, function(doc) {
                    queryResults.push(doc);
                });
                query._id ? cb(queryResults[0]) : cb(queryResults);
            } else {
                cb({statusCode: 404, message: "ERROR: Doc from '" + collectionName + "' not found: " + query});
            }
        } else {
            console.error("Error when fetching from '" + collectionName + "' the doc: " + query);
            cb({statusCode: 500, message: res_err.message});
        }
    });
};<commit_msg>Removed an unnecessary error log<commit_after>/**
 * Created by cristinaionescu on 26/01/2016.
 */
var MongoClient = require("vertx-mongo-js/mongo_client");

module.exports = MongoClientObj;

function MongoClientObj(host, port, dbName, poolname) {
    this.collectionName = null;
    this.mongoClient = MongoClient.createShared(vertx, {
        "connection_string": "mongodb://" + host + ":" + port,
        "db_name": dbName
    }, poolname);

    if ( this.mongoClient ) {
        console.log("Connected to MongoDB @ " + host + ":" + port + "/" + dbName);
    } else {
        throw "MongoClient could not be instantiated";
    }
};

MongoClientObj.prototype.saveObjectToDB = function(object, colName, cb) {
    var collectionName = colName ? colName : this.collectionName;

    this.mongoClient.save(collectionName, object, function (id, err) {
        if (!err && !id) {
            id = object._id;
        }
        cb(id, err);
    });
};

MongoClientObj.prototype.getDocumentsFromDB = function(query, colName, cb) {
    var collectionName = colName ? colName : this.collectionName;
    var queryResults = [];

    this.mongoClient.find(collectionName, query, function (res, res_err) {
        if (!res_err) {
            if (res.length > 0) {
                Array.prototype.forEach.call(res, function(doc) {
                    queryResults.push(doc);
                });
                query._id ? cb(queryResults[0]) : cb(queryResults);
            } else {
                cb({statusCode: 404, message: "ERROR: Doc from '" + collectionName + "' not found: " + query});
            }
        } else {
            console.error("Error when fetching from '" + collectionName + "' the doc: " + query);
            cb({statusCode: 500, message: res_err.message});
        }
    });
};<|endoftext|>


<commit_before>/**
 * Inverse Enemy Straight Angle
 *
 * @param {Number} x
 * @param {Number} y
 */
function BonusEnemyStraightAngle(x, y)
{
    BonusEnemy.call(this, x, y);
}

BonusEnemyStraightAngle.prototype = Object.create(BonusEnemy.prototype);
BonusEnemyStraightAngle.prototype.constructor = BonusEnemyStraightAngle;

/**
 * Duration
 *
 * @type {Number}
 */
BonusEnemyStraightAngle.prototype.duration = 5000;

/**
 * Probability
 *
 * @type {Number}
 */
BonusEnemyStraightAngle.prototype.probability = 0.6;

/**
 * Get effects
 *
 * @param {Avatar} avatar
 *
 * @return {Array}
 */
BonusEnemyStraightAngle.prototype.getEffects = function(avatar)
{
    return [
        ['directionInLoop', false],
        ['angularVelocityBase', Math.PI/2]
    ];
};
<commit_msg>ashahs<commit_after><|endoftext|>


<commit_before>const removeLeadingSlash = (path) => (path[0] === '/' ? path.substring(1) : path);

const generateFileNameSuffix = (fileName) => {
	// eslint-disable-next-line no-useless-escape
	const newString = fileName.replace(/[';:=#*+\[\]~<{\\()}>§$%&|^£@±?!"`□ ]/g, '-');
	return `${Date.now()}-${newString}`;
};

const returnFileType = (fileName) => ({
	docx:
		'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
	xlsx:
		'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
	pptx:
		'application/vnd.openxmlformats-officedocument.presentationml.presentation',
	ppt: 'application/vnd.ms-powerpoint',
	xls: 'application/vnd.ms-excel',
	doc: 'application/vnd.ms-word',
	odt: 'application/vnd.oasis.opendocument.text',
	txt: 'text/plain',
	pdf: 'application/pdf',
	png: 'image/png',
	jpg: 'image/jpeg',
	jpeg: 'image/jpeg',
	jpe: 'image/jpeg',
	gif: 'image/gif',
	tiff: 'image/tiff',
	tif: 'image/tiff',
}[fileName.split('.').pop()]);

module.exports = {
	removeLeadingSlash,
	generateFileNameSuffix,
	returnFileType,
};
<commit_msg>added toLowerCase<commit_after>const removeLeadingSlash = (path) => (path[0] === '/' ? path.substring(1) : path);

const generateFileNameSuffix = (fileName) => {
	// eslint-disable-next-line no-useless-escape
	const newString = fileName.replace(/[';:=#*+\[\]~<{\\()}>§$%&|^£@±?!"`□ ]/g, '-');
	return `${Date.now()}-${newString.toLowerCase()}`;
};

const returnFileType = (fileName) => ({
	docx:
		'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
	xlsx:
		'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
	pptx:
		'application/vnd.openxmlformats-officedocument.presentationml.presentation',
	ppt: 'application/vnd.ms-powerpoint',
	xls: 'application/vnd.ms-excel',
	doc: 'application/vnd.ms-word',
	odt: 'application/vnd.oasis.opendocument.text',
	txt: 'text/plain',
	pdf: 'application/pdf',
	png: 'image/png',
	jpg: 'image/jpeg',
	jpeg: 'image/jpeg',
	jpe: 'image/jpeg',
	gif: 'image/gif',
	tiff: 'image/tiff',
	tif: 'image/tiff',
}[fileName.split('.').pop()]);

module.exports = {
	removeLeadingSlash,
	generateFileNameSuffix,
	returnFileType,
};
<|endoftext|>


<commit_before>'use strict';

angular.module('CallForPaper', [
    'ngCookies',
    'ngResource',
    'ngResourceRetries',
    'ngSanitize',
    'ui.router',
    'ngAnimate',
    'ui.bootstrap',
    'ngTagsInput',
    'internationalPhoneNumber',
    'bs-has',
    'pascalprecht.translate',
    'k8LanguagePicker',
    'ngTable',
    'ui-notification',
    'customFilters',
    'ui.gravatar',
    'relativeDate',
    'matchMedia',
    'satellizer',
    'angular-jwt',
    'vcRecaptcha',
    'angular-loading-bar',
    'ngFx',
    'offClick',
    'konami',
    'ngFileUpload',
    'hc.marked',
    'mdPreview',
    'LocalStorageModule',
    'ngLodash',
    'cfp.hotkeys',
    'ngAria'
  ])
  .constant('Config', {
    'recaptcha': '6Lcn4gcTAAAAAPATfe-4XVAh8bI4CW7HUAAwbNvy',
    'googleClientId': '595606955444-hv8v62e1g0qtk5v2nrnn696m18tg1p12.apps.googleusercontent.com',
    'githubClientId': 'ebeee4b3339f42197096'
  })
  .config(['cfpLoadingBarProvider', function(cfpLoadingBarProvider) {
    cfpLoadingBarProvider.includeSpinner = false;
  }])
  .config(['$httpProvider', function($httpProvider) {
    //Http Intercpetor to check auth failures for xhr requests
    $httpProvider.interceptors.push('authHttpResponseInterceptor');
    $httpProvider.interceptors.push('csrfInterceptor');
  }])
  .config(['$stateProvider', '$urlRouterProvider', 'AuthServiceProvider', 'AppConfigProvider', function($stateProvider, $urlRouterProvider, AuthServiceProvider, AppConfigProvider) {
    $urlRouterProvider
      .when('', '/dashboard')
      .when('/', '/dashboard')

    .when('/admin/sessions/', '/admin/sessions')

    .when('/admin', '/admin/sessions')
      .when('/admin/', '/admin/sessions')

    .when('/form', '/form/')

    .otherwise('/login');

    $stateProvider
      .state('admin', {
        url: '/admin',
        abstract: true,
        views: {
          '': {
            templateUrl: 'views/admin/admin.html',
            controller: 'AdminCtrl',
            resolve: {
              isAutorizedAdmin: AuthServiceProvider.$get().isAutorizedAdmin,
              isConfigured: AppConfigProvider.$get().isConfigured
            },
            '@admin': {
              templateUrl: 'views/admin/sessions.html',
              controller: 'AdminSessionsCtrl'
            }
          }
        },
      })
      // Config
      .state('admin.config', {
        url: '/config',
        templateUrl: 'views/admin/config.html',
        controller: 'AdminConfigCtrl'
      })
      // Session
      .state('admin.sessions', {
        url: '/sessions',
        templateUrl: 'views/admin/sessions.html',
        controller: 'AdminSessionsCtrl'
      })
      .state('admin.export_postit', {
        url: '/export/postit',
        templateUrl: 'views/admin/sessions-export.html',
        controller: 'AdminSessionsExportCtrl'
      })
      .state('admin.export_json', {
        url: '/export/json',
        templateUrl: 'views/admin/sessions-export-json.html',
        controller: 'AdminSessionsExportJsonCtrl'
      })
      .state('admin.session', {
        url: '/sessions/:id?tab',
        templateUrl: 'views/admin/session.html',
        controller: 'AdminSessionCtrl'
      })

    // App configuration
    .state('config', {
        abstract: true,
        views: {
          '': {
            templateUrl: 'views/config/config.html',
            controller: 'ConfigCtrl'
          }
        }
      })
      .state('config.autorize', {
        url: '/config',
        templateUrl: 'views/config/autorize.html',
        controller: 'AutorizeCtrl',
        resolve: {
          isAutorizedAdmin: AuthServiceProvider.$get().isAutorizedConfig
        }
      })
      .state('config.about', {
        url: '/config/about',
        templateUrl: 'views/config/about.html'
      })
      .state('config.403', {
        templateUrl: 'views/config/403.html'
      })

    // Login Admin
    .state('loginAdmin', {
        url: '/admin/login',
        templateUrl: 'views/admin/login.html',
        controller: 'AdminLoginCtrl'
      })
      // Logout Admin
      .state('logoutAdmin', {
        url: '/admin/logout',
        templateUrl: 'views/admin/login.html',
        controller: 'AdminLogoutCtrl'
      })

    // Restricted
    .state('app', {
        abstract: true,
        views: {
          '': {
            templateUrl: 'views/header.html',
            controller: 'HeaderCtrl',
            resolve: {
              isConfigured: AppConfigProvider.$get().isConfigured
            }
          }
        },
      })
      .state('app.dashboard', {
        url: '/dashboard',
        templateUrl: 'views/restricted/dashboard.html',
        controller: 'DashboardCtrl',
        resolve: {
          authenticated: AuthServiceProvider.$get().authenticated
        }
      })
      .state('app.profil', {
        url: '/profil',
        templateUrl: 'views/restricted/profil.html',
        controller: 'ProfilCtrl',
        resolve: {
          authenticated: AuthServiceProvider.$get().authenticated
        }
      })

    // Auth
    .state('app.login', {
        url: '/login',
        templateUrl: 'views/login.html',
        controller: 'LoginCtrl'
      })
      .state('app.verify', {
        url: '/verify?token&id',
        templateUrl: 'views/verify.html',
        controller: 'VerifyCtrl'
      })
      .state('app.logout', {
        url: '/logout',
        template: null,
        controller: 'LogoutCtrl'
      })
      .state('app.signup', {
        url: '/signup',
        templateUrl: 'views/signup.html',
        controller: 'SignupCtrl'
      })

    // Form
    .state('app.form', {
      url: '/form/:id',
      views: {
        '': {
          templateUrl: 'views/restricted/form/form.html',
          controller: 'FormCtrl',
          resolve: {
            verified: AuthServiceProvider.$get().verified,
            isOpen: AppConfigProvider.$get().isOpen
          }
        },
        '@app.form': {
          templateUrl: 'views/restricted/form/step1.html',
          controller: 'Step1Ctrl'
        }
      },
    })

    .state('app.form.step2', {
        templateUrl: 'views/restricted/form/step2.html',
        controller: 'Step2Ctrl'
      })
      .state('app.form.step3', {
        templateUrl: 'views/restricted/form/step3.html',
        controller: 'Step3Ctrl'
      })
      .state('app.form.result', {
        templateUrl: 'views/restricted/form/result.html',
        controller: 'ResultCtrl'
      })

    .state('app.session', {
      url: '/sessions/:id?tab',
      templateUrl: 'views/restricted/session.html',
      controller: 'RestrictedSessionCtrl',
      resolve: {
        verified: AuthServiceProvider.$get().verified
      }
    })

    .state('403', {
      url: '/403',
      templateUrl: '403.html'
    })

    .state('404', {
      url: '/404',
      templateUrl: '404.html'
    });
  }])
  .config(['tagsInputConfigProvider', function(tagsInputConfigProvider) {
    tagsInputConfigProvider
      .setDefaults('tagsInput', {
        placeholder: '',
        minLength: 1,
        addOnEnter: true
      })
      .setDefaults('autoComplete', {
        debounceDelay: 200,
        loadOnDownArrow: true,
        loadOnEmpty: true
      })
  }])
  .config(['$translateProvider', function($translateProvider) {
    $translateProvider.useCookieStorage();
  }])
  .config(['$authProvider', 'Config', function($authProvider, Config) {
    $authProvider.google({
      clientId: Config.googleClientId
    });

    $authProvider.github({
      clientId: Config.githubClientId
    });

    $authProvider.oauth2({
      name: 'spreadsheet',
      url: '/auth/spreadsheet',
      authorizationEndpoint: 'https://accounts.google.com/o/oauth2/auth',
      redirectUri: window.location.origin || window.location.protocol + '//' + window.location.host,
      scope: ['https://www.googleapis.com/auth/drive.file', 'https://spreadsheets.google.com/feeds'],
      clientId: Config.googleClientId,
      scopeDelimiter: ' ',
      accessType: 'offline',
      approvalPrompt: 'force',
      requiredUrlParams: ['scope', 'access_type', 'approval_prompt'],
      optionalUrlParams: ['display'],
      display: 'popup',
      type: '2.0',
      popupOptions: {
        width: 580,
        height: 400
      }
    });

  }])
  .run(['AuthService', '$http', function(AuthService, $http) {
    AuthService.init();
    $http.defaults.xsrfHeaderName = 'X-CSRF-TOKEN';
    $http.defaults.xsrfCookieName = 'CSRF-TOKEN';
    $.material.init();
  }]);
<commit_msg>[front] commit local dev client id<commit_after>'use strict';

angular.module('CallForPaper', [
    'ngCookies',
    'ngResource',
    'ngResourceRetries',
    'ngSanitize',
    'ui.router',
    'ngAnimate',
    'ui.bootstrap',
    'ngTagsInput',
    'internationalPhoneNumber',
    'bs-has',
    'pascalprecht.translate',
    'k8LanguagePicker',
    'ngTable',
    'ui-notification',
    'customFilters',
    'ui.gravatar',
    'relativeDate',
    'matchMedia',
    'satellizer',
    'angular-jwt',
    'vcRecaptcha',
    'angular-loading-bar',
    'ngFx',
    'offClick',
    'konami',
    'ngFileUpload',
    'hc.marked',
    'mdPreview',
    'LocalStorageModule',
    'ngLodash',
    'cfp.hotkeys',
    'ngAria'
  ])
  .constant('Config', {
    'recaptcha': '6LdxgxATAAAAAFUCo5RuwxxCGF20b-UWaawAM0nM',
    'googleClientId': '980998530813-um48to1pf2be7tn9d9ar29d7si41a5kd.apps.googleusercontent.com',
    'githubClientId': '5fb632a6027ffe32338b'
  })
  .config(['cfpLoadingBarProvider', function(cfpLoadingBarProvider) {
    cfpLoadingBarProvider.includeSpinner = false;
  }])
  .config(['$httpProvider', function($httpProvider) {
    //Http Intercpetor to check auth failures for xhr requests
    $httpProvider.interceptors.push('authHttpResponseInterceptor');
    $httpProvider.interceptors.push('csrfInterceptor');
  }])
  .config(['$stateProvider', '$urlRouterProvider', 'AuthServiceProvider', 'AppConfigProvider', function($stateProvider, $urlRouterProvider, AuthServiceProvider, AppConfigProvider) {
    $urlRouterProvider
      .when('', '/dashboard')
      .when('/', '/dashboard')

    .when('/admin/sessions/', '/admin/sessions')

    .when('/admin', '/admin/sessions')
      .when('/admin/', '/admin/sessions')

    .when('/form', '/form/')

    .otherwise('/login');

    $stateProvider
      .state('admin', {
        url: '/admin',
        abstract: true,
        views: {
          '': {
            templateUrl: 'views/admin/admin.html',
            controller: 'AdminCtrl',
            resolve: {
              isAutorizedAdmin: AuthServiceProvider.$get().isAutorizedAdmin,
              isConfigured: AppConfigProvider.$get().isConfigured
            },
            '@admin': {
              templateUrl: 'views/admin/sessions.html',
              controller: 'AdminSessionsCtrl'
            }
          }
        },
      })
      // Config
      .state('admin.config', {
        url: '/config',
        templateUrl: 'views/admin/config.html',
        controller: 'AdminConfigCtrl'
      })
      // Session
      .state('admin.sessions', {
        url: '/sessions',
        templateUrl: 'views/admin/sessions.html',
        controller: 'AdminSessionsCtrl'
      })
      .state('admin.export_postit', {
        url: '/export/postit',
        templateUrl: 'views/admin/sessions-export.html',
        controller: 'AdminSessionsExportCtrl'
      })
      .state('admin.export_json', {
        url: '/export/json',
        templateUrl: 'views/admin/sessions-export-json.html',
        controller: 'AdminSessionsExportJsonCtrl'
      })
      .state('admin.session', {
        url: '/sessions/:id?tab',
        templateUrl: 'views/admin/session.html',
        controller: 'AdminSessionCtrl'
      })

    // App configuration
    .state('config', {
        abstract: true,
        views: {
          '': {
            templateUrl: 'views/config/config.html',
            controller: 'ConfigCtrl'
          }
        }
      })
      .state('config.autorize', {
        url: '/config',
        templateUrl: 'views/config/autorize.html',
        controller: 'AutorizeCtrl',
        resolve: {
          isAutorizedAdmin: AuthServiceProvider.$get().isAutorizedConfig
        }
      })
      .state('config.about', {
        url: '/config/about',
        templateUrl: 'views/config/about.html'
      })
      .state('config.403', {
        templateUrl: 'views/config/403.html'
      })

    // Login Admin
    .state('loginAdmin', {
        url: '/admin/login',
        templateUrl: 'views/admin/login.html',
        controller: 'AdminLoginCtrl'
      })
      // Logout Admin
      .state('logoutAdmin', {
        url: '/admin/logout',
        templateUrl: 'views/admin/login.html',
        controller: 'AdminLogoutCtrl'
      })

    // Restricted
    .state('app', {
        abstract: true,
        views: {
          '': {
            templateUrl: 'views/header.html',
            controller: 'HeaderCtrl',
            resolve: {
              isConfigured: AppConfigProvider.$get().isConfigured
            }
          }
        },
      })
      .state('app.dashboard', {
        url: '/dashboard',
        templateUrl: 'views/restricted/dashboard.html',
        controller: 'DashboardCtrl',
        resolve: {
          authenticated: AuthServiceProvider.$get().authenticated
        }
      })
      .state('app.profil', {
        url: '/profil',
        templateUrl: 'views/restricted/profil.html',
        controller: 'ProfilCtrl',
        resolve: {
          authenticated: AuthServiceProvider.$get().authenticated
        }
      })

    // Auth
    .state('app.login', {
        url: '/login',
        templateUrl: 'views/login.html',
        controller: 'LoginCtrl'
      })
      .state('app.verify', {
        url: '/verify?token&id',
        templateUrl: 'views/verify.html',
        controller: 'VerifyCtrl'
      })
      .state('app.logout', {
        url: '/logout',
        template: null,
        controller: 'LogoutCtrl'
      })
      .state('app.signup', {
        url: '/signup',
        templateUrl: 'views/signup.html',
        controller: 'SignupCtrl'
      })

    // Form
    .state('app.form', {
      url: '/form/:id',
      views: {
        '': {
          templateUrl: 'views/restricted/form/form.html',
          controller: 'FormCtrl',
          resolve: {
            verified: AuthServiceProvider.$get().verified,
            isOpen: AppConfigProvider.$get().isOpen
          }
        },
        '@app.form': {
          templateUrl: 'views/restricted/form/step1.html',
          controller: 'Step1Ctrl'
        }
      },
    })

    .state('app.form.step2', {
        templateUrl: 'views/restricted/form/step2.html',
        controller: 'Step2Ctrl'
      })
      .state('app.form.step3', {
        templateUrl: 'views/restricted/form/step3.html',
        controller: 'Step3Ctrl'
      })
      .state('app.form.result', {
        templateUrl: 'views/restricted/form/result.html',
        controller: 'ResultCtrl'
      })

    .state('app.session', {
      url: '/sessions/:id?tab',
      templateUrl: 'views/restricted/session.html',
      controller: 'RestrictedSessionCtrl',
      resolve: {
        verified: AuthServiceProvider.$get().verified
      }
    })

    .state('403', {
      url: '/403',
      templateUrl: '403.html'
    })

    .state('404', {
      url: '/404',
      templateUrl: '404.html'
    });
  }])
  .config(['tagsInputConfigProvider', function(tagsInputConfigProvider) {
    tagsInputConfigProvider
      .setDefaults('tagsInput', {
        placeholder: '',
        minLength: 1,
        addOnEnter: true
      })
      .setDefaults('autoComplete', {
        debounceDelay: 200,
        loadOnDownArrow: true,
        loadOnEmpty: true
      })
  }])
  .config(['$translateProvider', function($translateProvider) {
    $translateProvider.useCookieStorage();
  }])
  .config(['$authProvider', 'Config', function($authProvider, Config) {
    $authProvider.google({
      clientId: Config.googleClientId
    });

    $authProvider.github({
      clientId: Config.githubClientId
    });

    $authProvider.oauth2({
      name: 'spreadsheet',
      url: '/auth/spreadsheet',
      authorizationEndpoint: 'https://accounts.google.com/o/oauth2/auth',
      redirectUri: window.location.origin || window.location.protocol + '//' + window.location.host,
      scope: ['https://www.googleapis.com/auth/drive.file', 'https://spreadsheets.google.com/feeds'],
      clientId: Config.googleClientId,
      scopeDelimiter: ' ',
      accessType: 'offline',
      approvalPrompt: 'force',
      requiredUrlParams: ['scope', 'access_type', 'approval_prompt'],
      optionalUrlParams: ['display'],
      display: 'popup',
      type: '2.0',
      popupOptions: {
        width: 580,
        height: 400
      }
    });

  }])
  .run(['AuthService', '$http', function(AuthService, $http) {
    AuthService.init();
    $http.defaults.xsrfHeaderName = 'X-CSRF-TOKEN';
    $http.defaults.xsrfCookieName = 'CSRF-TOKEN';
    $.material.init();
  }]);
<|endoftext|>


<commit_before>// Constants {{
var
  ID = 0,

  // This is the duration of the video minus the offsets in
  // the start and stop, as determined through visual inspection.
  // These are the transitions put on by different uploaders, things
  // like "THIS IS A JJ COOLGUY RIP" etc.
  RUNTIME = 1,
  START = 2,
  STOP = 3,

  // This is for volume normalization on a per video
  // basis
  VOLUME = 4,

  // The year of release
  YEAR = 5,

  ARTIST = 6,

  TITLE = 7,

  NOTES = 8,

  // If there is a hash value (there should not be regularly)
  // Then debugging output is turned on, whatever the hell that
  // entails
  DEBUG = location.hash.length > 0,

  // The offset addition was after some toying around and
  // seeint how long the player took to load. This seemed
  // to work ok; we really want the drift to be as close
  // to 0 as possible.
  YTLOADTIME_sec = 5,

  // According to the docs: "The player does not request
  // the FLV until playVideo() or seekTo() is called.". In
  // order to combat this, we have to pre-load the video
  // by some increment, we take that to be the YTLOADTIME,
  // multiplied by 1000 because it's expressed in MS
  PRELOAD_ms = YTLOADTIME_sec * 1000,

  // An extra player
  EXTRA = 2,

  // @ref: http://code.google.com/apis/youtube/flash_api_reference.html
  LEVELS = ["small", "medium", "large", "hd720", "hd1080", "highres"];

// }} // Constants

// Utils {{
function getNow(offset) {
  return +(new Date() / 1000) + (offset || 0);
}

function toTime(sec) {
  return [
    (sec / 3600).toFixed(0),
    ((sec / 60).toFixed(0) % 60 + 100).toString().substr(1),
    ((sec.toFixed(0) % 60) + 100).toString().substr(1)
  ].join(':');
}

// }} // Utils

// Globals {{
var
  _active = 0,

  // This the the current playback quality index, which can be triggered
  // in a direction (either up or down) based on how successful we can
  // combat drift (basically by playing without hitting a buffer interval)
  //
  // We start at the lowest quality and then the skies the limit, I guess.
  _currentLevel = 0,
  _lagCounter = 0,

  _muted = false,

  _index = -1,
  _lastLoaded,

  _seekTimeout = 0,
  _qualityTimeout = 0,

  // The epoch time is based off the system time AND the users
  // local clock.  This makes sure that separate clock drifts
  // are *about* the same ... minus the TTL latency incurred by
  // the emit from the server of course (which we assume to be fairly
  // constant).
  _start = getNow(),
  _epoch = 1325138061 + ( _start - _referenceTime ),

  // How many of the YT players are loaded
  _loaded = 0,

  // And their associated references
  _player = [],

  _lastTime = 0,

  _next = 1,
  _runtime = _.reduce(_duration, function(a, b) { return a + b[RUNTIME] }, 0);
// }} // Globals

function mutetoggle(el){
  _muted = !_muted;
  if(_muted) {
    el.src = "mute_on_32.png";
    _player[_active].setVolume(0);
  } else {
    el.src = "mute_off_32.png";
    // bug
    _player[_active].setVolume(100);
  }
}

// This sets the quality of the video along with
// supporting going down or up a notch based on
// what is detected, probably in findOffset
function setQuality(direction) {
  var
    newQualityIndex = _currentLevel,
    newQualityWord,

    activeAvailable = _player[_active].getAvailableQualityLevels(),
    activeQualityWord = _player[_active].getPlaybackQuality();

  // If no video is loaded, then go no further.
  if(activeAvailable.length == 0) {
    return;
  }

  // If the lapse has dropped and the direction is specific
  if(direction && getNow() > _qualityTimeout) {
    newQualityIndex = Math.min(
      Math.max(_currentLevel + direction, 0),
      LEVELS.length
    );

    // To make sure we don't cycle through the
    // quality levels too quickly, there's a cool-off
    // time after a quality toggle.
    _qualityTimeout = getNow(+ YTLOADTIME_sec * 4);
  }

  // Now that we have the destination quality level, we need to see
  // if the current video playing has this quality level.
  newQualityWord = LEVELS[newQualityIndex];

  // If this video doesn't support the destination quality level
  if ( _.indexOf(activeAvailable, newQualityWord) == -1) {
    // Use the highest one available (the lower ones are always available)
    // Get the word version of the highest quality available
    newQualityWord = _.first(activeAvailable);
  }

  // If this new, supported quality isn't the current one set
  if (newQualityWord != activeQualityWord) {

    console.log("Quality: " + activeQualityWord + " => " + newQualityWord);

    // If we are downsampling then just do it
    if(true) { //direction < 0) {
      _player[_active].setPlaybackQuality(newQualityWord);

      // If we are upsampling, then do it seemlessly.
    } else if(
      _player[_active].getDuration() -
      _duration[_player[_active].index][STOP] -
      _player[_active].getCurrentTime() > YTLOADTIME_sec * 2.5
    ) {

      // Ug, still experimental
      var index = _player[_active].index;

      // First, load the active video in the extra player,
      // setting the volume to 0
      _player[EXTRA].loadVideoById(_duration[index][ID].split(":")[1])

      _player[EXTRA].setVolume(0);

      // Set the playback quality of the extra video to the higher
      // quality
      _player[EXTRA].setPlaybackQuality(newQualityWord);

      // By seeking to the current time subtracted from the load time, then by the time this seeks
      // It should be eclipsed by the active player
      _player[EXTRA].seekTo(_player[_active].getCurrentTime() - YTLOADTIME_sec / 2);
      _player[EXTRA].playVideo();

      // Now poll the two time offsets and swap videos when they cross
      var swapInterval = setInterval(function(){
        console.log(_player[EXTRA].getVideoBytesLoaded(), _player[EXTRA].getCurrentTime());
        if (
          (_player[EXTRA].getCurrentTime() > 0) &&
          (_player[_active].getCurrentTime() > _player[EXTRA].getCurrentTime())
        ) {
          // Nows our time to shine

          // Bring the volume up of the higher quality player and mute the current
          _player[EXTRA].setVolume(_duration[index][VOLUME]);
          _player[_active].setVolume(0);

          // Start the higher quality player and stop the current one
          _player[EXTRA].playVideo();
          _player[_active].stopVideo();

          // Show the higher quality and hide the current one
          document.getElementById("player-" + _active).style.visibility = 'hidden';
          document.getElementById("player-" + EXTRA).style.visibility = 'visible';

          // now set the active to the extra, this works because the next mechanics
          // is based not on the previous next, but on the active; so there is no
          // odd/even problem.
          _active = EXTRA;

          // Set up the index
          _player[_active].index = _index;

          // And then clear the polling interval
          clearInterval(swapInterval);
        }
      }, 100);
    }

    // And set it as the default
    _currentLevel = _.indexOf(LEVELS, newQualityWord);
  }
}

function findOffset() {
  var
    now = getNow(),
    lapse = (now - _epoch) % _runtime;

  for (var index = 0;

    lapse > _duration[index][RUNTIME];

    lapse -= _duration[index][RUNTIME],
    index = (index + 1) % _duration.length
  );

  // If the duration has a starting offset, then
  // we put that here...
  lapse += _duration[index][START];

  if(_index > -1) {
    document.title = _duration[_index][ARTIST] + " - " + _duration[_index][TITLE] + " | " + toTime(now - _start);
    if(DEBUG) {
      var drift = _player[_active].getCurrentTime() - lapse;
      if(drift > 0) {
        drift = "+" + drift.toFixed(3);
      } else {
        drift = drift.toFixed(3);
      }

      document.title += " " + [drift, _lagCounter].join(' ');
    }
  }

  if (_duration[index][RUNTIME] - _player[_active].getCurrentTime() < 10) {
    _index = (index + 1) % _duration.length;
    transition(0);
  } else if (_index == -1) {
    _index = index;

    // Since we increment in the transition (sloppy, kiddo), then
    // we need to offset from that here.  That function should
    // probably be broken up better than it is currently.
    transition(lapse);
  }

  if ( now > _seekTimeout &&
      _player[_active].getCurrentTime() > 0 &&
      _player[_active].index == index
    ) {

    // If we have been buffering for a while, then we shift forward
    // then we will downsample and shift forward
    if ( _lastTime == _player[_active].getCurrentTime() ) {
      _lagCounter ++;
    } else {
      _lagCounter --;
    }
    _lastTime = _player[_active].getCurrentTime();

    // If the lagCounter is greater than 3, that means we've been
    // lagging quite a bit, then we try to reduce our quality
    if(_lagCounter > 12) {
      setQuality(-1);
      _lagCounter -= 12;

      console.log("seeking", lapse, _player[_active].getCurrentTime());

      // Make sure that we don't reseek too frequently.
      _seekTimeout = now + YTLOADTIME_sec;

      // We don't trust seeking to be insanely accurate so we throw an offset
      // on to it to avoid some kind of weird seeking loop.
      _player[_active].seekTo(lapse + YTLOADTIME_sec * 7 / 3);
    }

    // TODO: If our lagcounter is really low, then
    // we have been good and can up the quality at
    // this point; but have to be smart about it so
    // that we aren't just constantly cycling through
    // two quality settings, pausing the video annoyingly
    // every time we cycle up or down.
    if(_lagCounter < -12) {
      setQuality(+1);
      _lagCounter += 12;

      // Make sure that we don't reseek too frequently.
      _seekTimeout = now + YTLOADTIME_sec;
    }
  }
}

function onYouTubePlayerReady(playerId) {
  var id = parseInt(playerId.substr(-1));
  _player[ id ] = document.getElementById(playerId);

  if(++_loaded == 3) {
    findOffset();
    setInterval(findOffset, 500);
  }
}

function remainingTime() {
  if(_player[_active] && _player[_active].getDuration && 'index' in _player[_active]) {
    return Math.max(0,
      _player[_active].getDuration() -
      _duration[_player[_active].index][STOP] -
      _player[_active].getCurrentTime()
    );
  } else {
    return 0;
  }
}

function transition(offset) {
  if(_index == _lastLoaded) {
    return;
  }
  _lastLoaded = _index;

  // Load the next video prior to actually switching over
  var
    id = _duration[_index][ID],
    proto = id.split(':')[0],
    uuid = id.split(':')[1];

  console.log("Loading: ", id);

  // Offset mechanics are throughout, but placing it here
  // make sure that on first load there isn't some brief beginning
  // of video sequence then a seek.
  _player[_next].loadVideoById(uuid, offset);
  _player[_next].pauseVideo();

  setTimeout(function(){

    // After the PRELOAD_ms interval, then we stop the playing video
    _player[_active].stopVideo();

    // Toggle the player pointers
    _active = (_active + 1) % 2;
    _next = (_active + 1) % 2;

    // When you toggle the visibility, there is still an annoying spinner.
    // So to avoid this we just "move" the players off screen that aren't
    // being used.
    document.getElementById("player-" + _active).style.left = "0%";
    document.getElementById("player-" + _next).style.left = "-200%";
    document.getElementById("player-" + EXTRA).style.left = "-200%";

    // Crank up the volume to the computed normalization
    // level.
    _player[_active].playVideo();
    _player[_active].index = _index;

    // Make sure that we observe the volume settings.
    if(_muted) {
      _player[_active].setVolume(0);
    } else {
      _player[_active].setVolume(_duration[_index][VOLUME]);
    }

    setQuality();
  }, remainingTime() * 1000);
}

(function(){
  // Load two players to be transitioned between at a nominal
  // resolution ... this is irrelevant as quality will be
  // managed in a more sophisticated manner than size of screen.
  for(var ix = 0; ix < 3; ix++) {

    swfobject.embedSWF("http://www.youtube.com/apiplayer?" + [
      "version=3",
      "enablejsapi=1",
      "playerapiid=player-" + ix
    ].join('&'),  // swfUrl
      "vid" + ix, // id
      "400",      // width
      "300",      // height
      "9",        // [false] version (the flv2 player (flash 8) has ad-free vevo, so we use the old player)
      null,       // express install swf url (we assume you have the flash player)
      null,       // flash vars

      {
        allowScriptAccess: "always"
      }, // params

      // This little hack forces our small mt80s logo to the bottom left so
      // the user can click on it at any time.
      {
        wmode: "transparent",
        id: 'player-' + ix
      }, // attributes

      new Function()                 // yt doesn't do the callbackfunction
    );
  }
})();
<commit_msg>cleanup<commit_after>// Constants {{
var
  ID = 0,

  // This is the duration of the video minus the offsets in
  // the start and stop, as determined through visual inspection.
  // These are the transitions put on by different uploaders, things
  // like "THIS IS A JJ COOLGUY RIP" etc.
  RUNTIME = 1,
  START = 2,
  STOP = 3,

  // This is for volume normalization on a per video
  // basis
  VOLUME = 4,

  // The year of release
  YEAR = 5,

  ARTIST = 6,

  TITLE = 7,

  NOTES = 8,

  // If there is a hash value (there should not be regularly)
  // Then debugging output is turned on, whatever the hell that
  // entails
  DEBUG = location.hash.length > 0,

  // The offset addition was after some toying around and
  // seeint how long the player took to load. This seemed
  // to work ok; we really want the drift to be as close
  // to 0 as possible.
  YTLOADTIME_sec = 5,

  // According to the docs: "The player does not request
  // the FLV until playVideo() or seekTo() is called.". In
  // order to combat this, we have to pre-load the video
  // by some increment, we take that to be the YTLOADTIME,
  // multiplied by 1000 because it's expressed in MS
  PRELOAD_ms = YTLOADTIME_sec * 1000,

  LAG_THRESHHOLD = 12,

  // An extra player
  EXTRA = 2,

  // @ref: http://code.google.com/apis/youtube/flash_api_reference.html
  LEVELS = ["small", "medium", "large", "hd720", "hd1080", "highres"];

// }} // Constants

// Utils {{
function getNow(offset) {
  return +(new Date() / 1000) + (offset || 0);
}

function toTime(sec) {
  return [
    (sec / 3600).toFixed(0),
    ((sec / 60).toFixed(0) % 60 + 100).toString().substr(1),
    ((sec.toFixed(0) % 60) + 100).toString().substr(1)
  ].join(':');
}

// }} // Utils

// Globals {{
var
  _active = 0,

  // This the the current playback quality index, which can be triggered
  // in a direction (either up or down) based on how successful we can
  // combat drift (basically by playing without hitting a buffer interval)
  //
  // We start at the lowest quality and then the skies the limit, I guess.
  _currentLevel = 0,

  // The lag counter is a token system that gets set by an interval.  If
  // we accumulate a certain negative or positive balance, then we can exchange
  // the negative or positive units for a quality shift. This makes sure that
  // we can prove the stability of any setting through successive incremental
  // sampling
  _lagCounter = 0,

  _muted = false,

  _index = -1,
  _lastLoaded,

  _seekTimeout = 0,
  _qualityTimeout = 0,

  // The epoch time is based off the system time AND the users
  // local clock.  This makes sure that separate clock drifts
  // are *about* the same ... minus the TTL latency incurred by
  // the emit from the server of course (which we assume to be fairly
  // constant).
  _start = getNow(),
  _epoch = 1325138061 + ( _start - _referenceTime ),

  // How many of the YT players are loaded
  _loaded = 0,

  // And their associated references
  _player = [],

  _lastTime = 0,

  _next = 1,
  _runtime = _.reduce(_duration, function(a, b) { return a + b[RUNTIME] }, 0);
// }} // Globals

function mutetoggle(el){
  _muted = !_muted;
  if(_muted) {
    el.src = "mute_on_32.png";
    _player[_active].setVolume(0);
  } else {
    el.src = "mute_off_32.png";
    // bug
    _player[_active].setVolume(100);
  }
}

// This sets the quality of the video along with
// supporting going down or up a notch based on
// what is detected, probably in findOffset
function setQuality(direction) {
  var
    newQualityIndex = _currentLevel,
    newQualityWord,

    activeAvailable = _player[_active].getAvailableQualityLevels(),
    activeQualityWord = _player[_active].getPlaybackQuality();

  // If no video is loaded, then go no further.
  if(activeAvailable.length == 0) {
    return;
  }

  // If the lapse has dropped and the direction is specific
  if(direction && getNow() > _qualityTimeout) {
    newQualityIndex = Math.min(
      Math.max(_currentLevel + direction, 0),
      LEVELS.length
    );

    // To make sure we don't cycle through the
    // quality levels too quickly, there's a cool-off
    // time after a quality toggle.
    _qualityTimeout = getNow(+ YTLOADTIME_sec * 4);
  }

  // Now that we have the destination quality level, we need to see
  // if the current video playing has this quality level.
  newQualityWord = LEVELS[newQualityIndex];

  // If this video doesn't support the destination quality level
  if ( _.indexOf(activeAvailable, newQualityWord) == -1) {
    // Use the highest one available (the lower ones are always available)
    // Get the word version of the highest quality available
    newQualityWord = _.first(activeAvailable);
  }

  // If this new, supported quality isn't the current one set
  if (newQualityWord != activeQualityWord) {

    console.log("Quality: " + activeQualityWord + " => " + newQualityWord);

    // If we are downsampling then just do it
    if(true) { //direction < 0) {
      _player[_active].setPlaybackQuality(newQualityWord);

      // If we are upsampling, then do it seemlessly.
    } else if(
      _player[_active].getDuration() -
      _duration[_player[_active].index][STOP] -
      _player[_active].getCurrentTime() > YTLOADTIME_sec * 2.5
    ) {

      // Ug, still experimental
      var index = _player[_active].index;

      // First, load the active video in the extra player,
      // setting the volume to 0
      _player[EXTRA].loadVideoById(_duration[index][ID].split(":")[1])

      _player[EXTRA].setVolume(0);

      // Set the playback quality of the extra video to the higher
      // quality
      _player[EXTRA].setPlaybackQuality(newQualityWord);

      // By seeking to the current time subtracted from the load time, then by the time this seeks
      // It should be eclipsed by the active player
      _player[EXTRA].seekTo(_player[_active].getCurrentTime() - YTLOADTIME_sec / 2);
      _player[EXTRA].playVideo();

      // Now poll the two time offsets and swap videos when they cross
      var swapInterval = setInterval(function(){
        console.log(_player[EXTRA].getVideoBytesLoaded(), _player[EXTRA].getCurrentTime());
        if (
          (_player[EXTRA].getCurrentTime() > 0) &&
          (_player[_active].getCurrentTime() > _player[EXTRA].getCurrentTime())
        ) {
          // Nows our time to shine

          // Bring the volume up of the higher quality player and mute the current
          _player[EXTRA].setVolume(_duration[index][VOLUME]);
          _player[_active].setVolume(0);

          // Start the higher quality player and stop the current one
          _player[EXTRA].playVideo();
          _player[_active].stopVideo();

          // Show the higher quality and hide the current one
          document.getElementById("player-" + _active).style.visibility = 'hidden';
          document.getElementById("player-" + EXTRA).style.visibility = 'visible';

          // now set the active to the extra, this works because the next mechanics
          // is based not on the previous next, but on the active; so there is no
          // odd/even problem.
          _active = EXTRA;

          // Set up the index
          _player[_active].index = _index;

          // And then clear the polling interval
          clearInterval(swapInterval);
        }
      }, 100);
    }

    // And set it as the default
    _currentLevel = _.indexOf(LEVELS, newQualityWord);
  }
}

function findOffset() {
  var
    now = getNow(),
    lapse = (now - _epoch) % _runtime;

  for (var index = 0;

    lapse > _duration[index][RUNTIME];

    lapse -= _duration[index][RUNTIME],
    index = (index + 1) % _duration.length
  );

  // If the duration has a starting offset, then
  // we put that here...
  lapse += _duration[index][START];

  if(_index > -1) {
    document.title = _duration[_index][ARTIST] + " - " + _duration[_index][TITLE] + " | " + toTime(now - _start);
    if(DEBUG) {
      var drift = _player[_active].getCurrentTime() - lapse;
      if(drift > 0) {
        drift = "+" + drift.toFixed(3);
      } else {
        drift = drift.toFixed(3);
      }

      document.title += " " + [drift, _lagCounter].join(' ');
    }
  }

  if (_duration[index][RUNTIME] - _player[_active].getCurrentTime() < 10) {
    _index = (index + 1) % _duration.length;
    transition(0);
  } else if (_index == -1) {
    _index = index;

    // Since we increment in the transition, then
    // we need to offset from that here.  That function should
    // probably be broken up better than it is currently.
    transition(lapse);
  }

  if ( now > _seekTimeout &&
      _player[_active].getCurrentTime() > 0 &&
      _player[_active].index == index
    ) {

    if ( _lastTime == _player[_active].getCurrentTime() ) {
      _lagCounter ++;
    } else {
      _lagCounter --;
    }
    _lastTime = _player[_active].getCurrentTime();

    // Make sure that we don't reseek too frequently.
    if(Math.abs(_lagCounter) > LAG_THRESHHOLD) {
      _seekTimeout = now + YTLOADTIME_sec;
    }

    // If we have been buffering for a while,
    // then we will downsample and shift forward
    if(_lagCounter > LAG_THRESHHOLD) {
      setQuality(-1);
      _lagCounter -= LAG_THRESHHOLD;

      console.log("seeking", lapse, _player[_active].getCurrentTime());

      // We don't trust seeking to be insanely accurate so we throw an offset
      // on to it to avoid some kind of weird seeking loop.
      _player[_active].seekTo(lapse + YTLOADTIME_sec * 7 / 3);
    }

    // If our lagcounter is really low, then
    // we have been good and can up the quality at
    // this point
    if(_lagCounter < -LAG_THRESHHOLD) {
      setQuality(+1);
      _lagCounter += LAG_THRESHHOLD;
    }
  }
}

function onYouTubePlayerReady(playerId) {
  var id = parseInt(playerId.substr(-1));
  _player[ id ] = document.getElementById(playerId);

  if(++_loaded == 3) {
    findOffset();
    setInterval(findOffset, 500);
  }
}

function remainingTime() {
  if(_player[_active] && _player[_active].getDuration && 'index' in _player[_active]) {
    return Math.max(0,
      _player[_active].getDuration() -
      _duration[_player[_active].index][STOP] -
      _player[_active].getCurrentTime()
    );
  } else {
    return 0;
  }
}

function transition(offset) {
  if(_index == _lastLoaded) {
    return;
  }
  _lastLoaded = _index;

  // Load the next video prior to actually switching over
  var
    id = _duration[_index][ID],
    proto = id.split(':')[0],
    uuid = id.split(':')[1];

  console.log("Loading: ", id);

  // Offset mechanics are throughout, but placing it here
  // make sure that on first load there isn't some brief beginning
  // of video sequence then a seek.
  _player[_next].loadVideoById(uuid, offset);
  _player[_next].pauseVideo();

  setTimeout(function(){

    // After the PRELOAD_ms interval, then we stop the playing video
    _player[_active].stopVideo();

    // Toggle the player pointers
    _active = (_active + 1) % 2;
    _next = (_active + 1) % 2;

    // When you toggle the visibility, there is still an annoying spinner.
    // So to avoid this we just "move" the players off screen that aren't
    // being used.
    document.getElementById("player-" + _active).style.left = "0%";
    document.getElementById("player-" + _next).style.left = "-200%";
    document.getElementById("player-" + EXTRA).style.left = "-200%";

    // Crank up the volume to the computed normalization
    // level.
    _player[_active].playVideo();
    _player[_active].index = _index;

    // Make sure that we observe the volume settings.
    if(_muted) {
      _player[_active].setVolume(0);
    } else {
      _player[_active].setVolume(_duration[_index][VOLUME]);
    }

    setQuality();
  }, remainingTime() * 1000);
}

(function(){
  // Load two players to be transitioned between at a nominal
  // resolution ... this is irrelevant as quality will be
  // managed in a more sophisticated manner than size of screen.
  for(var ix = 0; ix < 3; ix++) {

    swfobject.embedSWF("http://www.youtube.com/apiplayer?" + [
      "version=3",
      "enablejsapi=1",
      "playerapiid=player-" + ix
    ].join('&'),  // swfUrl
      "vid" + ix, // id
      "400",      // width
      "300",      // height
      "9",        // [false] version (the flv2 player (flash 8) has ad-free vevo, so we use the old player)
      null,       // express install swf url (we assume you have the flash player)
      null,       // flash vars

      {
        allowScriptAccess: "always"
      }, // params

      // This little hack forces our small mt80s logo to the bottom left so
      // the user can click on it at any time.
      {
        wmode: "transparent",
        id: 'player-' + ix
      }, // attributes

      new Function()                 // yt doesn't do the callbackfunction
    );
  }
})();
<|endoftext|>


<commit_before>'use strict';

angular.module('mwNav', [])

    .directive('mwSubNav', function () {
      return {
        restrict: 'A',
        scope: {
          justified: '='
        },
        replace: true,
        transclude: true,
        template: '

'
      };
    })

    .directive('mwSubNavPill', function ($location) {
      return {
        restrict: 'A',
        scope: {
          url: '@mwSubNavPill',
          mwDisabled: '='
        },
        transclude: true,
        replace: true,
        template: '

',
        link: function (scope, elm) {
          var setActiveClassOnUrlMatch = function (url) {
            if (scope.url && url === scope.url.slice(1)) {
              elm.addClass('active');
            } else {
              elm.removeClass('active');
            }
          };

          scope.$watch('url', function (newUrlAttr) {
            if (newUrlAttr) {
              setActiveClassOnUrlMatch($location.$$path);
            }
          });

          scope.navigate = function(url){
            if(!scope.mwDisabled){
              url = url.replace(/#\//,'');
              $location.path(url);
              $location.replace();
            }
          };

          setActiveClassOnUrlMatch($location.$$path);

        }
      };
    })

    .directive('mwNavbar', function ($location) {
      return {
        transclude: true,
        replace: true,
        templateUrl: 'modules/ui/templates/mwNav/mwNavbar.html',
        controller: function () {
          this.isActive = function (path, exact) {
            if(!path) {
              return false;
            }
            var newPath = path.substring(1);
            if(exact){
              return $location.path() === newPath;
            }
            return $location.path().indexOf(newPath) > -1;
          };
        }
      };
    })

    .directive('mwNavbarContent', function () {
      return {
        transclude: true,
        replace: true,
        template: '

',
        link: function(scope, elm) {
          scope.uncollapse = function() {
            if(elm.hasClass('in')) {
              elm.collapse('hide');
            }
          };
        }
      };
    })

    .directive('mwNavbarBrand', function () {
      return {
        transclude: true,
        replace: true,
        templateUrl: 'modules/ui/templates/mwNav/mwNavbarBrand.html'
      };
    })

    .directive('mwNavbarItems', function () {
      return {
        transclude: true,
        replace: true,
        template: '

',
        link: function (scope, elm, attr) {

          if(attr.mwNavbarItems) {
            elm.addClass('navbar-' + attr.mwNavbarItems);
          }

          elm.on('click', function () {
            if (elm.hasClass('in')) {
              elm.collapse('hide');
            }
          });
        }
      };
    })

    .directive('mwNavbarItem', function ($rootScope) {
      return {
        transclude: true,
        replace: true,
        scope: true,
        require: '^mwNavbar',
        template: '

',
        link: function (scope, elm, attr, mwNavbarCtrl) {
          var isActive = function () {
            scope.isActive = mwNavbarCtrl.isActive(elm.find('a').attr('href'));
          };
          isActive();
          $rootScope.$on('$routeChangeSuccess', isActive);

          elm.find('a').on('click', function() {
            scope.uncollapse();
          });
        }
      };
    })

    .directive('mwNavbarDropdown', function ($rootScope) {
      return {
        replace: true,
        require: '^mwNavbar',
        transclude: true,
        template: '

',
        link: function (scope, elm, attr, mwNavbarCtrl) {
          var isActive = function () {
            var active = false;
            angular.forEach(scope.dropdownItems, function (path) {
              if (!active) {
                active = mwNavbarCtrl.isActive(path);
              }
            });
            scope.isActive = active;
          };
          isActive();
          $rootScope.$on('$routeChangeSuccess', isActive);
        },
        controller: function ($scope) {
          var dropdownItems = $scope.dropdownItems = [];
          this.register = function (path) {
            dropdownItems.push(path);
          };
        }
      };
    })

    .directive('mwNavbarDropdownTitle', function () {
      return {
        replace: true,
        transclude: true,
        template: ' '
      };
    })

    .directive('mwNavbarDropdownItems', function () {
      return {
        transclude: true,
        replace: true,
        template: '

'
      };
    })

    .directive('mwNavbarDropdownItem', function ($rootScope) {
      return {
        transclude: true,
        replace: true,
        scope: true,
        require: ['^mwNavbarDropdown', '^mwNavbar'],
        template: '

',
        link: function (scope, elm, attr, ctrls) {
          var link = elm.find('a').attr('href'),
              mwNavbarDropdownItemsCtrl = ctrls[0],
              mwNavbarCtrl = ctrls[1];

          if(mwNavbarDropdownItemsCtrl){
            mwNavbarDropdownItemsCtrl.register(link);
          }

          var isActive = function () {
            scope.isActive = mwNavbarCtrl ? mwNavbarCtrl.isActive(link, true) : false;
          };
          isActive();

          $rootScope.$on('$routeChangeSuccess', isActive);

          elm.find('a').on('click', function() {
            scope.uncollapse();
          });
        }
      };
    })

;<commit_msg>fix @MDM-6391 Tooltip deactivated when workflow deactivated<commit_after>'use strict';

angular.module('mwNav', [])

    .directive('mwSubNav', function () {
      return {
        restrict: 'A',
        scope: {
          justified: '='
        },
        replace: true,
        transclude: true,
        template: '

'
      };
    })

    .directive('mwSubNavPill', function ($location) {
      return {
        restrict: 'A',
        scope: {
          url: '@mwSubNavPill',
          mwDisabled: '='
        },
        transclude: true,
        replace: true,
        template:
          '
' +
            '
' +
            '
' +
          '
',
        link: function (scope, elm) {
          var setActiveClassOnUrlMatch = function (url) {
            if (scope.url && url === scope.url.slice(1)) {
              elm.addClass('active');
            } else {
              elm.removeClass('active');
            }
          };

          scope.$watch('url', function (newUrlAttr) {
            if (newUrlAttr) {
              setActiveClassOnUrlMatch($location.$$path);
            }
          });

          scope.navigate = function(url){
            if(!scope.mwDisabled){
              url = url.replace(/#\//,'');
              $location.path(url);
              $location.replace();
            }
          };

          setActiveClassOnUrlMatch($location.$$path);

        }
      };
    })

    .directive('mwNavbar', function ($location) {
      return {
        transclude: true,
        replace: true,
        templateUrl: 'modules/ui/templates/mwNav/mwNavbar.html',
        controller: function () {
          this.isActive = function (path, exact) {
            if(!path) {
              return false;
            }
            var newPath = path.substring(1);
            if(exact){
              return $location.path() === newPath;
            }
            return $location.path().indexOf(newPath) > -1;
          };
        }
      };
    })

    .directive('mwNavbarContent', function () {
      return {
        transclude: true,
        replace: true,
        template: '

',
        link: function(scope, elm) {
          scope.uncollapse = function() {
            if(elm.hasClass('in')) {
              elm.collapse('hide');
            }
          };
        }
      };
    })

    .directive('mwNavbarBrand', function () {
      return {
        transclude: true,
        replace: true,
        templateUrl: 'modules/ui/templates/mwNav/mwNavbarBrand.html'
      };
    })

    .directive('mwNavbarItems', function () {
      return {
        transclude: true,
        replace: true,
        template: '

',
        link: function (scope, elm, attr) {

          if(attr.mwNavbarItems) {
            elm.addClass('navbar-' + attr.mwNavbarItems);
          }

          elm.on('click', function () {
            if (elm.hasClass('in')) {
              elm.collapse('hide');
            }
          });
        }
      };
    })

    .directive('mwNavbarItem', function ($rootScope) {
      return {
        transclude: true,
        replace: true,
        scope: true,
        require: '^mwNavbar',
        template: '

',
        link: function (scope, elm, attr, mwNavbarCtrl) {
          var isActive = function () {
            scope.isActive = mwNavbarCtrl.isActive(elm.find('a').attr('href'));
          };
          isActive();
          $rootScope.$on('$routeChangeSuccess', isActive);

          elm.find('a').on('click', function() {
            scope.uncollapse();
          });
        }
      };
    })

    .directive('mwNavbarDropdown', function ($rootScope) {
      return {
        replace: true,
        require: '^mwNavbar',
        transclude: true,
        template: '

',
        link: function (scope, elm, attr, mwNavbarCtrl) {
          var isActive = function () {
            var active = false;
            angular.forEach(scope.dropdownItems, function (path) {
              if (!active) {
                active = mwNavbarCtrl.isActive(path);
              }
            });
            scope.isActive = active;
          };
          isActive();
          $rootScope.$on('$routeChangeSuccess', isActive);
        },
        controller: function ($scope) {
          var dropdownItems = $scope.dropdownItems = [];
          this.register = function (path) {
            dropdownItems.push(path);
          };
        }
      };
    })

    .directive('mwNavbarDropdownTitle', function () {
      return {
        replace: true,
        transclude: true,
        template: ' '
      };
    })

    .directive('mwNavbarDropdownItems', function () {
      return {
        transclude: true,
        replace: true,
        template: '

'
      };
    })

    .directive('mwNavbarDropdownItem', function ($rootScope) {
      return {
        transclude: true,
        replace: true,
        scope: true,
        require: ['^mwNavbarDropdown', '^mwNavbar'],
        template: '

',
        link: function (scope, elm, attr, ctrls) {
          var link = elm.find('a').attr('href'),
              mwNavbarDropdownItemsCtrl = ctrls[0],
              mwNavbarCtrl = ctrls[1];

          if(mwNavbarDropdownItemsCtrl){
            mwNavbarDropdownItemsCtrl.register(link);
          }

          var isActive = function () {
            scope.isActive = mwNavbarCtrl ? mwNavbarCtrl.isActive(link, true) : false;
          };
          isActive();

          $rootScope.$on('$routeChangeSuccess', isActive);

          elm.find('a').on('click', function() {
            scope.uncollapse();
          });
        }
      };
    })

;<|endoftext|>