<commit_before>angular.module('HomepageModule').controller('AppCtrl', ['$scope', '$mdBottomSheet','$mdSidenav', '$mdDialog', '$templateCache', '$http',
  function($scope, $mdBottomSheet, $mdSidenav, $mdDialog, $templateCache, $http){

  // Toolbar search toggle
  $scope.toggleSearch = function(element) {
    $scope.showSearch = !$scope.showSearch;
  };

  // Sidenav toggle
  $scope.toggleSidenav = function(menuId) {
    $mdSidenav(menuId).toggle();
  };

  // Menu items
  $scope.menu = [
  {
    link : '',
    title: 'Dashboard',
      icon: 'action:ic_dashboard_24px' // we have to use Google's naming convention for the IDs of the SVGs in the spritesheet
    },
    {
      link : '',
      title: 'Friends',
      icon: 'social:ic_group_24px'
    },
    {
      link : '',
      title: 'Messages',
      icon: 'communication:ic_message_24px'
    }
    ];
    $scope.admin = [
    {
      link : '',
      title: 'Trash',
      icon: 'action:ic_delete_24px'
    },
    {
      link : 'showListBottomSheet($event)',
      title: 'Settings',
      icon: 'action:ic_settings_24px'
    }
    ];

  // Mock activity
  $scope.activity = [
  {
    what: 'Brunch this weekend?',
    who: 'Ali Conners',
    avatar: 'svg-1',
    when: '3:08PM',
    notes: " I'll be in your neighborhood doing errands"
  },
  {
    what: 'Summer BBQ',
    who: 'to Alex, Scott, Jennifer',
    avatar: 'svg-2',
    when: '3:08PM',
    notes: "Wish I could come out but I'm out of town this weekend"
  },
  {
    what: 'Oui Oui',
    who: 'Sandra Adams',
    avatar: 'svg-3',
    when: '3:08PM',
    notes: "Do you have Paris recommendations? Have you ever been?"
  },
  {
    what: 'Birthday Gift',
    who: 'Trevor Hansen',
    avatar: 'svg-4',
    when: '3:08PM',
    notes: "Have any ideas of what we should get Heidi for her birthday?"
  },
  {
    what: 'Recipe to try',
    who: 'Brian Holt',
    avatar: 'svg-5',
    when: '3:08PM',
    notes: "We should eat this: Grapefruit, Squash, Corn, and Tomatillo tacos"
  },
  ];

  // Bottomsheet & Modal Dialogs
  $scope.alert = '';
  $scope.showListBottomSheet = function($event) {
    $scope.alert = '';
    $mdBottomSheet.show({
      template: '<md-bottom-sheet class="md-list md-has-header"><md-list><md-list-item class="md-2-line" ng-repeat="item in items" role="link" md-ink-ripple><md-icon md-svg-icon="{{item.icon}}" aria-label="{{item.name}}"></md-icon>

{{item.name}}

</md-list-item> </md-list></md-bottom-sheet>',
      controller: 'ListBottomSheetCtrl',
      targetEvent: $event
    }).then(function(clickedItem) {
      $scope.alert = clickedItem.name + ' clicked!';
    });
  };

  $scope.showAdd = function(ev) {
    $http.get('poll.html', {cache:$templateCache});
    $mdDialog.show({
      controller: DialogController,
      title: 'Creation of a new STV Poll',
      template: $templateCache.get('poll.html'),
      clickOutsideToClose: true,
      targetEvent: ev,
    })
    .then(function(answer) {
      $scope.alert = 'You said the information was "' + answer + '".';
    }, function() {
      $scope.alert = 'You cancelled the dialog.';
    });
  };
}])

.controller('ListBottomSheetCtrl', function($scope, $mdBottomSheet) {
  $scope.items = [
  { name: 'Share', icon: 'social:ic_share_24px' },
  { name: 'Upload', icon: 'file:ic_cloud_upload_24px' },
  { name: 'Copy', icon: 'content:ic_content_copy_24px' },
  { name: 'Print this page', icon: 'action:ic_print_24px' },
  ];

  $scope.listItemClick = function($index) {
    var clickedItem = $scope.items[$index];
    $mdBottomSheet.hide(clickedItem);
  };
})

.config(function($mdThemingProvider) {
  var customBlueMap =     $mdThemingProvider.extendPalette('light-blue', {
    'contrastDefaultColor': 'light',
    'contrastDarkColors': ['50'],
    '50': 'ffffff'
  });
  $mdThemingProvider.definePalette('customBlue', customBlueMap);
  $mdThemingProvider.theme('default')
  .primaryPalette('customBlue', {
    'default': '500',
    'hue-1': '50'
  })
  .accentPalette('pink');
  $mdThemingProvider.theme('input', 'default')
  .primaryPalette('grey')
})

.config(function($mdIconProvider) {
  $mdIconProvider
      // linking to https://github.com/google/material-design-icons/tree/master/sprites/svg-sprite
      //
      .iconSet('action', 'svg/svg-sprite-action.svg', 24)
      .iconSet('alert', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-alert.svg', 24)
      .iconSet('av', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-av.svg', 24)
      .iconSet('communication', 'svg/svg-sprite-communication.svg', 24)
      .iconSet('content', 'svg/svg-sprite-content.svg', 24)
      .iconSet('device', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-device.svg', 24)
      .iconSet('editor', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-editor.svg', 24)
      .iconSet('file', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-file.svg', 24)
      .iconSet('hardware', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-hardware.svg', 24)
      .iconSet('image', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-image.svg', 24)
      .iconSet('maps', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-maps.svg', 24)
      .iconSet('navigation', 'svg/svg-sprite-navigation.svg', 24)
      .iconSet('notification', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-notification.svg', 24)
      .iconSet('social', 'svg/svg-sprite-social.svg', 24)
      .iconSet('toggle', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-toggle.svg', 24)

      // Illustrated user icons used in the docs https://material.angularjs.org/latest/#/demo/material.components.gridList
      .iconSet('avatars', 'svg/avatar-icons.svg', 24)
      .defaultIconSet('svg/svg-sprite-action.svg', 24);
    })

.controller('DatePicker', function($scope) {
  $scope.startDate = new Date();
  $scope.minDate = new Date(
    $scope.startDate.getFullYear(),
    $scope.startDate.getMonth(),
    $scope.startDate.getDate());
  $scope.maxDate = new Date(
    $scope.startDate.getFullYear(),
    $scope.startDate.getMonth() + 3,
    $scope.startDate.getDate());
})

.controller('CandidatesCtrl', function($scope) {
  // Set the loading state (i.e. show loading spinner)
  $scope.poll_form = {
    loading: false
  }

  $scope.poll_form.candidates = [];
  $scope.createCandidate = function($event, from_button) {
    $event.preventDefault();
    if ((from_button || $event.keyCode == 13) && $scope.poll_form.candidate) {
      $scope.poll_form.candidates.push({name: $scope.poll_form.candidate, desc: $scope.poll_form.can_desc, cancolor:$scope.poll_form.cancolor});
      $scope.poll_form.candidate = '';
      $scope.poll_form.can_desc = '';
      $scope.poll_form.cancolor = '';
    }
    console.log("heey ");
  };
  $scope.removeCandidate = function($index, item) {
    $scope.poll_form.candidates.splice($index, 1);
  };
})

.controller('pollForm', ['$scope', function($scope){
  // populate
  console.log($scope.poll_form);
  $scope.submitPollForm = function() {
    console.log('In submit poll form');
}
}])

.controller('DemoCtrl', DemoCtrl);
function DemoCtrl ($timeout, $q) {
  var self = this;
    // list of `state` value/display objects
    self.states        = loadAll();
    self.selectedItem  = null;
    self.searchText    = null;
    self.querySearch   = querySearch;
    // ******************************
    // Internal methods
    // ******************************
    /**
     * Search for states... use $timeout to simulate
     * remote dataservice call.
     */
     function querySearch (query) {
      var results = query ? self.states.filter( createFilterFor(query) ) : [];
      return results;
    }
    /**
     * Build `states` list of key/value pairs
     */
     function loadAll() {
      var allStates = 'Ali Conners, Alex, Scott, Jennifer, \
      Sandra Adams, Brian Holt, \
      Trevor Hansen';
      return allStates.split(/, +/g).map( function (state) {
        return {
          value: state.toLowerCase(),
          display: state
        };
      });
    }
    /**
     * Create filter function for a query string
     */
     function createFilterFor(query) {
      var lowercaseQuery = angular.lowercase(query);
      return function filterFn(state) {
        return (state.value.indexOf(lowercaseQuery) === 0);
      };
    }
  };

  function DialogController($scope, $mdDialog) {
    // populate
    $scope.hide = function() {
      $mdDialog.hide();
    };
    $scope.cancel = function() {
      $mdDialog.cancel();
    };

    $scope.answer = function(answer) {
      // Submit request to Sails.
      console.log('sending');
      return ;
      $http.post('/poll', {
        name: $scope.signupForm.name,
        title: $scope.signupForm.title,
        email: $scope.signupForm.email,
        password: $scope.signupForm.password
      })
      .then(function onSuccess(sailsResponse){
        window.location = '/';
      })
      .catch(function onError(sailsResponse){

    // Handle known error type(s).
    // If using sails-disk adpater -- Handle Duplicate Key
    var emailAddressAlreadyInUse = sailsResponse.status == 409;

    if (emailAddressAlreadyInUse) {
      toastr.error('That email address has already been taken, please try again.', 'Error');
      return;
    }
  })
      .finally(function eitherWay(){
        $scope.signupForm.loading = false;
      })
      $mdDialog.hide(answer);
    };
  };

  // // set-up loginForm loading state
  // $scope.loginForm = {
    //   loading: false
    // }

    // $scope.submitLoginForm = function (){

      //   // Set the loading state (i.e. show loading spinner)
      //   $scope.loginForm.loading = true;

      //   // Submit request to Sails.
      //   $http.put('/login', {
        //     email: $scope.loginForm.email,
        //     password: $scope.loginForm.password
        //   })
      //   .then(function onSuccess (){
        //     // Refresh the page now that we've been logged in.
        //     window.location = '/';
        //   })
      //   .catch(function onError(sailsResponse) {

        //     // Handle known error type(s).
        //     // Invalid username / password combination.
        //     if (sailsResponse.status === 400 || 404) {
          //       // $scope.loginForm.topLevelErrorMessage = 'Invalid email/password combination.';
          //       //
          //       toastr.error('Invalid email/password combination.', 'Error', {
            //         closeButton: true
            //       });
          //       return;
          //     }

          //       toastr.error('An unexpected error occurred, please try again.', 'Error', {
            //         closeButton: true
            //       });
          //       return;

          //   })
      //   .finally(function eitherWay(){
        //     $scope.loginForm.loading = false;
        //   });
      // };
<commit_msg>trying to push<commit_after>angular.module('HomepageModule').controller('AppCtrl', ['$scope', '$mdBottomSheet','$mdSidenav', '$mdDialog', '$templateCache', '$http',
  function($scope, $mdBottomSheet, $mdSidenav, $mdDialog, $templateCache, $http){

  // Toolbar search toggle
  $scope.toggleSearch = function(element) {
    $scope.showSearch = !$scope.showSearch;
  };

  // Sidenav toggle
  $scope.toggleSidenav = function(menuId) {
    $mdSidenav(menuId).toggle();
  };

  // Menu items
  $scope.menu = [
  {
    link : '',
    title: 'Dashboard',
      icon: 'action:ic_dashboard_24px' // we have to use Google's naming convention for the IDs of the SVGs in the spritesheet
    },
    {
      link : '',
      title: 'Friends',
      icon: 'social:ic_group_24px'
    },
    {
      link : '',
      title: 'Messages',
      icon: 'communication:ic_message_24px'
    }
    ];
    $scope.admin = [
    {
      link : '',
      title: 'Trash',
      icon: 'action:ic_delete_24px'
    },
    {
      link : 'showListBottomSheet($event)',
      title: 'Settings',
      icon: 'action:ic_settings_24px'
    }
    ];

  // Mock activity
  $scope.activity = [
  {
    what: 'Brunch this weekend?',
    who: 'Ali Conners',
    avatar: 'svg-1',
    when: '3:08PM',
    notes: " I'll be in your neighborhood doing errands"
  },
  {
    what: 'Summer BBQ',
    who: 'to Alex, Scott, Jennifer',
    avatar: 'svg-2',
    when: '3:08PM',
    notes: "Wish I could come out but I'm out of town this weekend"
  },
  {
    what: 'Oui Oui',
    who: 'Sandra Adams',
    avatar: 'svg-3',
    when: '3:08PM',
    notes: "Do you have Paris recommendations? Have you ever been?"
  },
  {
    what: 'Birthday Gift',
    who: 'Trevor Hansen',
    avatar: 'svg-4',
    when: '3:08PM',
    notes: "Have any ideas of what we should get Heidi for her birthday?"
  },
  {
    what: 'Recipe to try',
    who: 'Brian Holt',
    avatar: 'svg-5',
    when: '3:08PM',
    notes: "We should eat this: Grapefruit, Squash, Corn, and Tomatillo tacos"
  },
  ];

  // Bottomsheet & Modal Dialogs
  $scope.alert = '';
  $scope.showListBottomSheet = function($event) {
    $scope.alert = '';
    $mdBottomSheet.show({
      template: '<md-bottom-sheet class="md-list md-has-header"><md-list><md-list-item class="md-2-line" ng-repeat="item in items" role="link" md-ink-ripple><md-icon md-svg-icon="{{item.icon}}" aria-label="{{item.name}}"></md-icon>

{{item.name}}

</md-list-item> </md-list></md-bottom-sheet>',
      controller: 'ListBottomSheetCtrl',
      targetEvent: $event
    }).then(function(clickedItem) {
      $scope.alert = clickedItem.name + ' clicked!';
    });
  };

  $scope.showAdd = function(ev) {
    $http.get('poll.html', {cache:$templateCache});
    $mdDialog.show({
      controller: DialogController,
      title: 'Creation of a new STV Poll',
      template: $templateCache.get('poll.html'),
      clickOutsideToClose: true,
      targetEvent: ev,
    })
    .then(function(answer) {
      $scope.alert = 'You said the information was "' + answer + '".';
    }, function() {
      $scope.alert = 'You cancelled the dialog.';
    });
  };
}])

.controller('ListBottomSheetCtrl', function($scope, $mdBottomSheet) {
  $scope.items = [
  { name: 'Share', icon: 'social:ic_share_24px' },
  { name: 'Upload', icon: 'file:ic_cloud_upload_24px' },
  { name: 'Copy', icon: 'content:ic_content_copy_24px' },
  { name: 'Print this page', icon: 'action:ic_print_24px' },
  ];

  $scope.listItemClick = function($index) {
    var clickedItem = $scope.items[$index];
    $mdBottomSheet.hide(clickedItem);
  };
})

.config(function($mdThemingProvider) {
  var customBlueMap =     $mdThemingProvider.extendPalette('light-blue', {
    'contrastDefaultColor': 'light',
    'contrastDarkColors': ['50'],
    '50': 'ffffff'
  });
  $mdThemingProvider.definePalette('customBlue', customBlueMap);
  $mdThemingProvider.theme('default')
  .primaryPalette('customBlue', {
    'default': '500',
    'hue-1': '50'
  })
  .accentPalette('pink');
  $mdThemingProvider.theme('input', 'default')
  .primaryPalette('grey')
})

.config(function($mdIconProvider) {
  $mdIconProvider
      // linking to https://github.com/google/material-design-icons/tree/master/sprites/svg-sprite
      //
      .iconSet('action', 'svg/svg-sprite-action.svg', 24)
      .iconSet('alert', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-alert.svg', 24)
      .iconSet('av', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-av.svg', 24)
      .iconSet('communication', 'svg/svg-sprite-communication.svg', 24)
      .iconSet('content', 'svg/svg-sprite-content.svg', 24)
      .iconSet('device', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-device.svg', 24)
      .iconSet('editor', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-editor.svg', 24)
      .iconSet('file', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-file.svg', 24)
      .iconSet('hardware', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-hardware.svg', 24)
      .iconSet('image', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-image.svg', 24)
      .iconSet('maps', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-maps.svg', 24)
      .iconSet('navigation', 'svg/svg-sprite-navigation.svg', 24)
      .iconSet('notification', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-notification.svg', 24)
      .iconSet('social', 'svg/svg-sprite-social.svg', 24)
      .iconSet('toggle', 'https://raw.githubusercontent.com/google/material-design-icons/master/sprites/svg-sprite/svg-sprite-toggle.svg', 24)

      // Illustrated user icons used in the docs https://material.angularjs.org/latest/#/demo/material.components.gridList
      .iconSet('avatars', 'svg/avatar-icons.svg', 24)
      .defaultIconSet('svg/svg-sprite-action.svg', 24);
    })

.controller('DatePicker', function($scope) {
  $scope.startDate = new Date();
  $scope.minDate = new Date(
    $scope.startDate.getFullYear(),
    $scope.startDate.getMonth(),
    $scope.startDate.getDate());
  $scope.maxDate = new Date(
    $scope.startDate.getFullYear(),
    $scope.startDate.getMonth() + 3,
    $scope.startDate.getDate());
})

.controller('CandidatesCtrl', function($scope) {
  // Set the loading state (i.e. show loading spinner)
  $scope.poll_form = {
    loading: false
  }

  $scope.poll_form.candidates = [];
  $scope.createCandidate = function($event, from_button) {
    $event.preventDefault();
    if ((from_button || $event.keyCode == 13) && $scope.poll_form.candidate) {
      $scope.poll_form.candidates.push({name: $scope.poll_form.candidate, desc: $scope.poll_form.can_desc, cancolor:$scope.poll_form.cancolor});
      $scope.poll_form.candidate = '';
      $scope.poll_form.can_desc = '';
      $scope.poll_form.cancolor = '';
    }
    console.log("heey ");
  };
  $scope.removeCandidate = function($index, item) {
    $scope.poll_form.candidates.splice($index, 1);
  };
})

.controller('pollForm', ['$scope', function($scope){
  // populate
  console.log($scope.poll_form);
  $scope.submitPollForm = function() {
    console.log('In submit poll form');
}
}])

.controller('DemoCtrl', DemoCtrl);
function DemoCtrl ($timeout, $q) {
  var self = this;
    // list of `state` value/display objects
    self.states        = loadAll();
    self.selectedItem  = null;
    self.searchText    = null;
    self.querySearch   = querySearch;
    // ******************************
    // Internal methods
    // ******************************
    /**
     * Search for states... use $timeout to simulate
     * remote dataservice call.
     */
     function querySearch (query) {
      var results = query ? self.states.filter( createFilterFor(query) ) : [];
      return results;
    }
    /**
     * Build `states` list of key/value pairs
     */
     function loadAll() {
      var allStates = 'Ali Conners, Alex, Scott, Jennifer, \
      Sandra Adams, Brian Holt, \
      Trevor Hansen';
      return allStates.split(/, +/g).map( function (state) {
        return {
          value: state.toLowerCase(),
          display: state
        };
      });
    }
    /**
     * Create filter function for a query string
     */
     function createFilterFor(query) {
      var lowercaseQuery = angular.lowercase(query);
      return function filterFn(state) {
        return (state.value.indexOf(lowercaseQuery) === 0);
      };
    }
  };

  function DialogController($scope, $mdDialog) {
    // populate
    $scope.hide = function() {
      $mdDialog.hide();
    };
    $scope.cancel = function() {
      $mdDialog.cancel();
    };

    $scope.answer = function(answer) {
      // Submit request to Sails.
      console.log('sending');
      return ;
      $http.post('/poll', {
        name: $scope.signupForm.name,
        title: $scope.signupForm.title,
        email: $scope.signupForm.email,
        password: $scope.signupForm.password
      })
      .then(function onSuccess(sailsResponse){
        window.location = '/';
      })
      .catch(function onError(sailsResponse){

    // Handle known error type(s).
    // If using sails-disk adpater -- Handle Duplicate Key
    var emailAddressAlreadyInUse = sailsResponse.status == 409;

    if (emailAddressAlreadyInUse) {
      toastr.error('That email address has already been taken, please try again.', 'Error');
      return;
    }
  })
      .finally(function eitherWay(){
        $scope.signupForm.loading = false;
      })
      $mdDialog.hide(answer);
    };
  };

  // // set-up loginForm loading state
  // $scope.loginForm = {
    //   loading: false
    // }

    // $scope.submitLoginForm = function (){

      //   // Set the loading state (i.e. show loading spinner)
      //   $scope.loginForm.loading = true;

      //   // Submit request to Sails.
      //   $http.put('/login', {
        //     email: $scope.loginForm.email,
        //     password: $scope.loginForm.password
        //   })
      //   .then(function onSuccess (){
        //     // Refresh the page now that we've been logged in.
        //     window.location = '/';
        //   })
      //   .catch(function onError(sailsResponse) {

        //     // Handle known error type(s).
        //     // Invalid username / password combination.
        //     if (sailsResponse.status === 400 || 404) {
          //       // $scope.loginForm.topLevelErrorMessage = 'Invalid email/password combination.';
          //       //
          //       toastr.error('Invalid email/password combination.', 'Error', {
            //         closeButton: true
            //       });
          //       return;
          //     }

          //       toastr.error('An unexpected error occurred, please try again.', 'Error', {
            //         closeButton: true
            //       });
          //       return;

          //   })
      //   .finally(function eitherWay(){
        //     $scope.loginForm.loading = false;
        //   });
      // };
 <|endoftext|>


<commit_before>export default class MarqueeWizardCtrl {

  /**
   * @param {ng.IScope} $scope
   * @param {ng.ITimeoutService} $timeout
   */
  constructor($scope, $timeout) {

    // watch for changes to the button options
    const optionsWatcher = $scope.$watch('buttonOptions', (nv, ov) => {
      if (!angular.equals(nv, ov)) {
        this.updateButtonOptions();
      }
    }, true);

    // watch for any changes to the visible steps
    const stepWatcher = $scope.$watch(() => this.wizardSteps, () => this.updateButtonVisibility(), true);

    // cleanup afterwards
    $scope.$on('$destroy', () => {
      // remove the options watcher
      optionsWatcher();

      // remove the step watcher
      stepWatcher();
    });

    // Delay initial setup until we have all the required values
    $timeout(() => this.initialise());
  }

  initialise() {
    //initially set the completed state to false for each step
    this.processSteps();

    //select the first step initially
    this.stepIndex = this.wizardSteps.findIndex(step => !step.hidden);
    this.currentStep = this.wizardSteps[this.stepIndex];
    this.currentStep.visited = true;
    this.currentStep.error = false;

    //side info
    this.sidePanelTitle = this.sideInfo ? this.sideInfo.title : null;
    this.sidePanelDescription = this.sideInfo ? this.sideInfo.description : null;

    //process the button options
    this.updateButtonOptions();

    //determine which buttons to show
    this.updateButtonVisibility();
  }

  //allow the user to go to the next step
  goNext() {

    //check if we are on the last page
    if (this.stepIndex === this.wizardSteps.length - 1) return;

    //if on change function specified call it and await its response
    if (typeof this.onChanging === 'function') {

      const response = this.onChanging(this.stepIndex, this.stepIndex + 1);

      //dont go to the next page if the response is false
      if (response === false) {
        this.currentStep.error = true;
        return;
      }

      //check if the next step is visible
      while (this.stepIndex !== this.wizardSteps.length - 1) {
        if (this.wizardSteps[this.stepIndex + 1].hidden === true) {
          this.stepIndex += 1;
        } else {
          break;
        }
      }

      if (angular.isNumber(response) && response >= 0 && response < this.wizardSteps.length && !this.wizardSteps[response].hidden) {
        this.stepIndex = response;
      } else {
        this.stepIndex++;
      }
      this.currentStep.error = false;
    }

    //mark page as completed and visited
    this.currentStep.completed = true;

    //move to the next page
    this.currentStep = this.wizardSteps[this.stepIndex];

    //mark the new step as visited
    this.currentStep.visited = true;

    //determine which buttons to show
    this.updateButtonVisibility();
  }

  //allow the user to go to the previous step
  goPrevious() {

    //check if we are on the first page
    if (this.stepIndex === 0) return;

    //if on change function specified call it and await its response
    if (typeof this.onChanging === 'function') {
      const response = this.onChanging(this.stepIndex, this.stepIndex - 1);

      //check if the next step is visible
      while (this.stepIndex !== 0) {
        if (this.wizardSteps[this.stepIndex - 1].hidden === true) {
          this.stepIndex -= 1;
        } else {
          break;
        }
      }

      //dont go to the previous page if the response is false
      if (response === false) {
        return;
      }
      if (angular.isNumber(response) && response >= 0 && response < this.wizardSteps.length && !this.wizardSteps[response].hidden) {
        this.stepIndex = response;
      } else {
        this.stepIndex--;
      }
    }

    this.currentStep.error = false;

    //move to the next page
    this.currentStep = this.wizardSteps[this.stepIndex];

    //determine which buttons to show
    this.updateButtonVisibility();
  }

  //allow the user to finish
  finish() {

    //if on finishing function specified call it and await its response
    if (typeof this.onFinishing === 'function') {
      // determine whether or not we can proceed
      return this.canFinish(this.onFinishing());
    }

    // if there is on onFinishing function then we can always complete
    this.complete();
  }

  canFinish(response) {

    // start by making the current step valid unless we detect otherwise
    this.currentStep.error = false;

    // if the response is true then proceed
    if (response === true) {
      return this.complete();
    }

    // if the response is false then do not proceed
    if (response === false) {
      this.currentStep.error = true;
      return;
    }

    // if we returned a number then go to that specific step
    if (typeof response === 'number') {
      return this.goToStep(response);
    }

    // if a promise was return wait the promise response before continuing
    if (response && typeof response.then === 'function') {
      response.then(result => this.canFinish(result));
    }
  }

  complete() {

    //mark the final step as complete
    this.currentStep.completed = true;

    //if a function was specified to be called when the finish button is clicked call it
    if (typeof this.onFinished === 'function') this.onFinished();
  }

  //if modal is dimissed using the close button
  cancel() {
    //if a function was specified to be called when the modal is canceled then call it
    if (typeof this.onCanceled === 'function') this.onCanceled();
  }

  goToStep(stepIdx) {
    const targetStep = this.wizardSteps[stepIdx];

    if (targetStep.visited === true) {

      if (typeof this.onChanging === 'function') {
        const response = this.onChanging(this.stepIndex, stepIdx);

        //dont go to the selected step if the response is false
        if (response === false) {
          return;
        }
      }

      this.currentStep.error = false;
      this.stepIndex = stepIdx;
      this.currentStep = this.wizardSteps[this.stepIndex];

      //determine which buttons to show
      this.updateButtonVisibility();
    }
  }

  /*
    Private Functions
  */
  processSteps() {
    //add an additional property on the steps to store its completed and visited state
    this.wizardSteps.forEach(step => {
      step.completed = false;
      step.visited = this.isVisited !== null || this.isVisited !== undefined ? this.isVisited : false;
    });
  }

  updateButtonVisibility() {

    //set initially hide all the buttons
    this.showPrevious = false;
    this.showNext = false;
    this.showFinish = false;

    //show buttons accordingly
    if (this.stepIndex > 0 && this.buttonOptions.showPrevious === true) {
      this.showPrevious = true;
    }

    if (this.stepIndex === this.wizardSteps.length - 1 && this.buttonOptions.showFinish === true) {
      this.showFinish = true;
    } else if (this.buttonOptions.showNext) {
      this.showNext = true;
    }

    if (!this.showFinish && this.buttonOptions.showFinish === true && this.stepIndex !== this.wizardSteps.length) {
      this.showFinish = this.wizardSteps.slice(this.stepIndex + 1).filter(step => step.hidden !== true).length === 0;
      this.showNext = !this.showFinish;
    }

    // Override per-step
    if (angular.isFunction(this.buttonOptions.visibilityOnStep)) {
      const visibility = this.buttonOptions.visibilityOnStep(this.stepIndex);
      this.showPrevious = visibility.hasOwnProperty('previous') ? visibility.previous : this.showPrevious;
      this.showNext = visibility.hasOwnProperty('next') ? visibility.next : this.showNext;
      this.showFinish = visibility.hasOwnProperty('finish') ? visibility.finish : this.showFinish;
    }
  }

  updateButtonOptions() {

    const defaultOptions = {
      previousText: 'Previous',
      nextText: 'Next',
      finishText: 'Finish',
      showPrevious: true,
      showNext: true,
      showFinish: true,
      previousTooltip: null,
      nextTooltip: null,
      finishTooltip: null,
      previousEnabled: true,
      nextEnabled: true,
      finishEnabled: true
    };

    //store the button options
    this.buttonOptions = angular.extend(defaultOptions, this.buttonOptions);
  }

}

MarqueeWizardCtrl.$inject = ['$scope', '$timeout'];<commit_msg>EL-3240 - Marquee Wizard QA Fix (#835)<commit_after>export default class MarqueeWizardCtrl {

  /**
   * @param {ng.IScope} $scope
   * @param {ng.ITimeoutService} $timeout
   */
  constructor($scope, $timeout) {

    // watch for changes to the button options
    const optionsWatcher = $scope.$watch('buttonOptions', (nv, ov) => {
      if (!angular.equals(nv, ov)) {
        this.updateButtonOptions();
      }
    }, true);

    // watch for any changes to the visible steps
    const stepWatcher = $scope.$watch(() => this.wizardSteps, () => this.updateButtonVisibility(), true);

    // cleanup afterwards
    $scope.$on('$destroy', () => {
      // remove the options watcher
      optionsWatcher();

      // remove the step watcher
      stepWatcher();
    });

    // Delay initial setup until we have all the required values
    $timeout(() => this.initialise());
  }

  initialise() {
    //initially set the completed state to false for each step
    this.processSteps();

    //select the first step initially
    this.stepIndex = this.wizardSteps.findIndex(step => !step.hidden);
    this.currentStep = this.wizardSteps[this.stepIndex];
    this.currentStep.visited = true;
    this.currentStep.error = false;

    //side info
    this.sidePanelTitle = this.sideInfo ? this.sideInfo.title : null;
    this.sidePanelDescription = this.sideInfo ? this.sideInfo.description : null;

    //process the button options
    this.updateButtonOptions();

    //determine which buttons to show
    this.updateButtonVisibility();
  }

  //allow the user to go to the next step
  goNext() {

    //check if we are on the last page
    if (this.stepIndex === this.wizardSteps.length - 1) return;

    //if on change function specified call it and await its response
    if (typeof this.onChanging === 'function') {

      const response = this.onChanging(this.stepIndex, this.stepIndex + 1);

      //dont go to the next page if the response is false
      if (response === false) {
        this.currentStep.error = true;
        return;
      }

      //check if the next step is visible
      while (this.stepIndex !== this.wizardSteps.length - 1) {
        if (this.wizardSteps[this.stepIndex + 1].hidden === true) {
          this.stepIndex += 1;
        } else {
          break;
        }
      }

      if (angular.isNumber(response) && response >= 0 && response < this.wizardSteps.length && !this.wizardSteps[response].hidden) {
        this.stepIndex = response;
      } else {
        this.stepIndex++;
      }
      this.currentStep.error = false;
    }

    //mark page as completed and visited
    this.currentStep.completed = true;

    //move to the next page
    this.currentStep = this.wizardSteps[this.stepIndex];

    //mark the new step as visited
    this.currentStep.visited = true;

    //determine which buttons to show
    this.updateButtonVisibility();
  }

  //allow the user to go to the previous step
  goPrevious() {

    //check if we are on the first page
    if (this.stepIndex === 0) return;

    //if on change function specified call it and await its response
    if (typeof this.onChanging === 'function') {
      const response = this.onChanging(this.stepIndex, this.stepIndex - 1);

      //check if the next step is visible
      while (this.stepIndex !== 0) {
        if (this.wizardSteps[this.stepIndex - 1].hidden === true) {
          this.stepIndex -= 1;
        } else {
          break;
        }
      }

      //dont go to the previous page if the response is false
      if (response === false) {
        return;
      }
      if (angular.isNumber(response) && response >= 0 && response < this.wizardSteps.length && !this.wizardSteps[response].hidden) {
        this.stepIndex = response;
      } else {
        this.stepIndex--;
      }
    }

    this.currentStep.error = false;

    //move to the next page
    this.currentStep = this.wizardSteps[this.stepIndex];

    //determine which buttons to show
    this.updateButtonVisibility();
  }

  //allow the user to finish
  finish() {

    //if on finishing function specified call it and await its response
    if (typeof this.onFinishing === 'function') {
      // determine whether or not we can proceed
      return this.canFinish(this.onFinishing());
    }

    // if there is on onFinishing function then we can always complete
    this.complete();
  }

  canFinish(response) {

    // start by making the current step valid unless we detect otherwise
    this.currentStep.error = false;

    // if the response is true then proceed
    if (response === true) {
      return this.complete();
    }

    // if the response is false then do not proceed
    if (response === false) {
      this.currentStep.error = true;
      return;
    }

    // if we returned a number then go to that specific step
    if (typeof response === 'number') {
      return this.goToStep(response);
    }

    // if a promise was return wait the promise response before continuing
    if (response && typeof response.then === 'function') {
      response.then(result => this.canFinish(result));
    }
  }

  complete() {

    //mark the final step as complete
    this.currentStep.completed = true;

    //if a function was specified to be called when the finish button is clicked call it
    if (typeof this.onFinished === 'function') this.onFinished();
  }

  //if modal is dimissed using the close button
  cancel() {
    //if a function was specified to be called when the modal is canceled then call it
    if (typeof this.onCanceled === 'function') this.onCanceled();
  }

  goToStep(stepIdx) {
    const targetStep = this.wizardSteps[stepIdx];

    if (targetStep.visited === true) {

      if (typeof this.onChanging === 'function') {
        const response = this.onChanging(this.stepIndex, stepIdx);

        //dont go to the selected step if the response is false
        if (response === false) {
          return;
        }
      }

      this.currentStep.error = false;
      this.stepIndex = stepIdx;
      this.currentStep = this.wizardSteps[this.stepIndex];

      //determine which buttons to show
      this.updateButtonVisibility();
    }
  }

  /*
    Private Functions
  */
  processSteps() {
    //add an additional property on the steps to store its completed and visited state
    this.wizardSteps.forEach(step => {
      step.completed = false;
      step.visited = this.isVisited !== null || this.isVisited !== undefined ? this.isVisited : false;
    });
  }

  updateButtonVisibility() {

    //set initially hide all the buttons
    this.showPrevious = false;
    this.showNext = false;
    this.showFinish = false;

    // calculate the first visible step index
    const firstStepIdx = this.wizardSteps.findIndex(step => !step.hidden);

    //show buttons accordingly
    if (this.stepIndex > firstStepIdx && this.buttonOptions.showPrevious === true) {
      this.showPrevious = true;
    }

    if (this.stepIndex === this.wizardSteps.length - 1 && this.buttonOptions.showFinish === true) {
      this.showFinish = true;
    } else if (this.buttonOptions.showNext) {
      this.showNext = true;
    }

    if (!this.showFinish && this.buttonOptions.showFinish === true && this.stepIndex !== this.wizardSteps.length) {
      this.showFinish = this.wizardSteps.slice(this.stepIndex + 1).filter(step => step.hidden !== true).length === 0;
      this.showNext = !this.showFinish;
    }

    // Override per-step
    if (angular.isFunction(this.buttonOptions.visibilityOnStep)) {
      const visibility = this.buttonOptions.visibilityOnStep(this.stepIndex);
      this.showPrevious = visibility.hasOwnProperty('previous') ? visibility.previous : this.showPrevious;
      this.showNext = visibility.hasOwnProperty('next') ? visibility.next : this.showNext;
      this.showFinish = visibility.hasOwnProperty('finish') ? visibility.finish : this.showFinish;
    }
  }

  updateButtonOptions() {

    const defaultOptions = {
      previousText: 'Previous',
      nextText: 'Next',
      finishText: 'Finish',
      showPrevious: true,
      showNext: true,
      showFinish: true,
      previousTooltip: null,
      nextTooltip: null,
      finishTooltip: null,
      previousEnabled: true,
      nextEnabled: true,
      finishEnabled: true
    };

    //store the button options
    this.buttonOptions = angular.extend(defaultOptions, this.buttonOptions);
  }

}

MarqueeWizardCtrl.$inject = ['$scope', '$timeout'];<|endoftext|>


<commit_before>/*
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import { createPortal } from 'react-dom';
import styled from 'styled-components';
import {
  useLayoutEffect,
  useCallback,
  useState,
  useRef,
  useEffect,
} from 'react';
/**
 * Internal dependencies
 */
import { SCROLLBAR_WIDTH } from '../../constants';
import { getTransforms, getOffset } from './utils';

/**
 * Internal dependencies
 */

export const Placement = {
  // TOP
  TOP: 'top',
  TOP_START: 'top-start',
  TOP_END: 'top-end',
  // BOTTOM
  BOTTOM: 'bottom',
  BOTTOM_START: 'bottom-start',
  BOTTOM_END: 'bottom-end',
  // RIGHT
  RIGHT: 'right',
  RIGHT_START: 'right-start',
  RIGHT_END: 'right-end',
  // LEFT
  LEFT: 'left',
  LEFT_START: 'left-start',
  LEFT_END: 'left-end',
};

const Container = styled.div.attrs(
  ({ x, y, width, height, fillWidth, fillHeight }) => ({
    style: {
      left: `${x}px`,
      top: `${y}px`,
      ...(fillWidth ? { width: `${width}px` } : {}),
      ...(fillHeight ? { height: `${height}px` } : {}),
    },
  })
)`
  max-height: ${({ maxHeight }) =>
    maxHeight > 0 ? maxHeight + 'px' : 'initial'};
  overflow-y: auto;
  position: fixed;
  z-index: 2147483646;
  ${({ placement }) => getTransforms(placement)}

  /*
   * Custom gray scrollbars for Chromium & Firefox.
   */
  * {
    scrollbar-width: thin;
    scrollbar-color: ${({ theme }) => theme.colors.bg.v10}
      ${({ theme }) => theme.colors.bg.v12};
  }

  *::-webkit-scrollbar {
    width: ${SCROLLBAR_WIDTH}px;
    height: ${SCROLLBAR_WIDTH}px;
  }

  *::-webkit-scrollbar-track {
    background: ${({ theme }) => theme.colors.bg.v12};
  }

  *::-webkit-scrollbar-thumb {
    background-color: ${({ theme }) => theme.colors.fg.v5};
    border: 2px solid ${({ theme }) => theme.colors.bg.v12};
    border-left-width: 3px;
    border-top-width: 3px;
    border-radius: 6px;
  }
`;

function Popup({
  anchor,
  dock,
  children,
  placement = 'bottom',
  spacing,
  isOpen,
  fillWidth = false,
  fillHeight = false,
  maxHeight = 0,
}) {
  const [popupState, setPopupState] = useState(null);
  const [mounted, setMounted] = useState(false);
  const popup = useRef(null);

  const positionPopup = useCallback(
    (evt) => {
      if (!mounted) {
        return;
      }

      // If scrolling within the popup, ignore.
      if (evt?.target?.nodeType && popup.current?.contains(evt.target)) {
        return;
      }

      setPopupState({
        offset: getOffset(placement, spacing, anchor, dock, popup),
      });
    },
    [anchor, dock, placement, spacing, mounted]
  );

  useLayoutEffect(() => {
    setMounted(true);
    positionPopup();

    // Adjust the position when scrolling or resizing.
    window.addEventListener('resize', positionPopup);
    document.addEventListener('scroll', positionPopup, true);
    return () => {
      window.removeEventListener('resize', positionPopup);
      document.removeEventListener('scroll', positionPopup, true);
    };
  }, [positionPopup]);

  useEffect(() => {
    positionPopup();
  }, [placement, spacing, anchor, dock, popup, isOpen, positionPopup]);

  return popupState && isOpen
    ? createPortal(
        <Container
          ref={popup}
          {...popupState.offset}
          fillWidth={fillWidth}
          fillHeight={fillHeight}
          placement={placement}
          maxHeight={maxHeight}
        >
          {children}
        </Container>,
        document.body
      )
    : null;
}

export default Popup;
<commit_msg>Fix popup stacking with modals (#2045)<commit_after>/*
 * Copyright 2020 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * External dependencies
 */
import { createPortal } from 'react-dom';
import styled from 'styled-components';
import {
  useLayoutEffect,
  useCallback,
  useState,
  useRef,
  useEffect,
} from 'react';
/**
 * Internal dependencies
 */
import { SCROLLBAR_WIDTH } from '../../constants';
import { getTransforms, getOffset } from './utils';

/**
 * Internal dependencies
 */

export const Placement = {
  // TOP
  TOP: 'top',
  TOP_START: 'top-start',
  TOP_END: 'top-end',
  // BOTTOM
  BOTTOM: 'bottom',
  BOTTOM_START: 'bottom-start',
  BOTTOM_END: 'bottom-end',
  // RIGHT
  RIGHT: 'right',
  RIGHT_START: 'right-start',
  RIGHT_END: 'right-end',
  // LEFT
  LEFT: 'left',
  LEFT_START: 'left-start',
  LEFT_END: 'left-end',
};

const Container = styled.div.attrs(
  ({ x, y, width, height, fillWidth, fillHeight }) => ({
    style: {
      left: `${x}px`,
      top: `${y}px`,
      ...(fillWidth ? { width: `${width}px` } : {}),
      ...(fillHeight ? { height: `${height}px` } : {}),
    },
  })
)`
  max-height: ${({ maxHeight }) =>
    maxHeight > 0 ? maxHeight + 'px' : 'initial'};
  overflow-y: auto;
  position: fixed;
  z-index: 2;
  ${({ placement }) => getTransforms(placement)}

  /*
   * Custom gray scrollbars for Chromium & Firefox.
   */
  * {
    scrollbar-width: thin;
    scrollbar-color: ${({ theme }) => theme.colors.bg.v10}
      ${({ theme }) => theme.colors.bg.v12};
  }

  *::-webkit-scrollbar {
    width: ${SCROLLBAR_WIDTH}px;
    height: ${SCROLLBAR_WIDTH}px;
  }

  *::-webkit-scrollbar-track {
    background: ${({ theme }) => theme.colors.bg.v12};
  }

  *::-webkit-scrollbar-thumb {
    background-color: ${({ theme }) => theme.colors.fg.v5};
    border: 2px solid ${({ theme }) => theme.colors.bg.v12};
    border-left-width: 3px;
    border-top-width: 3px;
    border-radius: 6px;
  }
`;

function Popup({
  anchor,
  dock,
  children,
  placement = 'bottom',
  spacing,
  isOpen,
  fillWidth = false,
  fillHeight = false,
  maxHeight = 0,
}) {
  const [popupState, setPopupState] = useState(null);
  const [mounted, setMounted] = useState(false);
  const popup = useRef(null);

  const positionPopup = useCallback(
    (evt) => {
      if (!mounted) {
        return;
      }

      // If scrolling within the popup, ignore.
      if (evt?.target?.nodeType && popup.current?.contains(evt.target)) {
        return;
      }

      setPopupState({
        offset: getOffset(placement, spacing, anchor, dock, popup),
      });
    },
    [anchor, dock, placement, spacing, mounted]
  );

  useLayoutEffect(() => {
    setMounted(true);
    positionPopup();

    // Adjust the position when scrolling or resizing.
    window.addEventListener('resize', positionPopup);
    document.addEventListener('scroll', positionPopup, true);
    return () => {
      window.removeEventListener('resize', positionPopup);
      document.removeEventListener('scroll', positionPopup, true);
    };
  }, [positionPopup]);

  useEffect(() => {
    positionPopup();
  }, [placement, spacing, anchor, dock, popup, isOpen, positionPopup]);

  return popupState && isOpen
    ? createPortal(
        <Container
          ref={popup}
          {...popupState.offset}
          fillWidth={fillWidth}
          fillHeight={fillHeight}
          placement={placement}
          maxHeight={maxHeight}
        >
          {children}
        </Container>,
        document.body
      )
    : null;
}

export default Popup;
<|endoftext|>


<commit_before>import { assert } from "chai"
import { Manager } from "../src/manager.js"

describe("Manager", () => {

	it('can create', () => {
		var manager = new Manager;
		assert.instanceOf(manager, Manager);
	});

	it('can get feature', () => {
		var manager = new Manager;
		assert.equal(manager.get('experiment-1'), undefined);
	});

})
<commit_msg>test: Manager can set feature<commit_after>import { assert } from "chai"
import { Manager } from "../src/manager.js"

describe("Manager", () => {

	it('can create', () => {
		var manager = new Manager;
		assert.instanceOf(manager, Manager);
	});

	it('can get feature', () => {
		var manager = new Manager;
		assert.equal(manager.get('experiment-1'), undefined);
	});

	it('can set feature', () => {
		var experiment = 'experiment-1';

		var feature = {};

		var manager = new Manager;
		manager.set(experiment, feature)

		assert.equal(manager.get(experiment), feature);
	});

})
<|endoftext|>


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

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

  //record GA page view event to new primo tracker GA ID
  app.run(['$rootScope', '$location', '$window', function($rootScope, $location, $window){

    // remove favourite element from nav-bar because it's included in user area overwrite
    $rootScope.$on("$stateChangeSuccess", function() {
      // Primo keeps adding favourites element every time user clicks on My Account
      // Keep removing fav element every time it's added
      var favouritesElement = document.querySelector('.top-nav-bar > prm-search-bookmark-filter');
      if (favouritesElement !== null && typeof(favouritesElement) !== 'undefined') {
          favouritesElement.parentNode.removeChild(favouritesElement);
      }
    });

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

  app.component('prmTopBarBefore', {
    template: '
<uqlibrary-alerts></uqlibrary-alerts>
' +
    '
<uq-minimal-header show-login-button="false"></uq-minimal-header>
'
  });

  var template = 'components/search/topbar/userArea/user-area.html';
  var newUserArea = '
' +
      '{{$ctrl.userName()}}' +
      '<prm-search-bookmark-filter layout-align="end center" layout="row" flex="noshrink" aria-hidden="false"></prm-search-bookmark-filter>' +
      '<prm-library-card-menu ng-show="$ctrl.userName().length > 0"></prm-library-card-menu>' +
      '<prm-authentication layout="flex" [is-logged-in]="$ctrl.userName().length > 0"></prm-authentication>' +
      '
';

  app.component('prmUserAreaAfter', {
      bindings: {
          parentCtrl: '<'
      },
      controller: function($compile, $scope, $templateCache, $element) {
          $templateCache.put(template, newUserArea);
          $compile($element.parent())($scope);
      }
  });

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

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

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

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

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

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

  var scripts = [
    '//assets.library.uq.edu.au/primo-sand-box/reusable-components/webcomponentsjs/webcomponents-lite.min.js',
    '//assets.library.uq.edu.au/primo-sand-box/reusable-components/resources/preloader.js',
    '//assets.library.uq.edu.au/primo-sand-box/reusable-components/primo2/load.js'
  ];

  var links = [
    { rel: 'import', href: '//assets.library.uq.edu.au/primo-sand-box/reusable-components/elements.vulcanized.html'},
    { rel: 'stylesheet', href: '//assets.library.uq.edu.au/primo-sand-box/reusable-components/primo2/custom-styles.css'}
  ];

  insertLink(links[0]);
  insertLink(links[1]);

  insertScript(scripts[0]);
  insertScript(scripts[1]);
  insertScript(scripts[2]);

})();
<commit_msg>Merging sandbox<commit_after>(function () {
  "use strict";

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

  //record GA page view event to new primo tracker GA ID
  app.run(['$rootScope', '$location', '$window', function($rootScope, $location, $window){

    // remove favourite element from nav-bar because it's included in user area overwrite
    $rootScope.$on("$stateChangeSuccess", function() {
      // Primo keeps adding favourites element every time user clicks on My Account
      // Keep removing fav element every time it's added
      var favouritesElement = document.querySelector('.top-nav-bar > prm-search-bookmark-filter');
      if (favouritesElement !== null && typeof(favouritesElement) !== 'undefined') {
          favouritesElement.parentNode.removeChild(favouritesElement);
      }
    });

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

  app.component('prmTopBarBefore', {
    template: '
<uqlibrary-alerts></uqlibrary-alerts>
' +
    '
<uq-minimal-header show-login-button="false"></uq-minimal-header>
'
  });

  var template = 'components/search/topbar/userArea/user-area.html';
  var newUserArea = '
' +
      '{{$ctrl.userName()}}' +
      '<prm-search-bookmark-filter layout-align="end center" layout="row" flex="noshrink" aria-hidden="false"></prm-search-bookmark-filter>' +
      '<prm-library-card-menu ng-show="$ctrl.userName().length > 0"></prm-library-card-menu>' +
      '<prm-authentication layout="flex" [is-logged-in]="$ctrl.userName().length > 0"></prm-authentication>' +
      '
';

  app.component('prmUserAreaAfter', {
      bindings: {
          parentCtrl: '<'
      },
      controller: function($compile, $scope, $templateCache, $element) {
          $templateCache.put(template, newUserArea);
          $compile($element.parent())($scope);
      }
  });

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

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

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

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

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

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

  var scripts = [
    '//assets.library.uq.edu.au/master/reusable-components/webcomponentsjs/webcomponents-lite.min.js',
    '//assets.library.uq.edu.au/master/reusable-components/resources/preloader.js',
    '//assets.library.uq.edu.au/master/reusable-components/primo2/load.js'
  ];

  var links = [
    { rel: 'import', href: '//assets.library.uq.edu.au/master/reusable-components/elements.vulcanized.html'},
    { rel: 'stylesheet', href: '//assets.library.uq.edu.au/master/reusable-components/primo2/custom-styles.css'}
  ];

  insertLink(links[0]);
  insertLink(links[1]);

  insertScript(scripts[0]);
  insertScript(scripts[1]);
  insertScript(scripts[2]);

})();
<|endoftext|>


<commit_before>/*
    Copyright 2009,2010 Emilis Dambauskas

    This file is part of PolicyFeed module.

    PolicyFeed is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    PolicyFeed is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with PolicyFeed.  If not, see <http://www.gnu.org/licenses/>.
*/

var fs = require("fs");
var htmlunit = require("htmlunit");
var UrlQueue = require("PolicyFeed/UrlQueue");
var UrlList = require("PolicyFeed/UrlList");
var BrowserController = require("PolicyFeed/BrowserController");
var JsonStorage = require("ctl/JsonStorage");
var Sequence = require("ctl/SimpleSequence");

exports.list = {};

/**
 *
 */
exports.getSourceList = function(source_dir, source_prefix) {
    var list = {};

    var source_names = fs.list(source_dir);
    for each (var name in source_names) {
        if (name[0] != ".") {
            // remove ".js" extension:
            name = name.substr(0, name.length - 3);
            list[name] = require(source_prefix + name);
            if (list[name].disabled)
                delete list[name];
        }
    }

    return list;
}

/**
 *
 */
exports.getDomains = function() {
    var domains = {};

    for each (var source in this.list) {
        if (source.domains) {
            for (var domain in source.domains) {
                domains[domain] = { delay: source.domains[domain] };
            }
        } else {
            if (source.feed_url instanceof Array) {
                for each (var url in source.feed_url) {
                    domains[UrlQueue.getDomainFromUrl(url)] = {};
                }
            } else {
                domains[UrlQueue.getDomainFromUrl(source.feed_url)] = {};
            }
        }
    }

    return domains;
}

/**
 *
 */
exports.init = function(options) {
    options = options || {};
    var {source_dir, source_prefix} = options;

    this.list = this.getSourceList(source_dir, source_prefix);

    for (var name in this.list) {
        this.list[name].name = name;
        this.list[name].Crawler = this;
        //this.list[name].UrlQueue = UrlQueue;
    }

    UrlQueue.init({ domainList: this.getDomains() });

    BrowserController.init(this, UrlQueue);
    BrowserController.start();
}

/**
 *
 */
exports.checkUpdates = function() {
    for (var name in this.list) {
        var urls = this.list[name].feed_url;
        if (!(urls instanceof Array))
            urls = [urls];

        for each (var url in urls) {
            if (!UrlQueue.isUrlScheduled(url)) {
                UrlQueue.scheduleUrl({
                    url: url,
                    source: name,
                    method: "checkFeed"
                    }, 0);
            }
        }
    }
}

/**
 *
 */
exports.processUrl = function(url, page) {
    switch (url.method) {
        case "checkFeed":
            return this.checkFeed(url.source, url, page);
        break;
        case "parsePage":
            return this.parsePage(url.source, url, page);
        break;
        default:
            return this.list[url.source][url.method](url, page);
    }
}

/**
 *
 */
exports.checkFeed = function(source_name, url, page) {

    var urls = this.list[source_name].extractFeedItems(page);

    // Remove existing urls:
    urls = urls.filter(function (item) {
        if (UrlList.exists(item.url))
            return false;
        else
            return true;
        });

    // Save url to originals, add to UrlList and UrlQueue:
    urls.map(function (item) {
        // create originals:
        var id = "/originals/" + item.published.substr(0, 10).replace(/-/g, "/") + "/";
        id += Sequence.next();

        print("adding page:", id, item.published, item.url, item.title);

        JsonStorage.write(id, item);
        UrlList.addUrl(item.url, id);

        UrlQueue.addUrl({
            url: item.url,
            source: source_name,
            method: "parsePage",
            original_id: id
            });
    });

    // schedule next check:
    UrlQueue.scheduleUrl(url, new Date(new Date().getTime() + 5*60*1000));
}

/**
 *
 */
exports.parsePage = function(source_name, url, page) {
    var source = this.list[source_name];

    if (source.parsePage) {
        return source.parsePage(url, page);
    } else {
        var original = this.saveOriginal(source_name, url, page);
        var doc = source.extractPageData(original, page);
        JsonStorage.write(doc._id, doc);
    }
}

/**
 *
 */
exports.saveOriginal = function(source_name, url, page) {
    var original = JsonStorage.read(url.original_id);

    var response = page.getWebResponse();
    original.content_type = response.getContentType();

    // DOC files, etc.:
    if (page instanceof com.gargoylesoftware.htmlunit.UnexpectedPage) {
        var stream = new (require("io").Stream)(response.getContentAsStream());
        var fields = this.getFieldsFromStream(stream, content_type);
        for (var key in fields)
            original[key] = fields[key];
    }
    // Sgml page is parent class for HtmlPage, XmlPage and XhtmlPage.
    if (page instanceof com.gargoylesoftware.htmlunit.SgmlPage) {
        htmlunit.setPageCharset(page, "UTF-8");
        original.html = page.asXml();
    }
    else
        throw this.error("updateOriginal", url.original_id + " | " + url.url);

    // save original:
    JsonStorage.write(original._id, original);

    return original;
}

/**
 *
 */
exports.getFieldsFromStream = function(stream, content_type) {
    var fields = {};
    fields.content_type = content_type;

    // requirements to save file:
    import("fs");
    import("core/date");
    import("config");

    var data_dir = require("config").DATA_DIR + "/temp";
    var id = Math.random();

    // save file:
    var dir_name = data_dir + (new Date().format("/yyyy/MM/dd"));
    if (!fs.exists(dir_name))
        fs.makeTree(dir_name);
    var file_name = dir_name + "/" + id + ".orig";
    fs.write(file_name, stream.read());

    fields.original_file = file_name;

    // Convert file to HTML and read the result if possible:
    switch (content_type) {
        case "application/msword":
            // Convert DOC to HTML:
            var proc = java.lang.Runtime.getRuntime().exec(["abiword", "--to", "html", file_name]);
            proc.waitFor();

            // Set html field:
            var html_file_name = dir_name + "/" + id + ".html";
            fields.html = fs.read(html_file_name);
            fields.converted_by = "abiword";

            // Remove converted HTML to save disk space:
            //fs.remove(html_file_name);
            loadObject("Events").create("PolicyFeed/SourceList:setFieldsFromStream-debug", ["html_file_name", html_file_name]);
            break;

        default:
            fields.html = "";
    }

    return fields;

}

<commit_msg>Fixed DOC parsing code in PolicyFeed/Crawler.<commit_after>/*
    Copyright 2009,2010 Emilis Dambauskas

    This file is part of PolicyFeed module.

    PolicyFeed is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    PolicyFeed is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with PolicyFeed.  If not, see <http://www.gnu.org/licenses/>.
*/

var fs = require("fs");
var htmlunit = require("htmlunit");
var UrlQueue = require("PolicyFeed/UrlQueue");
var UrlList = require("PolicyFeed/UrlList");
var BrowserController = require("PolicyFeed/BrowserController");
var JsonStorage = require("ctl/JsonStorage");
var Sequence = require("ctl/SimpleSequence");

exports.list = {};

/**
 *
 */
exports.getSourceList = function(source_dir, source_prefix) {
    var list = {};

    var source_names = fs.list(source_dir);
    for each (var name in source_names) {
        if (name[0] != ".") {
            // remove ".js" extension:
            name = name.substr(0, name.length - 3);
            list[name] = require(source_prefix + name);
            if (list[name].disabled)
                delete list[name];
        }
    }

    return list;
}

/**
 *
 */
exports.getDomains = function() {
    var domains = {};

    for each (var source in this.list) {
        if (source.domains) {
            for (var domain in source.domains) {
                domains[domain] = { delay: source.domains[domain] };
            }
        } else {
            if (source.feed_url instanceof Array) {
                for each (var url in source.feed_url) {
                    domains[UrlQueue.getDomainFromUrl(url)] = {};
                }
            } else {
                domains[UrlQueue.getDomainFromUrl(source.feed_url)] = {};
            }
        }
    }

    return domains;
}

/**
 *
 */
exports.init = function(options) {
    options = options || {};
    var {source_dir, source_prefix} = options;

    this.list = this.getSourceList(source_dir, source_prefix);

    for (var name in this.list) {
        this.list[name].name = name;
        this.list[name].Crawler = this;
        //this.list[name].UrlQueue = UrlQueue;
    }

    UrlQueue.init({ domainList: this.getDomains() });

    BrowserController.init(this, UrlQueue);
    BrowserController.start();
}

/**
 *
 */
exports.checkUpdates = function() {
    for (var name in this.list) {
        var urls = this.list[name].feed_url;
        if (!(urls instanceof Array))
            urls = [urls];

        for each (var url in urls) {
            if (!UrlQueue.isUrlScheduled(url)) {
                UrlQueue.scheduleUrl({
                    url: url,
                    source: name,
                    method: "checkFeed"
                    }, 0);
            }
        }
    }
}

/**
 *
 */
exports.processUrl = function(url, page) {
    switch (url.method) {
        case "checkFeed":
            return this.checkFeed(url.source, url, page);
        break;
        case "parsePage":
            return this.parsePage(url.source, url, page);
        break;
        default:
            return this.list[url.source][url.method](url, page);
    }
}

/**
 *
 */
exports.checkFeed = function(source_name, url, page) {

    var urls = this.list[source_name].extractFeedItems(page);

    // Remove existing urls:
    urls = urls.filter(function (item) {
        if (UrlList.exists(item.url))
            return false;
        else
            return true;
        });

    // Save url to originals, add to UrlList and UrlQueue:
    urls.map(function (item) {
        // create originals:
        var id = "/originals/" + item.published.substr(0, 10).replace(/-/g, "/") + "/";
        id += Sequence.next();

        print("adding page:", id, item.published, item.url, item.title);

        JsonStorage.write(id, item);
        UrlList.addUrl(item.url, id);

        UrlQueue.addUrl({
            url: item.url,
            source: source_name,
            method: "parsePage",
            original_id: id
            });
    });

    // schedule next check:
    UrlQueue.scheduleUrl(url, new Date(new Date().getTime() + 5*60*1000));
}

/**
 *
 */
exports.parsePage = function(source_name, url, page) {
    var source = this.list[source_name];

    if (source.parsePage) {
        return source.parsePage(url, page);
    } else {
        var original = this.saveOriginal(source_name, url, page);
        var doc = source.extractPageData(original, page);
        JsonStorage.write(doc._id, doc);
    }
}

/**
 *
 */
exports.saveOriginal = function(source_name, url, page) {
    var original = JsonStorage.read(url.original_id);

    var response = page.getWebResponse();
    original.content_type = response.getContentType();

    // DOC files, etc.:
    if (page instanceof com.gargoylesoftware.htmlunit.UnexpectedPage) {
        var stream = new (require("io").Stream)(response.getContentAsStream());
        var fields = this.getFieldsFromStream(stream, original.content_type);
        for (var key in fields)
            original[key] = fields[key];
    } else if (page instanceof com.gargoylesoftware.htmlunit.SgmlPage) {
        // Sgml page is parent class for HtmlPage, XmlPage and XhtmlPage.
        htmlunit.setPageCharset(page, "UTF-8");
        original.html = page.asXml();
    }
    else
        throw Error("PolicyFeed/Crawler.saveOriginal: Unsupported page type.", url.original_id + " | " + url.url);

    // save original:
    JsonStorage.write(original._id, original);

    return original;
}

/**
 *
 */
exports.getFieldsFromStream = function(stream, content_type) {
    var fields = {};
    fields.content_type = content_type;

    // requirements to save file:
    import("fs");
    import("core/date");
    import("config");

    var data_dir = require("config").DATA_DIR + "/temp";
    var id = Math.random();

    // save file:
    var dir_name = data_dir + (new Date().format("/yyyy/MM/dd"));
    if (!fs.exists(dir_name))
        fs.makeTree(dir_name);
    var file_name = dir_name + "/" + id + ".orig";
    fs.write(file_name, stream.read());

    fields.original_file = file_name;

    // Convert file to HTML and read the result if possible:
    switch (content_type) {
        case "application/msword":
            // Convert DOC to HTML:
            var proc = java.lang.Runtime.getRuntime().exec(["abiword", "--to", "html", file_name]);
            proc.waitFor();

            // Set html field:
            var html_file_name = dir_name + "/" + id + ".html";
            fields.html = fs.read(html_file_name);
            fields.converted_by = "abiword";

            // Remove converted HTML to save disk space:
            //fs.remove(html_file_name);
            loadObject("Events").create("PolicyFeed/Crawler.setFieldsFromStream-debug", ["html_file_name", html_file_name]);
            break;

        default:
            fields.html = "";
    }

    return fields;

}

<|endoftext|>


<commit_before>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
"use strict";

const HarmonyCompatibilityDependency = require("./HarmonyCompatibilityDependency");

module.exports = class HarmonyDetectionParserPlugin {
	apply(parser) {
		parser.plugin("program", (ast) => {
			var isHarmony = ast.body.some(statement => {
				return /^(Import|Export).*Declaration$/.test(statement.type);
			});
			if(isHarmony) {
				let module = parser.state.module;
				const dep = new HarmonyCompatibilityDependency(module);
				dep.loc = {
					start: {
						line: -1,
						column: 0
					},
					end: {
						line: -1,
						column: 0
					},
					index: -2
				};
				module.addDependency(dep);
				module.meta.harmonyModule = true;
				module.strict = true;
				module.exportsArgument = "__webpack_exports__";
			}
		});
		var nonHarmonyIdentifiers = ["define", "exports"];
		nonHarmonyIdentifiers.forEach(identifer => {
			parser.plugin(`evaluate typeof ${identifer}`, nullInHarmony);
			parser.plugin(`typeof ${identifer}`, skipInHarmony);
			parser.plugin(`evaluate ${identifer}`, nullInHarmony);
			parser.plugin(`expression ${identifer}`, skipInHarmony);
			parser.plugin(`call ${identifer}`, skipInHarmony);
		});

		function skipInHarmony() {
			let module = this.state.module;
			if(module && module.meta && module.meta.harmonyModule)
				return true;
		}

		function nullInHarmony() {
			let module = this.state.module;
			if(module && module.meta && module.meta.harmonyModule)
				return null;
		}
	}
};
<commit_msg>use const where applicable in HarmonyDetectionParserPlugin<commit_after>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
"use strict";

const HarmonyCompatibilityDependency = require("./HarmonyCompatibilityDependency");

module.exports = class HarmonyDetectionParserPlugin {
	apply(parser) {
		parser.plugin("program", (ast) => {
			var isHarmony = ast.body.some(statement => {
				return /^(Import|Export).*Declaration$/.test(statement.type);
			});
			if(isHarmony) {
				const module = parser.state.module;
				const dep = new HarmonyCompatibilityDependency(module);
				dep.loc = {
					start: {
						line: -1,
						column: 0
					},
					end: {
						line: -1,
						column: 0
					},
					index: -2
				};
				module.addDependency(dep);
				module.meta.harmonyModule = true;
				module.strict = true;
				module.exportsArgument = "__webpack_exports__";
			}
		});
		var nonHarmonyIdentifiers = ["define", "exports"];
		nonHarmonyIdentifiers.forEach(identifer => {
			parser.plugin(`evaluate typeof ${identifer}`, nullInHarmony);
			parser.plugin(`typeof ${identifer}`, skipInHarmony);
			parser.plugin(`evaluate ${identifer}`, nullInHarmony);
			parser.plugin(`expression ${identifer}`, skipInHarmony);
			parser.plugin(`call ${identifer}`, skipInHarmony);
		});

		function skipInHarmony() {
			const module = this.state.module;
			if(module && module.meta && module.meta.harmonyModule)
				return true;
		}

		function nullInHarmony() {
			const module = this.state.module;
			if(module && module.meta && module.meta.harmonyModule)
				return null;
		}
	}
};
<|endoftext|>


<commit_before>/*global config:true, file:true, task:true, module: true */

var files = {
  0: [
    'libs/jquery-1.6.1.js',
    'libs/underscore.js'
  ],
  1: [
    'libs/jquery.scrollTo-1.4.2.js',
    'libs/jquery.hoverintent.js'
  ],
  2: [
    'src/js/core.js'
  ],
  3: [
    'src/js/models/fact.js',
    'src/js/views/ballooney_thingy.js',
    'src/js/views/balloon.js',
    'src/js/views/prepare.js'
  ],
  4: [
    'src/js/replace.js',
    'src/js/annotate.js',
    'src/js/highlight.js',
    'src/js/scrollto.js',
    'src/js/loaded_message.js',
    'src/js/search.js',
    'src/js/create.js',
    'src/js/modal.js',
    'src/js/lib/indicator.js'
  ],
  5: [
    'src/js/xdm.js'
  ],
  6: [
    'src/js/last.js'
  ]
};

var loaderFiles = {
  0: [
    'libs/easyXDM.js'
  ],
  1: [
    'src/js/loader.js'
  ]
};

module.exports = function(grunt){

  function createFactlinkConcatObject(filesObj) {
    return grunt.utils._.flatten(["<banner>", grunt.utils._(filesObj).map(function(fileGroup) {
      return fileGroup.map(function(file) {
        return "<file_strip_banner:" + file + ">";
      });
    })], true);
  }

  grunt.initConfig({
    pkg: '<json:package.json>',
    meta: {
      banner: '/*! \n' +
      ' * <%= pkg.title || pkg.name %> - v<%= pkg.version %> - \n' +
      '<%= pkg.homepage ? " * " + pkg.homepage + "\n" : "" %>' +
      ' *\n' +
      ' * Date: <%= grunt.template.today("m/d/yyyy") %>\n' +
      ' *\n' +
      ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>;\n' +
      ' */'
    },
    concat: {
      'dist/factlink.core.js': createFactlinkConcatObject(files),
      'dist/factlink.start_annotating.js': '<file_strip_banner:src/js/chrome/start_annotating.js>',
      'dist/factlink.stop_annotating.js': '<file_strip_banner:src/js/chrome/stop_annotating.js>',
      'dist/factlink.start_highlighting.js': '<file_strip_banner:src/js/chrome/start_highlighting.js>',
      'dist/factlink.stop_highlighting.js': '<file_strip_banner:src/js/chrome/stop_highlighting.js>',
      'dist/easyXDM/easyXDM.js': '<file_strip_banner:libs/easyXDM.js>',
      'dist/factlink.js': createFactlinkConcatObject(loaderFiles)
    },
    copy: {
      'dist/server/css/basic.css': 'dist/css/basic.css',

      'dist/server/images/arrow.png': 'src/images/arrow.png',
      'dist/server/images/arrows-bottom.png': 'src/images/arrows-bottom.png',
      'dist/server/images/arrows-top.png': 'src/images/arrows-top.png',
      'dist/server/images/bookmark.gif': 'src/images/bookmark.gif',
      'dist/server/images/logo-small.png': 'src/images/logo-small.png',

      'dist/images/arrow.png': 'src/images/arrow.png',
      'dist/images/arrows-bottom.png': 'src/images/arrows-bottom.png',
      'dist/images/arrows-top.png': 'src/images/arrows-top.png',
      'dist/images/bookmark.gif': 'src/images/bookmark.gif',
      'dist/images/logo-small.png': 'src/images/logo-small.png'
    },
    less: {
      basic: {
        src: 'src/css/basic.less',
        dest: 'dist/css/basic.css',
        options: {
          yuicompress: true
        }
      }
    },
    min: {
      'dist/server/factlink.core.min.js': ['<banner>', 'dist/factlink.core.js'],
      'dist/server/factlink.start_annotating.min.js': ['<banner>', 'dist/factlink.start_annotating.js'],
      'dist/server/factlink.stop_annotating.min.js': ['<banner>', 'dist/factlink.stop_annotating.js'],
      'dist/server/factlink.start_highlighting.min.js': ['<banner>', 'dist/factlink.start_highlighting.js'],
      'dist/server/factlink.stop_highlighting.min.js': ['<banner>', 'dist/factlink.stop_highlighting.js'],
      'dist/server/factlink.min.js': ['<banner>', 'dist/factlink.js']
      'dist/server/easyXDM/easyXDM.min.js': ['<banner>', 'dist/easyXDM/easyXDM.js'], // for the server
      'dist/easyXDM/easyXDM.min.js': ['<banner>', 'dist/easyXDM/easyXDM.js'],        // for local
    },
    qunit: {
      files: ['test/*.html']
    },
    lint: {
      files: ['grunt.js', 'src/js/**/*.js', 'test/**/*.js']
    },
    watch: {
      files: ['src/js/**/*', 'test/**/*', 'grunt.js'],
      tasks: 'lint qunit concat less copy'
    },
    jshint: {
      options: {
        // Settings
        "passfail"      : false,  // Stop on first error.
        "maxerr"        : 100,    // Maximum error before stopping.

        // Predefined globals whom JSHint will ignore.
        "browser"       : true,   // Standard browser globals e.g. `window`, `document`.

        "node"          : false,
        "rhino"         : false,
        "couch"         : false,
        "wsh"           : false,   // Windows Scripting Host.

        "jquery"        : true,
        "prototypejs"   : false,
        "mootools"      : false,
        "dojo"          : false,

        "predef"        : [  // Custom globals.
          "Factlink", "FactlinkConfig", "escape"
        ],

        // Development.
        "debug"         : false,  // Allow debugger statements e.g. browser breakpoints.
        "devel"         : true,   // Allow developments statements e.g. `console.log();`.

        // ECMAScript 5.
        "es5"           : true,   // Allow ECMAScript 5 syntax.
        "strict"        : false,  // Require `use strict` pragma  in every file.
        "globalstrict"  : false,  // Allow global "use strict" (also enables 'strict').

        // The Good Parts.
        "asi"           : false,  // Tolerate Automatic Semicolon Insertion (no semicolons).
        "laxbreak"      : true,   // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons.
        "bitwise"       : true,   // Prohibit bitwise operators (&, |, ^, etc.).
        "boss"          : true,   // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments.
        "curly"         : true,   // Require {} for every new block or scope.
        "eqeqeq"        : true,   // Require triple equals i.e. `===`.
        "eqnull"        : false,  // Tolerate use of `== null`.
        "evil"          : false,  // Tolerate use of `eval`.
        "expr"          : false,  // Tolerate `ExpressionStatement` as Programs.
        "forin"         : false,  // Tolerate `for in` loops without `hasOwnPrototype`.
        "immed"         : false,  // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );`
        "latedef"       : true,   // Prohipit variable use before definition.
        "loopfunc"      : true,   // Allow functions to be defined within loops.
        "noarg"         : true,   // Prohibit use of `arguments.caller` and `arguments.callee`.
        "regexp"        : false,  // Prohibit `.` and `[^...]` in regular expressions.
        "regexdash"     : false,  // Tolerate unescaped last dash i.e. `[-...]`.
        "scripturl"     : true,   // Tolerate script-targeted URLs.
        "shadow"        : false,  // Allows re-define variables later in code e.g. `var x=1; x=2;`.
        "supernew"      : false,  // Tolerate `new function () { ... };` and `new Object;`.
        "undef"         : true,   // Require all non-global variables be declared before they are used.

        // Personal styling preferences.
        "newcap"        : true,   // Require capitalization of all constructor functions e.g. `new F()`.
        "noempty"       : true,   // Prohibit use of empty blocks.
        "nonew"         : true,   // Prohibit use of constructors for side-effects.
        "nomen"         : false,  // Prohibit use of initial or trailing underbars in names.
        "onevar"        : false,  // Allow only one `var` statement per function.
        "plusplus"      : false,  // Prohibit use of `++` & `--`.
        "sub"           : false,  // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`.
        "trailing"      : true,   // Prohibit trailing whitespaces.
        "white"         : false,  // Check against strict whitespace and indentation rules.
        "indent"        : 2       // Specify indentation spacing
      }
    },
    uglify: {}
  });

  // Default task.
  grunt.registerTask('default', 'lint qunit concat min copy');
  grunt.registerTask('server', 'concat min copy');

  grunt.registerMultiTask('copy', 'copy files', function () {
    grunt.file.copy(this.data,this.target);
  });

  grunt.loadNpmTasks('grunt-less');
};
<commit_msg>Syntax error fix<commit_after>/*global config:true, file:true, task:true, module: true */

var files = {
  0: [
    'libs/jquery-1.6.1.js',
    'libs/underscore.js'
  ],
  1: [
    'libs/jquery.scrollTo-1.4.2.js',
    'libs/jquery.hoverintent.js'
  ],
  2: [
    'src/js/core.js'
  ],
  3: [
    'src/js/models/fact.js',
    'src/js/views/ballooney_thingy.js',
    'src/js/views/balloon.js',
    'src/js/views/prepare.js'
  ],
  4: [
    'src/js/replace.js',
    'src/js/annotate.js',
    'src/js/highlight.js',
    'src/js/scrollto.js',
    'src/js/loaded_message.js',
    'src/js/search.js',
    'src/js/create.js',
    'src/js/modal.js',
    'src/js/lib/indicator.js'
  ],
  5: [
    'src/js/xdm.js'
  ],
  6: [
    'src/js/last.js'
  ]
};

var loaderFiles = {
  0: [
    'libs/easyXDM.js'
  ],
  1: [
    'src/js/loader.js'
  ]
};

module.exports = function(grunt){

  function createFactlinkConcatObject(filesObj) {
    return grunt.utils._.flatten(["<banner>", grunt.utils._(filesObj).map(function(fileGroup) {
      return fileGroup.map(function(file) {
        return "<file_strip_banner:" + file + ">";
      });
    })], true);
  }

  grunt.initConfig({
    pkg: '<json:package.json>',
    meta: {
      banner: '/*! \n' +
      ' * <%= pkg.title || pkg.name %> - v<%= pkg.version %> - \n' +
      '<%= pkg.homepage ? " * " + pkg.homepage + "\n" : "" %>' +
      ' *\n' +
      ' * Date: <%= grunt.template.today("m/d/yyyy") %>\n' +
      ' *\n' +
      ' * Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author %>;\n' +
      ' */'
    },
    concat: {
      'dist/factlink.core.js': createFactlinkConcatObject(files),
      'dist/factlink.start_annotating.js': '<file_strip_banner:src/js/chrome/start_annotating.js>',
      'dist/factlink.stop_annotating.js': '<file_strip_banner:src/js/chrome/stop_annotating.js>',
      'dist/factlink.start_highlighting.js': '<file_strip_banner:src/js/chrome/start_highlighting.js>',
      'dist/factlink.stop_highlighting.js': '<file_strip_banner:src/js/chrome/stop_highlighting.js>',
      'dist/easyXDM/easyXDM.js': '<file_strip_banner:libs/easyXDM.js>',
      'dist/factlink.js': createFactlinkConcatObject(loaderFiles)
    },
    copy: {
      'dist/server/css/basic.css': 'dist/css/basic.css',

      'dist/server/images/arrow.png': 'src/images/arrow.png',
      'dist/server/images/arrows-bottom.png': 'src/images/arrows-bottom.png',
      'dist/server/images/arrows-top.png': 'src/images/arrows-top.png',
      'dist/server/images/bookmark.gif': 'src/images/bookmark.gif',
      'dist/server/images/logo-small.png': 'src/images/logo-small.png',

      'dist/images/arrow.png': 'src/images/arrow.png',
      'dist/images/arrows-bottom.png': 'src/images/arrows-bottom.png',
      'dist/images/arrows-top.png': 'src/images/arrows-top.png',
      'dist/images/bookmark.gif': 'src/images/bookmark.gif',
      'dist/images/logo-small.png': 'src/images/logo-small.png'
    },
    less: {
      basic: {
        src: 'src/css/basic.less',
        dest: 'dist/css/basic.css',
        options: {
          yuicompress: true
        }
      }
    },
    min: {
      'dist/server/factlink.core.min.js': ['<banner>', 'dist/factlink.core.js'],
      'dist/server/factlink.start_annotating.min.js': ['<banner>', 'dist/factlink.start_annotating.js'],
      'dist/server/factlink.stop_annotating.min.js': ['<banner>', 'dist/factlink.stop_annotating.js'],
      'dist/server/factlink.start_highlighting.min.js': ['<banner>', 'dist/factlink.start_highlighting.js'],
      'dist/server/factlink.stop_highlighting.min.js': ['<banner>', 'dist/factlink.stop_highlighting.js'],
      'dist/server/factlink.min.js': ['<banner>', 'dist/factlink.js'],
      'dist/server/easyXDM/easyXDM.min.js': ['<banner>', 'dist/easyXDM/easyXDM.js'], // for the server
      'dist/easyXDM/easyXDM.min.js': ['<banner>', 'dist/easyXDM/easyXDM.js']        // for local
    },
    qunit: {
      files: ['test/*.html']
    },
    lint: {
      files: ['grunt.js', 'src/js/**/*.js', 'test/**/*.js']
    },
    watch: {
      files: ['src/js/**/*', 'test/**/*', 'grunt.js'],
      tasks: 'lint qunit concat less copy'
    },
    jshint: {
      options: {
        // Settings
        "passfail"      : false,  // Stop on first error.
        "maxerr"        : 100,    // Maximum error before stopping.

        // Predefined globals whom JSHint will ignore.
        "browser"       : true,   // Standard browser globals e.g. `window`, `document`.

        "node"          : false,
        "rhino"         : false,
        "couch"         : false,
        "wsh"           : false,   // Windows Scripting Host.

        "jquery"        : true,
        "prototypejs"   : false,
        "mootools"      : false,
        "dojo"          : false,

        "predef"        : [  // Custom globals.
          "Factlink", "FactlinkConfig", "escape"
        ],

        // Development.
        "debug"         : false,  // Allow debugger statements e.g. browser breakpoints.
        "devel"         : true,   // Allow developments statements e.g. `console.log();`.

        // ECMAScript 5.
        "es5"           : true,   // Allow ECMAScript 5 syntax.
        "strict"        : false,  // Require `use strict` pragma  in every file.
        "globalstrict"  : false,  // Allow global "use strict" (also enables 'strict').

        // The Good Parts.
        "asi"           : false,  // Tolerate Automatic Semicolon Insertion (no semicolons).
        "laxbreak"      : true,   // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons.
        "bitwise"       : true,   // Prohibit bitwise operators (&, |, ^, etc.).
        "boss"          : true,   // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments.
        "curly"         : true,   // Require {} for every new block or scope.
        "eqeqeq"        : true,   // Require triple equals i.e. `===`.
        "eqnull"        : false,  // Tolerate use of `== null`.
        "evil"          : false,  // Tolerate use of `eval`.
        "expr"          : false,  // Tolerate `ExpressionStatement` as Programs.
        "forin"         : false,  // Tolerate `for in` loops without `hasOwnPrototype`.
        "immed"         : false,  // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );`
        "latedef"       : true,   // Prohipit variable use before definition.
        "loopfunc"      : true,   // Allow functions to be defined within loops.
        "noarg"         : true,   // Prohibit use of `arguments.caller` and `arguments.callee`.
        "regexp"        : false,  // Prohibit `.` and `[^...]` in regular expressions.
        "regexdash"     : false,  // Tolerate unescaped last dash i.e. `[-...]`.
        "scripturl"     : true,   // Tolerate script-targeted URLs.
        "shadow"        : false,  // Allows re-define variables later in code e.g. `var x=1; x=2;`.
        "supernew"      : false,  // Tolerate `new function () { ... };` and `new Object;`.
        "undef"         : true,   // Require all non-global variables be declared before they are used.

        // Personal styling preferences.
        "newcap"        : true,   // Require capitalization of all constructor functions e.g. `new F()`.
        "noempty"       : true,   // Prohibit use of empty blocks.
        "nonew"         : true,   // Prohibit use of constructors for side-effects.
        "nomen"         : false,  // Prohibit use of initial or trailing underbars in names.
        "onevar"        : false,  // Allow only one `var` statement per function.
        "plusplus"      : false,  // Prohibit use of `++` & `--`.
        "sub"           : false,  // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`.
        "trailing"      : true,   // Prohibit trailing whitespaces.
        "white"         : false,  // Check against strict whitespace and indentation rules.
        "indent"        : 2       // Specify indentation spacing
      }
    },
    uglify: {}
  });

  // Default task.
  grunt.registerTask('default', 'lint qunit concat min copy');
  grunt.registerTask('server', 'concat min copy');

  grunt.registerMultiTask('copy', 'copy files', function () {
    grunt.file.copy(this.data,this.target);
  });

  grunt.loadNpmTasks('grunt-less');
};
<|endoftext|>


<commit_before>var assert = require('assert');

var kramed = require('kramed');

var renderer = require('../');

describe('Text renderer', function() {
    it("should have all methods that kramed's renderer has", function() {
        var m1 = methods(kramed.Renderer.prototype);
        var m2 = methods(renderer.prototype);

        // Ensure arrays are sorted
        m1.sort();
        m2.sort();

        assert.equal(
            m1.join(),
            m2.join()
        );
    });
});

// Returns a list of method names for an object
function methods(obj) {
    var keys;
    try {
        keys = Object.keys(obj);
    } catch (err) {
        return [];
    }

    return keys.filter(function(k) {
        return (typeof obj[k] === "function");
    });
}
<commit_msg>Improve methods function for tests<commit_after>var assert = require('assert');

var kramed = require('kramed');

var renderer = require('../');

describe('Text renderer', function() {
    it("should have all methods that kramed's renderer has", function() {
        var m1 = methods(kramed.Renderer.prototype);
        var m2 = methods(renderer.prototype);

        // Ensure arrays are sorted
        m1.sort();
        m2.sort();

        assert.equal(
            m1.join(),
            m2.join()
        );
    });
});

// Returns a list of method names for an object
function methods(obj) {
    var keys;
    try {
        keys = Object.keys(obj);
    } catch (err) {
        return [];
    }

    return keys
    .filter(function(k) {
        return (typeof obj[k] === "function");
    })
    .filter(function(k) {
        return k[0] !== '_';
    })
}
<|endoftext|>