<commit_before>
/**
 * Test different channel shuffle implementation for CNN ShuffleNet.
 *
 * @see {@link https://jsperf.com/colorfulcakechen-cnn-channel-shuffle}
 */

// concat-reshape-transpose-reshape-split
function ConcatReshapeTransposeReshapeSplit( dataTensor3dArray ) {
  return tf.tidy( () => {
    let groupCount = dataTensor3dArray.length;
    let lastAxisId = dataTensor3dArray[ 0 ].rank - 1;

    let dataTensor3d = tf.concat( dataTensor3dArray, lastAxisId );

    let [ h, w, c ] = dataTensor3d.shape;
    let intermediateChannelCount = c / groupCount;

    let x = dataTensor3d.reshape( [ h, w, groupCount, intermediateChannelCount ] );
    x = x.transpose( [ 0, 1, 3, 2 ] );
    x = x.reshape( [ h, w, c] );

    return x = x.split( groupCount, lastAxisId );
  });
}

// concat-gather
function ConcatGather( dataTensor3dArray ) {
  return tf.tidy( () => {
    let groupCount = dataTensor3dArray.length;
    let lastAxisId = dataTensor3dArray[ 0 ].rank - 1;

    let dataTensor3d = tf.concat( dataTensor3dArray, lastAxisId );

    // shuffle and split by gather (one operation achieves two operations).
    let shuffledSplitedTensor3dArray = globalThis.shuffledChannelIndicesTensor1dArray.map(
      ( shuffledChannelIndicesTensor1d, i ) => {
        return dataTensor3d.gather( shuffledChannelIndicesTensor1d, lastAxisId );
    });

    return shuffledSplitedTensor3dArray;
  });
}

// split-concat
function SplitConcat( dataTensor3dArray ) {
  return tf.tidy( () => {
    let groupCount = dataTensor3dArray.length;
    let lastAxisId = dataTensor3dArray[ 0 ].rank - 1;

    let totalChannelCount = groupCount * dataTensor3dArray[ 0 ].shape[ lastAxisId ];
    let intermediateChannelCount = totalChannelCount / groupCount;

    // Split every group (a multiple channel tensor3d) into more (intermediate) channels.
    let tensor3dArrayArray = dataTensor3dArray.map( ( dataTensor3d, i ) => {
      return dataTensor3d.split( intermediateChannelCount, lastAxisId );
    });

    let oneChannelTensor3dArray = tensor3dArrayArray.flat(); // Every element will be a single channel tensor3d.

    // shuffle and split by concat (one operation achieves two operations).
    let shuffledSplitedTensor3dArray = globalThis.shuffledChannelIndicesArray.map( ( shuffledChannelIndices, i ) => {
      let multipleChannelTensor3dArray = shuffledChannelIndices.map( ( channelIndex ) => {
        return oneChannelTensor3dArray[ channelIndex ];
      });
      return multipleChannelTensor3dArray.concat( lastAxisId );
    });

    return shuffledSplitedTensor3dArray;

// !!!
//     let resultTensor3dArray = new Array( groupCount );
//     let shuffledTensor3dArray = new Array( intermediateChannelCount );
//     for ( let x = 0; x < groupCount; ++x ) {
//
//       // Collect x-th intermediate channels of every group as new (x-th) group (i.e. shuffle them).
//       for ( let y = 0; y < intermediateChannelCount; ++y ) {
//         shuffledTensor3dArray[ y ] = tensor3dArrayArray[ x ][ y ];
//       }
//
//       // Concatenate x-th intermediate channels into one group (i.e. the x-th group).
//       resultTensor3dArray[ x ] = tf.concat( shuffledTensor3dArray, lastAxisId );
//     }
//
//     return resultTensor3dArray;
  });
}

// Test concat-reshape-transpose-reshape-split
function by_ConcatReshapeTransposeReshapeSplit( dataTensor3dArray ) {
  tf.tidy( () => {
    ConcatReshapeTransposeReshapeSplit( dataTensor3dArray );
  });
}

// Test concat-gather
function by_ConcatGather( dataTensor3dArray ) {
  tf.tidy( () => {
    ConcatGather( dataTensor3dArray );
  });
}

// Test split-concat
function by_SplitConcat( dataTensor3dArray ) {
  tf.tidy( () => {
    SplitConcat( dataTensor3dArray );
  });
}

let height = 10; // image height
let width = 15;  // image width
let depth = 12;  // image channel count

let valueCount = height * width * depth;

let groupCount = 2; // Split the data into how many groups.

let dataTensor3dArray = tf.tidy( () => {
  let dataTensor1d = tf.linspace(0, valueCount - 1, valueCount );
  let dataTensor3d = dataTensor1d.reshape( [ height, width, depth ] );
  return dataTensor3d.split( groupCount, dataTensor3d.rank - 1 );  // Along the last axis.
});

// Shuffled channel indices tensor1d (One dimension) for ConcatGather()
globalThis.shuffledChannelIndicesTensor1dArray = tf.tidy( () => {
  let channelIndices = tf.linspace( 0, depth - 1, depth ).toInt(); // should be integer so that can be used as gather's index.
  let lastAxisId = channelIndices.rank - 1;

  let newChannelCount = depth / groupCount;

  let x = channelIndices.reshape( [ groupCount, newChannelCount ] );
  x = x.transpose( [ 1, 0 ] );
  x = x.reshape( [ depth ] );

  return x.split( groupCount, lastAxisId );
});

// Shuffled channel indices (One dimension) for SplitConcat()
globalThis.shuffledChannelIndicesArray = globalThis.shuffledChannelIndicesTensor1dArray.dataSync();

globalThis.dataTensor3dArray = dataTensor3dArray;

globalThis.cnnShuffle_by_ConcatReshapeTransposeReshapeSplit = by_ConcatReshapeTransposeReshapeSplit();
globalThis.cnnShuffle_by_ConcatGather = by_ConcatGather();
globalThis.cnnShuffle_by_SplitSplitConcatConcat = by_SplitSplitConcatConcat();
<commit_msg>Update jsPerf_CNNChannelShuffle.js<commit_after>
/**
 * Test different channel shuffle implementation for CNN ShuffleNet.
 *
 * @see {@link https://jsperf.com/colorfulcakechen-cnn-channel-shuffle}
 */

// concat-reshape-transpose-reshape-split
function ConcatReshapeTransposeReshapeSplit( dataTensor3dArray ) {
  return tf.tidy( () => {
    let groupCount = dataTensor3dArray.length;
    let lastAxisId = dataTensor3dArray[ 0 ].rank - 1;

    let dataTensor3d = tf.concat( dataTensor3dArray, lastAxisId );

    let [ h, w, c ] = dataTensor3d.shape;
    let intermediateChannelCount = c / groupCount;

    let x = dataTensor3d.reshape( [ h, w, groupCount, intermediateChannelCount ] );
    x = x.transpose( [ 0, 1, 3, 2 ] );
    x = x.reshape( [ h, w, c] );

    return x = x.split( groupCount, lastAxisId );
  });
}

// concat-gather
function ConcatGather( dataTensor3dArray ) {
  return tf.tidy( () => {
    let groupCount = dataTensor3dArray.length;
    let lastAxisId = dataTensor3dArray[ 0 ].rank - 1;

    let dataTensor3d = tf.concat( dataTensor3dArray, lastAxisId );

    // shuffle and split by gather (one operation achieves two operations).
    let shuffledSplitedTensor3dArray = globalThis.shuffledChannelIndicesTensor1dArray.map(
      ( shuffledChannelIndicesTensor1d, i ) => {
        return dataTensor3d.gather( shuffledChannelIndicesTensor1d, lastAxisId );
    });

    return shuffledSplitedTensor3dArray;
  });
}

// split-concat
function SplitConcat( dataTensor3dArray ) {
  return tf.tidy( () => {
    let groupCount = dataTensor3dArray.length;
    let lastAxisId = dataTensor3dArray[ 0 ].rank - 1;

    let totalChannelCount = groupCount * dataTensor3dArray[ 0 ].shape[ lastAxisId ];
    let intermediateChannelCount = totalChannelCount / groupCount;

    // Split every group (a multiple channel tensor3d) into more (intermediate) channels.
    let tensor3dArrayArray = dataTensor3dArray.map( ( dataTensor3d, i ) => {
      return dataTensor3d.split( intermediateChannelCount, lastAxisId );
    });

    let oneChannelTensor3dArray = tensor3dArrayArray.flat(); // Every element will be a single channel tensor3d.

    // shuffle and split by concat (one operation achieves two operations).
    let shuffledSplitedTensor3dArray = globalThis.shuffledChannelIndicesArray.map( ( shuffledChannelIndices, i ) => {
      let multipleChannelTensor3dArray = shuffledChannelIndices.map( ( channelIndex ) => {
        return oneChannelTensor3dArray[ channelIndex ];
      });
      return multipleChannelTensor3dArray.concat( lastAxisId );
    });

    return shuffledSplitedTensor3dArray;

// !!!
//     let resultTensor3dArray = new Array( groupCount );
//     let shuffledTensor3dArray = new Array( intermediateChannelCount );
//     for ( let x = 0; x < groupCount; ++x ) {
//
//       // Collect x-th intermediate channels of every group as new (x-th) group (i.e. shuffle them).
//       for ( let y = 0; y < intermediateChannelCount; ++y ) {
//         shuffledTensor3dArray[ y ] = tensor3dArrayArray[ x ][ y ];
//       }
//
//       // Concatenate x-th intermediate channels into one group (i.e. the x-th group).
//       resultTensor3dArray[ x ] = tf.concat( shuffledTensor3dArray, lastAxisId );
//     }
//
//     return resultTensor3dArray;
  });
}

// Test concat-reshape-transpose-reshape-split
function by_ConcatReshapeTransposeReshapeSplit( dataTensor3dArray ) {
  tf.tidy( () => {
    ConcatReshapeTransposeReshapeSplit( dataTensor3dArray );
  });
}

// Test concat-gather
function by_ConcatGather( dataTensor3dArray ) {
  tf.tidy( () => {
    ConcatGather( dataTensor3dArray );
  });
}

// Test split-concat
function by_SplitConcat( dataTensor3dArray ) {
  tf.tidy( () => {
    SplitConcat( dataTensor3dArray );
  });
}

let height = 10; // image height
let width = 15;  // image width
let depth = 12;  // image channel count

let valueCount = height * width * depth;

let groupCount = 2; // Split the data into how many groups.

let dataTensor3dArray = tf.tidy( () => {
  let dataTensor1d = tf.linspace(0, valueCount - 1, valueCount );
  let dataTensor3d = dataTensor1d.reshape( [ height, width, depth ] );
  return dataTensor3d.split( groupCount, dataTensor3d.rank - 1 );  // Along the last axis.
});

// Shuffled channel indices tensor1d (One dimension) for ConcatGather()
globalThis.shuffledChannelIndicesTensor1dArray = tf.tidy( () => {
  let channelIndices = tf.linspace( 0, depth - 1, depth ).toInt(); // should be integer so that can be used as gather's index.
  let lastAxisId = channelIndices.rank - 1;

  let intermediateChannelCount = depth / groupCount;

  let x = channelIndices.reshape( [ groupCount, intermediateChannelCount ] );
  x = x.transpose( [ 1, 0 ] );
  x = x.reshape( [ depth ] );

  return x.split( groupCount, lastAxisId );
});

// Shuffled channel indices (One dimension) for SplitConcat()
Promise.all(
  globalThis.shuffledChannelIndicesTensor1dArray.map( ( shuffledChannelIndicesTensor1d ) => {
    return shuffledChannelIndicesTensor1d.data();
  })
).then( ( values ) => {
  globalThis.shuffledChannelIndicesArray = values;
});

globalThis.dataTensor3dArray = dataTensor3dArray;

globalThis.cnnShuffle_by_ConcatReshapeTransposeReshapeSplit = by_ConcatReshapeTransposeReshapeSplit();
globalThis.cnnShuffle_by_ConcatGather = by_ConcatGather();
globalThis.cnnShuffle_by_SplitSplitConcatConcat = by_SplitSplitConcatConcat();
<|endoftext|>


<commit_before>"use strict"
exports.__esModule = true

const log = require('debug')('eslint-module-utils:ModuleCache')

class ModuleCache {
  constructor(map) {
    this.map = map || new Map()
  }

  /**
   * returns value for returning inline
   * @param {[type]} cacheKey [description]
   * @param {[type]} result   [description]
   */
  set(cacheKey, result) {
    this.map.set(cacheKey, { result, lastSeen: Date.now() })
    log('setting entry for', cacheKey)
    return result
  }

  get(cacheKey, settings) {
    if (this.map.has(cacheKey)) {
      const f = this.map.get(cacheKey)
      // check fresness
      if (Date.now() - f.lastSeen < (settings.lifetime * 1000)) return f.result
    } else log('cache miss for', cacheKey)
    // cache miss
    return undefined
  }

}

ModuleCache.getSettings = function (settings) {
  const cacheSettings = Object.assign({
    lifetime: 30,  // seconds
  }, settings['import/cache'])

  // parse infinity
  if (cacheSettings.lifetime === '∞' || cacheSettings.lifetime === 'Infinity') {
    cacheSettings.lifetime = Infinity
  }

  return cacheSettings
}

exports.default = ModuleCache
<commit_msg>use process.hrtime instead of Date.now (#1160)<commit_after>"use strict"
exports.__esModule = true

const log = require('debug')('eslint-module-utils:ModuleCache')

class ModuleCache {
  constructor(map) {
    this.map = map || new Map()
  }

  /**
   * returns value for returning inline
   * @param {[type]} cacheKey [description]
   * @param {[type]} result   [description]
   */
  set(cacheKey, result) {
    this.map.set(cacheKey, { result, lastSeen: process.hrtime() })
    log('setting entry for', cacheKey)
    return result
  }

  get(cacheKey, settings) {
    if (this.map.has(cacheKey)) {
      const f = this.map.get(cacheKey)
      // check fresness
      if (process.hrtime(f.lastSeen)[0] < settings.lifetime) return f.result
    } else log('cache miss for', cacheKey)
    // cache miss
    return undefined
  }

}

ModuleCache.getSettings = function (settings) {
  const cacheSettings = Object.assign({
    lifetime: 30,  // seconds
  }, settings['import/cache'])

  // parse infinity
  if (cacheSettings.lifetime === '∞' || cacheSettings.lifetime === 'Infinity') {
    cacheSettings.lifetime = Infinity
  }

  return cacheSettings
}

exports.default = ModuleCache
<|endoftext|>


<commit_before>'use strict';
// 3rd
const debug = require('debug')('app:db:profile-views');
const assert = require('better-assert');
// 1st
const util = require('./util');

////////////////////////////////////////////////////////////

exports.insertView = function * (viewerId, viewedId) {
  assert(Number.isInteger(viewerId));
  assert(Number.isInteger(viewedId));
  return yield util.query(`
    INSERT INTO profile_views (viewer_id, viewed_id)
    VALUES ($1, $2)
  `, [viewerId, viewedId]);
};

exports.getLatestViews = function * (viewedId) {
  assert(Number.isInteger(viewedId));
  const rows = yield util.queryMany(`
    SELECT DISTINCT sub.*
    FROM (
      SELECT viewers.*
      FROM profile_views pv
      JOIN users viewers ON pv.viewer_id = viewers.id
      WHERE pv.viewed_id = $1
      ORDER BY pv.created_at
    ) sub
    LIMIT 10
  `, [viewedId]);
  return rows;
};
<commit_msg>Fix profile-views query<commit_after>'use strict';
// 3rd
const debug = require('debug')('app:db:profile-views');
const assert = require('better-assert');
// 1st
const util = require('./util');

////////////////////////////////////////////////////////////

exports.insertView = function * (viewerId, viewedId) {
  assert(Number.isInteger(viewerId));
  assert(Number.isInteger(viewedId));
  return yield util.query(`
    INSERT INTO profile_views (viewer_id, viewed_id)
    VALUES ($1, $2)
  `, [viewerId, viewedId]);
};

exports.getLatestViews = function * (viewedId) {
  assert(Number.isInteger(viewedId));
  const rows = yield util.queryMany(`
    SELECT viewers.uname
         , viewers.slug
         , viewers.avatar_url
         , MAX(pv.created_at) as "maxstamp"
    FROM profile_views pv
    JOIN users viewers ON pv.viewer_id = viewers.id
    WHERE pv.viewed_id = $1
    GROUP BY viewers.uname, viewers.slug, viewers.avatar_url
    ORDER BY maxstamp DESC
    LIMIT 10
  `, [viewedId]);
  return rows;
};
<|endoftext|>


<commit_before>'use strict';

// We're going to ignore transitions for now.
//
// SO: first things first. We'll set up the chart dimensions.

var masterSelector = '.article-graphic.explainer';
var chartSelector = `${masterSelector} .explainer-chart`;

/*

var d3 = require('d3');

// set various css selectors
var masterSelector = '.article-graphic.explainer';
var chartSelector = `${masterSelector} .explainer-chart`;

// utility variable for development purposes
function log(s) {
	console.log(JSON.stringify(s, null, 4));
}

// create steps chatter
var steps = [
	{
		'title': 'Step 1',
		'text': 'This is a story about buses. Boston Public School buses.'
	},
	{
		'title': 'Step 2',
		'text': 'On any given day, hundreds of buses carry thousands of kids to school. Here’s September 4, the first day of classes. [Animate bar height and update bus trip count]'
	}
];

// initialize step index to 0, the first step
var stepIndex = 0;

// wire up prev/next buttons
$(`${masterSelector} .buttons button`).click(function(e) {

	// update the index
	if ($(this).text() === 'Previous') {
		if (stepIndex > 0) {
			stepIndex--;
		}
	} else {
		if (stepIndex < steps.length - 1) {
			stepIndex++;
		}
	}

	// set the chatter
	var currentStep = steps[stepIndex];
	$(`${masterSelector} .chatter .title`).html(currentStep.title);
	$(`${masterSelector} .chatter .text`).html(currentStep.text);

	// enable/disable buttons
	var parent = $(this).parent();
	$('.previous', parent).prop('disabled', stepIndex === 0);
	$('.next', parent).prop('disabled', stepIndex === steps.length - 1);
});

// click 'previous' once to setup the buttons correctly
$(`${masterSelector} .buttons .previous`).click();

// use d3's utility datetime string parser
var parseDate = d3.time.format('%Y-%m-%d').parse;

// get data and prepare for d3
var data = require('../../../data/output/trips-daily.csv')
	.map(function(d) {
		return {
			date: parseDate(d.date),
			trips: +d.n
		};
	});

// log it to browser
//log(data);

// setup graph margins, according to convention
var margin = {top: 0, right: 0, bottom: 0, left: 0};
var outerWidth = $(chartSelector).width();
var outerHeight = outerWidth * 9 / 16;
var width = outerWidth - margin.left - margin.right;
var height = outerHeight - margin.top - margin.bottom;

// make a graph container
var svg = d3.select(`${chartSelector} svg`)
	.attr({
		width: outerWidth,
		height: outerHeight
	});

// add g to svg
var g = svg.append('g')
	.attr('transform', `translate(${margin.left}, ${margin.top})`);

// set up x-axis scale
var x = d3.time.scale()
	.range([0, width])
	.domain(d3.extent(data, d => d.date));

// set up y-axis scale
var y = d3.scale.linear()
	.range([height, 0])
	.domain([0, d3.max(data, d => d.trips)]);

g.append('g')
	.selectAll('rect')
	.data(data)
	.enter().append('rect')
	.attr({
		x: d => x(d.date),
		y: d => y(d.trips),
		width: x.range()[1] / data.length,
		height: d => height - y(d.trips)
	});
   */
<commit_msg>wire up buttons and step divs<commit_after>'use strict';

// We're going to ignore transitions for now.
//
// SO: first things first. Wire up the buttons/steps interaction.

var masterSelector = '.article-graphic.explainer';
var chartSelector = `${masterSelector} .explainer-chart`;

// initialize step index to 0, the first step
var stepIndex = 0;

// get the jQuery steps element
var $steps = $(`${chartSelector} .steps .step`);

// wire up prev/next buttons
$(`${masterSelector} .buttons button`).click(function(e) {

	// update the index
	if ($(this).text() === 'Previous') {
		if (stepIndex > 0) {
			stepIndex--;
		}
	} else {
		if (stepIndex < $steps.length - 1) {
			stepIndex++;
		}
	}

	// show the correct step
	$steps.hide();
	$steps.eq(stepIndex).show();

	// enable/disable buttons
	var parent = $(this).parent();
	$('.previous', parent).prop('disabled', stepIndex === 0);
	$('.next', parent).prop('disabled', stepIndex === $steps.length - 1);
});

// click 'previous' once to setup the buttons correctly
$(`${masterSelector} .buttons .previous`).click();

/*

var d3 = require('d3');

// set various css selectors
var masterSelector = '.article-graphic.explainer';
var chartSelector = `${masterSelector} .explainer-chart`;

// utility variable for development purposes
function log(s) {
	console.log(JSON.stringify(s, null, 4));
}

// use d3's utility datetime string parser
var parseDate = d3.time.format('%Y-%m-%d').parse;

// get data and prepare for d3
var data = require('../../../data/output/trips-daily.csv')
	.map(function(d) {
		return {
			date: parseDate(d.date),
			trips: +d.n
		};
	});

// log it to browser
//log(data);

// setup graph margins, according to convention
var margin = {top: 0, right: 0, bottom: 0, left: 0};
var outerWidth = $(chartSelector).width();
var outerHeight = outerWidth * 9 / 16;
var width = outerWidth - margin.left - margin.right;
var height = outerHeight - margin.top - margin.bottom;

// make a graph container
var svg = d3.select(`${chartSelector} svg`)
	.attr({
		width: outerWidth,
		height: outerHeight
	});

// add g to svg
var g = svg.append('g')
	.attr('transform', `translate(${margin.left}, ${margin.top})`);

// set up x-axis scale
var x = d3.time.scale()
	.range([0, width])
	.domain(d3.extent(data, d => d.date));

// set up y-axis scale
var y = d3.scale.linear()
	.range([height, 0])
	.domain([0, d3.max(data, d => d.trips)]);

g.append('g')
	.selectAll('rect')
	.data(data)
	.enter().append('rect')
	.attr({
		x: d => x(d.date),
		y: d => y(d.trips),
		width: x.range()[1] / data.length,
		height: d => height - y(d.trips)
	});
   */
<|endoftext|>


<commit_before>/*
 * Licensed to the Sakai Foundation (SF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The SF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
/*global Config, $, jQuery, get_cookie, delete_cookie, set_cookie, window, alert */

var sakai = sakai || {};

/**
 * @name sakai.topnavigation
 *
 * @class topnavigation
 *
 * @description
 * Initialize the topnavigation widget
 *
 * @version 0.0.1
 * @param {String} tuid Unique id of the widget
 * @param {Boolean} showSettings Show the settings of the widget or not
 */
sakai.topnavigation = function(tuid, showSettings){

    /////////////////////////////
    // Configuration variables //
    /////////////////////////////

    var currentChatStatus = "";

    // Links and labels
    var hiLabel = "#hispan";
    var myprofileName = "#myprofile_name";
    var onlineButton = "#online_button";
    var pictureHolder = "#picture_holder";
    var showOnlineLink = "#show_online";
    var userIdLabel = "#userid";

    // User Link
    var userLink = "#user_link";
    var userLinkMenu = userLink + "_menu";
    var userLinkMenuLink = userLink + "_menu" + " a";

    // Navigation
    var nav = "#nav";
    var navContentMediaLink = "#nav_content_media_link";
    var navCoursesSitesLink = "#nav_courses_sites_link";
    var navCoursesSitesLinkClass = "#nav_courses_sites_link";
    var navPeopleLink = "#nav_people_link";
    var navPeopleLinkClass = "nav_people_link";
    var navMySakaiLink = "#nav_my_sakai_link";
    var navCalendarLink = "#nav_calendar_link";
    var navSelectedNavItemClass = "explore_nav_selected";

    // Messages
    var chatUnreadMessages = "#chat_unreadMessages";

    // Search
    var $general_search_form = $("#general_search_container form");
    var $general_search_input = $("#general_search_input");
    var $general_search_default_value = $("#general_search_default_value");
    var generalSearchSubmitButton = "#general_search_submit_button";
    var searchFocus = false;

    // Containers
    var exploreNavigationContainer = "#explore_nav_container";

    // CSS Classes
    var searchInputFocusClass = "search_input_focus";
    var chatAvailableStatusClass = "chat_available_status";
    var chatAvailableStatusClassOnline = chatAvailableStatusClass + "_online";
    var chatAvailableStatusClassBusy = chatAvailableStatusClass + "_busy";
    var chatAvailableStatusClassOffline = chatAvailableStatusClass + "_offline";

    var userLinkChatStatusClass = ".user_link_chat_status";

    ///////////////////////
    // Utility functions //
    ///////////////////////

    /**
     * Get the number of messages that are unread and show it.
     */
    var getCountUnreadMessages = function(){
        //we have the number of unread messages as a part of the me-feed
        //so get it directly from me object.
        $(chatUnreadMessages).text(sakai.data.me.messages.unread);
    };

    /**
     * Update a certain element with a specific chatstatus
     * @param {Object} element Element that needs to be updated
     * @param {String} chatstatus The chatstatus that needs to be added
     */
    var updateChatStatusElement = function(element, chatstatus){
        element.removeClass(chatAvailableStatusClassOnline);
        element.removeClass(chatAvailableStatusClassBusy);
        element.removeClass(chatAvailableStatusClassOffline);
        element.addClass(chatAvailableStatusClass + "_" + chatstatus);
    };

    /**
     * Update the status on the page by firing an event that handles this
     */
    var updateChatStatus = function(){
        // Trigger the chat_status_change event to update other widgets
        $(window).trigger("chat_status_change", currentChatStatus);
    };

    /**
     * Set the chatstatus of the user
     * @param {String} chatstatus The chatstatus which should be
     * online/offline or busy
     */
    var sendChatStatus = function(chatstatus){
        if (currentChatStatus !== chatstatus){
            currentChatStatus = chatstatus;

            var data = {
                "chatstatus": chatstatus,
                "_charset_": "utf-8"
            };

            $.ajax({
                url: "/~" + sakai.data.me.profile["rep:userId"] + "/public/authprofile",
                type: "POST",
                data: data,
                success: function(data){
                    updateChatStatus();
                },
                error: function(xhr, textStatus, thrownError){
                    alert("An error occurend when sending the status to the server.");
                }
            });
        }
    };

    /**
     * Show or hide the user link menu
     * @param {Boolean} hideOnly
     *  true: Hide the menu only
     *  false: Show or hide the menu depending if it's already visible
     */
    var showHideUserLinkMenu = function(hideOnly){
        if ($(userLinkMenu).is(":visible") || hideOnly) {
            $(userLinkMenu).hide();
        }
        else {
            $(userLinkMenu).css("left", Math.round($(userLink).offset().left) + "px");
            $(userLinkMenu).css("top", (Math.round($(userLink).offset().top) + $(userLink).height() + 2) + "px");
            $(userLinkMenu).css("width", ($(userLink).width() + 10) + "px");
            $(userLinkMenu).show();
        }
    };

    /**
     * Add binding to some elements
     */
    var addBinding = function(){
        $(userLink).bind("click", function(){
            showHideUserLinkMenu(false);
        });

        $(userLinkChatStatusClass).bind("click", function(ev){
            showHideUserLinkMenu(false);
            var clicked = ev.currentTarget.id.split("_")[ev.currentTarget.id.split("_").length - 1];
            sendChatStatus(clicked);
        });

        $(document).bind("click", function(e){
            var $clicked = $(e.target);

            // Check if one of the parents is the userLink
            if (!$clicked.parents().is(userLink)) {
                showHideUserLinkMenu(true);
            }
        });

        $(window).bind("chat_status_change", function(event, currentChatStatus){
            updateChatStatusElement($(userLink), currentChatStatus);
        });
    };

    ////////////////
    // NAVIGATION //
    ///////////////

    /**
     * Select the page in the top navigation where you are currently on.
     * This will apply a class to the selected navigation item based on the current URL
     * @returns void;
     */
    var determineCurrentNav = function(){
        var windowLocationPath = window.location.pathname.toLowerCase();

        // Remove all selected classes from nav elements
        $(nav + " " + navSelectedNavItemClass).removeClass(navSelectedNavItemClass);

        // My Sakai
        if ((windowLocationPath.indexOf(sakai.config.URL.MY_DASHBOARD_URL) !== -1) || (windowLocationPath.indexOf(sakai.config.URL.PUBLIC_MY_DASHBOARD_URL) !== -1)) {
            $(navMySakaiLink).addClass(navSelectedNavItemClass);
            return;
        }

        // Content & Media
        if ((windowLocationPath.indexOf(sakai.config.URL.CONTENT_MEDIA_URL) !== -1) || (windowLocationPath.indexOf(sakai.config.URL.PUBLIC_CONTENT_MEDIA_URL) !== -1)) {
            $(navContentMediaLink).addClass(navSelectedNavItemClass);
            return;
        }

        // People
        if ((windowLocationPath.indexOf(sakai.config.URL.PEOPLE_URL) !== -1) || (windowLocationPath.indexOf(sakai.config.URL.PUBLIC_PEOPLE_URL) !== -1)) {
            $(navPeopleLink).addClass(navSelectedNavItemClass);
            return;
        }

        // Courses & Sites
        if ((windowLocationPath.indexOf(sakai.config.URL.COURSES_SITES_URL) !== -1) || (windowLocationPath.indexOf(sakai.config.URL.PUBLIC_COURSES_SITES_URL) !== -1) || (windowLocationPath.indexOf("/sites/") !== -1)) {
            $(navCoursesSitesLink).addClass(navSelectedNavItemClass);
            return;
        }

        // Calendar
        if ((windowLocationPath.indexOf(sakai.config.URL.SEARCH_GENERAL_URL) !== -1) || (windowLocationPath.indexOf(sakai.config.URL.SEARCH_PEOPLE_URL) !== -1) || (windowLocationPath.indexOf(sakai.config.URL.SEARCH_SITES_URL) !== -1) || (windowLocationPath.indexOf(sakai.config.URL.SEARCH_CONTENT_URL) !== -1) || (windowLocationPath.indexOf(sakai.config.URL.PUBLIC_SEARCH_URL) !== -1)) {
            $(navCalendarLink).addClass(navSelectedNavItemClass);
            return;
        }

    };

    ////////////
    // SEARCH //
    ////////////

    /**
     * Execute the search for the value that is in the search input field
     */
    var doSearch = function(){
        var tosearch = $general_search_input.val();
        // Disable search button
        $(generalSearchSubmitButton).attr("disabled", true);
        // Check whether the search term is different than the default text. If not,
        // we do a search for *
        if (!tosearch || tosearch === $general_search_default_value.text()){
            tosearch = "*";
        }

        // Only enable button if the location is the search page
        if (window.location.pathname.split("/")[2] === "search.html") {
            $(generalSearchSubmitButton).attr("disabled", false);
            // if user is on the search page use the history event to perform the search
            History.addBEvent("1", encodeURIComponent(tosearch));
        } else {
            // Redirecting back to the general search page. This expects the URL to be
            // in a format like this one: page.html#pageid|searchstring
            document.location = sakai.config.URL.SEARCH_GENERAL_URL + "#q=" + tosearch;
        }
    };

    /**
     * If this is the first time the field gets focus, we'll make his text color black
     * and remove the default value
     */
    $general_search_input.bind("focus", function(ev){
        if (!searchFocus) {
            $general_search_input.val("").addClass(searchInputFocusClass);
            searchFocus = true;
        }
    });

    /**
     * If we leave the field without filling out anything, we'll reinsert the default
     * search inputbox value
     */
    $general_search_input.bind("blur", function(ev){

        if (!$general_search_input.val()) {
            $general_search_input.removeClass(searchInputFocusClass);
            $general_search_input.val($general_search_default_value.text());
            searchFocus = false;
        }
    });

    /**
     * Bind the submit event to the search form
     * This event is triggered when you hit enter in the input field and
     * when you click on the submit button
     */
    $general_search_form.bind("submit", function(){

        doSearch();
        return false;
    });

    /**
     * Switch navigation bar to anonymous mode
     * @returns void
     */
    var switchToAnonymousMode = function(){

        // Show Nav Container
        $(exploreNavigationContainer).show();

        // Hide things which are irrelvant for Anonymous user
        $(".personal .mail").hide();
        $(".personal .sign_out").hide();
        $(".help").hide();
        $("#user_link_container").hide();

        // Show anonymous elements
        $("#other_logins_button_container").show();
        $(".log_in").addClass("help_none");

        // if config.js is set to external, register link is hidden
        if(!sakai.config.Authentication.internal) {
            $("#register_button_container").hide();
        }
        else {
            $("#register_button_container").show();
        }
        $("#login_button_container").show();

        // Set up public nav links
        $("#nav_my_sakai_link a").attr("href", sakai.config.URL.PUBLIC_MY_DASHBOARD_URL);
        $("#nav_content_media_link a").attr("href", sakai.config.URL.PUBLIC_CONTENT_MEDIA_URL_PAGE);
        $("#nav_people_link a").attr("href", sakai.config.URL.PUBLIC_PEOPLE_URL);
        $("#nav_courses_sites_link a").attr("href", sakai.config.URL.PUBLIC_COURSES_SITES_URL);
        $("#nav_search_link a").attr("href", sakai.config.URL.PUBLIC_SEARCH_URL_PAGE);

        // Make the login page redirect to the current page after login
        $(".log_in").attr("href", $(".log_in").attr("href") + "?url=" + escape(window.location.pathname + window.location.search + window.location.hash));

    };

    /**
     * Set the presence for the current user
     * We need to do this in order to let the server know the user is still available for chatting.
     */
    var setPresence = function(){

        var data = {
            "sakai:status": "online",
            "_charset_": "utf-8"
        };

        $.ajax({
            url: sakai.config.URL.PRESENCE_SERVICE,
            type: "POST",
            success: function(){
                setTimeout(setPresence, 120000);
            },
            data: data
        });
    };

    /**
     * Parse the chatstatus for a user
     * @param {String} chatStatus The chatstatus which should be
     * online, busy or offline
     */
    var parseChatStatus = function(chatStatus){
        // Check if the status is defined
        if (!chatStatus) {
            chatStatus = "online";
        }
        return chatStatus;
    };

    /**
     * Get the chat status for the current user
     */
    var getChatStatus = function(){
        if (sakai.data.me.profile) {
            currentChatStatus = parseChatStatus(sakai.data.me.profile.chatstatus);
        }
        else {
            currentChatStatus = "online";
        }
        updateChatStatus();
    };

    ///////////////////////
    // Initial functions //
    ///////////////////////

    /**
     * Contains all the functions and methods that need to be
     * executed on the initial load of the page
     */
    var doInit = function(){
        var obj = {};
        var menulinks = [];

        for (var i in sakai.config.Navigation) {
            var temp = new Object();
            temp.url = sakai.config.Navigation[i].url;
            temp.label = sakai.api.i18n.General.getValueForKey(sakai.config.Navigation[i].label);
            temp.cleanurl = temp.url || "";
            if (temp.cleanurl) {
                if (temp.cleanurl.indexOf('?') && temp.cleanurl.indexOf('?') > 0) {
                    temp.cleanurl = temp.cleanurl.substring(0, temp.cleanurl.indexOf('?'));
                }
                if (temp.cleanurl.indexOf('#') && temp.cleanurl.indexOf('#') > 0) {
                    temp.cleanurl = temp.cleanurl.substring(0, temp.cleanurl.indexOf('#'));
                }
            }
            if (i == 0) {
                temp.firstlink = true;
            }
            else {
                temp.firstlink = false;
            }
            menulinks.push(temp);
        }
        obj.links = menulinks;
        // Get navigation and render menu template
        $(".explore").html($.TemplateRenderer("navigation_template", obj));

        var person = sakai.data.me;

        $(exploreNavigationContainer).show();

        // Fill in the name of the user in the different fields
        if (sakai.api.User.getDisplayName(person.profile) !== "") {
            $(userIdLabel).text(sakai.api.User.getDisplayName(person.profile));
            $(hiLabel).text(sakai.api.User.getProfileBasicElementValue(person.profile, "firstName"));
        }

        // Show the profile picture on the dashboard page
        /** TODO : Remove the lines beneath if this functionality is inside changepic.js */
        if (person.profile.picture) {
            var picture = $.parseJSON(person.profile.picture);
            if (picture.name) {
                $(pictureHolder).attr("src", "/~" + sakai.data.me.user.userid + "/public/" + picture.name);
            }
        }

        // Highlight current nav item
        determineCurrentNav();

        // Set presence and bind things
        addBinding();
        getCountUnreadMessages();
        setPresence();

        // Get chat status
        getChatStatus();
    };

    if (sakai.data.me.user.anon) {
        // If a user is not logged in -> switch to anonymous mode
        switchToAnonymousMode();
    }
    else {
        doInit();
    }

};
sakai.api.Widgets.widgetLoader.informOnLoad("topnavigation");<commit_msg>SAKIII-980 Bind event to window so that it close topnaviation dropdown on clicking anywhere apart from navigation menu itself.<commit_after>/*
 * Licensed to the Sakai Foundation (SF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The SF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */
/*global Config, $, jQuery, get_cookie, delete_cookie, set_cookie, window, alert */

var sakai = sakai || {};

/**
 * @name sakai.topnavigation
 *
 * @class topnavigation
 *
 * @description
 * Initialize the topnavigation widget
 *
 * @version 0.0.1
 * @param {String} tuid Unique id of the widget
 * @param {Boolean} showSettings Show the settings of the widget or not
 */
sakai.topnavigation = function(tuid, showSettings){

    /////////////////////////////
    // Configuration variables //
    /////////////////////////////

    var currentChatStatus = "";

    // Links and labels
    var hiLabel = "#hispan";
    var myprofileName = "#myprofile_name";
    var onlineButton = "#online_button";
    var pictureHolder = "#picture_holder";
    var showOnlineLink = "#show_online";
    var userIdLabel = "#userid";

    // User Link
    var userLink = "#user_link";
    var userLinkMenu = userLink + "_menu";
    var userLinkMenuLink = userLink + "_menu" + " a";

    // Navigation
    var nav = "#nav";
    var navContentMediaLink = "#nav_content_media_link";
    var navCoursesSitesLink = "#nav_courses_sites_link";
    var navCoursesSitesLinkClass = "#nav_courses_sites_link";
    var navPeopleLink = "#nav_people_link";
    var navPeopleLinkClass = "nav_people_link";
    var navMySakaiLink = "#nav_my_sakai_link";
    var navCalendarLink = "#nav_calendar_link";
    var navSelectedNavItemClass = "explore_nav_selected";

    // Messages
    var chatUnreadMessages = "#chat_unreadMessages";

    // Search
    var $general_search_form = $("#general_search_container form");
    var $general_search_input = $("#general_search_input");
    var $general_search_default_value = $("#general_search_default_value");
    var generalSearchSubmitButton = "#general_search_submit_button";
    var searchFocus = false;

    // Containers
    var exploreNavigationContainer = "#explore_nav_container";

    // CSS Classes
    var searchInputFocusClass = "search_input_focus";
    var chatAvailableStatusClass = "chat_available_status";
    var chatAvailableStatusClassOnline = chatAvailableStatusClass + "_online";
    var chatAvailableStatusClassBusy = chatAvailableStatusClass + "_busy";
    var chatAvailableStatusClassOffline = chatAvailableStatusClass + "_offline";

    var userLinkChatStatusClass = ".user_link_chat_status";

    ///////////////////////
    // Utility functions //
    ///////////////////////

    /**
     * Get the number of messages that are unread and show it.
     */
    var getCountUnreadMessages = function(){
        //we have the number of unread messages as a part of the me-feed
        //so get it directly from me object.
        $(chatUnreadMessages).text(sakai.data.me.messages.unread);
    };

    /**
     * Update a certain element with a specific chatstatus
     * @param {Object} element Element that needs to be updated
     * @param {String} chatstatus The chatstatus that needs to be added
     */
    var updateChatStatusElement = function(element, chatstatus){
        element.removeClass(chatAvailableStatusClassOnline);
        element.removeClass(chatAvailableStatusClassBusy);
        element.removeClass(chatAvailableStatusClassOffline);
        element.addClass(chatAvailableStatusClass + "_" + chatstatus);
    };

    /**
     * Update the status on the page by firing an event that handles this
     */
    var updateChatStatus = function(){
        // Trigger the chat_status_change event to update other widgets
        $(window).trigger("chat_status_change", currentChatStatus);
    };

    /**
     * Set the chatstatus of the user
     * @param {String} chatstatus The chatstatus which should be
     * online/offline or busy
     */
    var sendChatStatus = function(chatstatus){
        if (currentChatStatus !== chatstatus){
            currentChatStatus = chatstatus;

            var data = {
                "chatstatus": chatstatus,
                "_charset_": "utf-8"
            };

            $.ajax({
                url: "/~" + sakai.data.me.profile["rep:userId"] + "/public/authprofile",
                type: "POST",
                data: data,
                success: function(data){
                    updateChatStatus();
                },
                error: function(xhr, textStatus, thrownError){
                    alert("An error occurend when sending the status to the server.");
                }
            });
        }
    };

    /**
     * Show or hide the user link menu
     * @param {Boolean} hideOnly
     *  true: Hide the menu only
     *  false: Show or hide the menu depending if it's already visible
     */
    var showHideUserLinkMenu = function(hideOnly){
        if ($(userLinkMenu).is(":visible") || hideOnly) {
            $(userLinkMenu).hide();
        }
        else {
            $(userLinkMenu).css("left", Math.round($(userLink).offset().left) + "px");
            $(userLinkMenu).css("top", (Math.round($(userLink).offset().top) + $(userLink).height() + 2) + "px");
            $(userLinkMenu).css("width", ($(userLink).width() + 10) + "px");
            $(userLinkMenu).show();
        }
    };

    /**
     * Add binding to some elements
     */
    var addBinding = function(){
        $(userLink).bind("click", function(){
            showHideUserLinkMenu(false);
        });

        $(userLinkChatStatusClass).bind("click", function(ev){
            showHideUserLinkMenu(false);
            var clicked = ev.currentTarget.id.split("_")[ev.currentTarget.id.split("_").length - 1];
            sendChatStatus(clicked);
        });

        $(document).bind("click", function(e){
            var $clicked = $(e.target);

            // Check if one of the parents is the userLink
            if (!$clicked.parents().is(userLink)) {
                showHideUserLinkMenu(true);
            }
        });

        $(window).bind("chat_status_change", function(event, currentChatStatus){
            updateChatStatusElement($(userLink), currentChatStatus);
        });

        $(window).bind("click", function(e){
            // if menu is visible and the target element clicked is not menu hide dropdown
            if ($(userLinkMenu).is(":visible") && !$(e.target).parents().is(userLink)){
                showHideUserLinkMenu(true);
            }
        });
    };

    ////////////////
    // NAVIGATION //
    ///////////////

    /**
     * Select the page in the top navigation where you are currently on.
     * This will apply a class to the selected navigation item based on the current URL
     * @returns void;
     */
    var determineCurrentNav = function(){
        var windowLocationPath = window.location.pathname.toLowerCase();

        // Remove all selected classes from nav elements
        $(nav + " " + navSelectedNavItemClass).removeClass(navSelectedNavItemClass);

        // My Sakai
        if ((windowLocationPath.indexOf(sakai.config.URL.MY_DASHBOARD_URL) !== -1) || (windowLocationPath.indexOf(sakai.config.URL.PUBLIC_MY_DASHBOARD_URL) !== -1)) {
            $(navMySakaiLink).addClass(navSelectedNavItemClass);
            return;
        }

        // Content & Media
        if ((windowLocationPath.indexOf(sakai.config.URL.CONTENT_MEDIA_URL) !== -1) || (windowLocationPath.indexOf(sakai.config.URL.PUBLIC_CONTENT_MEDIA_URL) !== -1)) {
            $(navContentMediaLink).addClass(navSelectedNavItemClass);
            return;
        }

        // People
        if ((windowLocationPath.indexOf(sakai.config.URL.PEOPLE_URL) !== -1) || (windowLocationPath.indexOf(sakai.config.URL.PUBLIC_PEOPLE_URL) !== -1)) {
            $(navPeopleLink).addClass(navSelectedNavItemClass);
            return;
        }

        // Courses & Sites
        if ((windowLocationPath.indexOf(sakai.config.URL.COURSES_SITES_URL) !== -1) || (windowLocationPath.indexOf(sakai.config.URL.PUBLIC_COURSES_SITES_URL) !== -1) || (windowLocationPath.indexOf("/sites/") !== -1)) {
            $(navCoursesSitesLink).addClass(navSelectedNavItemClass);
            return;
        }

        // Calendar
        if ((windowLocationPath.indexOf(sakai.config.URL.SEARCH_GENERAL_URL) !== -1) || (windowLocationPath.indexOf(sakai.config.URL.SEARCH_PEOPLE_URL) !== -1) || (windowLocationPath.indexOf(sakai.config.URL.SEARCH_SITES_URL) !== -1) || (windowLocationPath.indexOf(sakai.config.URL.SEARCH_CONTENT_URL) !== -1) || (windowLocationPath.indexOf(sakai.config.URL.PUBLIC_SEARCH_URL) !== -1)) {
            $(navCalendarLink).addClass(navSelectedNavItemClass);
            return;
        }

    };

    ////////////
    // SEARCH //
    ////////////

    /**
     * Execute the search for the value that is in the search input field
     */
    var doSearch = function(){
        var tosearch = $general_search_input.val();
        // Disable search button
        $(generalSearchSubmitButton).attr("disabled", true);
        // Check whether the search term is different than the default text. If not,
        // we do a search for *
        if (!tosearch || tosearch === $general_search_default_value.text()){
            tosearch = "*";
        }

        // Only enable button if the location is the search page
        if (window.location.pathname.split("/")[2] === "search.html") {
            $(generalSearchSubmitButton).attr("disabled", false);
            // if user is on the search page use the history event to perform the search
            History.addBEvent("1", encodeURIComponent(tosearch));
        } else {
            // Redirecting back to the general search page. This expects the URL to be
            // in a format like this one: page.html#pageid|searchstring
            document.location = sakai.config.URL.SEARCH_GENERAL_URL + "#q=" + tosearch;
        }
    };

    /**
     * If this is the first time the field gets focus, we'll make his text color black
     * and remove the default value
     */
    $general_search_input.bind("focus", function(ev){
        if (!searchFocus) {
            $general_search_input.val("").addClass(searchInputFocusClass);
            searchFocus = true;
        }
    });

    /**
     * If we leave the field without filling out anything, we'll reinsert the default
     * search inputbox value
     */
    $general_search_input.bind("blur", function(ev){

        if (!$general_search_input.val()) {
            $general_search_input.removeClass(searchInputFocusClass);
            $general_search_input.val($general_search_default_value.text());
            searchFocus = false;
        }
    });

    /**
     * Bind the submit event to the search form
     * This event is triggered when you hit enter in the input field and
     * when you click on the submit button
     */
    $general_search_form.bind("submit", function(){

        doSearch();
        return false;
    });

    /**
     * Switch navigation bar to anonymous mode
     * @returns void
     */
    var switchToAnonymousMode = function(){

        // Show Nav Container
        $(exploreNavigationContainer).show();

        // Hide things which are irrelvant for Anonymous user
        $(".personal .mail").hide();
        $(".personal .sign_out").hide();
        $(".help").hide();
        $("#user_link_container").hide();

        // Show anonymous elements
        $("#other_logins_button_container").show();
        $(".log_in").addClass("help_none");

        // if config.js is set to external, register link is hidden
        if(!sakai.config.Authentication.internal) {
            $("#register_button_container").hide();
        }
        else {
            $("#register_button_container").show();
        }
        $("#login_button_container").show();

        // Set up public nav links
        $("#nav_my_sakai_link a").attr("href", sakai.config.URL.PUBLIC_MY_DASHBOARD_URL);
        $("#nav_content_media_link a").attr("href", sakai.config.URL.PUBLIC_CONTENT_MEDIA_URL_PAGE);
        $("#nav_people_link a").attr("href", sakai.config.URL.PUBLIC_PEOPLE_URL);
        $("#nav_courses_sites_link a").attr("href", sakai.config.URL.PUBLIC_COURSES_SITES_URL);
        $("#nav_search_link a").attr("href", sakai.config.URL.PUBLIC_SEARCH_URL_PAGE);

        // Make the login page redirect to the current page after login
        $(".log_in").attr("href", $(".log_in").attr("href") + "?url=" + escape(window.location.pathname + window.location.search + window.location.hash));

    };

    /**
     * Set the presence for the current user
     * We need to do this in order to let the server know the user is still available for chatting.
     */
    var setPresence = function(){

        var data = {
            "sakai:status": "online",
            "_charset_": "utf-8"
        };

        $.ajax({
            url: sakai.config.URL.PRESENCE_SERVICE,
            type: "POST",
            success: function(){
                setTimeout(setPresence, 120000);
            },
            data: data
        });
    };

    /**
     * Parse the chatstatus for a user
     * @param {String} chatStatus The chatstatus which should be
     * online, busy or offline
     */
    var parseChatStatus = function(chatStatus){
        // Check if the status is defined
        if (!chatStatus) {
            chatStatus = "online";
        }
        return chatStatus;
    };

    /**
     * Get the chat status for the current user
     */
    var getChatStatus = function(){
        if (sakai.data.me.profile) {
            currentChatStatus = parseChatStatus(sakai.data.me.profile.chatstatus);
        }
        else {
            currentChatStatus = "online";
        }
        updateChatStatus();
    };

    ///////////////////////
    // Initial functions //
    ///////////////////////

    /**
     * Contains all the functions and methods that need to be
     * executed on the initial load of the page
     */
    var doInit = function(){
        var obj = {};
        var menulinks = [];

        for (var i in sakai.config.Navigation) {
            var temp = new Object();
            temp.url = sakai.config.Navigation[i].url;
            temp.label = sakai.api.i18n.General.getValueForKey(sakai.config.Navigation[i].label);
            temp.cleanurl = temp.url || "";
            if (temp.cleanurl) {
                if (temp.cleanurl.indexOf('?') && temp.cleanurl.indexOf('?') > 0) {
                    temp.cleanurl = temp.cleanurl.substring(0, temp.cleanurl.indexOf('?'));
                }
                if (temp.cleanurl.indexOf('#') && temp.cleanurl.indexOf('#') > 0) {
                    temp.cleanurl = temp.cleanurl.substring(0, temp.cleanurl.indexOf('#'));
                }
            }
            if (i == 0) {
                temp.firstlink = true;
            }
            else {
                temp.firstlink = false;
            }
            menulinks.push(temp);
        }
        obj.links = menulinks;
        // Get navigation and render menu template
        $(".explore").html($.TemplateRenderer("navigation_template", obj));

        var person = sakai.data.me;

        $(exploreNavigationContainer).show();

        // Fill in the name of the user in the different fields
        if (sakai.api.User.getDisplayName(person.profile) !== "") {
            $(userIdLabel).text(sakai.api.User.getDisplayName(person.profile));
            $(hiLabel).text(sakai.api.User.getProfileBasicElementValue(person.profile, "firstName"));
        }

        // Show the profile picture on the dashboard page
        /** TODO : Remove the lines beneath if this functionality is inside changepic.js */
        if (person.profile.picture) {
            var picture = $.parseJSON(person.profile.picture);
            if (picture.name) {
                $(pictureHolder).attr("src", "/~" + sakai.data.me.user.userid + "/public/" + picture.name);
            }
        }

        // Highlight current nav item
        determineCurrentNav();

        // Set presence and bind things
        addBinding();
        getCountUnreadMessages();
        setPresence();

        // Get chat status
        getChatStatus();
    };

    if (sakai.data.me.user.anon) {
        // If a user is not logged in -> switch to anonymous mode
        switchToAnonymousMode();
    }
    else {
        doInit();
    }

};
sakai.api.Widgets.widgetLoader.informOnLoad("topnavigation");<|endoftext|>


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

/**
 * This file contains options that apply to ALL target build configurations. Because we use
 * the DllPlugin for dynamic loading, each individual bundle has its own config options
 * that can extend these.
 */
var fs = require('fs');
var path = require('path');
var yaml = require('js-yaml');
var webpack = require('webpack');

var ExtractTextPlugin = require('extract-text-webpack-plugin');

var paths = require('./webpack.paths.js');
var es2015Preset = require.resolve('babel-preset-es2015');
var istanbulPlugin = require.resolve('babel-plugin-istanbul');

function fileLoader() {
    return {
        loader: 'file-loader',
        query: {
            name: 'assets/[name]-[hash:8].[ext]'
        }
    };
}

function urlLoader(options) {
    options = options || {};
    var loader = {
        loader: 'url-loader',
        query: {
            limit: 4096
        }
    };
    if (options.mimetype) {
        loader.query.mimetype = options.mimetype;
    }
    return loader;
}

function defaultLoaderPlugins() {
    // Computes a list of plugin paths that are opting to use Girder's loader
    // configuration directly; these paths will be added to the "include"
    // directive for the loaders in the config template below.
    var dirs = fs.readdirSync('plugins');
    var paths = [];

    dirs.forEach(function (dir) {
        // Find a plugin config file.
        var pluginFile = path.resolve('plugins', dir, 'plugin.yml');
        if (!fs.existsSync(pluginFile)) {
            pluginFile = path.resolve('plugins', dir, 'plugin.json');
            if (!fs.existsSync(pluginFile)) {
                pluginFile = null;
            }
        }

        // If there's a plugin file, and it has no config, no webpack section,
        // no defaultLoaders property, or the defaultLoaders property is
        // explicitly set to anything besdies false, then add the plugin to the
        // list of plugins that want to use Girder's loader configuration.
        if (pluginFile) {
            var config = yaml.safeLoad(fs.readFileSync(pluginFile));
            if (!config || !config.webpack || config.webpack.defaultLoaders === undefined || config.webpack.defaultLoaders !== false) {
                paths.push(path.resolve('plugins', dir));
            }
        }
    });

    return paths;
}

var loaderPaths = defaultLoaderPlugins().concat([/clients\/web\/src/]);

module.exports = {
    output: {
        path: paths.web_built,
        filename: '[name].min.js'
    },
    plugins: [
        // Automatically detect jQuery and $ as free var in modules
        // and inject the jquery library. This is required by many jquery plugins
        new webpack.ProvidePlugin({
            jQuery: 'jquery',
            $: 'jquery',
            'window.jQuery': 'jquery'
        }),
        new ExtractTextPlugin({
            filename: '[name].min.css',
            allChunks: true,
            disable: false
        })
    ],
    module: {
        loaders: [
            // ES2015
            {
                test: /\.js$/,
                include: loaderPaths,
                loader: 'babel-loader',
                exclude: /node_modules/,
                query: {
                    presets: [es2015Preset],
                    env: {
                        cover: {
                            plugins: [[
                                istanbulPlugin, {
                                    exclude: ['**/*.pug', '**/*.jade', 'node_modules/**/*']
                                }
                            ]]
                        }
                    }
                }
            },
            // JSON files
            {
                test: /\.json$/,
                include: loaderPaths,
                loader: 'json-loader'
            },
            // Stylus
            {
                test: /\.styl$/,
                include: loaderPaths,
                loaders: [
                    ExtractTextPlugin.extract('style-loader'),
                    'css-loader',
                    {
                        loader: 'stylus-loader',
                        query: {
                            'resolve url': true
                        }
                    }
                ]
            },
            // CSS
            {
                test: /\.css$/,
                include: loaderPaths.concat([
                    /node_modules/
                ]),
                loaders: [
                    ExtractTextPlugin.extract('style-loader'),
                    'css-loader'
                ]
            },
            // Pug
            {
                test: /\.(pug|jade)$/,
                include: loaderPaths,
                loaders: [
                    {
                        loader: 'babel-loader',
                        query: {
                            presets: [es2015Preset]
                        }
                    },
                    'pug-loader'
                ]
            },
            // PNG, JPEG
            {
                test: /\.(png|jpg)$/,
                include: loaderPaths.concat([
                    /node_modules/
                ]),
                loaders: [
                    fileLoader()
                ]
            },
            // WOFF
            {
                test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
                include: loaderPaths.concat([
                    /node_modules/
                ]),
                loaders: [
                    urlLoader({ mimetype: 'application/font-woff' }),
                    fileLoader()
                ]
            },
            // WOFF2
            {
                test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
                include: loaderPaths.concat([
                    /node_modules/
                ]),
                loaders: [
                    urlLoader({ mimetype: 'application/font-woff2' }),
                    fileLoader()
                ]
            },
            // TTF
            {
                test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
                include: loaderPaths.concat([
                    /node_modules/
                ]),
                loaders: [
                    urlLoader({ mimetype: 'application/octet-stream' }),
                    fileLoader()
                ]
            },
            // EOT
            {
                test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
                include: loaderPaths.concat([
                    /node_modules/
                ]),
                loaders: [
                    fileLoader()
                ]
            },
            // SVG
            {
                test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
                include: loaderPaths.concat([
                    /node_modules/
                ]),
                loaders: [
                    urlLoader({ mimetype: 'image/svg+xml' }),
                    fileLoader()
                ]
            }
        ],
        noParse: [
            // Avoid warning:
            //   This seems to be a pre-built javascript file. Though this is
            //   possible, it's not recommended. Try to require the original source
            //   to get better results.
            // This needs fixing later, as Webpack works better when provided with source.
            // /node_modules\/pug/,
            // /node_modules\/remarkable/
        ]
    },
    resolve: {
        alias: {
            'girder': paths.web_src
        },
        extensions: ['.styl', '.css', '.pug', '.jade', '.js', ''],
        modules: [
            paths.clients_web,
            paths.plugins,
            paths.node_modules
        ]
    },
    node: {
        canvas: 'empty',
        file: 'empty',
        fs: 'empty',
        jsdom: 'empty',
        system: 'empty',
        xmldom: 'empty'
    }
};
<commit_msg>Use a variable for "loader paths plus node_modules"<commit_after>/**
 * Copyright 2015 Kitware Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * This file contains options that apply to ALL target build configurations. Because we use
 * the DllPlugin for dynamic loading, each individual bundle has its own config options
 * that can extend these.
 */
var fs = require('fs');
var path = require('path');
var yaml = require('js-yaml');
var webpack = require('webpack');

var ExtractTextPlugin = require('extract-text-webpack-plugin');

var paths = require('./webpack.paths.js');
var es2015Preset = require.resolve('babel-preset-es2015');
var istanbulPlugin = require.resolve('babel-plugin-istanbul');

function fileLoader() {
    return {
        loader: 'file-loader',
        query: {
            name: 'assets/[name]-[hash:8].[ext]'
        }
    };
}

function urlLoader(options) {
    options = options || {};
    var loader = {
        loader: 'url-loader',
        query: {
            limit: 4096
        }
    };
    if (options.mimetype) {
        loader.query.mimetype = options.mimetype;
    }
    return loader;
}

function defaultLoaderPlugins() {
    // Computes a list of plugin paths that are opting to use Girder's loader
    // configuration directly; these paths will be added to the "include"
    // directive for the loaders in the config template below.
    var dirs = fs.readdirSync('plugins');
    var paths = [];

    dirs.forEach(function (dir) {
        // Find a plugin config file.
        var pluginFile = path.resolve('plugins', dir, 'plugin.yml');
        if (!fs.existsSync(pluginFile)) {
            pluginFile = path.resolve('plugins', dir, 'plugin.json');
            if (!fs.existsSync(pluginFile)) {
                pluginFile = null;
            }
        }

        // If there's a plugin file, and it has no config, no webpack section,
        // no defaultLoaders property, or the defaultLoaders property is
        // explicitly set to anything besdies false, then add the plugin to the
        // list of plugins that want to use Girder's loader configuration.
        if (pluginFile) {
            var config = yaml.safeLoad(fs.readFileSync(pluginFile));
            if (!config || !config.webpack || config.webpack.defaultLoaders === undefined || config.webpack.defaultLoaders !== false) {
                paths.push(path.resolve('plugins', dir));
            }
        }
    });

    return paths;
}

var loaderPaths = defaultLoaderPlugins().concat([/clients\/web\/src/]);
var loaderPathsNodeModules = loaderPaths.concat([/node_modules/]);

module.exports = {
    output: {
        path: paths.web_built,
        filename: '[name].min.js'
    },
    plugins: [
        // Automatically detect jQuery and $ as free var in modules
        // and inject the jquery library. This is required by many jquery plugins
        new webpack.ProvidePlugin({
            jQuery: 'jquery',
            $: 'jquery',
            'window.jQuery': 'jquery'
        }),
        new ExtractTextPlugin({
            filename: '[name].min.css',
            allChunks: true,
            disable: false
        })
    ],
    module: {
        loaders: [
            // ES2015
            {
                test: /\.js$/,
                include: loaderPaths,
                loader: 'babel-loader',
                exclude: /node_modules/,
                query: {
                    presets: [es2015Preset],
                    env: {
                        cover: {
                            plugins: [[
                                istanbulPlugin, {
                                    exclude: ['**/*.pug', '**/*.jade', 'node_modules/**/*']
                                }
                            ]]
                        }
                    }
                }
            },
            // JSON files
            {
                test: /\.json$/,
                include: loaderPaths,
                loader: 'json-loader'
            },
            // Stylus
            {
                test: /\.styl$/,
                include: loaderPaths,
                loaders: [
                    ExtractTextPlugin.extract('style-loader'),
                    'css-loader',
                    {
                        loader: 'stylus-loader',
                        query: {
                            'resolve url': true
                        }
                    }
                ]
            },
            // CSS
            {
                test: /\.css$/,
                include: loaderPathsNodeModules,
                loaders: [
                    ExtractTextPlugin.extract('style-loader'),
                    'css-loader'
                ]
            },
            // Pug
            {
                test: /\.(pug|jade)$/,
                include: loaderPaths,
                loaders: [
                    {
                        loader: 'babel-loader',
                        query: {
                            presets: [es2015Preset]
                        }
                    },
                    'pug-loader'
                ]
            },
            // PNG, JPEG
            {
                test: /\.(png|jpg)$/,
                include: loaderPathsNodeModules,
                loaders: [
                    fileLoader()
                ]
            },
            // WOFF
            {
                test: /\.woff(\?v=\d+\.\d+\.\d+)?$/,
                include: loaderPathsNodeModules,
                loaders: [
                    urlLoader({ mimetype: 'application/font-woff' }),
                    fileLoader()
                ]
            },
            // WOFF2
            {
                test: /\.woff2(\?v=\d+\.\d+\.\d+)?$/,
                include: loaderPathsNodeModules,
                loaders: [
                    urlLoader({ mimetype: 'application/font-woff2' }),
                    fileLoader()
                ]
            },
            // TTF
            {
                test: /\.ttf(\?v=\d+\.\d+\.\d+)?$/,
                include: loaderPathsNodeModules,
                loaders: [
                    urlLoader({ mimetype: 'application/octet-stream' }),
                    fileLoader()
                ]
            },
            // EOT
            {
                test: /\.eot(\?v=\d+\.\d+\.\d+)?$/,
                include: loaderPathsNodeModules,
                loaders: [
                    fileLoader()
                ]
            },
            // SVG
            {
                test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
                include: loaderPathsNodeModules,
                loaders: [
                    urlLoader({ mimetype: 'image/svg+xml' }),
                    fileLoader()
                ]
            }
        ],
        noParse: [
            // Avoid warning:
            //   This seems to be a pre-built javascript file. Though this is
            //   possible, it's not recommended. Try to require the original source
            //   to get better results.
            // This needs fixing later, as Webpack works better when provided with source.
            // /node_modules\/pug/,
            // /node_modules\/remarkable/
        ]
    },
    resolve: {
        alias: {
            'girder': paths.web_src
        },
        extensions: ['.styl', '.css', '.pug', '.jade', '.js', ''],
        modules: [
            paths.clients_web,
            paths.plugins,
            paths.node_modules
        ]
    },
    node: {
        canvas: 'empty',
        file: 'empty',
        fs: 'empty',
        jsdom: 'empty',
        system: 'empty',
        xmldom: 'empty'
    }
};
<|endoftext|>


<commit_before>'use strict';

/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

/**
 * Returns a list for webpack.resolve
 *
 * @param {Array<string>} modules - list of modules
 * @returns {Array<string>}
 */
module.exports = function ({modules}) {
	return {modules};
};
<commit_msg>Added extensions<commit_after>'use strict';

/*!
 * V4Fire Client Core
 * https://github.com/V4Fire/Client
 *
 * Released under the MIT license
 * https://github.com/V4Fire/Client/blob/master/LICENSE
 */

/**
 * Returns a list for webpack.resolve
 *
 * @param {Array<string>} modules - list of modules
 * @returns {Array<string>}
 */
module.exports = function ({modules}) {
	return {
		extensions: ['.ts', '.js', '.json'],
		modules
	};
};
<|endoftext|>


<commit_before>// ==UserScript==
// @name         BBVA Twiks
// @namespace    http://federicojm.com/
// @version      0.4
// @description  Multiple twiks for BBVAnet Colombia.
// @author       Federico JM
// @match        https://www.e-bbva.com.co/*
// @match        https://www.bbvanet.com.co/bbvavip/colombiavip/OperacionCBTFServlet*
// @grant        none
// @require      https://cdnjs.cloudflare.com/ajax/libs/numeral.js/1.5.3/numeral.min.js
// @run-at       document-end
// ==/UserScript==

/* - jshint settings - */
/* globals numeral */

(function ($) {
    'use strict';

    // jQuery is available on BBVAnet on main frame only. This filters other frames.
    if (typeof $ === "undefined") {
        return false;
    }

    // Spanish for Numeral.
    var language = {
        delimiters: {
            thousands: '.',
            decimal: ','
        },
        abbreviations: {
            thousand: 'k',
            million: 'mm',
            billion: 'b',
            trillion: 't'
        },
        ordinal: function (number) {
            var b = number % 10;
            return b === 1 || b === 3 ? 'er' :
                b === 2 ? 'do' :
                b === 7 || b === 0 ? 'mo' :
                b === 8 ? 'vo' :
                b === 9 ? 'no' : 'to';
        },
        currency: {
            symbol: '$'
        }
    };
    numeral.language('es', language);

    // Set langauge for Numeral library.
    numeral.language('es');
    numeral.defaultFormat('0,0.00');

    $('.pesetas:not(:has(*)), .pesetas-i:not(:has(*)), .pesetas1:not(:has(*)), .dato:not(:has(*))').each(function () {
        var $this = $(this);

        if ($this.html().match(/[0-9]{1,3},[0-9]{3}(\.[0-9]{2})?$/) !== null) {
            numeral.language('en');
            var valor = numeral($this.html());
            numeral.language('es');
            $this.html(valor.format());
        }
    });

    // Set langauge for Numeral library.
    numeral.language('es');

    // Only on the main page.
    var paths = [
        "?proceso=posicion_global_pr&operacion=posicion_global_op&accion=menuPosicion",
        "?proceso=operaciones_generales_pr&operacion=inicio_op&accion=inicio",
    ];
    if (paths.indexOf($(location).attr('search')) >= 0) {
        // Move main table to the beginning of the page.
        var $main = $('body>div:eq(-1)');
        $main.children('table:eq(-1)').detach().prependTo($main);

        // Add current balance to Credit Cards.
        $('p.titulotabla:contains("Tarjetas de Crédito")').closest('table').find('tr:gt(1):lt(-2)').each(function () {
            var $tr = $(this);
            var $total = $tr.find('td:eq(2) .pesetas');
            var $disponible = $tr.find('td:last .pesetas');

            numeral.language('es');
            var saldo = numeral($total.html()).subtract(numeral($disponible.html()));

            var span = '';
            $disponible.append(span + saldo.format('0,0.00') + '');
        });
    }

})(window.jQuery);
<commit_msg>Bump version for BBVAnet<commit_after>// ==UserScript==
// @name         BBVA Twiks
// @namespace    http://federicojm.com/
// @version      0.5
// @description  Multiple twiks for BBVAnet Colombia.
// @author       Federico JM
// @match        https://www.e-bbva.com.co/*
// @match        https://www.bbvanet.com.co/bbvavip/colombiavip/OperacionCBTFServlet*
// @grant        none
// @require      https://cdnjs.cloudflare.com/ajax/libs/numeral.js/1.5.3/numeral.min.js
// @run-at       document-end
// ==/UserScript==

/* - jshint settings - */
/* globals numeral */

(function ($) {
    'use strict';

    // jQuery is available on BBVAnet on main frame only. This filters other frames.
    if (typeof $ === "undefined") {
        return false;
    }

    // Spanish for Numeral.
    var language = {
        delimiters: {
            thousands: '.',
            decimal: ','
        },
        abbreviations: {
            thousand: 'k',
            million: 'mm',
            billion: 'b',
            trillion: 't'
        },
        ordinal: function (number) {
            var b = number % 10;
            return b === 1 || b === 3 ? 'er' :
                b === 2 ? 'do' :
                b === 7 || b === 0 ? 'mo' :
                b === 8 ? 'vo' :
                b === 9 ? 'no' : 'to';
        },
        currency: {
            symbol: '$'
        }
    };
    numeral.language('es', language);

    // Set langauge for Numeral library.
    numeral.language('es');
    numeral.defaultFormat('0,0.00');

    $('.pesetas:not(:has(*)), .pesetas-i:not(:has(*)), .pesetas1:not(:has(*)), .dato:not(:has(*))').each(function () {
        var $this = $(this);

        if ($this.html().match(/[0-9]{1,3},[0-9]{3}(\.[0-9]{2})?$/) !== null) {
            numeral.language('en');
            var valor = numeral($this.html());
            numeral.language('es');
            $this.html(valor.format());
        }
    });

    // Set langauge for Numeral library.
    numeral.language('es');

    // Only on the main page.
    var paths = [
        "?proceso=posicion_global_pr&operacion=posicion_global_op&accion=menuPosicion",
        "?proceso=operaciones_generales_pr&operacion=inicio_op&accion=inicio",
    ];
    if (paths.indexOf($(location).attr('search')) >= 0) {
        // Move main table to the beginning of the page.
        var $main = $('body>div:eq(-1)');
        $main.children('table:eq(-1)').detach().prependTo($main);

        // Add current balance to Credit Cards.
        $('p.titulotabla:contains("Tarjetas de Crédito")').closest('table').find('tr:gt(1):lt(-2)').each(function () {
            var $tr = $(this);
            var $total = $tr.find('td:eq(2) .pesetas');
            var $disponible = $tr.find('td:last .pesetas');

            numeral.language('es');
            var saldo = numeral($total.html()).subtract(numeral($disponible.html()));

            var span = '';
            $disponible.append(span + saldo.format('0,0.00') + '');
        });
    }

})(window.jQuery);
<|endoftext|>


<commit_before><commit_msg>fixed issue with bad carriage return<commit_after><|endoftext|>


<commit_before>angular.module('app.services').factory('leaderContentHelper', function($http, serverConfig){
  var service = {}

  // usage in console:
  // var h = angular.element(document.body).injector().get('leaderContentHelper')
  // h.createAndPublishPollPetition('title', 'bodytext', 'a1', 'a2')

  service.createAndPublishPollPetition = function(subject, title, answer1, answer2){
    service.createPollPetition(subject, title).then(function(response){
      var pollID = response.data.id
      service.addPollAnswer(pollID, answer1).then(function(){
        service.addPollAnswer(pollID, answer2).then(function(){
          service.publishPoll(pollID).then(function(){
            console.log('poll:petition published, ID: '+pollID)
          })
        })
      })
    })
  }

  service.createAndPublishPollEvent = function(subject, title, answer1, answer2){
    service.createPollEvent(subject, title).then(function(response){
      var pollID = response.data.id
      service.addPollAnswer(pollID, answer1).then(function(){
        service.addPollAnswer(pollID, answer2).then(function(){
          service.publishPoll(pollID).then(function(){
            console.log('poll:event published, ID: '+pollID)
          })
        })
      })
    })
  }

  service.createPollEvent = function(subject, title){
    var data = {subject: subject,
      title: title,
      started_at: "2016-09-07 09:52:33", // t.strftime("%Y-%m-%d'%z'%H:%M:%S")
      finished_at: "2016-09-20 09:52:33",
      //petition_title: 'Petition title',
      //petition_body: 'Petition body',
      type: 'event'}

    var payload = JSON.stringify(data)
    var headers = {headers: {'Content-Type': 'application/json'}}

    var groupID = 285

    return $http.post(serverConfig.url + '/api/v2/groups/'+groupID+'/polls', payload, headers)
  }

  service.createPollPetition = function(title, body){
    var data = {subject: 'I have no idea what is the difference between subject and petition body',
      petition_title: title,
      petition_body: body,
      type: 'petition'}

    var payload = JSON.stringify(data)
    var headers = {headers: {'Content-Type': 'application/json'}}

    var groupID = 285

    return $http.post(serverConfig.url + '/api/v2/groups/'+groupID+'/polls', payload, headers)
  }

  // created poll with ID = 194 in group 285 as user Peter10

  service.addPollAnswer = function(pollID, value){
    var data = {value : value}
    var payload = JSON.stringify(data)
    var headers = {headers: {'Content-Type': 'application/json'}}

    return $http.post(serverConfig.url + '/api/v2/polls/'+pollID+'/options', payload, headers)
  }
  // addPollAnswer('answer YES') -> ID: 305
  // addPollAnswer('answer NO') -> ID: 306

  service.publishPoll = function(pollID){
    // var data = {options: [
    //   {id: 1, value: 'optionA', payment_amount: 10, is_user_amount: true},
    //   {id: 2, value: 'optionB', payment_amount: 10, is_user_amount: true}]}
    var data = {}

    var payload = JSON.stringify(data)
    var headers = {headers: {'Content-Type': 'application/json'}}
    return $http.patch(serverConfig.url + '/api/v2/polls/'+pollID, payload, headers)
  }

  return service
})<commit_msg>update leader-content-helpers.js<commit_after>angular.module('app.services').factory('leaderContentHelper', function($http, serverConfig){
  var service = {}

  // usage in console:
  // var h = angular.element(document.body).injector().get('leaderContentHelper')
  // h.createAndPublishPollPetition('title', 'bodytext', 'a1', 'a2', 285)

  service.createAndPublishPollPetition = function(subject, title, answer1, answer2, groupID){
    service.createPollPetition(subject, title, groupID).then(function(response){
      var pollID = response.data.id
      service.addPollAnswer(pollID, answer1).then(function(){
        service.addPollAnswer(pollID, answer2).then(function(){
          service.publishPoll(pollID).then(function(){
            console.log('poll:petition published, ID: '+pollID)
          })
        })
      })
    })
  }

  service.createAndPublishPollEvent = function(subject, title, answer1, answer2, started_at, finished_at, groupID){
    service.createPollEvent(subject, title, started_at, finished_at, groupID).then(function(response){
      var pollID = response.data.id
      service.addPollAnswer(pollID, answer1).then(function(){
        service.addPollAnswer(pollID, answer2).then(function(){
          service.publishPoll(pollID).then(function(){
            console.log('poll:event published, ID: '+pollID)
          })
        })
      })
    })
  }

  service.createPollEvent = function(subject, title, started_at, finished_at, groupID){
    var data = {subject: subject,
      title: title,
      started_at: started_at, //"2016-09-07 09:52:33", // t.strftime("%Y-%m-%d'%z'%H:%M:%S")
      finished_at: finished_at, //"2016-09-20 09:52:33",
      //petition_title: 'Petition title',
      //petition_body: 'Petition body',
      type: 'event'}

    var payload = JSON.stringify(data)
    var headers = {headers: {'Content-Type': 'application/json'}}

    //var groupID = 285

    return $http.post(serverConfig.url + '/api/v2/groups/'+groupID+'/polls', payload, headers)
  }

  service.createPollPetition = function(title, body, groupID){
    var data = {subject: 'I have no idea what is the difference between subject and petition body',
      petition_title: title,
      petition_body: body,
      type: 'petition'}

    var payload = JSON.stringify(data)
    var headers = {headers: {'Content-Type': 'application/json'}}

    return $http.post(serverConfig.url + '/api/v2/groups/'+groupID+'/polls', payload, headers)
  }

  // created poll with ID = 194 in group 285 as user Peter10

  service.addPollAnswer = function(pollID, value){
    var data = {value : value}
    var payload = JSON.stringify(data)
    var headers = {headers: {'Content-Type': 'application/json'}}

    return $http.post(serverConfig.url + '/api/v2/polls/'+pollID+'/options', payload, headers)
  }
  // addPollAnswer('answer YES') -> ID: 305
  // addPollAnswer('answer NO') -> ID: 306

  service.publishPoll = function(pollID){
    // var data = {options: [
    //   {id: 1, value: 'optionA', payment_amount: 10, is_user_amount: true},
    //   {id: 2, value: 'optionB', payment_amount: 10, is_user_amount: true}]}
    var data = {}

    var payload = JSON.stringify(data)
    var headers = {headers: {'Content-Type': 'application/json'}}
    return $http.patch(serverConfig.url + '/api/v2/polls/'+pollID, payload, headers)
  }

  return service
})<|endoftext|>


<commit_before>/**
 * Instantialize module Requisition
 * @param {string} Module name
 */
angular.module('AppMain')
  /**
   * The service to centralize and simplify the API calls.
   */
.factory('api', function($http, host, $rootScope, $location, storage) {
  var apiAddress = location.href.substr(0, location.href.indexOf('/', location.origin.length)) + '/';

  return {
    /**
     * Make the post call to api
     * @param  {string} route   Insert url, after domain, to submit data via REST and call to specific controller
     * @param  {object} data    All datas to submit.
     * @param  {string} token   Is the api key for firebase validation.
     * @return {promise}        return the promise method to wait for api response
     */
    post: function(route, data, token) {
      // Check if the data is set
      if (typeof data !== 'object') {
        data = {};
      }
      return $http.post(apiAddress + route, data, {
        headers: {
          auth: token,
          env: 'admin'
        }
      });
    },

    /**
     * Make the get call to api
     * @param  {string} route  Insert url, after domain, to submit data via REST and call to specific controller
     * @param  {object} data    All datas to submit.
     * @param  {string} token   Is the api key for firebase validation.
     * @return {promise}      The promisse to applicant work with specifc cases
     */
    get: function(route, data, token) {
      // Check if the data is set
      if (typeof data !== 'object') {
        data = {};
      }
      return $http.get(apiAddress + route, {
        headers: {
          auth: token,
          env: 'admin'
        },
        params: data
      });
    },

    /**
    * Make the get call to api
    * @param  {string} route  Insert url, after domain, to submit data via REST and call to specific controller
    * @param  {object} data    All datas to submit.
    * @param  {string} token   Is the api key for firebase validation.
    * @return {promise}      The promisse to applicant work with specifc cases
    */
    put: function(route, data, token) {
      // Check if the data is set
      if (typeof data !== 'object') {
        data = {};
      }
      return $http.put(apiAddress + route, data, {
        headers: {
          auth: token,
          env: 'admin'
        }
      });
    },

    /**
    * Make the get call to api
    * @param  {string} route  Insert url, after domain, to submit data via REST and call to specific controller
    * @param  {object} data    All datas to submit.
    * @param  {string} token   Is the api key for firebase validation.
    * @return {promise}      The promisse to applicant work with specifc cases
    */
    delete: function(route, data, token) {
      // Check if the data is set
      if (typeof data !== 'object') {
        data = {};
      }
      return $http.put(apiAddress + route, data, {
        headers: {
          auth: token,
          env: 'admin'
        }
      });
    },

    /**
     * Simplify the decision to use functions post or get to api
     * @param  {string} route    Insert url, after domain, to submit data via REST and call to specific controller
     * @param  {string} method    With value 'post' to use post method or empty/undefined or 'get' to use get method
     * @param  {object} data      All datas to submit.
     * @return {function}        Return the function specific to method selected
     */
    call: function(route, method, data) {
      var token = '';
      var tmp;
      switch (method) {
        case 'post':
          tmp = this.post;
          break;
        case 'get':
          tmp = this.get;
          break;
        case 'put':
          tmp = this.put;
          break;
        case 'delete':
          tmp = this.delete;
          break;
        default:
          console.error("Unrecognized method %s", method);
      }

      return tmp(route, data, token);
    }
  };
});
<commit_msg>Fix in requisition module<commit_after>/**
 * Instantialize module Requisition
 * @param {string} Module name
 */
angular.module('AppMain')
  /**
   * The service to centralize and simplify the API calls.
   */
.factory('api', function($http, $rootScope, $location) {
  var apiAddress = location.href.substr(0, location.href.indexOf('/', location.origin.length)) + '/';

  return {
    /**
     * Make the post call to api
     * @param  {string} route   Insert url, after domain, to submit data via REST and call to specific controller
     * @param  {object} data    All datas to submit.
     * @param  {string} token   Is the api key for firebase validation.
     * @return {promise}        return the promise method to wait for api response
     */
    post: function(route, data, token) {
      // Check if the data is set
      if (typeof data !== 'object') {
        data = {};
      }
      return $http.post(apiAddress + route, data, {
        headers: {
          auth: token,
          env: 'admin'
        }
      });
    },

    /**
     * Make the get call to api
     * @param  {string} route  Insert url, after domain, to submit data via REST and call to specific controller
     * @param  {object} data    All datas to submit.
     * @param  {string} token   Is the api key for firebase validation.
     * @return {promise}      The promisse to applicant work with specifc cases
     */
    get: function(route, data, token) {
      // Check if the data is set
      if (typeof data !== 'object') {
        data = {};
      }
      return $http.get(apiAddress + route, {
        headers: {
          auth: token,
          env: 'admin'
        },
        params: data
      });
    },

    /**
    * Make the get call to api
    * @param  {string} route  Insert url, after domain, to submit data via REST and call to specific controller
    * @param  {object} data    All datas to submit.
    * @param  {string} token   Is the api key for firebase validation.
    * @return {promise}      The promisse to applicant work with specifc cases
    */
    put: function(route, data, token) {
      // Check if the data is set
      if (typeof data !== 'object') {
        data = {};
      }
      return $http.put(apiAddress + route, data, {
        headers: {
          auth: token,
          env: 'admin'
        }
      });
    },

    /**
    * Make the get call to api
    * @param  {string} route  Insert url, after domain, to submit data via REST and call to specific controller
    * @param  {object} data    All datas to submit.
    * @param  {string} token   Is the api key for firebase validation.
    * @return {promise}      The promisse to applicant work with specifc cases
    */
    delete: function(route, data, token) {
      // Check if the data is set
      if (typeof data !== 'object') {
        data = {};
      }
      return $http.put(apiAddress + route, data, {
        headers: {
          auth: token,
          env: 'admin'
        }
      });
    },

    /**
     * Simplify the decision to use functions post or get to api
     * @param  {string} route    Insert url, after domain, to submit data via REST and call to specific controller
     * @param  {string} method    With value 'post' to use post method or empty/undefined or 'get' to use get method
     * @param  {object} data      All datas to submit.
     * @return {function}        Return the function specific to method selected
     */
    call: function(route, method, data) {
      var token = '';
      var tmp;
      switch (method) {
        case 'post':
          tmp = this.post;
          break;
        case 'get':
          tmp = this.get;
          break;
        case 'put':
          tmp = this.put;
          break;
        case 'delete':
          tmp = this.delete;
          break;
        default:
          console.error("Unrecognized method %s", method);
      }

      return tmp(route, data, token);
    }
  };
});
<|endoftext|>


<commit_before>function httpGet(theUrl)
{
    var xmlHttp = null;

    xmlHttp = new XMLHttpRequest();
    xmlHttp.open( "GET", theUrl, false );
    xmlHttp.send( null );
    return xmlHttp.responseText;
}

function checkform(){
	var str = window.location.pathname;
	var isbaha = httpGet(window.location.origin + str.replace("/use.php", "") + "/API/isbaha.php?name=" + document.getElementById("Name").value);
	if(isbaha == "1\n"){
      	return true;
	}else{
		flash('#Name',8,10,100);
		return false;
	}
}

function isEmail() {
	if (document.getElementById("email").value.search(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z]+$/)!= -1){
		return true;
	}else{
		flash('#email',8,10,100);
		return false;
	}
}

function sub(){
document.getElementById('verify').value="傳送中...";
document.getElementById('verify').disabled="disabled";
var name = document.getElementById('Name').value;
$.ajax({
  type: 'POST',
  url: "sendverify.php",
  data: { Name: name },
  success: function(data) {
                      $("#msg").html(data);
                  },
  async:false
});
$(".f1").stop(true,false).animate({left:'-=500px',opacity: 0});
$(".f2").stop(true,false).animate({right:'0px',opacity: 1});
return 1;
}

function sub2(){
document.getElementById('verify').value="傳送中...";
document.getElementById('verify').disabled="disabled";
var name = document.getElementById('name').value;
var hash = document.getElementById('hash').value;
var email = document.getElementById('email').value;
$.ajax({
  type: 'POST',
  url: "sendmailverify.php",
  data: { name: name , hash: hash , email: email},
  success: function(data) {
                      $("#msg").html(data);
                  },
  async:false
});
$(".f1").stop(true,false).animate({left:'-=500px',opacity: 0});
$(".f2").stop(true,false).animate({right:'0px',opacity: 1});
return 1;
}

<commit_msg>Fix \n bug<commit_after>function httpGet(theUrl)
{
    var xmlHttp = null;

    xmlHttp = new XMLHttpRequest();
    xmlHttp.open( "GET", theUrl, false );
    xmlHttp.send( null );
    return xmlHttp.responseText;
}

function checkform(){
	var str = window.location.pathname;
	var isbaha = httpGet(window.location.origin + str.replace("/use.php", "") + "/API/isbaha.php?name=" + document.getElementById("Name").value);
	if(isbaha == "1"){
      	return true;
	}else{
		flash('#Name',8,10,100);
		return false;
	}
}

function isEmail() {
	if (document.getElementById("email").value.search(/^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z]+$/)!= -1){
		return true;
	}else{
		flash('#email',8,10,100);
		return false;
	}
}

function sub(){
document.getElementById('verify').value="傳送中...";
document.getElementById('verify').disabled="disabled";
var name = document.getElementById('Name').value;
$.ajax({
  type: 'POST',
  url: "sendverify.php",
  data: { Name: name },
  success: function(data) {
                      $("#msg").html(data);
                  },
  async:false
});
$(".f1").stop(true,false).animate({left:'-=500px',opacity: 0});
$(".f2").stop(true,false).animate({right:'0px',opacity: 1});
return 1;
}

function sub2(){
document.getElementById('verify').value="傳送中...";
document.getElementById('verify').disabled="disabled";
var name = document.getElementById('name').value;
var hash = document.getElementById('hash').value;
var email = document.getElementById('email').value;
$.ajax({
  type: 'POST',
  url: "sendmailverify.php",
  data: { name: name , hash: hash , email: email},
  success: function(data) {
                      $("#msg").html(data);
                  },
  async:false
});
$(".f1").stop(true,false).animate({left:'-=500px',opacity: 0});
$(".f2").stop(true,false).animate({right:'0px',opacity: 1});
return 1;
}

<|endoftext|>