<commit_before>const debug = require('debug')('wololobot:drawing')

const removeFromArr = (arr, el) => {
  let i
  while ((i = arr.indexOf(el)) !== -1) {
    arr.splice(i, 1)
  }
  return arr
}

module.exports = function (opts) {
  opts = Object.assign({
    subChances: 2,     // Number of tickets for subs
    normalChances: 1  // Number of tickets for non-subs
  }, opts)

  let entrants = []
  let winners = []
  let nEntrants = 0
  let open = false

  function pickRandom () {
    debug(`Picking a random entrant out of ${entrants}`)
    let rand = entrants[Math.floor(Math.random() * entrants.length)]
    winners.push(rand)
    entrants = removeFromArr(entrants, rand)
  }

  function winnersStr () {
    if (winners.length === 0) {
      return 'There are no winners!'
    } else if (winners.length === 1) {
      return `The winner is ${winners[0]}`
    }
    let out = 'The winners are: '
    winners.forEach((winner) => {
      out += `${winner}, `
    })
    return out.slice(0, -2)
  }

  return function drawing (bot) {
    bot.command('!play', (message) => {
      if (!open) {
        return
      }
      message.user = message.user.toLowerCase()
      if (entrants.indexOf(message.user) !== -1) {
        return
      }
      nEntrants++
      if (message.tags.subscriber === '1') {
        for (let i = 0; i < opts.subChances; i++) {
          entrants.push(message.user)
        }
      } else {
        for (let i = 0; i < opts.normalChances; i++) {
          entrants.push(message.user)
        }
      }
    })

    bot.command('!draw open'
                , { rank: 'mod' }
                , (message) => {
                  entrants = []
                  open = true
                  nEntrants = 0
                  bot.send('New drawing opened! To enter, type !play. Subscribers have ' +
               `${opts.subChances / opts.normalChances}x higher chances to ` +
               'win. Type !draw close <number of players> to end the drawing.')
                })

    bot.command('!draw close'
                , { rank: 'mod' }
                , (message, number) => {
                  open = false
                  number = parseInt(number)
                  if (isNaN(number)) {
                    bot.send(`@${message.user} Usage: !draw close <number of players>`)
                    return
                  }
                  if (number > nEntrants) {
                    bot.send(`@${message.user} Only ${nEntrants} people entered the drawing. Do !draw close` +
                 `again with a number up to ${nEntrants}.`)
                    return
                  }
                  winners = []
                  for (let i = number; i > 0; i--) {
                    pickRandom()
                  }
                  bot.send(winnersStr())
                })

    bot.command('!draw reroll'
                , { rank: 'mod' }
                , (message, user) => {
                  if (user === void 0) {
                    bot.send(`@${message.user} Usage: !draw reroll <user>`)
                    return
                  }
                  user = user.toLowerCase()
                  let i = winners.indexOf(user)
                  if (i === -1) {
                    bot.send(`'${user}' didn't win the drawing!`)
                    return
                  }
                  if (entrants.length === 0) {
                    bot.send('There are no entrants remaining! Open another drawing with !draw open')
                    return
                  }
                  winners.splice(i, 1)
                  pickRandom()
                  bot.send(`${user} has been replaced with ${winners[winners.length - 1]}`)
                })

    bot.command('!winners', (message) => {
      bot.send(winnersStr())
    })
  }
}
<commit_msg>Use async functions in Drawing module.<commit_after>const debug = require('debug')('wololobot:drawing')

const removeFromArr = (arr, el) => {
  let i
  while ((i = arr.indexOf(el)) !== -1) {
    arr.splice(i, 1)
  }
  return arr
}

module.exports = function (opts) {
  opts = Object.assign({
    subChances: 2,     // Number of tickets for subs
    normalChances: 1  // Number of tickets for non-subs
  }, opts)

  let entrants = []
  let winners = []
  let nEntrants = 0
  let open = false

  function pickRandom () {
    debug(`Picking a random entrant out of ${entrants}`)
    let rand = entrants[Math.floor(Math.random() * entrants.length)]
    winners.push(rand)
    entrants = removeFromArr(entrants, rand)
  }

  function winnersStr () {
    if (winners.length === 0) {
      return 'There are no winners!'
    } else if (winners.length === 1) {
      return `The winner is ${winners[0]}`
    }
    let out = 'The winners are: '
    winners.forEach((winner) => {
      out += `${winner}, `
    })
    return out.slice(0, -2)
  }

  return function drawing (bot) {
    bot.command('!play', (message) => {
      if (!open) {
        return
      }
      message.user = message.user.toLowerCase()
      if (entrants.indexOf(message.user) !== -1) {
        return
      }
      nEntrants++
      if (message.tags.subscriber === '1') {
        for (let i = 0; i < opts.subChances; i++) {
          entrants.push(message.user)
        }
      } else {
        for (let i = 0; i < opts.normalChances; i++) {
          entrants.push(message.user)
        }
      }
    })

    bot.command('!draw open', { rank: 'mod' }, (message) => {
      entrants = []
      open = true
      nEntrants = 0

      bot.send(
        'New drawing opened! To enter, type !play. Subscribers have ' +
        `${opts.subChances / opts.normalChances}x higher chances to ` +
        'win. Type !draw close <number of players> to end the drawing.'
      )
    })

    bot.command('!draw close', { rank: 'mod' }, (message, number) => {
      open = false
      number = parseInt(number)
      if (isNaN(number)) {
        bot.send(`@${message.user} Usage: !draw close <number of players>`)
        return
      }
      if (number > nEntrants) {
        bot.send(`@${message.user} Only ${nEntrants} people entered the drawing. Do !draw close` +
      `again with a number up to ${nEntrants}.`)
        return
      }
      winners = []
      for (let i = number; i > 0; i--) {
        pickRandom()
      }
      bot.send(winnersStr())
    })

    bot.command('!draw reroll', { rank: 'mod' }, (message, user) => {
      if (user === void 0) {
        bot.send(`@${message.user} Usage: !draw reroll <user>`)
        return
      }
      user = user.toLowerCase()
      let i = winners.indexOf(user)
      if (i === -1) {
        bot.send(`'${user}' didn't win the drawing!`)
        return
      }
      if (entrants.length === 0) {
        bot.send('There are no entrants remaining! Open another drawing with !draw open')
        return
      }
      winners.splice(i, 1)
      pickRandom()
      bot.send(`${user} has been replaced with ${winners[winners.length - 1]}`)
    })

    bot.command('!winners', (message) => {
      bot.send(winnersStr())
    })
  }
}
<|endoftext|>


<commit_before>//  Copyright 2002-2014, University of Colorado Boulder

/**
 * A light sensor probe, used in simulations like Bending Light and Beer's Law Lab to show how much light is being
 * received. It is typically connected to a body with readouts with a curved wire.  The origin is in the center of the
 * circular part of the sensor (which is not vertically symmetrical).
 *
 * TODO: This is under development and not ready for review or usage in simulations other than Bending Light.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Chandrashekar Bemagoni (Actual Concepts)
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var Node = require( 'SCENERY/nodes/Node' );
  var Shape = require( 'KITE/Shape' );
  var Path = require( 'SCENERY/nodes/Path' );
  var Vector2 = require( 'DOT/Vector2' );
  var LinearGradient = require( 'SCENERY/util/LinearGradient' );
  var RadialGradient = require( 'SCENERY/util/RadialGradient' );

  /**
   * Constructor for the LightSensorNode
   * @constructor
   */
  function LightSensorNode() {

    // The shape of the outer body, circular at top with a handle at the bottom
    var sensorShape = new Shape()
      .ellipticalArc( 50, 50, 50, 50, 0, Math.PI * 0.8, Math.PI * 0.2, false )
      .quadraticCurveTo( 84, 87, 82, 100 )
      .quadraticCurveTo( 81, 115, 80, 130 )
      .quadraticCurveTo( 80, 151, 65, 151 )
      .quadraticCurveTo( 50, 151, 35, 151 )
      .quadraticCurveTo( 20, 151, 20, 130 )
      .quadraticCurveTo( 19, 115, 18, 100 )
      .quadraticCurveTo( 16, 87, 11, 82 )
      .close();

    var outerShapePath = new Path( sensorShape, {
      stroke: new LinearGradient( 0, 0, 0, 151 )
        .addColorStop( 0, '#408260' ) // dark green
        .addColorStop( 1, '#005D2D' ), // darker green
      fill: new LinearGradient( 0, 0, 0, 151 )
        .addColorStop( 0, '#7CCAA2' ) // light green
        .addColorStop( 0.3, '#009348' ) // medium green
        .addColorStop( 1, '#008B44' ), // another medium green
      lineWidth: 2
    } );

    // the front flat "surface" of the sensor, makes it look 3d by putting a shiny glare on the top edge
    var innerPath = new Path( sensorShape, {
      fill: '#008541', // darkish green
      lineWidth: 2,
      scale: new Vector2( 0.9, 0.93 ),
      centerX: outerShapePath.centerX,
      y: 5
    } );
    var innerCirclePath = new Path( Shape.circle( 50, 50, 35 ), {
      fill: new RadialGradient( 35, 17.5, 0, 35, 70, 60 )
        .addColorStop( 0, 'white' )
        .addColorStop( 0.4, '#E6F5FF' ) // light blue
        .addColorStop( 1, '#C2E7FF' ), // darker blue, like glass
      centerX: innerPath.centerX,
      centerY: 50
    } );

    Node.call( this, {
      children: [ outerShapePath, innerPath, innerCirclePath ],
      cursor: 'pointer'
    } );
  }

  return inherit( Node, LightSensorNode );
} );<commit_msg>Factored out width, see https://github.com/phetsims/bending-light/issues/165<commit_after>//  Copyright 2002-2014, University of Colorado Boulder

/**
 * A light sensor probe, used in simulations like Bending Light and Beer's Law Lab to show how much light is being
 * received. It is typically connected to a body with readouts with a curved wire.  The origin is in the center of the
 * circular part of the sensor (which is not vertically symmetrical).
 *
 * TODO: This is under development and not ready for review or usage in simulations other than Bending Light.
 *
 * @author Sam Reid (PhET Interactive Simulations)
 * @author Chandrashekar Bemagoni (Actual Concepts)
 */
define( function( require ) {
  'use strict';

  // modules
  var inherit = require( 'PHET_CORE/inherit' );
  var Node = require( 'SCENERY/nodes/Node' );
  var Shape = require( 'KITE/Shape' );
  var Path = require( 'SCENERY/nodes/Path' );
  var Vector2 = require( 'DOT/Vector2' );
  var LinearGradient = require( 'SCENERY/util/LinearGradient' );
  var RadialGradient = require( 'SCENERY/util/RadialGradient' );

  /**
   * Constructor for the LightSensorNode
   * @constructor
   */
  function LightSensorNode() {

    var width = 100;

    // The shape of the outer body, circular at top with a handle at the bottom
    var sensorShape = new Shape()
      .ellipticalArc( width / 2, width / 2, width / 2, width / 2, 0, Math.PI * 0.8, Math.PI * 0.2, false )
      .quadraticCurveTo( width * 0.84, width * 0.87, width * 0.82, width )
      .quadraticCurveTo( width * 0.81, width * 1.15, width * 0.80, width * 1.30 )
      .quadraticCurveTo( width * 0.80, width * 1.51, width * 0.65, width * 1.51 )
      .quadraticCurveTo( width * 0.50, width * 1.51, width * 0.35, width * 1.51 )
      .quadraticCurveTo( width * 0.20, width * 1.51, width * 0.20, width * 1.30 )
      .quadraticCurveTo( width * 0.19, width * 1.15, width * 0.18, width )
      .quadraticCurveTo( width * 0.16, width * 0.87, width * 0.11, width * 0.82 )
      .close();

    var outerShapePath = new Path( sensorShape, {
      stroke: new LinearGradient( 0, 0, 0, width * 1.51 )
        .addColorStop( 0, '#408260' ) // dark green
        .addColorStop( 1, '#005D2D' ), // darker green
      fill: new LinearGradient( 0, 0, 0, width * 1.51 )
        .addColorStop( 0, '#7CCAA2' ) // light green
        .addColorStop( 0.3, '#009348' ) // medium green
        .addColorStop( 1, '#008B44' ), // another medium green
      lineWidth: 2
    } );

    // the front flat "surface" of the sensor, makes it look 3d by putting a shiny glare on the top edge
    var innerPath = new Path( sensorShape, {
      fill: '#008541', // darkish green
      lineWidth: 2,
      scale: new Vector2( 0.9, 0.93 ),
      centerX: outerShapePath.centerX,
      y: width * 0.05
    } );
    var innerCirclePath = new Path( Shape.circle( width * 0.50, width * 0.50, width * 0.35 ), {
      fill: new RadialGradient( width * 0.35, width * 0.175, 0, width * 0.35, width * 0.70, width * 0.60 )
        .addColorStop( 0, 'white' )
        .addColorStop( 0.4, '#E6F5FF' ) // light blue
        .addColorStop( 1, '#C2E7FF' ), // darker blue, like glass
      centerX: innerPath.centerX,
      centerY: width * 0.50
    } );

    Node.call( this, {
      children: [ outerShapePath, innerPath, innerCirclePath ],
      cursor: 'pointer'
    } );
  }

  return inherit( Node, LightSensorNode );
} );<|endoftext|>


<commit_before>import { createActions, handleActions } from 'redux-actions';
import { all, put, call, takeEvery } from 'redux-saga/effects';
import { createSelector } from 'reselect';
import filter from 'lodash/filter';
import find from 'lodash/find';

import { load, save } from 'lib/api';
import { DEFAULT_ACCENT } from 'style/theme';
import { updateItem } from 'utils/array';

import OPTIONS, { SECTIONS } from 'options';
import { actions as toastActions } from 'modules/toast';

// state
const defaultState = {
  data: [],
  menuVisible: false,
};

// selectors
export const selectors = {
  options: state => state.options.data,
};

selectors.accentColor = createSelector([selectors.options], options => {
  const accentOption = find(options, { id: 'accent' });
  return accentOption ? find(accentOption.values, { id: accentOption.value }) : { value: DEFAULT_ACCENT };
});

selectors.enabled = createSelector([selectors.options], options => {
  const enabledOption = find(options, { id: 'enabled' });
  return enabledOption ? enabledOption.value : false;
});

selectors.visibleMenus = createSelector([selectors.options], options => {
  return filter(options, { section: 'visibleMenus' });
});

selectors.visiblePlaylists = createSelector([selectors.options], options => {
  return filter(options, { section: 'visiblePlaylists' });
});

selectors.sortedOptions = createSelector([selectors.options], options =>
  SECTIONS.map(section => {
    const sectionOptions = filter(options, o => {
      const oSection = o.section || 'default';
      return section.id === oSection;
    });

    return {
      ...section,
      options: sectionOptions || [],
    };
  })
);

// actions
export const actions = createActions(
  'FETCH_OPTIONS',
  'FETCH_OPTIONS_RESPONSE',
  'SAVE_OPTIONS',
  'SAVE_OPTIONS_RESPONSE',
  'TOGGLE_MENU',
  'UPDATE_OPTION'
);

const toObject = (options = []) =>
  options.reduce((obj, option) => {
    if (option.static) return obj;
    if (option.type === 'string') return obj;

    const updated = {
      ...obj,
      [option.id]: option.value !== undefined ? option.value : option.defaultValue,
    };

    return !option.plural
      ? updated
      : {
          ...updated,
          [option.plural]: option.values !== undefined ? option.values : option.defaultValues,
        };
  }, {});

const mapToValues = (options = [], values = {}) =>
  options.map(option => ({
    ...option,
    value: values[option.id],
    values: values[option.plural],
  }));

// sagas
export function* fetchOptionsSaga() {
  try {
    const DEFAULT_OPTIONS = toObject(OPTIONS);
    const optionsValues = yield call(load, DEFAULT_OPTIONS);
    const options = mapToValues(OPTIONS, optionsValues);
    yield put(actions.fetchOptionsResponse(options));
  } catch (e) {
    console.error(e);
  }
}

export function* saveOptionsSaga({ payload: optionsSave }) {
  try {
    yield call(save, toObject(optionsSave));
    yield put(actions.toggleMenu(false));
    yield put(actions.saveOptionsResponse(optionsSave));
    yield put(
      toastActions.createToast('success', {
        title: 'Options Saved!',
        message: `They're resting safely in the Google Cloud now.`,
      })
    );
  } catch (e) {
    console.error(e);
    yield put(
      toastActions.createToast('alert', {
        title: 'Options Failure!',
        message:
          'There seems to be an issue saving your options. Please try again or refresh the page. Please contact me if this persists!',
        timeout: false,
      })
    );
  }
}

export function* optionsSaga() {
  yield all([takeEvery(actions.fetchOptions, fetchOptionsSaga), takeEvery(actions.saveOptions, saveOptionsSaga)]);
}

// reducer
export default handleActions(
  {
    [actions.fetchOptionsResponse](state, { payload: data }) {
      return { ...state, data };
    },
    [actions.saveOptionsResponse](state, { payload: data }) {
      return { ...state, data };
    },
    [actions.updateOption](state, { payload: { id, value, isArray = false } }) {
      if (isArray) {
        return {
          ...state,
          data: updateItem(state.data, { plural: id, values: value }, 'plural'),
        };
      }

      return { ...state, data: updateItem(state.data, { id, value }) };
    },
    [actions.toggleMenu](state, { payload: toggleState }) {
      return {
        ...state,
        menuVisible: toggleState !== undefined ? toggleState : !state.menuVisible,
      };
    },
  },
  defaultState
);
<commit_msg>Started adding update check/notification logic, cleaned up toast formatting for prettier<commit_after>import { createActions, handleActions } from 'redux-actions';
import { all, put, select, call, takeEvery } from 'redux-saga/effects';
import { createSelector } from 'reselect';
import filter from 'lodash/filter';
import find from 'lodash/find';

import { load, save } from 'lib/api';
import { DEFAULT_ACCENT } from 'style/theme';
import { updateItem } from 'utils/array';

import OPTIONS, { SECTIONS } from 'options';
import { actions as toastActions } from 'modules/toast';

// state
const defaultState = {
  data: [],
  menuVisible: false,
};

// selectors
export const selectors = {
  options: state => state.options.data.filter(o => !o.static),
  allOptions: state => state.options.data,
};

selectors.accentColor = createSelector([selectors.options], options => {
  const accentOption = find(options, { id: 'accent' });
  return accentOption ? find(accentOption.values, { id: accentOption.value }) : { value: DEFAULT_ACCENT };
});

selectors.enabled = createSelector([selectors.options], options => {
  const enabledOption = find(options, { id: 'enabled' });
  return enabledOption ? enabledOption.value : false;
});

selectors.version = createSelector([selectors.allOptions], options => {
  const versionOption = find(options, { id: 'version' });
  return versionOption ? versionOption.value : undefined;
});

selectors.versionPrevious = createSelector([selectors.allOptions], options => {
  const versionOption = find(options, { id: 'lastRun' });
  return versionOption ? versionOption.value : undefined;
});

selectors.visibleMenus = createSelector([selectors.options], options => {
  return filter(options, { section: 'visibleMenus' });
});

selectors.visiblePlaylists = createSelector([selectors.options], options => {
  return filter(options, { section: 'visiblePlaylists' });
});

selectors.sortedOptions = createSelector([selectors.options], options =>
  SECTIONS.map(section => {
    const sectionOptions = filter(options, o => {
      const oSection = o.section || 'default';
      return section.id === oSection;
    });

    return {
      ...section,
      options: sectionOptions || [],
    };
  })
);

// actions
export const actions = createActions(
  'CHECK_UPDATE',
  'FETCH_OPTIONS',
  'FETCH_OPTIONS_RESPONSE',
  'SAVE_OPTIONS',
  'SAVE_OPTIONS_RESPONSE',
  'TOGGLE_MENU',
  'UPDATE_OPTION',
  'UPDATE_SAVE_OPTION',
);

const toObject = (options = []) =>
  options.reduce((obj, option) => {
    if (option.type === 'string') return obj;

    const updated = {
      ...obj,
      [option.id]: option.value !== undefined ? option.value : option.defaultValue,
    };

    return !option.plural
      ? updated
      : {
          ...updated,
          [option.plural]: option.values !== undefined ? option.values : option.defaultValues,
        };
  }, {});

const mapToValues = (options = [], values = {}) =>
  options.map(option => ({
    ...option,
    value: values[option.id],
    values: values[option.plural],
  }));

// sagas
export function* checkUpdateSaga({ payload }) {
  try {
    const version = yield select(selectors.version);
    const lastRun = yield select(selectors.versionPrevious);

    if (lastRun === version) {
      console.log(`Already up to date, enjoy your life!`);
    } else {
      yield put(
        toastActions.createToast('success', {
          id: 'PM_UPDATE',
          title: 'Updated',
          message: `Whoo, new toys! I'll be a modal soon!`,
        })
      );
      yield put(actions.updateSaveOption({ id: 'lastRun', value: version }));
    }
  } catch (e) {
    console.error(e);
  }
}

export function* fetchOptionsSaga() {
  try {
    const DEFAULT_OPTIONS = toObject(OPTIONS);
    const optionsValues = yield call(load, DEFAULT_OPTIONS);
    const options = mapToValues(OPTIONS, optionsValues);
    yield put(actions.fetchOptionsResponse(options));
    yield put(actions.checkUpdate(options));
  } catch (e) {
    console.error(e);
  }
}

export function* saveOptionsSaga({ payload: optionsSave }) {
  try {
    yield call(save, toObject(optionsSave));
    yield put(actions.toggleMenu(false));
    yield put(actions.saveOptionsResponse(optionsSave));
    yield put(
      toastActions.createToast('success', {
        title: 'Options Saved',
        message: `They're resting safely in the Google Cloud now`,
      })
    );
  } catch (e) {
    console.error(e);
    yield put(
      toastActions.createToast('alert', {
        title: 'Options Failure',
        message: `There seems to be an issue saving your options. \
        Please try again or refresh the page. Please contact me if this persists!`,
        timeout: false,
      })
    );
  }
}

export function* updateAndSaveOptionSaga({ payload: option }) {
  try {
    yield put(actions.updateOption(option));
    const update = yield select(selectors.allOptions);
    yield call(save, toObject(update));
    yield put(actions.saveOptionsResponse(update));
  } catch (e) {
    console.error(e);
    yield put(
      toastActions.createToast('alert', {
        title: 'Options Failure',
        message: `There seems to be an issue saving your options. \
        Please try again or refresh the page. Please contact me if this persists!`,
        timeout: false,
      })
    );
  }
}

export function* optionsSaga() {
  yield all([
    takeEvery(actions.checkUpdate, checkUpdateSaga),
    takeEvery(actions.fetchOptions, fetchOptionsSaga),
    takeEvery(actions.saveOptions, saveOptionsSaga),
    takeEvery(actions.updateSaveOption, updateAndSaveOptionSaga),
  ]);
}

// reducer
export default handleActions(
  {
    [actions.fetchOptionsResponse](state, { payload: data }) {
      return { ...state, data };
    },
    [actions.saveOptionsResponse](state, { payload: data }) {
      return { ...state, data };
    },
    [actions.updateOption](state, { payload: { id, value, isArray = false } }) {
      if (isArray) {
        return {
          ...state,
          data: updateItem(state.data, { plural: id, values: value }, 'plural'),
        };
      }

      return { ...state, data: updateItem(state.data, { id, value }) };
    },
    [actions.toggleMenu](state, { payload: toggleState }) {
      return {
        ...state,
        menuVisible: toggleState !== undefined ? toggleState : !state.menuVisible,
      };
    },
  },
  defaultState
);
<|endoftext|>


<commit_before>/*/////////////////////////////////////////////////////////////////////////////////

 MO5.js - JavaScript Library For Building Modern DOM And Canvas Applications

 Copyright (c) 2013 Jonathan Steinbeck
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

 * Neither the name MO5.js nor the names of its contributors
   may be used to endorse or promote products derived from this software
   without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

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

/* global MO5, document */

MO5("MO5.CoreObject", "MO5.transform", "MO5.TimerWatcher", "MO5.dom.effects.typewriter").
define("MO5.dom.Element", function (CoreObject, transform, TimerWatcher, typewriter) {

    function Element (args) {

        var self = this;

        args = args || {};

        CoreObject.call(this);

        this.parent = args.parent || document.body;
        this.nodeType = args.nodeType || "div";
        this.element = args.element || document.createElement(this.nodeType);

        wrapElement(this, this.element);

        Element.propertiesToExclude.forEach(function (property) {
            delete self[property];
        });
    }

    // Properties that should not shadow the DOM element's properties.
    // If you want to add a method with the same name as a DOM element's
    // property to the prototype, you need to add the method's name to this array.
    Element.propertiesToExclude = [
        "appendChild"
    ];

    Element.prototype = new CoreObject();
    Element.prototype.constructor = Element;

    Element.prototype.appendTo = function (element) {
        return element.appendChild(this.element);
    };

    Element.prototype.remove = function () {
        return this.element.parentNode.removeChild(this.element);
    };

    Element.prototype.appendChild = function (child) {
        var node = child instanceof Element ? child.element : child;
        return this.element.appendChild(node);
    };

    Element.prototype.fadeIn = function (args) {

        args = args || {};

        var element = this.element;

        return transform(
            function (v) {
                element.style.opacity = v;
            },
            0,
            1,
            args
        );
    };

    Element.prototype.fadeOut = function (args) {

        args = args || {};

        var element = this.element;

        return transform(
            function (v) {
                element.style.opacity = v;
            },
            1,
            0,
            args
        );
    };

    Element.prototype.moveTo = function (x, y, args) {

        args = args || {};

        var element = this.element,
            ox = element.offsetLeft,
            oy = element.offsetTop,
            t0, t1;

        t0 = transform(
            function (v) {
                element.style.left = v + "px";
            },
            ox,
            x,
            args
        );

        t1 = transform(
            function (v) {
                element.style.top = v + "px";
            },
            oy,
            y,
            args
        );

        return new TimerWatcher().addTimer(t0).addTimer(t1);
    };

    Element.prototype.move = function (x, y, args) {

        args = args || {};

        var element = this.element,
            dx = element.offsetLeft + x,
            dy = element.offsetTop + y;

        return this.moveTo(dx, dy, args);
    };

    Element.prototype.display = function () {

        var parent;

        try {
            parent = this.parent || document.body;
            parent.appendChild(this.element);
        }
        catch (e) {}
    };

    Element.prototype.hide = function () {

        var parent;

        try {
            parent = this.parent || document.body;
            parent.removeChild(this.element);
        }
        catch (e) {}
    };

    Element.prototype.typewriter = function (args) {
        args = args || {};
        typewriter(this.element, args);
    };

    Element.prototype.destroy = function () {
        try {
            this.element.parentNode.removeChild(this.element);
        }
        catch (e) {
            console.log(e);
        }

        this.element = null;

        this.destroyed = true;
        this.trigger("destroyed", null, false);

        for (var key in this) {
            if (this.hasOwnProperty(key)) {
                delete this[key];
            }
        }

        this.destroyed = true;
    };

    ////////////////////////////////////////
    // dom.Element helper functions
    ////////////////////////////////////////

    function wrapElement (element, domElement) {
        for (var key in domElement) {
            (function (currentProperty, key) {
                if (typeof currentProperty === "function") {
                    element[key] = function () {
                        return domElement[key].apply(domElement, arguments);
                    };
                }
                else {
                    element[key] = function (content) {
                        if (content) {
                            domElement[key] = content;
                            return element;
                        }

                        return domElement[key];
                    };
                }
            }(domElement[key], key));
        }
    }

    return Element;

});<commit_msg>js/MO5.dom.Element.js<commit_after>/*/////////////////////////////////////////////////////////////////////////////////

 MO5.js - JavaScript Library For Building Modern DOM And Canvas Applications

 Copyright (c) 2013 Jonathan Steinbeck
 All rights reserved.

 Redistribution and use in source and binary forms, with or without
 modification, are permitted provided that the following conditions are met:

 * Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

 * Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

 * Neither the name MO5.js nor the names of its contributors
   may be used to endorse or promote products derived from this software
   without specific prior written permission.

 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

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

/* global MO5, document, console */

MO5("MO5.CoreObject", "MO5.transform", "MO5.TimerWatcher", "MO5.dom.effects.typewriter").
define("MO5.dom.Element", function (CoreObject, transform, TimerWatcher, typewriter) {

    function Element (args) {

        var self = this;

        args = args || {};

        CoreObject.call(this);

        this.parent = args.parent || document.body;
        this.nodeType = args.nodeType || "div";
        this.element = args.element || document.createElement(this.nodeType);

        wrapElement(this, this.element);

        Element.propertiesToExclude.forEach(function (property) {
            delete self[property];
        });
    }

    // Properties that should not shadow the DOM element's properties.
    // If you want to add a method with the same name as a DOM element's
    // property to the prototype, you need to add the method's name to this array.
    Element.propertiesToExclude = [
        "appendChild"
    ];

    Element.prototype = new CoreObject();
    Element.prototype.constructor = Element;

    Element.prototype.appendTo = function (element) {
        return element.appendChild(this.element);
    };

    Element.prototype.remove = function () {
        return this.element.parentNode.removeChild(this.element);
    };

    Element.prototype.appendChild = function (child) {
        var node = child instanceof Element ? child.element : child;
        return this.element.appendChild(node);
    };

    Element.prototype.fadeIn = function (args) {

        args = args || {};

        var element = this.element;

        return transform(
            function (v) {
                element.style.opacity = v;
            },
            0,
            1,
            args
        );
    };

    Element.prototype.fadeOut = function (args) {

        args = args || {};

        var element = this.element;

        return transform(
            function (v) {
                element.style.opacity = v;
            },
            1,
            0,
            args
        );
    };

    Element.prototype.moveTo = function (x, y, args) {

        args = args || {};

        var element = this.element,
            ox = element.offsetLeft,
            oy = element.offsetTop,
            t0, t1;

        t0 = transform(
            function (v) {
                element.style.left = v + "px";
            },
            ox,
            x,
            args
        );

        t1 = transform(
            function (v) {
                element.style.top = v + "px";
            },
            oy,
            y,
            args
        );

        return new TimerWatcher().addTimer(t0).addTimer(t1);
    };

    Element.prototype.move = function (x, y, args) {

        args = args || {};

        var element = this.element,
            dx = element.offsetLeft + x,
            dy = element.offsetTop + y;

        return this.moveTo(dx, dy, args);
    };

    Element.prototype.display = function () {

        var parent;

        try {
            parent = this.parent || document.body;
            parent.appendChild(this.element);
        }
        catch (e) {}
    };

    Element.prototype.show = Element.prototype.display;

    Element.prototype.hide = function () {

        var parent;

        try {
            parent = this.parent || document.body;
            parent.removeChild(this.element);
        }
        catch (e) {}
    };

    Element.prototype.typewriter = function (args) {
        args = args || {};
        typewriter(this.element, args);
    };

    Element.prototype.addCssClass = function (classToAdd) {

        var classes;

        if (this.element.classList) {
            this.element.classList.add(classToAdd);
            return this;
        }

        classes = this.getCssClasses();

        if (!contains(classes, classToAdd)) {
            classes.push(classToAdd);
            this.element.setAttribute("class", classes.join(" "));
        }

        return this;
    };

    Element.prototype.removeCssClass = function (classToRemove) {

        var classes;

        if (this.element.classList) {
            this.element.classList.remove(classToRemove);
        }

        classes = this.getCssClasses();

        if (contains(classes, classToRemove)) {
            this.element.setAttribute("class", classes.filter(function (item) {
                return item !== classToRemove;
            }).join(" "));
        }

        return this;
    };

    Element.prototype.getCssClasses = function () {
        return (this.element.getAttribute("class") || "").split(" ");
    };

    Element.prototype.hasCssClass = function (classToCheckFor) {
        return this.element.classList ?
            this.element.classList.contains(classToCheckFor) :
            contains(this.getCssClasses(), classToCheckFor);
    };

    Element.prototype.clearCssClasses = function () {
        this.element.setAttribute("class", "");
        return this;
    };

    Element.prototype.destroy = function () {

        try {
            this.element.parentNode.removeChild(this.element);
        }
        catch (e) {
            console.log(e);
        }

        this.element = null;

        this.destroyed = true;
        this.trigger("destroyed", null, false);

        for (var key in this) {
            if (this.hasOwnProperty(key)) {
                delete this[key];
            }
        }

        this.destroyed = true;
    };

    ////////////////////////////////////////
    // dom.Element helper functions
    ////////////////////////////////////////

    function wrapElement (element, domElement) {
        for (var key in domElement) {
            (function (currentProperty, key) {
                if (typeof currentProperty === "function") {
                    element[key] = function () {
                        return domElement[key].apply(domElement, arguments);
                    };
                }
                else {
                    element[key] = function (content) {
                        if (content) {
                            domElement[key] = content;
                            return element;
                        }

                        return domElement[key];
                    };
                }
            }(domElement[key], key));
        }
    }

    function contains (array, item) {
        return array.indexOf(item) !== -1;
    }

    return Element;

});<|endoftext|>


<commit_before>// Copyright (c) Microsoft Open Technologies, Inc.  All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
(function () {
    "use strict";

    module.exports = function (grunt) {
        var config = require("../config.js");

        grunt.registerTask("test", function () {
            var parseArgs = require("minimist");
            var args = parseArgs(process.argv);

            if (config.inRazzle) {
                grunt.task.run(["default", "clean:qunit", "shell:runTests"]);
            } else {
                if (args.saucelabs) {
                    grunt.task.run(["release", "connect:saucelabs", "saucelabs-qunit"]);
                } else {
                    grunt.task.run(["default", "connect:localhost"]);
                }
            }
        });

        // Generate QUnit test pages
        grunt.registerTask("build-qunit", function () {
            var fs = require("fs");

            function extractDependencies(path) {
                var fileContents = fs.readFileSync(path, "utf-8");
                var dir = path.substring(0, path.lastIndexOf("/"));
                var deps = [];

                var lines = fileContents.split("\n");
                for (var i = 0; i < lines.length; i++) {
                    var line = lines[i];
                    var processedOne = false;
                    if (line.indexOf("<reference") < 0 || line.indexOf("ms-appx") >= 0) {
                        if (processedOne) {
                            break;
                        } else {
                            continue;
                        }
                    }

                    var startIndex = line.indexOf('path="') + 6;
                    var endIndex = line.indexOf('"', startIndex);
                    deps.push(dir + "/" + line.substring(startIndex, endIndex));

                    processedOne = true;
                }
                return deps;
            }

            function arrayIndexOf(arr, obj) {
                for (var i = 0; i < arr.length; i++) {
                    if (arr[i] === obj) {
                        return i;
                    }
                }
                return -1;
            }

            var testMenuTemplate =
        '    \r\n\
<!DOCTYPE html>                                                                                \r\n\
                                                                                \r\n\
                                                                                \r\n\
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />                                                                 \r\n\
    <title>WinJS Tests</title>                                                                                \r\n\
                                                                                \r\n\
                                                                                \r\n\
                                                                                \r\n\
                                              \r\n\

                                                                                \r\n\
@@TESTS                                                                                \r\n\

                                                                                \r\n\
                                                                                \r\n\
';

        var testPageTemplate =
    '    \r\n\
\r\n\
<!DOCTYPE html>                                                                                \r\n\
                                                                                \r\n\
                                                                                \r\n\
    <title>@@TITLE</title>                                                                                \r\n\
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />                                                                 \r\n\
                                                                                \r\n\
    <link type="text/css" rel="stylesheet" href="../../Microsoft.WinJS.2.1/css/ui-dark.css" />                              \r\n\
                                                                  \r\n\
                                                                    \r\n\
                                                    \r\n\
                                                      \r\n\
                                                                                \r\n\
                                                                                \r\n\
    <link type="text/css" rel="stylesheet" href="../../../node_modules/qunitjs/qunit/qunit.css" />                          \r\n\
                                                        \r\n\
                                                                       \r\n\
                                                                                \r\n\
                                                                                \r\n\
@@TESTREFERENCES                                                                                \r\n\
                                                                                \r\n\
                                                                                \r\n\

  \r\n\

                                                                                \r\n\
                                                                                \r\n\
'.replace(/@@TARGETFRAMEWORK/g, config.targetFramework);

            if (!fs.existsSync("./bin")) {
                fs.mkdirSync("./bin");
            }
            if (!fs.existsSync("./bin/tests")) {
                fs.mkdirSync("./bin/tests");
            }

            var dirs = fs.readdirSync("./tests");
            var tests = "";
            dirs.forEach(function (dir) {
                if (!fs.lstatSync("./tests/" + dir).isDirectory() || dir === "TestData" || dir === "TestLib") {
                    return;
                }

                var html = testPageTemplate;
                html = html.replace("@@TITLE", dir);

                var testReferences = "";

                var srcs = [];
                var csss = [];
                var files = fs.readdirSync("./tests/" + dir);
                for (var i = files.length - 1; i >= 0; i--) {
                    // Some folders have .html test assets, we can ignore those
                    var file = files[i];
                    if (file.indexOf(".css") >= 0) {
                        csss.push("./tests/" + dir + "/" + file);
                    } else if (file.indexOf(".js") >= 0) {
                        srcs.push("./tests/" + dir + "/" + file);
                    }
                }
                var done = false;
                while (!done) {
                    done = true;
                    var srcsCopy = srcs.slice(0);
                    for (var i = 0; i < srcs.length; i++) {
                        var deps = extractDependencies(srcs[i]);
                        var length = srcsCopy.length;
                        deps.forEach(function (dep) {
                            if (dep === srcs[i]) {
                                // Some files reference themselves, this check breaks the infinite loop
                                return;
                            }
                            if (dep.indexOf(".css") >= 0) {
                                if (arrayIndexOf(csss, dep) < 0) {
                                    csss.push(dep);
                                }
                            } else {
                                var index = arrayIndexOf(srcsCopy, dep);
                                if (index >= 0) {
                                    // If this dependency already exists, we need to reorder it to the bottom
                                    // of the array so it gets loaded first. This usually happens when a dependency
                                    // is in the same folder as the test folder but appears alphabetically before it.
                                    srcsCopy.splice(index, 1);
                                    length--;
                                } else {
                                    done = false;
                                }
                                // Since the \r\n';
                }
                testReferences = testReferences.substr(0, testReferences.length - 2);
                html = html.replace("@@TESTREFERENCES", testReferences);

                var testFolder = "./bin/tests/" + dir;
                if (!fs.existsSync(testFolder)) {
                    fs.mkdirSync(testFolder);
                }
                fs.writeFileSync(testFolder + "/test.html", html);
                tests += '
' + dir + " tests
\r\n";
            });
            tests = tests.substr(0, tests.length - 2);
            fs.writeFileSync("./bin/tests/tests.html", testMenuTemplate.replace("@@TESTS", tests));
        });
    };
})();<commit_msg>Updated the test build to verify that dependencies referenced in test files actually exist. Fixes #159.<commit_after>// Copyright (c) Microsoft Open Technologies, Inc.  All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
(function () {
    "use strict";

    module.exports = function (grunt) {
        var config = require("../config.js");

        grunt.registerTask("test", function () {
            var parseArgs = require("minimist");
            var args = parseArgs(process.argv);

            if (config.inRazzle) {
                grunt.task.run(["default", "clean:qunit", "shell:runTests"]);
            } else {
                if (args.saucelabs) {
                    grunt.task.run(["release", "connect:saucelabs", "saucelabs-qunit"]);
                } else {
                    grunt.task.run(["default", "connect:localhost"]);
                }
            }
        });

        // Generate QUnit test pages
        grunt.registerTask("build-qunit", function () {
            var fs = require("fs");

            function extractDependencies(path) {
                var fileContents = fs.readFileSync(path, "utf-8");
                var dir = path.substring(0, path.lastIndexOf("/"));
                var deps = [];

                var lines = fileContents.split("\n");
                for (var i = 0; i < lines.length; i++) {
                    var line = lines[i];
                    var processedOne = false;
                    if (line.indexOf("<reference") < 0 || line.indexOf("ms-appx") >= 0) {
                        if (processedOne) {
                            break;
                        } else {
                            continue;
                        }
                    }

                    var startIndex = line.indexOf('path="') + 6;
                    var endIndex = line.indexOf('"', startIndex);
                    var path = dir + "/" + line.substring(startIndex, endIndex);
                    if (!fs.existsSync(path)) {
                        grunt.fail.warn("Could not find dependency:\n" + line + "in file:\n" + path);
                    }
                    deps.push(path);

                    processedOne = true;
                }
                return deps;
            }

            function arrayIndexOf(arr, obj) {
                for (var i = 0; i < arr.length; i++) {
                    if (arr[i] === obj) {
                        return i;
                    }
                }
                return -1;
            }

            var testMenuTemplate =
        '    \r\n\
<!DOCTYPE html>                                                                                \r\n\
                                                                                \r\n\
                                                                                \r\n\
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />                                                                 \r\n\
    <title>WinJS Tests</title>                                                                                \r\n\
                                                                                \r\n\
                                                                                \r\n\
                                                                                \r\n\
                                              \r\n\

                                                                                \r\n\
@@TESTS                                                                                \r\n\

                                                                                \r\n\
                                                                                \r\n\
';

        var testPageTemplate =
    '    \r\n\
\r\n\
<!DOCTYPE html>                                                                                \r\n\
                                                                                \r\n\
                                                                                \r\n\
    <title>@@TITLE</title>                                                                                \r\n\
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />                                                                 \r\n\
                                                                                \r\n\
    <link type="text/css" rel="stylesheet" href="../../Microsoft.WinJS.2.1/css/ui-dark.css" />                              \r\n\
                                                                  \r\n\
                                                                    \r\n\
                                                    \r\n\
                                                      \r\n\
                                                                                \r\n\
                                                                                \r\n\
    <link type="text/css" rel="stylesheet" href="../../../node_modules/qunitjs/qunit/qunit.css" />                          \r\n\
                                                        \r\n\
                                                                       \r\n\
                                                                                \r\n\
                                                                                \r\n\
@@TESTREFERENCES                                                                                \r\n\
                                                                                \r\n\
                                                                                \r\n\

  \r\n\

                                                                                \r\n\
                                                                                \r\n\
'.replace(/@@TARGETFRAMEWORK/g, config.targetFramework);

            if (!fs.existsSync("./bin")) {
                fs.mkdirSync("./bin");
            }
            if (!fs.existsSync("./bin/tests")) {
                fs.mkdirSync("./bin/tests");
            }

            var dirs = fs.readdirSync("./tests");
            var tests = "";
            dirs.forEach(function (dir) {
                if (!fs.lstatSync("./tests/" + dir).isDirectory() || dir === "TestData" || dir === "TestLib") {
                    return;
                }

                var html = testPageTemplate;
                html = html.replace("@@TITLE", dir);

                var testReferences = "";

                var srcs = [];
                var csss = [];
                var files = fs.readdirSync("./tests/" + dir);
                for (var i = files.length - 1; i >= 0; i--) {
                    // Some folders have .html test assets, we can ignore those
                    var file = files[i];
                    if (file.indexOf(".css") >= 0) {
                        csss.push("./tests/" + dir + "/" + file);
                    } else if (file.indexOf(".js") >= 0) {
                        srcs.push("./tests/" + dir + "/" + file);
                    }
                }
                var done = false;
                while (!done) {
                    done = true;
                    var srcsCopy = srcs.slice(0);
                    for (var i = 0; i < srcs.length; i++) {
                        var deps = extractDependencies(srcs[i]);
                        var length = srcsCopy.length;
                        deps.forEach(function (dep) {
                            if (dep === srcs[i]) {
                                // Some files reference themselves, this check breaks the infinite loop
                                return;
                            }
                            if (dep.indexOf(".css") >= 0) {
                                if (arrayIndexOf(csss, dep) < 0) {
                                    csss.push(dep);
                                }
                            } else {
                                var index = arrayIndexOf(srcsCopy, dep);
                                if (index >= 0) {
                                    // If this dependency already exists, we need to reorder it to the bottom
                                    // of the array so it gets loaded first. This usually happens when a dependency
                                    // is in the same folder as the test folder but appears alphabetically before it.
                                    srcsCopy.splice(index, 1);
                                    length--;
                                } else {
                                    done = false;
                                }
                                // Since the \r\n';
                }
                testReferences = testReferences.substr(0, testReferences.length - 2);
                html = html.replace("@@TESTREFERENCES", testReferences);

                var testFolder = "./bin/tests/" + dir;
                if (!fs.existsSync(testFolder)) {
                    fs.mkdirSync(testFolder);
                }
                fs.writeFileSync(testFolder + "/test.html", html);
                tests += '
' + dir + " tests
\r\n";
            });
            tests = tests.substr(0, tests.length - 2);
            fs.writeFileSync("./bin/tests/tests.html", testMenuTemplate.replace("@@TESTS", tests));
        });
    };
})();<|endoftext|>


<commit_before>UseradminApp.service('Applications', function($http,Messages){

    var defaultlist = [
        {
            "id": "1",
            "name": "UserAdmin",
            "defaultRole": "UserAdmin",
            "defaultOrgid": "Whydah",
            "availableOrgIds": null
        },
        {
            "id": "2",
            "name": "Mobilefirst",
            "defaultRole": "client",
            "defaultOrgid": "Altran",
            "availableOrgIds": null
        },
        {
            "id": "3",
            "name": "Whydah",
            "defaultRole": "developer",
            "defaultOrgid": "Whydah",
            "availableOrgIds": null
        }
    ];

    var wishlist = {
        applicationId: 1,
        applicationName: 'name',
        defaultRole: 'role',
        defaultRoleValue: 'value',
        defaultOrg: 'org1',
        organisations: [
            'org1',
            'org2',
            'org3'
        ]
    }

    this.list = [];
    this.selected = false;

    this.search = function() {
        console.log('Searching for applications...');
        var that = this;
        $http({
            method: 'GET',
            url: baseUrl + 'applications'
        }).success(function (data) {
            that.list = data;
        });
        return this;
    };

     this.search = function(searchQuery) {
     console.log('Searching for applications...');
     this.searchQuery = searchQuery || '*';
     var that = this;
     $http({
     method: 'GET',
     url: baseUrl+'applications/find/'+this.searchQuery
     //url: 'json/users.json',
     }).success(function (data) {
     that.list = data.result;
     that.rows = data.rows;
     }).error(function(data,status){
     // This is most likely due to usertoken timeout - TODO: Redirect to login webapp
     console.log('Unable to search', data);
     switch (status) {
     case 403: // Forbidden
     Messages.add('danger', 'Unable to seach! Forbidden...');
     break;
     case 404:  // 404 No access
     Messages.add('danger', 'Unable to search! No access...');
     break;
     case 409:  // 409 Conflict - will prbably not occur here
     Messages.add('danger', 'Search already exists...');
     break;
     default:
     Messages.add('danger', 'Search failed with error code: ' + status);
     }

     });
     return this;
     };

    function buildRoleNames(application) {
        var roleNames = [];
        if (application.hasOwnProperty("roles")) {
            if (application.roles && application.roles.length) {
                for (var i = 0; i < application.roles.length; i++) {
                    var role = application.roles[i];
                    roleNames.push(role.name);
                }
            }
        }
        return roleNames;
    }
    function buildOrgNames(application) {
        var orgNames = [];
        if (application.hasOwnProperty("organizationNames")) {
            if (application.organizationNames && application.organizationNames.length) {
                for (var i = 0; i < application.organizationNames.length; i++) {
                    var org = application.organizationNames[i];
                    orgNames.push(org.name);
                }
            }
        }
        return orgNames;
    }

    this.get = function(id, callback) {
        console.log('Getting Application with id=', id);
        var that = this;
        $http({
            method: 'GET',
            url: baseUrl+'application/'+id+'/'
        }).success(function (data) {
            console.log('Got applicaton', data);
            that.application = data;
            that.application.secret = data.security.secret;
            that.application.applicationJson = JSON.stringify(data);
            that.application.roleNames = buildRoleNames(that.application);
            that.application.orgNames = buildOrgNames(that.application);
            if(callback) {
                callback(that.application);
            }
        });
        return this;
    };

    this.add = function(application, successCallback) {
        console.log('Adding application', application);
        var that = this;

        //application.security = {};
        //application.security.secret = application.secret;
        //delete application.secret;
        var postData = buildApplicationUpdate(application);
        if (postData.hasOwnProperty('name')) {
            $http({
                method: 'POST',
                url: baseUrl + 'application/',
                data: postData
            }).success(function (data) {
                Messages.add('success', 'application "' + application.name + '" was added successfully.');
                application.id = data.id;
                that.search(that.searchQuery);
                if (successCallback) {
                    successCallback();
                }
            }).error(function (data, status) {
                console.log('application was not added', data);
                switch (status) {
                    case 403:
                        Messages.add('danger', 'application was not added! No access...');
                        break;
                    case 404:  /* 404 No access */
                        Messages.add('danger', 'application was not added! No access...');
                        break;
                    case 409:  /* 409 Conflict - user exists or was double posted */
                        Messages.add('danger', 'application was not added! Already exists...');
                        break;
                    default:
                        Messages.add('danger', 'application was not added and! Try again later...');
                }
                $scope.activateTimeoutModal();
            });
        }
        return this;
    };

    this.save = function(application, successCallback) {
        console.log('Updating application', JSON.stringify(application));
        var that = this;
        var postData = buildApplicationUpdate(application);
        if (postData.hasOwnProperty('name')) {
            console.log("Save this json: " + JSON.stringify(postData));
            $http({
                method: 'PUT',
                url: baseUrl + 'application/' + application.id + '/',
                data: postData
            }).success(function (data) {
                Messages.add('success', 'application "' + application.name + '" was updated successfully.');
                application.id = data.id;
                that.search(that.searchQuery);
                if (successCallback) {
                    successCallback();
                }
            }).error(function (data, status) {
                console.log('application was not updated', data);
                switch (status) {
                    case 400:
                        Messages.add('danger','application was not updated! Please validate your form and applicationjson input.');
                        break;
                    case 403:
                        Messages.add('danger', 'application was not updated! No access...');
                        break;
                    case 404:  /* 404 No access */
                        Messages.add('danger', 'application was not updated! No access...');
                        break;
                    case 409:  /* 409 Conflict - user exists or was double posted */
                        Messages.add('danger', 'application was not updated! Already exists...');
                        break;
                    default:
                        Messages.add('danger', 'application was not updated and! Try again later...');
                }
                $scope.activateTimeoutModal();
            });
        }
        return this;
    };

    function buildApplicationUpdate(application) {
        var postData = {};
        if (application.hasOwnProperty('secret')) {
            if (application.hasOwnProperty('security')) {
                application.security.secret = application.secret;
            } else {
                application.security = {};
                application.security.secret = application.secret;
            }
            delete application.secret;
        }
        if (application.hasOwnProperty('roleNames')) {
            if (typeof application.roleNames === 'string') {
                application.roles = [];
                var roleSplit = application.roleNames.split(",");
                for (i = 0; i < roleSplit.length; i++) {
                     var role = {};
                     var item = roleSplit[i];
                     role.id = item.trim();
                     role.name = item.trim();
                     application.roles.push(role);
                }
            }
        }
        if (application.hasOwnProperty('orgNames')) {
            if (typeof application.orgNames === 'string') {
                application.organizationNames = [];
                var nameSplit = application.orgNames.split(",");
                for (i = 0; i < nameSplit.length; i++) {
                    var name = {};
                    var item = nameSplit[i];
                    name.id = item.trim();
                    name.name = item.trim();
                    application.organizationNames.push(name);
                }
            }
        }
        return application;
    }

    this.saveFromJson = function(application, successCallback) {
        console.log('Updating application from json', JSON.stringify(application.applicationJson));
        var that = this;
        var postData = {};
        if (application.applicationJson) {
            try {
                postData = JSON.parse(application.applicationJson);

                console.log("Save this json: " + JSON.stringify(postData));
                $http({
                    method: 'PUT',
                    url: baseUrl + 'application/' + application.id + '/',
                    data: postData
                }).success(function (data) {
                    Messages.add('success', 'application "' + application.name + '" was updated successfully.');
                    application.id = data.id;
                    that.search(that.searchQuery);
                    if (successCallback) {
                        successCallback();
                    }
                }).error(function (data, status) {
                    console.log('application was not updated', data);
                    switch (status) {
                        case 400:
                            Messages.add('danger','application was not updated! Please validate your form and applicationjson input.');
                            break;
                        case 403:
                            Messages.add('danger', 'application was not updated! No access...');
                            break;
                        case 404:  /* 404 No access */
                            Messages.add('danger', 'application was not updated! No access...');
                            break;
                        case 409:  /* 409 Conflict - user exists or was double posted */
                            Messages.add('danger', 'application was not updated! Already exists...');
                            break;
                        default:
                            Messages.add('danger', 'application was not updated and! Try again later...');
                    }
                    $scope.activateTimeoutModal();
                });
            } catch (e) {
                Messages.add('danger', 'Could not parse applicationJson to JSON object.');
            }
        } else {
            Messages.add('danger', 'Could not update application. ApplcationJson is missing.');
        }

        return this;
    };

    this.delete = function(application, successCallback) {
        console.log('Deleting application', JSON.stringify(application));
        var that = this;
        if (application.hasOwnProperty(secret)) {
            application.security = {};
            application.security.secret = application.secret;
            delete application.secret;
        }
        $http({
            method: 'DELETE',
            url: baseUrl+'application/'+application.id +'/'
            //data: application
        }).success(function (data) {
            Messages.add('success', 'application "'+application.name+'" was deleted.');
            application.id = data.id;
            that.search(that.searchQuery);
            if(successCallback){
                successCallback();
            }
        }).error(function(data,status){
            console.log('application was not deleted.', data, status);
            switch (status) {
                case 403:
                    Messages.add('danger', 'application was not deleted! No access...');
                    break;
                case 404:  /* 404 No access */
                    Messages.add('danger', 'application was not deleted! No access...');
                    break;
                case 409:  /* 409 Conflict - user exists or was double posted */
                    Messages.add('danger', 'application was not deleted! Already exists...');
                    break;
                default:
                    Messages.add('danger', 'application was not deleted and! Try again later...');
            }
            $scope.activateTimeoutModal();
        });
        return this;
    };

});<commit_msg>re-added application search<commit_after>UseradminApp.service('Applications', function($http,Messages){

    var defaultlist = [
        {
            "id": "1",
            "name": "UserAdmin",
            "defaultRole": "UserAdmin",
            "defaultOrgid": "Whydah",
            "availableOrgIds": null
        },
        {
            "id": "2",
            "name": "Mobilefirst",
            "defaultRole": "client",
            "defaultOrgid": "Altran",
            "availableOrgIds": null
        },
        {
            "id": "3",
            "name": "Whydah",
            "defaultRole": "developer",
            "defaultOrgid": "Whydah",
            "availableOrgIds": null
        }
    ];

    var wishlist = {
        applicationId: 1,
        applicationName: 'name',
        defaultRole: 'role',
        defaultRoleValue: 'value',
        defaultOrg: 'org1',
        organisations: [
            'org1',
            'org2',
            'org3'
        ]
    }

    this.list = [];
    this.selected = false;

//    this.search = function() {
//        console.log('Searching for applications...');
//        var that = this;
//        $http({
//            method: 'GET',
//            url: baseUrl + 'applications'
//        }).success(function (data) {
//            that.list = data;
//        });
//        return this;
//    };

     this.search = function(searchQuery) {
        console.log('Searching for applications...');
        this.searchQuery = searchQuery || '*';
         var that = this;
         $http({
            method: 'GET',
            url: baseUrl+'applications/find/'+this.searchQuery
            //url: 'json/users.json',
         }).success(function (data) {
            that.list = data.result;
            that.rows = data.rows;
         }).error(function(data,status){
         // This is most likely due to usertoken timeout - TODO: Redirect to login webapp
         console.log('Unable to search', data);
         switch (status) {
            case 403: // Forbidden
               Messages.add('danger', 'Unable to seach! Forbidden...');
               break;
            case 404:  // 404 No access
               Messages.add('danger', 'Unable to search! No access...');
               break;
            case 409:  // 409 Conflict - will prbably not occur here
               Messages.add('danger', 'Search already exists...');
               break;
            default:
               Messages.add('danger', 'Search failed with error code: ' + status);
          }

          });
        return this;
     };

    function buildRoleNames(application) {
        var roleNames = [];
        if (application.hasOwnProperty("roles")) {
            if (application.roles && application.roles.length) {
                for (var i = 0; i < application.roles.length; i++) {
                    var role = application.roles[i];
                    roleNames.push(role.name);
                }
            }
        }
        return roleNames;
    }
    function buildOrgNames(application) {
        var orgNames = [];
        if (application.hasOwnProperty("organizationNames")) {
            if (application.organizationNames && application.organizationNames.length) {
                for (var i = 0; i < application.organizationNames.length; i++) {
                    var org = application.organizationNames[i];
                    orgNames.push(org.name);
                }
            }
        }
        return orgNames;
    }

    this.get = function(id, callback) {
        console.log('Getting Application with id=', id);
        var that = this;
        $http({
            method: 'GET',
            url: baseUrl+'application/'+id+'/'
        }).success(function (data) {
            console.log('Got applicaton', data);
            that.application = data;
            that.application.secret = data.security.secret;
            that.application.applicationJson = JSON.stringify(data);
            that.application.roleNames = buildRoleNames(that.application);
            that.application.orgNames = buildOrgNames(that.application);
            if(callback) {
                callback(that.application);
            }
        });
        return this;
    };

    this.add = function(application, successCallback) {
        console.log('Adding application', application);
        var that = this;

        //application.security = {};
        //application.security.secret = application.secret;
        //delete application.secret;
        var postData = buildApplicationUpdate(application);
        if (postData.hasOwnProperty('name')) {
            $http({
                method: 'POST',
                url: baseUrl + 'application/',
                data: postData
            }).success(function (data) {
                Messages.add('success', 'application "' + application.name + '" was added successfully.');
                application.id = data.id;
                that.search(that.searchQuery);
                if (successCallback) {
                    successCallback();
                }
            }).error(function (data, status) {
                console.log('application was not added', data);
                switch (status) {
                    case 403:
                        Messages.add('danger', 'application was not added! No access...');
                        break;
                    case 404:  /* 404 No access */
                        Messages.add('danger', 'application was not added! No access...');
                        break;
                    case 409:  /* 409 Conflict - user exists or was double posted */
                        Messages.add('danger', 'application was not added! Already exists...');
                        break;
                    default:
                        Messages.add('danger', 'application was not added and! Try again later...');
                }
                $scope.activateTimeoutModal();
            });
        }
        return this;
    };

    this.save = function(application, successCallback) {
        console.log('Updating application', JSON.stringify(application));
        var that = this;
        var postData = buildApplicationUpdate(application);
        if (postData.hasOwnProperty('name')) {
            console.log("Save this json: " + JSON.stringify(postData));
            $http({
                method: 'PUT',
                url: baseUrl + 'application/' + application.id + '/',
                data: postData
            }).success(function (data) {
                Messages.add('success', 'application "' + application.name + '" was updated successfully.');
                application.id = data.id;
                that.search(that.searchQuery);
                if (successCallback) {
                    successCallback();
                }
            }).error(function (data, status) {
                console.log('application was not updated', data);
                switch (status) {
                    case 400:
                        Messages.add('danger','application was not updated! Please validate your form and applicationjson input.');
                        break;
                    case 403:
                        Messages.add('danger', 'application was not updated! No access...');
                        break;
                    case 404:  /* 404 No access */
                        Messages.add('danger', 'application was not updated! No access...');
                        break;
                    case 409:  /* 409 Conflict - user exists or was double posted */
                        Messages.add('danger', 'application was not updated! Already exists...');
                        break;
                    default:
                        Messages.add('danger', 'application was not updated and! Try again later...');
                }
                $scope.activateTimeoutModal();
            });
        }
        return this;
    };

    function buildApplicationUpdate(application) {
        var postData = {};
        if (application.hasOwnProperty('secret')) {
            if (application.hasOwnProperty('security')) {
                application.security.secret = application.secret;
            } else {
                application.security = {};
                application.security.secret = application.secret;
            }
            delete application.secret;
        }
        if (application.hasOwnProperty('roleNames')) {
            if (typeof application.roleNames === 'string') {
                application.roles = [];
                var roleSplit = application.roleNames.split(",");
                for (i = 0; i < roleSplit.length; i++) {
                     var role = {};
                     var item = roleSplit[i];
                     role.id = item.trim();
                     role.name = item.trim();
                     application.roles.push(role);
                }
            }
        }
        if (application.hasOwnProperty('orgNames')) {
            if (typeof application.orgNames === 'string') {
                application.organizationNames = [];
                var nameSplit = application.orgNames.split(",");
                for (i = 0; i < nameSplit.length; i++) {
                    var name = {};
                    var item = nameSplit[i];
                    name.id = item.trim();
                    name.name = item.trim();
                    application.organizationNames.push(name);
                }
            }
        }
        return application;
    }

    this.saveFromJson = function(application, successCallback) {
        console.log('Updating application from json', JSON.stringify(application.applicationJson));
        var that = this;
        var postData = {};
        if (application.applicationJson) {
            try {
                postData = JSON.parse(application.applicationJson);

                console.log("Save this json: " + JSON.stringify(postData));
                $http({
                    method: 'PUT',
                    url: baseUrl + 'application/' + application.id + '/',
                    data: postData
                }).success(function (data) {
                    Messages.add('success', 'application "' + application.name + '" was updated successfully.');
                    application.id = data.id;
                    that.search(that.searchQuery);
                    if (successCallback) {
                        successCallback();
                    }
                }).error(function (data, status) {
                    console.log('application was not updated', data);
                    switch (status) {
                        case 400:
                            Messages.add('danger','application was not updated! Please validate your form and applicationjson input.');
                            break;
                        case 403:
                            Messages.add('danger', 'application was not updated! No access...');
                            break;
                        case 404:  /* 404 No access */
                            Messages.add('danger', 'application was not updated! No access...');
                            break;
                        case 409:  /* 409 Conflict - user exists or was double posted */
                            Messages.add('danger', 'application was not updated! Already exists...');
                            break;
                        default:
                            Messages.add('danger', 'application was not updated and! Try again later...');
                    }
                    $scope.activateTimeoutModal();
                });
            } catch (e) {
                Messages.add('danger', 'Could not parse applicationJson to JSON object.');
            }
        } else {
            Messages.add('danger', 'Could not update application. ApplcationJson is missing.');
        }

        return this;
    };

    this.delete = function(application, successCallback) {
        console.log('Deleting application', JSON.stringify(application));
        var that = this;
        if (application.hasOwnProperty(secret)) {
            application.security = {};
            application.security.secret = application.secret;
            delete application.secret;
        }
        $http({
            method: 'DELETE',
            url: baseUrl+'application/'+application.id +'/'
            //data: application
        }).success(function (data) {
            Messages.add('success', 'application "'+application.name+'" was deleted.');
            application.id = data.id;
            that.search(that.searchQuery);
            if(successCallback){
                successCallback();
            }
        }).error(function(data,status){
            console.log('application was not deleted.', data, status);
            switch (status) {
                case 403:
                    Messages.add('danger', 'application was not deleted! No access...');
                    break;
                case 404:  /* 404 No access */
                    Messages.add('danger', 'application was not deleted! No access...');
                    break;
                case 409:  /* 409 Conflict - user exists or was double posted */
                    Messages.add('danger', 'application was not deleted! Already exists...');
                    break;
                default:
                    Messages.add('danger', 'application was not deleted and! Try again later...');
            }
            $scope.activateTimeoutModal();
        });
        return this;
    };

});<|endoftext|>


<commit_before>//viewmodel for the assess page
function pageViewModel(gvm) {
    // Page specific i18n bindings
    gvm.title = ko.computed(function(){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("AssessTitle");}, gvm);
    gvm.pageHeader = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AssessTitle");}, gvm);
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectName");}, gvm);
    gvm.homeManual = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("HomeManual");}, gvm);
    gvm.foundProjects = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("FoundProjects");}, gvm);
    gvm.selectCourse = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("SelectCourse");}, gvm);

    // Pagination i18n bindings
    gvm.addBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AddBtn")}, gvm);

    // Table i18n bindings
    gvm.codeTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("CodeTableTitle");}, gvm);
    gvm.nameTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("NameTableTitle");}, gvm);
    gvm.descTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("DescTableTitle");}, gvm);
    gvm.actionTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ActionTableTitle");}, gvm);

    gvm.availableLocations = ko.observableArray([]);
    gvm.availableTrainings = ko.observableArray([]);
    gvm.availableCourses = ko.observableArray([]);

    gvm.currentCourseId = null;

    gvm.updateLocations = function() {
        $.getJSON('/api/locations', function(data) {
            gvm.availableLocations.removeAll();
            $.each(data, function(i, item) {
                /* Put item in list */
                gvm.availableLocations.push(item);

                /* Add listener to listitem */
                $("#locbtn-" + item.id).click(function(){
                    gvm.currentCourseId = null;
                    gvm.updateTrainings(item.id);
                    $(".btn-location span:first").text($(this).text());
                });
            });
        });
    };

    /*
     * Update the training data
     */
    gvm.updateTrainings = function(id) {
        $.getJSON('/api/trainings/' + id, function(data) {
            gvm.availableTrainings.removeAll();
            $.each(data, function(i, item) {
                gvm.availableTrainings.push(item);

                /* Add listener to listitem */
                $("#trainingbtn-" + item.id).click(function(){
                    gvm.currentCourseId = null;
                    gvm.updateCourses(item.id);
                    $(".btn-training span:first").text($(this).text());
                });
            });
        });
    }

    /*
     * Update available courses
     */
    gvm.updateCourses = function(id) {
        $.getJSON('/api/courses/' + id, function(data) {
            gvm.availableCourses.removeAll();
            $.each(data, function(i, item) {
                gvm.availableCourses.push(item);

                /* Add listener to listitem */
                $("#coursebtn-" + item.id).click(function(){
                    $(".btn-course span:first").text($(this).text());
                    gvm.currentCourseId = item.id;
                    loadTablePage(item.id, 1);
                });
            });
        });
    }

    // The table data observable array
    gvm.tabledata = ko.observableArray([]);

    // Add data to the table
    gvm.addTableData = function(id, code, name, desc) {
        // Push data
        var tblOject = {tid: id, tcode: code, tname: name, tdesc: desc};
        gvm.tabledata.push(tblOject);
    }

    $('#assessbtn-' + id).bind('click', function(event, data){
        // Edit the table item
        showEditProjectTypeModal(code, name, desc, id);
        event.stopPropagation();
    });

    gvm.clearTable = function() {
        gvm.tabledata.removeAll();
    }
}

function loadTablePage(courseid, pagenr)
{
    $.getJSON('/api/projects/' + courseid + '/page/' + pagenr, function(data){

        /* Clear current table page */
        viewModel.clearTable()

        // Load table data
        $.each(data.data, function(i, item) {
            viewModel.addTableData(item.id, item.code, item.name, item.description);
        });

        /* Let previous en next buttons work */
        if(data.prev == "none"){
            $('#pager-prev-btn').addClass('disabled');
        } else {
            $('#pager-prev-btn').removeClass('disabled');
            $('#pager-prev-btn a').click(function(){
                loadTablePage(data.prev);
            });
        }

        if(data.next == "none"){
            $('#pager-next-btn').addClass('disabled');
        } else {
            $('#pager-next-btn').removeClass('disabled');
            $('#pager-next-btn a').click(function(){
                loadTablePage(data.next);
            });
        }

        // Number of pager buttons
        var numItems = $('.pager-nr-btn').length;

        /* Calculate for the pager buttons */
        var lowPage = Math.floor(pagenr/numItems) + 1;

        $('.pager-nr-btn').each(function() {
            /* calculate current page number */
            var thispagenr = lowPage++;

            /* Add the page number */
            $(this).html('' + thispagenr + '');

            /* Add active class to current page */
            if(thispagenr == pagenr) {
                $(this).addClass('active');
            } else {
                $(this).removeClass('active');
            }

            /* Disable inactive classes and bind handlers to active classes */
            if(thispagenr > data.pagecount) {
                $(this).addClass('disabled');
            } else {
                /* Add click listener for button */
                $(this).click(function() {
                    loadTablePage(courseid, thispagenr);
                });
            }
        });
    });

}

function initPage() {
    viewModel.updateLocations();
    loadTablePage(1);
}<commit_msg>assess projects<commit_after>//viewmodel for the assess page
function pageViewModel(gvm) {
    // Page specific i18n bindings
    gvm.title = ko.computed(function(){i18n.setLocale(gvm.lang()); return gvm.app() + ' - ' + i18n.__("AssessTitle");}, gvm);
    gvm.pageHeader = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AssessTitle");}, gvm);
    gvm.projectname = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ProjectName");}, gvm);
    gvm.homeManual = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("HomeManual");}, gvm);
    gvm.foundProjects = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("FoundProjects");}, gvm);
    gvm.selectCourse = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("SelectCourse");}, gvm);

    // Pagination i18n bindings
    gvm.addBtn = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("AddBtn")}, gvm);

    // Table i18n bindings
    gvm.codeTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("CodeTableTitle");}, gvm);
    gvm.nameTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("NameTableTitle");}, gvm);
    gvm.descTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("DescTableTitle");}, gvm);
    gvm.actionTableTitle = ko.computed(function(){i18n.setLocale(gvm.lang()); return i18n.__("ActionTableTitle");}, gvm);

    gvm.availableLocations = ko.observableArray([]);
    gvm.availableTrainings = ko.observableArray([]);
    gvm.availableCourses = ko.observableArray([]);

    gvm.currentCourseId = null;

    gvm.updateLocations = function() {
        $.getJSON('/api/locations', function(data) {
            gvm.availableLocations.removeAll();
            $.each(data, function(i, item) {
                /* Put item in list */
                gvm.availableLocations.push(item);

                /* Add listener to listitem */
                $("#locbtn-" + item.id).click(function(){
                    gvm.currentCourseId = null;
                    gvm.updateTrainings(item.id);
                    $(".btn-location span:first").text($(this).text());
                });
            });
        });
    };

    /*
     * Update the training data
     */
    gvm.updateTrainings = function(id) {
        $.getJSON('/api/trainings/' + id, function(data) {
            gvm.availableTrainings.removeAll();
            $.each(data, function(i, item) {
                gvm.availableTrainings.push(item);

                /* Add listener to listitem */
                $("#trainingbtn-" + item.id).click(function(){
                    gvm.currentCourseId = null;
                    gvm.updateCourses(item.id);
                    $(".btn-training span:first").text($(this).text());
                });
            });
        });
    }

    /*
     * Update available courses
     */
    gvm.updateCourses = function(id) {
        $.getJSON('/api/courses/' + id, function(data) {
            gvm.availableCourses.removeAll();
            $.each(data, function(i, item) {
                gvm.availableCourses.push(item);

                /* Add listener to listitem */
                $("#coursebtn-" + item.id).click(function(){
                    $(".btn-course span:first").text($(this).text());
                    gvm.currentCourseId = item.id;
                    loadTablePage(item.id, 1);
                });
            });
        });
    }

    // The table data observable array
    gvm.tabledata = ko.observableArray([]);

    // Add data to the table
    gvm.addTableData = function(id, code, name, desc) {
        // Push data
        var tblOject = {tid: id, tcode: code, tname: name, tdesc: desc};
        gvm.tabledata.push(tblOject);
    }

    gvm.clearTable = function() {
        gvm.tabledata.removeAll();
    }
}

function loadTablePage(courseid, pagenr)
{
    $.getJSON('/api/projects/' + courseid + '/page/' + pagenr, function(data){

        /* Clear current table page */
        viewModel.clearTable()

        // Load table data
        $.each(data.data, function(i, item) {
            viewModel.addTableData(item.id, item.code, item.name, item.description);
        });

        /* Let previous en next buttons work */
        if(data.prev == "none"){
            $('#pager-prev-btn').addClass('disabled');
        } else {
            $('#pager-prev-btn').removeClass('disabled');
            $('#pager-prev-btn a').click(function(){
                loadTablePage(data.prev);
            });
        }

        if(data.next == "none"){
            $('#pager-next-btn').addClass('disabled');
        } else {
            $('#pager-next-btn').removeClass('disabled');
            $('#pager-next-btn a').click(function(){
                loadTablePage(data.next);
            });
        }

        // Number of pager buttons
        var numItems = $('.pager-nr-btn').length;

        /* Calculate for the pager buttons */
        var lowPage = Math.floor(pagenr/numItems) + 1;

        $('.pager-nr-btn').each(function() {
            /* calculate current page number */
            var thispagenr = lowPage++;

            /* Add the page number */
            $(this).html('' + thispagenr + '');

            /* Add active class to current page */
            if(thispagenr == pagenr) {
                $(this).addClass('active');
            } else {
                $(this).removeClass('active');
            }

            /* Disable inactive classes and bind handlers to active classes */
            if(thispagenr > data.pagecount) {
                $(this).addClass('disabled');
            } else {
                /* Add click listener for button */
                $(this).click(function() {
                    loadTablePage(courseid, thispagenr);
                });
            }
        });
    });

}

function initPage() {
    viewModel.updateLocations();
    loadTablePage(1);
}<|endoftext|>