<commit_before>angular.module('reply', [])
.directive('myReply', function(MessageService) {
    return {
        restrict: 'A'
      , scope: {
            feedid: "=feedid"
        }
      , link: function(scope, element, attrs) {
            $(element).bind('click', function(e) {
                var feedid = scope.feedid;

                MessageService.fetch_messages('msg');
                MessageService.register_reply_message();

                $('div#reply-to-user').draggable();
                $('div#reply-to-user.lightbox').show();
                $(".dialog-form[feedid="+feedid+"]").show();
                e.preventDefault();
            });
        }
    }
})
.directive('replyCancel', function(){
    return function(scope, element, attrs){
        $(element).bind('click', function(e) {
            $(this).parents('form textarea[name=bcc] textarea[name=message]').clearFields();
            $(this).parents(".dialog-form").fadeOut();

            $('div#reply-to-user').draggable("destroy");
            $("#send_button").val("Send");
            e.preventDefault();
        });
    }
})
.directive('replySend', function() {
    return function(scope, element, attrs) {
        $(element).bind('click', function(e) {
            console.lot($(this).attr('value'));
            console.log("Clicked");
        });
        /*
        $(element).parents('form').validate({
            submitHandler: function(form) {
                $(form).ajaxSubmit({
                    success: function() {
                        alert("Your reply has been sent!");
                        $(element).parents(".dialog-form").fadeOut();
                        $('div#reply-to-user').draggable("destroy");
                        $(element).parents('form textarea[name=bcc] textarea[name=message]').clearFields();
                    }
                });
            }
		  , errorElement: "em"
          , rules: {
                message: {
                    required: true
                }
            }
        });
        */
    }
})
.directive('addReply', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind('click', function(e) {
                var quickmessage = $(this).attr('req-text');
                var textarea = $("textarea[name=message]");
                textarea.val(quickmessage);
                e.preventDefault();
            });
        }
    }
})
.directive('deleteReply', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind("click", function(e) {
                $(this).parents('li').remove();
                e.preventDefault();
            })
        }
    }
})
.directive('editReply', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind("click", function(e) {
                $("#send_button").val("Save");
                /*
                var msgid    = $(this).parents('span').siblings('a').attr('id');
                var req_text = $(this).parents('span').siblings('a').attr('req-text');
                var configure = $('.modal-configure');

                configure.dialog({ zIndex: 100000 });
                configure.dialog('open');
                configure.children('#msgid').val(msgid);
                configure.children('.regular-text').val(req_text);
                configure.children('#msgtype').val("msg");
                configure.children('.add-msg-box-buttons').children('input[type=submit]').val("Update");
                */
                e.preventDefault();
            })
        }
    }
})
.directive('replyBcc', function() {
    return function(scope, element, attrs){
        $(element).children('li').bind('click', function(e) {
            var children = $(this).children('a');
            var email = children.attr('email');
            var my_id = children.attr('feedid');
            var textarea = $(".bcc-target[feedid="+my_id+"]").children('textarea');

            textarea.val(textarea.val() + email + ",");
            e.preventDefault();
        });
    }

})
.directive('configureReply', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind('click', function(e) {
                var configure = $('.modal-configure');
                configure.dialog({ zIndex: 100001 });
                configure.dialog('open');
                configure.children('.regular-text').val("");
                configure.children('#msgid').val("");
                configure.children('#msgtype').val("msg");
                configure.children('.add-msg-box-buttons').children('input[type=submit]').val("Add");
                e.preventDefault();
            })
        }
    }
})
.directive('cancelReply', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attr) {
            $(element).bind("click", function(e) {
                var configure = $('.modal-configure');
                configure.dialog('close');
            })
        }
    }
})
.directive('goback', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attr) {
            $(element).bind("click", function(e) {
                $("#send_button").val("Send");
            })
        }
    }

})
<commit_msg>Story #92<commit_after>angular.module('reply', [])
.directive('myReply', function(MessageService) {
    return {
        restrict: 'A'
      , scope: {
            feedid: "=feedid"
        }
      , link: function(scope, element, attrs) {
            $(element).bind('click', function(e) {
                var feedid = scope.feedid;

                MessageService.fetch_messages('msg');
                MessageService.register_reply_message();

                $('div#reply-to-user').draggable();
                $('div#reply-to-user.lightbox').show();
                $(".dialog-form[feedid="+feedid+"]").show();
                e.preventDefault();
            });
        }
    }
})
.directive('replyCancel', function(){
    return function(scope, element, attrs){
        $(element).bind('click', function(e) {
            $(this).parents('form textarea[name=bcc] textarea[name=message]').clearFields();
            $(this).parents(".dialog-form").fadeOut();

            $('div#reply-to-user').draggable("destroy");
            $("#send_button").val("Send");
            e.preventDefault();
        });
    }
})
.directive('replySend', function() {
    return function(scope, element, attrs) {
        $(element).bind('click', function(e) {
            console.log($(this).attr('value'));
            console.log("Clicked");
        });
        /*
        $(element).parents('form').validate({
            submitHandler: function(form) {
                $(form).ajaxSubmit({
                    success: function() {
                        alert("Your reply has been sent!");
                        $(element).parents(".dialog-form").fadeOut();
                        $('div#reply-to-user').draggable("destroy");
                        $(element).parents('form textarea[name=bcc] textarea[name=message]').clearFields();
                    }
                });
            }
		  , errorElement: "em"
          , rules: {
                message: {
                    required: true
                }
            }
        });
        */
    }
})
.directive('addReply', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind('click', function(e) {
                var quickmessage = $(this).attr('req-text');
                var textarea = $("textarea[name=message]");
                textarea.val(quickmessage);
                e.preventDefault();
            });
        }
    }
})
.directive('deleteReply', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind("click", function(e) {
                $(this).parents('li').remove();
                e.preventDefault();
            })
        }
    }
})
.directive('editReply', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind("click", function(e) {
                $("#send_button").val("Save");
                /*
                var msgid    = $(this).parents('span').siblings('a').attr('id');
                var req_text = $(this).parents('span').siblings('a').attr('req-text');
                var configure = $('.modal-configure');

                configure.dialog({ zIndex: 100000 });
                configure.dialog('open');
                configure.children('#msgid').val(msgid);
                configure.children('.regular-text').val(req_text);
                configure.children('#msgtype').val("msg");
                configure.children('.add-msg-box-buttons').children('input[type=submit]').val("Update");
                */
                e.preventDefault();
            })
        }
    }
})
.directive('replyBcc', function() {
    return function(scope, element, attrs){
        $(element).children('li').bind('click', function(e) {
            var children = $(this).children('a');
            var email = children.attr('email');
            var my_id = children.attr('feedid');
            var textarea = $(".bcc-target[feedid="+my_id+"]").children('textarea');

            textarea.val(textarea.val() + email + ",");
            e.preventDefault();
        });
    }

})
.directive('configureReply', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attrs) {
            $(element).bind('click', function(e) {
                var configure = $('.modal-configure');
                configure.dialog({ zIndex: 100001 });
                configure.dialog('open');
                configure.children('.regular-text').val("");
                configure.children('#msgid').val("");
                configure.children('#msgtype').val("msg");
                configure.children('.add-msg-box-buttons').children('input[type=submit]').val("Add");
                e.preventDefault();
            })
        }
    }
})
.directive('cancelReply', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attr) {
            $(element).bind("click", function(e) {
                var configure = $('.modal-configure');
                configure.dialog('close');
            })
        }
    }
})
.directive('goback', function() {
    return {
        restrict: 'A'
      , link: function(scope, element, attr) {
            $(element).bind("click", function(e) {
                $("#send_button").val("Send");
            })
        }
    }

})
<|endoftext|>


<commit_before>// Log server response.
// Also write fatal errors details to system channel
//
'use strict';

const _         = require('lodash');
const serialize = require('serialize-error');
const parseUrl  = require('url').parse;
const http      = require('http');
const encode    = require('mdurl').encode;

const MAX_PARAMS_LOG_LENGTH = 100;
const PROTECTED_PARAMS = [ 'pwd', 'pass', 'password' ];

module.exports = function (N) {

  // Emulate request url for RPC calls.
  function createRpcUrl(env) {
    let result = '';
    let params = env.params;

    _.forEach(params, function (value, key) {
      result += result.length ? '&' : '?';
      result += encode(String(key), encode.componentChars);
      result += '=';

      // Don't dump protected params
      if (PROTECTED_PARAMS.indexOf(key) !== -1) result += '****';
      // Do not dump nested objects.
      else if (_.isObject(value)) result += '{...}';
      else result += encode(String(value), encode.componentChars);

      if (result.length > MAX_PARAMS_LOG_LENGTH) {
        result = result.slice(0, MAX_PARAMS_LOG_LENGTH);
        return false; // terminate
      }
    });

    return `/RPC/${env.method}${result}`;
  }

  N.wire.after([ 'responder:*' ], { priority: 101 }, function response_compress(env) {

    //
    // Commons
    //

    let logger = N.logger.getLogger(`${env.req.type}@${env.method}`);

    let req    = env.origin.req;
    let url    = env.req.type === 'rpc' ? createRpcUrl(env) : parseUrl(req.url).path;

    let request_info = `${req.method} ${url} HTTP/${req.httpVersion}`;
    let user_agent   = req.headers['user-agent'] || '';

    let message      = http.STATUS_CODES[env.status];

    let level  = 'info';

    //
    // Check error and select error level
    //

    if (env.err) {
      let err = env.err;

      if (err.code >= N.io.APP_ERROR) {
        level = 'fatal';
        message = err.stack || err.message || JSON.stringify(err);

      } else if (err.code >= N.io.BAD_REQUEST) {
        level = 'error';
        message = err.message || message;
      }
    }

    logger[level](
      `${env.req.ip} - ${JSON.stringify(request_info)} ` +
      `${env.status} ${JSON.stringify(user_agent)} - ${message}`
    );

    //
    // On fatal error write details to system log namespace
    //

    if (env.err_orig && env.err_orig instanceof Error) {
      let err = env.err_orig;

      let eData = serialize(err);
      delete eData.stack;

      let message;

      try {
        message = `***
ip:        ${env.req.ip}
url:       ${req.url}
request:   ${req.method}
responder: ${env.req.type}
apiPath:   ${env.method || '[unknown]'}
params:    ${JSON.stringify(env.params || '', null, '  ')}

stack: ${err.stack}

error: ${JSON.stringify(eData, null, '  ')}
***`;
      } catch (e) {
        message = e.stack;
      }

      N.logger.fatal(message);
    }
  });

};
<commit_msg>Update serialize-error api to 5.0<commit_after>// Log server response.
// Also write fatal errors details to system channel
//
'use strict';

const _         = require('lodash');
const serialize = require('serialize-error').serializeError;
const parseUrl  = require('url').parse;
const http      = require('http');
const encode    = require('mdurl').encode;

const MAX_PARAMS_LOG_LENGTH = 100;
const PROTECTED_PARAMS = [ 'pwd', 'pass', 'password' ];

module.exports = function (N) {

  // Emulate request url for RPC calls.
  function createRpcUrl(env) {
    let result = '';
    let params = env.params;

    _.forEach(params, function (value, key) {
      result += result.length ? '&' : '?';
      result += encode(String(key), encode.componentChars);
      result += '=';

      // Don't dump protected params
      if (PROTECTED_PARAMS.indexOf(key) !== -1) result += '****';
      // Do not dump nested objects.
      else if (_.isObject(value)) result += '{...}';
      else result += encode(String(value), encode.componentChars);

      if (result.length > MAX_PARAMS_LOG_LENGTH) {
        result = result.slice(0, MAX_PARAMS_LOG_LENGTH);
        return false; // terminate
      }
    });

    return `/RPC/${env.method}${result}`;
  }

  N.wire.after([ 'responder:*' ], { priority: 101 }, function response_compress(env) {

    //
    // Commons
    //

    let logger = N.logger.getLogger(`${env.req.type}@${env.method}`);

    let req    = env.origin.req;
    let url    = env.req.type === 'rpc' ? createRpcUrl(env) : parseUrl(req.url).path;

    let request_info = `${req.method} ${url} HTTP/${req.httpVersion}`;
    let user_agent   = req.headers['user-agent'] || '';

    let message      = http.STATUS_CODES[env.status];

    let level  = 'info';

    //
    // Check error and select error level
    //

    if (env.err) {
      let err = env.err;

      if (err.code >= N.io.APP_ERROR) {
        level = 'fatal';
        message = err.stack || err.message || JSON.stringify(err);

      } else if (err.code >= N.io.BAD_REQUEST) {
        level = 'error';
        message = err.message || message;
      }
    }

    logger[level](
      `${env.req.ip} - ${JSON.stringify(request_info)} ` +
      `${env.status} ${JSON.stringify(user_agent)} - ${message}`
    );

    //
    // On fatal error write details to system log namespace
    //

    if (env.err_orig && env.err_orig instanceof Error) {
      let err = env.err_orig;

      let eData = serialize(err);
      delete eData.stack;

      let message;

      try {
        message = `***
ip:        ${env.req.ip}
url:       ${req.url}
request:   ${req.method}
responder: ${env.req.type}
apiPath:   ${env.method || '[unknown]'}
params:    ${JSON.stringify(env.params || '', null, '  ')}

stack: ${err.stack}

error: ${JSON.stringify(eData, null, '  ')}
***`;
      } catch (e) {
        message = e.stack;
      }

      N.logger.fatal(message);
    }
  });

};
<|endoftext|>


<commit_before>function getopt (pat, argv) {
    var patterns = pat

    if (typeof pat == 'string') {
        patterns = pat.split('|')
        patterns.pop()
        patterns = patterns.map(function (argument) {
            var typed = argument.split(/[:@]/)
            var args = typed[0].split(',')
            if (args.length == 1) {
                args.unshift('-')
            }
            return {
                arguable: typed[1] != '!',
                short: args[0].slice(1),
                long: args[1].slice(2),
                key: args[1].slice(2)
            }
        })
    }

    patterns = patterns.map(function (pattern) {
        return {
            arguable: pattern.arguable,
            long: '--' + pattern.long,
            short: pattern.short ? '-' + pattern.short : '',
            key: pattern.long
        }
    })

    var params = {}

    patterns.filter(function (pattern) {
        return pattern.arguable
    }).map(function (pattern) {
        params[pattern.key] = []
    })

    var i = 0
    for (;;) {
        if (argv[0] == '--') {
            argv.shift()
            break
        }
        if (argv.length == 0 || !/^--?[^-]/.test(argv[0])) {
            break
        }
        var arg = argv.shift()
        var $ = /^(--[^=]+)=(.*)$/.exec(arg) || /^(-[^-])(.+)$/.exec(arg) || [false, arg, true]
        var catenated = !! $[0]
        var parameter = $[1]
        var value = $[2]
        var isLong = parameter[1] == '-'
        var alternates = patterns.filter(function (pattern) {
            return pattern.long.lastIndexOf(parameter, 0) == 0
                || pattern.short.lastIndexOf(parameter, 0) == 0
        })
        if (alternates.length != 1) {
            return {
                abend: alternates.length ? 'ambiguous argument' : 'unknown argument',
                context: parameter
            }
        }

        var pattern = alternates.shift()
        if (pattern.arguable) {
            if (!catenated) {
                if (argv.length == 0) {
                    return {
                        abend: 'missing argument',
                        context: isLong ? pattern.long : pattern.short
                    }
                }
                value = argv.shift()
            }
        } else if (catenated) {
            if (isLong) {
                return {
                    abend: 'unexpected argument value',
                    context: pattern.long
                }
            } else {
                argv.unshift('-' + value)
            }
        }

        if (!params[pattern.key]) {
            params[pattern.key] = [ value ]
        } else {
            params[pattern.key].push(value)
        }

        i++
    }

    // TODO Implement `--no-foo`.
    return {
        params: params,
        given: patterns.filter(function (pattern) {
            return params[pattern.key] && params[pattern.key].length != 0
        }).map(function (pattern) {
            return pattern.key
        })
    }
}

module.exports = getopt
<commit_msg>Remove string pattern parsing from `getopt`.<commit_after>function getopt (patterns, argv) {
    patterns = patterns.map(function (pattern) {
        return {
            arguable: pattern.arguable,
            long: '--' + pattern.long,
            short: pattern.short ? '-' + pattern.short : '',
            key: pattern.long
        }
    })

    var params = {}

    patterns.filter(function (pattern) {
        return pattern.arguable
    }).map(function (pattern) {
        params[pattern.key] = []
    })

    var i = 0
    for (;;) {
        if (argv[0] == '--') {
            argv.shift()
            break
        }
        if (argv.length == 0 || !/^--?[^-]/.test(argv[0])) {
            break
        }
        var arg = argv.shift()
        var $ = /^(--[^=]+)=(.*)$/.exec(arg) || /^(-[^-])(.+)$/.exec(arg) || [false, arg, true]
        var catenated = !! $[0]
        var parameter = $[1]
        var value = $[2]
        var isLong = parameter[1] == '-'
        var alternates = patterns.filter(function (pattern) {
            return pattern.long.lastIndexOf(parameter, 0) == 0
                || pattern.short.lastIndexOf(parameter, 0) == 0
        })
        if (alternates.length != 1) {
            return {
                abend: alternates.length ? 'ambiguous argument' : 'unknown argument',
                context: parameter
            }
        }

        var pattern = alternates.shift()
        if (pattern.arguable) {
            if (!catenated) {
                if (argv.length == 0) {
                    return {
                        abend: 'missing argument',
                        context: isLong ? pattern.long : pattern.short
                    }
                }
                value = argv.shift()
            }
        } else if (catenated) {
            if (isLong) {
                return {
                    abend: 'unexpected argument value',
                    context: pattern.long
                }
            } else {
                argv.unshift('-' + value)
            }
        }

        if (!params[pattern.key]) {
            params[pattern.key] = [ value ]
        } else {
            params[pattern.key].push(value)
        }

        i++
    }

    // TODO Implement `--no-foo`.
    return {
        params: params,
        given: patterns.filter(function (pattern) {
            return params[pattern.key] && params[pattern.key].length != 0
        }).map(function (pattern) {
            return pattern.key
        })
    }
}

module.exports = getopt
<|endoftext|>


<commit_before>hashTrack.controller('TweetsController', ['$scope', '$window', '$routeParams', 'geo', 'searchgeo', function($scope, $window, $routeParams, geo, searchgeo) {
	$scope.hashtag = $routeParams.h;

	geo.getUserGeo(function(error, geolocation) {
		if (error) {
			geolocation.latitude = 74;
			geolocation.longitude = -111;
			var mapOptions = { center: { latitude: 74, longitude: -111 }, zoom: 6 }
		} else {
			var mapOptions = { center: { latitude: geolocation.latitude, longitude: geolocation.longitude }, zoom: 12 };
		}

		(function() {
			console.log('latitude: ' + geolocation.latitude + ' longitude: ' + geolocation.longitude);
			console.log(mapOptions);
			$scope.map = mapOptions;
			$scope.$digest();
		})();
	});

	var doGetLocalTweets = function() {
		searchgeo.getGeoTweets($scope.hashtag, 20, function(error, data) {
			if (error) return error;
			var newData = data.map(function(tweet) {
				if (tweet.coordinates != null) {
					tweet.geolocation = {
						latitude: tweet.coordinates.coordinates[1],
						longitude: tweet.coordinates.coordinates[0]
					};
					tweet.created_at = Date.parse(tweet.created_at);
					tweet.mapOptions = {icon:'/images/tweet_icon.png'};
					return tweet;
				}
			});
			newData = searchgeo.clean(newData, undefined);
			$scope.apps = newData;
			$window.document.getElementsByClassName("loading-alert")[0].className += ' hidden';
			$window.document.getElementsByClassName("tweet-list")[0].className = 'tweet-list';
			if ($scope.apps.length === 0){
				$window.document.getElementsByClassName("no-hashtags")[0].className = 'no-hashtags';
			};
		});
	}

	doGetLocalTweets();

}]);
<commit_msg>idk know what i worked on but its goin up!<commit_after>hashTrack.controller('TweetsController', ['$scope', '$window', '$routeParams', 'geo', 'searchgeo', function($scope, $window, $routeParams, geo, searchgeo) {
	$scope.hashtag = $routeParams.h;

var mapRender = function (callback){
	geo.getUserGeo(function(error, geolocation) {
		if (error) {
			geolocation.latitude = 74;
			geolocation.longitude = -111;
			$scope.mapOptions = { center: { latitude: 74, longitude: -111 }, zoom: 6 }
		} else {
			$scope.mapOptions = { center: { latitude: geolocation.latitude, longitude: geolocation.longitude }, zoom: 12 };
		}
		console.log('latitude: ' + geolocation.latitude + ' longitude: ' + geolocation.longitude);
	});
	callback ($scope.mapOptions);
};

	var doGetLocalTweets = function() {
		searchgeo.getGeoTweets($scope.hashtag, 20, function(error, data) {
			if (error) return error;
			var newData = data.map(function(tweet) {
				if (tweet.coordinates != null) {
					tweet.geolocation = {
						latitude: tweet.coordinates.coordinates[1],
						longitude: tweet.coordinates.coordinates[0]
					};
					tweet.created_at = Date.parse(tweet.created_at);
					tweet.mapOptions = {icon:'/images/tweet_icon.png'};
					return tweet;
				}
			});
			newData = searchgeo.clean(newData, undefined);
			$scope.apps = newData;
			mapRender(function (mapOptions) {
				$window.document.getElementsByClassName("tweet-list")[0].className = 'tweet-list';
				if ($scope.apps.length === 0){
					$window.document.getElementsByClassName("no-hashtags")[0].className = 'no-hashtags';
				};
				$scope.map = mapOptions;
				$scope.$digest();
				$window.document.getElementsByClassName("loading-alert")[0].className += ' hidden';
			});

		});
	};

	doGetLocalTweets();

}]);
<|endoftext|>


<commit_before>function getopt (pat, argv) {
    var patterns = pat

    if (typeof pat == 'string') {
        patterns = pat.split('|')
        patterns.pop()
        patterns = patterns.map(function (argument) {
            var typed = argument.split(/[:@]/)
            var args = typed[0].split(',')
            if (args.length == 1) {
                args.unshift('-')
            }
            return {
                arguable: typed[1] != '!',
                short: args[0].slice(1),
                long: args[1].slice(2),
                key: args[1].slice(2)
            }
        })
    }

    patterns = patterns.map(function (pattern) {
        return {
            arguable: pattern.arguable,
            long: '--' + pattern.long,
            short: pattern.short ? '-' + pattern.short : '',
            key: pattern.long
        }
    })

    var params = {}

    patterns.filter(function (pattern) {
        return pattern.arguable
    }).map(function (pattern) {
        params[pattern.key] = []
    })

    var i = 0, unshifted = null
    for (;;) {
        if (argv[0] == '--') {
            argv.shift()
            break
        }
        if (argv.length == 0 || !/^--?[^-]/.test(argv[0])) {
            break
        }
        var arg = argv.shift()
        var $ = /^(--[^=]+)=(.*)$/.exec(arg) || /^(-[^-])(.+)$/.exec(arg) || [false, arg, true]
        var catenated = !! $[0]
        var parameter = $[1]
        var value = $[2]
        var isLong = parameter[1] == '-'
        var alternates = patterns.filter(function (pattern) {
            return pattern.long.lastIndexOf(parameter, 0) == 0
                || pattern.short.lastIndexOf(parameter, 0) == 0
        })
        if (alternates.length != 1) {
            return {
                abend: alternates.length ? 'ambiguous argument' : 'unknown argument',
                context: parameter
            }
        }

        unshifted = null

        var pattern = alternates.shift()
        if (pattern.arguable) {
            if (!catenated) {
                if (argv.length == 0) {
                    return {
                        abend: 'missing argument',
                        context: arg[1][1] != '-' ? arg[1] : '--' + opt
                    }
                }
                value = argv.shift()
            }
        } else if (catenated) {
            if (isLong) {
                return {
                    abend: 'unexpected argument value',
                    context: pattern.long
                }
            } else {
                argv.unshift('-' + value)
                unshifted = pattern.short
            }
        }

        if (!params[pattern.key]) {
            params[pattern.key] = [ value ]
        } else {
            params[pattern.key].push(value)
        }

        i++
    }

    // TODO Implement `--no-foo`.
    if (unshifted) {
        return {
            abend: 'unexpected argument value',
            context: unshifted
        }
    }

    return {
        params: params,
        given: patterns.filter(function (pattern) {
            return params[pattern.key] && params[pattern.key].length != 0
        }).map(function (pattern) {
            return pattern.key
        })
    }
}

module.exports = getopt
<commit_msg>Tidy missing argument.<commit_after>function getopt (pat, argv) {
    var patterns = pat

    if (typeof pat == 'string') {
        patterns = pat.split('|')
        patterns.pop()
        patterns = patterns.map(function (argument) {
            var typed = argument.split(/[:@]/)
            var args = typed[0].split(',')
            if (args.length == 1) {
                args.unshift('-')
            }
            return {
                arguable: typed[1] != '!',
                short: args[0].slice(1),
                long: args[1].slice(2),
                key: args[1].slice(2)
            }
        })
    }

    patterns = patterns.map(function (pattern) {
        return {
            arguable: pattern.arguable,
            long: '--' + pattern.long,
            short: pattern.short ? '-' + pattern.short : '',
            key: pattern.long
        }
    })

    var params = {}

    patterns.filter(function (pattern) {
        return pattern.arguable
    }).map(function (pattern) {
        params[pattern.key] = []
    })

    var i = 0, unshifted = null
    for (;;) {
        if (argv[0] == '--') {
            argv.shift()
            break
        }
        if (argv.length == 0 || !/^--?[^-]/.test(argv[0])) {
            break
        }
        var arg = argv.shift()
        var $ = /^(--[^=]+)=(.*)$/.exec(arg) || /^(-[^-])(.+)$/.exec(arg) || [false, arg, true]
        var catenated = !! $[0]
        var parameter = $[1]
        var value = $[2]
        var isLong = parameter[1] == '-'
        var alternates = patterns.filter(function (pattern) {
            return pattern.long.lastIndexOf(parameter, 0) == 0
                || pattern.short.lastIndexOf(parameter, 0) == 0
        })
        if (alternates.length != 1) {
            return {
                abend: alternates.length ? 'ambiguous argument' : 'unknown argument',
                context: parameter
            }
        }

        unshifted = null

        var pattern = alternates.shift()
        if (pattern.arguable) {
            if (!catenated) {
                if (argv.length == 0) {
                    return {
                        abend: 'missing argument',
                        context: isLong ? pattern.long : pattern.short
                    }
                }
                value = argv.shift()
            }
        } else if (catenated) {
            if (isLong) {
                return {
                    abend: 'unexpected argument value',
                    context: pattern.long
                }
            } else {
                argv.unshift('-' + value)
                unshifted = pattern.short
            }
        }

        if (!params[pattern.key]) {
            params[pattern.key] = [ value ]
        } else {
            params[pattern.key].push(value)
        }

        i++
    }

    // TODO Implement `--no-foo`.
    if (unshifted) {
        return {
            abend: 'unexpected argument value',
            context: unshifted
        }
    }

    return {
        params: params,
        given: patterns.filter(function (pattern) {
            return params[pattern.key] && params[pattern.key].length != 0
        }).map(function (pattern) {
            return pattern.key
        })
    }
}

module.exports = getopt
<|endoftext|>


<commit_before>(function($){

  var CommentView = Backbone.View.extend({
    template : _.template($('#photo-comment-tmpl').html()),
    render : function(){
      $(this.el).html(this.template(this.model.toJSON()));
      return this;
    }
  });

  var CommentsView = Backbone.View.extend({
    template : _.template($('#photo-comments-tmpl').html()),
    render : function(){
      $(this.el).html(this.template(this.model.toJSON()));
      this.updateCommentList();
      return this;
    },
    updateCommentList : function(){
      // how do we know what comments
      $el = $(this.el).find('ul.comment-list');
      $el.empty().hide();
      // get the comments...
      var actions = this.model.get('actions');

      /**
       *
       * DEMO to be replaced with the real actions
       *
       */
      actions = [{
        type: 'comment',
        name: 'Mark',
        email: 'fabrizim@owlwatch.com',
        avatar: 'http://openphotofabrizio.s3.amazonaws.com/custom/201212/7d0cae-IMG_4413_100x100xCR.jpg',
        value: 'ZOMG! This is like wicked awesome!',
        date : 'January 11, 2013 12:07am EST'
      },{
        type: 'comment',
        name: 'Mark',
        email: 'fabrizim@owlwatch.com',
        avatar: 'http://openphotofabrizio.s3.amazonaws.com/custom/201212/7d0cae-IMG_4413_100x100xCR.jpg',
        value: 'Meh.',
        date : 'January 11, 2013 12:11am EST'
      }];

      $(this.el).find('.comment-count').html( actions.length );
      _.each(actions, function(action){
        var model = new Backbone.Model(action);
        $el.append(new CommentView({model: model}).render().el);
      });
      $el.show();
    }
  });

  var TitleView = op.data.view.Editable.extend({
    template : _.template($('#photo-detail-title-tmpl').html()),
    editable    : {
      '.title.edit' : {
        name: 'title',
        title: 'Edit Photo Title',
        placement: 'bottom'
      }
    }
  });

  var DescriptionView = op.data.view.Editable.extend({
    template : _.template($('#photo-detail-description-tmpl').html()),
    editable    : {
      '.text.edit' : {
        type: 'textarea',
        name: 'description',
        title: 'Edit Photo Description',
        emptytext: 'Add a description',
        placement: 'top'
      }
    }
  });

  var PhotoMetaView = Backbone.View.extend({
    template : _.template($('#photo-detail-meta-tmpl').html()),
    render : function(){
      $(this.el).html(this.template(this.model.toJSON()));
      return this;
    },
    events : {
      'click .permission.edit': 'permission',
      'click .share': 'share'
    },
    permission: function(ev) {
      ev.preventDefault();
      var el = $(ev.currentTarget), id = el.attr('data-id'), model = this.model;
      model.set('permission', model.get('permission') == 0 ? 1 : 0, {silent:false});
      model.save();
    },
    share: function(ev) {
      ev.preventDefault();
      var $el = $(ev.currentTarget), id = $el.attr('data-id');
      OP.Util.makeRequest('/photos/'+id+'/share.json', {}, TBX.callbacks.share, 'json', 'get');
    }
  });

  var RightsView = Backbone.View.extend({
    template : _.template($('#photo-detail-rights-tmpl').html()),
    render : function(){
      $(this.el).html(this.template(this.model.toJSON()));
      return this;
    }
  });

  var CollapsiblesView = Backbone.View.extend({
    open : {},
    template : _.template($('#photo-detail-collapsibles-tmpl').html()),
    render : function(){
      var self = this;

      $(this.el).html(this.template(this.model.toJSON()));
      $(this.el).find('.collapse').on({
        'show' : function(e){
          self.open[$(e.target).attr('id')] = true;
          $(e.target).parents('.collapsibles li').addClass('active');

          if( e.target.id == 'photo-location' ){
            self.updateMap();
          }

        },
        'hide' : function(e){
          self.open[$(e.target).attr('id')] = false;
          $(e.target).parents('.collapsibles li').removeClass('active');
        }
      });

      for(var i in this.open ) if( this.open[i] ){
        $('a[href=#'+i+']').parents('.collapsibles li').addClass('active');
        $('#'+i).addClass('in');
        if(i === 'photo-location' ) this.updateMap();
      }

      return this;
    },
    updateMap : function(){
      var lat,lng;

      /**
       * DEMO
       */
      this.model.set('latitude',42.66937, {silent:true});
      this.model.set('longitude',-71.646664, {silent:true});

      if((lat=this.model.get('latitude')) && (lng=this.model.get('longitude')) ){
        var mapOptions = {
          center: new google.maps.LatLng(lat, lng),
          zoom: 10,
          mapTypeControl: false,
          streetViewControl: false,
          zoomControl: false,
          scrollwheel: false,
          mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        var map = new google.maps.Map($(this.el).find('.map')[0], mapOptions);
        var marker = new google.maps.Marker({
          map: map,
          position: map.getCenter()
        });
      }
    }
  });

  op.ns('data.view').PhotoDetail = op.data.view.Editable.extend({

    largePath : 'path870x870',
    thumbPath : 'path180x180xCR',

    viewMap : {
      '.comments'     :CommentsView,
      '.photo-title'  :TitleView,
      '.description'  :DescriptionView,
      '.photo-meta'   :PhotoMetaView,
      '.collapsibles' :CollapsiblesView,
      '.rights'       :RightsView
    },

    initialize: function() {
      this.model.on('change', this.updateViews, this);
      this.on('afterrender', this.onAfterRender, this);
      this.store = op.data.store.Photos;
      this.initialModel = this.model;
      this.thumbs = {};
      this.views = {};
      var self = this;
      op.Lightbox.getInstance().on('updatemodel', function(model){
        self.go(model.get('id'));
      });
    },
    model: this.model,
    className: 'photo-detail-meta',
    template    :_.template($('#photo-detail-meta').html()),
    modelChanged: function() {
      this.render();
    },

    onAfterRender: function(){
      var self = this;
      this.setupPagination();
      this.updateViews();
      $(this.el).find('.photo .mag').click(function(e){
        op.Lightbox.getInstance().open(self.model.get('id'));
      });
    },

    updateModel : function(model){
      this.model.off(null, null, this);
      this.model = model;
      this.model.on('change', this.updateViews, this);
      this.updateViews();
      // change the main image
      $(this.el).find('.photo img')
        .attr('src', this.model.get(this.largePath))

      $(this.el).find('.photo .photo-view-modal-click')
        .attr('data-id', this.model.get('id'))
    },

    updateViews : function(){
      this.updateUserBadge();
      for(var i in this.viewMap )
        if( this.viewMap.hasOwnProperty(i) ){
          this.updateView(i);
        }
    },

    updateView : function(name){
      if( !this.views[name] ){
        this.views[name] = new this.viewMap[name]({
          el: $(this.el).find(name),
          model: this.model
        }).render();
      }
      else{
        this.views[name].model = this.model;
        this.views[name].render();
      }
    },

    updateUserBadge : function(){
      // update the user badge...
      var $el = $(this.el).find('.userbadge')
        , model = op.data.store.Profiles.get(this.model.get('owner'))

      if( model ){
        new op.data.view.UserBadge({el: $el, model: model}).render();
      }
    },

    setupPagination : function(){
      var $scroller = $(this.el).find('.pagination .photos .scroller')
        , shimDiv

      $(this.el).find('.pagination .arrow-prev').click(_.bind(this.prev, this));
      $(this.el).find('.pagination .arrow-next').click(_.bind(this.next, this));

      // create the shim...
      shimDiv = $('

')
        .appendTo($(this.el).find('.pagination .photos .scroller .thumbs'));

      $('')
        .attr('src', this.model.get(this.thumbPath))
        .appendTo(shimDiv.find('.inner'))

      this.addModel(this.model);
      this.addPreviousFromModel(this.model);
      this.addNextFromModel(this.model);
    },

    addPreviousFromModel : function(model){
      this._addMoreFromModel(model, 'next');
    },

    addNextFromModel : function(model){
      this._addMoreFromModel(model, 'previous');
    },

    _addMoreFromModel : function(model, dir){
      if( !dir ) dir = 'next';
      if( (ar = model.get(dir)) && ar.length ){
        for(var i=0; i<ar.length; i++ ){
          var m = new op.data.model.Photo(ar[i]);
          if( ar.length === 1 ){
            m[dir==='next'?'_last':'_first'] = true;
          }
          this.addModel(m, dir==='next');
        }
      }
      else {
        model[dir==='next'?'_last':'_first'] = true;
      }
    },

    addModel : function(model, pos){
      if( (m = this.store.get(model.get('id'))) ){
        this.addThumbNav(m);
        return m;
      }

      this.store[pos===false?'unshift':'push'](model);
      this.addThumbNav(model);

      /**
       * TODO - figure out why routing won't work...
       *
      var self = this
        , a = document.createElement('a');

      a.href = model.get('url');
      this.router.route( a.pathname, 'photo_'+model.get('id'), function(){
        self.go(model.get('id'));
      });
      this.router.on('route:photo_'+model.get('id'), function(){

      });
      */
      return model;
    },

    addThumbNav : function(model){
      var t
        , id = model.get('id')

      if( (t = this.thumbs[id]) ){
        return t;
      }

      // get the difference
      var init = _.indexOf( this.store.models, this.initialModel )
        , diff = _.indexOf( this.store.models, model ) - init
        , x = diff * 33.33333333 + 33.33333333 + .625;

      t = this.thumbs[id] = $('
')
        .appendTo( $(this.el).find('.pagination .photos .scroller .thumbs') )
        .css({left: x+'%'})
        .click(_.bind(this.thumbClick, this, model.get('id')))

      var b = $('
').appendTo(t);
      var b2 = $('
').appendTo(b);

      var i = $('')
        .attr('src', model.get(this.thumbPath))
        .appendTo(b2);

      if( this.model == model )
        t.addClass('active');

      return t;
    },

    thumbClick : function(id){
      /**
       * TODO - this is where you would call the router kmethod
       * if it was working.
       */
      //this.router.navigate('/p/'+id, {trigger: true});
      this.go(id);
    },

    next : function(){
      var cur = _.indexOf( this.store.models, this.model );
      if( cur < this.store.models.length-1 ){
        this.go( this.store.at(cur + 1).get('id') );
      }
    },

    prev : function(){
      var cur = _.indexOf( this.store.models, this.model );
      if( cur > 0 ){
        this.go( this.store.at(cur - 1).get('id') );
      }
    },

    go : function(id){

      if( this.model === this.store.get(id)) return;

      // get the difference
      var init = _.indexOf( this.store.models, this.initialModel )
        , diff = _.indexOf( this.store.models, this.store.get(id) ) - init
        , router = op.data.store.Router;

      $(this.el).find('.pagination .photos .scroller .thumbs')
        .stop()
        // might be better to use css3 translate3d and transition properties instead
        .animate({'left': (-33.33333333*diff)+'%'}, 200)

      $(this.el).find('.pagination .photos .scroller .thumbs .thumb').removeClass('active');
      this.thumbs[id].addClass('active');

      // lets also get next/prev
      var x = _.indexOf( this.store.models, this.store.get(id) )
        , c = _.indexOf( this.store.models, this.model )

      this.loadMore( x > c );
      this.updateModel(this.store.get(id));
      router.navigate('/p/'+id, {trigger: false});
    },

    loadMore : function( dir ){
      var model
        , self = this
        , sizes = _.map(
          [this.thumbPath, this.largePath],
          function(str){ return str.replace(/^path/,''); }
        ).join(',')
        , apiParams = {nextprevious:'1', returnSizes:sizes}
        , endpoint
        , fn = 'next';

      if( dir ){
        // going to add more to the end...
        // first lets get the last model in the store
        // and check if its the last one
        var model = this.store.at( this.store.models.length-1 );
        if( model._last ) return;
      }
      else {
        fn = 'previous';
        var model = this.store.at(0);
        if( model._first ) return;
      }

      endpoint = TBX.init.pages.photo.filterOpts ?
        '/photo/'+model.get('id')+'/view.json' :
        '/photo/'+model.get('id')+'/'+TBX.init.pages.photo.filterOpts+'/view.json' ;

      OP.Util.makeRequest(endpoint, apiParams, function(response) {
        if( response.result ){
          if( response.result.next ) model.set('next', response.result.next);
          if( response.result.previous ) model.set('previous', response.result.previous);
        }
        self._addMoreFromModel(model, fn);
      }, 'json', 'get');
    }
  });
})(jQuery);

<commit_msg>Add a small zoom control on maps<commit_after>(function($){

  var CommentView = Backbone.View.extend({
    template : _.template($('#photo-comment-tmpl').html()),
    render : function(){
      $(this.el).html(this.template(this.model.toJSON()));
      return this;
    }
  });

  var CommentsView = Backbone.View.extend({
    template : _.template($('#photo-comments-tmpl').html()),
    render : function(){
      $(this.el).html(this.template(this.model.toJSON()));
      this.updateCommentList();
      return this;
    },
    updateCommentList : function(){
      // how do we know what comments
      $el = $(this.el).find('ul.comment-list');
      $el.empty().hide();
      // get the comments...
      var actions = this.model.get('actions');

      /**
       *
       * DEMO to be replaced with the real actions
       *
       */
      actions = [{
        type: 'comment',
        name: 'Mark',
        email: 'fabrizim@owlwatch.com',
        avatar: 'http://openphotofabrizio.s3.amazonaws.com/custom/201212/7d0cae-IMG_4413_100x100xCR.jpg',
        value: 'ZOMG! This is like wicked awesome!',
        date : 'January 11, 2013 12:07am EST'
      },{
        type: 'comment',
        name: 'Mark',
        email: 'fabrizim@owlwatch.com',
        avatar: 'http://openphotofabrizio.s3.amazonaws.com/custom/201212/7d0cae-IMG_4413_100x100xCR.jpg',
        value: 'Meh.',
        date : 'January 11, 2013 12:11am EST'
      }];

      $(this.el).find('.comment-count').html( actions.length );
      _.each(actions, function(action){
        var model = new Backbone.Model(action);
        $el.append(new CommentView({model: model}).render().el);
      });
      $el.show();
    }
  });

  var TitleView = op.data.view.Editable.extend({
    template : _.template($('#photo-detail-title-tmpl').html()),
    editable    : {
      '.title.edit' : {
        name: 'title',
        title: 'Edit Photo Title',
        placement: 'bottom'
      }
    }
  });

  var DescriptionView = op.data.view.Editable.extend({
    template : _.template($('#photo-detail-description-tmpl').html()),
    editable    : {
      '.text.edit' : {
        type: 'textarea',
        name: 'description',
        title: 'Edit Photo Description',
        emptytext: 'Add a description',
        placement: 'top'
      }
    }
  });

  var PhotoMetaView = Backbone.View.extend({
    template : _.template($('#photo-detail-meta-tmpl').html()),
    render : function(){
      $(this.el).html(this.template(this.model.toJSON()));
      return this;
    },
    events : {
      'click .permission.edit': 'permission',
      'click .share': 'share'
    },
    permission: function(ev) {
      ev.preventDefault();
      var el = $(ev.currentTarget), id = el.attr('data-id'), model = this.model;
      model.set('permission', model.get('permission') == 0 ? 1 : 0, {silent:false});
      model.save();
    },
    share: function(ev) {
      ev.preventDefault();
      var $el = $(ev.currentTarget), id = $el.attr('data-id');
      OP.Util.makeRequest('/photos/'+id+'/share.json', {}, TBX.callbacks.share, 'json', 'get');
    }
  });

  var RightsView = Backbone.View.extend({
    template : _.template($('#photo-detail-rights-tmpl').html()),
    render : function(){
      $(this.el).html(this.template(this.model.toJSON()));
      return this;
    }
  });

  var CollapsiblesView = Backbone.View.extend({
    open : {},
    template : _.template($('#photo-detail-collapsibles-tmpl').html()),
    render : function(){
      var self = this;

      $(this.el).html(this.template(this.model.toJSON()));
      $(this.el).find('.collapse').on({
        'show' : function(e){
          self.open[$(e.target).attr('id')] = true;
          $(e.target).parents('.collapsibles li').addClass('active');

          if( e.target.id == 'photo-location' ){
            self.updateMap();
          }

        },
        'hide' : function(e){
          self.open[$(e.target).attr('id')] = false;
          $(e.target).parents('.collapsibles li').removeClass('active');
        }
      });

      for(var i in this.open ) if( this.open[i] ){
        $('a[href=#'+i+']').parents('.collapsibles li').addClass('active');
        $('#'+i).addClass('in');
        if(i === 'photo-location' ) this.updateMap();
      }

      return this;
    },
    updateMap : function(){
      var lat,lng;

      /**
       * DEMO
       */
      this.model.set('latitude',42.66937, {silent:true});
      this.model.set('longitude',-71.646664, {silent:true});

      if((lat=this.model.get('latitude')) && (lng=this.model.get('longitude')) ){
        var mapOptions = {
          center: new google.maps.LatLng(lat, lng),
          zoom: 10,
          mapTypeControl: false,
          streetViewControl: false,
          zoomControl: true,
          scrollwheel: false,
          mapTypeId: google.maps.MapTypeId.ROADMAP
        };
        var map = new google.maps.Map($(this.el).find('.map')[0], mapOptions);
        var marker = new google.maps.Marker({
          map: map,
          position: map.getCenter()
        });
      }
    }
  });

  op.ns('data.view').PhotoDetail = op.data.view.Editable.extend({

    largePath : 'path870x870',
    thumbPath : 'path180x180xCR',

    viewMap : {
      '.comments'     :CommentsView,
      '.photo-title'  :TitleView,
      '.description'  :DescriptionView,
      '.photo-meta'   :PhotoMetaView,
      '.collapsibles' :CollapsiblesView,
      '.rights'       :RightsView
    },

    initialize: function() {
      this.model.on('change', this.updateViews, this);
      this.on('afterrender', this.onAfterRender, this);
      this.store = op.data.store.Photos;
      this.initialModel = this.model;
      this.thumbs = {};
      this.views = {};
      var self = this;
      op.Lightbox.getInstance().on('updatemodel', function(model){
        self.go(model.get('id'));
      });
    },
    model: this.model,
    className: 'photo-detail-meta',
    template    :_.template($('#photo-detail-meta').html()),
    modelChanged: function() {
      this.render();
    },

    onAfterRender: function(){
      var self = this;
      this.setupPagination();
      this.updateViews();
      $(this.el).find('.photo .mag').click(function(e){
        op.Lightbox.getInstance().open(self.model.get('id'));
      });
    },

    updateModel : function(model){
      this.model.off(null, null, this);
      this.model = model;
      this.model.on('change', this.updateViews, this);
      this.updateViews();
      // change the main image
      $(this.el).find('.photo img')
        .attr('src', this.model.get(this.largePath))

      $(this.el).find('.photo .photo-view-modal-click')
        .attr('data-id', this.model.get('id'))
    },

    updateViews : function(){
      this.updateUserBadge();
      for(var i in this.viewMap )
        if( this.viewMap.hasOwnProperty(i) ){
          this.updateView(i);
        }
    },

    updateView : function(name){
      if( !this.views[name] ){
        this.views[name] = new this.viewMap[name]({
          el: $(this.el).find(name),
          model: this.model
        }).render();
      }
      else{
        this.views[name].model = this.model;
        this.views[name].render();
      }
    },

    updateUserBadge : function(){
      // update the user badge...
      var $el = $(this.el).find('.userbadge')
        , model = op.data.store.Profiles.get(this.model.get('owner'))

      if( model ){
        new op.data.view.UserBadge({el: $el, model: model}).render();
      }
    },

    setupPagination : function(){
      var $scroller = $(this.el).find('.pagination .photos .scroller')
        , shimDiv

      $(this.el).find('.pagination .arrow-prev').click(_.bind(this.prev, this));
      $(this.el).find('.pagination .arrow-next').click(_.bind(this.next, this));

      // create the shim...
      shimDiv = $('

')
        .appendTo($(this.el).find('.pagination .photos .scroller .thumbs'));

      $('')
        .attr('src', this.model.get(this.thumbPath))
        .appendTo(shimDiv.find('.inner'))

      this.addModel(this.model);
      this.addPreviousFromModel(this.model);
      this.addNextFromModel(this.model);
    },

    addPreviousFromModel : function(model){
      this._addMoreFromModel(model, 'next');
    },

    addNextFromModel : function(model){
      this._addMoreFromModel(model, 'previous');
    },

    _addMoreFromModel : function(model, dir){
      if( !dir ) dir = 'next';
      if( (ar = model.get(dir)) && ar.length ){
        for(var i=0; i<ar.length; i++ ){
          var m = new op.data.model.Photo(ar[i]);
          if( ar.length === 1 ){
            m[dir==='next'?'_last':'_first'] = true;
          }
          this.addModel(m, dir==='next');
        }
      }
      else {
        model[dir==='next'?'_last':'_first'] = true;
      }
    },

    addModel : function(model, pos){
      if( (m = this.store.get(model.get('id'))) ){
        this.addThumbNav(m);
        return m;
      }

      this.store[pos===false?'unshift':'push'](model);
      this.addThumbNav(model);

      /**
       * TODO - figure out why routing won't work...
       *
      var self = this
        , a = document.createElement('a');

      a.href = model.get('url');
      this.router.route( a.pathname, 'photo_'+model.get('id'), function(){
        self.go(model.get('id'));
      });
      this.router.on('route:photo_'+model.get('id'), function(){

      });
      */
      return model;
    },

    addThumbNav : function(model){
      var t
        , id = model.get('id')

      if( (t = this.thumbs[id]) ){
        return t;
      }

      // get the difference
      var init = _.indexOf( this.store.models, this.initialModel )
        , diff = _.indexOf( this.store.models, model ) - init
        , x = diff * 33.33333333 + 33.33333333 + .625;

      t = this.thumbs[id] = $('
')
        .appendTo( $(this.el).find('.pagination .photos .scroller .thumbs') )
        .css({left: x+'%'})
        .click(_.bind(this.thumbClick, this, model.get('id')))

      var b = $('
').appendTo(t);
      var b2 = $('
').appendTo(b);

      var i = $('')
        .attr('src', model.get(this.thumbPath))
        .appendTo(b2);

      if( this.model == model )
        t.addClass('active');

      return t;
    },

    thumbClick : function(id){
      /**
       * TODO - this is where you would call the router kmethod
       * if it was working.
       */
      //this.router.navigate('/p/'+id, {trigger: true});
      this.go(id);
    },

    next : function(){
      var cur = _.indexOf( this.store.models, this.model );
      if( cur < this.store.models.length-1 ){
        this.go( this.store.at(cur + 1).get('id') );
      }
    },

    prev : function(){
      var cur = _.indexOf( this.store.models, this.model );
      if( cur > 0 ){
        this.go( this.store.at(cur - 1).get('id') );
      }
    },

    go : function(id){

      if( this.model === this.store.get(id)) return;

      // get the difference
      var init = _.indexOf( this.store.models, this.initialModel )
        , diff = _.indexOf( this.store.models, this.store.get(id) ) - init
        , router = op.data.store.Router;

      $(this.el).find('.pagination .photos .scroller .thumbs')
        .stop()
        // might be better to use css3 translate3d and transition properties instead
        .animate({'left': (-33.33333333*diff)+'%'}, 200)

      $(this.el).find('.pagination .photos .scroller .thumbs .thumb').removeClass('active');
      this.thumbs[id].addClass('active');

      // lets also get next/prev
      var x = _.indexOf( this.store.models, this.store.get(id) )
        , c = _.indexOf( this.store.models, this.model )

      this.loadMore( x > c );
      this.updateModel(this.store.get(id));
      router.navigate('/p/'+id, {trigger: false});
    },

    loadMore : function( dir ){
      var model
        , self = this
        , sizes = _.map(
          [this.thumbPath, this.largePath],
          function(str){ return str.replace(/^path/,''); }
        ).join(',')
        , apiParams = {nextprevious:'1', returnSizes:sizes}
        , endpoint
        , fn = 'next';

      if( dir ){
        // going to add more to the end...
        // first lets get the last model in the store
        // and check if its the last one
        var model = this.store.at( this.store.models.length-1 );
        if( model._last ) return;
      }
      else {
        fn = 'previous';
        var model = this.store.at(0);
        if( model._first ) return;
      }

      endpoint = TBX.init.pages.photo.filterOpts ?
        '/photo/'+model.get('id')+'/view.json' :
        '/photo/'+model.get('id')+'/'+TBX.init.pages.photo.filterOpts+'/view.json' ;

      OP.Util.makeRequest(endpoint, apiParams, function(response) {
        if( response.result ){
          if( response.result.next ) model.set('next', response.result.next);
          if( response.result.previous ) model.set('previous', response.result.previous);
        }
        self._addMoreFromModel(model, fn);
      }, 'json', 'get');
    }
  });
})(jQuery);

<|endoftext|>


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

'use strict';

var util = require('util');

var Constants = require('../../../util/constants');
var profile = require('../../../util/profile');
var utils = require('../../../util/utils');
var fs = require('fs');
var $ = utils.getLocaleString;

exports.init = function (cli) {
  var log = cli.output;

  var group = cli.category('group');
  var deployment = group.category('deployment')
      .description($('Commands to manage your deployment in a resource group'));

  deployment.command('list [resourceGroup] [state]')
    .description($('Get deployments'))
    .option('-g --resource-group <resourceGroup>', $('Name of the resource group.'))
    .option('--state <state>', $('Optional. Filter the deployments by provisioning state.'
      + 'Valid values are Accepted, Running, Failed and Succeeded'))
    .option('--subscription <subscription>', $('Subscription containing deployments to list'))
    .execute(function (resourceGroup, state, options, _) {
      if (!resourceGroup) {
        return cli.missingArgument('resourceGroup');
      }
      var subscription = profile.current.getSubscription(options.subscription);
      var client = subscription.createResourceClient('createResourceManagementClient');
      var progress = cli.interaction.progress($('Listing deployments'));

      try {
        var allDeployments = retrieveDeployments(client, resourceGroup, state, _);
        cli.interaction.formatOutput(allDeployments, function (outputData) {
          if (outputData) {
            for (var i = 0; i < outputData.length; i++) {
              var deployment = outputData[i];
              //TODO, will polish the output later
              log.data($('================'), deployment.deploymentName);
              cli.interaction.logEachData($(''), deployment);
              cli.interaction.logEachData($(''), deployment.properties);
              cli.interaction.logEachData($(''), deployment.properties.parameters);
            }
          }
        });
      } finally {
        progress.end();
      }
    });

  deployment.command('show [resourceGroup] [deploymentName]')
    .description($('get deployments'))
    .option('-g --resource-group <resourceGroup>', $('Name of the resource group.'))
    .option('-n --deployment-name <deploymentName>', $('Name of the deployment'))
	  .option('--subscription <subscription>', $('Subscription containing the deployment to display'))
    .execute(function (resourceGroup, name, options, _) {
      if (!resourceGroup) {
        return cli.missingArgument('resourceGroup');
      }
      var subscription = profile.current.getSubscription(options.subscription);
      var client = subscription.createResourceClient('createResourceManagementClient');
      var progress = cli.interaction.progress($('Getting deployments'));
      var deployment;
      try {
        if (name) {
          deployment = client.deployments.get(resourceGroup, name, _);
        }
        else {
          //look for the most recent one
          var allDeployments = retrieveDeployments(client, resourceGroup, '', _);
          if (allDeployments && allDeployments.length > 0) {
            allDeployments.sort( function (a, b) {
                return Date.parse(a.properties.timestamp) < parseFloat(b.properties.timestamp)
            });
            deployment = allDeployments[0];
          }
        }
        if (deployment) {
          //TODO, will polish the output later
          log.data($('================'), deployment.name || deployment.deploymentName);
          cli.interaction.logEachData($(''), deployment);
          cli.interaction.logEachData($(''), deployment.properties);
          cli.interaction.logEachData($(''), deployment.properties.parameters);
        }
      } finally {
        progress.end();
      }
    });

  deployment.command('stop [resourceGroup] [deploymentName]')
    .description($('stop current running deployment'))
    .option('-g --resource-group <resourceGroup>', $('Name of the resource group.'))
    .option('-q --quiet', $('Quiet mode. Do not ask confirmation for stop deployment'))
    .option('-n --deployment-name <deploymentName>', $('Name of the deployment'))
    .option('--subscription <subscription>', $('Subcription containing the deployment to stop'))
    .execute(function (resourceGroup, deploymentName, options, _) {
      if (!resourceGroup) {
        return cli.missingArgument('resourceGroup');
      }
      var subscription = profile.current.getSubscription(options.subscription);
      var client = subscription.createResourceClient('createResourceManagementClient');
      var progress = cli.interaction.progress($('Stopping deployment'));

      try {
        var deploymentToStop;

        if (!deploymentName){
          var allRunningDeployments = retrieveDeployments(client, resourceGroup, "'Running'", _);
          if (allRunningDeployments && allRunningDeployments.length > 0) {
            if (allRunningDeployments.length > 1) {
              throw new Error('There are more than 1 deployment in a running state, please name one');
            }
            deploymentToStop = allRunningDeployments[0].deploymentName;
          }
        }
        else{
          deploymentToStop = client.deployments.get(resourceGroup, deploymentName, _).name;
        }

        if (!options.quiet &&
            !cli.interaction.confirm(util.format($('Stop deployment %s? [y/n]: '), deploymentToStop.deploymentName), _)) {
            return;
          }
        client.deployments.cancel(resourceGroup, deploymentToStop, _);
      }
      finally {
        progress.end();
      }
    }
  )

  deployment.command('create [templateLink] [resourceGroup] [mode] [deploymentName] [parametersFile]')
    .option('-f --template-link <templateLink>', $('uri to the template file'))
    .option('-g --resource-group <resourceGroup>', $('name of the resource group'))
    .option('-m --mode <mode>', $('mode of the template deployment. Valid values are Repalce, New and Incremental'))
    .option('-n --deployment-name <deploymentName>', $('name of the deployment'))
    .option('-p --parameters-file <parametersFile>', $('file with parameters'))
    .option('--subscription <subscription>', $('Subcription containing group to delete'))
    .execute(function (templateLink, resourceGroup, mode, deploymentName, parametersFile, options, _) {

      function stripBOM(content) {
        if (content.charCodeAt(0) === 0xFEFF) {
          content = content.slice(1);
        }
        return content;
      }

      var subscription = profile.current.getSubscription(options.subscription);
      var client = subscription.createResourceClient('createResourceManagementClient');
      var progress = cli.interaction.progress($('starting to create deployment'));

      var jsonFile = fs.readFileSync(parametersFile, 'utf8');
      var deploymentParameters = JSON.parse(stripBOM(jsonFile));

      try {
        client.deployments.createOrUpdate(resourceGroup, deploymentName,
          {
            'parameters': deploymentParameters.properties.parameters,
            'mode': mode,
            'templateLink':
            {
              'uri': templateLink
            }
          }
          , _
       )
      }
      finally {
        progress.end();
      }

    })
};

function retrieveDeployments(client, resourceGroup, state, _) {
  //Wrap the value with single quot(needed for constructing RESTful query string)
  var stateFilter = state;
  if (stateFilter && !(utils.stringStartsWith(stateFilter, '\''))) {
    stateFilter = '\'' + stateFilter + '\'';
  }

  var response = client.deployments.list(resourceGroup, { provisioningState: stateFilter }, _);
  var allDeployments = response.deployments;
  var nextLink = response.nextLink;
  while (nextLink) {
    client.deployments.listNext(nextLink, function (newSet) {
      allDeployments.concat(newSet.deployments);
      nextLink = nextSet.nextLink;
    })
  }
  return allDeployments;
}<commit_msg>fix logic errors in dealing with stop deployment<commit_after>/**
* Copyright (c) Microsoft.  All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

var util = require('util');

var Constants = require('../../../util/constants');
var profile = require('../../../util/profile');
var utils = require('../../../util/utils');
var fs = require('fs');
var $ = utils.getLocaleString;

exports.init = function (cli) {
  var log = cli.output;

  var group = cli.category('group');
  var deployment = group.category('deployment')
      .description($('Commands to manage your deployment in a resource group'));

  deployment.command('list [resourceGroup] [state]')
    .description($('Get deployments'))
    .option('-g --resource-group <resourceGroup>', $('Name of the resource group.'))
    .option('--state <state>', $('Optional. Filter the deployments by provisioning state.'
      + 'Valid values are Accepted, Running, Failed and Succeeded'))
    .option('--subscription <subscription>', $('Subscription containing deployments to list'))
    .execute(function (resourceGroup, state, options, _) {
      if (!resourceGroup) {
        return cli.missingArgument('resourceGroup');
      }
      var subscription = profile.current.getSubscription(options.subscription);
      var client = subscription.createResourceClient('createResourceManagementClient');
      var progress = cli.interaction.progress($('Listing deployments'));

      try {
        var allDeployments = retrieveDeployments(client, resourceGroup, state, _);
        cli.interaction.formatOutput(allDeployments, function (outputData) {
          if (outputData) {
            for (var i = 0; i < outputData.length; i++) {
              var deployment = outputData[i];
              //TODO, will polish the output later
              log.data($('================'), deployment.deploymentName);
              cli.interaction.logEachData($(''), deployment);
              cli.interaction.logEachData($(''), deployment.properties);
              cli.interaction.logEachData($(''), deployment.properties.parameters);
            }
          }
        });
      } finally {
        progress.end();
      }
    });

  deployment.command('show [resourceGroup] [deploymentName]')
    .description($('get deployments'))
    .option('-g --resource-group <resourceGroup>', $('Name of the resource group.'))
    .option('-n --deployment-name <deploymentName>', $('Name of the deployment'))
	  .option('--subscription <subscription>', $('Subscription containing the deployment to display'))
    .execute(function (resourceGroup, name, options, _) {
      if (!resourceGroup) {
        return cli.missingArgument('resourceGroup');
      }
      var subscription = profile.current.getSubscription(options.subscription);
      var client = subscription.createResourceClient('createResourceManagementClient');
      var progress = cli.interaction.progress($('Getting deployments'));
      var deployment;
      try {
        if (name) {
          deployment = client.deployments.get(resourceGroup, name, _);
        }
        else {
          //look for the most recent one
          var allDeployments = retrieveDeployments(client, resourceGroup, '', _);
          if (allDeployments && allDeployments.length > 0) {
            allDeployments.sort( function (a, b) {
                return Date.parse(a.properties.timestamp) < parseFloat(b.properties.timestamp)
            });
            deployment = allDeployments[0];
          }
        }
        if (deployment) {
          //TODO, will polish the output later
          log.data($('================'), deployment.name || deployment.deploymentName);
          cli.interaction.logEachData($(''), deployment);
          cli.interaction.logEachData($(''), deployment.properties);
          cli.interaction.logEachData($(''), deployment.properties.parameters);
        }
      } finally {
        progress.end();
      }
    });

  deployment.command('stop [resourceGroup] [deploymentName]')
    .description($('stop current running deployment'))
    .option('-g --resource-group <resourceGroup>', $('Name of the resource group.'))
    .option('-q --quiet', $('Quiet mode. Do not ask confirmation for stop deployment'))
    .option('-n --deployment-name <deploymentName>', $('Name of the deployment'))
    .option('--subscription <subscription>', $('Subcription containing the deployment to stop'))
    .execute(function (resourceGroup, deploymentName, options, _) {
      if (!resourceGroup) {
        return cli.missingArgument('resourceGroup');
      }
      var subscription = profile.current.getSubscription(options.subscription);
      var client = subscription.createResourceClient('createResourceManagementClient');
      var progress = cli.interaction.progress($('Stopping deployment'));

      try {
        var deploymentToStop = deploymentName;

        if (!deploymentName){
          var allRunningDeployments = retrieveDeployments(client, resourceGroup, "'Running'", _);
          if (allRunningDeployments && allRunningDeployments.length > 0) {
            if (allRunningDeployments.length > 1) {
              cli.missingArgument('There are more than 1 deployment in a running state, please name one.');
            }
            deploymentToStop = allRunningDeployments[0].deploymentName;
          }
        }

        if (deploymentToStop) {
          if (!options.quiet &&
              !cli.interaction.confirm(util.format($('Stop deployment %s? [y/n]: '), deploymentToStop), _)) {
            return;
          }
          client.deployments.cancel(resourceGroup, deploymentToStop, _);
        }
      }
      finally {
        progress.end();
      }
    }
  )

  deployment.command('create [templateLink] [resourceGroup] [mode] [deploymentName] [parametersFile]')
    .option('-f --template-link <templateLink>', $('uri to the template file'))
    .option('-g --resource-group <resourceGroup>', $('name of the resource group'))
    .option('-m --mode <mode>', $('mode of the template deployment. Valid values are Repalce, New and Incremental'))
    .option('-n --deployment-name <deploymentName>', $('name of the deployment'))
    .option('-p --parameters-file <parametersFile>', $('file with parameters'))
    .option('--subscription <subscription>', $('Subcription containing group to delete'))
    .execute(function (templateLink, resourceGroup, mode, deploymentName, parametersFile, options, _) {

      function stripBOM(content) {
        if (content.charCodeAt(0) === 0xFEFF) {
          content = content.slice(1);
        }
        return content;
      }

      var subscription = profile.current.getSubscription(options.subscription);
      var client = subscription.createResourceClient('createResourceManagementClient');
      var progress = cli.interaction.progress($('starting to create deployment'));

      var jsonFile = fs.readFileSync(parametersFile, 'utf8');
      var deploymentParameters = JSON.parse(stripBOM(jsonFile));

      try {
        client.deployments.createOrUpdate(resourceGroup, deploymentName,
          {
            'parameters': deploymentParameters.properties.parameters,
            'mode': mode,
            'templateLink':
            {
              'uri': templateLink
            }
          }
          , _
       )
      }
      finally {
        progress.end();
      }

    })
};

function retrieveDeployments(client, resourceGroup, state, _) {
  //Wrap with single quots(needed for constructing RESTful query string)
  var stateFilter = state;
  if (stateFilter && !(utils.stringStartsWith(stateFilter, '\''))) {
    stateFilter = '\'' + stateFilter + '\'';
  }

  var response = client.deployments.list(resourceGroup, { provisioningState: stateFilter }, _);
  var allDeployments = response.deployments;
  var nextLink = response.nextLink;
  while (nextLink) {
    client.deployments.listNext(nextLink, function (newSet) {
      allDeployments.concat(newSet.deployments);
      nextLink = nextSet.nextLink;
    })
  }
  return allDeployments;
}<|endoftext|>


<commit_before>/**
 * platformer.js - lightweight library for typical 2D platformer movements
 * Copyright 2014 Remi Papillie
 *
 * MIT license
 */

// unique global for platformer.js
var platformer = {}

platformer.World = function(options)
{
	options = options || {}

	var gravity = options.gravity || [0, -9.8]

	this.gravity = vec2.clone(gravity)

	this.platforms = []
	this.players = []

	this.debugCanvas = null
}

platformer.World.prototype.createPlatform = function(options)
{
	var platform = new platformer.Platform(options || {})
	this.platforms.push(platform)

	return platform
}

platformer.World.prototype.createPlayer = function(options)
{
	var player = new platformer.Player(options || {})
	this.players.push(player)

	return player
}

// dt is in seconds
platformer.World.prototype.update = function(dt)
{
	// update player dynamics
	for (var i = 0; i < this.players.length; i++)
	{
		var player = this.players[i]

		// acceleration from forces (gravity)
		vec2.scaleAndAdd(player.velocity, player.velocity, this.gravity, dt)

		// position update from velocity integration
		vec2.scaleAndAdd(player.position, player.position, player.velocity, dt)

		// collision with platforms
		player.grounded = false
		for (var i = 0; i < this.platforms.length; i++)
		{
			var platform = this.platforms[i]

			var collisionInfo = platform.collide(player)
			if (collisionInfo)
			{
				var velocityDotNormal = vec2.dot(player.velocity, collisionInfo.normal)

				// exclude this contact if it is separating
				if (velocityDotNormal > 0)
					return

				// fix interpenetration
				vec2.scaleAndAdd(player.position, player.position, collisionInfo.normal, collisionInfo.depth)

				// keep only tangent velocity
				vec2.scaleAndAdd(player.velocity, player.velocity, collisionInfo.normal, -velocityDotNormal)

				// check if we collided with the ground
				if (collisionInfo.normal[1] > Math.abs(collisionInfo.normal[0]))
					player.grounded = true
			}
		}
	}

	if (this.debugCanvas)
		this.drawDebug()
}

platformer.World.prototype.enableDebug = function(canvas)
{
	this.debugCanvas = canvas
}

platformer.World.prototype.disableDebug = function()
{
	this.debugCanvas = null
}

platformer.World.prototype.drawDebug = function()
{
	var context = this.debugCanvas.getContext("2d")

	context.fillStyle = "#000"
	context.fillRect(0, 0, this.debugCanvas.width, this.debugCanvas.height)

	context.save()
	context.translate(this.debugCanvas.width * 0.5, this.debugCanvas.height * 0.5)
	context.scale(100, -100)

	for (var i = 0; i < this.platforms.length; i++)
	{
		var platform = this.platforms[i]

		context.fillStyle = "#ff0"
		context.fillRect(platform.position[0], platform.position[1], platform.size[0], platform.size[1])
	}

	for (var i = 0; i < this.players.length; i++)
	{
		var player = this.players[i]

		context.fillStyle = "#0f0"
		context.fillRect(player.position[0], player.position[1], player.size[0], player.size[1])
	}

	context.restore()
}

platformer.Platform = function(options)
{
	var position = options.position || [0, 0]
	var size = options.size || [1, 1]

	this.position = vec2.clone(position)
	this.size = vec2.clone(size)
}

platformer.Platform.prototype.collide = function(player)
{
	var collisionInfo = {
		normal: null,
		depth: null
	}

	function testOverlap(overlap, normal)
	{
		if (overlap < 0)
			return false

		if ((collisionInfo.depth === null) || (overlap < collisionInfo.depth))
		{
			// new minimal overlap found
			collisionInfo.depth = overlap
			collisionInfo.normal = normal
		}

		return true
	}

	if (!testOverlap(this.position[0] + this.size[0] - player.position[0], vec2.fromValues(1, 0))) return null
	if (!testOverlap(player.position[0] + player.size[0] - this.position[0], vec2.fromValues(-1, 0))) return null
	if (!testOverlap(this.position[1] + this.size[1] - player.position[1], vec2.fromValues(0, 1))) return null
	if (!testOverlap(player.position[1] + player.size[1] - this.position[1], vec2.fromValues(0, -1))) return null

	return collisionInfo
}

platformer.Player = function(options)
{
	var position = options.position || [0, 0]
	var velocity = options.velocity || [0, 0]
	var size = options.size || [1, 1]

	this.position = vec2.clone(position)
	this.velocity = vec2.clone(velocity)
	this.size = vec2.clone(size)
	this.moveSpeed = options.moveSpeed || 2
	this.jumpSpeed = options.jumpSpeed || 5

	this.grounded = false
}

platformer.Player.prototype.moveHorizontally = function(factor)
{
	this.velocity[0] = this.moveSpeed * factor
}

platformer.Player.prototype.jump = function()
{
	this.velocity[1] = this.jumpSpeed
}

platformer.EventDispatcher = function()
{
	this.listeners = {}
}

platformer.EventDispatcher.prototype.addEventListener = function(name, listener)
{
	if (!this.listeners[name])
		this.listeners[name] = []

	this.listeners[name].push(listener)
}

platformer.EventDispatcher.prototype.removeEventListener = function(name, listener)
{
	this.listeners[name].splice(this.listeners[name].indexOf(listener))
}

platformer.EventDispatcher.prototype.hasEventListener = function(name, listener)
{
	if (!this.listeners[name])
		return false

	return (this.listeners[name].indexOf(listener) != -1)
}

platformer.EventDispatcher.prototype.dispatchEvent = function(name, event)
{
	if (!this.listeners[name])
		return

	this.listeners[name].apply(function(listener)
	{
		listener(event)
	})
}
<commit_msg>optimized collision garbage<commit_after>/**
 * platformer.js - lightweight library for typical 2D platformer movements
 * Copyright 2014 Remi Papillie
 *
 * MIT license
 */

// unique global for platformer.js
var platformer = {}

platformer.World = function(options)
{
	options = options || {}

	var gravity = options.gravity || [0, -9.8]

	this.gravity = vec2.clone(gravity)

	this.platforms = []
	this.players = []

	this.debugCanvas = null
}

platformer.World.prototype.createPlatform = function(options)
{
	var platform = new platformer.Platform(options || {})
	this.platforms.push(platform)

	return platform
}

platformer.World.prototype.createPlayer = function(options)
{
	var player = new platformer.Player(options || {})
	this.players.push(player)

	return player
}

// dt is in seconds
platformer.World.prototype.update = function(dt)
{
	// update player dynamics
	for (var i = 0; i < this.players.length; i++)
	{
		var player = this.players[i]

		// acceleration from forces (gravity)
		vec2.scaleAndAdd(player.velocity, player.velocity, this.gravity, dt)

		// position update from velocity integration
		vec2.scaleAndAdd(player.position, player.position, player.velocity, dt)

		// collision with platforms
		player.grounded = false
		for (var i = 0; i < this.platforms.length; i++)
		{
			var platform = this.platforms[i]

			var collisionInfo = {
				normal: null,
				depth: null
			}
			if (platform.collide(player, collisionInfo))
			{
				var velocityDotNormal = vec2.dot(player.velocity, collisionInfo.normal)

				// exclude this contact if it is separating
				if (velocityDotNormal > 0)
					return

				// fix interpenetration
				vec2.scaleAndAdd(player.position, player.position, collisionInfo.normal, collisionInfo.depth)

				// keep only tangent velocity
				vec2.scaleAndAdd(player.velocity, player.velocity, collisionInfo.normal, -velocityDotNormal)

				// check if we collided with the ground
				if (collisionInfo.normal[1] > Math.abs(collisionInfo.normal[0]))
					player.grounded = true
			}
		}
	}

	if (this.debugCanvas)
		this.drawDebug()
}

platformer.World.prototype.enableDebug = function(canvas)
{
	this.debugCanvas = canvas
}

platformer.World.prototype.disableDebug = function()
{
	this.debugCanvas = null
}

platformer.World.prototype.drawDebug = function()
{
	var context = this.debugCanvas.getContext("2d")

	context.fillStyle = "#000"
	context.fillRect(0, 0, this.debugCanvas.width, this.debugCanvas.height)

	context.save()
	context.translate(this.debugCanvas.width * 0.5, this.debugCanvas.height * 0.5)
	context.scale(100, -100)

	context.fillStyle = "#ff0"
	for (var i = 0; i < this.platforms.length; i++)
	{
		var platform = this.platforms[i]
		context.fillRect(platform.position[0], platform.position[1], platform.size[0], platform.size[1])
	}

	context.fillStyle = "#0f0"
	for (var i = 0; i < this.players.length; i++)
	{
		var player = this.players[i]
		context.fillRect(player.position[0], player.position[1], player.size[0], player.size[1])
	}

	context.restore()
}

platformer.Platform = function(options)
{
	var position = options.position || [0, 0]
	var size = options.size || [1, 1]

	this.position = vec2.clone(position)
	this.size = vec2.clone(size)
}

platformer.Platform.prototype.collide = function()
{
	// create temporary vectors only once
	var LEFT = vec2.fromValues(-1, 0)
	var RIGHT = vec2.fromValues(1, 0)
	var UP = vec2.fromValues(0, 1)
	var DOWN = vec2.fromValues(0, -1)

	return function(player, collisionInfo)
	{
		collisionInfo.depth = null

		function testOverlap(overlap, normal)
		{
			if (overlap < 0)
				return false

			if ((collisionInfo.depth === null) || (overlap < collisionInfo.depth))
			{
				// new minimal overlap found
				collisionInfo.depth = overlap
				collisionInfo.normal = normal
			}

			return true
		}

		if (!testOverlap(this.position[0] + this.size[0] - player.position[0], RIGHT)) return false
		if (!testOverlap(player.position[0] + player.size[0] - this.position[0], LEFT)) return false
		if (!testOverlap(this.position[1] + this.size[1] - player.position[1], UP)) return false
		if (!testOverlap(player.position[1] + player.size[1] - this.position[1], DOWN)) return false

		return true
	}
}()

platformer.Player = function(options)
{
	var position = options.position || [0, 0]
	var velocity = options.velocity || [0, 0]
	var size = options.size || [1, 1]

	this.position = vec2.clone(position)
	this.velocity = vec2.clone(velocity)
	this.size = vec2.clone(size)
	this.moveSpeed = options.moveSpeed || 2
	this.jumpSpeed = options.jumpSpeed || 5

	this.grounded = false
}

platformer.Player.prototype.moveHorizontally = function(factor)
{
	this.velocity[0] = this.moveSpeed * factor
}

platformer.Player.prototype.jump = function()
{
	this.velocity[1] = this.jumpSpeed
}

platformer.EventDispatcher = function()
{
	this.listeners = {}
}

platformer.EventDispatcher.prototype.addEventListener = function(name, listener)
{
	if (!this.listeners[name])
		this.listeners[name] = []

	this.listeners[name].push(listener)
}

platformer.EventDispatcher.prototype.removeEventListener = function(name, listener)
{
	this.listeners[name].splice(this.listeners[name].indexOf(listener))
}

platformer.EventDispatcher.prototype.hasEventListener = function(name, listener)
{
	if (!this.listeners[name])
		return false

	return (this.listeners[name].indexOf(listener) != -1)
}

platformer.EventDispatcher.prototype.dispatchEvent = function(name, event)
{
	if (!this.listeners[name])
		return

	this.listeners[name].apply(function(listener)
	{
		listener(event)
	})
}
<|endoftext|>


<commit_before>import path from 'path';
import { logger } from '@storybook/node-logger';
import serverRequire from '../utils/server-require';

export default function loadCustomPresets({ configDir }) {
  const presets = serverRequire(path.resolve(configDir, 'presets'));

  if (presets) {
    logger.warn(
      '"Custom presets" is an experimental and undocumented feature that will be changed or deprecated soon. Use it on your own risk.'
    );

    return presets;
  }

  return [];
}
<commit_msg>Remove custom presets warning<commit_after>import path from 'path';
import serverRequire from '../utils/server-require';

export default function loadCustomPresets({ configDir }) {
  const presets = serverRequire(path.resolve(configDir, 'presets'));
  return presets || [];
}
<|endoftext|>


<commit_before>import find from 'array-find';
import React, { Component, PropTypes } from 'react';
import Menu from 'material-ui/Menu';
import MenuItem from 'material-ui/MenuItem';
// 😱
import RenderToLayer from 'material-ui/internal/RenderToLayer';

const MENU_HEIGHT = 320;
const MENU_WIDTH = 280;

const RANDOM_MUI_PADDING = 8;
const SCROLLBAR_WIDTH = 7;

const positionInsideWindow = (position, expectedHeight) => {
  const constrained = { x: position.x, y: position.y };
  const h = Math.min(expectedHeight, MENU_HEIGHT);
  const w = MENU_WIDTH;
  if (position.y + h >= window.innerHeight) {
    // position at the bottom of the screen
    constrained.y = window.innerHeight - h;
  }
  if (position.x + w >= window.innerWidth) {
    // position to the left-hand side of the anchor, instead of the right-hand side
    constrained.x -= w;
  }
  return constrained;
};

const menuStyle = {
  textAlign: 'left',
  zIndex: 30
};

export default class AddToPlaylistMenu extends Component {
  static propTypes = {
    onClose: PropTypes.func.isRequired,
    onSelect: PropTypes.func.isRequired,
    playlists: PropTypes.arrayOf(PropTypes.object),
    position: PropTypes.shape({
      x: PropTypes.number,
      y: PropTypes.number
    })
  };

  handleSelect = (e, item) => {
    const playlistID = item.props.value;
    this.props.onClose();
    this.props.onSelect(
      find(this.props.playlists, pl => pl._id === playlistID)
    );
  };

  renderLayer = () => {
    const { playlists, position } = this.props;
    const fixedPosition = positionInsideWindow(position, (playlists.length + 1) * 48);
    return (
      <div
        style={{
          position: 'absolute',
          left: fixedPosition.x,
          top: fixedPosition.y,
          width: MENU_WIDTH + RANDOM_MUI_PADDING + SCROLLBAR_WIDTH
        }}
      >
        <Menu
          style={menuStyle}
          maxHeight={MENU_HEIGHT}
          width={MENU_WIDTH}
          autoWidth={false}
          onItemTouchTap={this.handleSelect}
        >
          <MenuItem
            primaryText="New Playlist"
          />
          {playlists.map(playlist => (
            <MenuItem
              key={playlist._id}
              value={playlist._id}
              primaryText={playlist.name}
              secondaryText={`${playlist.size || 0}`}
              checked={!!playlist.active}
            />
          ))}
        </Menu>
      </div>
    );
  };

  render() {
    const { onClose } = this.props;
    return (
      <RenderToLayer
        open
        componentClickAway={onClose}
        render={this.renderLayer}
      />
    );
  }
}
<commit_msg>playlists: add <Paper> wrapper around AddToPlaylistMenu (material-ui 0.15)<commit_after>import find from 'array-find';
import React, { Component, PropTypes } from 'react';
import Paper from 'material-ui/Paper';
import Menu from 'material-ui/Menu';
import MenuItem from 'material-ui/MenuItem';
// 😱
import RenderToLayer from 'material-ui/internal/RenderToLayer';

const MENU_HEIGHT = 320;
const MENU_WIDTH = 280;

const RANDOM_MUI_PADDING = 8;
const SCROLLBAR_WIDTH = 7;

const positionInsideWindow = (position, expectedHeight) => {
  const constrained = { x: position.x, y: position.y };
  const h = Math.min(expectedHeight, MENU_HEIGHT);
  const w = MENU_WIDTH;
  if (position.y + h >= window.innerHeight) {
    // position at the bottom of the screen
    constrained.y = window.innerHeight - h;
  }
  if (position.x + w >= window.innerWidth) {
    // position to the left-hand side of the anchor, instead of the right-hand side
    constrained.x -= w;
  }
  return constrained;
};

const menuStyle = {
  textAlign: 'left',
  zIndex: 30
};
const menuItemStyle = {
  WebkitAppearance: 'initial'
};

export default class AddToPlaylistMenu extends Component {
  static propTypes = {
    onClose: PropTypes.func.isRequired,
    onSelect: PropTypes.func.isRequired,
    playlists: PropTypes.arrayOf(PropTypes.object),
    position: PropTypes.shape({
      x: PropTypes.number,
      y: PropTypes.number
    })
  };

  handleSelect = (e, item) => {
    const playlistID = item.props.value;
    this.props.onClose();
    this.props.onSelect(
      find(this.props.playlists, pl => pl._id === playlistID)
    );
  };

  renderLayer = () => {
    const { playlists, position } = this.props;
    const fixedPosition = positionInsideWindow(position, (playlists.length + 1) * 48);
    return (
      <div
        style={{
          position: 'absolute',
          left: fixedPosition.x,
          top: fixedPosition.y,
          width: MENU_WIDTH + RANDOM_MUI_PADDING + SCROLLBAR_WIDTH
        }}
      >
        <Paper>
          <Menu
            style={menuStyle}
            maxHeight={MENU_HEIGHT}
            width={MENU_WIDTH}
            autoWidth={false}
            onItemTouchTap={this.handleSelect}
          >
            <MenuItem
              style={menuItemStyle}
              primaryText="New Playlist"
            />
            {playlists.map(playlist => (
              <MenuItem
                key={playlist._id}
                style={menuItemStyle}
                value={playlist._id}
                primaryText={playlist.name}
                secondaryText={`${playlist.size || 0}`}
                checked={!!playlist.active}
              />
            ))}
          </Menu>
        </Paper>
      </div>
    );
  };

  render() {
    const { onClose } = this.props;
    return (
      <RenderToLayer
        open
        componentClickAway={onClose}
        render={this.renderLayer}
      />
    );
  }
}
<|endoftext|>


<commit_before>/**
 * React Starter Kit (https://www.reactstarterkit.com/)
 *
 * Copyright © 2014-2016 Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */
 /* global $:false */

import React, { Component, PropTypes } from 'react';
import s from './AudioPlayer.scss';
import withStyles from '../../decorators/withStyles';
import Audio from '../Audio';

@withStyles(s)
class AudioPlayer extends Component {

  static propTypes = {
    audioSrc: PropTypes.string.isRequired,
    nbRepeat: PropTypes.number,
  };

  constructor() {
    super();
    this.state = {
      play() {
        self.audio.play();
        self.playing = true;
        document.getElementById('btn').textContent = 'Pause';
      },

      pause() {
        self.audio.pause();
        self.playing = false;
        document.getElementById('btn').textContent = 'Play';
      },

      playPauseClick() {
        self.audio.load();
        console.log('onClick, playing: ' + self.playing);
        if (self.playing) {
          this.state.pause();
        } else {
          this.state.play();
        }
      },

      endOfAudio() {
        console.log(self.counter);
        if (self.counter !== 0) {
          self.counter = self.counter - 1;
          this.state.play();
        } else {
          console.log('end of audio');
          pause();
        }
      },
    };
  }

  componentDidMount() {
    console.log('mounted');
    this.updateAudio();

    // self.audio.src = this.props.audioSrc;
    self.counter = this.props.nbRepeat;
    self.audio.addEventListener('ended', this.state.endOfAudio);

    self.counter -= 1;
    this.state.pause();
  }

  // Always call this function before doing anything with audio.
  // This is because the audio could be changed by another element.
  updateAudio() {
    self.audio = document.getElementById('audio-current');
    console.log(self.audio);
    self.audio.load();
    console.log(self.audio);
  }

  render() {
    return (

        <button id="btn" onClick={this.state.playPauseClick.bind(this)}></button>
        <Audio src={this.props.audioSrc}/>

    );
  }

}

export default AudioPlayer;
<commit_msg>Repass test<commit_after>/**
 * React Starter Kit (https://www.reactstarterkit.com/)
 *
 * Copyright © 2014-2016 Kriasoft, LLC. All rights reserved.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE.txt file in the root directory of this source tree.
 */
 /* global $:false */

import React, { Component, PropTypes } from 'react';
import s from './AudioPlayer.scss';
import withStyles from '../../decorators/withStyles';
import Audio from '../Audio';

@withStyles(s)
class AudioPlayer extends Component {

  static propTypes = {
    audioSrc: PropTypes.string.isRequired,
    nbRepeat: PropTypes.number,
  };

  constructor() {
    super();
    this.state = {
      play() {
        self.audio.play();
        self.playing = true;
        document.getElementById('btn').textContent = 'Pause';
      },

      pause() {
        self.audio.pause();
        self.playing = false;
        document.getElementById('btn').textContent = 'Play';
      },

      playPauseClick() {
        self.audio.load();
        console.log('onClick, playing: ' + self.playing);
        if (self.playing) {
          this.state.pause();
        } else {
          this.state.play();
        }
      },

      endOfAudio() {
        console.log(self.counter);
        if (self.counter !== 0) {
          self.counter = self.counter - 1;
          this.state.play();
        } else {
          console.log('end of audio');
          this.state.pause();
        }
      },
    };
  }

  componentDidMount() {
    console.log('mounted');
    this.updateAudio();

    // self.audio.src = this.props.audioSrc;
    self.counter = this.props.nbRepeat;
    self.audio.addEventListener('ended', this.state.endOfAudio);

    self.counter -= 1;
    this.state.pause();
  }

  // Always call this function before doing anything with audio.
  // This is because the audio could be changed by another element.
  updateAudio() {
    self.audio = document.getElementById('audio-current');
    console.log(self.audio);
    self.audio.load();
    console.log(self.audio);
  }

  render() {
    return (

        <button id="btn" onClick={this.state.playPauseClick.bind(this)}></button>
        <Audio src={this.props.audioSrc}/>

    );
  }

}

export default AudioPlayer;
<|endoftext|>