<commit_before>'use strict';

// NODE_ENV=development node spotify-loader.js

// Load up my private env
require('./config/env/heroku')();

var config = require('./config/config'),
  mongoose = require('mongoose'),
  path = require('path'),
  chalk = require('chalk'),
  moment = require('moment'),
  SpotifyWebApi = require('spotify-web-api-node'),
  accounts = require('./spotify-playlist.json');

/**
 * Database, models, and helpers
 */

mongoose.connect(config.db, function(err) {
  if (err) {
    console.error(chalk.red('Could not connect to MongoDB!'));
    console.log(chalk.red(err));
  }
});

require(path.resolve('./app/models/playlist.server.model.js'));
var Playlist = mongoose.model('Playlist');

var getPublishedDate = function(title) {
  var onlyDigits = title.replace(/([A-Z])\w+/g, '');
  var m = moment(onlyDigits);

  if (m.isValid()) {
    return m.format('MM.DD.YYYY');
  } else {
    return null;
  }
};

var create = function(title, tracks, done) {
  var playlist = new Playlist(tracks);

  playlist.title = title
  playlist.tracks = tracks;
  playlist.published_date = getPublishedDate(title);

  var upsertData = playlist.toObject();

  delete upsertData._id;

  Playlist.update({
      title: playlist.title
    }, upsertData, {
      upsert: true
    },
    function(err) {
      if (err) {
        done(err);
      } else {
        done(playlist);
      }
    });
};

/**
 * Spotify Api
 */

var spotifyApi = new SpotifyWebApi({
  clientId: config.spotify.clientID,
  clientSecret: config.spotify.clientSecret,
  redirectUri: config.spotify.callbackURL
});

var savePlaylist = function(data) {

  var tracks = [];
  data.tracks.items.forEach(function(item) {
    tracks.push({
      id: item.track.id,
      name: item.track.name,
      artist: item.track.artists[0].name,
      added_at: item.added_at,
      open_url: item.track.external_urls.spotify,
      uri: item.track.uri
    });
  });

  var title = data.name;
  create(title, tracks, function(data) {
    console.log('[' + chalk.green(title) + ']' + ' saved!');
  });
};

/**
 **** Main entry point *****
 * Call out to Spotify and save all the playlist tracks
 */

spotifyApi.clientCredentialsGrant()
  .then(function(data) {
    console.log('The access token is ' + chalk.yellow(data.body['access_token']));

    // Save the access token so that it's used in future calls
    spotifyApi.setAccessToken(data.body['access_token']);

    // Loop over the accounts and save each playlist
    accounts.forEach(function(acct) {
      spotifyApi.getPlaylist(acct.user, acct.playlist).then(function(data) {
        // Upsert to the database
        savePlaylist(data.body);
      });
    });

  })
  .catch(function(error) {
    console.log(chalk.red('Something went wrong when retrieving an access token'), err);
  });
<commit_msg>spotify-loader.js: Compatibility fixes and cleanup<commit_after>'use strict';

// NODE_ENV=development node spotify-loader.js

// Load up my private env
require('./config/env/heroku')();

let config = require('./config/config'),
  mongoose = require('mongoose'),
  path = require('path'),
  chalk = require('chalk'),
  moment = require('moment'),
  SpotifyWebApi = require('spotify-web-api-node'),
  accounts = require('./spotify-playlist.json');

/**
 * Database, models, and helpers
 */

mongoose.connect(config.db, { useNewUrlParser: true, useUnifiedTopology: true }, function (err) {
  if (err) {
    console.error(chalk.red('Could not connect to MongoDB!'));
    console.log(chalk.red(err));
  }
});

require(path.resolve('./app/models/playlist.server.model.js'));
let Playlist = mongoose.model('Playlist');

let getPublishedDate = function (title) {
  let onlyDigits = title.replace(/([A-Z])\w+/g, '');
  let m = moment(onlyDigits);

  if (m.isValid()) {
    return m.format('MM.DD.YYYY');
  } else {
    return null;
  }
};

let create = function (title, tracks, done) {
  let playlist = new Playlist(tracks);

  playlist.title = title
  playlist.tracks = tracks;
  playlist.published_date = getPublishedDate(title);

  let upsertData = playlist.toObject();

  delete upsertData._id;

  Playlist.update({
    title: playlist.title
  }, upsertData, {
    upsert: true
  },
    function (err) {
      if (err) {
        done(err);
      } else {
        done(playlist);
      }
    });
};

/**
 * Spotify Api
 */

let spotifyApi = new SpotifyWebApi({
  clientId: config.spotify.clientID,
  clientSecret: config.spotify.clientSecret,
  redirectUri: config.spotify.callbackURL
});

let savePlaylist = function (data) {

  let tracks = [];
  data.tracks.items.forEach(function (item) {
    tracks.push({
      id: item.track.id,
      name: item.track.name,
      artist: item.track.artists[0].name,
      added_at: item.added_at,
      open_url: item.track.external_urls.spotify,
      uri: item.track.uri
    });
  });

  let title = data.name;
  create(title, tracks, function (data) {
    console.log('[' + chalk.green(title) + ']' + ' saved!');
  });
};

/**
 **** Main entry point *****
 * Call out to Spotify and save all the playlist tracks
 */

spotifyApi.clientCredentialsGrant()
  .then(function (data) {
    console.log('The access token is ' + chalk.yellow(data.body['access_token']));

    // Save the access token so that it's used in future calls
    spotifyApi.setAccessToken(data.body['access_token']);

    // Loop over the accounts and save each playlist
    accounts.forEach(function (acct) {
      spotifyApi.getPlaylist(acct.playlist).then(function (data) {
        // Upsert to the database
        savePlaylist(data.body);
      })
        .catch(error => {
          console.log(error)
        });
    });

  })
  .catch(function (error) {
    console.log(chalk.red('Something went wrong when retrieving an access token'), error);
  });
<|endoftext|>


<commit_before>var bitcointip = modules['bitcointip'];
bitcointip.beforeLoad();
bitcointip.load();
if (!bitcointip.getAddress()) {
    bitcointip.fetchAddress();
}
bitcointip.go();

/* Create the options panel. */
if (location.pathname === '/r/bitcointip/wiki/preferences') {
    var $wiki = $('div.md.wiki');
    var $form = $('<form/>').attr({
        'class': 'tip-preferences roundfield'
    });

    /* Build up the form. */
    for (var item in bitcointip.options) {
        var option = bitcointip.options[item];
        var $label = $('<label/>').text(option.name).addClass('roundfield');
        var $input = null;
        if (option.type === 'text') {
            $input = $('<input/>').attr({
                name: item,
                type: 'text',
                value: option.value
            });
        } else if (option.type === 'boolean') {
            $input = $('<select/>').attr({
                name: item
            });
            var yes = $('<option/>').attr({
                value: 'true'
            }).text('yes');
            var no = $('<option/>').attr({
                value: 'false'
            }).text('no');
            if (option.value) {
                yes.attr('selected', true);
            } else {
                no.attr('selected', true);
            }
            $input.append(yes).append(no);
        } else if (option.type === 'enum') {
            $input = $('<select/>').attr({
                name: item
            });
            for (var i = 0; i < option.values.length; i++) {
                var value = option.values[i];
                var $option = $('<option/>').attr({
                    value: value.value
                }).text(value.value);
                if (option.value === value.value) {
                $option.attr('selected', true);
            }
                $input.append($option);
            }
        }
        if ($input) {
            var $div = $('<div/>');
            $div.append($label).append($input);
            $form.append($div);
        }
    }

    $form.append($('<input/>').attr({
        type: 'submit',
        value: 'Save Preferences'
    }));

    $form.submit(function(event) {
        event.preventDefault();
        for (var item in bitcointip.options) {
            var option = bitcointip.options[item];
            var $input = $('input[name=' + item + '], ' +
                           'select[name=' + item + ']');
            if ($input.length === 1) {
                console.log('Saved ' + item);
                var value = $input.val();
                if (option.type === 'boolean') {
                    value = JSON.parse(value);
                }
                bitcointip.options[item].value = value;
            } else {
                console.log('Skipped ' + item);
            }
        }
        bitcoinTip.save();
        window.location.reload(true); // Just to provide feedback
    });

    $wiki.empty().append($form);
}

/* ## Test Tips
 *
 * Rejected:
 *   http://www.reddit.com/r/bitcointip/comments/132nhq/_/c7c7iue
 * Rejected flip:
 *   http://www.reddit.com/r/Bitcoin/comments/14i9e7/_/c7dc6w9
 * Combination folding:
 *   http://www.reddit.com/r/bitcointip/comments/13iykn/_/c7dj8ia
 * Multiple tips to one receiver:
 *   http://www.reddit.com/r/bitcointip/comments/12lmut/_/c7ny177
 * Multiple guilded to one receiver (for comparison):
 *   http://www.reddit.com/r/AdviceAnimals/comments/15mk25/_/c7ntrcc
 * Reversed:
 *   http://www.reddit.com/r/IAmA/comments/18tp7t/_/c8i8qto
 * Fun tip to ignore:
 *   http://www.reddit.com/r/gaming/comments/18ihmm/_/c8f54l4
 */
<commit_msg>Oops, missed a bitcoinTip.<commit_after>var bitcointip = modules['bitcointip'];
bitcointip.beforeLoad();
bitcointip.load();
if (!bitcointip.getAddress()) {
    bitcointip.fetchAddress();
}
bitcointip.go();

/* Create the options panel. */
if (location.pathname === '/r/bitcointip/wiki/preferences') {
    var $wiki = $('div.md.wiki');
    var $form = $('<form/>').attr({
        'class': 'tip-preferences roundfield'
    });

    /* Build up the form. */
    for (var item in bitcointip.options) {
        var option = bitcointip.options[item];
        var $label = $('<label/>').text(option.name).addClass('roundfield');
        var $input = null;
        if (option.type === 'text') {
            $input = $('<input/>').attr({
                name: item,
                type: 'text',
                value: option.value
            });
        } else if (option.type === 'boolean') {
            $input = $('<select/>').attr({
                name: item
            });
            var yes = $('<option/>').attr({
                value: 'true'
            }).text('yes');
            var no = $('<option/>').attr({
                value: 'false'
            }).text('no');
            if (option.value) {
                yes.attr('selected', true);
            } else {
                no.attr('selected', true);
            }
            $input.append(yes).append(no);
        } else if (option.type === 'enum') {
            $input = $('<select/>').attr({
                name: item
            });
            for (var i = 0; i < option.values.length; i++) {
                var value = option.values[i];
                var $option = $('<option/>').attr({
                    value: value.value
                }).text(value.value);
                if (option.value === value.value) {
                $option.attr('selected', true);
            }
                $input.append($option);
            }
        }
        if ($input) {
            var $div = $('<div/>');
            $div.append($label).append($input);
            $form.append($div);
        }
    }

    $form.append($('<input/>').attr({
        type: 'submit',
        value: 'Save Preferences'
    }));

    $form.submit(function(event) {
        event.preventDefault();
        for (var item in bitcointip.options) {
            var option = bitcointip.options[item];
            var $input = $('input[name=' + item + '], ' +
                           'select[name=' + item + ']');
            if ($input.length === 1) {
                console.log('Saved ' + item);
                var value = $input.val();
                if (option.type === 'boolean') {
                    value = JSON.parse(value);
                }
                bitcointip.options[item].value = value;
            } else {
                console.log('Skipped ' + item);
            }
        }
        bitcointip.save();
        window.location.reload(true); // Just to provide feedback
    });

    $wiki.empty().append($form);
}

/* ## Test Tips
 *
 * Rejected:
 *   http://www.reddit.com/r/bitcointip/comments/132nhq/_/c7c7iue
 * Rejected flip:
 *   http://www.reddit.com/r/Bitcoin/comments/14i9e7/_/c7dc6w9
 * Combination folding:
 *   http://www.reddit.com/r/bitcointip/comments/13iykn/_/c7dj8ia
 * Multiple tips to one receiver:
 *   http://www.reddit.com/r/bitcointip/comments/12lmut/_/c7ny177
 * Multiple guilded to one receiver (for comparison):
 *   http://www.reddit.com/r/AdviceAnimals/comments/15mk25/_/c7ntrcc
 * Reversed:
 *   http://www.reddit.com/r/IAmA/comments/18tp7t/_/c8i8qto
 * Fun tip to ignore:
 *   http://www.reddit.com/r/gaming/comments/18ihmm/_/c8f54l4
 */
<|endoftext|>


<commit_before>define(["js/core/I18n"], function(I18n) {

    return I18n.inherit({
        t: function(num, key) {

            var args = Array.prototype.slice.call(arguments), isPlural;
            key = args.shift();
            if (_.isNumber(key) && key > 1) {

                if (key > 5) {
                    key = args.shift();
                    return I18n.prototype.t.apply(this, [key + "_large_plural"].concat(args)) || I18n.prototype.t.apply(this, [key + "_plural"].concat(args))
                }

                key = args.shift();
                return I18n.prototype.t.apply(this, [key + "_plural"].concat(args));

            }

            return this.callBase();

        }.onChange("translations")
    })
});<commit_msg>DEV-120668 - fixed bug for IE with creating product with cool font<commit_after>define(["js/core/I18n"], function(I18n) {

    return I18n.inherit({
        t: function(num, key) {

            if (_.isNumber(num) && num > 1) {

                var args = Array.prototype.slice.call(arguments);
                key = args.shift();

                if (key > 5) {
                    key = args.shift();
                    return I18n.prototype.t.apply(this, [key + "_large_plural"].concat(args)) || I18n.prototype.t.apply(this, [key + "_plural"].concat(args))
                }

                key = args.shift();
                return I18n.prototype.t.apply(this, [key + "_plural"].concat(args));

            }

            return this.callBase();

        }.onChange("translations")
    })
});<|endoftext|>


<commit_before>exports.user = user => ({
  raw: user,
  id: user.id,
  name: user.nick,
  fullName: user.name,
  email: user.email,
  image: user.avatar,
  url: user.website
})

exports.message = state => message => ({
  raw: message,
  id: message.id,
  author: state.usersById[message.user],
  text: message.content
})

const indexBy = (prop, items) =>
  items.reduce((index, item) => (index[item[prop]] = item, index), {})

const flatten = items => [].concat(...items)

exports.state = state => {
  const { userId, flows } = state
  const flowsById = indexBy('id', flows)
  const users = flatten(flows.map(flow => flow.users)).map(exports.user)
  const usersById = indexBy('id', users)

  return { userId, flows, flowsById, usersById }
}
<commit_msg>Expose thread<commit_after>exports.user = user => ({
  raw: user,
  id: user.id,
  name: user.nick,
  fullName: user.name,
  email: user.email,
  image: user.avatar,
  url: user.website
})

exports.message = state => message => ({
  raw: message,
  id: message.id,
  author: state.usersById[message.user],
  thread: message.thread_id,
  text: message.content
})

const indexBy = (prop, items) =>
  items.reduce((index, item) => (index[item[prop]] = item, index), {})

const flatten = items => [].concat(...items)

exports.state = state => {
  const { userId, flows } = state
  const flowsById = indexBy('id', flows)
  const users = flatten(flows.map(flow => flow.users)).map(exports.user)
  const usersById = indexBy('id', users)

  return { userId, flows, flowsById, usersById }
}
<|endoftext|>


<commit_before>~function(){
var Format = window.Format = window.Format || function (type){
	this.type = type;
	this.toString = function(){
		return this.type;
	}
}
Format.noop = function(data){
	return data;
};
Format.prototype.func1 = Format.noop;	// format
Format.prototype.func2 = function(data){	// compress
    return data.replace(/([\r\n]+|\/\*.*?\*\/)/g, '').replace(/[\t\s]+/g, ' ').replace(/\s*([=,:;<>\{\}])\s*/g, '$1');
};
Format.prototype.loadDemo = function(){
	return (document.getElementById(this.type) || {}).innerHTML;
};
Format.regist = function(name, func1, func2){
	var instant = Format[name] = new Format(name);
	instant.func1 = func1 || instant.func1;
	instant.func2 = func2 || instant.func2;
};
Format.get = function(name){
	return Format[name] || new Format();
};

Format.regist('css', cssbeautify);
Format.regist('js', js_beautify);
Format.regist('json', js_beautify);
Format.regist('jade', function(html, cb){
	Html2Jade.convertHtml(html, {
		tabs: false,
		nspaces: 4,
		donotencode: true,
		bodyless: !(//i).test(html),
	}, function (err, jade) {
		cb(jade);
	});
});
Format.regist('html', style_html);
Format.regist('sensors', function(str, cb) {
	if (!str) {
		return;
	}
	str = decodeURIComponent(escape(window.atob(decodeURIComponent(str))));
	try {
		str = JSON.stringify(JSON.parse(str), null, 4);
	} catch (e) {
		str = '' + e + '';
	}
	cb(str);
});
Format.regist('markdown', toMarkdown, new Markdown.Converter().makeHtml);

}();
<commit_msg>sensor decode<commit_after>~function(){
var Format = window.Format = window.Format || function (type){
	this.type = type;
	this.toString = function(){
		return this.type;
	}
}
Format.noop = function(data){
	return data;
};
Format.prototype.func1 = Format.noop;	// format
Format.prototype.func2 = function(data){	// compress
    return data.replace(/([\r\n]+|\/\*.*?\*\/)/g, '').replace(/[\t\s]+/g, ' ').replace(/\s*([=,:;<>\{\}])\s*/g, '$1');
};
Format.prototype.loadDemo = function(){
	return (document.getElementById(this.type) || {}).innerHTML;
};
Format.regist = function(name, func1, func2){
	var instant = Format[name] = new Format(name);
	instant.func1 = func1 || instant.func1;
	instant.func2 = func2 || instant.func2;
};
Format.get = function(name){
	return Format[name] || new Format();
};

Format.regist('css', cssbeautify);
Format.regist('js', js_beautify);
Format.regist('json', js_beautify);
Format.regist('jade', function(html, cb){
	Html2Jade.convertHtml(html, {
		tabs: false,
		nspaces: 4,
		donotencode: true,
		bodyless: !(//i).test(html),
	}, function (err, jade) {
		cb(jade);
	});
});
Format.regist('html', style_html);
Format.regist('sensors', function(str, cb) {
	if (!str) {
		return;
	}
	try {
		str = JSON.stringify(JSON.parse(decodeURIComponent(escape(window.atob(decodeURIComponent(str))))), null, 4);
	} catch (e) {
		str = '' + e + '';
	}
	cb(str);
}, function(str, cb) {
	if (!str) {
		return;
	}
	try {
		str = JSON.parse(str);
		str = window.btoa(unescape(encodeURIComponent(JSON.stringify(str))));
		// 传递给 url query params 时，需要再 encodeURIComponent 一次
	} catch (e) {
		str = '' + e + '';
	}
	cb(str);
});
Format.regist('markdown', toMarkdown, new Markdown.Converter().makeHtml);

}();
<|endoftext|>


<commit_before>var replaceLong = {
	ak: "aardrijkskunde",
	biol: "biologie",
	dutl: "duits",
	econ: "economie",
	entl: "engels",
	fatl: "frans",
	kubv: "kunst",
	mt: "mentorles",
	nat: "natuurkunde",
	netl: "nederlands",
	schk: "scheikunde",
	wisa: "wiskunde A",
	wisb: "wiskunde B",
	wisc: "wiskunde C",
	wisd: "wiskunde D",
}

var replaceShort = {
	biol: "bio",
	dutl: "du",
	econ: "eco",
	entl: "en",
	fatl: "fr",
	kubv: "ku",
	nat: "na",
	netl: "ne",
	schk: "sk",
	wisa: "wi A",
	wisb: "wi B",
	wisc: "wi C",
	wisd: "wi D",
	zbb: "zb",
}

function formatLessons(roosterdata){
	var use12h = ( Cookies.get("12h") == "true" )

	function insert(cssclass, data, change){
		if(data != "" && data != undefined){
			$(div).append("" + data + "
")
		}
	}

	// get date of special days
	var year = new Date().getFullYear()
	var firstDayOfMonth = new Date( year, new Date().getMonth(), 1 )
	var purplefriday = new Date( year, 11, 8 + mod(5-firstDayOfMonth.getDay(), 7) )

	var kingsday = new Date( new Date().getFullYear(), 3, 27 )
	if( kingsday.getDay() === 0 ){
		kingsday.setDate( kingsDay.getDate() - 1 )
	}

	for( var i = 0; i < roosterdata.length; i++ ){
		var lesson = roosterdata[i]
		var div = $("
").appendTo("main .rooster .dag-"+(lesson.day-1))

		$(div).addClass("lesson")

		$(div).css("top", (lesson.starttime-8.5)*70)
		$(div).css("height", lesson.size*70)

		if( options.modifySubjects == "false" || options.modifySubjects == undefined ){
			insert("les-vak", lesson.desc.vak, lesson.subjectChanged)
		}else{
			var subject = lesson.desc.vak
			if( options.modifySubjects == "short" ){
				insert("les-vak", replaceShort[subject] || subject, lesson.subjectChanged)
			}else if( options.modifySubjects == "long" ){
				insert("les-vak", replaceLong[subject] || subject, lesson.subjectChanged)
			}
		}

		insert("les-lokaal", lesson.desc.lokaal, lesson.locationChanged)
		insert("les-docent", lesson.desc.docent)
		insert("les-opmerking", lesson.desc.opmerking)
		insert("les-klas", lesson.desc.klas)
		insert("les-tijd", lesson.startdate.toLocaleTimeString("en-US", {hour12: use12h, hour: "2-digit", minute: "2-digit"}))
		insert("les-eindtijd", lesson.enddate.toLocaleTimeString("en-US", {hour12: use12h, hour: "2-digit", minute: "2-digit"}))
		insert("les-verdanderbericht", lesson.desc.veranderbericht)

		if(lesson.desc.type == "exam"){
			$(div).addClass("toets")
		}

		// check for special days
		if( lesson.startdate.getMonth() == purplefriday.getMonth() && lesson.startdate.getDate() == purplefriday.getDate() ){
			$(div).addClass("purplefriday")
		}
		if( lesson.startdate.getMonth() == kingsday.getMonth() && lesson.startdate.getDate() == kingsday.getDate() ){
			$(div).addClass("kingsday")
		}

		// Check for removed lessons
		if( lesson.cancelled ){
			$(div).addClass("cancelled")
		}

		var top = $(div).css("top")
		var height = $(div).css("height")
		$("main .rooster .dag-"+(lesson.day-1)).append("

")
	}
}

function registerClickCallbacks(elem){
	$(elem).click(function(){
		$("#lesson-overlay").removeClass("active")
		$(".lesson").removeClass("big")
		$("#user").val( $(this).text() )
		getUser( $(this).text() ).then(function(scheduleFor){
			options.scheduleFor = scheduleFor
			showUserName(options)
			update(options)
		})
		return false
	})
}

function formatSchedule( data, options ){
	// Empty previous schedule
	for( var i = 0; i < 5; i++ ){
		$("main .rooster .dag-"+i).empty()
	}

	// Format lessons
	setTimeout(function(){
		formatLessons( data, options )

		// Add event listeners
		$("#lesson-overlay.active").click(function(){
			$("#lesson-overlay").removeClass("active")
		})

		$(".lesson").click(function(e){
			e.stopPropagation()
			var thislesson = this

			if( $(window).width() < $(window).height() ){ // Mobile device
				$(".lesson").removeClass("big")
				setTimeout(function(){
					$(".lesson").removeClass("top")
				}, 300)

				if( $("#lesson-overlay.active").length >= 1 ){
					$("#lesson-overlay").removeClass("active")
					setTimeout(function(){
						$("#lesson-overlay").html( $(thislesson).html() )
						$("#lesson-overlay").addClass("active")
						registerClickCallbacks("#lesson-overlay span a")
					}, 300)
				}else{
					$("#lesson-overlay").html( $(thislesson).html() )
					$("#lesson-overlay").addClass("active")
					registerClickCallbacks("#lesson-overlay span a")
				}
			}else{ // Desktop
				$("#lesson-overlay").removeClass("active")

				if( $(".top").length >= 1 ){
					setTimeout(function(){
						$(".lesson").removeClass("top")
					}, 300)
					if( $(".lesson.big")[0] != thislesson ){
						setTimeout(function(){
							$(thislesson).addClass("big")
							$(thislesson).addClass("top")
						}, 300)
					}
					$(".lesson").removeClass("big")
				}else{
					$(thislesson).addClass("big")
					$(thislesson).addClass("top")
				}
			}
		})

		registerClickCallbacks(".lesson span a")
	}, 0)
}

function showUserName(options){
	var capitalise = function(input){
		if( !input ){ return "" }
		text = input.match(/[a-z]+/g)
		if( text.join(" ") != input ){
			// Not a name, leave it
			return input
		}
		text[0] = text[0].charAt(0).toUpperCase() + text[0].slice(1)
		text[text.length-1] = text[text.length-1].charAt(0).toUpperCase() + text[text.length-1].slice(1)
		return text.join(" ")
	}
	if( options.scheduleFor ){
		$(".userName").text( capitalise(options.scheduleFor.name) )
	}
}
<commit_msg>Add lesson element to js object<commit_after>var replaceLong = {
	ak: "aardrijkskunde",
	biol: "biologie",
	dutl: "duits",
	econ: "economie",
	entl: "engels",
	fatl: "frans",
	kubv: "kunst",
	mt: "mentorles",
	nat: "natuurkunde",
	netl: "nederlands",
	schk: "scheikunde",
	wisa: "wiskunde A",
	wisb: "wiskunde B",
	wisc: "wiskunde C",
	wisd: "wiskunde D",
}

var replaceShort = {
	biol: "bio",
	dutl: "du",
	econ: "eco",
	entl: "en",
	fatl: "fr",
	kubv: "ku",
	nat: "na",
	netl: "ne",
	schk: "sk",
	wisa: "wi A",
	wisb: "wi B",
	wisc: "wi C",
	wisd: "wi D",
	zbb: "zb",
}

function formatLessons(roosterdata){
	var use12h = ( Cookies.get("12h") == "true" )

	function insert(cssclass, data, change){
		if(data != "" && data != undefined){
			$(lesson.elem).append("" + data + "
")
		}
	}

	// get date of special days
	var year = new Date().getFullYear()
	var firstDayOfMonth = new Date( year, new Date().getMonth(), 1 )
	var purplefriday = new Date( year, 11, 8 + mod(5-firstDayOfMonth.getDay(), 7) )

	var kingsday = new Date( new Date().getFullYear(), 3, 27 )
	if( kingsday.getDay() === 0 ){
		kingsday.setDate( kingsDay.getDate() - 1 )
	}

	for( var i = 0; i < roosterdata.length; i++ ){
		var lesson = roosterdata[i]
		lesson.elem = $("
").appendTo("main .rooster .dag-"+(lesson.day-1))

		$(lesson.elem).addClass("lesson")

		$(lesson.elem).css("top", (lesson.starttime-8.5)*70)
		$(lesson.elem).css("height", lesson.size*70)

		if( options.modifySubjects == "false" || options.modifySubjects == undefined ){
			insert("les-vak", lesson.desc.vak, lesson.subjectChanged)
		}else{
			var subject = lesson.desc.vak
			if( options.modifySubjects == "short" ){
				insert("les-vak", replaceShort[subject] || subject, lesson.subjectChanged)
			}else if( options.modifySubjects == "long" ){
				insert("les-vak", replaceLong[subject] || subject, lesson.subjectChanged)
			}
		}

		insert("les-lokaal", lesson.desc.lokaal, lesson.locationChanged)
		insert("les-docent", lesson.desc.docent)
		insert("les-opmerking", lesson.desc.opmerking)
		insert("les-klas", lesson.desc.klas)
		insert("les-tijd", lesson.startdate.toLocaleTimeString("en-US", {hour12: use12h, hour: "2-digit", minute: "2-digit"}))
		insert("les-eindtijd", lesson.enddate.toLocaleTimeString("en-US", {hour12: use12h, hour: "2-digit", minute: "2-digit"}))
		insert("les-verdanderbericht", lesson.desc.veranderbericht)

		if(lesson.desc.type == "exam"){
			$(lesson.elem).addClass("toets")
		}

		// check for special days
		if( lesson.startdate.getMonth() == purplefriday.getMonth() && lesson.startdate.getDate() == purplefriday.getDate() ){
			$(lesson.elem).addClass("purplefriday")
		}
		if( lesson.startdate.getMonth() == kingsday.getMonth() && lesson.startdate.getDate() == kingsday.getDate() ){
			$(lesson.elem).addClass("kingsday")
		}

		// Check for removed lessons
		if( lesson.cancelled ){
			$(lesson.elem).addClass("cancelled")
		}

		var top = $(lesson.elem).css("top")
		var height = $(lesson.elem).css("height")
		$("main .rooster .dag-"+(lesson.day-1)).append("

")
	}
}

function registerClickCallbacks(elem){
	$(elem).click(function(){
		$("#lesson-overlay").removeClass("active")
		$(".lesson").removeClass("big")
		$("#user").val( $(this).text() )
		getUser( $(this).text() ).then(function(scheduleFor){
			options.scheduleFor = scheduleFor
			showUserName(options)
			update(options)
		})
		return false
	})
}

function formatSchedule( data, options ){
	// Empty previous schedule
	for( var i = 0; i < 5; i++ ){
		$("main .rooster .dag-"+i).empty()
	}

	// Format lessons
	setTimeout(function(){
		formatLessons( data, options )

		// Add event listeners
		$("#lesson-overlay.active").click(function(){
			$("#lesson-overlay").removeClass("active")
		})

		$(".lesson").click(function(e){
			e.stopPropagation()
			var thislesson = this

			if( $(window).width() < $(window).height() ){ // Mobile device
				$(".lesson").removeClass("big")
				setTimeout(function(){
					$(".lesson").removeClass("top")
				}, 300)

				if( $("#lesson-overlay.active").length >= 1 ){
					$("#lesson-overlay").removeClass("active")
					setTimeout(function(){
						$("#lesson-overlay").html( $(thislesson).html() )
						$("#lesson-overlay").addClass("active")
						registerClickCallbacks("#lesson-overlay span a")
					}, 300)
				}else{
					$("#lesson-overlay").html( $(thislesson).html() )
					$("#lesson-overlay").addClass("active")
					registerClickCallbacks("#lesson-overlay span a")
				}
			}else{ // Desktop
				$("#lesson-overlay").removeClass("active")

				if( $(".top").length >= 1 ){
					setTimeout(function(){
						$(".lesson").removeClass("top")
					}, 300)
					if( $(".lesson.big")[0] != thislesson ){
						setTimeout(function(){
							$(thislesson).addClass("big")
							$(thislesson).addClass("top")
						}, 300)
					}
					$(".lesson").removeClass("big")
				}else{
					$(thislesson).addClass("big")
					$(thislesson).addClass("top")
				}
			}
		})

		registerClickCallbacks(".lesson span a")
	}, 0)
}

function showUserName(options){
	var capitalise = function(input){
		if( !input ){ return "" }
		text = input.match(/[a-z]+/g)
		if( text.join(" ") != input ){
			// Not a name, leave it
			return input
		}
		text[0] = text[0].charAt(0).toUpperCase() + text[0].slice(1)
		text[text.length-1] = text[text.length-1].charAt(0).toUpperCase() + text[text.length-1].slice(1)
		return text.join(" ")
	}
	if( options.scheduleFor ){
		$(".userName").text( capitalise(options.scheduleFor.name) )
	}
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
  http://dev.maxmind.com/geoip/legacy/csv (used by geo.mozilla.org)
  http://en.wikipedia.org/wiki/ISO_3166-1 (full list of cc's)
*/
;(function($) {
  'use strict';

  window.pause_ga_tracking = false;

  var COUNTRY_CODE = '';

  var PARTNER_DATA = {
    "br": {
      "partner": [
        {
          "name": "Vivo",
          "url": "http://www.vivo.com.br/firefox"
        }
      ]
    },
    "co": {
      "partner": [
        {
          "name": "Movistar",
          "url": "http://www.movistar.co"
        }
      ]
    },
    "de": {
      "partner": [
        {
          "name": "congstar",
          "url": "http://aktion.congstar.de/firefox-os"
        }
      ]
    },
    "es": {
      "partner": [
        {
          "name": "Movistar",
          "url": "http://www.movistar.es/firefoxos?aff=aff-firefoxOS1"
        }
      ]
    },
    "gr": {
      "partner": [
        {
          "name": "Cosmote",
          "url": "http://www.cosmote.gr/cosmoportal/cosmote.portal?_nfpb=true&_pageLabel=HDV&sku=20290038&s=0"
        }
      ]
    },
    "hu": {
      "partner": [
        {
          "name": "T-Mobile",
          "url": "https://webshop.t-mobile.hu/webapp/wcs/stores/ProductDisplay?catalogId=2001&storeId=2001&langId=-11&productId=644566"
        },
        {
          "name": "Telenor",
          "url": "http://www.telenor.hu/mobiltelefon/alcatel/one-touch-fire"
        }
      ]
    },
    "me": {
      "partner": [
        {
          "name": "Telenor",
          "url": "http://www.telenor.me/sr/Privatni-korisnici/Uredjaji/Alcatel/Alcatel-One-Touch-Fire/"
        }
      ]
    },
    "mx": {
      "partner": [
        {
          "name": "Movistar",
          "url": "http://www.movistar.com.mx/firefox"
        }
      ]
    },
    "pe": {
      "partner": [
        {
          "name": "Movistar",
          "url": "http://catalogo.movistar.com.pe/zte-open"
        }
      ]
    },
    "pl": {
      "partner": [
        {
          "name": "T-Mobile",
          "url": "http://www.t-mobile.pl/pl/firefox"
        }
      ]
    },
    "rs": {
      "partner": [
        {
          "name": "Telenor",
          "url": "https://www.telenor.rs/sr/Privatni-korisnici/webshop/Mobilni-telefoni/Alcatel/One_Touch_Fire"
        }
      ]
    },
    "uy": {
      "partner": [
        {
          "name": "Movistar",
          "url": "http://www.firefoxos.movistar.com.uy/"
        }
      ]
    },
    "ve": {
      "partner": [
        {
          "name": "Movistar",
          "url": "http://www.movistar.com.ve/movistar_firefox/index.html"
        }
      ]
    }
  };

  /*
   * Set page specific content relating to geo for partner data etc
   */
  function setPartnerContent () {
    var $getPhoneContent = $('#get-phone-wrapper .content');
    var $providerLinks = $('#provider-links');
    var links = '';

    if (PARTNER_DATA.hasOwnProperty(COUNTRY_CODE)) {

      // show get phone calls to action
      $('#primary-cta-phone').fadeIn();
      $('#primary-cta-signup').addClass('visibility', 'hidden');
      $('#secondary-cta-phone').css('display', 'inline-block');

      // if country has more than one provider, show the multi intro text
      if (PARTNER_DATA[COUNTRY_CODE].partner.length > 1) {
        $('#provider-text-single').hide();
        $('#provider-text-multi').show();
      }
      // show partner specific links on modal etc
      $.each(PARTNER_DATA[COUNTRY_CODE].partner, function(i, data) {
        //set data.name, data.url etc
        var index = i === 1 ? 'last' : '';
        links += '' + data.name + '';
      });
      // add country class as an extra style hook and inject the links
      $('#provider-links').addClass(COUNTRY_CODE).html(links);

      // setup GA event tracking on telecom provider exit links
      $('#provider-links a').on('click', trackProviderExit);

      // persistent pencil icon is distracting/obtrusive on small screens
      if ($(window).width() > 480) {
        $('#signup-toggle-icon').fadeIn();
      }
    } else {
      $('#primary-cta-signup').fadeIn();
      $('#primary-cta-phone').addClass('visibility', 'hidden');
      $('#secondary-cta-signup').css('display', 'inline-block');
    }
  }

  /*
   * Track telecom provider link clicks/page exits in Google Analytics
   */
  function trackProviderExit (e) {
    e.preventDefault();
    var $this = $(this);
    var href = this.href;

    var callback = function () {
      window.location = href;
    };

    trackGAEvent(['_trackEvent', 'FxOs Consumer Page', 'Get A Phone Exit', $this.text()], callback);
  }

  /*
   * Set newsletter default options based on cc
   */
  function setNewsletterDefaults () {
    var countrySelection = $('#id_country option[value='+ COUNTRY_CODE +']');

    // if cc is in the country option list, select it
    // remove the default selection first
    if (countrySelection.length !== 0) {
      $('#id_country option:selected').removeAttr('selected');
      countrySelection.attr('selected', 'selected');
    }

    // for ve and co set the default language to es
    // other countries auto select based on cc
    switch(COUNTRY_CODE) {
    case 've':
      $('#id_lang option[value="es"]').attr('selected', 'selected');
      break;
    case 'co':
      $('#id_lang option[value="es"]').attr('selected', 'selected');
      break;
    default:
      $('#id_lang option[value="' + COUNTRY_CODE + '"]').attr('selected', 'selected');
    }
  }

  /*
   * Get country code via geo-ip lookup
   */
  function getGeoLocation () {
    try {
      COUNTRY_CODE = geoip_country_code().toLowerCase();
    } catch (e) {
      COUNTRY_CODE = "";
    }
  }

  window.trackGAEvent = function (eventsArray, callback) {
    if (!pause_ga_tracking) {
      var timer = null;
      var hasCallback = typeof(callback) == 'function';
      var gaCallback = function () {
        clearTimeout(timer);
        callback();
      };
      if (typeof(window._gaq) == 'object') {

        if (hasCallback) {
          timer = setTimeout(gaCallback, 500);
          window._gaq.push(
            ['_set', 'hitCallback', gaCallback],
            eventsArray
          );
        } else {
          window._gaq.push(eventsArray);
        }
      } else if (hasCallback) {
        callback();
      }
    }
  };

  $('#useful-links').on('click', 'a', function (e) {
    e.preventDefault();
    var that = this;
    var callback = function () {
      window.location = that.href;
    };
    //track GA event for useful links
    trackGAEvent(['_trackEvent', 'FxOs Consumer Page', 'click', this.href], callback);
  });

  $script('//geo.mozilla.org/country.js', function() {
    getGeoLocation();
    setNewsletterDefaults();
    setPartnerContent();
  });

})(jQuery);
<commit_msg>Fix bug 935164 - update purchase link for Montenegro<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
  http://dev.maxmind.com/geoip/legacy/csv (used by geo.mozilla.org)
  http://en.wikipedia.org/wiki/ISO_3166-1 (full list of cc's)
*/
;(function($) {
  'use strict';

  window.pause_ga_tracking = false;

  var COUNTRY_CODE = '';

  var PARTNER_DATA = {
    "br": {
      "partner": [
        {
          "name": "Vivo",
          "url": "http://www.vivo.com.br/firefox"
        }
      ]
    },
    "co": {
      "partner": [
        {
          "name": "Movistar",
          "url": "http://www.movistar.co"
        }
      ]
    },
    "de": {
      "partner": [
        {
          "name": "congstar",
          "url": "http://aktion.congstar.de/firefox-os"
        }
      ]
    },
    "es": {
      "partner": [
        {
          "name": "Movistar",
          "url": "http://www.movistar.es/firefoxos?aff=aff-firefoxOS1"
        }
      ]
    },
    "gr": {
      "partner": [
        {
          "name": "Cosmote",
          "url": "http://www.cosmote.gr/cosmoportal/cosmote.portal?_nfpb=true&_pageLabel=HDV&sku=20290038&s=0"
        }
      ]
    },
    "hu": {
      "partner": [
        {
          "name": "T-Mobile",
          "url": "https://webshop.t-mobile.hu/webapp/wcs/stores/ProductDisplay?catalogId=2001&storeId=2001&langId=-11&productId=644566"
        },
        {
          "name": "Telenor",
          "url": "http://www.telenor.hu/mobiltelefon/alcatel/one-touch-fire"
        }
      ]
    },
    "me": {
      "partner": [
        {
          "name": "Telenor",
          "url": "http://www.telenor.me/sr/Privatni-korisnici/Uredjaji/Mobilni-telefoni/Alcatel/OT_Fire"
        }
      ]
    },
    "mx": {
      "partner": [
        {
          "name": "Movistar",
          "url": "http://www.movistar.com.mx/firefox"
        }
      ]
    },
    "pe": {
      "partner": [
        {
          "name": "Movistar",
          "url": "http://catalogo.movistar.com.pe/zte-open"
        }
      ]
    },
    "pl": {
      "partner": [
        {
          "name": "T-Mobile",
          "url": "http://www.t-mobile.pl/pl/firefox"
        }
      ]
    },
    "rs": {
      "partner": [
        {
          "name": "Telenor",
          "url": "https://www.telenor.rs/sr/Privatni-korisnici/webshop/Mobilni-telefoni/Alcatel/One_Touch_Fire"
        }
      ]
    },
    "uy": {
      "partner": [
        {
          "name": "Movistar",
          "url": "http://www.firefoxos.movistar.com.uy/"
        }
      ]
    },
    "ve": {
      "partner": [
        {
          "name": "Movistar",
          "url": "http://www.movistar.com.ve/movistar_firefox/index.html"
        }
      ]
    }
  };

  /*
   * Set page specific content relating to geo for partner data etc
   */
  function setPartnerContent () {
    var $getPhoneContent = $('#get-phone-wrapper .content');
    var $providerLinks = $('#provider-links');
    var links = '';

    if (PARTNER_DATA.hasOwnProperty(COUNTRY_CODE)) {

      // show get phone calls to action
      $('#primary-cta-phone').fadeIn();
      $('#primary-cta-signup').addClass('visibility', 'hidden');
      $('#secondary-cta-phone').css('display', 'inline-block');

      // if country has more than one provider, show the multi intro text
      if (PARTNER_DATA[COUNTRY_CODE].partner.length > 1) {
        $('#provider-text-single').hide();
        $('#provider-text-multi').show();
      }
      // show partner specific links on modal etc
      $.each(PARTNER_DATA[COUNTRY_CODE].partner, function(i, data) {
        //set data.name, data.url etc
        var index = i === 1 ? 'last' : '';
        links += '' + data.name + '';
      });
      // add country class as an extra style hook and inject the links
      $('#provider-links').addClass(COUNTRY_CODE).html(links);

      // setup GA event tracking on telecom provider exit links
      $('#provider-links a').on('click', trackProviderExit);

      // persistent pencil icon is distracting/obtrusive on small screens
      if ($(window).width() > 480) {
        $('#signup-toggle-icon').fadeIn();
      }
    } else {
      $('#primary-cta-signup').fadeIn();
      $('#primary-cta-phone').addClass('visibility', 'hidden');
      $('#secondary-cta-signup').css('display', 'inline-block');
    }
  }

  /*
   * Track telecom provider link clicks/page exits in Google Analytics
   */
  function trackProviderExit (e) {
    e.preventDefault();
    var $this = $(this);
    var href = this.href;

    var callback = function () {
      window.location = href;
    };

    trackGAEvent(['_trackEvent', 'FxOs Consumer Page', 'Get A Phone Exit', $this.text()], callback);
  }

  /*
   * Set newsletter default options based on cc
   */
  function setNewsletterDefaults () {
    var countrySelection = $('#id_country option[value='+ COUNTRY_CODE +']');

    // if cc is in the country option list, select it
    // remove the default selection first
    if (countrySelection.length !== 0) {
      $('#id_country option:selected').removeAttr('selected');
      countrySelection.attr('selected', 'selected');
    }

    // for ve and co set the default language to es
    // other countries auto select based on cc
    switch(COUNTRY_CODE) {
    case 've':
      $('#id_lang option[value="es"]').attr('selected', 'selected');
      break;
    case 'co':
      $('#id_lang option[value="es"]').attr('selected', 'selected');
      break;
    default:
      $('#id_lang option[value="' + COUNTRY_CODE + '"]').attr('selected', 'selected');
    }
  }

  /*
   * Get country code via geo-ip lookup
   */
  function getGeoLocation () {
    try {
      COUNTRY_CODE = geoip_country_code().toLowerCase();
    } catch (e) {
      COUNTRY_CODE = "";
    }
  }

  window.trackGAEvent = function (eventsArray, callback) {
    if (!pause_ga_tracking) {
      var timer = null;
      var hasCallback = typeof(callback) == 'function';
      var gaCallback = function () {
        clearTimeout(timer);
        callback();
      };
      if (typeof(window._gaq) == 'object') {

        if (hasCallback) {
          timer = setTimeout(gaCallback, 500);
          window._gaq.push(
            ['_set', 'hitCallback', gaCallback],
            eventsArray
          );
        } else {
          window._gaq.push(eventsArray);
        }
      } else if (hasCallback) {
        callback();
      }
    }
  };

  $('#useful-links').on('click', 'a', function (e) {
    e.preventDefault();
    var that = this;
    var callback = function () {
      window.location = that.href;
    };
    //track GA event for useful links
    trackGAEvent(['_trackEvent', 'FxOs Consumer Page', 'click', this.href], callback);
  });

  $script('//geo.mozilla.org/country.js', function() {
    getGeoLocation();
    setNewsletterDefaults();
    setPartnerContent();
  });

})(jQuery);
<|endoftext|>


<commit_before>/*
*     (C) Copyright 2008 Telefonica Investigacion y Desarrollo
*     S.A.Unipersonal (Telefonica I+D)
*
*     This file is part of Morfeo EzWeb Platform.
*
*     Morfeo EzWeb Platform is free software: you can redistribute it and/or modify
*     it under the terms of the GNU Affero General Public License as published by
*     the Free Software Foundation, either version 3 of the License, or
*     (at your option) any later version.
*
*     Morfeo EzWeb Platform is distributed in the hope that it will be useful,
*     but WITHOUT ANY WARRANTY; without even the implied warranty of
*     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*     GNU Affero General Public License for more details.
*
*     You should have received a copy of the GNU Affero General Public License
*     along with Morfeo EzWeb Platform.  If not, see <http://www.gnu.org/licenses/>.
*
*     Info about members and contributors of the MORFEO project
*     is available at
*
*     http://morfeo-project.org
 */

function VarManager (_workSpace) {

	VarManager.prototype.MAX_BUFFERED_REQUESTS = 10

	// ****************
	// PUBLIC METHODS
	// ****************

	VarManager.prototype.parseVariables = function (workSpaceInfo) {
		// Igadget variables!
		var tabs = workSpaceInfo['workspace']['tabList'];

		for (var i=0; i<tabs.length; i++) {
			var igadgets = tabs[i]['igadgetList'];

			for (var j=0; j<igadgets.length; j++) {
				this.parseIGadgetVariables(igadgets[j], this.workSpace.getTabInstance(tabs[i].id));
			}
		}

		// Workspace variables (Connectables and future variables!)
		var ws_vars = workSpaceInfo['workspace']['workSpaceVariableList'];

		this.parseWorkspaceVariables(ws_vars);
	}

	VarManager.prototype.parseWorkspaceVariables = function (ws_vars) {
		for (var i = 0; i<ws_vars.length; i++) {
			this.parseWorkspaceVariable(ws_vars[i]);
		}
	}

	VarManager.prototype.sendBufferedVars = function () {
		// Asynchronous handlers
		function onSuccess(transport) {
			var response = transport.responseText;
			var modifiedVariables = JSON.parse(response);
			var igadgetVars = modifiedVariables['igadgetVars']
			this.modificationsEnabled = false; //lock the adding of modified variables to the buffer
			for (var i=0;i<igadgetVars.length;i++){
				var id = igadgetVars[i].id;
				var variable = this.getVariableById(id);
				variable.annotate(igadgetVars[i].value)
			}
			for (var i=0;i<igadgetVars.length;i++){
				var id = igadgetVars[i].id;
				var variable = this.getVariableById(id);
				variable.set(igadgetVars[i].value) //set will not add the variable to the modified variables to be sent due to the 'disableModifications'
			}
			this.modificationsEnabled = true; //unlock the adding of modified variables to the buffer
		}

		function onError(transport, e) {
			var logManager = LogManagerFactory.getInstance();
			var msg = logManager.formatError(gettext("Error saving variables to persistence: %(errorMsg)s."), transport, e);
			logManager.log(msg);
		}

		// Max lenght of buffered requests have been reached. Uploading to server!
		if (this.igadgetModifiedVars.length > 0 || this.workspaceModifiedVars.length > 0) {
			var variables = {};

			variables['igadgetVars'] = this.igadgetModifiedVars;
			variables['workspaceVars'] = this.workspaceModifiedVars;

			var uri = URIs.PUT_VARIABLES.evaluate({workspaceId: this.workSpace.getId()});

			var options = {
				method: 'PUT',
				requestHeaders: {
					'Content-Type': 'application/json'
				},
				postBody: Object.toJSON(variables),
				onSuccess: onSuccess.bind(this),
				onFailure: onError.bind(this),
				onException: onError.bind(this)
			};
			PersistenceEngineFactory.getInstance().send(uri, options);
			this.resetModifiedVariables();
		}
	}

	VarManager.prototype.parseWorkspaceVariable = function (ws_var) {
		var id = ws_var.id;
		var name = ws_var.name;
		var aspect = ws_var.aspect;
		var value = ws_var.value;

		switch (aspect) {
			case Variable.prototype.INOUT:
				this.workspaceVariables[id] = new RWVariable(id, null, name, aspect, this, value);
				break;
			case Variable.prototype.TAB:
				this.workspaceVariables[id] = new RVariable(id, null, name, aspect, this, value);
				break;
		}
	}

	VarManager.prototype.removeWorkspaceVariable = function (ws_varId) {
		delete this.workspaceVariables[ws_varId];
		this.workspaceModifiedVars.removeById(ws_varId);
	}

	VarManager.prototype.parseIGadgetVariables = function (igadget, tab) {
		var igadgetVars = igadget['variables'];
		var objVars = []
		for (var i = 0; i<igadgetVars.length; i++) {
			var id = igadgetVars[i].id;
			var igadgetId = igadgetVars[i].igadgetId;
			var name = igadgetVars[i].name;
			var label = igadgetVars[i].label;
			var aspect = igadgetVars[i].aspect;
			var value = igadgetVars[i].value;
			var shared = igadgetVars[i].shared;

			switch (aspect) {
				case Variable.prototype.PROPERTY:
				case Variable.prototype.EVENT:
					objVars[name] = new RWVariable(id, igadgetId, name, aspect, this, value, label, tab, shared);
					this.variables[id] = objVars[name];
					break;
				case Variable.prototype.EXTERNAL_CONTEXT:
				case Variable.prototype.GADGET_CONTEXT:
				case Variable.prototype.SLOT:
				case Variable.prototype.USER_PREF:
					objVars[name] = new RVariable(id, igadgetId, name, aspect, this, value, label, tab, shared);
					this.variables[id] = objVars[name];
					break;
			}
		}

		this.iGadgets[igadget['id']] = objVars;

	}

	VarManager.prototype.registerVariable = function (iGadgetId, variableName, handler) {
		var variable = this.findVariable(iGadgetId, variableName);

		if (variable) {
			variable.setHandler(handler);
		} else {
			var transObj = {iGadgetId: iGadgetId, varName: variableName};
			var msg = interpolate(gettext("IGadget %(iGadgetId)s does not have any variable named \"%(varName)s\".\nIf you need it, please insert it into the gadget's template."), transObj, true);
			OpManagerFactory.getInstance().logIGadgetError(iGadgetId, msg, Constants.Logging.ERROR_MSG);
		}
	}

	VarManager.prototype.assignEventConnectable = function (iGadgetId, variableName, wEvent) {
		var variable = this.findVariable(iGadgetId, variableName);
		variable.assignEvent(wEvent);
	}

	VarManager.prototype.getVariable = function (iGadgetId, variableName) {
		var variable = this.findVariable(iGadgetId, variableName);

		// Error control

		return variable.get();
	}

	VarManager.prototype.setVariable = function (iGadgetId, variableName, value) {
		if (typeof(value) !== 'string') {
			var transObj = {iGadgetId: iGadgetId, varName: variableName};
			var msg = interpolate(gettext("IGadget %(iGadgetId)s attempted to establish a non-string value for the variable \"%(varName)s\"."), transObj, true);
			OpManagerFactory.getInstance().logIGadgetError(iGadgetId, msg, Constants.Logging.ERROR_MSG);

			throw new Error();
		}

		var variable = this.findVariable(iGadgetId, variableName);

		variable.set(value);
	}

	VarManager.prototype.addPendingVariable = function (iGadgetId, variableName, value) {
		var variables = this.pendingVariables[iGadgetId];
		if (!variables){
			this.pendingVariables[iGadgetId] = new Array();
			variables = this.pendingVariables[iGadgetId];
		}
		variables.push({"name":variableName, "value":value});
	}

	VarManager.prototype.dispatchPendingVariables = function (iGadgetId) {
		var variables = this.pendingVariables.remove(iGadgetId);
		if (variables){
			for (var i=0;i<variables.length;i++){
				this.setVariable(iGadgetId, variables[i]["name"], variables[i]["value"]);
			}
		}
	}

	VarManager.prototype.addInstance = function (iGadget, igadgetInfo, tab) {
		this.parseIGadgetVariables(igadgetInfo, tab);
	}

	VarManager.prototype.removeInstance = function (iGadgetId) {
		delete this.iGadgets[iGadgetId];

		this.removeIGadgetVariables(iGadgetId);
	}

	VarManager.prototype.removeIGadgetVariables = function (iGadgetId) {
		var variables_ids = this.variables.keys()

		for (var i=0; i<variables_ids.length; i++) {
			if (this.variables[variables_ids[i]].iGadget == iGadgetId) {
				this.igadgetModifiedVars.removeById(variables_ids[i]);
				delete this.variables[variables_ids[i]];
			}
		}
	}

	VarManager.prototype.unload = function () {
	}

	VarManager.prototype.commitModifiedVariables = function() {
		//If it have not been buffered all the requests, it's not time to send a PUT request
		if (!this.force_commit && this.buffered_requests < VarManager.prototype.MAX_BUFFERED_REQUESTS) {
			this.buffered_requests++;
			return
		}

		this.sendBufferedVars();
	}

	VarManager.prototype.createWorkspaceVariable = function(name) {
		var provisional_id = new Date().getTime();

		return new RWVariable(provisional_id, null, name, Variable.prototype.INOUT, this, "");

	}

	VarManager.prototype.addWorkspaceVariable = function(id, variable) {
		this.workspaceVariables[id] = variable;
	}

	VarManager.prototype.getWorkspaceVariableById = function(varId) {
		return this.workspaceVariables[varId];
	}

	VarManager.prototype.initializeInterface = function () {
	    // Calling all SLOT vars handler
	    var variable;
	    var vars;
	    var varIndex;
	    var gadgetIndex;

	    for (gadgetIndex in this.iGadgets) {
		vars = this.iGadgets[gadgetIndex];

			for (varIndex in vars) {
			    variable = vars[varIndex];

			    if (variable.aspect == "SLOT" && variable.handler) {
					try {
					    variable.handler(variable.value);
					} catch (e) {
					}
			    }
			}

	    }
	}

	VarManager.prototype.findVariableInCollection = function(varCollection, id){
		for (var i = 0; i < varCollection.length; i++){
			var modVar = varCollection[i];

			if (modVar.id == id) {
				return modVar
			}
		}
		return null;
	}

	VarManager.prototype.markVariablesAsModified = function (variables) {
		if (this.modificationsEnabled) {
			var varCollection;

			for (var j = 0; j < variables.length; j++) {
				var variable = variables[j];

				// Is it a igadgetVar or a workspaceVar?
				if (variable.aspect == Variable.prototype.INOUT ||
				variable.aspect == Variable.prototype.TAB) {
					varCollection = this.workspaceModifiedVars;
				}
				else {
					varCollection = this.igadgetModifiedVars;
				}

				var modVar = this.findVariableInCollection(varCollection, variable.id)
				if (modVar) {
					modVar.value = variable.value;
					return;
				}

				//It's doesn't exist in the list
				//It's time to create it!
				var varInfo = {}

				varInfo['id'] = variable.id
				varInfo['value'] = variable.value
				if (variable.shared != null) { //it is a possible shared variable
					varInfo['shared'] = variable.shared
				}

				varCollection.push(varInfo);
			}
		}

	}

	VarManager.prototype.incNestingLevel = function() {
		if (this.modificationsEnabled)
	    	this.nestingLevel++;
	}

	VarManager.prototype.decNestingLevel = function() {
		if (this.modificationsEnabled) {
			this.nestingLevel--;
			if (this.nestingLevel == 0)
				this.commitModifiedVariables();
		}
	}

	VarManager.prototype.resetModifiedVariables = function () {
	    this.nestingLevel = 0;
	    this.buffered_requests = 0;
	    this.igadgetModifiedVars = [];
	    this.workspaceModifiedVars = [];
		this.force_commit = false;
	}

	VarManager.prototype.forceCommit = function(){
		if (this.modificationsEnabled){
			this.force_commit = true;
		}
	}

	VarManager.prototype.getVariableById = function (varId) {
		return this.variables[varId];
	}

	VarManager.prototype.getVariableByName = function (igadgetId, varName) {
		return this.findVariable(igadgetId, varName);
	}

	VarManager.prototype.getWorkspace = function () {
		return this.workSpace;
	}

	// *********************************
	// PRIVATE VARIABLES AND CONSTRUCTOR
	// *********************************

	VarManager.prototype.findVariable = function (iGadgetId, name) {
		var variables = this.iGadgets[iGadgetId];
		var variable = variables[name];

		return variable;
	}

	this.workSpace = _workSpace;
	this.iGadgets = new Hash();
	this.variables = new Hash();

	// For now workspace variables must be in a separated hash table, because they have a
	// different identifier space and can collide with the idenfiers of normal variables
	this.workspaceVariables = new Hash();

	this.igadgetModifiedVars = []
	this.workspaceModifiedVars = []

	this.nestingLevel = 0;

	this.buffered_requests = 0;

	this.force_commit = false;

	this.modificationsEnabled = true;

	this.pendingVariables = new Hash(); //to manage igadgets loaded on demand caused by a wiring propagation

	// Creation of ALL EzWeb variables regarding one workspace
	this.parseVariables(this.workSpace.workSpaceGlobalInfo);
}
<commit_msg>refs #690. Fixed error saving variables into persistence when using chrome.<commit_after>/*
*     (C) Copyright 2008 Telefonica Investigacion y Desarrollo
*     S.A.Unipersonal (Telefonica I+D)
*
*     This file is part of Morfeo EzWeb Platform.
*
*     Morfeo EzWeb Platform is free software: you can redistribute it and/or modify
*     it under the terms of the GNU Affero General Public License as published by
*     the Free Software Foundation, either version 3 of the License, or
*     (at your option) any later version.
*
*     Morfeo EzWeb Platform is distributed in the hope that it will be useful,
*     but WITHOUT ANY WARRANTY; without even the implied warranty of
*     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*     GNU Affero General Public License for more details.
*
*     You should have received a copy of the GNU Affero General Public License
*     along with Morfeo EzWeb Platform.  If not, see <http://www.gnu.org/licenses/>.
*
*     Info about members and contributors of the MORFEO project
*     is available at
*
*     http://morfeo-project.org
 */

function VarManager (_workSpace) {

	VarManager.prototype.MAX_BUFFERED_REQUESTS = 10

	// ****************
	// PUBLIC METHODS
	// ****************

	VarManager.prototype.parseVariables = function (workSpaceInfo) {
		// Igadget variables!
		var tabs = workSpaceInfo['workspace']['tabList'];

		for (var i=0; i<tabs.length; i++) {
			var igadgets = tabs[i]['igadgetList'];

			for (var j=0; j<igadgets.length; j++) {
				this.parseIGadgetVariables(igadgets[j], this.workSpace.getTabInstance(tabs[i].id));
			}
		}

		// Workspace variables (Connectables and future variables!)
		var ws_vars = workSpaceInfo['workspace']['workSpaceVariableList'];

		this.parseWorkspaceVariables(ws_vars);
	}

	VarManager.prototype.parseWorkspaceVariables = function (ws_vars) {
		for (var i = 0; i<ws_vars.length; i++) {
			this.parseWorkspaceVariable(ws_vars[i]);
		}
	}

	VarManager.prototype.sendBufferedVars = function () {
		// Asynchronous handlers
		function onSuccess(transport) {
			var response = transport.responseText;
			var modifiedVariables = JSON.parse(response);
			var igadgetVars = modifiedVariables['igadgetVars']
			this.modificationsEnabled = false; //lock the adding of modified variables to the buffer
			for (var i=0;i<igadgetVars.length;i++){
				var id = igadgetVars[i].id;
				var variable = this.getVariableById(id);
				variable.annotate(igadgetVars[i].value)
			}
			for (var i=0;i<igadgetVars.length;i++){
				var id = igadgetVars[i].id;
				var variable = this.getVariableById(id);
				variable.set(igadgetVars[i].value) //set will not add the variable to the modified variables to be sent due to the 'disableModifications'
			}
			this.modificationsEnabled = true; //unlock the adding of modified variables to the buffer
		}

		function onError(transport, e) {
			var logManager = LogManagerFactory.getInstance();
			var msg = logManager.formatError(gettext("Error saving variables to persistence: %(errorMsg)s."), transport, e);
			logManager.log(msg);
		}

		// Max lenght of buffered requests have been reached. Uploading to server!
		if (this.igadgetModifiedVars.length > 0 || this.workspaceModifiedVars.length > 0) {
			var variables = {};

			variables['igadgetVars'] = this.igadgetModifiedVars;
			variables['workspaceVars'] = this.workspaceModifiedVars;

			var uri = URIs.PUT_VARIABLES.evaluate({workspaceId: this.workSpace.getId()});

			var options = {
				method: 'PUT',
				contentType: 'application/json',
				postBody: Object.toJSON(variables),
				onSuccess: onSuccess.bind(this),
				onFailure: onError.bind(this),
				onException: onError.bind(this)
			};
			PersistenceEngineFactory.getInstance().send(uri, options);
			this.resetModifiedVariables();
		}
	}

	VarManager.prototype.parseWorkspaceVariable = function (ws_var) {
		var id = ws_var.id;
		var name = ws_var.name;
		var aspect = ws_var.aspect;
		var value = ws_var.value;

		switch (aspect) {
			case Variable.prototype.INOUT:
				this.workspaceVariables[id] = new RWVariable(id, null, name, aspect, this, value);
				break;
			case Variable.prototype.TAB:
				this.workspaceVariables[id] = new RVariable(id, null, name, aspect, this, value);
				break;
		}
	}

	VarManager.prototype.removeWorkspaceVariable = function (ws_varId) {
		delete this.workspaceVariables[ws_varId];
		this.workspaceModifiedVars.removeById(ws_varId);
	}

	VarManager.prototype.parseIGadgetVariables = function (igadget, tab) {
		var igadgetVars = igadget['variables'];
		var objVars = []
		for (var i = 0; i<igadgetVars.length; i++) {
			var id = igadgetVars[i].id;
			var igadgetId = igadgetVars[i].igadgetId;
			var name = igadgetVars[i].name;
			var label = igadgetVars[i].label;
			var aspect = igadgetVars[i].aspect;
			var value = igadgetVars[i].value;
			var shared = igadgetVars[i].shared;

			switch (aspect) {
				case Variable.prototype.PROPERTY:
				case Variable.prototype.EVENT:
					objVars[name] = new RWVariable(id, igadgetId, name, aspect, this, value, label, tab, shared);
					this.variables[id] = objVars[name];
					break;
				case Variable.prototype.EXTERNAL_CONTEXT:
				case Variable.prototype.GADGET_CONTEXT:
				case Variable.prototype.SLOT:
				case Variable.prototype.USER_PREF:
					objVars[name] = new RVariable(id, igadgetId, name, aspect, this, value, label, tab, shared);
					this.variables[id] = objVars[name];
					break;
			}
		}

		this.iGadgets[igadget['id']] = objVars;

	}

	VarManager.prototype.registerVariable = function (iGadgetId, variableName, handler) {
		var variable = this.findVariable(iGadgetId, variableName);

		if (variable) {
			variable.setHandler(handler);
		} else {
			var transObj = {iGadgetId: iGadgetId, varName: variableName};
			var msg = interpolate(gettext("IGadget %(iGadgetId)s does not have any variable named \"%(varName)s\".\nIf you need it, please insert it into the gadget's template."), transObj, true);
			OpManagerFactory.getInstance().logIGadgetError(iGadgetId, msg, Constants.Logging.ERROR_MSG);
		}
	}

	VarManager.prototype.assignEventConnectable = function (iGadgetId, variableName, wEvent) {
		var variable = this.findVariable(iGadgetId, variableName);
		variable.assignEvent(wEvent);
	}

	VarManager.prototype.getVariable = function (iGadgetId, variableName) {
		var variable = this.findVariable(iGadgetId, variableName);

		// Error control

		return variable.get();
	}

	VarManager.prototype.setVariable = function (iGadgetId, variableName, value) {
		if (typeof(value) !== 'string') {
			var transObj = {iGadgetId: iGadgetId, varName: variableName};
			var msg = interpolate(gettext("IGadget %(iGadgetId)s attempted to establish a non-string value for the variable \"%(varName)s\"."), transObj, true);
			OpManagerFactory.getInstance().logIGadgetError(iGadgetId, msg, Constants.Logging.ERROR_MSG);

			throw new Error();
		}

		var variable = this.findVariable(iGadgetId, variableName);

		variable.set(value);
	}

	VarManager.prototype.addPendingVariable = function (iGadgetId, variableName, value) {
		var variables = this.pendingVariables[iGadgetId];
		if (!variables){
			this.pendingVariables[iGadgetId] = new Array();
			variables = this.pendingVariables[iGadgetId];
		}
		variables.push({"name":variableName, "value":value});
	}

	VarManager.prototype.dispatchPendingVariables = function (iGadgetId) {
		var variables = this.pendingVariables.remove(iGadgetId);
		if (variables){
			for (var i=0;i<variables.length;i++){
				this.setVariable(iGadgetId, variables[i]["name"], variables[i]["value"]);
			}
		}
	}

	VarManager.prototype.addInstance = function (iGadget, igadgetInfo, tab) {
		this.parseIGadgetVariables(igadgetInfo, tab);
	}

	VarManager.prototype.removeInstance = function (iGadgetId) {
		delete this.iGadgets[iGadgetId];

		this.removeIGadgetVariables(iGadgetId);
	}

	VarManager.prototype.removeIGadgetVariables = function (iGadgetId) {
		var variables_ids = this.variables.keys()

		for (var i=0; i<variables_ids.length; i++) {
			if (this.variables[variables_ids[i]].iGadget == iGadgetId) {
				this.igadgetModifiedVars.removeById(variables_ids[i]);
				delete this.variables[variables_ids[i]];
			}
		}
	}

	VarManager.prototype.unload = function () {
	}

	VarManager.prototype.commitModifiedVariables = function() {
		//If it have not been buffered all the requests, it's not time to send a PUT request
		if (!this.force_commit && this.buffered_requests < VarManager.prototype.MAX_BUFFERED_REQUESTS) {
			this.buffered_requests++;
			return
		}

		this.sendBufferedVars();
	}

	VarManager.prototype.createWorkspaceVariable = function(name) {
		var provisional_id = new Date().getTime();

		return new RWVariable(provisional_id, null, name, Variable.prototype.INOUT, this, "");

	}

	VarManager.prototype.addWorkspaceVariable = function(id, variable) {
		this.workspaceVariables[id] = variable;
	}

	VarManager.prototype.getWorkspaceVariableById = function(varId) {
		return this.workspaceVariables[varId];
	}

	VarManager.prototype.initializeInterface = function () {
	    // Calling all SLOT vars handler
	    var variable;
	    var vars;
	    var varIndex;
	    var gadgetIndex;

	    for (gadgetIndex in this.iGadgets) {
		vars = this.iGadgets[gadgetIndex];

			for (varIndex in vars) {
			    variable = vars[varIndex];

			    if (variable.aspect == "SLOT" && variable.handler) {
					try {
					    variable.handler(variable.value);
					} catch (e) {
					}
			    }
			}

	    }
	}

	VarManager.prototype.findVariableInCollection = function(varCollection, id){
		for (var i = 0; i < varCollection.length; i++){
			var modVar = varCollection[i];

			if (modVar.id == id) {
				return modVar
			}
		}
		return null;
	}

	VarManager.prototype.markVariablesAsModified = function (variables) {
		if (this.modificationsEnabled) {
			var varCollection;

			for (var j = 0; j < variables.length; j++) {
				var variable = variables[j];

				// Is it a igadgetVar or a workspaceVar?
				if (variable.aspect == Variable.prototype.INOUT ||
				variable.aspect == Variable.prototype.TAB) {
					varCollection = this.workspaceModifiedVars;
				}
				else {
					varCollection = this.igadgetModifiedVars;
				}

				var modVar = this.findVariableInCollection(varCollection, variable.id)
				if (modVar) {
					modVar.value = variable.value;
					return;
				}

				//It's doesn't exist in the list
				//It's time to create it!
				var varInfo = {}

				varInfo['id'] = variable.id
				varInfo['value'] = variable.value
				if (variable.shared != null) { //it is a possible shared variable
					varInfo['shared'] = variable.shared
				}

				varCollection.push(varInfo);
			}
		}

	}

	VarManager.prototype.incNestingLevel = function() {
		if (this.modificationsEnabled)
	    	this.nestingLevel++;
	}

	VarManager.prototype.decNestingLevel = function() {
		if (this.modificationsEnabled) {
			this.nestingLevel--;
			if (this.nestingLevel == 0)
				this.commitModifiedVariables();
		}
	}

	VarManager.prototype.resetModifiedVariables = function () {
	    this.nestingLevel = 0;
	    this.buffered_requests = 0;
	    this.igadgetModifiedVars = [];
	    this.workspaceModifiedVars = [];
		this.force_commit = false;
	}

	VarManager.prototype.forceCommit = function(){
		if (this.modificationsEnabled){
			this.force_commit = true;
		}
	}

	VarManager.prototype.getVariableById = function (varId) {
		return this.variables[varId];
	}

	VarManager.prototype.getVariableByName = function (igadgetId, varName) {
		return this.findVariable(igadgetId, varName);
	}

	VarManager.prototype.getWorkspace = function () {
		return this.workSpace;
	}

	// *********************************
	// PRIVATE VARIABLES AND CONSTRUCTOR
	// *********************************

	VarManager.prototype.findVariable = function (iGadgetId, name) {
		var variables = this.iGadgets[iGadgetId];
		var variable = variables[name];

		return variable;
	}

	this.workSpace = _workSpace;
	this.iGadgets = new Hash();
	this.variables = new Hash();

	// For now workspace variables must be in a separated hash table, because they have a
	// different identifier space and can collide with the idenfiers of normal variables
	this.workspaceVariables = new Hash();

	this.igadgetModifiedVars = []
	this.workspaceModifiedVars = []

	this.nestingLevel = 0;

	this.buffered_requests = 0;

	this.force_commit = false;

	this.modificationsEnabled = true;

	this.pendingVariables = new Hash(); //to manage igadgets loaded on demand caused by a wiring propagation

	// Creation of ALL EzWeb variables regarding one workspace
	this.parseVariables(this.workSpace.workSpaceGlobalInfo);
}
<|endoftext|>


<commit_before>// Universal Subtitles, universalsubtitles.org
//
// Copyright (C) 2010 Participatory Culture Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see
// http://www.gnu.org/licenses/agpl-3.0.html.

goog.provide('mirosubs.widget.droplockdialog.Dialog');

/**
 * @constructor
 * @param {string} videoID
*/
mirosubs.widget.droplockdialog.Dialog = function(secondsUntilWarning,  secondsUntilFreeze, eventNode){
    goog.ui.Dialog.call(this, 'mirosubs-modal-lang', true);
    this.setButtonSet(null);
    this.setDisposeOnHide(true);
    /*
     * @type {int}
     */
    this.secondsUntilFreeze_ = secondsUntilFreeze;
    /*
     * @type {int}
     */
    this.initialSecondsUntilFreeze_ = secondsUntilFreeze;
    /*
     * @type {int}
     */
    this.secondsUntilWarning_ = secondsUntilWarning;

    this.warningTimer_ = null;
    // we reset our timer on any inactivity,
    // mouse event or keyboard press
    this.inputHandler_ = new goog.events.InputHandler(eventNode);
    goog.events.listen(this.inputHandler_, goog.events.InputHandler.EventType.INPUT,
                   goog.bind(this.startLockoutTimer_, this));
    goog.events.listen(eventNode, "mousemove",
                   goog.bind(this.startLockoutTimer_, this));
    // create proper ENUM for this
    this.state = 'IDLE';
    this.startLockoutTimer_();
    // TODO: dispose events
};

goog.inherits(mirosubs.widget.droplockdialog.Dialog, goog.ui.Dialog);

mirosubs.widget.droplockdialog.Dialog.prototype.reset_ = function (){
    this.startLockoutTimer_();
    this.setVisible(false);
    this.state = 'IDLE';
}

/* Starts the timer for dropping the lock on this editing session, if
 * called multiple times will properly clear the old timer and start a new one.
 */
mirosubs.widget.droplockdialog.Dialog.prototype.startLockoutTimer_ = function (){
    if (this.idleTimer_){
        this.idleTimer_.stop();
    }else{
        // TODO: should we use a goog.ui.IdleTimer instead of our own idleTimer?
        this.idleTimer_ = new goog.Timer(this.secondsUntilWarning_ * 1000);
        goog.events.listen(this.idleTimer_, goog.Timer.TICK,
                           goog.bind(this.showWarning_, this));
    }
    this.idleTimer_.start();

};

mirosubs.widget.droplockdialog.Dialog.prototype.createWarningDom = function() {
    // TODOS: layout issues
    var $d = goog.bind(this.getDomHelper().createDom,
                       this.getDomHelper());
    var el = this.getElement();
    goog.dom.removeChildren(el);
    el.appendChild(
        $d('h3', null, 'Warning, idle'));
    this.contentDiv_ = $d('div', null);
    var pText = "Warning: you've been idle for "
        + this.toMinutes(this.secondsUntilWarning_)
        + ' minutes.  To give other users a chance to help, we will close your session in ';
    this.timeRemainingSpan_ = $d( "span", "remaining-minutes");
    var p = $d( "p", null, pText, this.timeRemainingSpan_);

    //p.appendChild(this.timeRemainingSpan_);
    this.contentDiv_.appendChild(p);

    this.contentDiv_.appendChild(this.timeRemainingSpan_);
    goog.dom.append(this.contentDiv_, ".");

    el.appendChild(this.contentDiv_);
    this.backToEditingButton_ =
        $d('a',
           {'href':'#',
            'className': "mirosubs-green-button mirosubs-big"},
           'Nope! Get me back to subtitling');
   goog.events.listen(this.backToEditingButton_, "click",
                     goog.bind(this.onBackToEditing_, this));
   el.appendChild( this.backToEditingButton_);
    this.state = 'WARNINING';
};

mirosubs.widget.droplockdialog.Dialog.prototype.createDom = function() {
    mirosubs.startdialog.Dialog.superClass_.createDom.call(this);
    this.createWarningDom();

};

mirosubs.widget.droplockdialog.Dialog.prototype.showWarning_ = function(e){
    // TODOS: layout issues
    if (this.state != 'IDLE'){
        return;
    }
    this.idleTimer_.disposeInternal();
    this.idleTimer_ = null;
    this.warningTimer_ = new goog.Timer(1000);

    goog.events.listen(this.warningTimer_, goog.Timer.TICK,
                       goog.bind(this.onUpdateTimeDisplay_, this));
    this.warningTimer_.start();
    this.setVisible(true);
    this.state_ = "WARNING";
    this.secondsUntilFreeze_ = this.initialSecondsUntilFreeze_;
    this.onUpdateTimeDisplay_();
};

mirosubs.widget.droplockdialog.Dialog.prototype.createLockDroppedDom_ = function(e){
        var $d = goog.bind(this.getDomHelper().createDom,
                           this.getDomHelper());
    var el = this.getElement();
    goog.dom.removeChildren(el);
    el.appendChild(
        $d('h3', null, 'Warning, idle'));
    this.contentDiv_ = $d('div', null);
    var p = $d("p", null, "Since you were idle for " +
               this.toMinutes( this.secondsUntilWarning_)
               + " minutes, we've closed your subtitling session so that other users can work on this video.\n\n" +
               "If there was work you don't want to loose, ");

    this.downloadWorkButton_ = $d("a", "inline-download-subs", "download subtitles here.");
    goog.dom.setProperties(this.downloadWorkButton_, {"href":"#"});
    goog.dom.appendChild(p, this.downloadWorkButton_);
    goog.events.listen(this.downloadWorkButton_, 'click', goog.bind(this.onDownloadWorkClicked, this));

    //goog.dom.setTextContent(this.backToEditingButton_, "I want to get back to editing");

    this.closeButton_ =
        $d('a',
           {'href':'#',
            'className': "mirosubs-green-button mirosubs-big"},
           "Ok, I'm done");
    goog.events.listen(this.closeButton_, "click",
                       goog.bind(this.onCloseClicked_, this));
    goog.dom.appendChild(this.contentDiv_, $d("div", "clearfix"));

    goog.dom.appendChild(this.contentDiv_, p );

    el.appendChild(this.contentDiv_);
    goog.dom.appendChild(el, this.closeButton_);
    goog.dom.appendChild(el, this.backToEditingButton_);

};

mirosubs.widget.droplockdialog.Dialog.prototype.onUpdateTimeDisplay_ = function(e){

    if (this.timeRemainingSpan_){
        goog.dom.setTextContent(this.timeRemainingSpan_, this.secondsUntilFreeze_ + " seconds");
        this.secondsUntilFreeze_  -= 1;
        if (this.secondsUntilFreeze_ === 0){
            this.warningTimer_.stop();
            this.warningTimer_.disposeInternal();
            this.dispatchEvent(new mirosubs.widget.droplockdialog.SessionIdleEvent(this));
            this.createLockDroppedDom_();
            this.state = "DROPPED";
        }
    }

}

mirosubs.widget.droplockdialog.Dialog.prototype.onCloseClicked_ = function(e){
    e.preventDefault();
    this.dispatchEvent(new goog.events.Event("close", this));
    this.setVisible(false);
};

mirosubs.widget.droplockdialog.Dialog.prototype.onDownloadWorkClicked = function(e) {
    e.preventDefault();
    this.dispatchEvent(new mirosubs.widget.droplockdialog.DownloadRequestEvent (this));
    this.downloadPanel_ = new mirosubs.finishfaildialog.ErrorPanel(this.logger_);
};

mirosubs.widget.droplockdialog.Dialog.prototype.toMinutes = function(seconds) {
    return Math.ceil(seconds / 60);
}

mirosubs.widget.droplockdialog.Dialog.prototype.enterDocument = function() {
    mirosubs.widget.droplockdialog.Dialog.superClass_.enterDocument.call(this);
    //this.connectEvents_();
};

mirosubs.widget.droplockdialog.Dialog.prototype.onBackToEditing_ = function(e){
    this.warningTimer_.disposeInternal();
    this.dispatchEvent(new mirosubs.widget.droplockdialog.SessionResumedEvent(this));
    this.reset_();
    this.setVisible(false);
}

mirosubs.widget.droplockdialog.Dialog.SESSION_IDDLE = "SESSION_IDLE";
/**
* @constructor
* @param dialog {type} mirosubs.widget.droplockdialog.Dialog
*/
mirosubs.widget.droplockdialog.SessionIdleEvent = function(dialog) {
    this.type = mirosubs.widget.droplockdialog.Dialog.SESSION_IDDLE;
    this.dialog = dialog;
};

mirosubs.widget.droplockdialog.Dialog.SESSION_RESUMED = "SESSION_RESUMED";
/**
* @constructor
* @param dialog {type} mirosubs.widget.droplockdialog.Dialog
*/
mirosubs.widget.droplockdialog.SessionResumedEvent = function(dialog) {
    this.type = mirosubs.widget.droplockdialog.Dialog.SESSION_RESUMED;
    this.dialog = dialog;
};

mirosubs.widget.droplockdialog.Dialog.DOWNLOAD_REQUESTED = "DOWNLOAD_REQUESTED";
/**
* @constructor
* @param dialog {type} mirosubs.widget.droplockdialog.Dialog
*/
mirosubs.widget.droplockdialog.DownloadRequestEvent = function(dialog) {
    this.type = mirosubs.widget.droplockdialog.Dialog.DOWNLOAD_REQUESTED;
    this.dialog = dialog;
};
<commit_msg>Fixed typo on lock dialog, for https://www.pivotaltracker.com/story/show/14646611<commit_after>// Universal Subtitles, universalsubtitles.org
//
// Copyright (C) 2010 Participatory Culture Foundation
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see
// http://www.gnu.org/licenses/agpl-3.0.html.

goog.provide('mirosubs.widget.droplockdialog.Dialog');

/**
 * @constructor
 * @param {string} videoID
*/
mirosubs.widget.droplockdialog.Dialog = function(secondsUntilWarning,  secondsUntilFreeze, eventNode){
    goog.ui.Dialog.call(this, 'mirosubs-modal-lang', true);
    this.setButtonSet(null);
    this.setDisposeOnHide(true);
    /*
     * @type {int}
     */
    this.secondsUntilFreeze_ = secondsUntilFreeze;
    /*
     * @type {int}
     */
    this.initialSecondsUntilFreeze_ = secondsUntilFreeze;
    /*
     * @type {int}
     */
    this.secondsUntilWarning_ = secondsUntilWarning;

    this.warningTimer_ = null;
    // we reset our timer on any inactivity,
    // mouse event or keyboard press
    this.inputHandler_ = new goog.events.InputHandler(eventNode);
    goog.events.listen(this.inputHandler_, goog.events.InputHandler.EventType.INPUT,
                   goog.bind(this.startLockoutTimer_, this));
    goog.events.listen(eventNode, "mousemove",
                   goog.bind(this.startLockoutTimer_, this));
    // create proper ENUM for this
    this.state = 'IDLE';
    this.startLockoutTimer_();
    // TODO: dispose events
};

goog.inherits(mirosubs.widget.droplockdialog.Dialog, goog.ui.Dialog);

mirosubs.widget.droplockdialog.Dialog.prototype.reset_ = function (){
    this.startLockoutTimer_();
    this.setVisible(false);
    this.state = 'IDLE';
}

/* Starts the timer for dropping the lock on this editing session, if
 * called multiple times will properly clear the old timer and start a new one.
 */
mirosubs.widget.droplockdialog.Dialog.prototype.startLockoutTimer_ = function (){
    if (this.idleTimer_){
        this.idleTimer_.stop();
    }else{
        // TODO: should we use a goog.ui.IdleTimer instead of our own idleTimer?
        this.idleTimer_ = new goog.Timer(this.secondsUntilWarning_ * 1000);
        goog.events.listen(this.idleTimer_, goog.Timer.TICK,
                           goog.bind(this.showWarning_, this));
    }
    this.idleTimer_.start();

};

mirosubs.widget.droplockdialog.Dialog.prototype.createWarningDom = function() {
    // TODOS: layout issues
    var $d = goog.bind(this.getDomHelper().createDom,
                       this.getDomHelper());
    var el = this.getElement();
    goog.dom.removeChildren(el);
    el.appendChild(
        $d('h3', null, 'Warning, idle'));
    this.contentDiv_ = $d('div', null);
    var pText = "Warning: you've been idle for "
        + this.toMinutes(this.secondsUntilWarning_)
        + ' minutes.  To give other users a chance to help, we will close your session in ';
    this.timeRemainingSpan_ = $d( "span", "remaining-minutes");
    var p = $d( "p", null, pText, this.timeRemainingSpan_);

    //p.appendChild(this.timeRemainingSpan_);
    this.contentDiv_.appendChild(p);

    this.contentDiv_.appendChild(this.timeRemainingSpan_);
    goog.dom.append(this.contentDiv_, ".");

    el.appendChild(this.contentDiv_);
    this.backToEditingButton_ =
        $d('a',
           {'href':'#',
            'className': "mirosubs-green-button mirosubs-big"},
           'Nope! Get me back to subtitling');
   goog.events.listen(this.backToEditingButton_, "click",
                     goog.bind(this.onBackToEditing_, this));
   el.appendChild( this.backToEditingButton_);
    this.state = 'WARNINING';
};

mirosubs.widget.droplockdialog.Dialog.prototype.createDom = function() {
    mirosubs.startdialog.Dialog.superClass_.createDom.call(this);
    this.createWarningDom();

};

mirosubs.widget.droplockdialog.Dialog.prototype.showWarning_ = function(e){
    // TODOS: layout issues
    if (this.state != 'IDLE'){
        return;
    }
    this.idleTimer_.disposeInternal();
    this.idleTimer_ = null;
    this.warningTimer_ = new goog.Timer(1000);

    goog.events.listen(this.warningTimer_, goog.Timer.TICK,
                       goog.bind(this.onUpdateTimeDisplay_, this));
    this.warningTimer_.start();
    this.setVisible(true);
    this.state_ = "WARNING";
    this.secondsUntilFreeze_ = this.initialSecondsUntilFreeze_;
    this.onUpdateTimeDisplay_();
};

mirosubs.widget.droplockdialog.Dialog.prototype.createLockDroppedDom_ = function(e){
        var $d = goog.bind(this.getDomHelper().createDom,
                           this.getDomHelper());
    var el = this.getElement();
    goog.dom.removeChildren(el);
    el.appendChild(
        $d('h3', null, 'Warning, idle'));
    this.contentDiv_ = $d('div', null);
    var p = $d("p", null, "Since you were idle for " +
               this.toMinutes( this.secondsUntilWarning_)
               + " minutes, we've closed your subtitling session so that other users can work on this video.\n\n" +
               "If there was work you don't want to lose, ");

    this.downloadWorkButton_ = $d("a", "inline-download-subs", "download subtitles here.");
    goog.dom.setProperties(this.downloadWorkButton_, {"href":"#"});
    goog.dom.appendChild(p, this.downloadWorkButton_);
    goog.events.listen(this.downloadWorkButton_, 'click', goog.bind(this.onDownloadWorkClicked, this));

    //goog.dom.setTextContent(this.backToEditingButton_, "I want to get back to editing");

    this.closeButton_ =
        $d('a',
           {'href':'#',
            'className': "mirosubs-green-button mirosubs-big"},
           "Ok, I'm done");
    goog.events.listen(this.closeButton_, "click",
                       goog.bind(this.onCloseClicked_, this));
    goog.dom.appendChild(this.contentDiv_, $d("div", "clearfix"));

    goog.dom.appendChild(this.contentDiv_, p );

    el.appendChild(this.contentDiv_);
    goog.dom.appendChild(el, this.closeButton_);
    goog.dom.appendChild(el, this.backToEditingButton_);

};

mirosubs.widget.droplockdialog.Dialog.prototype.onUpdateTimeDisplay_ = function(e){

    if (this.timeRemainingSpan_){
        goog.dom.setTextContent(this.timeRemainingSpan_, this.secondsUntilFreeze_ + " seconds");
        this.secondsUntilFreeze_  -= 1;
        if (this.secondsUntilFreeze_ === 0){
            this.warningTimer_.stop();
            this.warningTimer_.disposeInternal();
            this.dispatchEvent(new mirosubs.widget.droplockdialog.SessionIdleEvent(this));
            this.createLockDroppedDom_();
            this.state = "DROPPED";
        }
    }

}

mirosubs.widget.droplockdialog.Dialog.prototype.onCloseClicked_ = function(e){
    e.preventDefault();
    this.dispatchEvent(new goog.events.Event("close", this));
    this.setVisible(false);
};

mirosubs.widget.droplockdialog.Dialog.prototype.onDownloadWorkClicked = function(e) {
    e.preventDefault();
    this.dispatchEvent(new mirosubs.widget.droplockdialog.DownloadRequestEvent (this));
    this.downloadPanel_ = new mirosubs.finishfaildialog.ErrorPanel(this.logger_);
};

mirosubs.widget.droplockdialog.Dialog.prototype.toMinutes = function(seconds) {
    return Math.ceil(seconds / 60);
}

mirosubs.widget.droplockdialog.Dialog.prototype.enterDocument = function() {
    mirosubs.widget.droplockdialog.Dialog.superClass_.enterDocument.call(this);
    //this.connectEvents_();
};

mirosubs.widget.droplockdialog.Dialog.prototype.onBackToEditing_ = function(e){
    this.warningTimer_.disposeInternal();
    this.dispatchEvent(new mirosubs.widget.droplockdialog.SessionResumedEvent(this));
    this.reset_();
    this.setVisible(false);
}

mirosubs.widget.droplockdialog.Dialog.SESSION_IDDLE = "SESSION_IDLE";
/**
* @constructor
* @param dialog {type} mirosubs.widget.droplockdialog.Dialog
*/
mirosubs.widget.droplockdialog.SessionIdleEvent = function(dialog) {
    this.type = mirosubs.widget.droplockdialog.Dialog.SESSION_IDDLE;
    this.dialog = dialog;
};

mirosubs.widget.droplockdialog.Dialog.SESSION_RESUMED = "SESSION_RESUMED";
/**
* @constructor
* @param dialog {type} mirosubs.widget.droplockdialog.Dialog
*/
mirosubs.widget.droplockdialog.SessionResumedEvent = function(dialog) {
    this.type = mirosubs.widget.droplockdialog.Dialog.SESSION_RESUMED;
    this.dialog = dialog;
};

mirosubs.widget.droplockdialog.Dialog.DOWNLOAD_REQUESTED = "DOWNLOAD_REQUESTED";
/**
* @constructor
* @param dialog {type} mirosubs.widget.droplockdialog.Dialog
*/
mirosubs.widget.droplockdialog.DownloadRequestEvent = function(dialog) {
    this.type = mirosubs.widget.droplockdialog.Dialog.DOWNLOAD_REQUESTED;
    this.dialog = dialog;
};
<|endoftext|>


<commit_before>require('ts-node/register');
exports.config = {
  baseUrl: 'http://127.0.0.1:14525/',

  specs: [
    'src/**/*.e2e.ts'
  ],
  exclude: [],

  framework: 'mocha',

  allScriptsTimeout: 110000,

  directConnect: true,

  capabilities: {
    'browserName': 'chrome',
    'chromeOptions': {
      args: ['--disable-web-security']
    }
  },

  onPrepare: function() {
    browser.ignoreSynchronization = true;
  }
};
<commit_msg>Add config<commit_after>require('ts-node/register');
exports.config = {
  baseUrl: 'http://127.0.0.1:14525/',
  seleniumAddress: 'http://127.0.0.1:4723/wd/hub',

  specs: [
    'src/**/*.e2e.ts'
  ],
  exclude: [],

  framework: 'mocha',

  allScriptsTimeout: 110000,

  directConnect: true,

  capabilities: {
    'browserName': 'chrome',
    'deviceName' : 'Android Emulator',
    'chromeOptions': {
      args: ['--disable-web-security'],
    }
  },

  onPrepare: function() {
    browser.ignoreSynchronization = true;
  }
};
<|endoftext|>


<commit_before>(function($, Proud) {

  // Proudnav
  var proudNav = (function() {

    var layerOpen = {
      menu: false,
      search: false,
      answers: false,
    },
    layerClasses = {
      'menu': 'menu-nav-open',
      'search': 'search-active',
      'answers': 'active-311'
    },
    $body,
    self = {};

    // Closes overlays + menus
    // localLayers = ['menu', 'search']
    self.closeLayers = function(localLayers, callback) {
      // Default is all
      localLayers = localLayers || _.keys(layerOpen);
      var classes = [];
      _.map(localLayers, function(layer) {
        classes.push(layerClasses[layer]);
        layerOpen[layer] = false;
      });
      // Remove
      $body.removeClass(classes.join(' '));
      if(callback) {
        callback();
      }
    };

    // Closes overlays + menus
    self.openLayer = function(layer, callback) {
      setTimeout(function() {
        $body.addClass(layerClasses[layer]);
        layerOpen[layer] = true;
        $body.trigger('scroll');
        if(callback) {
          callback();
        }
      }, 50);
    };

    self.toggleMenu = function() {
      // Just close everything
      if(layerOpen.menu) {
        self.closeLayers();
        return;
      }
      else {
        self.closeLayers(['answers', 'search']);
        self.openLayer('menu');
      }
    };

    self.toggleOverlay = function(item, callback) {
      var thisLayer, otherLayer;
      switch(item) {
        case 'answers':
        case 'payments':
        case 'report':
        case 'status':
          thisLayer = 'answers';
          otherLayer = 'search';
          break;

        case 'search':
          thisLayer = 'search';
          otherLayer = 'answers';
          break;
      }

      // Close all
      if(layerOpen[thisLayer]) {
        self.closeLayers(null, callback);
      }
      else {
        // Close others, open ours
        self.closeLayers([otherLayer, 'menu'], callback);
        self.openLayer(thisLayer, callback);
      }
    };

    self.triggerOverlay = function(data, hash, classOverride) {
      if(classOverride) {
        layerClasses[data] = classOverride;
      }

      $body.trigger({
        type:     "proudNavClick",
        event:    data,
        hash:     hash,
        callback: function(open, scrollId, scrollOffset, forceClose, callback) {
          // Scrollto id
          if(scrollId) {
            var $scroll = $("#" + scrollId),
                scrollOffset = scrollOffset || 0,
                offset = $body.hasClass('proud-toolbar-active') ? 150 : 100;
            if($scroll.length) {
              $('html, body').animate({
                  scrollTop: $scroll.offset().top - (offset + scrollOffset)
              }, 200);
            }
          }
          // Oper layer
          if(open) {
            self.toggleOverlay(data, callback);
          }
          // Force close layers
          if(forceClose) {
            self.closeLayers(forceClose, callback);
          }
        }
      });
    };

    $(document).ready(function() {
      $body = $('body');
    })

    return self;
  })();

  Proud.proudNav = proudNav;

  Proud.behaviors.proudNavbar = { attach: function(context, settings) {

    // Click top buttons
    $('[data-proud-navbar]').once('proud-navbar', function() {
      var $self = $(this);
      $self.click(function(e) {
        e.preventDefault();
        var data = $self.data('proud-navbar');

        if(data) {
          proudNav.triggerOverlay(data, $self.data('proud-navbar-hash'));
        }
      });
    });

    // mobile menu open
    $('#menu-button').once('proud-navbar', function() {
      $(this).click(function(e) {
        e.preventDefault();
        proudNav.toggleMenu();
      });
    });

    // close overlay
    $('#overlay-311-close, #overlay-search-close').once('proud-navbar', function() {
      $(this).click(function(e) {
        e.preventDefault();
        proudNav.closeLayers();
      });
    });

  }};
})(jQuery, Proud);

<commit_msg>adding escape to close overlay<commit_after>(function($, Proud) {

  // Proudnav
  var proudNav = (function() {

    var layerOpen = {
      menu: false,
      search: false,
      answers: false,
    },
    layerClasses = {
      'menu': 'menu-nav-open',
      'search': 'search-active',
      'answers': 'active-311'
    },
    $body,
    self = {};

    // Closes overlays + menus
    // localLayers = ['menu', 'search']
    self.closeLayers = function(localLayers, callback) {
      // Default is all
      localLayers = localLayers || _.keys(layerOpen);
      var classes = [];
      _.map(localLayers, function(layer) {
        classes.push(layerClasses[layer]);
        layerOpen[layer] = false;
      });
      // Remove
      $body.removeClass(classes.join(' '));
      if(callback) {
        callback();
      }
    };

    // Closes overlays + menus
    self.openLayer = function(layer, callback) {
      setTimeout(function() {
        $body.addClass(layerClasses[layer]);
        layerOpen[layer] = true;
        $body.trigger('scroll');
        if(callback) {
          callback();
        }
      }, 50);
    };

    self.toggleMenu = function() {
      // Just close everything
      if(layerOpen.menu) {
        self.closeLayers();
        return;
      }
      else {
        self.closeLayers(['answers', 'search']);
        self.openLayer('menu');
      }
    };

    self.toggleOverlay = function(item, callback) {
      var thisLayer, otherLayer;
      switch(item) {
        case 'answers':
        case 'payments':
        case 'report':
        case 'status':
          thisLayer = 'answers';
          otherLayer = 'search';
          break;

        case 'search':
          thisLayer = 'search';
          otherLayer = 'answers';
          break;
      }

      // Close all
      if(layerOpen[thisLayer]) {
        self.closeLayers(null, callback);
      }
      else {
        // Close others, open ours
        self.closeLayers([otherLayer, 'menu'], callback);
        self.openLayer(thisLayer, callback);
      }
    };

    self.triggerOverlay = function(data, hash, classOverride) {
      if(classOverride) {
        layerClasses[data] = classOverride;
      }

      $body.trigger({
        type:     "proudNavClick",
        event:    data,
        hash:     hash,
        callback: function(open, scrollId, scrollOffset, forceClose, callback) {
          // Scrollto id
          if(scrollId) {
            var $scroll = $("#" + scrollId),
                scrollOffset = scrollOffset || 0,
                offset = $body.hasClass('proud-toolbar-active') ? 150 : 100;
            if($scroll.length) {
              $('html, body').animate({
                  scrollTop: $scroll.offset().top - (offset + scrollOffset)
              }, 200);
            }
          }
          // Oper layer
          if(open) {
            self.toggleOverlay(data, callback);
          }
          // Force close layers
          if(forceClose) {
            self.closeLayers(forceClose, callback);
          }
        }
      });
    };

    $(document).ready(function() {
      $body = $('body');

      // Listen for esc key
      $body.keydown(function(e) {  //keypress did not work with ESC;
        if (e.which == '27') {
          var closing = true;
          _.map(layerOpen, function(val) {
            if(val && closing) {
              self.closeLayers();
              closing = false;
            }
          });
        }
      });
    })

    return self;
  })();

  Proud.proudNav = proudNav;

  Proud.behaviors.proudNavbar = { attach: function(context, settings) {

    // Click top buttons
    $('[data-proud-navbar]').once('proud-navbar', function() {
      var $self = $(this);
      $self.click(function(e) {
        e.preventDefault();
        var data = $self.data('proud-navbar');

        if(data) {
          proudNav.triggerOverlay(data, $self.data('proud-navbar-hash'));
        }
      });
    });

    // mobile menu open
    $('#menu-button').once('proud-navbar', function() {
      $(this).click(function(e) {
        e.preventDefault();
        proudNav.toggleMenu();
      });
    });

    // close overlay
    $('#overlay-311-close, #overlay-search-close').once('proud-navbar', function() {
      $(this).click(function(e) {
        e.preventDefault();
        proudNav.closeLayers();
      });
    });

  }};
})(jQuery, Proud);

<|endoftext|>